xref: /plan9/sys/src/libdraw/init.c (revision 711d15577662d055e75a7f87f5884323f7e7fad6)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier 
57dd7cddfSDavid du Colombier Display	*display;
67dd7cddfSDavid du Colombier Font	*font;
77dd7cddfSDavid du Colombier Image	*screen;
8*711d1557SDavid du Colombier int	_drawdebug = 0;
97dd7cddfSDavid du Colombier 
107dd7cddfSDavid du Colombier static char deffontname[] = "*default*";
117dd7cddfSDavid du Colombier Screen	*_screen;
127dd7cddfSDavid du Colombier 
137dd7cddfSDavid du Colombier int		debuglockdisplay = 0;
147dd7cddfSDavid du Colombier 
157dd7cddfSDavid du Colombier static void
167dd7cddfSDavid du Colombier drawshutdown(void)
177dd7cddfSDavid du Colombier {
187dd7cddfSDavid du Colombier 	Display *d;
197dd7cddfSDavid du Colombier 
207dd7cddfSDavid du Colombier 	d = display;
217dd7cddfSDavid du Colombier 	if(d){
227dd7cddfSDavid du Colombier 		display = nil;
237dd7cddfSDavid du Colombier 		closedisplay(d);
247dd7cddfSDavid du Colombier 	}
257dd7cddfSDavid du Colombier }
267dd7cddfSDavid du Colombier 
277dd7cddfSDavid du Colombier int
287dd7cddfSDavid du Colombier geninitdraw(char *devdir, void(*error)(Display*, char*), char *fontname, char *label, char *windir, int ref)
297dd7cddfSDavid du Colombier {
307dd7cddfSDavid du Colombier 	int fd, n;
317dd7cddfSDavid du Colombier 	Subfont *df;
327dd7cddfSDavid du Colombier 	char buf[128];
337dd7cddfSDavid du Colombier 
347dd7cddfSDavid du Colombier 	display = initdisplay(devdir, windir, error);
357dd7cddfSDavid du Colombier 	if(display == nil)
367dd7cddfSDavid du Colombier 		return -1;
377dd7cddfSDavid du Colombier 
387dd7cddfSDavid du Colombier 	/*
397dd7cddfSDavid du Colombier 	 * Set up default font
407dd7cddfSDavid du Colombier 	 */
417dd7cddfSDavid du Colombier 	df = getdefont(display);
427dd7cddfSDavid du Colombier 	display->defaultsubfont = df;
437dd7cddfSDavid du Colombier 	if(df == nil){
449a747e4fSDavid du Colombier 		fprint(2, "imageinit: can't open default subfont: %r\n");
457dd7cddfSDavid du Colombier     Error:
467dd7cddfSDavid du Colombier 		closedisplay(display);
477dd7cddfSDavid du Colombier 		display = nil;
487dd7cddfSDavid du Colombier 		return -1;
497dd7cddfSDavid du Colombier 	}
507dd7cddfSDavid du Colombier 	if(fontname == nil){
517dd7cddfSDavid du Colombier 		fd = open("/env/font", OREAD);
527dd7cddfSDavid du Colombier 		if(fd >= 0){
537dd7cddfSDavid du Colombier 			n = read(fd, buf, sizeof(buf));
547dd7cddfSDavid du Colombier 			if(n>0 && n<sizeof buf-1){
557dd7cddfSDavid du Colombier 				buf[n] = 0;
567dd7cddfSDavid du Colombier 				fontname = buf;
577dd7cddfSDavid du Colombier 			}
587dd7cddfSDavid du Colombier 			close(fd);
597dd7cddfSDavid du Colombier 		}
607dd7cddfSDavid du Colombier 	}
617dd7cddfSDavid du Colombier 	/*
627dd7cddfSDavid du Colombier 	 * Build fonts with caches==depth of screen, for speed.
637dd7cddfSDavid du Colombier 	 * If conversion were faster, we'd use 0 and save memory.
647dd7cddfSDavid du Colombier 	 */
657dd7cddfSDavid du Colombier 	if(fontname == nil){
667dd7cddfSDavid du Colombier 		snprint(buf, sizeof buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent,
677dd7cddfSDavid du Colombier 			df->n-1, deffontname);
687dd7cddfSDavid du Colombier //BUG: Need something better for this	installsubfont("*default*", df);
697dd7cddfSDavid du Colombier 		font = buildfont(display, buf, deffontname);
707dd7cddfSDavid du Colombier 		if(font == nil){
719a747e4fSDavid du Colombier 			fprint(2, "imageinit: can't open default font: %r\n");
727dd7cddfSDavid du Colombier 			goto Error;
737dd7cddfSDavid du Colombier 		}
747dd7cddfSDavid du Colombier 	}else{
757dd7cddfSDavid du Colombier 		font = openfont(display, fontname);	/* BUG: grey fonts */
767dd7cddfSDavid du Colombier 		if(font == nil){
779a747e4fSDavid du Colombier 			fprint(2, "imageinit: can't open font %s: %r\n", fontname);
787dd7cddfSDavid du Colombier 			goto Error;
797dd7cddfSDavid du Colombier 		}
807dd7cddfSDavid du Colombier 	}
817dd7cddfSDavid du Colombier 	display->defaultfont = font;
827dd7cddfSDavid du Colombier 
837dd7cddfSDavid du Colombier 	/*
847dd7cddfSDavid du Colombier 	 * Write label; ignore errors (we might not be running under rio)
857dd7cddfSDavid du Colombier 	 */
867dd7cddfSDavid du Colombier 	if(label){
877dd7cddfSDavid du Colombier 		snprint(buf, sizeof buf, "%s/label", display->windir);
887dd7cddfSDavid du Colombier 		fd = open(buf, OREAD);
897dd7cddfSDavid du Colombier 		if(fd >= 0){
907dd7cddfSDavid du Colombier 			read(fd, display->oldlabel, (sizeof display->oldlabel)-1);
917dd7cddfSDavid du Colombier 			close(fd);
927dd7cddfSDavid du Colombier 			fd = create(buf, OWRITE, 0666);
937dd7cddfSDavid du Colombier 			if(fd >= 0){
947dd7cddfSDavid du Colombier 				write(fd, label, strlen(label));
957dd7cddfSDavid du Colombier 				close(fd);
967dd7cddfSDavid du Colombier 			}
977dd7cddfSDavid du Colombier 		}
987dd7cddfSDavid du Colombier 	}
997dd7cddfSDavid du Colombier 
1009a747e4fSDavid du Colombier 	snprint(buf, sizeof buf, "%s/winname", display->windir);
1019a747e4fSDavid du Colombier 	if(gengetwindow(display, buf, &screen, &_screen, ref) < 0)
1027dd7cddfSDavid du Colombier 		goto Error;
1037dd7cddfSDavid du Colombier 
1047dd7cddfSDavid du Colombier 	atexit(drawshutdown);
1057dd7cddfSDavid du Colombier 
1067dd7cddfSDavid du Colombier 	return 1;
1077dd7cddfSDavid du Colombier }
1087dd7cddfSDavid du Colombier 
1097dd7cddfSDavid du Colombier int
1107dd7cddfSDavid du Colombier initdraw(void(*error)(Display*, char*), char *fontname , char *label)
1117dd7cddfSDavid du Colombier {
1127dd7cddfSDavid du Colombier 	char *dev = "/dev";
1137dd7cddfSDavid du Colombier 
1149a747e4fSDavid du Colombier 	if(access("/dev/draw/new", AEXIST)<0 && bind("#i", "/dev", MAFTER)<0){
1159a747e4fSDavid du Colombier 		fprint(2, "imageinit: can't bind /dev/draw: %r");
1167dd7cddfSDavid du Colombier 		return -1;
1177dd7cddfSDavid du Colombier 	}
1187dd7cddfSDavid du Colombier 	return geninitdraw(dev, error, fontname, label, dev, Refnone);
1197dd7cddfSDavid du Colombier }
1207dd7cddfSDavid du Colombier 
1217dd7cddfSDavid du Colombier /*
1227dd7cddfSDavid du Colombier  * Attach, or possibly reattach, to window.
1237dd7cddfSDavid du Colombier  * If reattaching, maintain value of screen pointer.
1247dd7cddfSDavid du Colombier  */
1257dd7cddfSDavid du Colombier int
12680ee5cbfSDavid du Colombier gengetwindow(Display *d, char *winname, Image **winp, Screen **scrp, int ref)
1277dd7cddfSDavid du Colombier {
1287dd7cddfSDavid du Colombier 	int n, fd;
12980ee5cbfSDavid du Colombier 	char buf[64+1];
1307dd7cddfSDavid du Colombier 	Image *image;
1319a747e4fSDavid du Colombier 	Rectangle r;
1327dd7cddfSDavid du Colombier 
13380ee5cbfSDavid du Colombier 	fd = open(winname, OREAD);
13480ee5cbfSDavid du Colombier 	if(fd<0 || (n=read(fd, buf, sizeof buf-1))<=0){
1359a747e4fSDavid du Colombier 		if((image=d->image) == nil){
1369a747e4fSDavid du Colombier 			fprint(2, "gengetwindow: %r\n");
1379a747e4fSDavid du Colombier 			*winp = nil;
1389a747e4fSDavid du Colombier 			d->screenimage = nil;
1399a747e4fSDavid du Colombier 			return -1;
1407dd7cddfSDavid du Colombier 		}
1419a747e4fSDavid du Colombier 		strcpy(buf, "noborder");
1429a747e4fSDavid du Colombier 	}else{
1437dd7cddfSDavid du Colombier 		close(fd);
14480ee5cbfSDavid du Colombier 		buf[n] = '\0';
14580ee5cbfSDavid du Colombier 		if(*winp != nil){
14680ee5cbfSDavid du Colombier 			_freeimage1(*winp);
14780ee5cbfSDavid du Colombier 			freeimage((*scrp)->image);
14880ee5cbfSDavid du Colombier 			freescreen(*scrp);
14980ee5cbfSDavid du Colombier 			*scrp = nil;
1507dd7cddfSDavid du Colombier 		}
15180ee5cbfSDavid du Colombier 		image = namedimage(d, buf);
1527dd7cddfSDavid du Colombier 		if(image == 0){
1539a747e4fSDavid du Colombier 			fprint(2, "namedimage %s failed: %r\n", buf);
15480ee5cbfSDavid du Colombier 			*winp = nil;
1559a747e4fSDavid du Colombier 			d->screenimage = nil;
1567dd7cddfSDavid du Colombier 			return -1;
1577dd7cddfSDavid du Colombier 		}
1587dd7cddfSDavid du Colombier 		assert(image->chan != 0);
1599a747e4fSDavid du Colombier 	}
1607dd7cddfSDavid du Colombier 
1619a747e4fSDavid du Colombier 	d->screenimage = image;
16280ee5cbfSDavid du Colombier 	*scrp = allocscreen(image, d->white, 0);
16380ee5cbfSDavid du Colombier 	if(*scrp == nil){
1649a747e4fSDavid du Colombier 		freeimage(d->screenimage);
16580ee5cbfSDavid du Colombier 		*winp = nil;
1669a747e4fSDavid du Colombier 		d->screenimage = nil;
1677dd7cddfSDavid du Colombier 		return -1;
1687dd7cddfSDavid du Colombier 	}
1697dd7cddfSDavid du Colombier 
1709a747e4fSDavid du Colombier 	r = image->r;
1719a747e4fSDavid du Colombier 	if(strncmp(buf, "noborder", 8) != 0)
1729a747e4fSDavid du Colombier 		r = insetrect(image->r, Borderwidth);
1739a747e4fSDavid du Colombier 	*winp = _allocwindow(*winp, *scrp, r, ref, DWhite);
1749a747e4fSDavid du Colombier 	if(*winp == nil){
1759a747e4fSDavid du Colombier 		freescreen(*scrp);
1769a747e4fSDavid du Colombier 		*scrp = nil;
1779a747e4fSDavid du Colombier 		freeimage(image);
1789a747e4fSDavid du Colombier 		d->screenimage = nil;
1797dd7cddfSDavid du Colombier 		return -1;
1809a747e4fSDavid du Colombier 	}
1819a747e4fSDavid du Colombier 	d->screenimage = *winp;
18280ee5cbfSDavid du Colombier 	assert((*winp)->chan != 0);
1837dd7cddfSDavid du Colombier 	return 1;
1847dd7cddfSDavid du Colombier }
1857dd7cddfSDavid du Colombier 
18680ee5cbfSDavid du Colombier int
18780ee5cbfSDavid du Colombier getwindow(Display *d, int ref)
18880ee5cbfSDavid du Colombier {
18980ee5cbfSDavid du Colombier 	char winname[128];
19080ee5cbfSDavid du Colombier 
19180ee5cbfSDavid du Colombier 	snprint(winname, sizeof winname, "%s/winname", d->windir);
19280ee5cbfSDavid du Colombier 	return gengetwindow(d, winname, &screen, &_screen, ref);
19380ee5cbfSDavid du Colombier }
19480ee5cbfSDavid du Colombier 
1957dd7cddfSDavid du Colombier #define	NINFO	12*12
1967dd7cddfSDavid du Colombier 
1977dd7cddfSDavid du Colombier Display*
1987dd7cddfSDavid du Colombier initdisplay(char *dev, char *win, void(*error)(Display*, char*))
1997dd7cddfSDavid du Colombier {
2009a747e4fSDavid du Colombier 	char buf[128], info[NINFO+1], *t, isnew;
2019a747e4fSDavid du Colombier 	int n, datafd, ctlfd, reffd;
2027dd7cddfSDavid du Colombier 	Display *disp;
2039a747e4fSDavid du Colombier 	Dir *dir;
2047dd7cddfSDavid du Colombier 	Image *image;
2057dd7cddfSDavid du Colombier 
2069a747e4fSDavid du Colombier 	fmtinstall('P', Pfmt);
2079a747e4fSDavid du Colombier 	fmtinstall('R', Rfmt);
2087dd7cddfSDavid du Colombier 	if(dev == 0)
2097dd7cddfSDavid du Colombier 		dev = "/dev";
2107dd7cddfSDavid du Colombier 	if(win == 0)
2117dd7cddfSDavid du Colombier 		win = "/dev";
2127dd7cddfSDavid du Colombier 	if(strlen(dev)>sizeof buf-25 || strlen(win)>sizeof buf-25){
2137dd7cddfSDavid du Colombier 		werrstr("initdisplay: directory name too long");
2147dd7cddfSDavid du Colombier 		return nil;
2157dd7cddfSDavid du Colombier 	}
2167dd7cddfSDavid du Colombier 	t = strdup(win);
2177dd7cddfSDavid du Colombier 	if(t == nil)
2187dd7cddfSDavid du Colombier 		return nil;
2197dd7cddfSDavid du Colombier 
2207dd7cddfSDavid du Colombier 	sprint(buf, "%s/draw/new", dev);
2217dd7cddfSDavid du Colombier 	ctlfd = open(buf, ORDWR|OCEXEC);
2227dd7cddfSDavid du Colombier 	if(ctlfd < 0){
2237dd7cddfSDavid du Colombier 		if(bind("#i", dev, MAFTER) < 0){
2247dd7cddfSDavid du Colombier     Error1:
2257dd7cddfSDavid du Colombier 			free(t);
2267dd7cddfSDavid du Colombier 			werrstr("initdisplay: %s: %r", buf);
2277dd7cddfSDavid du Colombier 			return 0;
2287dd7cddfSDavid du Colombier 		}
2297dd7cddfSDavid du Colombier 		ctlfd = open(buf, ORDWR|OCEXEC);
2307dd7cddfSDavid du Colombier 	}
2317dd7cddfSDavid du Colombier 	if(ctlfd < 0)
2327dd7cddfSDavid du Colombier 		goto Error1;
2339a747e4fSDavid du Colombier 	if((n=read(ctlfd, info, sizeof info)) < 12){
2347dd7cddfSDavid du Colombier     Error2:
2357dd7cddfSDavid du Colombier 		close(ctlfd);
2367dd7cddfSDavid du Colombier 		goto Error1;
2377dd7cddfSDavid du Colombier 	}
2389a747e4fSDavid du Colombier 	if(n==NINFO+1)
2399a747e4fSDavid du Colombier 		n = NINFO;
2409a747e4fSDavid du Colombier 	buf[n] = '\0';
2419a747e4fSDavid du Colombier 	isnew = 0;
2429a747e4fSDavid du Colombier 	if(n < NINFO)	/* this will do for now, we need something better here */
2439a747e4fSDavid du Colombier 		isnew = 1;
2447dd7cddfSDavid du Colombier 	sprint(buf, "%s/draw/%d/data", dev, atoi(info+0*12));
2457dd7cddfSDavid du Colombier 	datafd = open(buf, ORDWR|OCEXEC);
2467dd7cddfSDavid du Colombier 	if(datafd < 0)
2477dd7cddfSDavid du Colombier 		goto Error2;
2487dd7cddfSDavid du Colombier 	sprint(buf, "%s/draw/%d/refresh", dev, atoi(info+0*12));
2497dd7cddfSDavid du Colombier 	reffd = open(buf, OREAD|OCEXEC);
2507dd7cddfSDavid du Colombier 	if(reffd < 0){
2517dd7cddfSDavid du Colombier     Error3:
2527dd7cddfSDavid du Colombier 		close(datafd);
2537dd7cddfSDavid du Colombier 		goto Error2;
2547dd7cddfSDavid du Colombier 	}
2559a747e4fSDavid du Colombier 	disp = mallocz(sizeof(Display), 1);
2567dd7cddfSDavid du Colombier 	if(disp == 0){
2577dd7cddfSDavid du Colombier     Error4:
2587dd7cddfSDavid du Colombier 		close(reffd);
2597dd7cddfSDavid du Colombier 		goto Error3;
2607dd7cddfSDavid du Colombier 	}
2619a747e4fSDavid du Colombier 	image = nil;
2629a747e4fSDavid du Colombier 	if(0){
2637dd7cddfSDavid du Colombier     Error5:
2649a747e4fSDavid du Colombier 		free(image);
2657dd7cddfSDavid du Colombier 		free(disp);
2667dd7cddfSDavid du Colombier 		goto Error4;
2677dd7cddfSDavid du Colombier 	}
2689a747e4fSDavid du Colombier 	if(n >= NINFO){
2699a747e4fSDavid du Colombier 		image = mallocz(sizeof(Image), 1);
2709a747e4fSDavid du Colombier 		if(image == nil)
2719a747e4fSDavid du Colombier 			goto Error5;
2727dd7cddfSDavid du Colombier 		image->display = disp;
2737dd7cddfSDavid du Colombier 		image->id = 0;
2749a747e4fSDavid du Colombier 		image->chan = strtochan(info+2*12);
2759a747e4fSDavid du Colombier 		image->depth = chantodepth(image->chan);
2767dd7cddfSDavid du Colombier 		image->repl = atoi(info+3*12);
2777dd7cddfSDavid du Colombier 		image->r.min.x = atoi(info+4*12);
2787dd7cddfSDavid du Colombier 		image->r.min.y = atoi(info+5*12);
2797dd7cddfSDavid du Colombier 		image->r.max.x = atoi(info+6*12);
2807dd7cddfSDavid du Colombier 		image->r.max.y = atoi(info+7*12);
2817dd7cddfSDavid du Colombier 		image->clipr.min.x = atoi(info+8*12);
2827dd7cddfSDavid du Colombier 		image->clipr.min.y = atoi(info+9*12);
2837dd7cddfSDavid du Colombier 		image->clipr.max.x = atoi(info+10*12);
2847dd7cddfSDavid du Colombier 		image->clipr.max.y = atoi(info+11*12);
2859a747e4fSDavid du Colombier 	}
2869a747e4fSDavid du Colombier 
2879a747e4fSDavid du Colombier 	disp->_isnewdisplay = isnew;
2889a747e4fSDavid du Colombier 	disp->bufsize = iounit(datafd);
2899a747e4fSDavid du Colombier 	if(disp->bufsize <= 0)
2909a747e4fSDavid du Colombier 		disp->bufsize = 8000;
2919a747e4fSDavid du Colombier 	if(disp->bufsize < 512){
2929a747e4fSDavid du Colombier 		werrstr("iounit %d too small", disp->bufsize);
2939a747e4fSDavid du Colombier 		goto Error5;
2949a747e4fSDavid du Colombier 	}
2959a747e4fSDavid du Colombier 	disp->buf = malloc(disp->bufsize+5);	/* +5 for flush message */
2969a747e4fSDavid du Colombier 	if(disp->buf == nil)
2979a747e4fSDavid du Colombier 		goto Error5;
2989a747e4fSDavid du Colombier 
2999a747e4fSDavid du Colombier 	disp->image = image;
3007dd7cddfSDavid du Colombier 	disp->dirno = atoi(info+0*12);
3017dd7cddfSDavid du Colombier 	disp->fd = datafd;
3027dd7cddfSDavid du Colombier 	disp->ctlfd = ctlfd;
3037dd7cddfSDavid du Colombier 	disp->reffd = reffd;
3047dd7cddfSDavid du Colombier 	disp->bufp = disp->buf;
3057dd7cddfSDavid du Colombier 	disp->error = error;
3067dd7cddfSDavid du Colombier 	disp->windir = t;
3077dd7cddfSDavid du Colombier 	disp->devdir = strdup(dev);
3087dd7cddfSDavid du Colombier 	qlock(&disp->qlock);
3097dd7cddfSDavid du Colombier 	disp->white = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DWhite);
3107dd7cddfSDavid du Colombier 	disp->black = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DBlack);
3117dd7cddfSDavid du Colombier 	if(disp->white == nil || disp->black == nil){
3127dd7cddfSDavid du Colombier 		free(disp->devdir);
3137dd7cddfSDavid du Colombier 		free(disp->white);
3147dd7cddfSDavid du Colombier 		free(disp->black);
3157dd7cddfSDavid du Colombier 		goto Error5;
3167dd7cddfSDavid du Colombier 	}
3177dd7cddfSDavid du Colombier 	disp->opaque = disp->white;
3187dd7cddfSDavid du Colombier 	disp->transparent = disp->black;
3199a747e4fSDavid du Colombier 	dir = dirfstat(ctlfd);
3209a747e4fSDavid du Colombier 	if(dir!=nil && dir->type=='i'){
3217dd7cddfSDavid du Colombier 		disp->local = 1;
3229a747e4fSDavid du Colombier 		disp->dataqid = dir->qid.path;
3237dd7cddfSDavid du Colombier 	}
3249a747e4fSDavid du Colombier 	if(dir!=nil && dir->qid.vers==1)	/* other way to tell */
3259a747e4fSDavid du Colombier 		disp->_isnewdisplay = 1;
3269a747e4fSDavid du Colombier 	free(dir);
3277dd7cddfSDavid du Colombier 
3287dd7cddfSDavid du Colombier 	return disp;
3297dd7cddfSDavid du Colombier }
3307dd7cddfSDavid du Colombier 
3317dd7cddfSDavid du Colombier /*
3327dd7cddfSDavid du Colombier  * Call with d unlocked.
3337dd7cddfSDavid du Colombier  * Note that disp->defaultfont and defaultsubfont are not freed here.
3347dd7cddfSDavid du Colombier  */
3357dd7cddfSDavid du Colombier void
3367dd7cddfSDavid du Colombier closedisplay(Display *disp)
3377dd7cddfSDavid du Colombier {
3387dd7cddfSDavid du Colombier 	int fd;
3397dd7cddfSDavid du Colombier 	char buf[128];
3407dd7cddfSDavid du Colombier 
3417dd7cddfSDavid du Colombier 	if(disp == nil)
3427dd7cddfSDavid du Colombier 		return;
3437dd7cddfSDavid du Colombier 	if(disp == display)
3447dd7cddfSDavid du Colombier 		display = nil;
3457dd7cddfSDavid du Colombier 	if(disp->oldlabel[0]){
3467dd7cddfSDavid du Colombier 		snprint(buf, sizeof buf, "%s/label", disp->windir);
3477dd7cddfSDavid du Colombier 		fd = open(buf, OWRITE);
3487dd7cddfSDavid du Colombier 		if(fd >= 0){
3497dd7cddfSDavid du Colombier 			write(fd, disp->oldlabel, strlen(disp->oldlabel));
3507dd7cddfSDavid du Colombier 			close(fd);
3517dd7cddfSDavid du Colombier 		}
3527dd7cddfSDavid du Colombier 	}
3537dd7cddfSDavid du Colombier 
3547dd7cddfSDavid du Colombier 	free(disp->devdir);
3557dd7cddfSDavid du Colombier 	free(disp->windir);
3567dd7cddfSDavid du Colombier 	freeimage(disp->white);
3577dd7cddfSDavid du Colombier 	freeimage(disp->black);
3587dd7cddfSDavid du Colombier 	close(disp->fd);
3597dd7cddfSDavid du Colombier 	close(disp->ctlfd);
3607dd7cddfSDavid du Colombier 	/* should cause refresh slave to shut down */
3617dd7cddfSDavid du Colombier 	close(disp->reffd);
3627dd7cddfSDavid du Colombier 	qunlock(&disp->qlock);
3637dd7cddfSDavid du Colombier 	free(disp);
3647dd7cddfSDavid du Colombier }
3657dd7cddfSDavid du Colombier 
3667dd7cddfSDavid du Colombier void
3677dd7cddfSDavid du Colombier lockdisplay(Display *disp)
3687dd7cddfSDavid du Colombier {
3697dd7cddfSDavid du Colombier 	if(debuglockdisplay){
3707dd7cddfSDavid du Colombier 		/* avoid busy looping; it's rare we collide anyway */
3717dd7cddfSDavid du Colombier 		while(!canqlock(&disp->qlock)){
3729a747e4fSDavid du Colombier 			fprint(1, "proc %d waiting for display lock...\n", getpid());
3737dd7cddfSDavid du Colombier 			sleep(1000);
3747dd7cddfSDavid du Colombier 		}
3757dd7cddfSDavid du Colombier 	}else
3767dd7cddfSDavid du Colombier 		qlock(&disp->qlock);
3777dd7cddfSDavid du Colombier }
3787dd7cddfSDavid du Colombier 
3797dd7cddfSDavid du Colombier void
3807dd7cddfSDavid du Colombier unlockdisplay(Display *disp)
3817dd7cddfSDavid du Colombier {
3827dd7cddfSDavid du Colombier 	qunlock(&disp->qlock);
3837dd7cddfSDavid du Colombier }
3847dd7cddfSDavid du Colombier 
3857dd7cddfSDavid du Colombier void
3867dd7cddfSDavid du Colombier drawerror(Display *d, char *s)
3877dd7cddfSDavid du Colombier {
3889a747e4fSDavid du Colombier 	char err[ERRMAX];
3897dd7cddfSDavid du Colombier 
3907dd7cddfSDavid du Colombier 	if(d->error)
3917dd7cddfSDavid du Colombier 		d->error(d, s);
3927dd7cddfSDavid du Colombier 	else{
3939a747e4fSDavid du Colombier 		errstr(err, sizeof err);
3949a747e4fSDavid du Colombier 		fprint(2, "draw: %s: %s\n", s, err);
3957dd7cddfSDavid du Colombier 		exits(s);
3967dd7cddfSDavid du Colombier 	}
3977dd7cddfSDavid du Colombier }
3987dd7cddfSDavid du Colombier 
3997dd7cddfSDavid du Colombier static
4007dd7cddfSDavid du Colombier int
4017dd7cddfSDavid du Colombier doflush(Display *d)
4027dd7cddfSDavid du Colombier {
403*711d1557SDavid du Colombier 	int n, nn;
4047dd7cddfSDavid du Colombier 
4057dd7cddfSDavid du Colombier 	n = d->bufp-d->buf;
4067dd7cddfSDavid du Colombier 	if(n <= 0)
4077dd7cddfSDavid du Colombier 		return 1;
4087dd7cddfSDavid du Colombier 
409*711d1557SDavid du Colombier 	if((nn=write(d->fd, d->buf, n)) != n){
41059cc4ca5SDavid du Colombier 		if(_drawdebug)
411*711d1557SDavid du Colombier 			fprint(2, "flushimage fail: d=%p: n=%d nn=%d %r\n", d, n, nn); /**/
4127dd7cddfSDavid du Colombier 		d->bufp = d->buf;	/* might as well; chance of continuing */
4137dd7cddfSDavid du Colombier 		return -1;
4147dd7cddfSDavid du Colombier 	}
4157dd7cddfSDavid du Colombier 	d->bufp = d->buf;
4167dd7cddfSDavid du Colombier 	return 1;
4177dd7cddfSDavid du Colombier }
4187dd7cddfSDavid du Colombier 
4197dd7cddfSDavid du Colombier int
4207dd7cddfSDavid du Colombier flushimage(Display *d, int visible)
4217dd7cddfSDavid du Colombier {
4229a747e4fSDavid du Colombier 	if(visible){
4239a747e4fSDavid du Colombier 		*d->bufp++ = 'v';	/* five bytes always reserved for this */
4249a747e4fSDavid du Colombier 		if(d->_isnewdisplay){
4259a747e4fSDavid du Colombier 			BPLONG(d->bufp, d->screenimage->id);
4269a747e4fSDavid du Colombier 			d->bufp += 4;
4279a747e4fSDavid du Colombier 		}
4289a747e4fSDavid du Colombier 	}
4297dd7cddfSDavid du Colombier 	return doflush(d);
4307dd7cddfSDavid du Colombier }
4317dd7cddfSDavid du Colombier 
4327dd7cddfSDavid du Colombier uchar*
4337dd7cddfSDavid du Colombier bufimage(Display *d, int n)
4347dd7cddfSDavid du Colombier {
4357dd7cddfSDavid du Colombier 	uchar *p;
4367dd7cddfSDavid du Colombier 
4379a747e4fSDavid du Colombier 	if(n<0 || n>d->bufsize){
4387dd7cddfSDavid du Colombier 		werrstr("bad count in bufimage");
4397dd7cddfSDavid du Colombier 		return 0;
4407dd7cddfSDavid du Colombier 	}
4419a747e4fSDavid du Colombier 	if(d->bufp+n > d->buf+d->bufsize)
4427dd7cddfSDavid du Colombier 		if(doflush(d) < 0)
4437dd7cddfSDavid du Colombier 			return 0;
4447dd7cddfSDavid du Colombier 	p = d->bufp;
4457dd7cddfSDavid du Colombier 	d->bufp += n;
4467dd7cddfSDavid du Colombier 	return p;
4477dd7cddfSDavid du Colombier }
4487dd7cddfSDavid du Colombier 
449