xref: /plan9/sys/src/libdraw/init.c (revision 80ee5cbfe36716af62da8896207e9763b8e3d760)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier 
57dd7cddfSDavid du Colombier Point	ZP;
67dd7cddfSDavid du Colombier Rectangle ZR;
77dd7cddfSDavid du Colombier Display	*display;
87dd7cddfSDavid du Colombier Font	*font;
97dd7cddfSDavid du Colombier Image	*screen;
1059cc4ca5SDavid du Colombier int	_drawdebug;
117dd7cddfSDavid du Colombier 
127dd7cddfSDavid du Colombier static char deffontname[] = "*default*";
137dd7cddfSDavid du Colombier Screen	*_screen;
147dd7cddfSDavid du Colombier 
157dd7cddfSDavid du Colombier int		debuglockdisplay = 0;
167dd7cddfSDavid du Colombier 
177dd7cddfSDavid du Colombier int
187dd7cddfSDavid du Colombier Rconv(va_list *arg, Fconv *f)
197dd7cddfSDavid du Colombier {
207dd7cddfSDavid du Colombier 	Rectangle r;
217dd7cddfSDavid du Colombier 	char buf[128];
227dd7cddfSDavid du Colombier 
237dd7cddfSDavid du Colombier 	r = va_arg(*arg, Rectangle);
247dd7cddfSDavid du Colombier 	sprint(buf, "%P %P", r.min, r.max);
257dd7cddfSDavid du Colombier 	strconv(buf, f);
267dd7cddfSDavid du Colombier 	return 0;
277dd7cddfSDavid du Colombier }
287dd7cddfSDavid du Colombier 
297dd7cddfSDavid du Colombier int
307dd7cddfSDavid du Colombier Pconv(va_list *arg, Fconv *f)
317dd7cddfSDavid du Colombier {
327dd7cddfSDavid du Colombier 	Point p;
337dd7cddfSDavid du Colombier 	char buf[64];
347dd7cddfSDavid du Colombier 
357dd7cddfSDavid du Colombier 	p = va_arg(*arg, Point);
367dd7cddfSDavid du Colombier 	sprint(buf, "[%d %d]", p.x, p.y);
377dd7cddfSDavid du Colombier 	strconv(buf, f);
387dd7cddfSDavid du Colombier 	return 0;
397dd7cddfSDavid du Colombier }
407dd7cddfSDavid du Colombier 
417dd7cddfSDavid du Colombier static void
427dd7cddfSDavid du Colombier drawshutdown(void)
437dd7cddfSDavid du Colombier {
447dd7cddfSDavid du Colombier 	Display *d;
457dd7cddfSDavid du Colombier 
467dd7cddfSDavid du Colombier 	d = display;
477dd7cddfSDavid du Colombier 	if(d){
487dd7cddfSDavid du Colombier 		display = nil;
497dd7cddfSDavid du Colombier 		closedisplay(d);
507dd7cddfSDavid du Colombier 	}
517dd7cddfSDavid du Colombier }
527dd7cddfSDavid du Colombier 
537dd7cddfSDavid du Colombier int
547dd7cddfSDavid du Colombier geninitdraw(char *devdir, void(*error)(Display*, char*), char *fontname, char *label, char *windir, int ref)
557dd7cddfSDavid du Colombier {
567dd7cddfSDavid du Colombier 	int fd, n;
577dd7cddfSDavid du Colombier 	Subfont *df;
587dd7cddfSDavid du Colombier 	char buf[128];
597dd7cddfSDavid du Colombier 
607dd7cddfSDavid du Colombier 	display = initdisplay(devdir, windir, error);
617dd7cddfSDavid du Colombier 	if(display == nil)
627dd7cddfSDavid du Colombier 		return -1;
637dd7cddfSDavid du Colombier 
647dd7cddfSDavid du Colombier 	/*
657dd7cddfSDavid du Colombier 	 * Set up default font
667dd7cddfSDavid du Colombier 	 */
677dd7cddfSDavid du Colombier 	df = getdefont(display);
687dd7cddfSDavid du Colombier 	display->defaultsubfont = df;
697dd7cddfSDavid du Colombier 	if(df == nil){
707dd7cddfSDavid du Colombier 		_drawprint(2, "imageinit: can't open default subfont: %r\n");
717dd7cddfSDavid du Colombier     Error:
727dd7cddfSDavid du Colombier 		closedisplay(display);
737dd7cddfSDavid du Colombier 		display = nil;
747dd7cddfSDavid du Colombier 		return -1;
757dd7cddfSDavid du Colombier 	}
767dd7cddfSDavid du Colombier 	if(fontname == nil){
777dd7cddfSDavid du Colombier 		fd = open("/env/font", OREAD);
787dd7cddfSDavid du Colombier 		if(fd >= 0){
797dd7cddfSDavid du Colombier 			n = read(fd, buf, sizeof(buf));
807dd7cddfSDavid du Colombier 			if(n>0 && n<sizeof buf-1){
817dd7cddfSDavid du Colombier 				buf[n] = 0;
827dd7cddfSDavid du Colombier 				fontname = buf;
837dd7cddfSDavid du Colombier 			}
847dd7cddfSDavid du Colombier 			close(fd);
857dd7cddfSDavid du Colombier 		}
867dd7cddfSDavid du Colombier 	}
877dd7cddfSDavid du Colombier 	/*
887dd7cddfSDavid du Colombier 	 * Build fonts with caches==depth of screen, for speed.
897dd7cddfSDavid du Colombier 	 * If conversion were faster, we'd use 0 and save memory.
907dd7cddfSDavid du Colombier 	 */
917dd7cddfSDavid du Colombier 	if(fontname == nil){
927dd7cddfSDavid du Colombier 		snprint(buf, sizeof buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent,
937dd7cddfSDavid du Colombier 			df->n-1, deffontname);
947dd7cddfSDavid du Colombier //BUG: Need something better for this	installsubfont("*default*", df);
957dd7cddfSDavid du Colombier 		font = buildfont(display, buf, deffontname);
967dd7cddfSDavid du Colombier 		if(font == nil){
977dd7cddfSDavid du Colombier 			_drawprint(2, "imageinit: can't open default font: %r\n");
987dd7cddfSDavid du Colombier 			goto Error;
997dd7cddfSDavid du Colombier 		}
1007dd7cddfSDavid du Colombier 	}else{
1017dd7cddfSDavid du Colombier 		font = openfont(display, fontname);	/* BUG: grey fonts */
1027dd7cddfSDavid du Colombier 		if(font == nil){
1037dd7cddfSDavid du Colombier 			_drawprint(2, "imageinit: can't open font %s: %r\n", fontname);
1047dd7cddfSDavid du Colombier 			goto Error;
1057dd7cddfSDavid du Colombier 		}
1067dd7cddfSDavid du Colombier 	}
1077dd7cddfSDavid du Colombier 	display->defaultfont = font;
1087dd7cddfSDavid du Colombier 
1097dd7cddfSDavid du Colombier 	/*
1107dd7cddfSDavid du Colombier 	 * Write label; ignore errors (we might not be running under rio)
1117dd7cddfSDavid du Colombier 	 */
1127dd7cddfSDavid du Colombier 	if(label){
1137dd7cddfSDavid du Colombier 		snprint(buf, sizeof buf, "%s/label", display->windir);
1147dd7cddfSDavid du Colombier 		fd = open(buf, OREAD);
1157dd7cddfSDavid du Colombier 		if(fd >= 0){
1167dd7cddfSDavid du Colombier 			read(fd, display->oldlabel, (sizeof display->oldlabel)-1);
1177dd7cddfSDavid du Colombier 			close(fd);
1187dd7cddfSDavid du Colombier 			fd = create(buf, OWRITE, 0666);
1197dd7cddfSDavid du Colombier 			if(fd >= 0){
1207dd7cddfSDavid du Colombier 				write(fd, label, strlen(label));
1217dd7cddfSDavid du Colombier 				close(fd);
1227dd7cddfSDavid du Colombier 			}
1237dd7cddfSDavid du Colombier 		}
1247dd7cddfSDavid du Colombier 	}
1257dd7cddfSDavid du Colombier 
1267dd7cddfSDavid du Colombier 	if(getwindow(display, ref) < 0)
1277dd7cddfSDavid du Colombier 		goto Error;
1287dd7cddfSDavid du Colombier 
1297dd7cddfSDavid du Colombier 	atexit(drawshutdown);
1307dd7cddfSDavid du Colombier 
1317dd7cddfSDavid du Colombier 	return 1;
1327dd7cddfSDavid du Colombier }
1337dd7cddfSDavid du Colombier 
1347dd7cddfSDavid du Colombier int
1357dd7cddfSDavid du Colombier initdraw(void(*error)(Display*, char*), char *fontname , char *label)
1367dd7cddfSDavid du Colombier {
1377dd7cddfSDavid du Colombier 	char *dev = "/dev";
1387dd7cddfSDavid du Colombier 	char dir[DIRLEN];
1397dd7cddfSDavid du Colombier 
1407dd7cddfSDavid du Colombier 	if(stat("/dev/draw/new", dir)<0 && bind("#i", "/dev", MAFTER)<0){
1417dd7cddfSDavid du Colombier 		_drawprint(2, "imageinit: can't bind /dev/draw: %r");
1427dd7cddfSDavid du Colombier 		return -1;
1437dd7cddfSDavid du Colombier 	}
1447dd7cddfSDavid du Colombier 	return geninitdraw(dev, error, fontname, label, dev, Refnone);
1457dd7cddfSDavid du Colombier }
1467dd7cddfSDavid du Colombier 
1477dd7cddfSDavid du Colombier /*
1487dd7cddfSDavid du Colombier  * Attach, or possibly reattach, to window.
1497dd7cddfSDavid du Colombier  * If reattaching, maintain value of screen pointer.
1507dd7cddfSDavid du Colombier  */
1517dd7cddfSDavid du Colombier int
152*80ee5cbfSDavid du Colombier gengetwindow(Display *d, char *winname, Image **winp, Screen **scrp, int ref)
1537dd7cddfSDavid du Colombier {
1547dd7cddfSDavid du Colombier 	int n, fd;
155*80ee5cbfSDavid du Colombier 	char buf[64+1];
1567dd7cddfSDavid du Colombier 	Image *image;
1577dd7cddfSDavid du Colombier 
158*80ee5cbfSDavid du Colombier 	fd = open(winname, OREAD);
159*80ee5cbfSDavid du Colombier 	if(fd<0 || (n=read(fd, buf, sizeof buf-1))<=0){
160*80ee5cbfSDavid du Colombier 		*winp = d->image;
161*80ee5cbfSDavid du Colombier 		assert(*winp && (*winp)->chan != 0);
1627dd7cddfSDavid du Colombier 		return 1;
1637dd7cddfSDavid du Colombier 	}
1647dd7cddfSDavid du Colombier 	close(fd);
165*80ee5cbfSDavid du Colombier 	buf[n] = '\0';
166*80ee5cbfSDavid du Colombier 	if(*winp != nil){
167*80ee5cbfSDavid du Colombier 		_freeimage1(*winp);
168*80ee5cbfSDavid du Colombier 		freeimage((*scrp)->image);
169*80ee5cbfSDavid du Colombier 		freescreen(*scrp);
170*80ee5cbfSDavid du Colombier 		*scrp = nil;
1717dd7cddfSDavid du Colombier 	}
172*80ee5cbfSDavid du Colombier 	image = namedimage(d, buf);
1737dd7cddfSDavid du Colombier 	if(image == 0){
174*80ee5cbfSDavid du Colombier 		*winp = nil;
1757dd7cddfSDavid du Colombier 		return -1;
1767dd7cddfSDavid du Colombier 	}
1777dd7cddfSDavid du Colombier 	assert(image->chan != 0);
1787dd7cddfSDavid du Colombier 
179*80ee5cbfSDavid du Colombier 	*scrp = allocscreen(image, d->white, 0);
180*80ee5cbfSDavid du Colombier 	if(*scrp == nil){
181*80ee5cbfSDavid du Colombier 		*winp = nil;
1827dd7cddfSDavid du Colombier 		return -1;
1837dd7cddfSDavid du Colombier 	}
1847dd7cddfSDavid du Colombier 
185*80ee5cbfSDavid du Colombier 	*winp = _allocwindow(*winp, *scrp, insetrect(image->r, Borderwidth), ref, DWhite);
186*80ee5cbfSDavid du Colombier 	if(*winp == nil)
1877dd7cddfSDavid du Colombier 		return -1;
188*80ee5cbfSDavid du Colombier 	assert((*winp)->chan != 0);
1897dd7cddfSDavid du Colombier 	return 1;
1907dd7cddfSDavid du Colombier }
1917dd7cddfSDavid du Colombier 
192*80ee5cbfSDavid du Colombier int
193*80ee5cbfSDavid du Colombier getwindow(Display *d, int ref)
194*80ee5cbfSDavid du Colombier {
195*80ee5cbfSDavid du Colombier 	char winname[128];
196*80ee5cbfSDavid du Colombier 
197*80ee5cbfSDavid du Colombier 	snprint(winname, sizeof winname, "%s/winname", d->windir);
198*80ee5cbfSDavid du Colombier 	return gengetwindow(d, winname, &screen, &_screen, ref);
199*80ee5cbfSDavid du Colombier }
200*80ee5cbfSDavid du Colombier 
2017dd7cddfSDavid du Colombier #define	NINFO	12*12
2027dd7cddfSDavid du Colombier 
2037dd7cddfSDavid du Colombier Display*
2047dd7cddfSDavid du Colombier initdisplay(char *dev, char *win, void(*error)(Display*, char*))
2057dd7cddfSDavid du Colombier {
2067dd7cddfSDavid du Colombier 	char buf[128], info[NINFO+1], *t;
2077dd7cddfSDavid du Colombier 	int datafd, ctlfd, reffd;
2087dd7cddfSDavid du Colombier 	Display *disp;
2097dd7cddfSDavid du Colombier 	Image *image;
2107dd7cddfSDavid du Colombier 	Dir dir;
2117dd7cddfSDavid du Colombier 	ulong chan;
2127dd7cddfSDavid du Colombier 
2137dd7cddfSDavid du Colombier 	fmtinstall('P', Pconv);
2147dd7cddfSDavid du Colombier 	fmtinstall('R', Rconv);
2157dd7cddfSDavid du Colombier 	if(dev == 0)
2167dd7cddfSDavid du Colombier 		dev = "/dev";
2177dd7cddfSDavid du Colombier 	if(win == 0)
2187dd7cddfSDavid du Colombier 		win = "/dev";
2197dd7cddfSDavid du Colombier 	if(strlen(dev)>sizeof buf-25 || strlen(win)>sizeof buf-25){
2207dd7cddfSDavid du Colombier 		werrstr("initdisplay: directory name too long");
2217dd7cddfSDavid du Colombier 		return nil;
2227dd7cddfSDavid du Colombier 	}
2237dd7cddfSDavid du Colombier 	t = strdup(win);
2247dd7cddfSDavid du Colombier 	if(t == nil)
2257dd7cddfSDavid du Colombier 		return nil;
2267dd7cddfSDavid du Colombier 
2277dd7cddfSDavid du Colombier 	sprint(buf, "%s/draw/new", dev);
2287dd7cddfSDavid du Colombier 	ctlfd = open(buf, ORDWR|OCEXEC);
2297dd7cddfSDavid du Colombier 	if(ctlfd < 0){
2307dd7cddfSDavid du Colombier 		if(bind("#i", dev, MAFTER) < 0){
2317dd7cddfSDavid du Colombier     Error1:
2327dd7cddfSDavid du Colombier 			free(t);
2337dd7cddfSDavid du Colombier 			werrstr("initdisplay: %s: %r", buf);
2347dd7cddfSDavid du Colombier 			return 0;
2357dd7cddfSDavid du Colombier 		}
2367dd7cddfSDavid du Colombier 		ctlfd = open(buf, ORDWR|OCEXEC);
2377dd7cddfSDavid du Colombier 	}
2387dd7cddfSDavid du Colombier 	if(ctlfd < 0)
2397dd7cddfSDavid du Colombier 		goto Error1;
2407dd7cddfSDavid du Colombier 	if(read(ctlfd, info, sizeof info) < NINFO){
2417dd7cddfSDavid du Colombier     Error2:
2427dd7cddfSDavid du Colombier 		close(ctlfd);
2437dd7cddfSDavid du Colombier 		goto Error1;
2447dd7cddfSDavid du Colombier 	}
2457dd7cddfSDavid du Colombier 
2467dd7cddfSDavid du Colombier 	if((chan=strtochan(info+2*12)) == 0){
2477dd7cddfSDavid du Colombier 		werrstr("bad channel in %s", buf);
2487dd7cddfSDavid du Colombier 		goto Error2;
2497dd7cddfSDavid du Colombier 	}
2507dd7cddfSDavid du Colombier 
2517dd7cddfSDavid du Colombier 	sprint(buf, "%s/draw/%d/data", dev, atoi(info+0*12));
2527dd7cddfSDavid du Colombier 	datafd = open(buf, ORDWR|OCEXEC);
2537dd7cddfSDavid du Colombier 	if(datafd < 0)
2547dd7cddfSDavid du Colombier 		goto Error2;
2557dd7cddfSDavid du Colombier 	sprint(buf, "%s/draw/%d/refresh", dev, atoi(info+0*12));
2567dd7cddfSDavid du Colombier 	reffd = open(buf, OREAD|OCEXEC);
2577dd7cddfSDavid du Colombier 	if(reffd < 0){
2587dd7cddfSDavid du Colombier     Error3:
2597dd7cddfSDavid du Colombier 		close(datafd);
2607dd7cddfSDavid du Colombier 		goto Error2;
2617dd7cddfSDavid du Colombier 	}
2627dd7cddfSDavid du Colombier 	disp = malloc(sizeof(Display));
2637dd7cddfSDavid du Colombier 	if(disp == 0){
2647dd7cddfSDavid du Colombier     Error4:
2657dd7cddfSDavid du Colombier 		close(reffd);
2667dd7cddfSDavid du Colombier 		goto Error3;
2677dd7cddfSDavid du Colombier 	}
2687dd7cddfSDavid du Colombier 	image = malloc(sizeof(Image));
2697dd7cddfSDavid du Colombier 	if(image == 0){
2707dd7cddfSDavid du Colombier     Error5:
2717dd7cddfSDavid du Colombier 		free(disp);
2727dd7cddfSDavid du Colombier 		goto Error4;
2737dd7cddfSDavid du Colombier 	}
2747dd7cddfSDavid du Colombier 	memset(image, 0, sizeof(Image));
2757dd7cddfSDavid du Colombier 	memset(disp, 0, sizeof(Display));
2767dd7cddfSDavid du Colombier 	image->display = disp;
2777dd7cddfSDavid du Colombier 	image->id = 0;
2787dd7cddfSDavid du Colombier 	image->chan = chan;
2797dd7cddfSDavid du Colombier 	image->depth = chantodepth(chan);
2807dd7cddfSDavid du Colombier 	image->repl = atoi(info+3*12);
2817dd7cddfSDavid du Colombier 	image->r.min.x = atoi(info+4*12);
2827dd7cddfSDavid du Colombier 	image->r.min.y = atoi(info+5*12);
2837dd7cddfSDavid du Colombier 	image->r.max.x = atoi(info+6*12);
2847dd7cddfSDavid du Colombier 	image->r.max.y = atoi(info+7*12);
2857dd7cddfSDavid du Colombier 	image->clipr.min.x = atoi(info+8*12);
2867dd7cddfSDavid du Colombier 	image->clipr.min.y = atoi(info+9*12);
2877dd7cddfSDavid du Colombier 	image->clipr.max.x = atoi(info+10*12);
2887dd7cddfSDavid du Colombier 	image->clipr.max.y = atoi(info+11*12);
2897dd7cddfSDavid du Colombier 	disp->dirno = atoi(info+0*12);
2907dd7cddfSDavid du Colombier 	disp->fd = datafd;
2917dd7cddfSDavid du Colombier 	disp->ctlfd = ctlfd;
2927dd7cddfSDavid du Colombier 	disp->reffd = reffd;
2937dd7cddfSDavid du Colombier 	disp->image = image;
2947dd7cddfSDavid du Colombier 	disp->bufp = disp->buf;
2957dd7cddfSDavid du Colombier 	disp->error = error;
2967dd7cddfSDavid du Colombier 	disp->chan = image->chan;
2977dd7cddfSDavid du Colombier 	disp->depth = image->depth;
2987dd7cddfSDavid du Colombier 	disp->windir = t;
2997dd7cddfSDavid du Colombier 	disp->devdir = strdup(dev);
3007dd7cddfSDavid du Colombier 	qlock(&disp->qlock);
3017dd7cddfSDavid du Colombier 	disp->white = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DWhite);
3027dd7cddfSDavid du Colombier 	disp->black = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DBlack);
3037dd7cddfSDavid du Colombier 	if(disp->white == nil || disp->black == nil){
3047dd7cddfSDavid du Colombier 		free(image);
3057dd7cddfSDavid du Colombier 		free(disp->devdir);
3067dd7cddfSDavid du Colombier 		free(disp->white);
3077dd7cddfSDavid du Colombier 		free(disp->black);
3087dd7cddfSDavid du Colombier 		goto Error5;
3097dd7cddfSDavid du Colombier 	}
3107dd7cddfSDavid du Colombier 	disp->opaque = disp->white;
3117dd7cddfSDavid du Colombier 	disp->transparent = disp->black;
3127dd7cddfSDavid du Colombier 	if(dirfstat(ctlfd, &dir)>=0 && dir.type=='i'){
3137dd7cddfSDavid du Colombier 		disp->local = 1;
3147dd7cddfSDavid du Colombier 		disp->dataqid = dir.qid.path;
3157dd7cddfSDavid du Colombier 	}
3167dd7cddfSDavid du Colombier 
3177dd7cddfSDavid du Colombier 	assert(disp->chan != 0 && image->chan != 0);
3187dd7cddfSDavid du Colombier 	return disp;
3197dd7cddfSDavid du Colombier }
3207dd7cddfSDavid du Colombier 
3217dd7cddfSDavid du Colombier /*
3227dd7cddfSDavid du Colombier  * Call with d unlocked.
3237dd7cddfSDavid du Colombier  * Note that disp->defaultfont and defaultsubfont are not freed here.
3247dd7cddfSDavid du Colombier  */
3257dd7cddfSDavid du Colombier void
3267dd7cddfSDavid du Colombier closedisplay(Display *disp)
3277dd7cddfSDavid du Colombier {
3287dd7cddfSDavid du Colombier 	int fd;
3297dd7cddfSDavid du Colombier 	char buf[128];
3307dd7cddfSDavid du Colombier 
3317dd7cddfSDavid du Colombier 	if(disp == nil)
3327dd7cddfSDavid du Colombier 		return;
3337dd7cddfSDavid du Colombier 	if(disp == display)
3347dd7cddfSDavid du Colombier 		display = nil;
3357dd7cddfSDavid du Colombier 	if(disp->oldlabel[0]){
3367dd7cddfSDavid du Colombier 		snprint(buf, sizeof buf, "%s/label", disp->windir);
3377dd7cddfSDavid du Colombier 		fd = open(buf, OWRITE);
3387dd7cddfSDavid du Colombier 		if(fd >= 0){
3397dd7cddfSDavid du Colombier 			write(fd, disp->oldlabel, strlen(disp->oldlabel));
3407dd7cddfSDavid du Colombier 			close(fd);
3417dd7cddfSDavid du Colombier 		}
3427dd7cddfSDavid du Colombier 	}
3437dd7cddfSDavid du Colombier 
3447dd7cddfSDavid du Colombier 	free(disp->devdir);
3457dd7cddfSDavid du Colombier 	free(disp->windir);
3467dd7cddfSDavid du Colombier 	freeimage(disp->white);
3477dd7cddfSDavid du Colombier 	freeimage(disp->black);
3487dd7cddfSDavid du Colombier 	free(disp->image);
3497dd7cddfSDavid du Colombier 	close(disp->fd);
3507dd7cddfSDavid du Colombier 	close(disp->ctlfd);
3517dd7cddfSDavid du Colombier 	/* should cause refresh slave to shut down */
3527dd7cddfSDavid du Colombier 	close(disp->reffd);
3537dd7cddfSDavid du Colombier 	qunlock(&disp->qlock);
3547dd7cddfSDavid du Colombier 	free(disp);
3557dd7cddfSDavid du Colombier }
3567dd7cddfSDavid du Colombier 
3577dd7cddfSDavid du Colombier void
3587dd7cddfSDavid du Colombier lockdisplay(Display *disp)
3597dd7cddfSDavid du Colombier {
3607dd7cddfSDavid du Colombier 	if(debuglockdisplay){
3617dd7cddfSDavid du Colombier 		/* avoid busy looping; it's rare we collide anyway */
3627dd7cddfSDavid du Colombier 		while(!canqlock(&disp->qlock)){
3637dd7cddfSDavid du Colombier 			_drawprint(1, "proc %d waiting for display lock...\n", getpid());
3647dd7cddfSDavid du Colombier 			sleep(1000);
3657dd7cddfSDavid du Colombier 		}
3667dd7cddfSDavid du Colombier 	}else
3677dd7cddfSDavid du Colombier 		qlock(&disp->qlock);
3687dd7cddfSDavid du Colombier }
3697dd7cddfSDavid du Colombier 
3707dd7cddfSDavid du Colombier void
3717dd7cddfSDavid du Colombier unlockdisplay(Display *disp)
3727dd7cddfSDavid du Colombier {
3737dd7cddfSDavid du Colombier 	qunlock(&disp->qlock);
3747dd7cddfSDavid du Colombier }
3757dd7cddfSDavid du Colombier 
3767dd7cddfSDavid du Colombier /* use static buffer to avoid stack bloat */
3777dd7cddfSDavid du Colombier int
3787dd7cddfSDavid du Colombier _drawprint(int fd, char *fmt, ...)
3797dd7cddfSDavid du Colombier {
3807dd7cddfSDavid du Colombier 	int n;
3817dd7cddfSDavid du Colombier 	va_list arg;
3827dd7cddfSDavid du Colombier 	static char buf[1024];
3837dd7cddfSDavid du Colombier 	static QLock l;
3847dd7cddfSDavid du Colombier 
3857dd7cddfSDavid du Colombier 	qlock(&l);
3867dd7cddfSDavid du Colombier 	va_start(arg, fmt);
3877dd7cddfSDavid du Colombier 	doprint(buf, buf+sizeof buf, fmt, arg);
3887dd7cddfSDavid du Colombier 	va_end(arg);
3897dd7cddfSDavid du Colombier 	n = write(fd, buf, strlen(buf));
3907dd7cddfSDavid du Colombier 	qunlock(&l);
3917dd7cddfSDavid du Colombier 	return n;
3927dd7cddfSDavid du Colombier }
3937dd7cddfSDavid du Colombier 
3947dd7cddfSDavid du Colombier void
3957dd7cddfSDavid du Colombier drawerror(Display *d, char *s)
3967dd7cddfSDavid du Colombier {
3977dd7cddfSDavid du Colombier 	char err[ERRLEN];
3987dd7cddfSDavid du Colombier 
3997dd7cddfSDavid du Colombier 	if(d->error)
4007dd7cddfSDavid du Colombier 		d->error(d, s);
4017dd7cddfSDavid du Colombier 	else{
4027dd7cddfSDavid du Colombier 		errstr(err);
4037dd7cddfSDavid du Colombier 		_drawprint(2, "draw: %s: %s\n", s, err);
4047dd7cddfSDavid du Colombier 		exits(s);
4057dd7cddfSDavid du Colombier 	}
4067dd7cddfSDavid du Colombier }
4077dd7cddfSDavid du Colombier 
4087dd7cddfSDavid du Colombier static
4097dd7cddfSDavid du Colombier int
4107dd7cddfSDavid du Colombier doflush(Display *d)
4117dd7cddfSDavid du Colombier {
4127dd7cddfSDavid du Colombier 	int n;
4137dd7cddfSDavid du Colombier 
4147dd7cddfSDavid du Colombier 	n = d->bufp-d->buf;
4157dd7cddfSDavid du Colombier 	if(n <= 0)
4167dd7cddfSDavid du Colombier 		return 1;
4177dd7cddfSDavid du Colombier 
4187dd7cddfSDavid du Colombier 	if(write(d->fd, d->buf, n) != n){
41959cc4ca5SDavid du Colombier 		if(_drawdebug)
42059cc4ca5SDavid du Colombier 			_drawprint(2, "flushimage fail: d=%p: %r\n", d); /**/
4217dd7cddfSDavid du Colombier 		d->bufp = d->buf;	/* might as well; chance of continuing */
4227dd7cddfSDavid du Colombier 		return -1;
4237dd7cddfSDavid du Colombier 	}
4247dd7cddfSDavid du Colombier 	d->bufp = d->buf;
4257dd7cddfSDavid du Colombier 	return 1;
4267dd7cddfSDavid du Colombier }
4277dd7cddfSDavid du Colombier 
4287dd7cddfSDavid du Colombier int
4297dd7cddfSDavid du Colombier flushimage(Display *d, int visible)
4307dd7cddfSDavid du Colombier {
4317dd7cddfSDavid du Colombier 	if(visible)
4327dd7cddfSDavid du Colombier 		*d->bufp++ = 'v';	/* one byte always reserved for this */
4337dd7cddfSDavid du Colombier 	return doflush(d);
4347dd7cddfSDavid du Colombier }
4357dd7cddfSDavid du Colombier 
4367dd7cddfSDavid du Colombier uchar*
4377dd7cddfSDavid du Colombier bufimage(Display *d, int n)
4387dd7cddfSDavid du Colombier {
4397dd7cddfSDavid du Colombier 	uchar *p;
4407dd7cddfSDavid du Colombier 
4417dd7cddfSDavid du Colombier 	if(n<0 || n>Displaybufsize){
4427dd7cddfSDavid du Colombier 		werrstr("bad count in bufimage");
4437dd7cddfSDavid du Colombier 		return 0;
4447dd7cddfSDavid du Colombier 	}
4457dd7cddfSDavid du Colombier 	if(d->bufp+n > d->buf+Displaybufsize)
4467dd7cddfSDavid du Colombier 		if(doflush(d) < 0)
4477dd7cddfSDavid du Colombier 			return 0;
4487dd7cddfSDavid du Colombier 	p = d->bufp;
4497dd7cddfSDavid du Colombier 	d->bufp += n;
4507dd7cddfSDavid du Colombier 	return p;
4517dd7cddfSDavid du Colombier }
4527dd7cddfSDavid du Colombier 
453