xref: /plan9/sys/src/libdraw/init.c (revision 5d9de2d38d2503efca29e12e0e32036368a7a75f)
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;
8711d1557SDavid 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 
15f366f900SDavid du Colombier static void _closedisplay(Display*, int);
16f366f900SDavid du Colombier 
17f366f900SDavid du Colombier /* note handler */
187dd7cddfSDavid du Colombier static void
drawshutdown(void)197dd7cddfSDavid du Colombier drawshutdown(void)
207dd7cddfSDavid du Colombier {
217dd7cddfSDavid du Colombier 	Display *d;
227dd7cddfSDavid du Colombier 
237dd7cddfSDavid du Colombier 	d = display;
247dd7cddfSDavid du Colombier 	if(d){
257dd7cddfSDavid du Colombier 		display = nil;
26f366f900SDavid du Colombier 		_closedisplay(d, 1);
277dd7cddfSDavid du Colombier 	}
287dd7cddfSDavid du Colombier }
297dd7cddfSDavid du Colombier 
307dd7cddfSDavid du Colombier int
geninitdraw(char * devdir,void (* error)(Display *,char *),char * fontname,char * label,char * windir,int ref)317dd7cddfSDavid du Colombier geninitdraw(char *devdir, void(*error)(Display*, char*), char *fontname, char *label, char *windir, int ref)
327dd7cddfSDavid du Colombier {
337dd7cddfSDavid du Colombier 	int fd, n;
347dd7cddfSDavid du Colombier 	Subfont *df;
357dd7cddfSDavid du Colombier 	char buf[128];
367dd7cddfSDavid du Colombier 
377dd7cddfSDavid du Colombier 	display = initdisplay(devdir, windir, error);
387dd7cddfSDavid du Colombier 	if(display == nil)
397dd7cddfSDavid du Colombier 		return -1;
407dd7cddfSDavid du Colombier 
417dd7cddfSDavid du Colombier 	/*
427dd7cddfSDavid du Colombier 	 * Set up default font
437dd7cddfSDavid du Colombier 	 */
447dd7cddfSDavid du Colombier 	df = getdefont(display);
457dd7cddfSDavid du Colombier 	display->defaultsubfont = df;
467dd7cddfSDavid du Colombier 	if(df == nil){
479a747e4fSDavid du Colombier 		fprint(2, "imageinit: can't open default subfont: %r\n");
487dd7cddfSDavid du Colombier     Error:
497dd7cddfSDavid du Colombier 		closedisplay(display);
507dd7cddfSDavid du Colombier 		display = nil;
517dd7cddfSDavid du Colombier 		return -1;
527dd7cddfSDavid du Colombier 	}
537dd7cddfSDavid du Colombier 	if(fontname == nil){
547dd7cddfSDavid du Colombier 		fd = open("/env/font", OREAD);
557dd7cddfSDavid du Colombier 		if(fd >= 0){
567dd7cddfSDavid du Colombier 			n = read(fd, buf, sizeof(buf));
577dd7cddfSDavid du Colombier 			if(n>0 && n<sizeof buf-1){
587dd7cddfSDavid du Colombier 				buf[n] = 0;
597dd7cddfSDavid du Colombier 				fontname = buf;
607dd7cddfSDavid du Colombier 			}
617dd7cddfSDavid du Colombier 			close(fd);
627dd7cddfSDavid du Colombier 		}
637dd7cddfSDavid du Colombier 	}
647dd7cddfSDavid du Colombier 	/*
657dd7cddfSDavid du Colombier 	 * Build fonts with caches==depth of screen, for speed.
667dd7cddfSDavid du Colombier 	 * If conversion were faster, we'd use 0 and save memory.
677dd7cddfSDavid du Colombier 	 */
687dd7cddfSDavid du Colombier 	if(fontname == nil){
697dd7cddfSDavid du Colombier 		snprint(buf, sizeof buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent,
707dd7cddfSDavid du Colombier 			df->n-1, deffontname);
717dd7cddfSDavid du Colombier //BUG: Need something better for this	installsubfont("*default*", df);
727dd7cddfSDavid du Colombier 		font = buildfont(display, buf, deffontname);
737dd7cddfSDavid du Colombier 		if(font == nil){
749a747e4fSDavid du Colombier 			fprint(2, "imageinit: can't open default font: %r\n");
757dd7cddfSDavid du Colombier 			goto Error;
767dd7cddfSDavid du Colombier 		}
777dd7cddfSDavid du Colombier 	}else{
787dd7cddfSDavid du Colombier 		font = openfont(display, fontname);	/* BUG: grey fonts */
797dd7cddfSDavid du Colombier 		if(font == nil){
809a747e4fSDavid du Colombier 			fprint(2, "imageinit: can't open font %s: %r\n", fontname);
817dd7cddfSDavid du Colombier 			goto Error;
827dd7cddfSDavid du Colombier 		}
837dd7cddfSDavid du Colombier 	}
847dd7cddfSDavid du Colombier 	display->defaultfont = font;
857dd7cddfSDavid du Colombier 
867dd7cddfSDavid du Colombier 	/*
877dd7cddfSDavid du Colombier 	 * Write label; ignore errors (we might not be running under rio)
887dd7cddfSDavid du Colombier 	 */
897dd7cddfSDavid du Colombier 	if(label){
907dd7cddfSDavid du Colombier 		snprint(buf, sizeof buf, "%s/label", display->windir);
917dd7cddfSDavid du Colombier 		fd = open(buf, OREAD);
927dd7cddfSDavid du Colombier 		if(fd >= 0){
937dd7cddfSDavid du Colombier 			read(fd, display->oldlabel, (sizeof display->oldlabel)-1);
947dd7cddfSDavid du Colombier 			close(fd);
957dd7cddfSDavid du Colombier 			fd = create(buf, OWRITE, 0666);
967dd7cddfSDavid du Colombier 			if(fd >= 0){
977dd7cddfSDavid du Colombier 				write(fd, label, strlen(label));
987dd7cddfSDavid du Colombier 				close(fd);
997dd7cddfSDavid du Colombier 			}
1007dd7cddfSDavid du Colombier 		}
1017dd7cddfSDavid du Colombier 	}
1027dd7cddfSDavid du Colombier 
1039a747e4fSDavid du Colombier 	snprint(buf, sizeof buf, "%s/winname", display->windir);
1049a747e4fSDavid du Colombier 	if(gengetwindow(display, buf, &screen, &_screen, ref) < 0)
1057dd7cddfSDavid du Colombier 		goto Error;
1067dd7cddfSDavid du Colombier 
1077dd7cddfSDavid du Colombier 	atexit(drawshutdown);
1087dd7cddfSDavid du Colombier 
1097dd7cddfSDavid du Colombier 	return 1;
1107dd7cddfSDavid du Colombier }
1117dd7cddfSDavid du Colombier 
1127dd7cddfSDavid du Colombier int
initdraw(void (* error)(Display *,char *),char * fontname,char * label)1137dd7cddfSDavid du Colombier initdraw(void(*error)(Display*, char*), char *fontname , char *label)
1147dd7cddfSDavid du Colombier {
1157dd7cddfSDavid du Colombier 	char *dev = "/dev";
1167dd7cddfSDavid du Colombier 
1179a747e4fSDavid du Colombier 	if(access("/dev/draw/new", AEXIST)<0 && bind("#i", "/dev", MAFTER)<0){
11872061b92SDavid du Colombier 		fprint(2, "imageinit: can't bind /dev/draw: %r\n");
1197dd7cddfSDavid du Colombier 		return -1;
1207dd7cddfSDavid du Colombier 	}
1217dd7cddfSDavid du Colombier 	return geninitdraw(dev, error, fontname, label, dev, Refnone);
1227dd7cddfSDavid du Colombier }
1237dd7cddfSDavid du Colombier 
1247dd7cddfSDavid du Colombier /*
1257dd7cddfSDavid du Colombier  * Attach, or possibly reattach, to window.
1267dd7cddfSDavid du Colombier  * If reattaching, maintain value of screen pointer.
1277dd7cddfSDavid du Colombier  */
1287dd7cddfSDavid du Colombier int
gengetwindow(Display * d,char * winname,Image ** winp,Screen ** scrp,int ref)12980ee5cbfSDavid du Colombier gengetwindow(Display *d, char *winname, Image **winp, Screen **scrp, int ref)
1307dd7cddfSDavid du Colombier {
1317dd7cddfSDavid du Colombier 	int n, fd;
13280ee5cbfSDavid du Colombier 	char buf[64+1];
1337dd7cddfSDavid du Colombier 	Image *image;
1349a747e4fSDavid du Colombier 	Rectangle r;
1357dd7cddfSDavid du Colombier 
13680ee5cbfSDavid du Colombier 	fd = open(winname, OREAD);
13780ee5cbfSDavid du Colombier 	if(fd<0 || (n=read(fd, buf, sizeof buf-1))<=0){
1389a747e4fSDavid du Colombier 		if((image=d->image) == nil){
1399a747e4fSDavid du Colombier 			fprint(2, "gengetwindow: %r\n");
1409a747e4fSDavid du Colombier 			*winp = nil;
1419a747e4fSDavid du Colombier 			d->screenimage = nil;
1429a747e4fSDavid du Colombier 			return -1;
1437dd7cddfSDavid du Colombier 		}
1449a747e4fSDavid du Colombier 		strcpy(buf, "noborder");
1459a747e4fSDavid du Colombier 	}else{
1467dd7cddfSDavid du Colombier 		close(fd);
14780ee5cbfSDavid du Colombier 		buf[n] = '\0';
14880ee5cbfSDavid du Colombier 		if(*winp != nil){
14980ee5cbfSDavid du Colombier 			_freeimage1(*winp);
15080ee5cbfSDavid du Colombier 			freeimage((*scrp)->image);
15180ee5cbfSDavid du Colombier 			freescreen(*scrp);
15280ee5cbfSDavid du Colombier 			*scrp = nil;
1537dd7cddfSDavid du Colombier 		}
15480ee5cbfSDavid du Colombier 		image = namedimage(d, buf);
1557dd7cddfSDavid du Colombier 		if(image == 0){
1569a747e4fSDavid du Colombier 			fprint(2, "namedimage %s failed: %r\n", buf);
15780ee5cbfSDavid du Colombier 			*winp = nil;
1589a747e4fSDavid du Colombier 			d->screenimage = nil;
1597dd7cddfSDavid du Colombier 			return -1;
1607dd7cddfSDavid du Colombier 		}
1617dd7cddfSDavid du Colombier 		assert(image->chan != 0);
1629a747e4fSDavid du Colombier 	}
1637dd7cddfSDavid du Colombier 
1649a747e4fSDavid du Colombier 	d->screenimage = image;
16580ee5cbfSDavid du Colombier 	*scrp = allocscreen(image, d->white, 0);
16680ee5cbfSDavid du Colombier 	if(*scrp == nil){
1679a747e4fSDavid du Colombier 		freeimage(d->screenimage);
16880ee5cbfSDavid du Colombier 		*winp = nil;
1699a747e4fSDavid du Colombier 		d->screenimage = nil;
1707dd7cddfSDavid du Colombier 		return -1;
1717dd7cddfSDavid du Colombier 	}
1727dd7cddfSDavid du Colombier 
1739a747e4fSDavid du Colombier 	r = image->r;
1749a747e4fSDavid du Colombier 	if(strncmp(buf, "noborder", 8) != 0)
1759a747e4fSDavid du Colombier 		r = insetrect(image->r, Borderwidth);
1769a747e4fSDavid du Colombier 	*winp = _allocwindow(*winp, *scrp, r, ref, DWhite);
1779a747e4fSDavid du Colombier 	if(*winp == nil){
1789a747e4fSDavid du Colombier 		freescreen(*scrp);
1799a747e4fSDavid du Colombier 		*scrp = nil;
1809a747e4fSDavid du Colombier 		freeimage(image);
1819a747e4fSDavid du Colombier 		d->screenimage = nil;
1827dd7cddfSDavid du Colombier 		return -1;
1839a747e4fSDavid du Colombier 	}
1849a747e4fSDavid du Colombier 	d->screenimage = *winp;
18580ee5cbfSDavid du Colombier 	assert((*winp)->chan != 0);
1867dd7cddfSDavid du Colombier 	return 1;
1877dd7cddfSDavid du Colombier }
1887dd7cddfSDavid du Colombier 
18980ee5cbfSDavid du Colombier int
getwindow(Display * d,int ref)19080ee5cbfSDavid du Colombier getwindow(Display *d, int ref)
19180ee5cbfSDavid du Colombier {
19280ee5cbfSDavid du Colombier 	char winname[128];
19380ee5cbfSDavid du Colombier 
19480ee5cbfSDavid du Colombier 	snprint(winname, sizeof winname, "%s/winname", d->windir);
19580ee5cbfSDavid du Colombier 	return gengetwindow(d, winname, &screen, &_screen, ref);
19680ee5cbfSDavid du Colombier }
19780ee5cbfSDavid du Colombier 
1987dd7cddfSDavid du Colombier #define	NINFO	12*12
1997dd7cddfSDavid du Colombier 
2007dd7cddfSDavid du Colombier Display*
initdisplay(char * dev,char * win,void (* error)(Display *,char *))2017dd7cddfSDavid du Colombier initdisplay(char *dev, char *win, void(*error)(Display*, char*))
2027dd7cddfSDavid du Colombier {
203*5d9de2d3SDavid du Colombier 	char buf[128], info[NINFO+1], *t, isnew;
2049a747e4fSDavid du Colombier 	int n, datafd, ctlfd, reffd;
2057dd7cddfSDavid du Colombier 	Display *disp;
2069a747e4fSDavid du Colombier 	Dir *dir;
2077dd7cddfSDavid du Colombier 	Image *image;
2087dd7cddfSDavid du Colombier 
2099a747e4fSDavid du Colombier 	fmtinstall('P', Pfmt);
2109a747e4fSDavid du Colombier 	fmtinstall('R', Rfmt);
2117dd7cddfSDavid du Colombier 	if(dev == 0)
2127dd7cddfSDavid du Colombier 		dev = "/dev";
2137dd7cddfSDavid du Colombier 	if(win == 0)
2147dd7cddfSDavid du Colombier 		win = "/dev";
2157dd7cddfSDavid du Colombier 	if(strlen(dev)>sizeof buf-25 || strlen(win)>sizeof buf-25){
2167dd7cddfSDavid du Colombier 		werrstr("initdisplay: directory name too long");
2177dd7cddfSDavid du Colombier 		return nil;
2187dd7cddfSDavid du Colombier 	}
2197dd7cddfSDavid du Colombier 	t = strdup(win);
2207dd7cddfSDavid du Colombier 	if(t == nil)
2217dd7cddfSDavid du Colombier 		return nil;
2227dd7cddfSDavid du Colombier 
2237dd7cddfSDavid du Colombier 	sprint(buf, "%s/draw/new", dev);
2247dd7cddfSDavid du Colombier 	ctlfd = open(buf, ORDWR|OCEXEC);
2257dd7cddfSDavid du Colombier 	if(ctlfd < 0){
2267dd7cddfSDavid du Colombier 		if(bind("#i", dev, MAFTER) < 0){
2277dd7cddfSDavid du Colombier     Error1:
2287dd7cddfSDavid du Colombier 			free(t);
2297dd7cddfSDavid du Colombier 			werrstr("initdisplay: %s: %r", buf);
2307dd7cddfSDavid du Colombier 			return 0;
2317dd7cddfSDavid du Colombier 		}
2327dd7cddfSDavid du Colombier 		ctlfd = open(buf, ORDWR|OCEXEC);
2337dd7cddfSDavid du Colombier 	}
2347dd7cddfSDavid du Colombier 	if(ctlfd < 0)
2357dd7cddfSDavid du Colombier 		goto Error1;
2369a747e4fSDavid du Colombier 	if((n=read(ctlfd, info, sizeof info)) < 12){
2377dd7cddfSDavid du Colombier     Error2:
2387dd7cddfSDavid du Colombier 		close(ctlfd);
2397dd7cddfSDavid du Colombier 		goto Error1;
2407dd7cddfSDavid du Colombier 	}
2419a747e4fSDavid du Colombier 	if(n==NINFO+1)
2429a747e4fSDavid du Colombier 		n = NINFO;
243*5d9de2d3SDavid du Colombier 	info[n] = '\0';
2449a747e4fSDavid du Colombier 	isnew = 0;
2459a747e4fSDavid du Colombier 	if(n < NINFO)	/* this will do for now, we need something better here */
2469a747e4fSDavid du Colombier 		isnew = 1;
2477dd7cddfSDavid du Colombier 	sprint(buf, "%s/draw/%d/data", dev, atoi(info+0*12));
2487dd7cddfSDavid du Colombier 	datafd = open(buf, ORDWR|OCEXEC);
2497dd7cddfSDavid du Colombier 	if(datafd < 0)
2507dd7cddfSDavid du Colombier 		goto Error2;
2517dd7cddfSDavid du Colombier 	sprint(buf, "%s/draw/%d/refresh", dev, atoi(info+0*12));
2527dd7cddfSDavid du Colombier 	reffd = open(buf, OREAD|OCEXEC);
2537dd7cddfSDavid du Colombier 	if(reffd < 0){
2547dd7cddfSDavid du Colombier     Error3:
2557dd7cddfSDavid du Colombier 		close(datafd);
2567dd7cddfSDavid du Colombier 		goto Error2;
2577dd7cddfSDavid du Colombier 	}
2589a747e4fSDavid du Colombier 	disp = mallocz(sizeof(Display), 1);
2597dd7cddfSDavid du Colombier 	if(disp == 0){
2607dd7cddfSDavid du Colombier     Error4:
2617dd7cddfSDavid du Colombier 		close(reffd);
2627dd7cddfSDavid du Colombier 		goto Error3;
2637dd7cddfSDavid du Colombier 	}
2649a747e4fSDavid du Colombier 	image = nil;
2659a747e4fSDavid du Colombier 	if(0){
2667dd7cddfSDavid du Colombier     Error5:
2679a747e4fSDavid du Colombier 		free(image);
2687dd7cddfSDavid du Colombier 		free(disp);
2697dd7cddfSDavid du Colombier 		goto Error4;
2707dd7cddfSDavid du Colombier 	}
2719a747e4fSDavid du Colombier 	if(n >= NINFO){
2729a747e4fSDavid du Colombier 		image = mallocz(sizeof(Image), 1);
2739a747e4fSDavid du Colombier 		if(image == nil)
2749a747e4fSDavid du Colombier 			goto Error5;
2757dd7cddfSDavid du Colombier 		image->display = disp;
2767dd7cddfSDavid du Colombier 		image->id = 0;
2779a747e4fSDavid du Colombier 		image->chan = strtochan(info+2*12);
2789a747e4fSDavid du Colombier 		image->depth = chantodepth(image->chan);
2797dd7cddfSDavid du Colombier 		image->repl = atoi(info+3*12);
2807dd7cddfSDavid du Colombier 		image->r.min.x = atoi(info+4*12);
2817dd7cddfSDavid du Colombier 		image->r.min.y = atoi(info+5*12);
2827dd7cddfSDavid du Colombier 		image->r.max.x = atoi(info+6*12);
2837dd7cddfSDavid du Colombier 		image->r.max.y = atoi(info+7*12);
2847dd7cddfSDavid du Colombier 		image->clipr.min.x = atoi(info+8*12);
2857dd7cddfSDavid du Colombier 		image->clipr.min.y = atoi(info+9*12);
2867dd7cddfSDavid du Colombier 		image->clipr.max.x = atoi(info+10*12);
2877dd7cddfSDavid du Colombier 		image->clipr.max.y = atoi(info+11*12);
2889a747e4fSDavid du Colombier 	}
2899a747e4fSDavid du Colombier 
2909a747e4fSDavid du Colombier 	disp->_isnewdisplay = isnew;
2919a747e4fSDavid du Colombier 	disp->bufsize = iounit(datafd);
2929a747e4fSDavid du Colombier 	if(disp->bufsize <= 0)
2939a747e4fSDavid du Colombier 		disp->bufsize = 8000;
2949a747e4fSDavid du Colombier 	if(disp->bufsize < 512){
2959a747e4fSDavid du Colombier 		werrstr("iounit %d too small", disp->bufsize);
2969a747e4fSDavid du Colombier 		goto Error5;
2979a747e4fSDavid du Colombier 	}
2989a747e4fSDavid du Colombier 	disp->buf = malloc(disp->bufsize+5);	/* +5 for flush message */
2999a747e4fSDavid du Colombier 	if(disp->buf == nil)
3009a747e4fSDavid du Colombier 		goto Error5;
3019a747e4fSDavid du Colombier 
3029a747e4fSDavid du Colombier 	disp->image = image;
3037dd7cddfSDavid du Colombier 	disp->dirno = atoi(info+0*12);
3047dd7cddfSDavid du Colombier 	disp->fd = datafd;
3057dd7cddfSDavid du Colombier 	disp->ctlfd = ctlfd;
3067dd7cddfSDavid du Colombier 	disp->reffd = reffd;
3077dd7cddfSDavid du Colombier 	disp->bufp = disp->buf;
3087dd7cddfSDavid du Colombier 	disp->error = error;
3097dd7cddfSDavid du Colombier 	disp->windir = t;
3107dd7cddfSDavid du Colombier 	disp->devdir = strdup(dev);
3117dd7cddfSDavid du Colombier 	qlock(&disp->qlock);
3127dd7cddfSDavid du Colombier 	disp->white = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DWhite);
3137dd7cddfSDavid du Colombier 	disp->black = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DBlack);
3147dd7cddfSDavid du Colombier 	if(disp->white == nil || disp->black == nil){
3157dd7cddfSDavid du Colombier 		free(disp->devdir);
3167dd7cddfSDavid du Colombier 		free(disp->white);
3177dd7cddfSDavid du Colombier 		free(disp->black);
3187dd7cddfSDavid du Colombier 		goto Error5;
3197dd7cddfSDavid du Colombier 	}
3207dd7cddfSDavid du Colombier 	disp->opaque = disp->white;
3217dd7cddfSDavid du Colombier 	disp->transparent = disp->black;
3229a747e4fSDavid du Colombier 	dir = dirfstat(ctlfd);
3239a747e4fSDavid du Colombier 	if(dir!=nil && dir->type=='i'){
3247dd7cddfSDavid du Colombier 		disp->local = 1;
3259a747e4fSDavid du Colombier 		disp->dataqid = dir->qid.path;
3267dd7cddfSDavid du Colombier 	}
3279a747e4fSDavid du Colombier 	if(dir!=nil && dir->qid.vers==1)	/* other way to tell */
3289a747e4fSDavid du Colombier 		disp->_isnewdisplay = 1;
3299a747e4fSDavid du Colombier 	free(dir);
3307dd7cddfSDavid du Colombier 
3317dd7cddfSDavid du Colombier 	return disp;
3327dd7cddfSDavid du Colombier }
3337dd7cddfSDavid du Colombier 
3347dd7cddfSDavid du Colombier /*
3357dd7cddfSDavid du Colombier  * Call with d unlocked.
3367dd7cddfSDavid du Colombier  * Note that disp->defaultfont and defaultsubfont are not freed here.
3377dd7cddfSDavid du Colombier  */
3387dd7cddfSDavid du Colombier void
closedisplay(Display * disp)3397dd7cddfSDavid du Colombier closedisplay(Display *disp)
3407dd7cddfSDavid du Colombier {
341f366f900SDavid du Colombier 	_closedisplay(disp, 0);
342f366f900SDavid du Colombier }
343f366f900SDavid du Colombier 
344f366f900SDavid du Colombier static void
_closedisplay(Display * disp,int isshutdown)345f366f900SDavid du Colombier _closedisplay(Display *disp, int isshutdown)
346f366f900SDavid du Colombier {
3477dd7cddfSDavid du Colombier 	int fd;
3487dd7cddfSDavid du Colombier 	char buf[128];
3497dd7cddfSDavid du Colombier 
3507dd7cddfSDavid du Colombier 	if(disp == nil)
3517dd7cddfSDavid du Colombier 		return;
3527dd7cddfSDavid du Colombier 	if(disp == display)
3537dd7cddfSDavid du Colombier 		display = nil;
3547dd7cddfSDavid du Colombier 	if(disp->oldlabel[0]){
3557dd7cddfSDavid du Colombier 		snprint(buf, sizeof buf, "%s/label", disp->windir);
3567dd7cddfSDavid du Colombier 		fd = open(buf, OWRITE);
3577dd7cddfSDavid du Colombier 		if(fd >= 0){
3587dd7cddfSDavid du Colombier 			write(fd, disp->oldlabel, strlen(disp->oldlabel));
3597dd7cddfSDavid du Colombier 			close(fd);
3607dd7cddfSDavid du Colombier 		}
3617dd7cddfSDavid du Colombier 	}
3627dd7cddfSDavid du Colombier 
363f366f900SDavid du Colombier 	/*
364f366f900SDavid du Colombier 	 * if we're shutting down, don't free all the resources.
365f366f900SDavid du Colombier 	 * if other procs are getting shot down by notes too,
366f366f900SDavid du Colombier 	 * one might get shot down while holding the malloc lock.
367f366f900SDavid du Colombier 	 * just let the kernel clean things up when we exit.
368f366f900SDavid du Colombier 	 */
369f366f900SDavid du Colombier 	if(isshutdown)
370f366f900SDavid du Colombier 		return;
371f366f900SDavid du Colombier 
3727dd7cddfSDavid du Colombier 	free(disp->devdir);
3737dd7cddfSDavid du Colombier 	free(disp->windir);
3747dd7cddfSDavid du Colombier 	freeimage(disp->white);
3757dd7cddfSDavid du Colombier 	freeimage(disp->black);
3767dd7cddfSDavid du Colombier 	close(disp->fd);
3777dd7cddfSDavid du Colombier 	close(disp->ctlfd);
3787dd7cddfSDavid du Colombier 	/* should cause refresh slave to shut down */
3797dd7cddfSDavid du Colombier 	close(disp->reffd);
3807dd7cddfSDavid du Colombier 	qunlock(&disp->qlock);
3817dd7cddfSDavid du Colombier 	free(disp);
3827dd7cddfSDavid du Colombier }
3837dd7cddfSDavid du Colombier 
3847dd7cddfSDavid du Colombier void
lockdisplay(Display * disp)3857dd7cddfSDavid du Colombier lockdisplay(Display *disp)
3867dd7cddfSDavid du Colombier {
3877dd7cddfSDavid du Colombier 	if(debuglockdisplay){
3887dd7cddfSDavid du Colombier 		/* avoid busy looping; it's rare we collide anyway */
3897dd7cddfSDavid du Colombier 		while(!canqlock(&disp->qlock)){
3909a747e4fSDavid du Colombier 			fprint(1, "proc %d waiting for display lock...\n", getpid());
3917dd7cddfSDavid du Colombier 			sleep(1000);
3927dd7cddfSDavid du Colombier 		}
3937dd7cddfSDavid du Colombier 	}else
3947dd7cddfSDavid du Colombier 		qlock(&disp->qlock);
3957dd7cddfSDavid du Colombier }
3967dd7cddfSDavid du Colombier 
3977dd7cddfSDavid du Colombier void
unlockdisplay(Display * disp)3987dd7cddfSDavid du Colombier unlockdisplay(Display *disp)
3997dd7cddfSDavid du Colombier {
4007dd7cddfSDavid du Colombier 	qunlock(&disp->qlock);
4017dd7cddfSDavid du Colombier }
4027dd7cddfSDavid du Colombier 
4037dd7cddfSDavid du Colombier void
drawerror(Display * d,char * s)4047dd7cddfSDavid du Colombier drawerror(Display *d, char *s)
4057dd7cddfSDavid du Colombier {
4069a747e4fSDavid du Colombier 	char err[ERRMAX];
4077dd7cddfSDavid du Colombier 
4088d37e088SDavid du Colombier 	if(d && d->error)
4097dd7cddfSDavid du Colombier 		d->error(d, s);
4107dd7cddfSDavid du Colombier 	else{
4119a747e4fSDavid du Colombier 		errstr(err, sizeof err);
4129a747e4fSDavid du Colombier 		fprint(2, "draw: %s: %s\n", s, err);
4137dd7cddfSDavid du Colombier 		exits(s);
4147dd7cddfSDavid du Colombier 	}
4157dd7cddfSDavid du Colombier }
4167dd7cddfSDavid du Colombier 
4177dd7cddfSDavid du Colombier static
4187dd7cddfSDavid du Colombier int
doflush(Display * d)4197dd7cddfSDavid du Colombier doflush(Display *d)
4207dd7cddfSDavid du Colombier {
421711d1557SDavid du Colombier 	int n, nn;
4227dd7cddfSDavid du Colombier 
4237dd7cddfSDavid du Colombier 	n = d->bufp-d->buf;
4247dd7cddfSDavid du Colombier 	if(n <= 0)
4257dd7cddfSDavid du Colombier 		return 1;
4267dd7cddfSDavid du Colombier 
427711d1557SDavid du Colombier 	if((nn=write(d->fd, d->buf, n)) != n){
42859cc4ca5SDavid du Colombier 		if(_drawdebug)
429711d1557SDavid du Colombier 			fprint(2, "flushimage fail: d=%p: n=%d nn=%d %r\n", d, n, nn); /**/
4307dd7cddfSDavid du Colombier 		d->bufp = d->buf;	/* might as well; chance of continuing */
4317dd7cddfSDavid du Colombier 		return -1;
4327dd7cddfSDavid du Colombier 	}
4337dd7cddfSDavid du Colombier 	d->bufp = d->buf;
4347dd7cddfSDavid du Colombier 	return 1;
4357dd7cddfSDavid du Colombier }
4367dd7cddfSDavid du Colombier 
4377dd7cddfSDavid du Colombier int
flushimage(Display * d,int visible)4387dd7cddfSDavid du Colombier flushimage(Display *d, int visible)
4397dd7cddfSDavid du Colombier {
440108f07eeSDavid du Colombier 	if(d == nil)
441108f07eeSDavid du Colombier 		return 0;
4429a747e4fSDavid du Colombier 	if(visible){
4439a747e4fSDavid du Colombier 		*d->bufp++ = 'v';	/* five bytes always reserved for this */
4449a747e4fSDavid du Colombier 		if(d->_isnewdisplay){
4459a747e4fSDavid du Colombier 			BPLONG(d->bufp, d->screenimage->id);
4469a747e4fSDavid du Colombier 			d->bufp += 4;
4479a747e4fSDavid du Colombier 		}
4489a747e4fSDavid du Colombier 	}
4497dd7cddfSDavid du Colombier 	return doflush(d);
4507dd7cddfSDavid du Colombier }
4517dd7cddfSDavid du Colombier 
4527dd7cddfSDavid du Colombier uchar*
bufimage(Display * d,int n)4537dd7cddfSDavid du Colombier bufimage(Display *d, int n)
4547dd7cddfSDavid du Colombier {
4557dd7cddfSDavid du Colombier 	uchar *p;
4567dd7cddfSDavid du Colombier 
4579a747e4fSDavid du Colombier 	if(n<0 || n>d->bufsize){
4587dd7cddfSDavid du Colombier 		werrstr("bad count in bufimage");
4597dd7cddfSDavid du Colombier 		return 0;
4607dd7cddfSDavid du Colombier 	}
4619a747e4fSDavid du Colombier 	if(d->bufp+n > d->buf+d->bufsize)
4627dd7cddfSDavid du Colombier 		if(doflush(d) < 0)
4637dd7cddfSDavid du Colombier 			return 0;
4647dd7cddfSDavid du Colombier 	p = d->bufp;
4657dd7cddfSDavid du Colombier 	d->bufp += n;
4667dd7cddfSDavid du Colombier 	return p;
4677dd7cddfSDavid du Colombier }
4687dd7cddfSDavid du Colombier 
469