xref: /plan9/sys/src/libdraw/init.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1*7dd7cddfSDavid du Colombier #include <u.h>
2*7dd7cddfSDavid du Colombier #include <libc.h>
3*7dd7cddfSDavid du Colombier #include <draw.h>
4*7dd7cddfSDavid du Colombier 
5*7dd7cddfSDavid du Colombier Point	ZP;
6*7dd7cddfSDavid du Colombier Rectangle ZR;
7*7dd7cddfSDavid du Colombier Display	*display;
8*7dd7cddfSDavid du Colombier Font	*font;
9*7dd7cddfSDavid du Colombier Image	*screen;
10*7dd7cddfSDavid du Colombier 
11*7dd7cddfSDavid du Colombier static char deffontname[] = "*default*";
12*7dd7cddfSDavid du Colombier Screen	*_screen;
13*7dd7cddfSDavid du Colombier 
14*7dd7cddfSDavid du Colombier int		debuglockdisplay = 0;
15*7dd7cddfSDavid du Colombier 
16*7dd7cddfSDavid du Colombier int
17*7dd7cddfSDavid du Colombier Rconv(va_list *arg, Fconv *f)
18*7dd7cddfSDavid du Colombier {
19*7dd7cddfSDavid du Colombier 	Rectangle r;
20*7dd7cddfSDavid du Colombier 	char buf[128];
21*7dd7cddfSDavid du Colombier 
22*7dd7cddfSDavid du Colombier 	r = va_arg(*arg, Rectangle);
23*7dd7cddfSDavid du Colombier 	sprint(buf, "%P %P", r.min, r.max);
24*7dd7cddfSDavid du Colombier 	strconv(buf, f);
25*7dd7cddfSDavid du Colombier 	return 0;
26*7dd7cddfSDavid du Colombier }
27*7dd7cddfSDavid du Colombier 
28*7dd7cddfSDavid du Colombier int
29*7dd7cddfSDavid du Colombier Pconv(va_list *arg, Fconv *f)
30*7dd7cddfSDavid du Colombier {
31*7dd7cddfSDavid du Colombier 	Point p;
32*7dd7cddfSDavid du Colombier 	char buf[64];
33*7dd7cddfSDavid du Colombier 
34*7dd7cddfSDavid du Colombier 	p = va_arg(*arg, Point);
35*7dd7cddfSDavid du Colombier 	sprint(buf, "[%d %d]", p.x, p.y);
36*7dd7cddfSDavid du Colombier 	strconv(buf, f);
37*7dd7cddfSDavid du Colombier 	return 0;
38*7dd7cddfSDavid du Colombier }
39*7dd7cddfSDavid du Colombier 
40*7dd7cddfSDavid du Colombier static void
41*7dd7cddfSDavid du Colombier drawshutdown(void)
42*7dd7cddfSDavid du Colombier {
43*7dd7cddfSDavid du Colombier 	Display *d;
44*7dd7cddfSDavid du Colombier 
45*7dd7cddfSDavid du Colombier 	d = display;
46*7dd7cddfSDavid du Colombier 	if(d){
47*7dd7cddfSDavid du Colombier 		display = nil;
48*7dd7cddfSDavid du Colombier 		closedisplay(d);
49*7dd7cddfSDavid du Colombier 	}
50*7dd7cddfSDavid du Colombier }
51*7dd7cddfSDavid du Colombier 
52*7dd7cddfSDavid du Colombier int
53*7dd7cddfSDavid du Colombier geninitdraw(char *devdir, void(*error)(Display*, char*), char *fontname, char *label, char *windir, int ref)
54*7dd7cddfSDavid du Colombier {
55*7dd7cddfSDavid du Colombier 	int fd, n;
56*7dd7cddfSDavid du Colombier 	Subfont *df;
57*7dd7cddfSDavid du Colombier 	char buf[128];
58*7dd7cddfSDavid du Colombier 
59*7dd7cddfSDavid du Colombier 	display = initdisplay(devdir, windir, error);
60*7dd7cddfSDavid du Colombier 	if(display == nil)
61*7dd7cddfSDavid du Colombier 		return -1;
62*7dd7cddfSDavid du Colombier 
63*7dd7cddfSDavid du Colombier 	/*
64*7dd7cddfSDavid du Colombier 	 * Set up default font
65*7dd7cddfSDavid du Colombier 	 */
66*7dd7cddfSDavid du Colombier 	df = getdefont(display);
67*7dd7cddfSDavid du Colombier 	display->defaultsubfont = df;
68*7dd7cddfSDavid du Colombier 	if(df == nil){
69*7dd7cddfSDavid du Colombier 		_drawprint(2, "imageinit: can't open default subfont: %r\n");
70*7dd7cddfSDavid du Colombier     Error:
71*7dd7cddfSDavid du Colombier 		closedisplay(display);
72*7dd7cddfSDavid du Colombier 		display = nil;
73*7dd7cddfSDavid du Colombier 		return -1;
74*7dd7cddfSDavid du Colombier 	}
75*7dd7cddfSDavid du Colombier 	if(fontname == nil){
76*7dd7cddfSDavid du Colombier 		fd = open("/env/font", OREAD);
77*7dd7cddfSDavid du Colombier 		if(fd >= 0){
78*7dd7cddfSDavid du Colombier 			n = read(fd, buf, sizeof(buf));
79*7dd7cddfSDavid du Colombier 			if(n>0 && n<sizeof buf-1){
80*7dd7cddfSDavid du Colombier 				buf[n] = 0;
81*7dd7cddfSDavid du Colombier 				fontname = buf;
82*7dd7cddfSDavid du Colombier 			}
83*7dd7cddfSDavid du Colombier 			close(fd);
84*7dd7cddfSDavid du Colombier 		}
85*7dd7cddfSDavid du Colombier 	}
86*7dd7cddfSDavid du Colombier 	/*
87*7dd7cddfSDavid du Colombier 	 * Build fonts with caches==depth of screen, for speed.
88*7dd7cddfSDavid du Colombier 	 * If conversion were faster, we'd use 0 and save memory.
89*7dd7cddfSDavid du Colombier 	 */
90*7dd7cddfSDavid du Colombier 	if(fontname == nil){
91*7dd7cddfSDavid du Colombier 		snprint(buf, sizeof buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent,
92*7dd7cddfSDavid du Colombier 			df->n-1, deffontname);
93*7dd7cddfSDavid du Colombier //BUG: Need something better for this	installsubfont("*default*", df);
94*7dd7cddfSDavid du Colombier 		font = buildfont(display, buf, deffontname);
95*7dd7cddfSDavid du Colombier 		if(font == nil){
96*7dd7cddfSDavid du Colombier 			_drawprint(2, "imageinit: can't open default font: %r\n");
97*7dd7cddfSDavid du Colombier 			goto Error;
98*7dd7cddfSDavid du Colombier 		}
99*7dd7cddfSDavid du Colombier 	}else{
100*7dd7cddfSDavid du Colombier 		font = openfont(display, fontname);	/* BUG: grey fonts */
101*7dd7cddfSDavid du Colombier 		if(font == nil){
102*7dd7cddfSDavid du Colombier 			_drawprint(2, "imageinit: can't open font %s: %r\n", fontname);
103*7dd7cddfSDavid du Colombier 			goto Error;
104*7dd7cddfSDavid du Colombier 		}
105*7dd7cddfSDavid du Colombier 	}
106*7dd7cddfSDavid du Colombier 	display->defaultfont = font;
107*7dd7cddfSDavid du Colombier 
108*7dd7cddfSDavid du Colombier 	/*
109*7dd7cddfSDavid du Colombier 	 * Write label; ignore errors (we might not be running under rio)
110*7dd7cddfSDavid du Colombier 	 */
111*7dd7cddfSDavid du Colombier 	if(label){
112*7dd7cddfSDavid du Colombier 		snprint(buf, sizeof buf, "%s/label", display->windir);
113*7dd7cddfSDavid du Colombier 		fd = open(buf, OREAD);
114*7dd7cddfSDavid du Colombier 		if(fd >= 0){
115*7dd7cddfSDavid du Colombier 			read(fd, display->oldlabel, (sizeof display->oldlabel)-1);
116*7dd7cddfSDavid du Colombier 			close(fd);
117*7dd7cddfSDavid du Colombier 			fd = create(buf, OWRITE, 0666);
118*7dd7cddfSDavid du Colombier 			if(fd >= 0){
119*7dd7cddfSDavid du Colombier 				write(fd, label, strlen(label));
120*7dd7cddfSDavid du Colombier 				close(fd);
121*7dd7cddfSDavid du Colombier 			}
122*7dd7cddfSDavid du Colombier 		}
123*7dd7cddfSDavid du Colombier 	}
124*7dd7cddfSDavid du Colombier 
125*7dd7cddfSDavid du Colombier 	if(getwindow(display, ref) < 0)
126*7dd7cddfSDavid du Colombier 		goto Error;
127*7dd7cddfSDavid du Colombier 
128*7dd7cddfSDavid du Colombier 	atexit(drawshutdown);
129*7dd7cddfSDavid du Colombier 
130*7dd7cddfSDavid du Colombier 	return 1;
131*7dd7cddfSDavid du Colombier }
132*7dd7cddfSDavid du Colombier 
133*7dd7cddfSDavid du Colombier int
134*7dd7cddfSDavid du Colombier initdraw(void(*error)(Display*, char*), char *fontname , char *label)
135*7dd7cddfSDavid du Colombier {
136*7dd7cddfSDavid du Colombier 	char *dev = "/dev";
137*7dd7cddfSDavid du Colombier 	char dir[DIRLEN];
138*7dd7cddfSDavid du Colombier 
139*7dd7cddfSDavid du Colombier 	if(stat("/dev/draw/new", dir)<0 && bind("#i", "/dev", MAFTER)<0){
140*7dd7cddfSDavid du Colombier 		_drawprint(2, "imageinit: can't bind /dev/draw: %r");
141*7dd7cddfSDavid du Colombier 		return -1;
142*7dd7cddfSDavid du Colombier 	}
143*7dd7cddfSDavid du Colombier 	return geninitdraw(dev, error, fontname, label, dev, Refnone);
144*7dd7cddfSDavid du Colombier }
145*7dd7cddfSDavid du Colombier 
146*7dd7cddfSDavid du Colombier /*
147*7dd7cddfSDavid du Colombier  * Attach, or possibly reattach, to window.
148*7dd7cddfSDavid du Colombier  * If reattaching, maintain value of screen pointer.
149*7dd7cddfSDavid du Colombier  */
150*7dd7cddfSDavid du Colombier int
151*7dd7cddfSDavid du Colombier getwindow(Display *d, int ref)
152*7dd7cddfSDavid du Colombier {
153*7dd7cddfSDavid du Colombier 	int n, fd;
154*7dd7cddfSDavid du Colombier 	char buf[128];
155*7dd7cddfSDavid du Colombier 	Image *image;
156*7dd7cddfSDavid du Colombier 
157*7dd7cddfSDavid du Colombier 	snprint(buf, sizeof buf, "%s/winname", d->windir);
158*7dd7cddfSDavid du Colombier 	fd = open(buf, OREAD);
159*7dd7cddfSDavid du Colombier 	if(fd<0 || (n=read(fd, buf, 64))<=0){
160*7dd7cddfSDavid du Colombier 		screen = display->image;
161*7dd7cddfSDavid du Colombier 		assert(screen && screen->chan != 0);
162*7dd7cddfSDavid du Colombier 		return 1;
163*7dd7cddfSDavid du Colombier 	}
164*7dd7cddfSDavid du Colombier 	close(fd);
165*7dd7cddfSDavid du Colombier 	buf[n] = 0;
166*7dd7cddfSDavid du Colombier 	if(screen != nil){
167*7dd7cddfSDavid du Colombier 		_freeimage1(screen);
168*7dd7cddfSDavid du Colombier 		freeimage(_screen->image);
169*7dd7cddfSDavid du Colombier 		freescreen(_screen);
170*7dd7cddfSDavid du Colombier 		_screen = nil;
171*7dd7cddfSDavid du Colombier 	}
172*7dd7cddfSDavid du Colombier 	image = namedimage(display, buf);
173*7dd7cddfSDavid du Colombier 	if(image == 0){
174*7dd7cddfSDavid du Colombier 		screen = nil;
175*7dd7cddfSDavid du Colombier 		return -1;
176*7dd7cddfSDavid du Colombier 	}
177*7dd7cddfSDavid du Colombier 	assert(image->chan != 0);
178*7dd7cddfSDavid du Colombier 
179*7dd7cddfSDavid du Colombier 	_screen = allocscreen(image, display->white, 0);
180*7dd7cddfSDavid du Colombier 	if(_screen == nil){
181*7dd7cddfSDavid du Colombier 		screen = nil;
182*7dd7cddfSDavid du Colombier 		return -1;
183*7dd7cddfSDavid du Colombier 	}
184*7dd7cddfSDavid du Colombier 
185*7dd7cddfSDavid du Colombier 	screen = _allocwindow(screen, _screen, insetrect(image->r, Borderwidth), ref, DWhite);
186*7dd7cddfSDavid du Colombier 	if(screen == nil)
187*7dd7cddfSDavid du Colombier 		return -1;
188*7dd7cddfSDavid du Colombier 	assert(screen->chan != 0);
189*7dd7cddfSDavid du Colombier 	return 1;
190*7dd7cddfSDavid du Colombier }
191*7dd7cddfSDavid du Colombier 
192*7dd7cddfSDavid du Colombier #define	NINFO	12*12
193*7dd7cddfSDavid du Colombier 
194*7dd7cddfSDavid du Colombier Display*
195*7dd7cddfSDavid du Colombier initdisplay(char *dev, char *win, void(*error)(Display*, char*))
196*7dd7cddfSDavid du Colombier {
197*7dd7cddfSDavid du Colombier 	char buf[128], info[NINFO+1], *t;
198*7dd7cddfSDavid du Colombier 	int datafd, ctlfd, reffd;
199*7dd7cddfSDavid du Colombier 	Display *disp;
200*7dd7cddfSDavid du Colombier 	Image *image;
201*7dd7cddfSDavid du Colombier 	Dir dir;
202*7dd7cddfSDavid du Colombier 	ulong chan;
203*7dd7cddfSDavid du Colombier 
204*7dd7cddfSDavid du Colombier 	fmtinstall('P', Pconv);
205*7dd7cddfSDavid du Colombier 	fmtinstall('R', Rconv);
206*7dd7cddfSDavid du Colombier 	if(dev == 0)
207*7dd7cddfSDavid du Colombier 		dev = "/dev";
208*7dd7cddfSDavid du Colombier 	if(win == 0)
209*7dd7cddfSDavid du Colombier 		win = "/dev";
210*7dd7cddfSDavid du Colombier 	if(strlen(dev)>sizeof buf-25 || strlen(win)>sizeof buf-25){
211*7dd7cddfSDavid du Colombier 		werrstr("initdisplay: directory name too long");
212*7dd7cddfSDavid du Colombier 		return nil;
213*7dd7cddfSDavid du Colombier 	}
214*7dd7cddfSDavid du Colombier 	t = strdup(win);
215*7dd7cddfSDavid du Colombier 	if(t == nil)
216*7dd7cddfSDavid du Colombier 		return nil;
217*7dd7cddfSDavid du Colombier 
218*7dd7cddfSDavid du Colombier 	sprint(buf, "%s/draw/new", dev);
219*7dd7cddfSDavid du Colombier 	ctlfd = open(buf, ORDWR|OCEXEC);
220*7dd7cddfSDavid du Colombier 	if(ctlfd < 0){
221*7dd7cddfSDavid du Colombier 		if(bind("#i", dev, MAFTER) < 0){
222*7dd7cddfSDavid du Colombier     Error1:
223*7dd7cddfSDavid du Colombier 			free(t);
224*7dd7cddfSDavid du Colombier 			werrstr("initdisplay: %s: %r", buf);
225*7dd7cddfSDavid du Colombier 			return 0;
226*7dd7cddfSDavid du Colombier 		}
227*7dd7cddfSDavid du Colombier 		ctlfd = open(buf, ORDWR|OCEXEC);
228*7dd7cddfSDavid du Colombier 	}
229*7dd7cddfSDavid du Colombier 	if(ctlfd < 0)
230*7dd7cddfSDavid du Colombier 		goto Error1;
231*7dd7cddfSDavid du Colombier 	if(read(ctlfd, info, sizeof info) < NINFO){
232*7dd7cddfSDavid du Colombier     Error2:
233*7dd7cddfSDavid du Colombier 		close(ctlfd);
234*7dd7cddfSDavid du Colombier 		goto Error1;
235*7dd7cddfSDavid du Colombier 	}
236*7dd7cddfSDavid du Colombier 
237*7dd7cddfSDavid du Colombier 	if((chan=strtochan(info+2*12)) == 0){
238*7dd7cddfSDavid du Colombier 		werrstr("bad channel in %s", buf);
239*7dd7cddfSDavid du Colombier 		goto Error2;
240*7dd7cddfSDavid du Colombier 	}
241*7dd7cddfSDavid du Colombier 
242*7dd7cddfSDavid du Colombier 	sprint(buf, "%s/draw/%d/data", dev, atoi(info+0*12));
243*7dd7cddfSDavid du Colombier 	datafd = open(buf, ORDWR|OCEXEC);
244*7dd7cddfSDavid du Colombier 	if(datafd < 0)
245*7dd7cddfSDavid du Colombier 		goto Error2;
246*7dd7cddfSDavid du Colombier 	sprint(buf, "%s/draw/%d/refresh", dev, atoi(info+0*12));
247*7dd7cddfSDavid du Colombier 	reffd = open(buf, OREAD|OCEXEC);
248*7dd7cddfSDavid du Colombier 	if(reffd < 0){
249*7dd7cddfSDavid du Colombier     Error3:
250*7dd7cddfSDavid du Colombier 		close(datafd);
251*7dd7cddfSDavid du Colombier 		goto Error2;
252*7dd7cddfSDavid du Colombier 	}
253*7dd7cddfSDavid du Colombier 	disp = malloc(sizeof(Display));
254*7dd7cddfSDavid du Colombier 	if(disp == 0){
255*7dd7cddfSDavid du Colombier     Error4:
256*7dd7cddfSDavid du Colombier 		close(reffd);
257*7dd7cddfSDavid du Colombier 		goto Error3;
258*7dd7cddfSDavid du Colombier 	}
259*7dd7cddfSDavid du Colombier 	image = malloc(sizeof(Image));
260*7dd7cddfSDavid du Colombier 	if(image == 0){
261*7dd7cddfSDavid du Colombier     Error5:
262*7dd7cddfSDavid du Colombier 		free(disp);
263*7dd7cddfSDavid du Colombier 		goto Error4;
264*7dd7cddfSDavid du Colombier 	}
265*7dd7cddfSDavid du Colombier 	memset(image, 0, sizeof(Image));
266*7dd7cddfSDavid du Colombier 	memset(disp, 0, sizeof(Display));
267*7dd7cddfSDavid du Colombier 	image->display = disp;
268*7dd7cddfSDavid du Colombier 	image->id = 0;
269*7dd7cddfSDavid du Colombier 	image->chan = chan;
270*7dd7cddfSDavid du Colombier 	image->depth = chantodepth(chan);
271*7dd7cddfSDavid du Colombier 	image->repl = atoi(info+3*12);
272*7dd7cddfSDavid du Colombier 	image->r.min.x = atoi(info+4*12);
273*7dd7cddfSDavid du Colombier 	image->r.min.y = atoi(info+5*12);
274*7dd7cddfSDavid du Colombier 	image->r.max.x = atoi(info+6*12);
275*7dd7cddfSDavid du Colombier 	image->r.max.y = atoi(info+7*12);
276*7dd7cddfSDavid du Colombier 	image->clipr.min.x = atoi(info+8*12);
277*7dd7cddfSDavid du Colombier 	image->clipr.min.y = atoi(info+9*12);
278*7dd7cddfSDavid du Colombier 	image->clipr.max.x = atoi(info+10*12);
279*7dd7cddfSDavid du Colombier 	image->clipr.max.y = atoi(info+11*12);
280*7dd7cddfSDavid du Colombier 	disp->dirno = atoi(info+0*12);
281*7dd7cddfSDavid du Colombier 	disp->fd = datafd;
282*7dd7cddfSDavid du Colombier 	disp->ctlfd = ctlfd;
283*7dd7cddfSDavid du Colombier 	disp->reffd = reffd;
284*7dd7cddfSDavid du Colombier 	disp->image = image;
285*7dd7cddfSDavid du Colombier 	disp->bufp = disp->buf;
286*7dd7cddfSDavid du Colombier 	disp->error = error;
287*7dd7cddfSDavid du Colombier 	disp->chan = image->chan;
288*7dd7cddfSDavid du Colombier 	disp->depth = image->depth;
289*7dd7cddfSDavid du Colombier 	disp->windir = t;
290*7dd7cddfSDavid du Colombier 	disp->devdir = strdup(dev);
291*7dd7cddfSDavid du Colombier 	qlock(&disp->qlock);
292*7dd7cddfSDavid du Colombier 	disp->white = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DWhite);
293*7dd7cddfSDavid du Colombier 	disp->black = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DBlack);
294*7dd7cddfSDavid du Colombier 	if(disp->white == nil || disp->black == nil){
295*7dd7cddfSDavid du Colombier 		free(image);
296*7dd7cddfSDavid du Colombier 		free(disp->devdir);
297*7dd7cddfSDavid du Colombier 		free(disp->white);
298*7dd7cddfSDavid du Colombier 		free(disp->black);
299*7dd7cddfSDavid du Colombier 		goto Error5;
300*7dd7cddfSDavid du Colombier 	}
301*7dd7cddfSDavid du Colombier 	disp->opaque = disp->white;
302*7dd7cddfSDavid du Colombier 	disp->transparent = disp->black;
303*7dd7cddfSDavid du Colombier 	if(dirfstat(ctlfd, &dir)>=0 && dir.type=='i'){
304*7dd7cddfSDavid du Colombier 		disp->local = 1;
305*7dd7cddfSDavid du Colombier 		disp->dataqid = dir.qid.path;
306*7dd7cddfSDavid du Colombier 	}
307*7dd7cddfSDavid du Colombier 
308*7dd7cddfSDavid du Colombier 	assert(disp->chan != 0 && image->chan != 0);
309*7dd7cddfSDavid du Colombier 	return disp;
310*7dd7cddfSDavid du Colombier }
311*7dd7cddfSDavid du Colombier 
312*7dd7cddfSDavid du Colombier /*
313*7dd7cddfSDavid du Colombier  * Call with d unlocked.
314*7dd7cddfSDavid du Colombier  * Note that disp->defaultfont and defaultsubfont are not freed here.
315*7dd7cddfSDavid du Colombier  */
316*7dd7cddfSDavid du Colombier void
317*7dd7cddfSDavid du Colombier closedisplay(Display *disp)
318*7dd7cddfSDavid du Colombier {
319*7dd7cddfSDavid du Colombier 	int fd;
320*7dd7cddfSDavid du Colombier 	char buf[128];
321*7dd7cddfSDavid du Colombier 
322*7dd7cddfSDavid du Colombier 	if(disp == nil)
323*7dd7cddfSDavid du Colombier 		return;
324*7dd7cddfSDavid du Colombier 	if(disp == display)
325*7dd7cddfSDavid du Colombier 		display = nil;
326*7dd7cddfSDavid du Colombier 	if(disp->oldlabel[0]){
327*7dd7cddfSDavid du Colombier 		snprint(buf, sizeof buf, "%s/label", disp->windir);
328*7dd7cddfSDavid du Colombier 		fd = open(buf, OWRITE);
329*7dd7cddfSDavid du Colombier 		if(fd >= 0){
330*7dd7cddfSDavid du Colombier 			write(fd, disp->oldlabel, strlen(disp->oldlabel));
331*7dd7cddfSDavid du Colombier 			close(fd);
332*7dd7cddfSDavid du Colombier 		}
333*7dd7cddfSDavid du Colombier 	}
334*7dd7cddfSDavid du Colombier 
335*7dd7cddfSDavid du Colombier 	free(disp->devdir);
336*7dd7cddfSDavid du Colombier 	free(disp->windir);
337*7dd7cddfSDavid du Colombier 	freeimage(disp->white);
338*7dd7cddfSDavid du Colombier 	freeimage(disp->black);
339*7dd7cddfSDavid du Colombier 	free(disp->image);
340*7dd7cddfSDavid du Colombier 	close(disp->fd);
341*7dd7cddfSDavid du Colombier 	close(disp->ctlfd);
342*7dd7cddfSDavid du Colombier 	/* should cause refresh slave to shut down */
343*7dd7cddfSDavid du Colombier 	close(disp->reffd);
344*7dd7cddfSDavid du Colombier 	qunlock(&disp->qlock);
345*7dd7cddfSDavid du Colombier 	free(disp);
346*7dd7cddfSDavid du Colombier }
347*7dd7cddfSDavid du Colombier 
348*7dd7cddfSDavid du Colombier void
349*7dd7cddfSDavid du Colombier lockdisplay(Display *disp)
350*7dd7cddfSDavid du Colombier {
351*7dd7cddfSDavid du Colombier 	if(debuglockdisplay){
352*7dd7cddfSDavid du Colombier 		/* avoid busy looping; it's rare we collide anyway */
353*7dd7cddfSDavid du Colombier 		while(!canqlock(&disp->qlock)){
354*7dd7cddfSDavid du Colombier 			_drawprint(1, "proc %d waiting for display lock...\n", getpid());
355*7dd7cddfSDavid du Colombier 			sleep(1000);
356*7dd7cddfSDavid du Colombier 		}
357*7dd7cddfSDavid du Colombier 	}else
358*7dd7cddfSDavid du Colombier 		qlock(&disp->qlock);
359*7dd7cddfSDavid du Colombier }
360*7dd7cddfSDavid du Colombier 
361*7dd7cddfSDavid du Colombier void
362*7dd7cddfSDavid du Colombier unlockdisplay(Display *disp)
363*7dd7cddfSDavid du Colombier {
364*7dd7cddfSDavid du Colombier 	qunlock(&disp->qlock);
365*7dd7cddfSDavid du Colombier }
366*7dd7cddfSDavid du Colombier 
367*7dd7cddfSDavid du Colombier /* use static buffer to avoid stack bloat */
368*7dd7cddfSDavid du Colombier int
369*7dd7cddfSDavid du Colombier _drawprint(int fd, char *fmt, ...)
370*7dd7cddfSDavid du Colombier {
371*7dd7cddfSDavid du Colombier 	int n;
372*7dd7cddfSDavid du Colombier 	va_list arg;
373*7dd7cddfSDavid du Colombier 	static char buf[1024];
374*7dd7cddfSDavid du Colombier 	static QLock l;
375*7dd7cddfSDavid du Colombier 
376*7dd7cddfSDavid du Colombier 	qlock(&l);
377*7dd7cddfSDavid du Colombier 	va_start(arg, fmt);
378*7dd7cddfSDavid du Colombier 	doprint(buf, buf+sizeof buf, fmt, arg);
379*7dd7cddfSDavid du Colombier 	va_end(arg);
380*7dd7cddfSDavid du Colombier 	n = write(fd, buf, strlen(buf));
381*7dd7cddfSDavid du Colombier 	qunlock(&l);
382*7dd7cddfSDavid du Colombier 	return n;
383*7dd7cddfSDavid du Colombier }
384*7dd7cddfSDavid du Colombier 
385*7dd7cddfSDavid du Colombier void
386*7dd7cddfSDavid du Colombier drawerror(Display *d, char *s)
387*7dd7cddfSDavid du Colombier {
388*7dd7cddfSDavid du Colombier 	char err[ERRLEN];
389*7dd7cddfSDavid du Colombier 
390*7dd7cddfSDavid du Colombier 	if(d->error)
391*7dd7cddfSDavid du Colombier 		d->error(d, s);
392*7dd7cddfSDavid du Colombier 	else{
393*7dd7cddfSDavid du Colombier 		errstr(err);
394*7dd7cddfSDavid du Colombier 		_drawprint(2, "draw: %s: %s\n", s, err);
395*7dd7cddfSDavid du Colombier 		exits(s);
396*7dd7cddfSDavid du Colombier 	}
397*7dd7cddfSDavid du Colombier }
398*7dd7cddfSDavid du Colombier 
399*7dd7cddfSDavid du Colombier static
400*7dd7cddfSDavid du Colombier int
401*7dd7cddfSDavid du Colombier doflush(Display *d)
402*7dd7cddfSDavid du Colombier {
403*7dd7cddfSDavid du Colombier 	int n;
404*7dd7cddfSDavid du Colombier 
405*7dd7cddfSDavid du Colombier 	n = d->bufp-d->buf;
406*7dd7cddfSDavid du Colombier 	if(n <= 0)
407*7dd7cddfSDavid du Colombier 		return 1;
408*7dd7cddfSDavid du Colombier 
409*7dd7cddfSDavid du Colombier 	if(write(d->fd, d->buf, n) != n){
410*7dd7cddfSDavid du Colombier /*		_drawprint(2, "flushimage fail: d=%lux: %r\n", d); /**/
411*7dd7cddfSDavid du Colombier 		d->bufp = d->buf;	/* might as well; chance of continuing */
412*7dd7cddfSDavid du Colombier 		return -1;
413*7dd7cddfSDavid du Colombier 	}
414*7dd7cddfSDavid du Colombier 	d->bufp = d->buf;
415*7dd7cddfSDavid du Colombier 	return 1;
416*7dd7cddfSDavid du Colombier }
417*7dd7cddfSDavid du Colombier 
418*7dd7cddfSDavid du Colombier int
419*7dd7cddfSDavid du Colombier flushimage(Display *d, int visible)
420*7dd7cddfSDavid du Colombier {
421*7dd7cddfSDavid du Colombier 	if(visible)
422*7dd7cddfSDavid du Colombier 		*d->bufp++ = 'v';	/* one byte always reserved for this */
423*7dd7cddfSDavid du Colombier 	return doflush(d);
424*7dd7cddfSDavid du Colombier }
425*7dd7cddfSDavid du Colombier 
426*7dd7cddfSDavid du Colombier uchar*
427*7dd7cddfSDavid du Colombier bufimage(Display *d, int n)
428*7dd7cddfSDavid du Colombier {
429*7dd7cddfSDavid du Colombier 	uchar *p;
430*7dd7cddfSDavid du Colombier 
431*7dd7cddfSDavid du Colombier 	if(n<0 || n>Displaybufsize){
432*7dd7cddfSDavid du Colombier 		werrstr("bad count in bufimage");
433*7dd7cddfSDavid du Colombier 		return 0;
434*7dd7cddfSDavid du Colombier 	}
435*7dd7cddfSDavid du Colombier 	if(d->bufp+n > d->buf+Displaybufsize)
436*7dd7cddfSDavid du Colombier 		if(doflush(d) < 0)
437*7dd7cddfSDavid du Colombier 			return 0;
438*7dd7cddfSDavid du Colombier 	p = d->bufp;
439*7dd7cddfSDavid du Colombier 	d->bufp += n;
440*7dd7cddfSDavid du Colombier 	return p;
441*7dd7cddfSDavid du Colombier }
442*7dd7cddfSDavid du Colombier 
443