xref: /inferno-os/libdraw/window.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1 #include "lib9.h"
2 #include "draw.h"
3 #include "kernel.h"
4 
5 typedef struct Memimage Memimage;
6 
7 static int	screenid;
8 
9 Screen*
allocscreen(Image * image,Image * fill,int public)10 allocscreen(Image *image, Image *fill, int public)
11 {
12 	uchar *a;
13 	Screen *s;
14 	int id, try;
15 	Display *d;
16 
17 	d = image->display;
18 	if(d != fill->display){
19 		kwerrstr("allocscreen: image and fill on different displays");
20 		return 0;
21 	}
22 	s = malloc(sizeof(Screen));
23 	if(s == 0)
24 		return 0;
25 	SET(id);
26 	for(try=0; try<25; try++){
27 		/* loop until find a free id */
28 		a = bufimage(d, 1+4+4+4+1);
29 		if(a == 0){
30 			free(s);
31 			return 0;
32 		}
33 		id = ++screenid;
34 		a[0] = 'A';
35 		BPLONG(a+1, id);
36 		BPLONG(a+5, image->id);
37 		BPLONG(a+9, fill->id);
38 		a[13] = public;
39 		if(flushimage(d, 0) != -1)
40 			break;
41 	}
42 	s->display = d;
43 	s->id = id;
44 	s->image = image;
45 //	assert(s->image && s->image->chan != 0);
46 
47 	s->fill = fill;
48 	return s;
49 }
50 
51 Screen*
publicscreen(Display * d,int id,ulong chan)52 publicscreen(Display *d, int id, ulong chan)
53 {
54 	uchar *a;
55 	Screen *s;
56 
57 	s = malloc(sizeof(Screen));
58 	if(s == 0)
59 		return 0;
60 	a = bufimage(d, 1+4+4);
61 	if(a == 0){
62     Error:
63 		free(s);
64 		return 0;
65 	}
66 	a[0] = 'S';
67 	BPLONG(a+1, id);
68 	BPLONG(a+5, chan);
69 	if(flushimage(d, 0) < 0)
70 		goto Error;
71 
72 	s->display = d;
73 	s->id = id;
74 	s->image = 0;
75 	s->fill = 0;
76 	return s;
77 }
78 
79 int
freescreen(Screen * s)80 freescreen(Screen *s)
81 {
82 	uchar *a;
83 	Display *d;
84 
85 	if(s == 0)
86 		return 0;
87 	d = s->display;
88 	a = bufimage(d, 1+4);
89 	if(a == 0)
90 		return -1;
91 	a[0] = 'F';
92 	BPLONG(a+1, s->id);
93 	/*
94 	 * flush(1) because screen is likely holding last reference to
95 	 * window, and want it to disappear visually.
96 	 */
97 	if(flushimage(d, 1) < 0)
98 		return -1;
99 	free(s);
100 	return 1;
101 }
102 
103 Image*
allocwindow(Screen * s,Rectangle r,int ref,ulong val)104 allocwindow(Screen *s, Rectangle r, int ref, ulong val)
105 {
106 	return _allocwindow(nil, s, r, ref, val);
107 }
108 
109 Image*
_allocwindow(Image * i,Screen * s,Rectangle r,int ref,ulong val)110 _allocwindow(Image *i, Screen *s, Rectangle r, int ref, ulong val)
111 {
112 	Display *d;
113 
114 	d = s->display;
115 	i = _allocimage(i, d, r, s->image->chan, 0, val, s->id, ref);
116 	if(i == 0)
117 		return 0;
118 	i->screen = s;
119 	i->next = s->display->windows;
120 	s->display->windows = i;
121 	return i;
122 }
123 
124 static
125 void
topbottom(Image ** w,int n,int top)126 topbottom(Image **w, int n, int top)
127 {
128 	int i;
129 	uchar *b;
130 	Display *d;
131 
132 	if(n<0 || n>(Displaybufsize-100)/4){
133 		_drawprint(2, "top/bottom: ridiculous number of windows\n");
134 		return;
135 	}
136 	if(n==0)
137 		return;
138 	/* check that all images are on the same display; only it can check the screens */
139 	d = w[0]->display;
140 	for(i=1; i<n; i++)
141 		if(w[i]->display != d){
142 			_drawprint(2, "top/bottom: windows not on same display\n");
143 			return;
144 		}
145 	b = bufimage(d, 1+1+2+4*n);
146 	if (b == 0) {
147 		_drawprint(2, "top/bottom: no bufimage\n");
148 		return;
149 	}
150 	b[0] = 't';
151 	b[1] = top;
152 	BPSHORT(b+2, n);
153 	for(i=0; i<n; i++)
154 		BPLONG(b+4+4*i, w[i]->id);
155 }
156 
157 void
bottomwindow(Image * w)158 bottomwindow(Image *w)
159 {
160 	topbottom(&w, 1, 0);
161 }
162 
163 void
topwindow(Image * w)164 topwindow(Image *w)
165 {
166 	topbottom(&w, 1, 1);
167 }
168 
169 void
bottomnwindows(Image ** w,int n)170 bottomnwindows(Image **w, int n)
171 {
172 	topbottom(w, n, 0);
173 }
174 
175 void
topnwindows(Image ** w,int n)176 topnwindows(Image **w, int n)
177 {
178 	topbottom(w, n, 1);
179 }
180 
181 int
originwindow(Image * w,Point log,Point scr)182 originwindow(Image *w, Point log, Point scr)
183 {
184 	uchar *b;
185 	Point delta;
186 
187 	flushimage(w->display, 0);
188 	b = bufimage(w->display, 1+4+2*4+2*4);
189 	if(b == nil)
190 		return 0;
191 	b[0] = 'o';
192 	BPLONG(b+1, w->id);
193 	BPLONG(b+5, log.x);
194 	BPLONG(b+9, log.y);
195 	BPLONG(b+13, scr.x);
196 	BPLONG(b+17, scr.y);
197 	if(flushimage(w->display, 1) < 0)
198 		return -1;
199 	delta = subpt(log, w->r.min);
200 	w->r = rectaddpt(w->r, delta);
201 	w->clipr = rectaddpt(w->clipr, delta);
202 	return 1;
203 }
204