Commit Diff


commit - 324891a5579d6f504201a6107369c64dab245a98
commit + 74dc60da74c62e07f0d63179da9724d705794a6d
blob - 7ab9be19afcc6df0e7f807ba2dca598ffc9c2bc8
blob + 0d15c12d8d3152d9b1745bcb342fdf659b24715c
--- src/libdraw/alloc.c
+++ src/libdraw/alloc.c
@@ -132,7 +132,7 @@ namedimage(Display *d, char *name)
 	a[6+n] = 'I';
 	if(flushimage(d, 0) < 0)
 		goto Error;
-	if(_drawmsgread(d, buf, sizeof buf) < 12*12)
+	if(_displayrddraw(d, buf, sizeof buf) < 12*12)
 		goto Error;
 	buf[12*12] = '\0';
 
blob - 2f67cde88a92b539fdbf7c79bb578ead82af8653
blob + 6e4d7f5c3e5424fe8371deb521129783e2b63f19
--- src/libdraw/event.c
+++ src/libdraw/event.c
@@ -1,28 +1,12 @@
 #include <u.h>
+#include <sys/select.h>
 #include <libc.h>
 #include <draw.h>
 #include <cursor.h>
 #include <event.h>
 
-typedef struct	Slave Slave;
-typedef struct	Ebuf Ebuf;
-
-struct Slave
-{
-	int	pid;
-	Ebuf	*head;		/* ueue of messages for this descriptor */
-	Ebuf	*tail;
-	int	(*fn)(int, Event*, uchar*, int);
-};
 
-struct Ebuf
-{
-	Ebuf	*next;
-	int	n;		/* number of bytes in buf */
-	uchar	buf[EMAXMSG];
-};
 
-static	Slave	eslave[MAXSLAVE];
 static	int	Skeyboard = -1;
 static	int	Smouse = -1;
 static	int	Stimer = -1;
blob - 0f8cc76625af91be62d4b0a864f20ecba755d561
blob + bbce668b684ca0c7ad1db3dda92896cbdd09e9fd
--- src/libdraw/init.c
+++ src/libdraw/init.c
@@ -11,6 +11,7 @@ static char deffontname[] = "*default*";
 Screen	*_screen;
 
 int		debuglockdisplay = 1;
+char	*winsize;
 
 /*
 static void
@@ -27,19 +28,17 @@ drawshutdown(void)
 */
 
 int
-initdraw(void (*error)(Display*, char*), char *fontname, char *label)
+geninitdraw(char *devdir, void(*error)(Display*, char*), char *fontname, char *label, char *windir, int ref)
 {
 	Subfont *df;
 	char buf[128];
 
-	rfork(RFNOTEG);	/* x11-event.c will postnote hangup */
-	display = _initdisplay(error, label); /* sets screen too */
+	if(label == nil)
+		label = argv0;
+	display = _initdisplay(error, label);
 	if(display == nil)
 		return -1;
 
-	lockdisplay(display);
-	display->screenimage = display->image;
-
 	/*
 	 * Set up default font
 	 */
@@ -53,7 +52,7 @@ initdraw(void (*error)(Display*, char*), char *fontnam
 		return -1;
 	}
 	if(fontname == nil)
-		fontname = getenv("font");	/* leak */
+		fontname = getenv("font");
 
 	/*
 	 * Build fonts with caches==depth of screen, for speed.
@@ -62,32 +61,28 @@ initdraw(void (*error)(Display*, char*), char *fontnam
 	if(fontname == nil){
 		snprint(buf, sizeof buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent,
 			df->n-1, deffontname);
-/*BUG: Need something better for this	installsubfont("*default*", df); */
+//BUG: Need something better for this	installsubfont("*default*", df);
 		font = buildfont(display, buf, deffontname);
 		if(font == nil){
-			fprint(2, "initdraw: can't open default font: %r\n");
+			fprint(2, "imageinit: can't open default font: %r\n");
 			goto Error;
 		}
 	}else{
 		font = openfont(display, fontname);	/* BUG: grey fonts */
 		if(font == nil){
-			fprint(2, "initdraw: can't open font %s: %r\n", fontname);
+			fprint(2, "imageinit: can't open font %s: %r\n", fontname);
 			goto Error;
 		}
 	}
 	display->defaultfont = font;
 
-	display->white = allocimage(display, Rect(0,0,1,1), GREY1, 1, DWhite);
-	display->black = allocimage(display, Rect(0,0,1,1), GREY1, 1, DBlack);
-	if(display->white == nil || display->black == nil){
-		fprint(2, "initdraw: can't allocate white and black");
-		goto Error;
-	}
-	display->opaque = display->white;
-	display->transparent = display->black;
-
 	_screen = allocscreen(display->image, display->white, 0);
+	display->screenimage = display->image;	/* _allocwindow wants screenimage->chan */
 	screen = _allocwindow(nil, _screen, display->image->r, Refnone, DWhite);
+	if(screen == nil){
+		fprint(2, "_allocwindow: %r\n");
+		goto Error;
+	}
 	display->screenimage = screen;
 	draw(screen, screen->r, display->white, nil, ZP);
 	flushimage(display, 1);
@@ -100,8 +95,167 @@ initdraw(void (*error)(Display*, char*), char *fontnam
 	 * atexit(drawshutdown);
 	 */
 	return 1;
+}
+
+int
+initdraw(void (*error)(Display*, char*), char *fontname, char *label)
+{
+	return geninitdraw("/dev", error, fontname, label, "/dev", Refnone);
+}
+
+extern int _freeimage1(Image*);
+
+static Image*
+getimage0(Display *d, Image *image)
+{
+	char info[12*12+1];
+	uchar *a;
+	int n;
+
+	/*
+	 * If there's an old screen, it has id 0.  The 'J' request below
+	 * will try to install the new screen as id 0, so the old one 
+	 * must be freed first.
+	 */
+	if(image){
+		_freeimage1(image);
+		memset(image, 0, sizeof(Image));
+	}
+
+	a = bufimage(d, 2);
+	a[0] = 'J';
+	a[1] = 'I';
+	if(flushimage(d, 0) < 0){
+		fprint(2, "cannot read screen info: %r\n");
+		return nil;
+	}
+
+	n = _displayrddraw(d, info, sizeof info);
+	if(n != 12*12){
+		fprint(2, "short screen info\n");
+		return nil;
+	}
+
+	if(image == nil){
+		image = mallocz(sizeof(Image), 1);
+		if(image == nil){
+			fprint(2, "cannot allocate image: %r\n");
+			return nil;
+		}
+	}
+
+	image->display = d;
+	image->id = 0;
+	image->chan = strtochan(info+2*12);
+	image->depth = chantodepth(image->chan);
+	image->repl = atoi(info+3*12);
+	image->r.min.x = atoi(info+4*12);
+	image->r.min.y = atoi(info+5*12);
+	image->r.max.x = atoi(info+6*12);
+	image->r.max.y = atoi(info+7*12);
+	image->clipr.min.x = atoi(info+8*12);
+	image->clipr.min.y = atoi(info+9*12);
+	image->clipr.max.x = atoi(info+10*12);
+	image->clipr.max.y = atoi(info+11*12);
+	return image;
+}
+
+/*
+ * Attach, or possibly reattach, to window.
+ * If reattaching, maintain value of screen pointer.
+ */
+int
+getwindow(Display *d, int ref)
+{
+	Image *i, *oi;
+	
+	/* XXX check for destroyed? */
+	
+	/*
+	 * Libdraw promises not to change the value of "screen",
+	 * so we have to reuse the image structure
+	 * memory we already have.
+	 */
+	oi = d->image;
+	i = getimage0(d, oi);
+	if(i == nil)
+		sysfatal("getwindow failed");
+	d->image = i;
+	/* fprint(2, "getwindow %p -> %p\n", oi, i); */
+
+	freescreen(_screen);
+	_screen = allocscreen(i, d->white, 0);
+	_freeimage1(screen);
+	screen = _allocwindow(screen, _screen, i->r, ref, DWhite);
+	d->screenimage = screen;
+	return 0;
 }
 
+Display*
+_initdisplay(void (*error)(Display*, char*), char *label)
+{
+	Display *disp;
+	Image *image;
+
+	fmtinstall('P', Pfmt);
+	fmtinstall('R', Rfmt);
+
+	disp = mallocz(sizeof(Display), 1);
+	if(disp == nil){
+    Error1:
+		return nil;
+	}
+	disp->srvfd = -1;
+	image = nil;
+	if(0){
+    Error2:
+		free(image);
+		free(disp);
+		goto Error1;
+	}
+	disp->bufsize = 65500;
+	disp->buf = malloc(disp->bufsize+5);	/* +5 for flush message */
+	disp->bufp = disp->buf;
+	disp->error = error;
+	qlock(&disp->qlock);
+
+	if(disp->buf == nil)
+		goto Error2;
+	if(0){
+    Error3:
+		free(disp->buf);
+		goto Error2;
+	}
+	
+	if(_displaymux(disp) < 0
+	|| _displayconnect(disp) < 0
+	|| _displayinit(disp, label, winsize) < 0)
+		goto Error3;
+	if(0){
+    Error4:
+		close(disp->srvfd);
+		goto Error3;
+	}
+
+	image = getimage0(disp, nil);
+	if(image == nil)
+		goto Error4;
+	
+	disp->image = image;
+	disp->white = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DWhite);
+	disp->black = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DBlack);
+	if(disp->white == nil || disp->black == nil){
+		free(disp->white);
+		free(disp->black);
+		goto Error4;
+	}
+	
+	disp->opaque = disp->white;
+	disp->transparent = disp->black;
+
+	return disp;
+}
+
 /*
  * Call with d unlocked.
  * Note that disp->defaultfont and defaultsubfont are not freed here.
@@ -131,6 +285,8 @@ closedisplay(Display *disp)
 		freeimage(disp->white);
 	if(disp->black)
 		freeimage(disp->black);
+	if(disp->srvfd >= 0)
+		close(disp->srvfd);
 	free(disp);
 }
 
@@ -177,7 +333,7 @@ doflush(Display *d)
 	if(n <= 0)
 		return 1;
 
-	if(_drawmsgwrite(d, d->buf, n) != n){
+	if(_displaywrdraw(d, d->buf, n) != n){
 		if(_drawdebug)
 			fprint(2, "flushimage fail: d=%p: %r\n", d); /**/
 		d->bufp = d->buf;	/* might as well; chance of continuing */
blob - 0a8ec010eac632e383c93e8fd20ed0b99681a5ab
blob + 755ffbd327361a61847c9dbeb9f40b5c856af88b
--- src/libdraw/keyboard.c
+++ src/libdraw/keyboard.c
@@ -4,25 +4,18 @@
 #include <thread.h>
 #include <keyboard.h>
 
-
 void
 closekeyboard(Keyboardctl *kc)
 {
+	Rune r;
+
 	if(kc == nil)
 		return;
 
-	postnote(PNPROC, kc->pid, "kill");
+/*	postnote(PNPROC, kc->pid, "kill"); */
 
-#ifdef BUG
-	/* Drain the channel */
-	while(?kc->c)
-		<-kc->c;
-#endif
-
-	close(kc->ctlfd);
-	close(kc->consfd);
-	free(kc->file);
-	free(kc->c);
+	do; while(nbrecv(kc->c, &r) > 0);
+	chanfree(kc->c);
 	free(kc);
 }
 
@@ -30,29 +23,15 @@ static
 void
 _ioproc(void *arg)
 {
-	int m, n;
-	char buf[20];
 	Rune r;
 	Keyboardctl *kc;
-
+	
 	kc = arg;
 	threadsetname("kbdproc");
-	kc->pid = getpid();
-	n = 0;
 	for(;;){
-		while(n>0 && fullrune(buf, n)){
-			m = chartorune(&r, buf);
-			n -= m;
-			memmove(buf, buf+m, n);
-			send(kc->c, &r);
-		}
-		m = read(kc->consfd, buf+n, sizeof buf-n);
-		if(m <= 0){
-			yield();	/* if error is due to exiting, we'll exit here */
-			fprint(2, "keyboard read error: %r\n");
-			threadexits("error");
-		}
-		n += m;
+		if(_displayrdkbd(display, &r) < 0)
+			threadexits("read error");
+		send(kc->c, &r);
 	}
 }
 
@@ -60,44 +39,14 @@ Keyboardctl*
 initkeyboard(char *file)
 {
 	Keyboardctl *kc;
-	char *t;
 
 	kc = mallocz(sizeof(Keyboardctl), 1);
 	if(kc == nil)
 		return nil;
-	if(file == nil)
-		file = "/dev/cons";
-	kc->file = strdup(file);
-	kc->consfd = open(file, ORDWR|OCEXEC);
-	t = malloc(strlen(file)+16);
-	if(kc->consfd<0 || t==nil){
-Error1:
-		free(kc);
-		return nil;
-	}
-	sprint(t, "%sctl", file);
-	kc->ctlfd = open(t, OWRITE|OCEXEC);
-	if(kc->ctlfd < 0){
-		fprint(2, "initkeyboard: can't open %s: %r\n", t);
-Error2:
-		close(kc->consfd);
-		free(t);
-		goto Error1;
-	}
-	if(ctlkeyboard(kc, "rawon") < 0){
-		fprint(2, "initkeyboard: can't turn on raw mode on %s: %r\n", t);
-		close(kc->ctlfd);
-		goto Error2;
-	}
-	free(t);
+	USED(file);
 	kc->c = chancreate(sizeof(Rune), 20);
 	chansetname(kc->c, "kbdc");
-	proccreate(_ioproc, kc, 4096);
+	proccreate(_ioproc, kc, 32*1024);
 	return kc;
 }
 
-int
-ctlkeyboard(Keyboardctl *kc, char *m)
-{
-	return write(kc->ctlfd, m, strlen(m));
-}
blob - b6ad61a73511c09d9c969629c292374b752e28bf (mode 644)
blob + /dev/null
--- src/libdraw/md-alloc.c
+++ /dev/null
@@ -1,204 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-#define poolalloc(a, b) malloc(b)
-#define poolfree(a, b) free(b)
-
-void
-memimagemove(void *from, void *to)
-{
-	Memdata *md;
-
-	md = *(Memdata**)to;
-	if(md->base != from){
-		print("compacted data not right: #%p\n", md->base);
-		abort();
-	}
-	md->base = to;
-
-	/* if allocmemimage changes this must change too */
-	md->bdata = (uchar*)md->base+sizeof(Memdata*)+sizeof(ulong);
-}
-
-Memimage*
-allocmemimaged(Rectangle r, u32int chan, Memdata *md, void *X)
-{
-	int d;
-	u32int l;
-	Memimage *i;
-
-	if(Dx(r) <= 0 || Dy(r) <= 0){
-		werrstr("bad rectangle %R", r);
-		return nil;
-	}
-	if((d = chantodepth(chan)) == 0) {
-		werrstr("bad channel descriptor %.8lux", chan);
-		return nil;
-	}
-
-	l = wordsperline(r, d);
-
-	i = mallocz(sizeof(Memimage), 1);
-	if(i == nil)
-		return nil;
-
-	i->X = X;
-	i->data = md;
-	i->zero = sizeof(u32int)*l*r.min.y;
-	
-	if(r.min.x >= 0)
-		i->zero += (r.min.x*d)/8;
-	else
-		i->zero -= (-r.min.x*d+7)/8;
-	i->zero = -i->zero;
-	i->width = l;
-	i->r = r;
-	i->clipr = r;
-	i->flags = 0;
-	i->layer = nil;
-	i->cmap = memdefcmap;
-	if(memsetchan(i, chan) < 0){
-		free(i);
-		return nil;
-	}
-	return i;
-}
-
-Memimage*
-_allocmemimage(Rectangle r, u32int chan)
-{
-	int d;
-	u32int l, nw;
-	uchar *p;
-	Memdata *md;
-	Memimage *i;
-
-	if((d = chantodepth(chan)) == 0) {
-		werrstr("bad channel descriptor %.8lux", chan);
-		return nil;
-	}
-
-	l = wordsperline(r, d);
-	nw = l*Dy(r);
-	md = malloc(sizeof(Memdata));
-	if(md == nil)
-		return nil;
-
-	md->ref = 1;
-	md->base = poolalloc(imagmem, sizeof(Memdata*)+(1+nw)*sizeof(ulong));
-	if(md->base == nil){
-		free(md);
-		return nil;
-	}
-
-	p = (uchar*)md->base;
-	*(Memdata**)p = md;
-	p += sizeof(Memdata*);
-
-	*(ulong*)p = getcallerpc(&r);
-	p += sizeof(ulong);
-
-	/* if this changes, memimagemove must change too */
-	md->bdata = p;
-	md->allocd = 1;
-
-	i = allocmemimaged(r, chan, md, nil);
-	if(i == nil){
-		poolfree(imagmem, md->base);
-		free(md);
-		return nil;
-	}
-	md->imref = i;
-	return i;
-}
-
-void
-_freememimage(Memimage *i)
-{
-	if(i == nil)
-		return;
-	if(i->data->ref-- == 1 && i->data->allocd){
-		if(i->data->base)
-			poolfree(imagmem, i->data->base);
-		free(i->data);
-	}
-	free(i);
-}
-
-/*
- * Wordaddr is deprecated.
- */
-u32int*
-wordaddr(Memimage *i, Point p)
-{
-	return (u32int*) ((ulong)byteaddr(i, p) & ~(sizeof(u32int)-1));
-}
-
-uchar*
-byteaddr(Memimage *i, Point p)
-{
-	uchar *a;
-
-	a = i->data->bdata+i->zero+sizeof(u32int)*p.y*i->width;
-
-	if(i->depth < 8){
-		/*
-		 * We need to always round down,
-		 * but C rounds toward zero.
-		 */
-		int np;
-		np = 8/i->depth;
-		if(p.x < 0)
-			return a+(p.x-np+1)/np;
-		else
-			return a+p.x/np;
-	}
-	else
-		return a+p.x*(i->depth/8);
-}
-
-int
-memsetchan(Memimage *i, u32int chan)
-{
-	int d;
-	int t, j, k;
-	u32int cc;
-	int bytes;
-
-	if((d = chantodepth(chan)) == 0) {
-		werrstr("bad channel descriptor");
-		return -1;
-	}
-
-	i->depth = d;
-	i->chan = chan;
-	i->flags &= ~(Fgrey|Falpha|Fcmap|Fbytes);
-	bytes = 1;
-	for(cc=chan, j=0, k=0; cc; j+=NBITS(cc), cc>>=8, k++){
-		t=TYPE(cc);
-		if(t < 0 || t >= NChan){
-			werrstr("bad channel string");
-			return -1;
-		}
-		if(t == CGrey)
-			i->flags |= Fgrey;
-		if(t == CAlpha)
-			i->flags |= Falpha;
-		if(t == CMap && i->cmap == nil){
-			i->cmap = memdefcmap;
-			i->flags |= Fcmap;
-		}
-
-		i->shift[t] = j;
-		i->mask[t] = (1<<NBITS(cc))-1;
-		i->nbits[t] = NBITS(cc);
-		if(NBITS(cc) != 8)
-			bytes = 0;
-	}
-	i->nchan = k;
-	if(bytes)
-		i->flags |= Fbytes;
-	return 0;
-}
blob - df836a00e324c99a4c8f7dee7db0a0af37e81123 (mode 644)
blob + /dev/null
--- src/libdraw/md-arc.c
+++ /dev/null
@@ -1,116 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-/*
- * elarc(dst,c,a,b,t,src,sp,alpha,phi)
- *   draws the part of an ellipse between rays at angles alpha and alpha+phi
- *   measured counterclockwise from the positive x axis. other
- *   arguments are as for ellipse(dst,c,a,b,t,src,sp)
- */
-
-enum
-{
-	R, T, L, B	/* right, top, left, bottom */
-};
-
-static
-Point corners[] = {
-	{1,1},
-	{-1,1},
-	{-1,-1},
-	{1,-1}
-};
-
-static
-Point p00;
-
-/*
- * make a "wedge" mask covering the desired angle and contained in
- * a surrounding square; draw a full ellipse; intersect that with the
- * wedge to make a mask through which to copy src to dst.
- */
-void
-memarc(Memimage *dst, Point c, int a, int b, int t, Memimage *src, Point sp, int alpha, int phi, int op)
-{
-	int i, w, beta, tmp, c1, c2, m, m1;
-	Rectangle rect;
-	Point p,	bnd[8];
-	Memimage *wedge, *figure, *mask;
-
-	if(a < 0)
-		a = -a;
-	if(b < 0)
-		b = -b;
-	w = t;
-	if(w < 0)
-		w = 0;
-	alpha = -alpha;		/* compensate for upside-down coords */
-	phi = -phi;
-	beta = alpha + phi;
-	if(phi < 0){
-		tmp = alpha;
-		alpha = beta;
-		beta = tmp;
-		phi = -phi;
-	}
-	if(phi >= 360){
-		memellipse(dst, c, a, b, t, src, sp, op);
-		return;
-	}
-	while(alpha < 0)
-		alpha += 360;
-	while(beta < 0)
-		beta += 360;
-	c1 = alpha/90 & 3;	/* number of nearest corner */
-	c2 = beta/90 & 3;
-		/*
-		 * icossin returns point at radius ICOSSCALE.
-		 * multiplying by m1 moves it outside the ellipse
-		*/
-	rect = Rect(-a-w, -b-w, a+w+1, b+w+1);
-	m = rect.max.x;	/* inradius of bounding square */
-	if(m < rect.max.y)
-		m = rect.max.y;
-	m1 = (m+ICOSSCALE-1) >> 10;
-	m = m1 << 10;		/* assure m1*cossin is inside */
-	i = 0;
-	bnd[i++] = Pt(0,0);
-	icossin(alpha, &p.x, &p.y);
-	bnd[i++] = mulpt(p, m1);
-	for(;;) {
-		bnd[i++] = mulpt(corners[c1], m);
-		if(c1==c2 && phi<180)
-			break;
-		c1 = (c1+1) & 3;
-		phi -= 90;
-	}
-	icossin(beta, &p.x, &p.y);
-	bnd[i++] = mulpt(p, m1);
-
-	figure = nil;
-	mask = nil;
-	wedge = allocmemimage(rect, GREY1);
-	if(wedge == nil)
-		goto Return;
-	memfillcolor(wedge, DTransparent);
-	memfillpoly(wedge, bnd, i, ~0, memopaque, p00, S);
-	figure = allocmemimage(rect, GREY1);
-	if(figure == nil)
-		goto Return;
-	memfillcolor(figure, DTransparent);
-	memellipse(figure, p00, a, b, t, memopaque, p00, S);
-	mask = allocmemimage(rect, GREY1);
-	if(mask == nil)
-		goto Return;
-	memfillcolor(mask, DTransparent);
-	memimagedraw(mask, rect, figure, rect.min, wedge, rect.min, S);
-	c = subpt(c, dst->r.min);
-	memdraw(dst, dst->r, src, subpt(sp, c), mask, subpt(p00, c), op);
-
-    Return:
-	freememimage(wedge);
-	freememimage(figure);
-	freememimage(mask);
-}
blob - b3a8c21119b67ad4a227fbe2caa4e497b1ed1350 (mode 644)
blob + /dev/null
--- src/libdraw/md-arctest.c
+++ /dev/null
@@ -1,61 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-extern int drawdebug;
-void
-main(int argc, char **argv)
-{
-	char cc;
-	Memimage *x;
-	Point c = {208,871};
-	int a = 441;
-	int b = 441;
-	int thick = 0;
-	Point sp = {0,0};
-	int alpha = 51;
-	int phi = 3;
-	vlong t0, t1;
-	int i, n;
-	vlong del;
-
-	memimageinit();
-
-	x = allocmemimage(Rect(0,0,1000,1000), CMAP8);
-	n = atoi(argv[1]);
-
-	t0 = nsec();
-	t0 = nsec();
-	t0 = nsec();
-	t1 = nsec();
-	del = t1-t0;
-	t0 = nsec();
-	for(i=0; i<n; i++)
-		memarc(x, c, a, b, thick, memblack, sp, alpha, phi, SoverD);
-	t1 = nsec();
-	print("%lld %lld\n", t1-t0-del, del);
-}
-
-int drawdebug = 0;
-
-void
-rdb(void)
-{
-}
-
-int
-iprint(char *fmt, ...)
-{
-	int n;	
-	va_list va;
-	char buf[1024];
-
-	va_start(va, fmt);
-	n = doprint(buf, buf+sizeof buf, fmt, va) - buf;
-	va_end(va);
-
-	write(1,buf,n);
-	return 1;
-}
-
blob - 472caa6bac52ab44beaba8f009c5b85ed10363d4 (mode 644)
blob + /dev/null
--- src/libdraw/md-cload.c
+++ /dev/null
@@ -1,68 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-int
-_cloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
-{
-	int y, bpl, c, cnt, offs;
-	uchar mem[NMEM], *memp, *omemp, *emem, *linep, *elinep, *u, *eu;
-
-	if(!rectinrect(r, i->r))
-		return -1;
-	bpl = bytesperline(r, i->depth);
-	u = data;
-	eu = data+ndata;
-	memp = mem;
-	emem = mem+NMEM;
-	y = r.min.y;
-	linep = byteaddr(i, Pt(r.min.x, y));
-	elinep = linep+bpl;
-	for(;;){
-		if(linep == elinep){
-			if(++y == r.max.y)
-				break;
-			linep = byteaddr(i, Pt(r.min.x, y));
-			elinep = linep+bpl;
-		}
-		if(u == eu){	/* buffer too small */
-			return -1;
-		}
-		c = *u++;
-		if(c >= 128){
-			for(cnt=c-128+1; cnt!=0 ;--cnt){
-				if(u == eu){		/* buffer too small */
-					return -1;
-				}
-				if(linep == elinep){	/* phase error */
-					return -1;
-				}
-				*linep++ = *u;
-				*memp++ = *u++;
-				if(memp == emem)
-					memp = mem;
-			}
-		}
-		else{
-			if(u == eu)	/* short buffer */
-				return -1;
-			offs = *u++ + ((c&3)<<8)+1;
-			if(memp-mem < offs)
-				omemp = memp+(NMEM-offs);
-			else
-				omemp = memp-offs;
-			for(cnt=(c>>2)+NMATCH; cnt!=0; --cnt){
-				if(linep == elinep)	/* phase error */
-					return -1;
-				*linep++ = *omemp;
-				*memp++ = *omemp++;
-				if(omemp == emem)
-					omemp = mem;
-				if(memp == emem)
-					memp = mem;
-			}
-		}
-	}
-	return u-data;
-}
blob - 2561c3f1cd2e9309849728ab0f16e3c0fc00c504 (mode 644)
blob + /dev/null
--- src/libdraw/md-cmap.c
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * generated by mkcmap.c
- */
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-static Memcmap def = {
-/* cmap2rgb */ {
-	0x00,0x00,0x00,0x00,0x00,0x44,0x00,0x00,0x88,0x00,0x00,0xcc,0x00,0x44,0x00,0x00,
-	0x44,0x44,0x00,0x44,0x88,0x00,0x44,0xcc,0x00,0x88,0x00,0x00,0x88,0x44,0x00,0x88,
-	0x88,0x00,0x88,0xcc,0x00,0xcc,0x00,0x00,0xcc,0x44,0x00,0xcc,0x88,0x00,0xcc,0xcc,
-	0x00,0xdd,0xdd,0x11,0x11,0x11,0x00,0x00,0x55,0x00,0x00,0x99,0x00,0x00,0xdd,0x00,
-	0x55,0x00,0x00,0x55,0x55,0x00,0x4c,0x99,0x00,0x49,0xdd,0x00,0x99,0x00,0x00,0x99,
-	0x4c,0x00,0x99,0x99,0x00,0x93,0xdd,0x00,0xdd,0x00,0x00,0xdd,0x49,0x00,0xdd,0x93,
-	0x00,0xee,0x9e,0x00,0xee,0xee,0x22,0x22,0x22,0x00,0x00,0x66,0x00,0x00,0xaa,0x00,
-	0x00,0xee,0x00,0x66,0x00,0x00,0x66,0x66,0x00,0x55,0xaa,0x00,0x4f,0xee,0x00,0xaa,
-	0x00,0x00,0xaa,0x55,0x00,0xaa,0xaa,0x00,0x9e,0xee,0x00,0xee,0x00,0x00,0xee,0x4f,
-	0x00,0xff,0x55,0x00,0xff,0xaa,0x00,0xff,0xff,0x33,0x33,0x33,0x00,0x00,0x77,0x00,
-	0x00,0xbb,0x00,0x00,0xff,0x00,0x77,0x00,0x00,0x77,0x77,0x00,0x5d,0xbb,0x00,0x55,
-	0xff,0x00,0xbb,0x00,0x00,0xbb,0x5d,0x00,0xbb,0xbb,0x00,0xaa,0xff,0x00,0xff,0x00,
-	0x44,0x00,0x44,0x44,0x00,0x88,0x44,0x00,0xcc,0x44,0x44,0x00,0x44,0x44,0x44,0x44,
-	0x44,0x88,0x44,0x44,0xcc,0x44,0x88,0x00,0x44,0x88,0x44,0x44,0x88,0x88,0x44,0x88,
-	0xcc,0x44,0xcc,0x00,0x44,0xcc,0x44,0x44,0xcc,0x88,0x44,0xcc,0xcc,0x44,0x00,0x00,
-	0x55,0x00,0x00,0x55,0x00,0x55,0x4c,0x00,0x99,0x49,0x00,0xdd,0x55,0x55,0x00,0x55,
-	0x55,0x55,0x4c,0x4c,0x99,0x49,0x49,0xdd,0x4c,0x99,0x00,0x4c,0x99,0x4c,0x4c,0x99,
-	0x99,0x49,0x93,0xdd,0x49,0xdd,0x00,0x49,0xdd,0x49,0x49,0xdd,0x93,0x49,0xdd,0xdd,
-	0x4f,0xee,0xee,0x66,0x00,0x00,0x66,0x00,0x66,0x55,0x00,0xaa,0x4f,0x00,0xee,0x66,
-	0x66,0x00,0x66,0x66,0x66,0x55,0x55,0xaa,0x4f,0x4f,0xee,0x55,0xaa,0x00,0x55,0xaa,
-	0x55,0x55,0xaa,0xaa,0x4f,0x9e,0xee,0x4f,0xee,0x00,0x4f,0xee,0x4f,0x4f,0xee,0x9e,
-	0x55,0xff,0xaa,0x55,0xff,0xff,0x77,0x00,0x00,0x77,0x00,0x77,0x5d,0x00,0xbb,0x55,
-	0x00,0xff,0x77,0x77,0x00,0x77,0x77,0x77,0x5d,0x5d,0xbb,0x55,0x55,0xff,0x5d,0xbb,
-	0x00,0x5d,0xbb,0x5d,0x5d,0xbb,0xbb,0x55,0xaa,0xff,0x55,0xff,0x00,0x55,0xff,0x55,
-	0x88,0x00,0x88,0x88,0x00,0xcc,0x88,0x44,0x00,0x88,0x44,0x44,0x88,0x44,0x88,0x88,
-	0x44,0xcc,0x88,0x88,0x00,0x88,0x88,0x44,0x88,0x88,0x88,0x88,0x88,0xcc,0x88,0xcc,
-	0x00,0x88,0xcc,0x44,0x88,0xcc,0x88,0x88,0xcc,0xcc,0x88,0x00,0x00,0x88,0x00,0x44,
-	0x99,0x00,0x4c,0x99,0x00,0x99,0x93,0x00,0xdd,0x99,0x4c,0x00,0x99,0x4c,0x4c,0x99,
-	0x4c,0x99,0x93,0x49,0xdd,0x99,0x99,0x00,0x99,0x99,0x4c,0x99,0x99,0x99,0x93,0x93,
-	0xdd,0x93,0xdd,0x00,0x93,0xdd,0x49,0x93,0xdd,0x93,0x93,0xdd,0xdd,0x99,0x00,0x00,
-	0xaa,0x00,0x00,0xaa,0x00,0x55,0xaa,0x00,0xaa,0x9e,0x00,0xee,0xaa,0x55,0x00,0xaa,
-	0x55,0x55,0xaa,0x55,0xaa,0x9e,0x4f,0xee,0xaa,0xaa,0x00,0xaa,0xaa,0x55,0xaa,0xaa,
-	0xaa,0x9e,0x9e,0xee,0x9e,0xee,0x00,0x9e,0xee,0x4f,0x9e,0xee,0x9e,0x9e,0xee,0xee,
-	0xaa,0xff,0xff,0xbb,0x00,0x00,0xbb,0x00,0x5d,0xbb,0x00,0xbb,0xaa,0x00,0xff,0xbb,
-	0x5d,0x00,0xbb,0x5d,0x5d,0xbb,0x5d,0xbb,0xaa,0x55,0xff,0xbb,0xbb,0x00,0xbb,0xbb,
-	0x5d,0xbb,0xbb,0xbb,0xaa,0xaa,0xff,0xaa,0xff,0x00,0xaa,0xff,0x55,0xaa,0xff,0xaa,
-	0xcc,0x00,0xcc,0xcc,0x44,0x00,0xcc,0x44,0x44,0xcc,0x44,0x88,0xcc,0x44,0xcc,0xcc,
-	0x88,0x00,0xcc,0x88,0x44,0xcc,0x88,0x88,0xcc,0x88,0xcc,0xcc,0xcc,0x00,0xcc,0xcc,
-	0x44,0xcc,0xcc,0x88,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0xcc,0x00,0x44,0xcc,0x00,0x88,
-	0xdd,0x00,0x93,0xdd,0x00,0xdd,0xdd,0x49,0x00,0xdd,0x49,0x49,0xdd,0x49,0x93,0xdd,
-	0x49,0xdd,0xdd,0x93,0x00,0xdd,0x93,0x49,0xdd,0x93,0x93,0xdd,0x93,0xdd,0xdd,0xdd,
-	0x00,0xdd,0xdd,0x49,0xdd,0xdd,0x93,0xdd,0xdd,0xdd,0xdd,0x00,0x00,0xdd,0x00,0x49,
-	0xee,0x00,0x4f,0xee,0x00,0x9e,0xee,0x00,0xee,0xee,0x4f,0x00,0xee,0x4f,0x4f,0xee,
-	0x4f,0x9e,0xee,0x4f,0xee,0xee,0x9e,0x00,0xee,0x9e,0x4f,0xee,0x9e,0x9e,0xee,0x9e,
-	0xee,0xee,0xee,0x00,0xee,0xee,0x4f,0xee,0xee,0x9e,0xee,0xee,0xee,0xee,0x00,0x00,
-	0xff,0x00,0x00,0xff,0x00,0x55,0xff,0x00,0xaa,0xff,0x00,0xff,0xff,0x55,0x00,0xff,
-	0x55,0x55,0xff,0x55,0xaa,0xff,0x55,0xff,0xff,0xaa,0x00,0xff,0xaa,0x55,0xff,0xaa,
-	0xaa,0xff,0xaa,0xff,0xff,0xff,0x00,0xff,0xff,0x55,0xff,0xff,0xaa,0xff,0xff,0xff,
-},
-/* rgb2cmap */ {
-	0x00,0x00,0x11,0x01,0x01,0x12,0x23,0x34,0x02,0x13,0x24,0x35,0x03,0x14,0x25,0x36,
-	0x00,0x11,0x11,0x01,0x01,0x12,0x23,0x34,0x02,0x13,0x24,0x35,0x03,0x14,0x25,0x36,
-	0x11,0x11,0x11,0x01,0x01,0x12,0x23,0x34,0x02,0x13,0x24,0x35,0x03,0x14,0x25,0x36,
-	0x04,0x04,0x04,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x17,0x07,0x07,0x18,0x18,0x29,
-	0x04,0x04,0x04,0x05,0x05,0x05,0x16,0x06,0x06,0x17,0x28,0x07,0x07,0x18,0x29,0x3a,
-	0x15,0x15,0x15,0x05,0x05,0x16,0x16,0x06,0x06,0x17,0x28,0x39,0x07,0x18,0x29,0x3a,
-	0x26,0x26,0x26,0x05,0x16,0x16,0x27,0x27,0x38,0x28,0x28,0x39,0x39,0x29,0x29,0x3a,
-	0x37,0x37,0x37,0x09,0x09,0x09,0x27,0x38,0x0a,0x0a,0x39,0x0b,0x0b,0x0b,0x1c,0x3a,
-	0x08,0x08,0x08,0x09,0x09,0x09,0x38,0x0a,0x0a,0x0a,0x1b,0x0b,0x0b,0x1c,0x1c,0x2d,
-	0x19,0x19,0x19,0x09,0x1a,0x1a,0x2b,0x0a,0x0a,0x1b,0x1b,0x0b,0x0b,0x1c,0x2d,0x3e,
-	0x2a,0x2a,0x2a,0x1a,0x2b,0x2b,0x2b,0x3c,0x1b,0x1b,0x2c,0x2c,0x3d,0x2d,0x2d,0x3e,
-	0x3b,0x3b,0x3b,0x0d,0x0d,0x3c,0x3c,0x0e,0x0e,0x0e,0x2c,0x3d,0x0f,0x0f,0x3e,0x3e,
-	0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x3c,0x0e,0x0e,0x0e,0x3d,0x0f,0x0f,0x0f,0x10,0x3e,
-	0x1d,0x1d,0x1d,0x1e,0x1e,0x1e,0x2f,0x0e,0x1f,0x1f,0x20,0x0f,0x0f,0x10,0x10,0x21,
-	0x2e,0x2e,0x2e,0x1e,0x2f,0x2f,0x2f,0x1f,0x1f,0x20,0x20,0x31,0x10,0x10,0x21,0x21,
-	0x3f,0x3f,0x3f,0x2f,0x30,0x30,0x30,0x30,0x20,0x31,0x31,0x31,0x31,0x21,0x21,0x32,
-	0x00,0x11,0x11,0x01,0x01,0x12,0x23,0x34,0x02,0x13,0x24,0x35,0x03,0x14,0x25,0x36,
-	0x11,0x11,0x11,0x01,0x01,0x12,0x23,0x34,0x02,0x13,0x24,0x35,0x03,0x14,0x25,0x36,
-	0x11,0x11,0x22,0x22,0x01,0x12,0x23,0x34,0x02,0x13,0x24,0x35,0x03,0x14,0x25,0x36,
-	0x04,0x04,0x22,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x17,0x07,0x07,0x18,0x18,0x29,
-	0x04,0x04,0x04,0x05,0x05,0x05,0x16,0x06,0x06,0x17,0x28,0x07,0x07,0x18,0x29,0x3a,
-	0x15,0x15,0x15,0x05,0x05,0x16,0x16,0x06,0x06,0x17,0x28,0x39,0x07,0x18,0x29,0x3a,
-	0x26,0x26,0x26,0x05,0x16,0x16,0x27,0x27,0x38,0x28,0x28,0x39,0x39,0x29,0x29,0x3a,
-	0x37,0x37,0x37,0x09,0x09,0x09,0x27,0x38,0x0a,0x0a,0x39,0x0b,0x0b,0x0b,0x1c,0x3a,
-	0x08,0x08,0x08,0x09,0x09,0x09,0x38,0x0a,0x0a,0x0a,0x1b,0x0b,0x0b,0x1c,0x1c,0x2d,
-	0x19,0x19,0x19,0x09,0x1a,0x1a,0x2b,0x0a,0x0a,0x1b,0x1b,0x0b,0x0b,0x1c,0x2d,0x3e,
-	0x2a,0x2a,0x2a,0x1a,0x2b,0x2b,0x2b,0x3c,0x1b,0x1b,0x2c,0x2c,0x3d,0x2d,0x2d,0x3e,
-	0x3b,0x3b,0x3b,0x0d,0x0d,0x3c,0x3c,0x0e,0x0e,0x0e,0x2c,0x3d,0x0f,0x0f,0x3e,0x3e,
-	0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x3c,0x0e,0x0e,0x0e,0x3d,0x0f,0x0f,0x0f,0x10,0x3e,
-	0x1d,0x1d,0x1d,0x1e,0x1e,0x1e,0x2f,0x0e,0x1f,0x1f,0x20,0x0f,0x0f,0x10,0x10,0x21,
-	0x2e,0x2e,0x2e,0x1e,0x2f,0x2f,0x2f,0x1f,0x1f,0x20,0x20,0x31,0x10,0x10,0x21,0x21,
-	0x3f,0x3f,0x3f,0x2f,0x30,0x30,0x30,0x30,0x20,0x31,0x31,0x31,0x31,0x21,0x21,0x32,
-	0x11,0x11,0x11,0x01,0x01,0x12,0x23,0x34,0x02,0x13,0x24,0x35,0x03,0x14,0x25,0x36,
-	0x11,0x11,0x22,0x22,0x01,0x12,0x23,0x34,0x02,0x13,0x24,0x35,0x03,0x14,0x25,0x36,
-	0x11,0x22,0x22,0x22,0x33,0x33,0x23,0x34,0x02,0x13,0x24,0x35,0x03,0x14,0x25,0x36,
-	0x04,0x22,0x22,0x33,0x33,0x33,0x05,0x06,0x06,0x06,0x17,0x07,0x07,0x18,0x18,0x29,
-	0x04,0x04,0x33,0x33,0x33,0x05,0x16,0x06,0x06,0x17,0x28,0x07,0x07,0x18,0x29,0x3a,
-	0x15,0x15,0x33,0x33,0x05,0x16,0x16,0x06,0x06,0x17,0x28,0x39,0x07,0x18,0x29,0x3a,
-	0x26,0x26,0x26,0x05,0x16,0x16,0x27,0x27,0x38,0x28,0x28,0x39,0x39,0x29,0x29,0x3a,
-	0x37,0x37,0x37,0x09,0x09,0x09,0x27,0x38,0x0a,0x0a,0x39,0x0b,0x0b,0x0b,0x1c,0x3a,
-	0x08,0x08,0x08,0x09,0x09,0x09,0x38,0x0a,0x0a,0x0a,0x1b,0x0b,0x0b,0x1c,0x1c,0x2d,
-	0x19,0x19,0x19,0x09,0x1a,0x1a,0x2b,0x0a,0x0a,0x1b,0x1b,0x0b,0x0b,0x1c,0x2d,0x3e,
-	0x2a,0x2a,0x2a,0x1a,0x2b,0x2b,0x2b,0x3c,0x1b,0x1b,0x2c,0x2c,0x3d,0x2d,0x2d,0x3e,
-	0x3b,0x3b,0x3b,0x0d,0x0d,0x3c,0x3c,0x0e,0x0e,0x0e,0x2c,0x3d,0x0f,0x0f,0x3e,0x3e,
-	0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x3c,0x0e,0x0e,0x0e,0x3d,0x0f,0x0f,0x0f,0x10,0x3e,
-	0x1d,0x1d,0x1d,0x1e,0x1e,0x1e,0x2f,0x0e,0x1f,0x1f,0x20,0x0f,0x0f,0x10,0x10,0x21,
-	0x2e,0x2e,0x2e,0x1e,0x2f,0x2f,0x2f,0x1f,0x1f,0x20,0x20,0x31,0x10,0x10,0x21,0x21,
-	0x3f,0x3f,0x3f,0x2f,0x30,0x30,0x30,0x30,0x20,0x31,0x31,0x31,0x31,0x21,0x21,0x32,
-	0x4f,0x4f,0x22,0x40,0x40,0x40,0x40,0x41,0x41,0x41,0x52,0x42,0x42,0x53,0x53,0x64,
-	0x4f,0x22,0x22,0x22,0x40,0x40,0x40,0x41,0x41,0x41,0x52,0x42,0x42,0x53,0x53,0x64,
-	0x22,0x22,0x22,0x33,0x33,0x33,0x40,0x41,0x41,0x41,0x52,0x42,0x42,0x53,0x53,0x64,
-	0x43,0x22,0x33,0x33,0x33,0x44,0x44,0x45,0x45,0x45,0x56,0x46,0x46,0x46,0x57,0x68,
-	0x43,0x43,0x33,0x33,0x44,0x44,0x44,0x45,0x45,0x45,0x56,0x46,0x46,0x57,0x57,0x68,
-	0x43,0x43,0x33,0x44,0x44,0x44,0x55,0x45,0x45,0x56,0x56,0x46,0x46,0x57,0x68,0x68,
-	0x43,0x43,0x43,0x44,0x44,0x55,0x55,0x45,0x45,0x56,0x67,0x46,0x46,0x57,0x68,0x79,
-	0x47,0x47,0x47,0x48,0x48,0x48,0x48,0x49,0x49,0x49,0x49,0x4a,0x4a,0x4a,0x5b,0x79,
-	0x47,0x47,0x47,0x48,0x48,0x48,0x48,0x49,0x49,0x49,0x5a,0x4a,0x4a,0x4a,0x5b,0x6c,
-	0x47,0x47,0x47,0x48,0x48,0x59,0x59,0x49,0x49,0x5a,0x5a,0x4a,0x4a,0x5b,0x5b,0x6c,
-	0x58,0x58,0x58,0x59,0x59,0x59,0x6a,0x49,0x5a,0x5a,0x6b,0x6b,0x5b,0x5b,0x6c,0x7d,
-	0x4b,0x4b,0x4b,0x4c,0x4c,0x4c,0x4c,0x4d,0x4d,0x4d,0x6b,0x4e,0x4e,0x4e,0x6c,0x7d,
-	0x4b,0x4b,0x4b,0x4c,0x4c,0x4c,0x4c,0x4d,0x4d,0x4d,0x5e,0x4e,0x4e,0x4e,0x5f,0x5f,
-	0x5c,0x5c,0x5c,0x4c,0x5d,0x5d,0x5d,0x4d,0x4d,0x5e,0x5e,0x4e,0x4e,0x5f,0x5f,0x60,
-	0x5c,0x5c,0x5c,0x5d,0x5d,0x6e,0x6e,0x5e,0x5e,0x5e,0x6f,0x6f,0x5f,0x5f,0x60,0x60,
-	0x6d,0x6d,0x6d,0x6e,0x6e,0x6e,0x7f,0x7f,0x6f,0x6f,0x70,0x70,0x5f,0x60,0x60,0x71,
-	0x4f,0x4f,0x40,0x40,0x40,0x40,0x51,0x41,0x41,0x52,0x63,0x42,0x42,0x53,0x64,0x75,
-	0x4f,0x4f,0x22,0x40,0x40,0x40,0x51,0x41,0x41,0x52,0x63,0x42,0x42,0x53,0x64,0x75,
-	0x43,0x22,0x33,0x33,0x33,0x40,0x51,0x41,0x41,0x52,0x63,0x42,0x42,0x53,0x64,0x75,
-	0x43,0x43,0x33,0x33,0x44,0x44,0x44,0x45,0x45,0x45,0x56,0x46,0x46,0x57,0x57,0x68,
-	0x43,0x43,0x33,0x44,0x44,0x44,0x55,0x45,0x45,0x56,0x56,0x46,0x46,0x57,0x68,0x68,
-	0x43,0x43,0x43,0x44,0x44,0x55,0x55,0x45,0x45,0x56,0x67,0x46,0x46,0x57,0x68,0x79,
-	0x54,0x54,0x54,0x44,0x55,0x55,0x55,0x45,0x56,0x56,0x67,0x78,0x78,0x57,0x68,0x79,
-	0x47,0x47,0x47,0x48,0x48,0x48,0x48,0x49,0x49,0x49,0x49,0x4a,0x4a,0x4a,0x5b,0x79,
-	0x47,0x47,0x47,0x48,0x48,0x48,0x59,0x49,0x49,0x49,0x5a,0x4a,0x4a,0x5b,0x5b,0x6c,
-	0x58,0x58,0x58,0x48,0x59,0x59,0x59,0x49,0x49,0x5a,0x5a,0x4a,0x4a,0x5b,0x6c,0x6c,
-	0x69,0x69,0x69,0x59,0x59,0x6a,0x6a,0x49,0x5a,0x5a,0x6b,0x6b,0x5b,0x5b,0x6c,0x7d,
-	0x4b,0x4b,0x4b,0x4c,0x4c,0x4c,0x7b,0x4d,0x4d,0x4d,0x6b,0x4e,0x4e,0x4e,0x7d,0x7d,
-	0x4b,0x4b,0x4b,0x4c,0x4c,0x4c,0x7b,0x4d,0x4d,0x4d,0x5e,0x4e,0x4e,0x4e,0x5f,0x7d,
-	0x5c,0x5c,0x5c,0x5d,0x5d,0x5d,0x5d,0x4d,0x5e,0x5e,0x5e,0x4e,0x4e,0x5f,0x5f,0x60,
-	0x6d,0x6d,0x6d,0x5d,0x6e,0x6e,0x6e,0x5e,0x5e,0x6f,0x6f,0x70,0x5f,0x5f,0x60,0x60,
-	0x7e,0x7e,0x7e,0x6e,0x6e,0x7f,0x7f,0x7f,0x6f,0x6f,0x70,0x70,0x70,0x60,0x60,0x71,
-	0x50,0x50,0x50,0x40,0x40,0x51,0x51,0x41,0x41,0x52,0x63,0x74,0x42,0x53,0x64,0x75,
-	0x50,0x50,0x50,0x40,0x40,0x51,0x51,0x41,0x41,0x52,0x63,0x74,0x42,0x53,0x64,0x75,
-	0x50,0x50,0x33,0x33,0x40,0x51,0x51,0x41,0x41,0x52,0x63,0x74,0x42,0x53,0x64,0x75,
-	0x43,0x43,0x33,0x44,0x44,0x44,0x55,0x45,0x45,0x56,0x56,0x46,0x46,0x57,0x68,0x68,
-	0x43,0x43,0x43,0x44,0x44,0x55,0x55,0x45,0x45,0x56,0x67,0x46,0x46,0x57,0x68,0x79,
-	0x54,0x54,0x54,0x44,0x55,0x55,0x55,0x45,0x56,0x56,0x67,0x78,0x78,0x57,0x68,0x79,
-	0x54,0x54,0x54,0x55,0x55,0x55,0x66,0x66,0x56,0x67,0x67,0x78,0x78,0x68,0x68,0x79,
-	0x47,0x47,0x47,0x48,0x48,0x48,0x66,0x49,0x49,0x49,0x78,0x78,0x4a,0x4a,0x5b,0x79,
-	0x47,0x47,0x47,0x48,0x48,0x59,0x59,0x49,0x49,0x5a,0x5a,0x4a,0x4a,0x5b,0x6c,0x6c,
-	0x58,0x58,0x58,0x59,0x59,0x59,0x6a,0x49,0x5a,0x5a,0x6b,0x6b,0x5b,0x5b,0x6c,0x7d,
-	0x69,0x69,0x69,0x59,0x6a,0x6a,0x6a,0x7b,0x5a,0x6b,0x6b,0x6b,0x7c,0x6c,0x6c,0x7d,
-	0x7a,0x7a,0x7a,0x4c,0x4c,0x7b,0x7b,0x7b,0x4d,0x6b,0x6b,0x7c,0x7c,0x4e,0x7d,0x7d,
-	0x4b,0x4b,0x4b,0x4c,0x4c,0x7b,0x7b,0x4d,0x4d,0x5e,0x7c,0x7c,0x4e,0x5f,0x5f,0x7d,
-	0x5c,0x5c,0x5c,0x5d,0x5d,0x5d,0x6e,0x4d,0x5e,0x5e,0x6f,0x4e,0x5f,0x5f,0x60,0x60,
-	0x6d,0x6d,0x6d,0x6e,0x6e,0x6e,0x6e,0x5e,0x6f,0x6f,0x6f,0x70,0x5f,0x60,0x60,0x71,
-	0x7e,0x7e,0x7e,0x6e,0x7f,0x7f,0x7f,0x7f,0x6f,0x70,0x70,0x70,0x70,0x60,0x71,0x71,
-	0x61,0x61,0x61,0x40,0x51,0x51,0x62,0x62,0x73,0x63,0x63,0x74,0x74,0x64,0x64,0x75,
-	0x61,0x61,0x61,0x40,0x51,0x51,0x62,0x62,0x73,0x63,0x63,0x74,0x74,0x64,0x64,0x75,
-	0x61,0x61,0x61,0x40,0x51,0x51,0x62,0x62,0x73,0x63,0x63,0x74,0x74,0x64,0x64,0x75,
-	0x43,0x43,0x43,0x44,0x44,0x55,0x55,0x45,0x45,0x56,0x67,0x46,0x46,0x57,0x68,0x79,
-	0x54,0x54,0x54,0x44,0x55,0x55,0x55,0x45,0x56,0x56,0x67,0x78,0x78,0x57,0x68,0x79,
-	0x54,0x54,0x54,0x55,0x55,0x55,0x66,0x66,0x56,0x67,0x67,0x78,0x78,0x68,0x68,0x79,
-	0x65,0x65,0x65,0x55,0x55,0x66,0x66,0x66,0x77,0x67,0x78,0x78,0x78,0x78,0x79,0x79,
-	0x65,0x65,0x65,0x48,0x48,0x66,0x66,0x77,0x77,0x77,0x78,0x78,0x78,0x5b,0x79,0x79,
-	0x76,0x76,0x76,0x48,0x59,0x59,0x77,0x77,0x77,0x5a,0x5a,0x4a,0x4a,0x5b,0x6c,0x6c,
-	0x69,0x69,0x69,0x59,0x59,0x6a,0x6a,0x77,0x5a,0x5a,0x6b,0x6b,0x5b,0x6c,0x6c,0x7d,
-	0x69,0x69,0x69,0x6a,0x6a,0x6a,0x7b,0x7b,0x5a,0x6b,0x6b,0x7c,0x7c,0x6c,0x7d,0x7d,
-	0x7a,0x7a,0x7a,0x4c,0x7b,0x7b,0x7b,0x7b,0x4d,0x6b,0x7c,0x7c,0x7c,0x7c,0x7d,0x7d,
-	0x7a,0x7a,0x7a,0x4c,0x7b,0x7b,0x7b,0x7b,0x4d,0x5e,0x7c,0x7c,0x7c,0x5f,0x5f,0x7d,
-	0x6d,0x6d,0x6d,0x5d,0x5d,0x6e,0x7b,0x5e,0x5e,0x6f,0x6f,0x7c,0x5f,0x5f,0x60,0x60,
-	0x6d,0x6d,0x6d,0x6e,0x6e,0x6e,0x7f,0x7f,0x6f,0x6f,0x70,0x70,0x5f,0x60,0x60,0x71,
-	0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x7f,0x7f,0x6f,0x70,0x70,0x70,0x70,0x60,0x71,0x71,
-	0x72,0x72,0x72,0x8f,0x8f,0x62,0x62,0x73,0x73,0x80,0x74,0x81,0x81,0x81,0x92,0x75,
-	0x72,0x72,0x72,0x8f,0x8f,0x62,0x62,0x73,0x73,0x80,0x74,0x81,0x81,0x81,0x92,0x75,
-	0x72,0x72,0x72,0x83,0x83,0x62,0x62,0x73,0x73,0x80,0x74,0x81,0x81,0x81,0x92,0x75,
-	0x82,0x82,0x82,0x83,0x83,0x83,0x83,0x84,0x84,0x84,0x84,0x85,0x85,0x85,0x96,0x79,
-	0x82,0x82,0x82,0x83,0x83,0x83,0x66,0x84,0x84,0x84,0x67,0x85,0x85,0x85,0x96,0x79,
-	0x65,0x65,0x65,0x83,0x83,0x66,0x66,0x66,0x84,0x84,0x78,0x78,0x85,0x85,0x96,0x79,
-	0x65,0x65,0x65,0x83,0x66,0x66,0x66,0x77,0x77,0x77,0x78,0x78,0x78,0x96,0x79,0x79,
-	0x76,0x76,0x76,0x87,0x87,0x66,0x77,0x77,0x77,0x88,0x78,0x89,0x89,0x89,0x89,0x79,
-	0x76,0x76,0x76,0x87,0x87,0x87,0x77,0x77,0x88,0x88,0x88,0x89,0x89,0x89,0x9a,0x9a,
-	0x86,0x86,0x86,0x87,0x87,0x87,0x77,0x88,0x88,0x88,0x6b,0x89,0x89,0x9a,0x9a,0x7d,
-	0x7a,0x7a,0x7a,0x87,0x6a,0x7b,0x7b,0x7b,0x88,0x6b,0x6b,0x7c,0x7c,0x9a,0x7d,0x7d,
-	0x8a,0x8a,0x8a,0x8b,0x8b,0x7b,0x7b,0x8c,0x8c,0x8c,0x7c,0x7c,0x8d,0x8d,0x7d,0x7d,
-	0x8a,0x8a,0x8a,0x8b,0x8b,0x8b,0x7b,0x8c,0x8c,0x8c,0x7c,0x8d,0x8d,0x8d,0x9e,0x9e,
-	0x8a,0x8a,0x8a,0x8b,0x8b,0x8b,0x9c,0x8c,0x8c,0x9d,0x9d,0x8d,0x8d,0x9e,0x9e,0x9e,
-	0x9b,0x9b,0x9b,0x9c,0x9c,0x9c,0x7f,0x8c,0x9d,0x9d,0x70,0x70,0x9e,0x9e,0x9e,0x71,
-	0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x7f,0x7f,0x9d,0x70,0x70,0x70,0x9e,0x9e,0x71,0x71,
-	0x8e,0x8e,0x8e,0x8f,0x8f,0x8f,0x73,0x73,0x80,0x80,0x91,0x81,0x81,0x92,0x92,0xa3,
-	0x8e,0x8e,0x8e,0x8f,0x8f,0x8f,0x73,0x73,0x80,0x80,0x91,0x81,0x81,0x92,0x92,0xa3,
-	0x82,0x82,0x82,0x83,0x83,0x83,0x73,0x73,0x80,0x80,0x91,0x81,0x81,0x92,0x92,0xa3,
-	0x82,0x82,0x82,0x83,0x83,0x83,0x83,0x84,0x84,0x84,0x95,0x85,0x85,0x85,0x96,0xa7,
-	0x82,0x82,0x82,0x83,0x83,0x83,0x94,0x84,0x84,0x84,0x95,0x85,0x85,0x96,0x96,0xa7,
-	0x82,0x82,0x82,0x83,0x83,0x94,0x94,0x84,0x84,0x95,0x95,0x85,0x85,0x96,0xa7,0xa7,
-	0x76,0x76,0x76,0x83,0x94,0x94,0x77,0x77,0x77,0x95,0x95,0x85,0x85,0x96,0xa7,0xa7,
-	0x76,0x76,0x76,0x87,0x87,0x87,0x77,0x77,0x88,0x88,0x88,0x89,0x89,0x89,0x9a,0x9a,
-	0x86,0x86,0x86,0x87,0x87,0x87,0x77,0x88,0x88,0x88,0x99,0x89,0x89,0x9a,0x9a,0xab,
-	0x86,0x86,0x86,0x87,0x87,0x98,0x98,0x88,0x88,0x99,0x99,0x89,0x89,0x9a,0x9a,0xab,
-	0x97,0x97,0x97,0x98,0x98,0x98,0x98,0x88,0x99,0x99,0x99,0x89,0x9a,0x9a,0xab,0xab,
-	0x8a,0x8a,0x8a,0x8b,0x8b,0x8b,0x8b,0x8c,0x8c,0x8c,0x8c,0x8d,0x8d,0x8d,0xab,0xbc,
-	0x8a,0x8a,0x8a,0x8b,0x8b,0x8b,0x8b,0x8c,0x8c,0x8c,0x9d,0x8d,0x8d,0x8d,0x9e,0x9e,
-	0x9b,0x9b,0x9b,0x8b,0x9c,0x9c,0x9c,0x8c,0x9d,0x9d,0x9d,0x8d,0x8d,0x9e,0x9e,0xaf,
-	0x9b,0x9b,0x9b,0x9c,0x9c,0xad,0xad,0x9d,0x9d,0x9d,0xae,0xae,0x9e,0x9e,0xaf,0xaf,
-	0xac,0xac,0xac,0xad,0xad,0xad,0xad,0x9d,0xae,0xae,0xae,0xbf,0x9e,0xaf,0xaf,0xaf,
-	0x9f,0x9f,0x9f,0x8f,0x90,0x90,0xa1,0x80,0x80,0x91,0x91,0x81,0x81,0x92,0xa3,0xb4,
-	0x9f,0x9f,0x9f,0x8f,0x90,0x90,0xa1,0x80,0x80,0x91,0x91,0x81,0x81,0x92,0xa3,0xb4,
-	0x9f,0x9f,0x9f,0x83,0x90,0x90,0xa1,0x80,0x80,0x91,0x91,0x81,0x81,0x92,0xa3,0xb4,
-	0x82,0x82,0x82,0x83,0x83,0x94,0x94,0x84,0x84,0x95,0x95,0x85,0x85,0x96,0x96,0xa7,
-	0x93,0x93,0x93,0x83,0x94,0x94,0x94,0x84,0x84,0x95,0x95,0x85,0x85,0x96,0xa7,0xa7,
-	0x93,0x93,0x93,0x94,0x94,0x94,0xa5,0x84,0x95,0x95,0xa6,0xa6,0x96,0x96,0xa7,0xb8,
-	0xa4,0xa4,0xa4,0x94,0x94,0xa5,0xa5,0x77,0x95,0x95,0xa6,0xa6,0x96,0xa7,0xa7,0xb8,
-	0x86,0x86,0x86,0x87,0x87,0x87,0x77,0x88,0x88,0x88,0x99,0x89,0x89,0x9a,0x9a,0xb8,
-	0x86,0x86,0x86,0x87,0x87,0x98,0x98,0x88,0x88,0x99,0x99,0x89,0x89,0x9a,0x9a,0xab,
-	0x97,0x97,0x97,0x98,0x98,0x98,0x98,0x88,0x99,0x99,0x99,0x89,0x9a,0x9a,0xab,0xab,
-	0x97,0x97,0x97,0x98,0x98,0xa9,0xa9,0x99,0x99,0x99,0xaa,0xaa,0x9a,0xab,0xab,0xbc,
-	0x8a,0x8a,0x8a,0x8b,0x8b,0xa9,0xa9,0x8c,0x8c,0x8c,0xaa,0x8d,0x8d,0x8d,0xab,0xbc,
-	0x8a,0x8a,0x8a,0x8b,0x8b,0x9c,0x9c,0x8c,0x8c,0x9d,0x9d,0x8d,0x8d,0x9e,0x9e,0xbc,
-	0x9b,0x9b,0x9b,0x9c,0x9c,0x9c,0xad,0x9d,0x9d,0x9d,0xae,0x8d,0x9e,0x9e,0xaf,0xaf,
-	0xac,0xac,0xac,0x9c,0xad,0xad,0xad,0x9d,0x9d,0xae,0xae,0xae,0x9e,0xaf,0xaf,0xaf,
-	0xbd,0xbd,0xbd,0xad,0xad,0xbe,0xbe,0xbe,0xae,0xae,0xbf,0xbf,0xbf,0xaf,0xaf,0xb0,
-	0xa0,0xa0,0xa0,0x90,0xa1,0xa1,0xa1,0xb2,0x91,0x91,0xa2,0xa2,0xb3,0xa3,0xa3,0xb4,
-	0xa0,0xa0,0xa0,0x90,0xa1,0xa1,0xa1,0xb2,0x91,0x91,0xa2,0xa2,0xb3,0xa3,0xa3,0xb4,
-	0xa0,0xa0,0xa0,0x90,0xa1,0xa1,0xa1,0xb2,0x91,0x91,0xa2,0xa2,0xb3,0xa3,0xa3,0xb4,
-	0x93,0x93,0x93,0x94,0x94,0x94,0xa5,0x84,0x95,0x95,0xa6,0xa6,0x96,0x96,0xa7,0xb8,
-	0xa4,0xa4,0xa4,0x94,0x94,0xa5,0xa5,0x84,0x95,0x95,0xa6,0xa6,0x96,0x96,0xa7,0xb8,
-	0xa4,0xa4,0xa4,0x94,0xa5,0xa5,0xa5,0xb6,0x95,0xa6,0xa6,0xa6,0xb7,0xa7,0xa7,0xb8,
-	0xa4,0xa4,0xa4,0xa5,0xa5,0xa5,0xb6,0xb6,0x95,0xa6,0xa6,0xb7,0xb7,0xa7,0xb8,0xb8,
-	0xb5,0xb5,0xb5,0x87,0x87,0xb6,0xb6,0xb6,0x88,0x99,0xa6,0xb7,0xb7,0x9a,0xb8,0xb8,
-	0x97,0x97,0x97,0x98,0x98,0x98,0x98,0x88,0x99,0x99,0x99,0x89,0x9a,0x9a,0xab,0xab,
-	0x97,0x97,0x97,0x98,0x98,0xa9,0xa9,0x99,0x99,0x99,0xaa,0xaa,0x9a,0xab,0xab,0xbc,
-	0xa8,0xa8,0xa8,0xa9,0xa9,0xa9,0xa9,0xa9,0x99,0xaa,0xaa,0xaa,0xbb,0xab,0xab,0xbc,
-	0xa8,0xa8,0xa8,0xa9,0xa9,0xa9,0xba,0xba,0x8c,0xaa,0xaa,0xbb,0xbb,0xab,0xbc,0xbc,
-	0xb9,0xb9,0xb9,0x9c,0x9c,0xba,0xba,0xba,0x9d,0x9d,0xbb,0xbb,0xbb,0x9e,0x9e,0xbc,
-	0xac,0xac,0xac,0x9c,0x9c,0xad,0xad,0x9d,0x9d,0xae,0xae,0xae,0x9e,0x9e,0xaf,0xaf,
-	0xac,0xac,0xac,0xad,0xad,0xad,0xbe,0xbe,0xae,0xae,0xae,0xbf,0x9e,0xaf,0xaf,0xb0,
-	0xbd,0xbd,0xbd,0xbe,0xbe,0xbe,0xbe,0xbe,0xae,0xbf,0xbf,0xbf,0xbf,0xaf,0xb0,0xb0,
-	0xb1,0xb1,0xb1,0xce,0xce,0xb2,0xb2,0xcf,0xcf,0xa2,0xa2,0xb3,0xb3,0xc0,0xb4,0xb4,
-	0xb1,0xb1,0xb1,0xce,0xce,0xb2,0xb2,0xcf,0xcf,0xa2,0xa2,0xb3,0xb3,0xc0,0xb4,0xb4,
-	0xb1,0xb1,0xb1,0xc2,0xc2,0xb2,0xb2,0xc3,0xc3,0xa2,0xa2,0xb3,0xb3,0xc0,0xb4,0xb4,
-	0xc1,0xc1,0xc1,0xc2,0xc2,0xc2,0xa5,0xc3,0xc3,0xc3,0xa6,0xc4,0xc4,0xc4,0xa7,0xb8,
-	0xc1,0xc1,0xc1,0xc2,0xc2,0xa5,0xb6,0xc3,0xc3,0xc3,0xa6,0xc4,0xc4,0xc4,0xb8,0xb8,
-	0xb5,0xb5,0xb5,0xc2,0xa5,0xb6,0xb6,0xb6,0xc3,0xa6,0xa6,0xb7,0xb7,0xc4,0xb8,0xb8,
-	0xb5,0xb5,0xb5,0xa5,0xb6,0xb6,0xb6,0xb6,0xc3,0xa6,0xb7,0xb7,0xb7,0xb7,0xb8,0xb8,
-	0xc5,0xc5,0xc5,0xc6,0xc6,0xb6,0xb6,0xc7,0xc7,0xc7,0xb7,0xb7,0xc8,0xc8,0xb8,0xb8,
-	0xc5,0xc5,0xc5,0xc6,0xc6,0xc6,0xc6,0xc7,0xc7,0xc7,0xaa,0xc8,0xc8,0xc8,0xab,0xbc,
-	0xa8,0xa8,0xa8,0xc6,0xc6,0xa9,0xa9,0xc7,0xc7,0xaa,0xaa,0xaa,0xc8,0xc8,0xab,0xbc,
-	0xa8,0xa8,0xa8,0xa9,0xa9,0xa9,0xba,0xba,0xaa,0xaa,0xaa,0xbb,0xbb,0xab,0xbc,0xbc,
-	0xb9,0xb9,0xb9,0xca,0xca,0xba,0xba,0xba,0xcb,0xaa,0xbb,0xbb,0xbb,0xcc,0xbc,0xbc,
-	0xb9,0xb9,0xb9,0xca,0xca,0xba,0xba,0xcb,0xcb,0xcb,0xbb,0xbb,0xcc,0xcc,0xcc,0xbc,
-	0xc9,0xc9,0xc9,0xca,0xca,0xca,0xba,0xcb,0xcb,0xcb,0xae,0xcc,0xcc,0xcc,0xaf,0xaf,
-	0xbd,0xbd,0xbd,0xad,0xbe,0xbe,0xbe,0xbe,0xae,0xae,0xbf,0xbf,0xcc,0xaf,0xaf,0xb0,
-	0xbd,0xbd,0xbd,0xbe,0xbe,0xbe,0xbe,0xbe,0xbf,0xbf,0xbf,0xbf,0xbf,0xaf,0xb0,0xb0,
-	0xcd,0xcd,0xcd,0xce,0xce,0xce,0xb2,0xcf,0xcf,0xcf,0xb3,0xb3,0xc0,0xc0,0xd1,0xb4,
-	0xcd,0xcd,0xcd,0xce,0xce,0xce,0xb2,0xcf,0xcf,0xcf,0xb3,0xb3,0xc0,0xc0,0xd1,0xb4,
-	0xc1,0xc1,0xc1,0xc2,0xc2,0xc2,0xb2,0xc3,0xc3,0xc3,0xb3,0xb3,0xc0,0xc0,0xd1,0xb4,
-	0xc1,0xc1,0xc1,0xc2,0xc2,0xc2,0xc2,0xc3,0xc3,0xc3,0xd4,0xc4,0xc4,0xc4,0xd5,0xd5,
-	0xc1,0xc1,0xc1,0xc2,0xc2,0xc2,0xb6,0xc3,0xc3,0xc3,0xd4,0xc4,0xc4,0xc4,0xd5,0xb8,
-	0xc1,0xc1,0xc1,0xc2,0xc2,0xb6,0xb6,0xc3,0xc3,0xd4,0xb7,0xb7,0xc4,0xd5,0xd5,0xb8,
-	0xb5,0xb5,0xb5,0xc2,0xb6,0xb6,0xb6,0xb6,0xc3,0xd4,0xb7,0xb7,0xb7,0xd5,0xd5,0xb8,
-	0xc5,0xc5,0xc5,0xc6,0xc6,0xc6,0xb6,0xc7,0xc7,0xc7,0xb7,0xc8,0xc8,0xc8,0xd9,0xd9,
-	0xc5,0xc5,0xc5,0xc6,0xc6,0xc6,0xc6,0xc7,0xc7,0xc7,0xd8,0xc8,0xc8,0xc8,0xd9,0xd9,
-	0xc5,0xc5,0xc5,0xc6,0xc6,0xd7,0xd7,0xc7,0xc7,0xd8,0xd8,0xc8,0xc8,0xd9,0xd9,0xbc,
-	0xb9,0xb9,0xb9,0xd7,0xd7,0xba,0xba,0xba,0xd8,0xd8,0xbb,0xbb,0xbb,0xd9,0xd9,0xbc,
-	0xb9,0xb9,0xb9,0xca,0xca,0xba,0xba,0xcb,0xcb,0xcb,0xbb,0xbb,0xcc,0xcc,0xcc,0xbc,
-	0xc9,0xc9,0xc9,0xca,0xca,0xca,0xba,0xcb,0xcb,0xcb,0xbb,0xcc,0xcc,0xcc,0xdd,0xdd,
-	0xc9,0xc9,0xc9,0xca,0xca,0xdb,0xdb,0xcb,0xcb,0xdc,0xdc,0xcc,0xcc,0xdd,0xdd,0xdd,
-	0xda,0xda,0xda,0xdb,0xdb,0xdb,0xdb,0xdc,0xdc,0xdc,0xdc,0xcc,0xdd,0xdd,0xdd,0xb0,
-	0xbd,0xbd,0xbd,0xdb,0xbe,0xbe,0xbe,0xdc,0xdc,0xbf,0xbf,0xbf,0xdd,0xdd,0xb0,0xb0,
-	0xde,0xde,0xde,0xdf,0xdf,0xdf,0xe0,0xcf,0xd0,0xd0,0xe1,0xc0,0xc0,0xd1,0xd1,0xe2,
-	0xde,0xde,0xde,0xdf,0xdf,0xdf,0xe0,0xcf,0xd0,0xd0,0xe1,0xc0,0xc0,0xd1,0xd1,0xe2,
-	0xde,0xde,0xde,0xdf,0xdf,0xdf,0xe0,0xc3,0xd0,0xd0,0xe1,0xc0,0xc0,0xd1,0xd1,0xe2,
-	0xd2,0xd2,0xd2,0xc2,0xd3,0xd3,0xd3,0xc3,0xc3,0xd4,0xd4,0xc4,0xc4,0xd5,0xd5,0xe6,
-	0xd2,0xd2,0xd2,0xd3,0xd3,0xd3,0xd3,0xc3,0xd4,0xd4,0xd4,0xc4,0xc4,0xd5,0xd5,0xe6,
-	0xd2,0xd2,0xd2,0xd3,0xd3,0xd3,0xe4,0xc3,0xd4,0xd4,0xe5,0xc4,0xd5,0xd5,0xe6,0xe6,
-	0xe3,0xe3,0xe3,0xd3,0xd3,0xe4,0xb6,0xd4,0xd4,0xe5,0xe5,0xb7,0xd5,0xd5,0xe6,0xe6,
-	0xc5,0xc5,0xc5,0xc6,0xc6,0xc6,0xd7,0xc7,0xc7,0xd8,0xd8,0xc8,0xc8,0xd9,0xd9,0xd9,
-	0xd6,0xd6,0xd6,0xc6,0xd7,0xd7,0xd7,0xc7,0xd8,0xd8,0xd8,0xc8,0xc8,0xd9,0xd9,0xea,
-	0xd6,0xd6,0xd6,0xd7,0xd7,0xd7,0xe8,0xd8,0xd8,0xd8,0xe9,0xc8,0xd9,0xd9,0xea,0xea,
-	0xe7,0xe7,0xe7,0xd7,0xd7,0xe8,0xe8,0xd8,0xd8,0xe9,0xe9,0xe9,0xd9,0xd9,0xea,0xea,
-	0xc9,0xc9,0xc9,0xca,0xca,0xca,0xba,0xcb,0xcb,0xcb,0xe9,0xcc,0xcc,0xcc,0xea,0xea,
-	0xc9,0xc9,0xc9,0xca,0xca,0xdb,0xdb,0xcb,0xcb,0xdc,0xdc,0xcc,0xcc,0xdd,0xdd,0xdd,
-	0xda,0xda,0xda,0xdb,0xdb,0xdb,0xdb,0xdc,0xdc,0xdc,0xdc,0xcc,0xdd,0xdd,0xdd,0xee,
-	0xda,0xda,0xda,0xdb,0xdb,0xec,0xec,0xdc,0xdc,0xed,0xed,0xed,0xdd,0xdd,0xee,0xee,
-	0xeb,0xeb,0xeb,0xec,0xec,0xec,0xec,0xdc,0xed,0xed,0xed,0xed,0xdd,0xee,0xee,0xee,
-	0xef,0xef,0xef,0xdf,0xe0,0xe0,0xe0,0xd0,0xd0,0xe1,0xe1,0xf2,0xd1,0xd1,0xe2,0xe2,
-	0xef,0xef,0xef,0xdf,0xe0,0xe0,0xe0,0xd0,0xd0,0xe1,0xe1,0xf2,0xd1,0xd1,0xe2,0xe2,
-	0xef,0xef,0xef,0xdf,0xe0,0xe0,0xe0,0xd0,0xd0,0xe1,0xe1,0xf2,0xd1,0xd1,0xe2,0xe2,
-	0xd2,0xd2,0xd2,0xd3,0xd3,0xe4,0xe4,0xd4,0xd4,0xd4,0xe5,0xe5,0xd5,0xd5,0xe6,0xe6,
-	0xe3,0xe3,0xe3,0xd3,0xe4,0xe4,0xe4,0xd4,0xd4,0xe5,0xe5,0xf6,0xd5,0xd5,0xe6,0xe6,
-	0xe3,0xe3,0xe3,0xe4,0xe4,0xe4,0xe4,0xd4,0xe5,0xe5,0xe5,0xf6,0xd5,0xe6,0xe6,0xf7,
-	0xe3,0xe3,0xe3,0xe4,0xe4,0xe4,0xf5,0xf5,0xe5,0xe5,0xf6,0xf6,0xd5,0xe6,0xe6,0xf7,
-	0xd6,0xd6,0xd6,0xd7,0xd7,0xd7,0xf5,0xc7,0xd8,0xd8,0xf6,0xc8,0xd9,0xd9,0xd9,0xf7,
-	0xd6,0xd6,0xd6,0xd7,0xd7,0xe8,0xe8,0xd8,0xd8,0xd8,0xe9,0xe9,0xd9,0xd9,0xea,0xea,
-	0xe7,0xe7,0xe7,0xd7,0xe8,0xe8,0xe8,0xd8,0xd8,0xe9,0xe9,0xe9,0xd9,0xea,0xea,0xea,
-	0xe7,0xe7,0xe7,0xe8,0xe8,0xe8,0xf9,0xf9,0xe9,0xe9,0xe9,0xfa,0xd9,0xea,0xea,0xfb,
-	0xf8,0xf8,0xf8,0xe8,0xf9,0xf9,0xf9,0xcb,0xe9,0xe9,0xfa,0xfa,0xcc,0xea,0xea,0xfb,
-	0xda,0xda,0xda,0xdb,0xdb,0xdb,0xdb,0xdc,0xdc,0xdc,0xdc,0xcc,0xdd,0xdd,0xdd,0xee,
-	0xda,0xda,0xda,0xdb,0xdb,0xec,0xec,0xdc,0xdc,0xed,0xed,0xed,0xdd,0xdd,0xee,0xee,
-	0xeb,0xeb,0xeb,0xec,0xec,0xec,0xec,0xdc,0xed,0xed,0xed,0xed,0xdd,0xee,0xee,0xee,
-	0xeb,0xeb,0xeb,0xec,0xec,0xfd,0xfd,0xfd,0xed,0xed,0xfe,0xfe,0xee,0xee,0xee,0xff,
-	0xf0,0xf0,0xf0,0xe0,0xf1,0xf1,0xf1,0xf1,0xe1,0xf2,0xf2,0xf2,0xf2,0xe2,0xe2,0xf3,
-	0xf0,0xf0,0xf0,0xe0,0xf1,0xf1,0xf1,0xf1,0xe1,0xf2,0xf2,0xf2,0xf2,0xe2,0xe2,0xf3,
-	0xf0,0xf0,0xf0,0xe0,0xf1,0xf1,0xf1,0xf1,0xe1,0xf2,0xf2,0xf2,0xf2,0xe2,0xe2,0xf3,
-	0xe3,0xe3,0xe3,0xe4,0xe4,0xe4,0xf5,0xf5,0xe5,0xe5,0xf6,0xf6,0xd5,0xe6,0xe6,0xf7,
-	0xf4,0xf4,0xf4,0xe4,0xe4,0xf5,0xf5,0xf5,0xe5,0xe5,0xf6,0xf6,0xf6,0xe6,0xe6,0xf7,
-	0xf4,0xf4,0xf4,0xe4,0xf5,0xf5,0xf5,0xf5,0xe5,0xf6,0xf6,0xf6,0xf6,0xe6,0xf7,0xf7,
-	0xf4,0xf4,0xf4,0xf5,0xf5,0xf5,0xf5,0xf5,0xe5,0xf6,0xf6,0xf6,0xf6,0xe6,0xf7,0xf7,
-	0xf4,0xf4,0xf4,0xf5,0xf5,0xf5,0xf5,0xf5,0xd8,0xf6,0xf6,0xf6,0xd9,0xd9,0xf7,0xf7,
-	0xe7,0xe7,0xe7,0xe8,0xe8,0xe8,0xe8,0xd8,0xe9,0xe9,0xe9,0xfa,0xd9,0xea,0xea,0xea,
-	0xf8,0xf8,0xf8,0xe8,0xe8,0xf9,0xf9,0xf9,0xe9,0xe9,0xfa,0xfa,0xfa,0xea,0xea,0xfb,
-	0xf8,0xf8,0xf8,0xf9,0xf9,0xf9,0xf9,0xf9,0xe9,0xfa,0xfa,0xfa,0xfa,0xea,0xfb,0xfb,
-	0xf8,0xf8,0xf8,0xf9,0xf9,0xf9,0xf9,0xf9,0xfa,0xfa,0xfa,0xfa,0xfa,0xea,0xfb,0xfb,
-	0xf8,0xf8,0xf8,0xdb,0xf9,0xf9,0xf9,0xdc,0xdc,0xfa,0xfa,0xfa,0xdd,0xdd,0xee,0xfb,
-	0xeb,0xeb,0xeb,0xec,0xec,0xec,0xec,0xdc,0xed,0xed,0xed,0xed,0xdd,0xee,0xee,0xee,
-	0xeb,0xeb,0xeb,0xec,0xec,0xfd,0xfd,0xfd,0xed,0xed,0xfe,0xfe,0xee,0xee,0xee,0xff,
-	0xfc,0xfc,0xfc,0xfd,0xfd,0xfd,0xfd,0xfd,0xed,0xfe,0xfe,0xfe,0xfe,0xee,0xff,0xff,
-}
-};
-Memcmap *memdefcmap = &def;
-void _memmkcmap(void){}
blob - 4fa5942a4bb9b578fd213cc7debafbc2230ba35b (mode 644)
blob + /dev/null
--- src/libdraw/md-cread.c
+++ /dev/null
@@ -1,96 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-Memimage*
-creadmemimage(int fd)
-{
-	char hdr[5*12+1];
-	Rectangle r;
-	int m, nb, miny, maxy, new, ldepth, ncblock;
-	uchar *buf;
-	Memimage *i;
-	u32int chan;
-
-	if(readn(fd, hdr, 5*12) != 5*12){
-		werrstr("readmemimage: short header (2)");
-		return nil;
-	}
-
-	/*
-	 * distinguish new channel descriptor from old ldepth.
-	 * channel descriptors have letters as well as numbers,
-	 * while ldepths are a single digit formatted as %-11d.
-	 */
-	new = 0;
-	for(m=0; m<10; m++){
-		if(hdr[m] != ' '){
-			new = 1;
-			break;
-		}
-	}
-	if(hdr[11] != ' '){
-		werrstr("creadimage: bad format");
-		return nil;
-	}
-	if(new){
-		hdr[11] = '\0';
-		if((chan = strtochan(hdr)) == 0){
-			werrstr("creadimage: bad channel string %s", hdr);
-			return nil;
-		}
-	}else{
-		ldepth = ((int)hdr[10])-'0';
-		if(ldepth<0 || ldepth>3){
-			werrstr("creadimage: bad ldepth %d", ldepth);
-			return nil;
-		}
-		chan = drawld2chan[ldepth];
-	}
-	r.min.x=atoi(hdr+1*12);
-	r.min.y=atoi(hdr+2*12);
-	r.max.x=atoi(hdr+3*12);
-	r.max.y=atoi(hdr+4*12);
-	if(r.min.x>r.max.x || r.min.y>r.max.y){
-		werrstr("creadimage: bad rectangle");
-		return nil;
-	}
-
-	i = allocmemimage(r, chan);
-	if(i == nil)
-		return nil;
-	ncblock = _compblocksize(r, i->depth);
-	buf = malloc(ncblock);
-	if(buf == nil)
-		goto Errout;
-	miny = r.min.y;
-	while(miny != r.max.y){
-		if(readn(fd, hdr, 2*12) != 2*12){
-		Shortread:
-			werrstr("readmemimage: short read");
-		Errout:
-			freememimage(i);
-			free(buf);
-			return nil;
-		}
-		maxy = atoi(hdr+0*12);
-		nb = atoi(hdr+1*12);
-		if(maxy<=miny || r.max.y<maxy){
-			werrstr("readimage: bad maxy %d", maxy);
-			goto Errout;
-		}
-		if(nb<=0 || ncblock<nb){
-			werrstr("readimage: bad count %d", nb);
-			goto Errout;
-		}
-		if(readn(fd, buf, nb)!=nb)
-			goto Shortread;
-		if(!new)	/* old image: flip the data bits */
-			_twiddlecompressed(buf, nb);
-		cloadmemimage(i, Rect(r.min.x, miny, r.max.x, maxy), buf, nb);
-		miny = maxy;
-	}
-	free(buf);
-	return i;
-}
blob - 21ea6cc013dfe8520b2230075ad4549a13640f02 (mode 644)
blob + /dev/null
--- src/libdraw/md-defont.c
+++ /dev/null
@@ -1,68 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-Memsubfont*
-getmemdefont(void)
-{
-	char *hdr, *p;
-	int n;
-	Fontchar *fc;
-	Memsubfont *f;
-	int ld;
-	Rectangle r;
-	Memdata *md;
-	Memimage *i;
-
-	/*
-	 * make sure data is word-aligned.  this is true with Plan 9 compilers
-	 * but not in general.  the byte order is right because the data is
-	 * declared as char*, not u32int*.
-	 */
-	p = (char*)defontdata;
-	n = (uintptr)p & 3;
-	if(n != 0){
-		memmove(p+(4-n), p, sizeofdefont-n);
-		p += 4-n;
-	}
-	ld = atoi(p+0*12);
-	r.min.x = atoi(p+1*12);
-	r.min.y = atoi(p+2*12);
-	r.max.x = atoi(p+3*12);
-	r.max.y = atoi(p+4*12);
-
-	md = mallocz(sizeof(Memdata), 1);
-	if(md == nil)
-		return nil;
-	
-	p += 5*12;
-
-	md->base = nil;		/* so freememimage doesn't free p */
-	md->bdata = (uchar*)p;	/* ick */
-	md->ref = 1;
-	md->allocd = 1;		/* so freememimage does free md */
-
-	i = allocmemimaged(r, drawld2chan[ld], md, nil);
-	if(i == nil){
-		free(md);
-		return nil;
-	}
-
-	hdr = p+Dy(r)*i->width*sizeof(u32int);
-	n = atoi(hdr);
-	p = hdr+3*12;
-	fc = malloc(sizeof(Fontchar)*(n+1));
-	if(fc == 0){
-		freememimage(i);
-		return 0;
-	}
-	_unpackinfo(fc, (uchar*)p, n);
-	f = allocmemsubfont("*default*", n, atoi(hdr+12), atoi(hdr+24), fc, i);
-	if(f == 0){
-		freememimage(i);
-		free(fc);
-		return 0;
-	}
-	return f;
-}
blob - 2d8681e5ee156abfa91e72b41a88477921e13fa7 (mode 644)
blob + /dev/null
--- src/libdraw/md-draw.c
+++ /dev/null
@@ -1,2489 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-int drawdebug;
-static int	tablesbuilt;
-
-/* perfect approximation to NTSC = .299r+.587g+.114b when 0 ≤ r,g,b < 256 */
-#define RGB2K(r,g,b)	((156763*(r)+307758*(g)+59769*(b))>>19)
-
-/*
- * for 0 ≤ x ≤ 255*255, (x*0x0101+0x100)>>16 is a perfect approximation.
- * for 0 ≤ x < (1<<16), x/255 = ((x+1)*0x0101)>>16 is a perfect approximation.
- * the last one is perfect for all up to 1<<16, avoids a multiply, but requires a rathole.
- */
-/* #define DIV255(x) (((x)*257+256)>>16)  */
-#define DIV255(x) ((((x)+1)*257)>>16)
-/* #define DIV255(x) (tmp=(x)+1, (tmp+(tmp>>8))>>8) */
-
-#define MUL(x, y, t)	(t = (x)*(y)+128, (t+(t>>8))>>8)
-#define MASK13	0xFF00FF00
-#define MASK02	0x00FF00FF
-#define MUL13(a, x, t)		(t = (a)*(((x)&MASK13)>>8)+128, ((t+((t>>8)&MASK02))>>8)&MASK02)
-#define MUL02(a, x, t)		(t = (a)*(((x)&MASK02)>>0)+128, ((t+((t>>8)&MASK02))>>8)&MASK02)
-#define MUL0123(a, x, s, t)	((MUL13(a, x, s)<<8)|MUL02(a, x, t))
-
-#define MUL2(u, v, x, y)	(t = (u)*(v)+(x)*(y)+256, (t+(t>>8))>>8)
-
-static void mktables(void);
-typedef int Subdraw(Memdrawparam*);
-static Subdraw chardraw, alphadraw, memoptdraw;
-
-static Memimage*	memones;
-static Memimage*	memzeros;
-Memimage *memwhite;
-Memimage *memblack;
-Memimage *memtransparent;
-Memimage *memopaque;
-
-int	__ifmt(Fmt*);
-
-void
-memimageinit(void)
-{
-	static int didinit = 0;
-
-	if(didinit)
-		return;
-
-	didinit = 1;
-
-	mktables();
-	_memmkcmap();
-
-	fmtinstall('R', Rfmt); 
-	fmtinstall('P', Pfmt);
-	fmtinstall('b', __ifmt);
-
-	memones = allocmemimage(Rect(0,0,1,1), GREY1);
-	memones->flags |= Frepl;
-	memones->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
-	*byteaddr(memones, ZP) = ~0;
-
-	memzeros = allocmemimage(Rect(0,0,1,1), GREY1);
-	memzeros->flags |= Frepl;
-	memzeros->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
-	*byteaddr(memzeros, ZP) = 0;
-
-	if(memones == nil || memzeros == nil)
-		assert(0 /*cannot initialize memimage library */);	/* RSC BUG */
-
-	memwhite = memones;
-	memblack = memzeros;
-	memopaque = memones;
-	memtransparent = memzeros;
-}
-
-u32int _imgtorgba(Memimage*, u32int);
-u32int _rgbatoimg(Memimage*, u32int);
-u32int _pixelbits(Memimage*, Point);
-
-#define DBG if(drawdebug)
-static Memdrawparam par;
-
-Memdrawparam*
-_memimagedrawsetup(Memimage *dst, Rectangle r, Memimage *src, Point p0, Memimage *mask, Point p1, int op)
-{
-	if(mask == nil)
-		mask = memopaque;
-
-DBG	print("memimagedraw %p/%luX %R @ %p %p/%luX %P %p/%luX %P... ", dst, dst->chan, r, dst->data->bdata, src, src->chan, p0, mask, mask->chan, p1);
-
-	if(drawclip(dst, &r, src, &p0, mask, &p1, &par.sr, &par.mr) == 0){
-/*		if(drawdebug) */
-/*			iprint("empty clipped rectangle\n"); */
-		return nil;
-	}
-
-	if(op < Clear || op > SoverD){
-/*		if(drawdebug) */
-/*			iprint("op out of range: %d\n", op); */
-		return nil;
-	}
-
-	par.op = op;
-	par.dst = dst;
-	par.r = r;
-	par.src = src;
-	/* par.sr set by drawclip */
-	par.mask = mask;
-	/* par.mr set by drawclip */
-
-	par.state = 0;
-	if(src->flags&Frepl){
-		par.state |= Replsrc;
-		if(Dx(src->r)==1 && Dy(src->r)==1){
-			par.sval = pixelbits(src, src->r.min);
-			par.state |= Simplesrc;
-			par.srgba = _imgtorgba(src, par.sval);
-			par.sdval = _rgbatoimg(dst, par.srgba);
-			if((par.srgba&0xFF) == 0 && (op&DoutS)){
-/*				if (drawdebug) iprint("fill with transparent source\n"); */
-				return nil;	/* no-op successfully handled */
-			}
-			if((par.srgba&0xFF) == 0xFF)
-				par.state |= Fullsrc;
-		}
-	}
-
-	if(mask->flags & Frepl){
-		par.state |= Replmask;
-		if(Dx(mask->r)==1 && Dy(mask->r)==1){
-			par.mval = pixelbits(mask, mask->r.min);
-			if(par.mval == 0 && (op&DoutS)){
-/*				if(drawdebug) iprint("fill with zero mask\n"); */
-				return nil;	/* no-op successfully handled */
-			}
-			par.state |= Simplemask;
-			if(par.mval == ~0)
-				par.state |= Fullmask;
-			par.mrgba = _imgtorgba(mask, par.mval);
-		}
-	}
-
-/*	if(drawdebug) */
-/*		iprint("dr %R sr %R mr %R...", r, par.sr, par.mr); */
-DBG print("draw dr %R sr %R mr %R %lux\n", r, par.sr, par.mr, par.state);
-
-	return &par;
-}
-
-void
-_memimagedraw(Memdrawparam *par)
-{
-	/*
-	 * Now that we've clipped the parameters down to be consistent, we 
-	 * simply try sub-drawing routines in order until we find one that was able
-	 * to handle us.  If the sub-drawing routine returns zero, it means it was
-	 * unable to satisfy the request, so we do not return.
-	 */
-
-	/*
-	 * Hardware support.  Each video driver provides this function,
-	 * which checks to see if there is anything it can help with.
-	 * There could be an if around this checking to see if dst is in video memory.
-	 */
-DBG print("test hwdraw\n");
-	if(hwdraw(par)){
-/*if(drawdebug) iprint("hw handled\n"); */
-DBG print("hwdraw handled\n");
-		return;
-	}
-	/*
-	 * Optimizations using memmove and memset.
-	 */
-DBG print("test memoptdraw\n");
-	if(memoptdraw(par)){
-/*if(drawdebug) iprint("memopt handled\n"); */
-DBG print("memopt handled\n");
-		return;
-	}
-
-	/*
-	 * Character drawing.
-	 * Solid source color being painted through a boolean mask onto a high res image.
-	 */
-DBG print("test chardraw\n");
-	if(chardraw(par)){
-/*if(drawdebug) iprint("chardraw handled\n"); */
-DBG print("chardraw handled\n");
-		return;
-	}
-
-	/*
-	 * General calculation-laden case that does alpha for each pixel.
-	 */
-DBG print("do alphadraw\n");
-	alphadraw(par);
-/*if(drawdebug) iprint("alphadraw handled\n"); */
-DBG print("alphadraw handled\n");
-}
-#undef DBG
-
-/*
- * Clip the destination rectangle further based on the properties of the 
- * source and mask rectangles.  Once the destination rectangle is properly
- * clipped, adjust the source and mask rectangles to be the same size.
- * Then if source or mask is replicated, move its clipped rectangle
- * so that its minimum point falls within the repl rectangle.
- *
- * Return zero if the final rectangle is null.
- */
-int
-drawclip(Memimage *dst, Rectangle *r, Memimage *src, Point *p0, Memimage *mask, Point *p1, Rectangle *sr, Rectangle *mr)
-{
-	Point rmin, delta;
-	int splitcoords;
-	Rectangle omr;
-
-	if(r->min.x>=r->max.x || r->min.y>=r->max.y)
-		return 0;
-	splitcoords = (p0->x!=p1->x) || (p0->y!=p1->y);
-	/* clip to destination */
-	rmin = r->min;
-	if(!rectclip(r, dst->r) || !rectclip(r, dst->clipr))
-		return 0;
-	/* move mask point */
-	p1->x += r->min.x-rmin.x;
-	p1->y += r->min.y-rmin.y;
-	/* move source point */
-	p0->x += r->min.x-rmin.x;
-	p0->y += r->min.y-rmin.y;
-	/* map destination rectangle into source */
-	sr->min = *p0;
-	sr->max.x = p0->x+Dx(*r);
-	sr->max.y = p0->y+Dy(*r);
-	/* sr is r in source coordinates; clip to source */
-	if(!(src->flags&Frepl) && !rectclip(sr, src->r))
-		return 0;
-	if(!rectclip(sr, src->clipr))
-		return 0;
-	/* compute and clip rectangle in mask */
-	if(splitcoords){
-		/* move mask point with source */
-		p1->x += sr->min.x-p0->x;
-		p1->y += sr->min.y-p0->y;
-		mr->min = *p1;
-		mr->max.x = p1->x+Dx(*sr);
-		mr->max.y = p1->y+Dy(*sr);
-		omr = *mr;
-		/* mr is now rectangle in mask; clip it */
-		if(!(mask->flags&Frepl) && !rectclip(mr, mask->r))
-			return 0;
-		if(!rectclip(mr, mask->clipr))
-			return 0;
-		/* reflect any clips back to source */
-		sr->min.x += mr->min.x-omr.min.x;
-		sr->min.y += mr->min.y-omr.min.y;
-		sr->max.x += mr->max.x-omr.max.x;
-		sr->max.y += mr->max.y-omr.max.y;
-		*p1 = mr->min;
-	}else{
-		if(!(mask->flags&Frepl) && !rectclip(sr, mask->r))
-			return 0;
-		if(!rectclip(sr, mask->clipr))
-			return 0;
-		*p1 = sr->min;
-	}
-
-	/* move source clipping back to destination */
-	delta.x = r->min.x - p0->x;
-	delta.y = r->min.y - p0->y;
-	r->min.x = sr->min.x + delta.x;
-	r->min.y = sr->min.y + delta.y;
-	r->max.x = sr->max.x + delta.x;
-	r->max.y = sr->max.y + delta.y;
-
-	/* move source rectangle so sr->min is in src->r */
-	if(src->flags&Frepl) {
-		delta.x = drawreplxy(src->r.min.x, src->r.max.x, sr->min.x) - sr->min.x;
-		delta.y = drawreplxy(src->r.min.y, src->r.max.y, sr->min.y) - sr->min.y;
-		sr->min.x += delta.x;
-		sr->min.y += delta.y;
-		sr->max.x += delta.x;
-		sr->max.y += delta.y;
-	}
-	*p0 = sr->min;
-
-	/* move mask point so it is in mask->r */
-	*p1 = drawrepl(mask->r, *p1);
-	mr->min = *p1;
-	mr->max.x = p1->x+Dx(*sr);
-	mr->max.y = p1->y+Dy(*sr);
-
-	assert(Dx(*sr) == Dx(*mr) && Dx(*mr) == Dx(*r));
-	assert(Dy(*sr) == Dy(*mr) && Dy(*mr) == Dy(*r));
-	assert(ptinrect(*p0, src->r));
-	assert(ptinrect(*p1, mask->r));
-	assert(ptinrect(r->min, dst->r));
-
-	return 1;
-}
-
-/*
- * Conversion tables.
- */
-static uchar replbit[1+8][256];		/* replbit[x][y] is the replication of the x-bit quantity y to 8-bit depth */
-static uchar conv18[256][8];		/* conv18[x][y] is the yth pixel in the depth-1 pixel x */
-static uchar conv28[256][4];		/* ... */
-static uchar conv48[256][2];
-
-/*
- * bitmap of how to replicate n bits to fill 8, for 1 ≤ n ≤ 8.
- * the X's are where to put the bottom (ones) bit of the n-bit pattern.
- * only the top 8 bits of the result are actually used.
- * (the lower 8 bits are needed to get bits in the right place
- * when n is not a divisor of 8.)
- *
- * Should check to see if its easier to just refer to replmul than
- * use the precomputed values in replbit.  On PCs it may well
- * be; on machines with slow multiply instructions it probably isn't.
- */
-#define a ((((((((((((((((0
-#define X *2+1)
-#define _ *2)
-static int replmul[1+8] = {
-	0,
-	a X X X X X X X X X X X X X X X X,
-	a _ X _ X _ X _ X _ X _ X _ X _ X,
-	a _ _ X _ _ X _ _ X _ _ X _ _ X _,
-	a _ _ _ X _ _ _ X _ _ _ X _ _ _ X,
-	a _ _ _ _ X _ _ _ _ X _ _ _ _ X _,
-	a _ _ _ _ _ X _ _ _ _ _ X _ _ _ _, 
-	a _ _ _ _ _ _ X _ _ _ _ _ _ X _ _,
-	a _ _ _ _ _ _ _ X _ _ _ _ _ _ _ X,
-};
-#undef a
-#undef X
-#undef _
-
-static void
-mktables(void)
-{
-	int i, j, mask, sh, small;
-		
-	if(tablesbuilt)
-		return;
-
-	fmtinstall('R', Rfmt);
-	fmtinstall('P', Pfmt);
-	tablesbuilt = 1;
-
-	/* bit replication up to 8 bits */
-	for(i=0; i<256; i++){
-		for(j=0; j<=8; j++){	/* j <= 8 [sic] */
-			small = i & ((1<<j)-1);
-			replbit[j][i] = (small*replmul[j])>>8;
-		}
-	}
-
-	/* bit unpacking up to 8 bits, only powers of 2 */
-	for(i=0; i<256; i++){
-		for(j=0, sh=7, mask=1; j<8; j++, sh--)
-			conv18[i][j] = replbit[1][(i>>sh)&mask];
-
-		for(j=0, sh=6, mask=3; j<4; j++, sh-=2)
-			conv28[i][j] = replbit[2][(i>>sh)&mask];
-
-		for(j=0, sh=4, mask=15; j<2; j++, sh-=4)
-			conv48[i][j] = replbit[4][(i>>sh)&mask];
-	}
-}
-
-static uchar ones = 0xff;
-
-/*
- * General alpha drawing case.  Can handle anything.
- */
-typedef struct	Buffer	Buffer;
-struct Buffer {
-	/* used by most routines */
-	uchar	*red;
-	uchar	*grn;
-	uchar	*blu;
-	uchar	*alpha;
-	uchar	*grey;
-	u32int	*rgba;
-	int	delta;	/* number of bytes to add to pointer to get next pixel to the right */
-
-	/* used by boolcalc* for mask data */
-	uchar	*m;		/* ptr to mask data r.min byte; like p->bytermin */
-	int		mskip;	/* no. of left bits to skip in *m */
-	uchar	*bm;		/* ptr to mask data img->r.min byte; like p->bytey0s */
-	int		bmskip;	/* no. of left bits to skip in *bm */
-	uchar	*em;		/* ptr to mask data img->r.max.x byte; like p->bytey0e */
-	int		emskip;	/* no. of right bits to skip in *em */
-};
-
-typedef struct	Param	Param;
-typedef Buffer	Readfn(Param*, uchar*, int);
-typedef void	Writefn(Param*, uchar*, Buffer);
-typedef Buffer	Calcfn(Buffer, Buffer, Buffer, int, int, int);
-
-enum {
-	MAXBCACHE = 16
-};
-
-/* giant rathole to customize functions with */
-struct Param {
-	Readfn	*replcall;
-	Readfn	*greymaskcall;	
-	Readfn	*convreadcall;
-	Writefn	*convwritecall;
-
-	Memimage *img;
-	Rectangle	r;
-	int	dx;	/* of r */
-	int	needbuf;
-	int	convgrey;
-	int	alphaonly;
-
-	uchar	*bytey0s;		/* byteaddr(Pt(img->r.min.x, img->r.min.y)) */
-	uchar	*bytermin;	/* byteaddr(Pt(r.min.x, img->r.min.y)) */
-	uchar	*bytey0e;		/* byteaddr(Pt(img->r.max.x, img->r.min.y)) */
-	int		bwidth;
-
-	int	replcache;	/* if set, cache buffers */
-	Buffer	bcache[MAXBCACHE];
-	u32int	bfilled;
-	uchar	*bufbase;
-	int	bufoff;
-	int	bufdelta;
-
-	int	dir;
-
-	int	convbufoff;
-	uchar	*convbuf;
-	Param	*convdpar;
-	int	convdx;
-};
-
-static uchar *drawbuf;
-static int	ndrawbuf;
-static int	mdrawbuf;
-static Param spar, mpar, dpar;	/* easier on the stacks */
-static Readfn	greymaskread, replread, readptr;
-static Writefn	nullwrite;
-static Calcfn	alphacalc0, alphacalc14, alphacalc2810, alphacalc3679, alphacalc5, alphacalc11, alphacalcS;
-static Calcfn	boolcalc14, boolcalc236789, boolcalc1011;
-
-static Readfn*	readfn(Memimage*);
-static Readfn*	readalphafn(Memimage*);
-static Writefn*	writefn(Memimage*);
-
-static Calcfn*	boolcopyfn(Memimage*, Memimage*);
-static Readfn*	convfn(Memimage*, Param*, Memimage*, Param*);
-
-static Calcfn *alphacalc[Ncomp] = 
-{
-	alphacalc0,		/* Clear */
-	alphacalc14,		/* DoutS */
-	alphacalc2810,		/* SoutD */
-	alphacalc3679,		/* DxorS */
-	alphacalc14,		/* DinS */
-	alphacalc5,		/* D */
-	alphacalc3679,		/* DatopS */
-	alphacalc3679,		/* DoverS */
-	alphacalc2810,		/* SinD */
-	alphacalc3679,		/* SatopD */
-	alphacalc2810,		/* S */
-	alphacalc11,		/* SoverD */
-};
-
-static Calcfn *boolcalc[Ncomp] =
-{
-	alphacalc0,		/* Clear */
-	boolcalc14,		/* DoutS */
-	boolcalc236789,		/* SoutD */
-	boolcalc236789,		/* DxorS */
-	boolcalc14,		/* DinS */
-	alphacalc5,		/* D */
-	boolcalc236789,		/* DatopS */
-	boolcalc236789,		/* DoverS */
-	boolcalc236789,		/* SinD */
-	boolcalc236789,		/* SatopD */
-	boolcalc1011,		/* S */
-	boolcalc1011,		/* SoverD */
-};
-
-static int
-allocdrawbuf(void)
-{
-	uchar *p;
-
-	if(ndrawbuf > mdrawbuf){
-		p = realloc(drawbuf, ndrawbuf);
-		if(p == nil){
-			werrstr("memimagedraw out of memory");
-			return -1;
-		}
-		drawbuf = p;
-		mdrawbuf = ndrawbuf;
-	}
-	return 0;
-}
-
-static void
-getparam(Param *p, Memimage *img, Rectangle r, int convgrey, int needbuf)
-{
-	int nbuf;
-
-	memset(p, 0, sizeof *p);
-
-	p->img = img;
-	p->r = r;
-	p->dx = Dx(r);
-	p->needbuf = needbuf;
-	p->convgrey = convgrey;
-
-	assert(img->r.min.x <= r.min.x && r.min.x < img->r.max.x);
-
-	p->bytey0s = byteaddr(img, Pt(img->r.min.x, img->r.min.y));
-	p->bytermin = byteaddr(img, Pt(r.min.x, img->r.min.y));
-	p->bytey0e = byteaddr(img, Pt(img->r.max.x, img->r.min.y));
-	p->bwidth = sizeof(u32int)*img->width;
-
-	assert(p->bytey0s <= p->bytermin && p->bytermin <= p->bytey0e);
-
-	if(p->r.min.x == p->img->r.min.x)
-		assert(p->bytermin == p->bytey0s);
-
-	nbuf = 1;
-	if((img->flags&Frepl) && Dy(img->r) <= MAXBCACHE && Dy(img->r) < Dy(r)){
-		p->replcache = 1;
-		nbuf = Dy(img->r);
-	}
-	p->bufdelta = 4*p->dx;
-	p->bufoff = ndrawbuf;
-	ndrawbuf += p->bufdelta*nbuf;
-}
-
-static void
-clipy(Memimage *img, int *y)
-{
-	int dy;
-
-	dy = Dy(img->r);
-	if(*y == dy)
-		*y = 0;
-	else if(*y == -1)
-		*y = dy-1;
-	assert(0 <= *y && *y < dy);
-}
-
-static void
-dumpbuf(char *s, Buffer b, int n)
-{
-	int i;
-	uchar *p;
-	
-	print("%s", s);
-	for(i=0; i<n; i++){
-		print(" ");
-		if(p=b.grey){
-			print(" k%.2uX", *p);
-			b.grey += b.delta;
-		}else{	
-			if(p=b.red){
-				print(" r%.2uX", *p);
-				b.red += b.delta;
-			}
-			if(p=b.grn){
-				print(" g%.2uX", *p);
-				b.grn += b.delta;
-			}
-			if(p=b.blu){
-				print(" b%.2uX", *p);
-				b.blu += b.delta;
-			}
-		}
-		if((p=b.alpha) != &ones){
-			print(" α%.2uX", *p);
-			b.alpha += b.delta;
-		}
-	}
-	print("\n");
-}
-
-/*
- * For each scan line, we expand the pixels from source, mask, and destination
- * into byte-aligned red, green, blue, alpha, and grey channels.  If buffering is not
- * needed and the channels were already byte-aligned (grey8, rgb24, rgba32, rgb32),
- * the readers need not copy the data: they can simply return pointers to the data.
- * If the destination image is grey and the source is not, it is converted using the NTSC
- * formula.
- *
- * Once we have all the channels, we call either rgbcalc or greycalc, depending on 
- * whether the destination image is color.  This is allowed to overwrite the dst buffer (perhaps
- * the actual data, perhaps a copy) with its result.  It should only overwrite the dst buffer
- * with the same format (i.e. red bytes with red bytes, etc.)  A new buffer is returned from
- * the calculator, and that buffer is passed to a function to write it to the destination.
- * If the buffer is already pointing at the destination, the writing function is a no-op.
- */
-#define DBG if(drawdebug)
-static int
-alphadraw(Memdrawparam *par)
-{
-	int isgrey, starty, endy, op;
-	int needbuf, dsty, srcy, masky;
-	int y, dir, dx, dy;
-	Buffer bsrc, bdst, bmask;
-	Readfn *rdsrc, *rdmask, *rddst;
-	Calcfn *calc;
-	Writefn *wrdst;
-	Memimage *src, *mask, *dst;
-	Rectangle r, sr, mr;
-
-	if(drawdebug)
-		print("alphadraw %R\n", par->r);
-	r = par->r;
-	dx = Dx(r);
-	dy = Dy(r);
-
-	ndrawbuf = 0;
-
-	src = par->src;
-	mask = par->mask;	
-	dst = par->dst;
-	sr = par->sr;
-	mr = par->mr;
-	op = par->op;
-
-	isgrey = dst->flags&Fgrey;
-
-	/*
-	 * Buffering when src and dst are the same bitmap is sufficient but not 
-	 * necessary.  There are stronger conditions we could use.  We could
-	 * check to see if the rectangles intersect, and if simply moving in the
-	 * correct y direction can avoid the need to buffer.
-	 */
-	needbuf = (src->data == dst->data);
-
-	getparam(&spar, src, sr, isgrey, needbuf);
-	getparam(&dpar, dst, r, isgrey, needbuf);
-	getparam(&mpar, mask, mr, 0, needbuf);
-
-	dir = (needbuf && byteaddr(dst, r.min) > byteaddr(src, sr.min)) ? -1 : 1;
-	spar.dir = mpar.dir = dpar.dir = dir;
-
-	/*
-	 * If the mask is purely boolean, we can convert from src to dst format
-	 * when we read src, and then just copy it to dst where the mask tells us to.
-	 * This requires a boolean (1-bit grey) mask and lack of a source alpha channel.
-	 *
-	 * The computation is accomplished by assigning the function pointers as follows:
-	 *	rdsrc - read and convert source into dst format in a buffer
-	 * 	rdmask - convert mask to bytes, set pointer to it
-	 * 	rddst - fill with pointer to real dst data, but do no reads
-	 *	calc - copy src onto dst when mask says to.
-	 *	wrdst - do nothing
-	 * This is slightly sleazy, since things aren't doing exactly what their names say,
-	 * but it avoids a fair amount of code duplication to make this a case here
-	 * rather than have a separate booldraw.
-	 */
-/*if(drawdebug) iprint("flag %lud mchan %lux=?%x dd %d\n", src->flags&Falpha, mask->chan, GREY1, dst->depth); */
-	if(!(src->flags&Falpha) && mask->chan == GREY1 && dst->depth >= 8 && op == SoverD){
-/*if(drawdebug) iprint("boolcopy..."); */
-		rdsrc = convfn(dst, &dpar, src, &spar);
-		rddst = readptr;
-		rdmask = readfn(mask);
-		calc = boolcopyfn(dst, mask);
-		wrdst = nullwrite;
-	}else{
-		/* usual alphadraw parameter fetching */
-		rdsrc = readfn(src);
-		rddst = readfn(dst);
-		wrdst = writefn(dst);
-		calc = alphacalc[op];
-
-		/*
-		 * If there is no alpha channel, we'll ask for a grey channel
-		 * and pretend it is the alpha.
-		 */
-		if(mask->flags&Falpha){
-			rdmask = readalphafn(mask);
-			mpar.alphaonly = 1;
-		}else{
-			mpar.greymaskcall = readfn(mask);
-			mpar.convgrey = 1;
-			rdmask = greymaskread;
-
-			/*
-			 * Should really be above, but then boolcopyfns would have
-			 * to deal with bit alignment, and I haven't written that.
-			 *
-			 * This is a common case for things like ellipse drawing.
-			 * When there's no alpha involved and the mask is boolean,
-			 * we can avoid all the division and multiplication.
-			 */
-			if(mask->chan == GREY1 && !(src->flags&Falpha))
-				calc = boolcalc[op];
-			else if(op == SoverD && !(src->flags&Falpha))
-				calc = alphacalcS;
-		}
-	}
-
-	/*
-	 * If the image has a small enough repl rectangle,
-	 * we can just read each line once and cache them.
-	 */
-	if(spar.replcache){
-		spar.replcall = rdsrc;
-		rdsrc = replread;
-	}
-	if(mpar.replcache){
-		mpar.replcall = rdmask;
-		rdmask = replread;
-	}
-
-	if(allocdrawbuf() < 0)
-		return 0;
-
-	/*
-	 * Before we were saving only offsets from drawbuf in the parameter
-	 * structures; now that drawbuf has been grown to accomodate us,
-	 * we can fill in the pointers.
-	 */
-	spar.bufbase = drawbuf+spar.bufoff;
-	mpar.bufbase = drawbuf+mpar.bufoff;
-	dpar.bufbase = drawbuf+dpar.bufoff;
-	spar.convbuf = drawbuf+spar.convbufoff;
-
-	if(dir == 1){
-		starty = 0;
-		endy = dy;
-	}else{
-		starty = dy-1;
-		endy = -1;
-	}
-
-	/*
-	 * srcy, masky, and dsty are offsets from the top of their
-	 * respective Rectangles.  they need to be contained within
-	 * the rectangles, so clipy can keep them there without division.
- 	 */
-	srcy = (starty + sr.min.y - src->r.min.y)%Dy(src->r);
-	masky = (starty + mr.min.y - mask->r.min.y)%Dy(mask->r);
-	dsty = starty + r.min.y - dst->r.min.y;
-
-	assert(0 <= srcy && srcy < Dy(src->r));
-	assert(0 <= masky && masky < Dy(mask->r));
-	assert(0 <= dsty && dsty < Dy(dst->r));
-
-	if(drawdebug)
-		print("alphadraw: rdsrc=%p rdmask=%p rddst=%p calc=%p wrdst=%p\n",
-			rdsrc, rdmask, rddst, calc, wrdst);
-	for(y=starty; y!=endy; y+=dir, srcy+=dir, masky+=dir, dsty+=dir){
-		clipy(src, &srcy);
-		clipy(dst, &dsty);
-		clipy(mask, &masky);
-
-		bsrc = rdsrc(&spar, spar.bufbase, srcy);
-DBG print("[");
-		bmask = rdmask(&mpar, mpar.bufbase, masky);
-DBG print("]\n");
-		bdst = rddst(&dpar, dpar.bufbase, dsty);
-DBG		dumpbuf("src", bsrc, dx);
-DBG		dumpbuf("mask", bmask, dx);
-DBG		dumpbuf("dst", bdst, dx);
-		bdst = calc(bdst, bsrc, bmask, dx, isgrey, op);
-DBG		dumpbuf("bdst", bdst, dx);
-		wrdst(&dpar, dpar.bytermin+dsty*dpar.bwidth, bdst);
-	}
-
-	return 1;
-}
-#undef DBG
-
-static Buffer
-alphacalc0(Buffer bdst, Buffer b1, Buffer b2, int dx, int grey, int op)
-{
-	USED(grey);
-	USED(op);
-	memset(bdst.rgba, 0, dx*bdst.delta);
-	return bdst;
-}
-
-static Buffer
-alphacalc14(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
-{
-	Buffer obdst;
-	int fd, sadelta;
-	int i, sa, ma, q;
-	u32int s, t;
-
-	obdst = bdst;
-	sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta;
-	q = bsrc.delta == 4 && bdst.delta == 4;
-
-	for(i=0; i<dx; i++){
-		sa = *bsrc.alpha;
-		ma = *bmask.alpha;
-		fd = MUL(sa, ma, t);
-		if(op == DoutS)
-			fd = 255-fd;
-
-		if(grey){
-			*bdst.grey = MUL(fd, *bdst.grey, t);
-			bsrc.grey += bsrc.delta;
-			bdst.grey += bdst.delta;
-		}else{
-			if(q){
-				*bdst.rgba = MUL0123(fd, *bdst.rgba, s, t);
-				bsrc.rgba++;
-				bdst.rgba++;
-				bsrc.alpha += sadelta;
-				bmask.alpha += bmask.delta;
-				continue;
-			}
-			*bdst.red = MUL(fd, *bdst.red, t);
-			*bdst.grn = MUL(fd, *bdst.grn, t);
-			*bdst.blu = MUL(fd, *bdst.blu, t);
-			bsrc.red += bsrc.delta;
-			bsrc.blu += bsrc.delta;
-			bsrc.grn += bsrc.delta;
-			bdst.red += bdst.delta;
-			bdst.blu += bdst.delta;
-			bdst.grn += bdst.delta;
-		}
-		if(bdst.alpha != &ones){
-			*bdst.alpha = MUL(fd, *bdst.alpha, t);
-			bdst.alpha += bdst.delta;
-		}
-		bmask.alpha += bmask.delta;
-		bsrc.alpha += sadelta;
-	}
-	return obdst;
-}
-
-static Buffer
-alphacalc2810(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
-{
-	Buffer obdst;
-	int fs, sadelta;
-	int i, ma, da, q;
-	u32int s, t;
-
-	obdst = bdst;
-	sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta;
-	q = bsrc.delta == 4 && bdst.delta == 4;
-
-	for(i=0; i<dx; i++){
-		ma = *bmask.alpha;
-		da = *bdst.alpha;
-		if(op == SoutD)
-			da = 255-da;
-		fs = ma;
-		if(op != S)
-			fs = MUL(fs, da, t);
-
-		if(grey){
-			*bdst.grey = MUL(fs, *bsrc.grey, t);
-			bsrc.grey += bsrc.delta;
-			bdst.grey += bdst.delta;
-		}else{
-			if(q){
-				*bdst.rgba = MUL0123(fs, *bsrc.rgba, s, t);
-				bsrc.rgba++;
-				bdst.rgba++;
-				bmask.alpha += bmask.delta;
-				bdst.alpha += bdst.delta;
-				continue;
-			}
-			*bdst.red = MUL(fs, *bsrc.red, t);
-			*bdst.grn = MUL(fs, *bsrc.grn, t);
-			*bdst.blu = MUL(fs, *bsrc.blu, t);
-			bsrc.red += bsrc.delta;
-			bsrc.blu += bsrc.delta;
-			bsrc.grn += bsrc.delta;
-			bdst.red += bdst.delta;
-			bdst.blu += bdst.delta;
-			bdst.grn += bdst.delta;
-		}
-		if(bdst.alpha != &ones){
-			*bdst.alpha = MUL(fs, *bsrc.alpha, t);
-			bdst.alpha += bdst.delta;
-		}
-		bmask.alpha += bmask.delta;
-		bsrc.alpha += sadelta;
-	}
-	return obdst;
-}
-
-static Buffer
-alphacalc3679(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
-{
-	Buffer obdst;
-	int fs, fd, sadelta;
-	int i, sa, ma, da, q;
-	u32int s, t, u, v;
-
-	obdst = bdst;
-	sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta;
-	q = bsrc.delta == 4 && bdst.delta == 4;
-
-	for(i=0; i<dx; i++){
-		sa = *bsrc.alpha;
-		ma = *bmask.alpha;
-		da = *bdst.alpha;
-		if(op == SatopD)
-			fs = MUL(ma, da, t);
-		else
-			fs = MUL(ma, 255-da, t);
-		if(op == DoverS)
-			fd = 255;
-		else{
-			fd = MUL(sa, ma, t);
-			if(op != DatopS)
-				fd = 255-fd;
-		}
-
-		if(grey){
-			*bdst.grey = MUL(fs, *bsrc.grey, s)+MUL(fd, *bdst.grey, t);
-			bsrc.grey += bsrc.delta;
-			bdst.grey += bdst.delta;
-		}else{
-			if(q){
-				*bdst.rgba = MUL0123(fs, *bsrc.rgba, s, t)+MUL0123(fd, *bdst.rgba, u, v);
-				bsrc.rgba++;
-				bdst.rgba++;
-				bsrc.alpha += sadelta;
-				bmask.alpha += bmask.delta;
-				bdst.alpha += bdst.delta;
-				continue;
-			}
-			*bdst.red = MUL(fs, *bsrc.red, s)+MUL(fd, *bdst.red, t);
-			*bdst.grn = MUL(fs, *bsrc.grn, s)+MUL(fd, *bdst.grn, t);
-			*bdst.blu = MUL(fs, *bsrc.blu, s)+MUL(fd, *bdst.blu, t);
-			bsrc.red += bsrc.delta;
-			bsrc.blu += bsrc.delta;
-			bsrc.grn += bsrc.delta;
-			bdst.red += bdst.delta;
-			bdst.blu += bdst.delta;
-			bdst.grn += bdst.delta;
-		}
-		if(bdst.alpha != &ones){
-			*bdst.alpha = MUL(fs, sa, s)+MUL(fd, da, t);
-			bdst.alpha += bdst.delta;
-		}
-		bmask.alpha += bmask.delta;
-		bsrc.alpha += sadelta;
-	}
-	return obdst;
-}
-
-static Buffer
-alphacalc5(Buffer bdst, Buffer b1, Buffer b2, int dx, int grey, int op)
-{
-	USED(dx);
-	USED(grey);
-	USED(op);
-	return bdst;
-}
-
-static Buffer
-alphacalc11(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
-{
-	Buffer obdst;
-	int fd, sadelta;
-	int i, sa, ma, q;
-	u32int s, t, u, v;
-
-	USED(op);
-	obdst = bdst;
-	sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta;
-	q = bsrc.delta == 4 && bdst.delta == 4;
-
-	for(i=0; i<dx; i++){
-		sa = *bsrc.alpha;
-		ma = *bmask.alpha;
-		fd = 255-MUL(sa, ma, t);
-
-		if(grey){
-			*bdst.grey = MUL(ma, *bsrc.grey, s)+MUL(fd, *bdst.grey, t);
-			bsrc.grey += bsrc.delta;
-			bdst.grey += bdst.delta;
-		}else{
-			if(q){
-				*bdst.rgba = MUL0123(ma, *bsrc.rgba, s, t)+MUL0123(fd, *bdst.rgba, u, v);
-				bsrc.rgba++;
-				bdst.rgba++;
-				bsrc.alpha += sadelta;
-				bmask.alpha += bmask.delta;
-				continue;
-			}
-			*bdst.red = MUL(ma, *bsrc.red, s)+MUL(fd, *bdst.red, t);
-			*bdst.grn = MUL(ma, *bsrc.grn, s)+MUL(fd, *bdst.grn, t);
-			*bdst.blu = MUL(ma, *bsrc.blu, s)+MUL(fd, *bdst.blu, t);
-			bsrc.red += bsrc.delta;
-			bsrc.blu += bsrc.delta;
-			bsrc.grn += bsrc.delta;
-			bdst.red += bdst.delta;
-			bdst.blu += bdst.delta;
-			bdst.grn += bdst.delta;
-		}
-		if(bdst.alpha != &ones){
-			*bdst.alpha = MUL(ma, sa, s)+MUL(fd, *bdst.alpha, t);
-			bdst.alpha += bdst.delta;
-		}
-		bmask.alpha += bmask.delta;
-		bsrc.alpha += sadelta;
-	}
-	return obdst;
-}
-
-/*
-not used yet
-source and mask alpha 1
-static Buffer
-alphacalcS0(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
-{
-	Buffer obdst;
-	int i;
-
-	USED(op);
-	obdst = bdst;
-	if(bsrc.delta == bdst.delta){
-		memmove(bdst.rgba, bsrc.rgba, dx*bdst.delta);
-		return obdst;
-	}
-	for(i=0; i<dx; i++){
-		if(grey){
-			*bdst.grey = *bsrc.grey;
-			bsrc.grey += bsrc.delta;
-			bdst.grey += bdst.delta;
-		}else{
-			*bdst.red = *bsrc.red;
-			*bdst.grn = *bsrc.grn;
-			*bdst.blu = *bsrc.blu;
-			bsrc.red += bsrc.delta;
-			bsrc.blu += bsrc.delta;
-			bsrc.grn += bsrc.delta;
-			bdst.red += bdst.delta;
-			bdst.blu += bdst.delta;
-			bdst.grn += bdst.delta;
-		}
-		if(bdst.alpha != &ones){
-			*bdst.alpha = 255;
-			bdst.alpha += bdst.delta;
-		}
-	}
-	return obdst;
-}
-*/
-
-/* source alpha 1 */
-static Buffer
-alphacalcS(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
-{
-	Buffer obdst;
-	int fd;
-	int i, ma;
-	u32int s, t;
-
-	USED(op);
-	obdst = bdst;
-
-	for(i=0; i<dx; i++){
-		ma = *bmask.alpha;
-		fd = 255-ma;
-
-		if(grey){
-			*bdst.grey = MUL(ma, *bsrc.grey, s)+MUL(fd, *bdst.grey, t);
-			bsrc.grey += bsrc.delta;
-			bdst.grey += bdst.delta;
-		}else{
-			*bdst.red = MUL(ma, *bsrc.red, s)+MUL(fd, *bdst.red, t);
-			*bdst.grn = MUL(ma, *bsrc.grn, s)+MUL(fd, *bdst.grn, t);
-			*bdst.blu = MUL(ma, *bsrc.blu, s)+MUL(fd, *bdst.blu, t);
-			bsrc.red += bsrc.delta;
-			bsrc.blu += bsrc.delta;
-			bsrc.grn += bsrc.delta;
-			bdst.red += bdst.delta;
-			bdst.blu += bdst.delta;
-			bdst.grn += bdst.delta;
-		}
-		if(bdst.alpha != &ones){
-			*bdst.alpha = ma+MUL(fd, *bdst.alpha, t);
-			bdst.alpha += bdst.delta;
-		}
-		bmask.alpha += bmask.delta;
-	}
-	return obdst;
-}
-
-static Buffer
-boolcalc14(Buffer bdst, Buffer b1, Buffer bmask, int dx, int grey, int op)
-{
-	Buffer obdst;
-	int i, ma, zero;
-
-	obdst = bdst;
-
-	for(i=0; i<dx; i++){
-		ma = *bmask.alpha;
-		zero = ma ? op == DoutS : op == DinS;
-
-		if(grey){
-			if(zero)
-				*bdst.grey = 0;
-			bdst.grey += bdst.delta;
-		}else{
-			if(zero)
-				*bdst.red = *bdst.grn = *bdst.blu = 0;
-			bdst.red += bdst.delta;
-			bdst.blu += bdst.delta;
-			bdst.grn += bdst.delta;
-		}
-		bmask.alpha += bmask.delta;
-		if(bdst.alpha != &ones){
-			if(zero)
-				*bdst.alpha = 0;
-			bdst.alpha += bdst.delta;
-		}
-	}
-	return obdst;
-}
-
-static Buffer
-boolcalc236789(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
-{
-	Buffer obdst;
-	int fs, fd;
-	int i, ma, da, zero;
-	u32int s, t;
-
-	obdst = bdst;
-	zero = !(op&1);
-
-	for(i=0; i<dx; i++){
-		ma = *bmask.alpha;
-		da = *bdst.alpha;
-		fs = da;
-		if(op&2)
-			fs = 255-da;
-		fd = 0;
-		if(op&4)
-			fd = 255;
-
-		if(grey){
-			if(ma)
-				*bdst.grey = MUL(fs, *bsrc.grey, s)+MUL(fd, *bdst.grey, t);
-			else if(zero)
-				*bdst.grey = 0;
-			bsrc.grey += bsrc.delta;
-			bdst.grey += bdst.delta;
-		}else{
-			if(ma){
-				*bdst.red = MUL(fs, *bsrc.red, s)+MUL(fd, *bdst.red, t);
-				*bdst.grn = MUL(fs, *bsrc.grn, s)+MUL(fd, *bdst.grn, t);
-				*bdst.blu = MUL(fs, *bsrc.blu, s)+MUL(fd, *bdst.blu, t);
-			}
-			else if(zero)
-				*bdst.red = *bdst.grn = *bdst.blu = 0;
-			bsrc.red += bsrc.delta;
-			bsrc.blu += bsrc.delta;
-			bsrc.grn += bsrc.delta;
-			bdst.red += bdst.delta;
-			bdst.blu += bdst.delta;
-			bdst.grn += bdst.delta;
-		}
-		bmask.alpha += bmask.delta;
-		if(bdst.alpha != &ones){
-			if(ma)
-				*bdst.alpha = fs+MUL(fd, da, t);
-			else if(zero)
-				*bdst.alpha = 0;
-			bdst.alpha += bdst.delta;
-		}
-	}
-	return obdst;
-}
-
-static Buffer
-boolcalc1011(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
-{
-	Buffer obdst;
-	int i, ma, zero;
-
-	obdst = bdst;
-	zero = !(op&1);
-
-	for(i=0; i<dx; i++){
-		ma = *bmask.alpha;
-
-		if(grey){
-			if(ma)
-				*bdst.grey = *bsrc.grey;
-			else if(zero)
-				*bdst.grey = 0;
-			bsrc.grey += bsrc.delta;
-			bdst.grey += bdst.delta;
-		}else{
-			if(ma){
-				*bdst.red = *bsrc.red;
-				*bdst.grn = *bsrc.grn;
-				*bdst.blu = *bsrc.blu;
-			}
-			else if(zero)
-				*bdst.red = *bdst.grn = *bdst.blu = 0;
-			bsrc.red += bsrc.delta;
-			bsrc.blu += bsrc.delta;
-			bsrc.grn += bsrc.delta;
-			bdst.red += bdst.delta;
-			bdst.blu += bdst.delta;
-			bdst.grn += bdst.delta;
-		}
-		bmask.alpha += bmask.delta;
-		if(bdst.alpha != &ones){
-			if(ma)
-				*bdst.alpha = 255;
-			else if(zero)
-				*bdst.alpha = 0;
-			bdst.alpha += bdst.delta;
-		}
-	}
-	return obdst;
-}
-/*
- * Replicated cached scan line read.  Call the function listed in the Param,
- * but cache the result so that for replicated images we only do the work once.
- */
-static Buffer
-replread(Param *p, uchar *s, int y)
-{
-	Buffer *b;
-
-	USED(s);
-	b = &p->bcache[y];
-	if((p->bfilled & (1<<y)) == 0){
-		p->bfilled |= 1<<y;
-		*b = p->replcall(p, p->bufbase+y*p->bufdelta, y);
-	}
-	return *b;
-}
-
-/*
- * Alpha reading function that simply relabels the grey pointer.
- */
-static Buffer
-greymaskread(Param *p, uchar *buf, int y)
-{
-	Buffer b;
-
-	b = p->greymaskcall(p, buf, y);
-	b.alpha = b.grey;
-	return b;
-}
-
-#define DBG if(0)
-static Buffer
-readnbit(Param *p, uchar *buf, int y)
-{
-	Buffer b;
-	Memimage *img;
-	uchar *repl, *r, *w, *ow, bits;
-	int i, n, sh, depth, x, dx, npack, nbits;
-
-	memset(&b, 0, sizeof b);
-	b.rgba = (u32int*)buf;
-	b.grey = w = buf;
-	b.red = b.blu = b.grn = w;
-	b.alpha = &ones;
-	b.delta = 1;
-
-	dx = p->dx;
-	img = p->img;
-	depth = img->depth;
-	repl = &replbit[depth][0];
-	npack = 8/depth;
-	sh = 8-depth;
-
-	/* copy from p->r.min.x until end of repl rectangle */
-	x = p->r.min.x;
-	n = dx;
-	if(n > p->img->r.max.x - x)
-		n = p->img->r.max.x - x;
-
-	r = p->bytermin + y*p->bwidth;
-DBG print("readnbit dx %d %p=%p+%d*%d, *r=%d fetch %d ", dx, r, p->bytermin, y, p->bwidth, *r, n);
-	bits = *r++;
-	nbits = 8;
-	if(i=x&(npack-1)){
-DBG print("throwaway %d...", i);
-		bits <<= depth*i;
-		nbits -= depth*i;
-	}
-	for(i=0; i<n; i++){
-		if(nbits == 0){
-DBG print("(%.2ux)...", *r);
-			bits = *r++;
-			nbits = 8;
-		}
-		*w++ = repl[bits>>sh];
-DBG print("bit %x...", repl[bits>>sh]);
-		bits <<= depth;
-		nbits -= depth;
-	}
-	dx -= n;
-	if(dx == 0)
-		return b;
-
-	assert(x+i == p->img->r.max.x);
-
-	/* copy from beginning of repl rectangle until where we were before. */
-	x = p->img->r.min.x;
-	n = dx;
-	if(n > p->r.min.x - x)
-		n = p->r.min.x - x;
-
-	r = p->bytey0s + y*p->bwidth;
-DBG print("x=%d r=%p...", x, r);
-	bits = *r++;
-	nbits = 8;
-	if(i=x&(npack-1)){
-		bits <<= depth*i;
-		nbits -= depth*i;
-	}
-DBG print("nbits=%d...", nbits);
-	for(i=0; i<n; i++){
-		if(nbits == 0){
-			bits = *r++;
-			nbits = 8;
-		}
-		*w++ = repl[bits>>sh];
-DBG print("bit %x...", repl[bits>>sh]);
-		bits <<= depth;
-		nbits -= depth;
-DBG print("bits %x nbits %d...", bits, nbits);
-	}
-	dx -= n;
-	if(dx == 0)
-		return b;
-
-	assert(dx > 0);
-	/* now we have exactly one full scan line: just replicate the buffer itself until we are done */
-	ow = buf;
-	while(dx--)
-		*w++ = *ow++;
-
-	return b;
-}
-#undef DBG
-
-#define DBG if(0)
-static void
-writenbit(Param *p, uchar *w, Buffer src)
-{
-	uchar *r;
-	u32int bits;
-	int i, sh, depth, npack, nbits, x, ex;
-
-	assert(src.grey != nil && src.delta == 1);
-
-	x = p->r.min.x;
-	ex = x+p->dx;
-	depth = p->img->depth;
-	npack = 8/depth;
-
-	i=x&(npack-1);
-	bits = i ? (*w >> (8-depth*i)) : 0;
-	nbits = depth*i;
-	sh = 8-depth;
-	r = src.grey;
-
-	for(; x<ex; x++){
-		bits <<= depth;
-DBG print(" %x", *r);
-		bits |= (*r++ >> sh);
-		nbits += depth;
-		if(nbits == 8){
-			*w++ = bits;
-			nbits = 0;
-		}
-	}
-
-	if(nbits){
-		sh = 8-nbits;
-		bits <<= sh;
-		bits |= *w & ((1<<sh)-1);
-		*w = bits;
-	}
-DBG print("\n");
-	return;
-}
-#undef DBG
-
-static Buffer
-readcmap(Param *p, uchar *buf, int y)
-{
-	Buffer b;
-	int a, convgrey, copyalpha, dx, i, m;
-	uchar *q, *cmap, *begin, *end, *r, *w;
-
-	memset(&b, 0, sizeof b);
-	begin = p->bytey0s + y*p->bwidth;
-	r = p->bytermin + y*p->bwidth;
-	end = p->bytey0e + y*p->bwidth;
-	cmap = p->img->cmap->cmap2rgb;
-	convgrey = p->convgrey;
-	copyalpha = (p->img->flags&Falpha) ? 1 : 0;
-
-	w = buf;
-	dx = p->dx;
-	if(copyalpha){
-		b.alpha = buf++;
-		a = p->img->shift[CAlpha]/8;
-		m = p->img->shift[CMap]/8;
-		for(i=0; i<dx; i++){
-			*w++ = r[a];
-			q = cmap+r[m]*3;
-			r += 2;
-			if(r == end)
-				r = begin;
-			if(convgrey){
-				*w++ = RGB2K(q[0], q[1], q[2]);
-			}else{
-				*w++ = q[2];	/* blue */
-				*w++ = q[1];	/* green */
-				*w++ = q[0];	/* red */
-			}
-		}
-	}else{
-		b.alpha = &ones;
-		for(i=0; i<dx; i++){
-			q = cmap+*r++*3;
-			if(r == end)
-				r = begin;
-			if(convgrey){
-				*w++ = RGB2K(q[0], q[1], q[2]);
-			}else{
-				*w++ = q[2];	/* blue */
-				*w++ = q[1];	/* green */
-				*w++ = q[0];	/* red */
-			}
-		}
-	}
-
-	b.rgba = (u32int*)(buf-copyalpha);
-
-	if(convgrey){
-		b.grey = buf;
-		b.red = b.blu = b.grn = buf;
-		b.delta = 1+copyalpha;
-	}else{
-		b.blu = buf;
-		b.grn = buf+1;
-		b.red = buf+2;
-		b.grey = nil;
-		b.delta = 3+copyalpha;
-	}
-	return b;
-}
-
-static void
-writecmap(Param *p, uchar *w, Buffer src)
-{
-	uchar *cmap, *red, *grn, *blu;
-	int i, dx, delta;
-
-	cmap = p->img->cmap->rgb2cmap;
-	
-	delta = src.delta;
-	red= src.red;
-	grn = src.grn;
-	blu = src.blu;
-
-	dx = p->dx;
-	for(i=0; i<dx; i++, red+=delta, grn+=delta, blu+=delta)
-		*w++ = cmap[(*red>>4)*256+(*grn>>4)*16+(*blu>>4)];
-}
-
-#define DBG if(drawdebug)
-static Buffer
-readbyte(Param *p, uchar *buf, int y)
-{
-	Buffer b;
-	Memimage *img;
-	int dx, isgrey, convgrey, alphaonly, copyalpha, i, nb;
-	uchar *begin, *end, *r, *w, *rrepl, *grepl, *brepl, *arepl, *krepl;
-	uchar ured, ugrn, ublu;
-	u32int u;
-
-	img = p->img;
-	begin = p->bytey0s + y*p->bwidth;
-	r = p->bytermin + y*p->bwidth;
-	end = p->bytey0e + y*p->bwidth;
-
-	w = buf;
-	dx = p->dx;
-	nb = img->depth/8;
-
-	convgrey = p->convgrey;	/* convert rgb to grey */
-	isgrey = img->flags&Fgrey;
-	alphaonly = p->alphaonly;
-	copyalpha = (img->flags&Falpha) ? 1 : 0;
-
-	/* if we can, avoid processing everything */
-	if(!(img->flags&Frepl) && !convgrey && (img->flags&Fbytes)){
-		memset(&b, 0, sizeof b);
-		if(p->needbuf){
-			memmove(buf, r, dx*nb);
-			r = buf;
-		}
-		b.rgba = (u32int*)r;
-		if(copyalpha)
-			b.alpha = r+img->shift[CAlpha]/8;
-		else
-			b.alpha = &ones;
-		if(isgrey){
-			b.grey = r+img->shift[CGrey]/8;
-			b.red = b.grn = b.blu = b.grey;
-		}else{
-			b.red = r+img->shift[CRed]/8;
-			b.grn = r+img->shift[CGreen]/8;
-			b.blu = r+img->shift[CBlue]/8;
-		}
-		b.delta = nb;
-		return b;
-	}
-
-	rrepl = replbit[img->nbits[CRed]];
-	grepl = replbit[img->nbits[CGreen]];
-	brepl = replbit[img->nbits[CBlue]];
-	arepl = replbit[img->nbits[CAlpha]];
-	krepl = replbit[img->nbits[CGrey]];
-
-	for(i=0; i<dx; i++){
-		u = r[0] | (r[1]<<8) | (r[2]<<16) | (r[3]<<24);
-		if(copyalpha)
-			*w++ = arepl[(u>>img->shift[CAlpha]) & img->mask[CAlpha]];
-
-		if(isgrey)
-			*w++ = krepl[(u >> img->shift[CGrey]) & img->mask[CGrey]];
-		else if(!alphaonly){
-			ured = rrepl[(u >> img->shift[CRed]) & img->mask[CRed]];
-			ugrn = grepl[(u >> img->shift[CGreen]) & img->mask[CGreen]];
-			ublu = brepl[(u >> img->shift[CBlue]) & img->mask[CBlue]];
-			if(convgrey){
-				*w++ = RGB2K(ured, ugrn, ublu);
-			}else{
-				*w++ = brepl[(u >> img->shift[CBlue]) & img->mask[CBlue]];
-				*w++ = grepl[(u >> img->shift[CGreen]) & img->mask[CGreen]];
-				*w++ = rrepl[(u >> img->shift[CRed]) & img->mask[CRed]];
-			}
-		}
-		r += nb;
-		if(r == end)
-			r = begin;
-	}
-	
-	b.alpha = copyalpha ? buf : &ones;
-	b.rgba = (u32int*)buf;
-	if(alphaonly){
-		b.red = b.grn = b.blu = b.grey = nil;
-		if(!copyalpha)
-			b.rgba = nil;
-		b.delta = 1;
-	}else if(isgrey || convgrey){
-		b.grey = buf+copyalpha;
-		b.red = b.grn = b.blu = buf+copyalpha;
-		b.delta = copyalpha+1;
-	}else{
-		b.blu = buf+copyalpha;
-		b.grn = buf+copyalpha+1;
-		b.grey = nil;
-		b.red = buf+copyalpha+2;
-		b.delta = copyalpha+3;
-	}
-	return b;
-}
-#undef DBG
-
-#define DBG if(drawdebug)
-static void
-writebyte(Param *p, uchar *w, Buffer src)
-{
-	Memimage *img;
-	int i, isalpha, isgrey, nb, delta, dx, adelta;
-	uchar ff, *red, *grn, *blu, *grey, *alpha;
-	u32int u, mask;
-
-	img = p->img;
-
-	red = src.red;
-	grn = src.grn;
-	blu = src.blu;
-	alpha = src.alpha;
-	delta = src.delta;
-	grey = src.grey;
-	dx = p->dx;
-
-	nb = img->depth/8;
-	mask = (nb==4) ? 0 : ~((1<<img->depth)-1);
-
-	isalpha = img->flags&Falpha;
-	isgrey = img->flags&Fgrey;
-	adelta = src.delta;
-
-	if(isalpha && (alpha == nil || alpha == &ones)){
-		ff = 0xFF;
-		alpha = &ff;
-		adelta = 0;
-	}
-
-	for(i=0; i<dx; i++){
-		u = w[0] | (w[1]<<8) | (w[2]<<16) | (w[3]<<24);
-DBG print("u %.8lux...", u);
-		u &= mask;
-DBG print("&mask %.8lux...", u);
-		if(isgrey){
-			u |= ((*grey >> (8-img->nbits[CGrey])) & img->mask[CGrey]) << img->shift[CGrey];
-DBG print("|grey %.8lux...", u);
-			grey += delta;
-		}else{
-			u |= ((*red >> (8-img->nbits[CRed])) & img->mask[CRed]) << img->shift[CRed];
-			u |= ((*grn >> (8-img->nbits[CGreen])) & img->mask[CGreen]) << img->shift[CGreen];
-			u |= ((*blu >> (8-img->nbits[CBlue])) & img->mask[CBlue]) << img->shift[CBlue];
-			red += delta;
-			grn += delta;
-			blu += delta;
-DBG print("|rgb %.8lux...", u);
-		}
-
-		if(isalpha){
-			u |= ((*alpha >> (8-img->nbits[CAlpha])) & img->mask[CAlpha]) << img->shift[CAlpha];
-			alpha += adelta;
-DBG print("|alpha %.8lux...", u);
-		}
-
-		w[0] = u;
-		w[1] = u>>8;
-		w[2] = u>>16;
-		w[3] = u>>24;
-DBG print("write back %.8lux...", u);
-		w += nb;
-	}
-}
-#undef DBG
-
-static Readfn*
-readfn(Memimage *img)
-{
-	if(img->depth < 8)
-		return readnbit;
-	if(img->nbits[CMap] == 8)
-		return readcmap;
-	return readbyte;
-}
-
-static Readfn*
-readalphafn(Memimage *m)
-{
-	USED(m);
-	return readbyte;
-}
-
-static Writefn*
-writefn(Memimage *img)
-{
-	if(img->depth < 8)
-		return writenbit;
-	if(img->chan == CMAP8)
-		return writecmap;
-	return writebyte;
-}
-
-static void
-nullwrite(Param *p, uchar *s, Buffer b)
-{
-	USED(p);
-	USED(s);
-}
-
-static Buffer
-readptr(Param *p, uchar *s, int y)
-{
-	Buffer b;
-	uchar *q;
-
-	USED(s);
-	memset(&b, 0, sizeof b);
-	q = p->bytermin + y*p->bwidth;
-	b.red = q;	/* ptr to data */
-	b.grn = b.blu = b.grey = b.alpha = nil;
-	b.rgba = (u32int*)q;
-	b.delta = p->img->depth/8;
-	return b;
-}
-
-static Buffer
-boolmemmove(Buffer bdst, Buffer bsrc, Buffer b1, int dx, int i, int o)
-{
-	USED(i);
-	USED(o);
-	memmove(bdst.red, bsrc.red, dx*bdst.delta);
-	return bdst;
-}
-
-static Buffer
-boolcopy8(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o)
-{
-	uchar *m, *r, *w, *ew;
-
-	USED(i);
-	USED(o);
-	m = bmask.grey;
-	w = bdst.red;
-	r = bsrc.red;
-	ew = w+dx;
-	for(; w < ew; w++,r++)
-		if(*m++)
-			*w = *r;
-	return bdst;	/* not used */
-}
-
-static Buffer
-boolcopy16(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o)
-{
-	uchar *m;
-	ushort *r, *w, *ew;
-
-	USED(i);
-	USED(o);
-	m = bmask.grey;
-	w = (ushort*)bdst.red;
-	r = (ushort*)bsrc.red;
-	ew = w+dx;
-	for(; w < ew; w++,r++)
-		if(*m++)
-			*w = *r;
-	return bdst;	/* not used */
-}
-
-static Buffer
-boolcopy24(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o)
-{
-	uchar *m;
-	uchar *r, *w, *ew;
-
-	USED(i);
-	USED(o);
-	m = bmask.grey;
-	w = bdst.red;
-	r = bsrc.red;
-	ew = w+dx*3;
-	while(w < ew){
-		if(*m++){
-			*w++ = *r++;
-			*w++ = *r++;
-			*w++ = *r++;
-		}else{
-			w += 3;
-			r += 3;
-		}
-	}
-	return bdst;	/* not used */
-}
-
-static Buffer
-boolcopy32(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o)
-{
-	uchar *m;
-	u32int *r, *w, *ew;
-
-	USED(i);
-	USED(o);
-	m = bmask.grey;
-	w = (u32int*)bdst.red;
-	r = (u32int*)bsrc.red;
-	ew = w+dx;
-	for(; w < ew; w++,r++)
-		if(*m++)
-			*w = *r;
-	return bdst;	/* not used */
-}
-
-static Buffer
-genconv(Param *p, uchar *buf, int y)
-{
-	Buffer b;
-	int nb;
-	uchar *r, *w, *ew;
-
-	/* read from source into RGB format in convbuf */
-	b = p->convreadcall(p, p->convbuf, y);
-
-	/* write RGB format into dst format in buf */
-	p->convwritecall(p->convdpar, buf, b);
-
-	if(p->convdx){
-		nb = p->convdpar->img->depth/8;
-		r = buf;
-		w = buf+nb*p->dx;
-		ew = buf+nb*p->convdx;
-		while(w<ew)
-			*w++ = *r++;
-	}
-
-	b.red = buf;
-	b.blu = b.grn = b.grey = b.alpha = nil;
-	b.rgba = (u32int*)buf;
-	b.delta = 0;
-	
-	return b;
-}
-
-static Readfn*
-convfn(Memimage *dst, Param *dpar, Memimage *src, Param *spar)
-{
-	if(dst->chan == src->chan && !(src->flags&Frepl)){
-/*if(drawdebug) iprint("readptr..."); */
-		return readptr;
-	}
-
-	if(dst->chan==CMAP8 && (src->chan==GREY1||src->chan==GREY2||src->chan==GREY4)){
-		/* cheat because we know the replicated value is exactly the color map entry. */
-/*if(drawdebug) iprint("Readnbit..."); */
-		return readnbit;
-	}
-
-	spar->convreadcall = readfn(src);
-	spar->convwritecall = writefn(dst);
-	spar->convdpar = dpar;
-
-	/* allocate a conversion buffer */
-	spar->convbufoff = ndrawbuf;
-	ndrawbuf += spar->dx*4;
-
-	if(spar->dx > Dx(spar->img->r)){
-		spar->convdx = spar->dx;
-		spar->dx = Dx(spar->img->r);
-	}
-
-/*if(drawdebug) iprint("genconv..."); */
-	return genconv;
-}
-
-/*
- * Do NOT call this directly.  pixelbits is a wrapper
- * around this that fetches the bits from the X server
- * when necessary.
- */
-u32int
-_pixelbits(Memimage *i, Point pt)
-{
-	uchar *p;
-	u32int val;
-	int off, bpp, npack;
-
-	val = 0;
-	p = byteaddr(i, pt);
-	switch(bpp=i->depth){
-	case 1:
-	case 2:
-	case 4:
-		npack = 8/bpp;
-		off = pt.x%npack;
-		val = p[0] >> bpp*(npack-1-off);
-		val &= (1<<bpp)-1;
-		break;
-	case 8:
-		val = p[0];
-		break;
-	case 16:
-		val = p[0]|(p[1]<<8);
-		break;
-	case 24:
-		val = p[0]|(p[1]<<8)|(p[2]<<16);
-		break;
-	case 32:
-		val = p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24);
-		break;
-	}
-	while(bpp<32){
-		val |= val<<bpp;
-		bpp *= 2;
-	}
-	return val;
-}
-
-static Calcfn*
-boolcopyfn(Memimage *img, Memimage *mask)
-{
-	if(mask->flags&Frepl && Dx(mask->r)==1 && Dy(mask->r)==1 && pixelbits(mask, mask->r.min)==~0)
-		return boolmemmove;
-
-	switch(img->depth){
-	case 8:
-		return boolcopy8;
-	case 16:
-		return boolcopy16;
-	case 24:
-		return boolcopy24;
-	case 32:
-		return boolcopy32;
-	default:
-		assert(0 /* boolcopyfn */);
-	}
-	return 0;
-}
-
-/*
- * Optimized draw for filling and scrolling; uses memset and memmove.
- */
-static void
-memsets(void *vp, ushort val, int n)
-{
-	ushort *p, *ep;
-
-	p = vp;
-	ep = p+n;
-	while(p<ep)
-		*p++ = val;
-}
-
-static void
-memsetl(void *vp, u32int val, int n)
-{
-	u32int *p, *ep;
-
-	p = vp;
-	ep = p+n;
-	while(p<ep)
-		*p++ = val;
-}
-
-static void
-memset24(void *vp, u32int val, int n)
-{
-	uchar *p, *ep;
-	uchar a,b,c;
-
-	p = vp;
-	ep = p+3*n;
-	a = val;
-	b = val>>8;
-	c = val>>16;
-	while(p<ep){
-		*p++ = a;
-		*p++ = b;
-		*p++ = c;
-	}
-}
-
-u32int
-_imgtorgba(Memimage *img, u32int val)
-{
-	uchar r, g, b, a;
-	int nb, ov, v;
-	u32int chan;
-	uchar *p;
-
-	a = 0xFF;
-	r = g = b = 0xAA;	/* garbage */
-	for(chan=img->chan; chan; chan>>=8){
-		nb = NBITS(chan);
-		ov = v = val&((1<<nb)-1);
-		val >>= nb;
-
-		while(nb < 8){
-			v |= v<<nb;
-			nb *= 2;
-		}
-		v >>= (nb-8);
-
-		switch(TYPE(chan)){
-		case CRed:
-			r = v;
-			break;
-		case CGreen:
-			g = v;
-			break;
-		case CBlue:
-			b = v;
-			break;
-		case CAlpha:
-			a = v;
-			break;
-		case CGrey:
-			r = g = b = v;
-			break;
-		case CMap:
-			p = img->cmap->cmap2rgb+3*ov;
-			r = *p++;
-			g = *p++;	
-			b = *p;
-			break;
-		}
-	}
-	return (r<<24)|(g<<16)|(b<<8)|a;	
-}
-
-u32int
-_rgbatoimg(Memimage *img, u32int rgba)
-{
-	u32int chan;
-	int d, nb;
-	u32int v;
-	uchar *p, r, g, b, a, m;
-
-	v = 0;
-	r = rgba>>24;
-	g = rgba>>16;
-	b = rgba>>8;
-	a = rgba;
-	d = 0;
-	for(chan=img->chan; chan; chan>>=8){
-		nb = NBITS(chan);
-		switch(TYPE(chan)){
-		case CRed:
-			v |= (r>>(8-nb))<<d;
-			break;
-		case CGreen:
-			v |= (g>>(8-nb))<<d;
-			break;
-		case CBlue:
-			v |= (b>>(8-nb))<<d;
-			break;
-		case CAlpha:
-			v |= (a>>(8-nb))<<d;
-			break;
-		case CMap:
-			p = img->cmap->rgb2cmap;
-			m = p[(r>>4)*256+(g>>4)*16+(b>>4)];
-			v |= (m>>(8-nb))<<d;
-			break;
-		case CGrey:
-			m = RGB2K(r,g,b);
-			v |= (m>>(8-nb))<<d;
-			break;
-		}
-		d += nb;
-	}
-/*	print("rgba2img %.8lux = %.*lux\n", rgba, 2*d/8, v); */
-	return v;
-}
-
-#define DBG if(0)
-static int
-memoptdraw(Memdrawparam *par)
-{
-	int m, y, dy, dx, op;
-	u32int v;
-	Memimage *src;
-	Memimage *dst;
-
-	dx = Dx(par->r);
-	dy = Dy(par->r);
-	src = par->src;
-	dst = par->dst;
-	op = par->op;
-
-DBG print("state %lux mval %lux dd %d\n", par->state, par->mval, dst->depth);
-	/*
-	 * If we have an opaque mask and source is one opaque pixel we can convert to the
-	 * destination format and just replicate with memset.
-	 */
-	m = Simplesrc|Simplemask|Fullmask;
-	if((par->state&m)==m && (par->srgba&0xFF) == 0xFF && (op ==S || op == SoverD)){
-		uchar *dp, p[4];
-		int d, dwid, ppb, np, nb;
-		uchar lm, rm;
-
-DBG print("memopt, dst %p, dst->data->bdata %p\n", dst, dst->data->bdata);
-		dwid = dst->width*sizeof(u32int);
-		dp = byteaddr(dst, par->r.min);
-		v = par->sdval;
-DBG print("sdval %lud, depth %d\n", v, dst->depth);
-		switch(dst->depth){
-		case 1:
-		case 2:
-		case 4:
-			for(d=dst->depth; d<8; d*=2)
-				v |= (v<<d);
-			ppb = 8/dst->depth;	/* pixels per byte */
-			m = ppb-1;
-			/* left edge */
-			np = par->r.min.x&m;		/* no. pixels unused on left side of word */
-			dx -= (ppb-np);
-			nb = 8 - np * dst->depth;		/* no. bits used on right side of word */
-			lm = (1<<nb)-1;
-DBG print("np %d x %d nb %d lm %ux ppb %d m %ux\n", np, par->r.min.x, nb, lm, ppb, m);	
-
-			/* right edge */
-			np = par->r.max.x&m;	/* no. pixels used on left side of word */
-			dx -= np;
-			nb = 8 - np * dst->depth;		/* no. bits unused on right side of word */
-			rm = ~((1<<nb)-1);
-DBG print("np %d x %d nb %d rm %ux ppb %d m %ux\n", np, par->r.max.x, nb, rm, ppb, m);	
-
-DBG print("dx %d Dx %d\n", dx, Dx(par->r));
-			/* lm, rm are masks that are 1 where we should touch the bits */
-			if(dx < 0){	/* just one byte */
-				lm &= rm;
-				for(y=0; y<dy; y++, dp+=dwid)
-					*dp ^= (v ^ *dp) & lm;
-			}else if(dx == 0){	/* no full bytes */
-				if(lm)
-					dwid--;
-
-				for(y=0; y<dy; y++, dp+=dwid){
-					if(lm){
-DBG print("dp %p v %lux lm %ux (v ^ *dp) & lm %lux\n", dp, v, lm, (v^*dp)&lm);
-						*dp ^= (v ^ *dp) & lm;
-						dp++;
-					}
-					*dp ^= (v ^ *dp) & rm;
-				}
-			}else{		/* full bytes in middle */
-				dx /= ppb;
-				if(lm)
-					dwid--;
-				dwid -= dx;
-
-				for(y=0; y<dy; y++, dp+=dwid){
-					if(lm){
-						*dp ^= (v ^ *dp) & lm;
-						dp++;
-					}
-					memset(dp, v, dx);
-					dp += dx;
-					*dp ^= (v ^ *dp) & rm;
-				}
-			}
-			return 1;
-		case 8:
-			for(y=0; y<dy; y++, dp+=dwid)
-				memset(dp, v, dx);
-			return 1;
-		case 16:
-			p[0] = v;		/* make little endian */
-			p[1] = v>>8;
-			v = *(ushort*)p;
-DBG print("dp=%p; dx=%d; for(y=0; y<%d; y++, dp+=%d)\nmemsets(dp, v, dx);\n",
-	dp, dx, dy, dwid);
-			for(y=0; y<dy; y++, dp+=dwid)
-				memsets(dp, v, dx);
-			return 1;
-		case 24:
-			for(y=0; y<dy; y++, dp+=dwid)
-				memset24(dp, v, dx);
-			return 1;
-		case 32:
-			p[0] = v;		/* make little endian */
-			p[1] = v>>8;
-			p[2] = v>>16;
-			p[3] = v>>24;
-			v = *(u32int*)p;
-			for(y=0; y<dy; y++, dp+=dwid)
-				memsetl(dp, v, dx);
-			return 1;
-		default:
-			assert(0 /* bad dest depth in memoptdraw */);
-		}
-	}
-
-	/*
-	 * If no source alpha, an opaque mask, we can just copy the
-	 * source onto the destination.  If the channels are the same and
-	 * the source is not replicated, memmove suffices.
-	 */
-	m = Simplemask|Fullmask;
-	if((par->state&(m|Replsrc))==m && src->depth >= 8 
-	&& src->chan == dst->chan && !(src->flags&Falpha) && (op == S || op == SoverD)){
-		uchar *sp, *dp;
-		long swid, dwid, nb;
-		int dir;
-
-		if(src->data == dst->data && byteaddr(dst, par->r.min) > byteaddr(src, par->sr.min))
-			dir = -1;
-		else
-			dir = 1;
-
-		swid = src->width*sizeof(u32int);
-		dwid = dst->width*sizeof(u32int);
-		sp = byteaddr(src, par->sr.min);
-		dp = byteaddr(dst, par->r.min);
-		if(dir == -1){
-			sp += (dy-1)*swid;
-			dp += (dy-1)*dwid;
-			swid = -swid;
-			dwid = -dwid;
-		}
-		nb = (dx*src->depth)/8;
-		for(y=0; y<dy; y++, sp+=swid, dp+=dwid)
-			memmove(dp, sp, nb);
-		return 1;
-	}
-
-	/*
-	 * If we have a 1-bit mask, 1-bit source, and 1-bit destination, and
-	 * they're all bit aligned, we can just use bit operators.  This happens
-	 * when we're manipulating boolean masks, e.g. in the arc code.
-	 */
-	if((par->state&(Simplemask|Simplesrc|Replmask|Replsrc))==0 
-	&& dst->chan==GREY1 && src->chan==GREY1 && par->mask->chan==GREY1 
-	&& (par->r.min.x&7)==(par->sr.min.x&7) && (par->r.min.x&7)==(par->mr.min.x&7)){
-		uchar *sp, *dp, *mp;
-		uchar lm, rm;
-		long swid, dwid, mwid;
-		int i, x, dir;
-
-		sp = byteaddr(src, par->sr.min);
-		dp = byteaddr(dst, par->r.min);
-		mp = byteaddr(par->mask, par->mr.min);
-		swid = src->width*sizeof(u32int);
-		dwid = dst->width*sizeof(u32int);
-		mwid = par->mask->width*sizeof(u32int);
-
-		if(src->data == dst->data && byteaddr(dst, par->r.min) > byteaddr(src, par->sr.min)){
-			dir = -1;
-		}else
-			dir = 1;
-
-		lm = 0xFF>>(par->r.min.x&7);
-		rm = 0xFF<<(8-(par->r.max.x&7));
-		dx -= (8-(par->r.min.x&7)) + (par->r.max.x&7);
-
-		if(dx < 0){	/* one byte wide */
-			lm &= rm;
-			if(dir == -1){
-				dp += dwid*(dy-1);
-				sp += swid*(dy-1);
-				mp += mwid*(dy-1);
-				dwid = -dwid;
-				swid = -swid;
-				mwid = -mwid;
-			}
-			for(y=0; y<dy; y++){
-				*dp ^= (*dp ^ *sp) & *mp & lm;
-				dp += dwid;
-				sp += swid;
-				mp += mwid;
-			}
-			return 1;
-		}
-
-		dx /= 8;
-		if(dir == 1){
-			i = (lm!=0)+dx+(rm!=0);
-			mwid -= i;
-			swid -= i;
-			dwid -= i;
-			for(y=0; y<dy; y++, dp+=dwid, sp+=swid, mp+=mwid){
-				if(lm){
-					*dp ^= (*dp ^ *sp++) & *mp++ & lm;
-					dp++;
-				}
-				for(x=0; x<dx; x++){
-					*dp ^= (*dp ^ *sp++) & *mp++;
-					dp++;
-				}
-				if(rm){
-					*dp ^= (*dp ^ *sp++) & *mp++ & rm;
-					dp++;
-				}
-			}
-			return 1;
-		}else{
-		/* dir == -1 */
-			i = (lm!=0)+dx+(rm!=0);
-			dp += dwid*(dy-1)+i-1;
-			sp += swid*(dy-1)+i-1;
-			mp += mwid*(dy-1)+i-1;
-			dwid = -dwid+i;
-			swid = -swid+i;
-			mwid = -mwid+i;
-			for(y=0; y<dy; y++, dp+=dwid, sp+=swid, mp+=mwid){
-				if(rm){
-					*dp ^= (*dp ^ *sp--) & *mp-- & rm;
-					dp--;
-				}
-				for(x=0; x<dx; x++){
-					*dp ^= (*dp ^ *sp--) & *mp--;
-					dp--;
-				}
-				if(lm){
-					*dp ^= (*dp ^ *sp--) & *mp-- & lm;
-					dp--;
-				}
-			}
-		}
-		return 1;
-	}
-	return 0;	
-}
-#undef DBG
-
-/*
- * Boolean character drawing.
- * Solid opaque color through a 1-bit greyscale mask.
- */
-#define DBG if(0)
-static int
-chardraw(Memdrawparam *par)
-{
-	u32int bits;
-	int i, ddepth, dy, dx, x, bx, ex, y, npack, bsh, depth, op;
-	u32int v, maskwid, dstwid;
-	uchar *wp, *rp, *q, *wc;
-	ushort *ws;
-	u32int *wl;
-	uchar sp[4];
-	Rectangle r, mr;
-	Memimage *mask, *src, *dst;
-
-if(0) if(drawdebug) iprint("chardraw? mf %lux md %d sf %lux dxs %d dys %d dd %d ddat %p sdat %p\n",
-		par->mask->flags, par->mask->depth, par->src->flags, 
-		Dx(par->src->r), Dy(par->src->r), par->dst->depth, par->dst->data, par->src->data);
-
-	mask = par->mask;
-	src = par->src;
-	dst = par->dst;
-	r = par->r;
-	mr = par->mr;
-	op = par->op;
-
-	if((par->state&(Replsrc|Simplesrc|Fullsrc|Replmask)) != (Replsrc|Simplesrc|Fullsrc)
-	|| mask->depth != 1 || dst->depth<8 || dst->data==src->data
-	|| op != SoverD)
-		return 0;
-
-/*if(drawdebug) iprint("chardraw..."); */
-
-	depth = mask->depth;
-	maskwid = mask->width*sizeof(u32int);
-	rp = byteaddr(mask, mr.min);
-	npack = 8/depth;
-	bsh = (mr.min.x % npack) * depth;
-
-	wp = byteaddr(dst, r.min);
-	dstwid = dst->width*sizeof(u32int);
-DBG print("bsh %d\n", bsh);
-	dy = Dy(r);
-	dx = Dx(r);
-
-	ddepth = dst->depth;
-
-	/*
-	 * for loop counts from bsh to bsh+dx
-	 *
-	 * we want the bottom bits to be the amount
-	 * to shift the pixels down, so for n≡0 (mod 8) we want 
-	 * bottom bits 7.  for n≡1, 6, etc.
-	 * the bits come from -n-1.
-	 */
-
-	bx = -bsh-1;
-	ex = -bsh-1-dx;
-	SET(bits);
-	v = par->sdval;
-
-	/* make little endian */
-	sp[0] = v;
-	sp[1] = v>>8;
-	sp[2] = v>>16;
-	sp[3] = v>>24;
-
-/*print("sp %x %x %x %x\n", sp[0], sp[1], sp[2], sp[3]); */
-	for(y=0; y<dy; y++, rp+=maskwid, wp+=dstwid){
-		q = rp;
-		if(bsh)
-			bits = *q++;
-		switch(ddepth){
-		case 8:
-/*if(drawdebug) iprint("8loop..."); */
-			wc = wp;
-			for(x=bx; x>ex; x--, wc++){
-				i = x&7;
-				if(i == 8-1)
-					bits = *q++;
-DBG print("bits %lux sh %d...", bits, i);
-				if((bits>>i)&1)
-					*wc = v;
-			}
-			break;
-		case 16:
-			ws = (ushort*)wp;
-			v = *(ushort*)sp;
-			for(x=bx; x>ex; x--, ws++){
-				i = x&7;
-				if(i == 8-1)
-					bits = *q++;
-DBG print("bits %lux sh %d...", bits, i);
-				if((bits>>i)&1)
-					*ws = v;
-			}
-			break;
-		case 24:
-			wc = wp;
-			for(x=bx; x>ex; x--, wc+=3){
-				i = x&7;
-				if(i == 8-1)
-					bits = *q++;
-DBG print("bits %lux sh %d...", bits, i);
-				if((bits>>i)&1){
-					wc[0] = sp[0];
-					wc[1] = sp[1];
-					wc[2] = sp[2];
-				}
-			}
-			break;
-		case 32:
-			wl = (u32int*)wp;
-			v = *(u32int*)sp;
-			for(x=bx; x>ex; x--, wl++){
-				i = x&7;
-				if(i == 8-1)
-					bits = *q++;
-DBG iprint("bits %lux sh %d...", bits, i);
-				if((bits>>i)&1)
-					*wl = v;
-			}
-			break;
-		}
-	}
-
-DBG print("\n");	
-	return 1;	
-}
-#undef DBG
-
-
-/*
- * Fill entire byte with replicated (if necessary) copy of source pixel,
- * assuming destination ldepth is >= source ldepth.
- *
- * This code is just plain wrong for >8bpp.
- *
-u32int
-membyteval(Memimage *src)
-{
-	int i, val, bpp;
-	uchar uc;
-
-	unloadmemimage(src, src->r, &uc, 1);
-	bpp = src->depth;
-	uc <<= (src->r.min.x&(7/src->depth))*src->depth;
-	uc &= ~(0xFF>>bpp);
-	* pixel value is now in high part of byte. repeat throughout byte 
-	val = uc;
-	for(i=bpp; i<8; i<<=1)
-		val |= val>>i;
-	return val;
-}
- * 
- */
-
-void
-_memfillcolor(Memimage *i, u32int val)
-{
-	u32int bits;
-	int d, y;
-	uchar p[4];
-
-	if(val == DNofill)
-		return;
-
-	bits = _rgbatoimg(i, val);
-	switch(i->depth){
-	case 24:	/* 24-bit images suck */
-		for(y=i->r.min.y; y<i->r.max.y; y++)
-			memset24(byteaddr(i, Pt(i->r.min.x, y)), bits, Dx(i->r));
-		break;
-	default:	/* 1, 2, 4, 8, 16, 32 */
-		for(d=i->depth; d<32; d*=2)
-			bits = (bits << d) | bits;
-		p[0] = bits;		/* make little endian */
-		p[1] = bits>>8;
-		p[2] = bits>>16;
-		p[3] = bits>>24;
-		bits = *(u32int*)p;
-		memsetl(wordaddr(i, i->r.min), bits, i->width*Dy(i->r));
-		break;
-	}
-}
-
blob - 9d991782589c4659265a782c13fc3bd707e800f4 (mode 644)
blob + /dev/null
--- src/libdraw/md-drawtest.c
+++ /dev/null
@@ -1,1004 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <draw.h>
-#include <memdraw.h>
-
-#define DBG if(0)
-#define RGB2K(r,g,b)	((299*((u32int)(r))+587*((u32int)(g))+114*((u32int)(b)))/1000)
-
-/*
- * This program tests the 'memimagedraw' primitive stochastically.
- * It tests the combination aspects of it thoroughly, but since the
- * three images it uses are disjoint, it makes no check of the
- * correct behavior when images overlap.  That is, however, much
- * easier to get right and to test.
- */
-
-void	drawonepixel(Memimage*, Point, Memimage*, Point, Memimage*, Point);
-void	verifyone(void);
-void	verifyline(void);
-void	verifyrect(void);
-void	verifyrectrepl(int, int);
-void putpixel(Memimage *img, Point pt, u32int nv);
-u32int rgbatopix(uchar, uchar, uchar, uchar);
-
-char *dchan, *schan, *mchan;
-int dbpp, sbpp, mbpp;
-
-int drawdebug=0;
-int	seed;
-int	niters = 100;
-int	dbpp;	/* bits per pixel in destination */
-int	sbpp;	/* bits per pixel in src */
-int	mbpp;	/* bits per pixel in mask */
-int	dpm;	/* pixel mask at high part of byte, in destination */
-int	nbytes;	/* in destination */
-
-int	Xrange	= 64;
-int	Yrange	= 8;
-
-Memimage	*dst;
-Memimage	*src;
-Memimage	*mask;
-Memimage	*stmp;
-Memimage	*mtmp;
-Memimage	*ones;
-uchar	*dstbits;
-uchar	*srcbits;
-uchar	*maskbits;
-u32int	*savedstbits;
-
-void
-rdb(void)
-{
-}
-
-int
-iprint(char *fmt, ...)
-{
-	int n;	
-	va_list va;
-	char buf[1024];
-
-	va_start(va, fmt);
-	n = doprint(buf, buf+sizeof buf, fmt, va) - buf;
-	va_end(va);
-
-	write(1,buf,n);
-	return 1;
-}
-
-void
-main(int argc, char *argv[])
-{
-	memimageinit();
-	seed = time(0);
-
-	ARGBEGIN{
-	case 'x':
-		Xrange = atoi(ARGF());
-		break;
-	case 'y':
-		Yrange = atoi(ARGF());
-		break;
-	case 'n':
-		niters = atoi(ARGF());
-		break;
-	case 's':
-		seed = atoi(ARGF());
-		break;
-	}ARGEND
-
-	dchan = "r8g8b8";
-	schan = "r8g8b8";
-	mchan = "r8g8b8";
-	switch(argc){
-	case 3:	mchan = argv[2];
-	case 2:	schan = argv[1];
-	case 1:	dchan = argv[0];
-	case 0:	break;
-	default:	goto Usage;
-	Usage:
-		fprint(2, "usage: dtest [dchan [schan [mchan]]]\n");
-		exits("usage");
-	}
-
-	fmtinstall('b', numbconv);	/* binary! */
-
-	fprint(2, "%s -x %d -y %d -s 0x%x %s %s %s\n", argv0, Xrange, Yrange, seed, dchan, schan, mchan);
-	srand(seed);
-
-	dst = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(dchan));
-	src = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(schan));
-	mask = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(mchan));
-	stmp = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(schan));
-	mtmp = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(mchan));
-	ones = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(mchan));
-/*	print("chan %lux %lux %lux %lux %lux %lux\n", dst->chan, src->chan, mask->chan, stmp->chan, mtmp->chan, ones->chan); */
-	if(dst==0 || src==0 || mask==0 || mtmp==0 || ones==0) {
-	Alloc:
-		fprint(2, "dtest: allocation failed: %r\n");
-		exits("alloc");
-	}
-	nbytes = (4*Xrange+4)*Yrange;
-	srcbits = malloc(nbytes);
-	dstbits = malloc(nbytes);
-	maskbits = malloc(nbytes);
-	savedstbits = malloc(nbytes);
-	if(dstbits==0 || srcbits==0 || maskbits==0 || savedstbits==0)
-		goto Alloc;
-	dbpp = dst->depth;
-	sbpp = src->depth;
-	mbpp = mask->depth;
-	dpm = 0xFF ^ (0xFF>>dbpp);
-	memset(ones->data->bdata, 0xFF, ones->width*sizeof(u32int)*Yrange);
-
-
-	fprint(2, "dtest: verify single pixel operation\n");
-	verifyone();
-
-	fprint(2, "dtest: verify full line non-replicated\n");
-	verifyline();
-
-	fprint(2, "dtest: verify full rectangle non-replicated\n");
-	verifyrect();
-
-	fprint(2, "dtest: verify full rectangle source replicated\n");
-	verifyrectrepl(1, 0);
-
-	fprint(2, "dtest: verify full rectangle mask replicated\n");
-	verifyrectrepl(0, 1);
-
-	fprint(2, "dtest: verify full rectangle source and mask replicated\n");
-	verifyrectrepl(1, 1);
-
-	exits(0);
-}
-
-/*
- * Dump out an ASCII representation of an image.  The label specifies
- * a list of characters to put at various points in the picture.
- */
-static void
-Bprintr5g6b5(Biobuf *bio, char*, u32int v)
-{
-	int r,g,b;
-	r = (v>>11)&31;
-	g = (v>>5)&63;
-	b = v&31;
-	Bprint(bio, "%.2x%.2x%.2x", r,g,b);
-}
-
-static void
-Bprintr5g5b5a1(Biobuf *bio, char*, u32int v)
-{
-	int r,g,b,a;
-	r = (v>>11)&31;
-	g = (v>>6)&31;
-	b = (v>>1)&31;
-	a = v&1;
-	Bprint(bio, "%.2x%.2x%.2x%.2x", r,g,b,a);
-}
-
-void
-dumpimage(char *name, Memimage *img, void *vdata, Point labelpt)
-{
-	Biobuf b;
-	uchar *data;
-	uchar *p;
-	char *arg;
-	void (*fmt)(Biobuf*, char*, u32int);
-	int npr, x, y, nb, bpp;
-	u32int v, mask;
-	Rectangle r;
-
-	fmt = nil;
-	arg = nil;
-	switch(img->depth){
-	case 1:
-	case 2:
-	case 4:
-		fmt = (void(*)(Biobuf*,char*,u32int))Bprint;
-		arg = "%.1ux";
-		break;
-	case 8:
-		fmt = (void(*)(Biobuf*,char*,u32int))Bprint;
-		arg = "%.2ux";
-		break;
-	case 16:
-		arg = nil;
-		if(img->chan == RGB16)
-			fmt = Bprintr5g6b5;
-		else{
-			fmt = (void(*)(Biobuf*,char*,u32int))Bprint;
-			arg = "%.4ux";
-		}
-		break;
-	case 24:
-		fmt = (void(*)(Biobuf*,char*,u32int))Bprint;
-		arg = "%.6lux";
-		break;
-	case 32:
-		fmt = (void(*)(Biobuf*,char*,u32int))Bprint;
-		arg = "%.8lux";
-		break;
-	}
-	if(fmt == nil){
-		fprint(2, "bad format\n");
-		abort();
-	}
-
-	r  = img->r;
-	Binit(&b, 2, OWRITE);
-	data = vdata;
-	bpp = img->depth;
-	Bprint(&b, "%s\t%d\tr %R clipr %R repl %d data %p *%P\n", name, r.min.x, r, img->clipr, (img->flags&Frepl) ? 1 : 0, vdata, labelpt);
-	mask = (1ULL<<bpp)-1;
-/*	for(y=r.min.y; y<r.max.y; y++){ */
-	for(y=0; y<Yrange; y++){
-		nb = 0;
-		v = 0;
-		p = data+(byteaddr(img, Pt(0,y))-(uchar*)img->data->bdata);
-		Bprint(&b, "%-4d\t", y);
-/*		for(x=r.min.x; x<r.max.x; x++){ */
-		for(x=0; x<Xrange; x++){
-			if(x==0)
-				Bprint(&b, "\t");
-
-			if(x != 0 && (x%8)==0)
-				Bprint(&b, " ");
-
-			npr = 0;
-			if(x==labelpt.x && y==labelpt.y){
-				Bprint(&b, "*");
-				npr++;
-			}
-			if(npr == 0)
-				Bprint(&b, " ");
-
-			while(nb < bpp){
-				v &= (1<<nb)-1;
-				v |= (u32int)(*p++) << nb;
-				nb += 8;
-			}
-			nb -= bpp;
-/*			print("bpp %d v %.8lux mask %.8lux nb %d\n", bpp, v, mask, nb); */
-			fmt(&b, arg, (v>>nb)&mask);
-		}
-		Bprint(&b, "\n");
-	}
-	Bterm(&b);
-}
-
-/*
- * Verify that the destination pixel has the specified value.
- * The value is in the high bits of v, suitably masked, but must
- * be extracted from the destination Memimage.
- */
-void
-checkone(Point p, Point sp, Point mp)
-{
-	int delta;
-	uchar *dp, *sdp;
-
-	delta = (uchar*)byteaddr(dst, p)-(uchar*)dst->data->bdata;
-	dp = (uchar*)dst->data->bdata+delta;
-	sdp = (uchar*)savedstbits+delta;
-
-	if(memcmp(dp, sdp, (dst->depth+7)/8) != 0) {
-		fprint(2, "dtest: one bad pixel drawing at dst %P from source %P mask %P\n", p, sp, mp);
-		fprint(2, " %.2ux %.2ux %.2ux %.2ux should be %.2ux %.2ux %.2ux %.2ux\n",
-			dp[0], dp[1], dp[2], dp[3], sdp[0], sdp[1], sdp[2], sdp[3]);
-		fprint(2, "addresses dst %p src %p mask %p\n", dp, byteaddr(src, sp), byteaddr(mask, mp));
-		dumpimage("src", src, src->data->bdata, sp);
-		dumpimage("mask", mask, mask->data->bdata, mp);
-		dumpimage("origdst", dst, dstbits, p);
-		dumpimage("dst", dst, dst->data->bdata, p);
-		dumpimage("gooddst", dst, savedstbits, p);
-		abort();
-	}
-}
-
-/*
- * Verify that the destination line has the same value as the saved line.
- */
-#define RECTPTS(r) (r).min.x, (r).min.y, (r).max.x, (r).max.y
-void
-checkline(Rectangle r, Point sp, Point mp, int y, Memimage *stmp, Memimage *mtmp)
-{
-	u32int *dp;
-	int nb;
-	u32int *saved;
-
-	dp = wordaddr(dst, Pt(0, y));
-	saved = savedstbits + y*dst->width;
-	if(dst->depth < 8)
-		nb = Xrange/(8/dst->depth);
-	else
-		nb = Xrange*(dst->depth/8);
-	if(memcmp(dp, saved, nb) != 0){
-		fprint(2, "dtest: bad line at y=%d; saved %p dp %p\n", y, saved, dp);
-		fprint(2, "draw dst %R src %P mask %P\n", r, sp, mp);
-		dumpimage("src", src, src->data->bdata, sp);
-		if(stmp) dumpimage("stmp", stmp, stmp->data->bdata, sp);
-		dumpimage("mask", mask, mask->data->bdata, mp);
-		if(mtmp) dumpimage("mtmp", mtmp, mtmp->data->bdata, mp);
-		dumpimage("origdst", dst, dstbits, r.min);
-		dumpimage("dst", dst, dst->data->bdata, r.min);
-		dumpimage("gooddst", dst, savedstbits, r.min);
-		abort();
-	}
-}
-
-/*
- * Fill the bits of an image with random data.
- * The Memimage parameter is used only to make sure
- * the data is well formatted: only ucbits is written.
- */
-void
-fill(Memimage *img, uchar *ucbits)
-{
-	int i, x, y;
-	ushort *up;
-	uchar alpha, r, g, b;
-	void *data;
-
-	if((img->flags&Falpha) == 0){
-		up = (ushort*)ucbits;
-		for(i=0; i<nbytes/2; i++)
-			*up++ = lrand() >> 7;
-		if(i+i != nbytes)
-			*(uchar*)up = lrand() >> 7;
-	}else{
-		data = img->data->bdata;
-		img->data->bdata = ucbits;
-
-		for(x=img->r.min.x; x<img->r.max.x; x++)
-		for(y=img->r.min.y; y<img->r.max.y; y++){
-			alpha = rand() >> 4;
-			r = rand()%(alpha+1);
-			g = rand()%(alpha+1);
-			b = rand()%(alpha+1);
-			putpixel(img, Pt(x,y), rgbatopix(r,g,b,alpha));
-		}
-		img->data->bdata = data;
-	}
-		
-}
-
-/*
- * Mask is preset; do the rest
- */
-void
-verifyonemask(void)
-{
-	Point dp, sp, mp;
-
-	fill(dst, dstbits);
-	fill(src, srcbits);
-	memmove(dst->data->bdata, dstbits, dst->width*sizeof(u32int)*Yrange);
-	memmove(src->data->bdata, srcbits, src->width*sizeof(u32int)*Yrange);
-	memmove(mask->data->bdata, maskbits, mask->width*sizeof(u32int)*Yrange);
-
-	dp.x = nrand(Xrange);
-	dp.y = nrand(Yrange);
-
-	sp.x = nrand(Xrange);
-	sp.y = nrand(Yrange);
-
-	mp.x = nrand(Xrange);
-	mp.y = nrand(Yrange);
-
-	drawonepixel(dst, dp, src, sp, mask, mp);
-	memmove(mask->data->bdata, maskbits, mask->width*sizeof(u32int)*Yrange);
-	memmove(savedstbits, dst->data->bdata, dst->width*sizeof(u32int)*Yrange);
-	
-	memmove(dst->data->bdata, dstbits, dst->width*sizeof(u32int)*Yrange);
-	memimagedraw(dst, Rect(dp.x, dp.y, dp.x+1, dp.y+1), src, sp, mask, mp, SoverD);
-	memmove(mask->data->bdata, maskbits, mask->width*sizeof(u32int)*Yrange);
-
-	checkone(dp, sp, mp);
-}
-
-void
-verifyone(void)
-{
-	int i;
-
-	/* mask all zeros */
-	memset(maskbits, 0, nbytes);
-	for(i=0; i<niters; i++)
-		verifyonemask();
-
-	/* mask all ones */
-	memset(maskbits, 0xFF, nbytes);
-	for(i=0; i<niters; i++)
-		verifyonemask();
-
-	/* random mask */
-	for(i=0; i<niters; i++){
-		fill(mask, maskbits);
-		verifyonemask();
-	}
-}
-
-/*
- * Mask is preset; do the rest
- */
-void
-verifylinemask(void)
-{
-	Point sp, mp, tp, up;
-	Rectangle dr;
-	int x;
-
-	fill(dst, dstbits);
-	fill(src, srcbits);
-	memmove(dst->data->bdata, dstbits, dst->width*sizeof(u32int)*Yrange);
-	memmove(src->data->bdata, srcbits, src->width*sizeof(u32int)*Yrange);
-	memmove(mask->data->bdata, maskbits, mask->width*sizeof(u32int)*Yrange);
-
-	dr.min.x = nrand(Xrange-1);
-	dr.min.y = nrand(Yrange-1);
-	dr.max.x = dr.min.x + 1 + nrand(Xrange-1-dr.min.x);
-	dr.max.y = dr.min.y + 1;
-
-	sp.x = nrand(Xrange);
-	sp.y = nrand(Yrange);
-
-	mp.x = nrand(Xrange);
-	mp.y = nrand(Yrange);
-
-	tp = sp;
-	up = mp;
-	for(x=dr.min.x; x<dr.max.x && tp.x<Xrange && up.x<Xrange; x++,tp.x++,up.x++)
-		memimagedraw(dst, Rect(x, dr.min.y, x+1, dr.min.y+1), src, tp, mask, up, SoverD);
-	memmove(savedstbits, dst->data->bdata, dst->width*sizeof(u32int)*Yrange);
-
-	memmove(dst->data->bdata, dstbits, dst->width*sizeof(u32int)*Yrange);
-
-	memimagedraw(dst, dr, src, sp, mask, mp, SoverD);
-	checkline(dr, drawrepl(src->r, sp), drawrepl(mask->r, mp), dr.min.y, nil, nil);
-}
-
-void
-verifyline(void)
-{
-	int i;
-
-	/* mask all ones */
-	memset(maskbits, 0xFF, nbytes);
-	for(i=0; i<niters; i++)
-		verifylinemask();
-
-	/* mask all zeros */
-	memset(maskbits, 0, nbytes);
-	for(i=0; i<niters; i++)
-		verifylinemask();
-
-	/* random mask */
-	for(i=0; i<niters; i++){
-		fill(mask, maskbits);
-		verifylinemask();
-	}
-}
-
-/*
- * Mask is preset; do the rest
- */
-void
-verifyrectmask(void)
-{
-	Point sp, mp, tp, up;
-	Rectangle dr;
-	int x, y;
-
-	fill(dst, dstbits);
-	fill(src, srcbits);
-	memmove(dst->data->bdata, dstbits, dst->width*sizeof(u32int)*Yrange);
-	memmove(src->data->bdata, srcbits, src->width*sizeof(u32int)*Yrange);
-	memmove(mask->data->bdata, maskbits, mask->width*sizeof(u32int)*Yrange);
-
-	dr.min.x = nrand(Xrange-1);
-	dr.min.y = nrand(Yrange-1);
-	dr.max.x = dr.min.x + 1 + nrand(Xrange-1-dr.min.x);
-	dr.max.y = dr.min.y + 1 + nrand(Yrange-1-dr.min.y);
-
-	sp.x = nrand(Xrange);
-	sp.y = nrand(Yrange);
-
-	mp.x = nrand(Xrange);
-	mp.y = nrand(Yrange);
-
-	tp = sp;
-	up = mp;
-	for(y=dr.min.y; y<dr.max.y && tp.y<Yrange && up.y<Yrange; y++,tp.y++,up.y++){
-		for(x=dr.min.x; x<dr.max.x && tp.x<Xrange && up.x<Xrange; x++,tp.x++,up.x++)
-			memimagedraw(dst, Rect(x, y, x+1, y+1), src, tp, mask, up, SoverD);
-		tp.x = sp.x;
-		up.x = mp.x;
-	}
-	memmove(savedstbits, dst->data->bdata, dst->width*sizeof(u32int)*Yrange);
-
-	memmove(dst->data->bdata, dstbits, dst->width*sizeof(u32int)*Yrange);
-
-	memimagedraw(dst, dr, src, sp, mask, mp, SoverD);
-	for(y=0; y<Yrange; y++)
-		checkline(dr, drawrepl(src->r, sp), drawrepl(mask->r, mp), y, nil, nil);
-}
-
-void
-verifyrect(void)
-{
-	int i;
-
-	/* mask all zeros */
-	memset(maskbits, 0, nbytes);
-	for(i=0; i<niters; i++)
-		verifyrectmask();
-
-	/* mask all ones */
-	memset(maskbits, 0xFF, nbytes);
-	for(i=0; i<niters; i++)
-		verifyrectmask();
-
-	/* random mask */
-	for(i=0; i<niters; i++){
-		fill(mask, maskbits);
-		verifyrectmask();
-	}
-}
-
-Rectangle
-randrect(void)
-{
-	Rectangle r;
-
-	r.min.x = nrand(Xrange-1);
-	r.min.y = nrand(Yrange-1);
-	r.max.x = r.min.x + 1 + nrand(Xrange-1-r.min.x);
-	r.max.y = r.min.y + 1 + nrand(Yrange-1-r.min.y);
-	return r;
-}
-
-/*
- * Return coordinate corresponding to x withing range [minx, maxx)
- */
-int
-tilexy(int minx, int maxx, int x)
-{
-	int sx;
-
-	sx = (x-minx) % (maxx-minx);
-	if(sx < 0)
-		sx += maxx-minx;
-	return sx+minx;
-}
-
-void
-replicate(Memimage *i, Memimage *tmp)
-{
-	Rectangle r, r1;
-	int x, y, nb;
-
-	/* choose the replication window (i->r) */
-	r.min.x = nrand(Xrange-1);
-	r.min.y = nrand(Yrange-1);
-	/* make it trivial more often than pure chance allows */
-	switch(lrand()&0){
-	case 1:
-		r.max.x = r.min.x + 2;
-		r.max.y = r.min.y + 2;
-		if(r.max.x < Xrange && r.max.y < Yrange)
-			break;
-		/* fall through */
-	case 0:
-		r.max.x = r.min.x + 1;
-		r.max.y = r.min.y + 1;
-		break;
-	default:
-		if(r.min.x+3 >= Xrange)
-			r.max.x = Xrange;
-		else
-			r.max.x = r.min.x+3 + nrand(Xrange-(r.min.x+3));
-
-		if(r.min.y+3 >= Yrange)
-			r.max.y = Yrange;
-		else
-			r.max.y = r.min.y+3 + nrand(Yrange-(r.min.y+3));
-	}
-	assert(r.min.x >= 0);	
-	assert(r.max.x <= Xrange);
-	assert(r.min.y >= 0);
-	assert(r.max.y <= Yrange);
-	/* copy from i to tmp so we have just the replicated bits */
-	nb = tmp->width*sizeof(u32int)*Yrange;
-	memset(tmp->data->bdata, 0, nb);
-	memimagedraw(tmp, r, i, r.min, ones, r.min, SoverD);
-	memmove(i->data->bdata, tmp->data->bdata, nb);
-	/* i is now a non-replicated instance of the replication */
-	/* replicate it by hand through tmp */
-	memset(tmp->data->bdata, 0, nb);
-	x = -(tilexy(r.min.x, r.max.x, 0)-r.min.x);
-	for(; x<Xrange; x+=Dx(r)){
-		y = -(tilexy(r.min.y, r.max.y, 0)-r.min.y);
-		for(; y<Yrange; y+=Dy(r)){
-			/* set r1 to instance of tile by translation */
-			r1.min.x = x;
-			r1.min.y = y;
-			r1.max.x = r1.min.x+Dx(r);
-			r1.max.y = r1.min.y+Dy(r);
-			memimagedraw(tmp, r1, i, r.min, ones, r.min, SoverD);
-		}
-	}
-	i->flags |= Frepl;
-	i->r = r;
-	i->clipr = randrect();
-/*	fprint(2, "replicate [[%d %d] [%d %d]] [[%d %d][%d %d]]\n", r.min.x, r.min.y, r.max.x, r.max.y, */
-/*		i->clipr.min.x, i->clipr.min.y, i->clipr.max.x, i->clipr.max.y); */
-	tmp->clipr = i->clipr;
-}
-
-/*
- * Mask is preset; do the rest
- */
-void
-verifyrectmaskrepl(int srcrepl, int maskrepl)
-{
-	Point sp, mp, tp, up;
-	Rectangle dr;
-	int x, y;
-	Memimage *s, *m;
-
-/*	print("verfrect %d %d\n", srcrepl, maskrepl); */
-	src->flags &= ~Frepl;
-	src->r = Rect(0, 0, Xrange, Yrange);
-	src->clipr = src->r;
-	stmp->flags &= ~Frepl;
-	stmp->r = Rect(0, 0, Xrange, Yrange);
-	stmp->clipr = src->r;
-	mask->flags &= ~Frepl;
-	mask->r = Rect(0, 0, Xrange, Yrange);
-	mask->clipr = mask->r;
-	mtmp->flags &= ~Frepl;
-	mtmp->r = Rect(0, 0, Xrange, Yrange);
-	mtmp->clipr = mask->r;
-
-	fill(dst, dstbits);
-	fill(src, srcbits);
-
-	memmove(dst->data->bdata, dstbits, dst->width*sizeof(u32int)*Yrange);
-	memmove(src->data->bdata, srcbits, src->width*sizeof(u32int)*Yrange);
-	memmove(mask->data->bdata, maskbits, mask->width*sizeof(u32int)*Yrange);
-
-	if(srcrepl){
-		replicate(src, stmp);
-		s = stmp;
-	}else
-		s = src;
-	if(maskrepl){
-		replicate(mask, mtmp);
-		m = mtmp;
-	}else
-		m = mask;
-
-	dr = randrect();
-
-	sp.x = nrand(Xrange);
-	sp.y = nrand(Yrange);
-
-	mp.x = nrand(Xrange);
-	mp.y = nrand(Yrange);
-
-DBG	print("smalldraws\n");
-	for(tp.y=sp.y,up.y=mp.y,y=dr.min.y; y<dr.max.y && tp.y<Yrange && up.y<Yrange; y++,tp.y++,up.y++)
-		for(tp.x=sp.x,up.x=mp.x,x=dr.min.x; x<dr.max.x && tp.x<Xrange && up.x<Xrange; x++,tp.x++,up.x++)
-			memimagedraw(dst, Rect(x, y, x+1, y+1), s, tp, m, up, SoverD);
-	memmove(savedstbits, dst->data->bdata, dst->width*sizeof(u32int)*Yrange);
-
-	memmove(dst->data->bdata, dstbits, dst->width*sizeof(u32int)*Yrange);
-
-DBG	print("bigdraw\n");
-	memimagedraw(dst, dr, src, sp, mask, mp, SoverD);
-	for(y=0; y<Yrange; y++)
-		checkline(dr, drawrepl(src->r, sp), drawrepl(mask->r, mp), y, srcrepl?stmp:nil, maskrepl?mtmp:nil);
-}
-
-void
-verifyrectrepl(int srcrepl, int maskrepl)
-{
-	int i;
-
-	/* mask all ones */
-	memset(maskbits, 0xFF, nbytes);
-	for(i=0; i<niters; i++)
-		verifyrectmaskrepl(srcrepl, maskrepl);
-
-	/* mask all zeros */
-	memset(maskbits, 0, nbytes);
-	for(i=0; i<niters; i++)
-		verifyrectmaskrepl(srcrepl, maskrepl);
-
-	/* random mask */
-	for(i=0; i<niters; i++){
-		fill(mask, maskbits);
-		verifyrectmaskrepl(srcrepl, maskrepl);
-	}
-}
-
-/*
- * Trivial draw implementation.
- * Color values are passed around as u32ints containing ααRRGGBB
- */
-
-/*
- * Convert v, which is nhave bits wide, into its nwant bits wide equivalent.
- * Replicates to widen the value, truncates to narrow it.
- */
-u32int
-replbits(u32int v, int nhave, int nwant)
-{
-	v &= (1<<nhave)-1;
-	for(; nhave<nwant; nhave*=2)
-		v |= v<<nhave;
-	v >>= (nhave-nwant);
-	return v & ((1<<nwant)-1);
-}
-
-/*
- * Decode a pixel into the uchar* values.
- */
-void
-pixtorgba(u32int v, uchar *r, uchar *g, uchar *b, uchar *a)
-{
-	*a = v>>24;
-	*r = v>>16;
-	*g = v>>8;
-	*b = v;
-}
-
-/*
- * Convert uchar channels into u32int pixel.
- */
-u32int
-rgbatopix(uchar r, uchar g, uchar b, uchar a)
-{
-	return (a<<24)|(r<<16)|(g<<8)|b;
-}
-
-/*
- * Retrieve the pixel value at pt in the image.
- */
-u32int
-getpixel(Memimage *img, Point pt)
-{
-	uchar r, g, b, a, *p;
-	int nbits, npack, bpp;
-	u32int v, c, rbits, bits;
-
-	r = g = b = 0;
-	a = ~0;	/* default alpha is full */
-
-	p = byteaddr(img, pt);
-	v = p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24);
-	bpp = img->depth;
-	if(bpp<8){
-		/*
-		 * Sub-byte greyscale pixels.
-		 *
-		 * We want to throw away the top pt.x%npack pixels and then use the next bpp bits
-		 * in the bottom byte of v.  This madness is due to having big endian bits
-		 * but little endian bytes.
-		 */
-		npack = 8/bpp;
-		v >>= 8 - bpp*(pt.x%npack+1);
-		v &= (1<<bpp)-1;
-		r = g = b = replbits(v, bpp, 8);
-	}else{
-		/*
-		 * General case.  We need to parse the channel descriptor and do what it says.
-		 * In all channels but the color map, we replicate to 8 bits because that's the
-		 * precision that all calculations are done at.
-		 *
-		 * In the case of the color map, we leave the bits alone, in case a color map
-		 * with less than 8 bits of index is used.  This is currently disallowed, so it's
-		 * sort of silly.
-		 */
-
-		for(c=img->chan; c; c>>=8){
-			nbits = NBITS(c);
-			bits = v & ((1<<nbits)-1);
-			rbits = replbits(bits, nbits, 8);
-			v >>= nbits;
-			switch(TYPE(c)){
-			case CRed:
-				r = rbits;
-				break;
-			case CGreen:
-				g = rbits;
-				break;
-			case CBlue:
-				b = rbits;
-				break;
-			case CGrey:
-				r = g = b = rbits;
-				break;
-			case CAlpha:
-				a = rbits;
-				break;
-			case CMap:
-				p = img->cmap->cmap2rgb + 3*bits;
-				r = p[0];
-				g = p[1];
-				b = p[2];
-				break;
-			case CIgnore:
-				break;
-			default:
-				fprint(2, "unknown channel type %lud\n", TYPE(c));
-				abort();
-			}
-		}
-	}
-	return rgbatopix(r, g, b, a);
-}
-
-/*
- * Return the greyscale equivalent of a pixel.
- */
-uchar
-getgrey(Memimage *img, Point pt)
-{
-	uchar r, g, b, a;
-	pixtorgba(getpixel(img, pt), &r, &g, &b, &a);
-	return RGB2K(r, g, b);
-}
-
-/*
- * Return the value at pt in image, if image is interpreted
- * as a mask.  This means the alpha channel if present, else
- * the greyscale or its computed equivalent.
- */
-uchar
-getmask(Memimage *img, Point pt)
-{
-	if(img->flags&Falpha)
-		return getpixel(img, pt)>>24;
-	else
-		return getgrey(img, pt);
-}
-#undef DBG
-
-#define DBG if(0)
-/*
- * Write a pixel to img at point pt.
- * 
- * We do this by reading a 32-bit little endian
- * value from p and then writing it back
- * after tweaking the appropriate bits.  Because
- * the data is little endian, we don't have to worry
- * about what the actual depth is, as long as it is
- * less than 32 bits.
- */
-void
-putpixel(Memimage *img, Point pt, u32int nv)
-{
-	uchar r, g, b, a, *p, *q;
-	u32int c, mask, bits, v;
-	int bpp, sh, npack, nbits;
-
-	pixtorgba(nv, &r, &g, &b, &a);
-
-	p = byteaddr(img, pt);
-	v = p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24);
-	bpp = img->depth;
-DBG print("v %.8lux...", v);
-	if(bpp < 8){
-		/*
-		 * Sub-byte greyscale pixels.  We need to skip the leftmost pt.x%npack pixels,
-		 * which is equivalent to skipping the rightmost npack - pt.x%npack - 1 pixels.
-		 */	
-		npack = 8/bpp;
-		sh = bpp*(npack - pt.x%npack - 1);
-		bits = RGB2K(r,g,b);
-DBG print("repl %lux 8 %d = %lux...", bits, bpp, replbits(bits, 8, bpp));
-		bits = replbits(bits, 8, bpp);
-		mask = (1<<bpp)-1;
-DBG print("bits %lux mask %lux sh %d...", bits, mask, sh);
-		mask <<= sh;
-		bits <<= sh;
-DBG print("(%lux & %lux) | (%lux & %lux)", v, ~mask, bits, mask);
-		v = (v & ~mask) | (bits & mask);
-	} else {
-		/*
-		 * General case.  We need to parse the channel descriptor again.
-		 */
-		sh = 0;
-		for(c=img->chan; c; c>>=8){
-			nbits = NBITS(c);
-			switch(TYPE(c)){
-			case CRed:
-				bits = r;
-				break;
-			case CGreen:
-				bits = g;
-				break;
-			case CBlue:
-				bits = b;
-				break;
-			case CGrey:
-				bits = RGB2K(r, g, b);
-				break;
-			case CAlpha:
-				bits = a;
-				break;
-			case CIgnore:
-				bits = 0;
-				break;
-			case CMap:
-				q = img->cmap->rgb2cmap;
-				bits = q[(r>>4)*16*16+(g>>4)*16+(b>>4)];
-				break;
-			default:
-				SET(bits);
-				fprint(2, "unknown channel type %lud\n", TYPE(c));
-				abort();
-			}
-
-DBG print("repl %lux 8 %d = %lux...", bits, nbits, replbits(bits, 8, nbits));
-			if(TYPE(c) != CMap)
-				bits = replbits(bits, 8, nbits);
-			mask = (1<<nbits)-1;
-DBG print("bits %lux mask %lux sh %d...", bits, mask, sh);
-			bits <<= sh;
-			mask <<= sh;
-			v = (v & ~mask) | (bits & mask);
-			sh += nbits;
-		}
-	}
-DBG print("v %.8lux\n", v);
-	p[0] = v;
-	p[1] = v>>8;
-	p[2] = v>>16;
-	p[3] = v>>24;	
-}
-#undef DBG
-
-#define DBG if(0)
-void
-drawonepixel(Memimage *dst, Point dp, Memimage *src, Point sp, Memimage *mask, Point mp)
-{
-	uchar m, M, sr, sg, sb, sa, sk, dr, dg, db, da, dk;
-
-	pixtorgba(getpixel(dst, dp), &dr, &dg, &db, &da);
-	pixtorgba(getpixel(src, sp), &sr, &sg, &sb, &sa);
-	m = getmask(mask, mp);
-	M = 255-(sa*m)/255;
-
-DBG print("dst %x %x %x %x src %x %x %x %x m %x = ", dr,dg,db,da, sr,sg,sb,sa, m);
-	if(dst->flags&Fgrey){
-		/*
-		 * We need to do the conversion to grey before the alpha calculation
-		 * because the draw operator does this, and we need to be operating
-		 * at the same precision so we get exactly the same answers.
-		 */
-		sk = RGB2K(sr, sg, sb);
-		dk = RGB2K(dr, dg, db);
-		dk = (sk*m + dk*M)/255;
-		dr = dg = db = dk;
-		da = (sa*m + da*M)/255;
-	}else{
-		/*
-		 * True color alpha calculation treats all channels (including alpha)
-		 * the same.  It might have been nice to use an array, but oh well.
-		 */
-		dr = (sr*m + dr*M)/255;
-		dg = (sg*m + dg*M)/255;
-		db = (sb*m + db*M)/255;
-		da = (sa*m + da*M)/255;
-	}
-
-DBG print("%x %x %x %x\n", dr,dg,db,da);
-	putpixel(dst, dp, rgbatopix(dr, dg, db, da));
-}
blob - 7dc45cd6fee3dab9ea799c8b0dcdb62422018e20 (mode 644)
blob + /dev/null
--- src/libdraw/md-ellipse.c
+++ /dev/null
@@ -1,247 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-/*
- * ellipse(dst, c, a, b, t, src, sp)
- *   draws an ellipse centered at c with semiaxes a,b>=0
- *   and semithickness t>=0, or filled if t<0.  point sp
- *   in src maps to c in dst
- *
- *   very thick skinny ellipses are brushed with circles (slow)
- *   others are approximated by filling between 2 ellipses
- *   criterion for very thick when b<a: t/b > 0.5*x/(1-x)
- *   where x = b/a
- */
-
-typedef struct Param	Param;
-typedef struct State	State;
-
-static	void	bellipse(int, State*, Param*);
-static	void	erect(int, int, int, int, Param*);
-static	void	eline(int, int, int, int, Param*);
-
-struct Param {
-	Memimage	*dst;
-	Memimage	*src;
-	Point			c;
-	int			t;
-	Point			sp;
-	Memimage	*disc;
-	int			op;
-};
-
-/*
- * denote residual error by e(x,y) = b^2*x^2 + a^2*y^2 - a^2*b^2
- * e(x,y) = 0 on ellipse, e(x,y) < 0 inside, e(x,y) > 0 outside
- */
-
-struct State {
-	int	a;
-	int	x;
-	vlong	a2;	/* a^2 */
-	vlong	b2;	/* b^2 */
-	vlong	b2x;	/* b^2 * x */
-	vlong	a2y;	/* a^2 * y */
-	vlong	c1;
-	vlong	c2;	/* test criteria */
-	vlong	ee;	/* ee = e(x+1/2,y-1/2) - (a^2+b^2)/4 */
-	vlong	dxe;
-	vlong	dye;
-	vlong	d2xe;
-	vlong	d2ye;
-};
-
-static
-State*
-newstate(State *s, int a, int b)
-{
-	s->x = 0;
-	s->a = a;
-	s->a2 = (vlong)(a*a);
-	s->b2 = (vlong)(b*b);
-	s->b2x = (vlong)0;
-	s->a2y = s->a2*(vlong)b;
-	s->c1 = -((s->a2>>2) + (vlong)(a&1) + s->b2);
-	s->c2 = -((s->b2>>2) + (vlong)(b&1));
-	s->ee = -s->a2y;
-	s->dxe = (vlong)0;
-	s->dye = s->ee<<1;
-	s->d2xe = s->b2<<1;
-	s->d2ye = s->a2<<1;
-	return s;
-}
-
-/*
- * return x coord of rightmost pixel on next scan line
- */
-static
-int
-step(State *s)
-{
-	while(s->x < s->a) {
-		if(s->ee+s->b2x <= s->c1 ||	/* e(x+1,y-1/2) <= 0 */
-		   s->ee+s->a2y <= s->c2) {	/* e(x+1/2,y) <= 0 (rare) */
-			s->dxe += s->d2xe;	  
-			s->ee += s->dxe;	  
-			s->b2x += s->b2;
-			s->x++;	  
-			continue;
-		}
-		s->dye += s->d2ye;	  
-		s->ee += s->dye;	  
-		s->a2y -= s->a2;
-		if(s->ee-s->a2y <= s->c2) {	/* e(x+1/2,y-1) <= 0 */
-			s->dxe += s->d2xe;	  
-			s->ee += s->dxe;	  
-			s->b2x += s->b2;
-			return s->x++;
-		}
-		break;
-	}
-	return s->x;	  
-}
-
-void
-memellipse(Memimage *dst, Point c, int a, int b, int t, Memimage *src, Point sp, int op)
-{
-	State in, out;
-	int y, inb, inx, outx, u;
-	Param p;
-
-	if(a < 0)
-		a = -a;
-	if(b < 0)
-		b = -b;
-	p.dst = dst;
-	p.src = src;
-	p.c = c;
-	p.t = t;
-	p.sp = subpt(sp, c);
-	p.disc = nil;
-	p.op = op;
-
-	u = (t<<1)*(a-b);
-	if(b<a && u>b*b || a<b && -u>a*a) {
-/*	if(b<a&&(t<<1)>b*b/a || a<b&&(t<<1)>a*a/b)	# very thick */
-		bellipse(b, newstate(&in, a, b), &p);
-		return;
-	}
-
-	if(t < 0) {
-		inb = -1;
-		newstate(&out, a, y = b);
-	} else {	
-		inb = b - t;
-		newstate(&out, a+t, y = b+t);
-	}
-	if(t > 0)
-		newstate(&in, a-t, inb);
-	inx = 0;
-	for( ; y>=0; y--) {
-		outx = step(&out);
-		if(y > inb) {
-			erect(-outx, y, outx, y, &p);
-			if(y != 0)
-				erect(-outx, -y, outx, -y, &p);
-			continue;
-		}
-		if(t > 0) {
-			inx = step(&in);
-			if(y == inb)
-				inx = 0;
-		} else if(inx > outx)
-			inx = outx;
-		erect(inx, y, outx, y, &p);
-		if(y != 0)
-			erect(inx, -y, outx, -y, &p);
-		erect(-outx, y, -inx, y, &p);
-		if(y != 0)
-			erect(-outx, -y, -inx, -y, &p);
-		inx = outx + 1;
-	}
-}
-
-static Point p00 = {0, 0};
-
-/*
- * a brushed ellipse
- */
-static
-void
-bellipse(int y, State *s, Param *p)
-{
-	int t, ox, oy, x, nx;
-
-	t = p->t;
-	p->disc = allocmemimage(Rect(-t,-t,t+1,t+1), GREY1);
-	if(p->disc == nil)
-		return;
-	memfillcolor(p->disc, DTransparent);
-	memellipse(p->disc, p00, t, t, -1, memopaque, p00, p->op);
-	oy = y;
-	ox = 0;
-	nx = x = step(s);
-	do {
-		while(nx==x && y-->0)
-			nx = step(s);
-		y++;
-		eline(-x,-oy,-ox, -y, p);
-		eline(ox,-oy,  x, -y, p);
-		eline(-x,  y,-ox, oy, p);
-		eline(ox,  y,  x, oy, p);
-		ox = x+1;
-		x = nx;
-		y--;
-		oy = y;
-	} while(oy > 0);
-}
-
-/*
- * a rectangle with closed (not half-open) coordinates expressed
- * relative to the center of the ellipse
- */
-static
-void
-erect(int x0, int y0, int x1, int y1, Param *p)
-{
-	Rectangle r;
-
-/*	print("R %d,%d %d,%d\n", x0, y0, x1, y1); */
-	r = Rect(p->c.x+x0, p->c.y+y0, p->c.x+x1+1, p->c.y+y1+1);
-	memdraw(p->dst, r, p->src, addpt(p->sp, r.min), memopaque, p00, p->op);
-}
-
-/*
- * a brushed point similarly specified
- */
-static
-void
-epoint(int x, int y, Param *p)
-{
-	Point p0;
-	Rectangle r;
-
-/*	print("P%d %d,%d\n", p->t, x, y);	*/
-	p0 = Pt(p->c.x+x, p->c.y+y);
-	r = Rpt(addpt(p0, p->disc->r.min), addpt(p0, p->disc->r.max));
-	memdraw(p->dst, r, p->src, addpt(p->sp, r.min), p->disc, p->disc->r.min, p->op);
-}
-
-/* 
- * a brushed horizontal or vertical line similarly specified
- */
-static
-void
-eline(int x0, int y0, int x1, int y1, Param *p)
-{
-/*	print("L%d %d,%d %d,%d\n", p->t, x0, y0, x1, y1); */
-	if(x1 > x0+1)
-		erect(x0+1, y0-p->t, x1-1, y1+p->t, p);
-	else if(y1 > y0+1)
-		erect(x0-p->t, y0+1, x1+p->t, y1-1, p);
-	epoint(x0, y0, p);
-	if(x1-x0 || y1-y0)
-		epoint(x1, y1, p);
-}
blob - fcacae51afdb6b43a5d33fdc4584964bfec86471 (mode 644)
blob + /dev/null
--- src/libdraw/md-fillpoly.c
+++ /dev/null
@@ -1,524 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-typedef struct Seg	Seg;
-
-struct Seg
-{
-	Point	p0;
-	Point	p1;
-	long	num;
-	long	den;
-	long	dz;
-	long	dzrem;
-	long	z;
-	long	zerr;
-	long	d;
-};
-
-static	void	zsort(Seg **seg, Seg **ep);
-static	int	ycompare(const void*, const void*);
-static	int	xcompare(const void*, const void*);
-static	int	zcompare(const void*, const void*);
-static	void	xscan(Memimage *dst, Seg **seg, Seg *segtab, int nseg, int wind, Memimage *src, Point sp, int, int, int, int);
-static	void	yscan(Memimage *dst, Seg **seg, Seg *segtab, int nseg, int wind, Memimage *src, Point sp, int, int);
-
-#if 0
-static void
-fillcolor(Memimage *dst, int left, int right, int y, Memimage *src, Point p)
-{
-	int srcval;
-
-	USED(src);
-	srcval = p.x;
-	p.x = left;
-	p.y = y;
-	memset(byteaddr(dst, p), srcval, right-left);
-}
-#endif
-
-static void
-fillline(Memimage *dst, int left, int right, int y, Memimage *src, Point p, int op)
-{
-	Rectangle r;
-
-	r.min.x = left;
-	r.min.y = y;
-	r.max.x = right;
-	r.max.y = y+1;
-	p.x += left;
-	p.y += y;
-	memdraw(dst, r, src, p, memopaque, p, op);
-}
-
-static void
-fillpoint(Memimage *dst, int x, int y, Memimage *src, Point p, int op)
-{
-	Rectangle r;
-
-	r.min.x = x;
-	r.min.y = y;
-	r.max.x = x+1;
-	r.max.y = y+1;
-	p.x += x;
-	p.y += y;
-	memdraw(dst, r, src, p, memopaque, p, op);
-}
-
-void
-memfillpoly(Memimage *dst, Point *vert, int nvert, int w, Memimage *src, Point sp, int op)
-{
-	_memfillpolysc(dst, vert, nvert, w, src, sp, 0, 0, 0, op);
-}
-
-void
-_memfillpolysc(Memimage *dst, Point *vert, int nvert, int w, Memimage *src, Point sp, int detail, int fixshift, int clipped, int op)
-{
-	Seg **seg, *segtab;
-	Point p0;
-	int i;
-
-	if(nvert == 0)
-		return;
-
-	seg = malloc((nvert+2)*sizeof(Seg*));
-	if(seg == nil)
-		return;
-	segtab = malloc((nvert+1)*sizeof(Seg));
-	if(segtab == nil) {
-		free(seg);
-		return;
-	}
-
-	sp.x = (sp.x - vert[0].x) >> fixshift;
-	sp.y = (sp.y - vert[0].y) >> fixshift;
-	p0 = vert[nvert-1];
-	if(!fixshift) {
-		p0.x <<= 1;
-		p0.y <<= 1;
-	}
-	for(i = 0; i < nvert; i++) {
-		segtab[i].p0 = p0;
-		p0 = vert[i];
-		if(!fixshift) {
-			p0.x <<= 1;
-			p0.y <<= 1;
-		}
-		segtab[i].p1 = p0;
-		segtab[i].d = 1;
-	}
-	if(!fixshift)
-		fixshift = 1;
-
-	xscan(dst, seg, segtab, nvert, w, src, sp, detail, fixshift, clipped, op);
-	if(detail)
-		yscan(dst, seg, segtab, nvert, w, src, sp, fixshift, op);
-
-	free(seg);
-	free(segtab);
-}
-
-static long
-mod(long x, long y)
-{
-	long z;
-
-	z = x%y;
-	if((long)(((ulong)z)^((ulong)y)) > 0 || z == 0)
-		return z;
-	return z + y;
-}
-
-static long
-sdiv(long x, long y)
-{
-	if((long)(((ulong)x)^((ulong)y)) >= 0 || x == 0)
-		return x/y;
-
-	return (x+((y>>30)|1))/y-1;
-}
-
-static long
-smuldivmod(long x, long y, long z, long *mod)
-{
-	vlong vx;
-
-	if(x == 0 || y == 0){
-		*mod = 0;
-		return 0;
-	}
-	vx = x;
-	vx *= y;
-	*mod = vx % z;
-	if(*mod < 0)
-		*mod += z;	/* z is always >0 */
-	if((vx < 0) == (z < 0))
-		return vx/z;
-	return -((-vx)/z);
-}
-
-static void
-xscan(Memimage *dst, Seg **seg, Seg *segtab, int nseg, int wind, Memimage *src, Point sp, int detail, int fixshift, int clipped, int op)
-{
-	long y, maxy, x, x2, xerr, xden, onehalf;
-	Seg **ep, **next, **p, **q, *s;
-	long n, i, iy, cnt, ix, ix2, minx, maxx;
-	Point pt;
-	void	(*fill)(Memimage*, int, int, int, Memimage*, Point, int);
-
-	fill = fillline;
-/*
- * This can only work on 8-bit destinations, since fillcolor is
- * just using memset on sp.x.
- *
- * I'd rather not even enable it then, since then if the general
- * code is too slow, someone will come up with a better improvement
- * than this sleazy hack.	-rsc
- *
-	if(clipped && (src->flags&Frepl) && src->depth==8 && Dx(src->r)==1 && Dy(src->r)==1) {
-		fill = fillcolor;
-		sp.x = membyteval(src);
-	}
- *
- */
-	USED(clipped);
-
-
-	for(i=0, s=segtab, p=seg; i<nseg; i++, s++) {
-		*p = s;
-		if(s->p0.y == s->p1.y)
-			continue;
-		if(s->p0.y > s->p1.y) {
-			pt = s->p0;
-			s->p0 = s->p1;
-			s->p1 = pt;
-			s->d = -s->d;
-		}
-		s->num = s->p1.x - s->p0.x;
-		s->den = s->p1.y - s->p0.y;
-		s->dz = sdiv(s->num, s->den) << fixshift;
-		s->dzrem = mod(s->num, s->den) << fixshift;
-		s->dz += sdiv(s->dzrem, s->den);
-		s->dzrem = mod(s->dzrem, s->den);
-		p++;
-	}
-	n = p-seg;
-	if(n == 0)
-		return;
-	*p = 0;
-	qsort(seg, p-seg , sizeof(Seg*), ycompare);
-
-	onehalf = 0;
-	if(fixshift)
-		onehalf = 1 << (fixshift-1);
-
-	minx = dst->clipr.min.x;
-	maxx = dst->clipr.max.x;
-
-	y = seg[0]->p0.y;
-	if(y < (dst->clipr.min.y << fixshift))
-		y = dst->clipr.min.y << fixshift;
-	iy = (y + onehalf) >> fixshift;
-	y = (iy << fixshift) + onehalf;
-	maxy = dst->clipr.max.y << fixshift;
-
-	ep = next = seg;
-
-	while(y<maxy) {
-		for(q = p = seg; p < ep; p++) {
-			s = *p;
-			if(s->p1.y < y)
-				continue;
-			s->z += s->dz;
-			s->zerr += s->dzrem;
-			if(s->zerr >= s->den) {
-				s->z++;
-				s->zerr -= s->den;
-				if(s->zerr < 0 || s->zerr >= s->den)
-					print("bad ratzerr1: %ld den %ld dzrem %ld\n", s->zerr, s->den, s->dzrem);
-			}
-			*q++ = s;
-		}
-
-		for(p = next; *p; p++) {
-			s = *p;
-			if(s->p0.y >= y)
-				break;
-			if(s->p1.y < y)
-				continue;
-			s->z = s->p0.x;
-			s->z += smuldivmod(y - s->p0.y, s->num, s->den, &s->zerr);
-			if(s->zerr < 0 || s->zerr >= s->den)
-				print("bad ratzerr2: %ld den %ld ratdzrem %ld\n", s->zerr, s->den, s->dzrem);
-			*q++ = s;
-		}
-		ep = q;
-		next = p;
-
-		if(ep == seg) {
-			if(*next == 0)
-				break;
-			iy = (next[0]->p0.y + onehalf) >> fixshift;
-			y = (iy << fixshift) + onehalf;
-			continue;
-		}
-
-		zsort(seg, ep);
-
-		for(p = seg; p < ep; p++) {
-			cnt = 0;
-			x = p[0]->z;
-			xerr = p[0]->zerr;
-			xden = p[0]->den;
-			ix = (x + onehalf) >> fixshift;
-			if(ix >= maxx)
-				break;
-			if(ix < minx)
-				ix = minx;
-			cnt += p[0]->d;
-			p++;
-			for(;;) {
-				if(p == ep) {
-					print("xscan: fill to infinity");
-					return;
-				}
-				cnt += p[0]->d;
-				if((cnt&wind) == 0)
-					break;
-				p++;
-			}
-			x2 = p[0]->z;
-			ix2 = (x2 + onehalf) >> fixshift;
-			if(ix2 <= minx)
-				continue;
-			if(ix2 > maxx)
-				ix2 = maxx;
-			if(ix == ix2 && detail) {
-				if(xerr*p[0]->den + p[0]->zerr*xden > p[0]->den*xden)
-					x++;
-				ix = (x + x2) >> (fixshift+1);
-				ix2 = ix+1;
-			}
-			(*fill)(dst, ix, ix2, iy, src, sp, op);
-		}
-		y += (1<<fixshift);
-		iy++;
-	}
-}
-
-static void
-yscan(Memimage *dst, Seg **seg, Seg *segtab, int nseg, int wind, Memimage *src, Point sp, int fixshift, int op)
-{
-	long x, maxx, y, y2, yerr, yden, onehalf;
-	Seg **ep, **next, **p, **q, *s;
-	int n, i, ix, cnt, iy, iy2, miny, maxy;
-	Point pt;
-
-	for(i=0, s=segtab, p=seg; i<nseg; i++, s++) {
-		*p = s;
-		if(s->p0.x == s->p1.x)
-			continue;
-		if(s->p0.x > s->p1.x) {
-			pt = s->p0;
-			s->p0 = s->p1;
-			s->p1 = pt;
-			s->d = -s->d;
-		}
-		s->num = s->p1.y - s->p0.y;
-		s->den = s->p1.x - s->p0.x;
-		s->dz = sdiv(s->num, s->den) << fixshift;
-		s->dzrem = mod(s->num, s->den) << fixshift;
-		s->dz += sdiv(s->dzrem, s->den);
-		s->dzrem = mod(s->dzrem, s->den);
-		p++;
-	}
-	n = p-seg;
-	if(n == 0)
-		return;
-	*p = 0;
-	qsort(seg, n , sizeof(Seg*), xcompare);
-
-	onehalf = 0;
-	if(fixshift)
-		onehalf = 1 << (fixshift-1);
-
-	miny = dst->clipr.min.y;
-	maxy = dst->clipr.max.y;
-
-	x = seg[0]->p0.x;
-	if(x < (dst->clipr.min.x << fixshift))
-		x = dst->clipr.min.x << fixshift;
-	ix = (x + onehalf) >> fixshift;
-	x = (ix << fixshift) + onehalf;
-	maxx = dst->clipr.max.x << fixshift;
-
-	ep = next = seg;
-
-	while(x<maxx) {
-		for(q = p = seg; p < ep; p++) {
-			s = *p;
-			if(s->p1.x < x)
-				continue;
-			s->z += s->dz;
-			s->zerr += s->dzrem;
-			if(s->zerr >= s->den) {
-				s->z++;
-				s->zerr -= s->den;
-				if(s->zerr < 0 || s->zerr >= s->den)
-					print("bad ratzerr1: %ld den %ld ratdzrem %ld\n", s->zerr, s->den, s->dzrem);
-			}
-			*q++ = s;
-		}
-
-		for(p = next; *p; p++) {
-			s = *p;
-			if(s->p0.x >= x)
-				break;
-			if(s->p1.x < x)
-				continue;
-			s->z = s->p0.y;
-			s->z += smuldivmod(x - s->p0.x, s->num, s->den, &s->zerr);
-			if(s->zerr < 0 || s->zerr >= s->den)
-				print("bad ratzerr2: %ld den %ld ratdzrem %ld\n", s->zerr, s->den, s->dzrem);
-			*q++ = s;
-		}
-		ep = q;
-		next = p;
-
-		if(ep == seg) {
-			if(*next == 0)
-				break;
-			ix = (next[0]->p0.x + onehalf) >> fixshift;
-			x = (ix << fixshift) + onehalf;
-			continue;
-		}
-
-		zsort(seg, ep);
-
-		for(p = seg; p < ep; p++) {
-			cnt = 0;
-			y = p[0]->z;
-			yerr = p[0]->zerr;
-			yden = p[0]->den;
-			iy = (y + onehalf) >> fixshift;
-			if(iy >= maxy)
-				break;
-			if(iy < miny)
-				iy = miny;
-			cnt += p[0]->d;
-			p++;
-			for(;;) {
-				if(p == ep) {
-					print("yscan: fill to infinity");
-					return;
-				}
-				cnt += p[0]->d;
-				if((cnt&wind) == 0)
-					break;
-				p++;
-			}
-			y2 = p[0]->z;
-			iy2 = (y2 + onehalf) >> fixshift;
-			if(iy2 <= miny)
-				continue;
-			if(iy2 > maxy)
-				iy2 = maxy;
-			if(iy == iy2) {
-				if(yerr*p[0]->den + p[0]->zerr*yden > p[0]->den*yden)
-					y++;
-				iy = (y + y2) >> (fixshift+1);
-				fillpoint(dst, ix, iy, src, sp, op);
-			}
-		}
-		x += (1<<fixshift);
-		ix++;
-	}
-}
-
-static void
-zsort(Seg **seg, Seg **ep)
-{
-	int done;
-	Seg **q, **p, *s;
-
-	if(ep-seg < 20) {
-		/* bubble sort by z - they should be almost sorted already */
-		q = ep;
-		do {
-			done = 1;
-			q--;
-			for(p = seg; p < q; p++) {
-				if(p[0]->z > p[1]->z) {
-					s = p[0];
-					p[0] = p[1];
-					p[1] = s;
-					done = 0;
-				}
-			}
-		} while(!done);
-	} else {
-		q = ep-1;
-		for(p = seg; p < q; p++) {
-			if(p[0]->z > p[1]->z) {
-				qsort(seg, ep-seg, sizeof(Seg*), zcompare);
-				break;
-			}
-		}
-	}
-}
-
-static int
-ycompare(const void *a, const void *b)
-{
-	Seg **s0, **s1;
-	long y0, y1;
-
-	s0 = (Seg**)a;
-	s1 = (Seg**)b;
-	y0 = (*s0)->p0.y;
-	y1 = (*s1)->p0.y;
-
-	if(y0 < y1)
-		return -1;
-	if(y0 == y1)
-		return 0;
-	return 1;
-}
-
-static int
-xcompare(const void *a, const void *b)
-{
-	Seg **s0, **s1;
-	long x0, x1;
-
-	s0 = (Seg**)a;
-	s1 = (Seg**)b;
-	x0 = (*s0)->p0.x;
-	x1 = (*s1)->p0.x;
-
-	if(x0 < x1)
-		return -1;
-	if(x0 == x1)
-		return 0;
-	return 1;
-}
-
-static int
-zcompare(const void *a, const void *b)
-{
-	Seg **s0, **s1;
-	long z0, z1;
-
-	s0 = (Seg**)a;
-	s1 = (Seg**)b;
-	z0 = (*s0)->z;
-	z1 = (*s1)->z;
-
-	if(z0 < z1)
-		return -1;
-	if(z0 == z1)
-		return 0;
-	return 1;
-}
blob - 3f36250f22ec43c8bf6cb3d064bc2cc8e01333e5 (mode 644)
blob + /dev/null
--- src/libdraw/md-hwdraw.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-int
-hwdraw(Memdrawparam *p)
-{
-	USED(p);
-	return 0;	/* could not satisfy request */
-}
-
blob - 923b6b448c8e075b6c258e5777eb21a24de21cdd (mode 644)
blob + /dev/null
--- src/libdraw/md-iprint.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-int
-iprint(char *fmt,...)
-{
-	USED(fmt);
-	return -1;
-}
-
blob - c7042b9fc4f1ac4f9d1c6ffb105213f4b59a42a3 (mode 644)
blob + /dev/null
--- src/libdraw/md-line.c
+++ /dev/null
@@ -1,486 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-enum
-{
-	Arrow1 = 8,
-	Arrow2 = 10,
-	Arrow3 = 3
-};
-
-/*
-static
-int
-lmin(int a, int b)
-{
-	if(a < b)
-		return a;
-	return b;
-}
-*/
-
-static
-int
-lmax(int a, int b)
-{
-	if(a > b)
-		return a;
-	return b;
-}
-
-#ifdef NOTUSED
-/*
- * Rather than line clip, we run the Bresenham loop over the full line,
- * and clip on each pixel.  This is more expensive but means that
- * lines look the same regardless of how the windowing has tiled them.
- * For speed, we check for clipping outside the loop and make the
- * test easy when possible.
- */
-
-static
-void
-horline1(Memimage *dst, Point p0, Point p1, int srcval, Rectangle clipr)
-{
-	int x, y, dy, deltay, deltax, maxx;
-	int dd, easy, e, bpp, m, m0;
-	uchar *d;
-
-	deltax = p1.x - p0.x;
-	deltay = p1.y - p0.y;
-	dd = dst->width*sizeof(u32int);
-	dy = 1;
-	if(deltay < 0){
-		dd = -dd;
-		deltay = -deltay;
-		dy = -1;
-	}
-	maxx = lmin(p1.x, clipr.max.x-1);
-	bpp = dst->depth;
-	m0 = 0xFF^(0xFF>>bpp);
-	m = m0 >> (p0.x&(7/dst->depth))*bpp;
-	easy = ptinrect(p0, clipr) && ptinrect(p1, clipr);
-	e = 2*deltay - deltax;
-	y = p0.y;
-	d = byteaddr(dst, p0);
-	deltay *= 2;
-	deltax = deltay - 2*deltax;
-	for(x=p0.x; x<=maxx; x++){
-		if(easy || (clipr.min.x<=x && clipr.min.y<=y && y<clipr.max.y))
-			*d ^= (*d^srcval) & m;
-		if(e > 0){
-			y += dy;
-			d += dd;
-			e += deltax;
-		}else
-			e += deltay;
-		d++;
-		m >>= bpp;
-		if(m == 0)
-			m = m0;
-	}
-}
-
-static
-void
-verline1(Memimage *dst, Point p0, Point p1, int srcval, Rectangle clipr)
-{
-	int x, y, deltay, deltax, maxy;
-	int easy, e, bpp, m, m0, dd;
-	uchar *d;
-
-	deltax = p1.x - p0.x;
-	deltay = p1.y - p0.y;
-	dd = 1;
-	if(deltax < 0){
-		dd = -1;
-		deltax = -deltax;
-	}
-	maxy = lmin(p1.y, clipr.max.y-1);
-	bpp = dst->depth;
-	m0 = 0xFF^(0xFF>>bpp);
-	m = m0 >> (p0.x&(7/dst->depth))*bpp;
-	easy = ptinrect(p0, clipr) && ptinrect(p1, clipr);
-	e = 2*deltax - deltay;
-	x = p0.x;
-	d = byteaddr(dst, p0);
-	deltax *= 2;
-	deltay = deltax - 2*deltay;
-	for(y=p0.y; y<=maxy; y++){
-		if(easy || (clipr.min.y<=y && clipr.min.x<=x && x<clipr.max.x))
-			*d ^= (*d^srcval) & m;
-		if(e > 0){
-			x += dd;
-			d += dd;
-			e += deltay;
-		}else
-			e += deltax;
-		d += dst->width*sizeof(u32int);
-		m >>= bpp;
-		if(m == 0)
-			m = m0;
-	}
-}
-
-static
-void
-horliner(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr)
-{
-	int x, y, sx, sy, deltay, deltax, minx, maxx;
-	int bpp, m, m0;
-	uchar *d, *s;
-
-	deltax = p1.x - p0.x;
-	deltay = p1.y - p0.y;
-	sx = drawreplxy(src->r.min.x, src->r.max.x, p0.x+dsrc.x);
-	minx = lmax(p0.x, clipr.min.x);
-	maxx = lmin(p1.x, clipr.max.x-1);
-	bpp = dst->depth;
-	m0 = 0xFF^(0xFF>>bpp);
-	m = m0 >> (minx&(7/dst->depth))*bpp;
-	for(x=minx; x<=maxx; x++){
-		y = p0.y + (deltay*(x-p0.x)+deltax/2)/deltax;
-		if(clipr.min.y<=y && y<clipr.max.y){
-			d = byteaddr(dst, Pt(x, y));
-			sy = drawreplxy(src->r.min.y, src->r.max.y, y+dsrc.y);
-			s = byteaddr(src, Pt(sx, sy));
-			*d ^= (*d^*s) & m;
-		}
-		if(++sx >= src->r.max.x)
-			sx = src->r.min.x;
-		m >>= bpp;
-		if(m == 0)
-			m = m0;
-	}
-}
-
-static
-void
-verliner(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr)
-{
-	int x, y, sx, sy, deltay, deltax, miny, maxy;
-	int bpp, m, m0;
-	uchar *d, *s;
-
-	deltax = p1.x - p0.x;
-	deltay = p1.y - p0.y;
-	sy = drawreplxy(src->r.min.y, src->r.max.y, p0.y+dsrc.y);
-	miny = lmax(p0.y, clipr.min.y);
-	maxy = lmin(p1.y, clipr.max.y-1);
-	bpp = dst->depth;
-	m0 = 0xFF^(0xFF>>bpp);
-	for(y=miny; y<=maxy; y++){
-		if(deltay == 0)	/* degenerate line */
-			x = p0.x;
-		else
-			x = p0.x + (deltax*(y-p0.y)+deltay/2)/deltay;
-		if(clipr.min.x<=x && x<clipr.max.x){
-			m = m0 >> (x&(7/dst->depth))*bpp;
-			d = byteaddr(dst, Pt(x, y));
-			sx = drawreplxy(src->r.min.x, src->r.max.x, x+dsrc.x);
-			s = byteaddr(src, Pt(sx, sy));
-			*d ^= (*d^*s) & m;
-		}
-		if(++sy >= src->r.max.y)
-			sy = src->r.min.y;
-	}
-}
-
-static
-void
-horline(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr)
-{
-	int x, y, deltay, deltax, minx, maxx;
-	int bpp, m, m0;
-	uchar *d, *s;
-
-	deltax = p1.x - p0.x;
-	deltay = p1.y - p0.y;
-	minx = lmax(p0.x, clipr.min.x);
-	maxx = lmin(p1.x, clipr.max.x-1);
-	bpp = dst->depth;
-	m0 = 0xFF^(0xFF>>bpp);
-	m = m0 >> (minx&(7/dst->depth))*bpp;
-	for(x=minx; x<=maxx; x++){
-		y = p0.y + (deltay*(x-p0.x)+deltay/2)/deltax;
-		if(clipr.min.y<=y && y<clipr.max.y){
-			d = byteaddr(dst, Pt(x, y));
-			s = byteaddr(src, addpt(dsrc, Pt(x, y)));
-			*d ^= (*d^*s) & m;
-		}
-		m >>= bpp;
-		if(m == 0)
-			m = m0;
-	}
-}
-
-static
-void
-verline(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr)
-{
-	int x, y, deltay, deltax, miny, maxy;
-	int bpp, m, m0;
-	uchar *d, *s;
-
-	deltax = p1.x - p0.x;
-	deltay = p1.y - p0.y;
-	miny = lmax(p0.y, clipr.min.y);
-	maxy = lmin(p1.y, clipr.max.y-1);
-	bpp = dst->depth;
-	m0 = 0xFF^(0xFF>>bpp);
-	for(y=miny; y<=maxy; y++){
-		if(deltay == 0)	/* degenerate line */
-			x = p0.x;
-		else
-			x = p0.x + deltax*(y-p0.y)/deltay;
-		if(clipr.min.x<=x && x<clipr.max.x){
-			m = m0 >> (x&(7/dst->depth))*bpp;
-			d = byteaddr(dst, Pt(x, y));
-			s = byteaddr(src, addpt(dsrc, Pt(x, y)));
-			*d ^= (*d^*s) & m;
-		}
-	}
-}
-#endif /* NOTUSED */
-
-static Memimage*
-membrush(int radius)
-{
-	static Memimage *brush;
-	static int brushradius;
-
-	if(brush==nil || brushradius!=radius){
-		freememimage(brush);
-		brush = allocmemimage(Rect(0, 0, 2*radius+1, 2*radius+1), memopaque->chan);
-		if(brush != nil){
-			memfillcolor(brush, DTransparent);	/* zeros */
-			memellipse(brush, Pt(radius, radius), radius, radius, -1, memopaque, Pt(radius, radius), S);
-		}
-		brushradius = radius;
-	}
-	return brush;
-}
-
-static
-void
-discend(Point p, int radius, Memimage *dst, Memimage *src, Point dsrc, int op)
-{
-	Memimage *disc;
-	Rectangle r;
-
-	disc = membrush(radius);
-	if(disc != nil){
-		r.min.x = p.x - radius;
-		r.min.y = p.y - radius;
-		r.max.x = p.x + radius+1;
-		r.max.y = p.y + radius+1;
-		memdraw(dst, r, src, addpt(r.min, dsrc), disc, Pt(0,0), op);
-	}
-}
-
-static
-void
-arrowend(Point tip, Point *pp, int end, int sin, int cos, int radius)
-{
-	int x1, x2, x3;
-
-	/* before rotation */
-	if(end == Endarrow){
-		x1 = Arrow1;
-		x2 = Arrow2;
-		x3 = Arrow3;
-	}else{
-		x1 = (end>>5) & 0x1FF;	/* distance along line from end of line to tip */
-		x2 = (end>>14) & 0x1FF;	/* distance along line from barb to tip */
-		x3 = (end>>23) & 0x1FF;	/* distance perpendicular from edge of line to barb */
-	}
-
-	/* comments follow track of right-facing arrowhead */
-	pp->x = tip.x+((2*radius+1)*sin/2-x1*cos);		/* upper side of shaft */
-	pp->y = tip.y-((2*radius+1)*cos/2+x1*sin);
-	pp++;
-	pp->x = tip.x+((2*radius+2*x3+1)*sin/2-x2*cos);		/* upper barb */
-	pp->y = tip.y-((2*radius+2*x3+1)*cos/2+x2*sin);
-	pp++;
-	pp->x = tip.x;
-	pp->y = tip.y;
-	pp++;
-	pp->x = tip.x+(-(2*radius+2*x3+1)*sin/2-x2*cos);	/* lower barb */
-	pp->y = tip.y-(-(2*radius+2*x3+1)*cos/2+x2*sin);
-	pp++;
-	pp->x = tip.x+(-(2*radius+1)*sin/2-x1*cos);		/* lower side of shaft */
-	pp->y = tip.y+((2*radius+1)*cos/2-x1*sin);
-}
-
-void
-_memimageline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, Rectangle clipr, int op)
-{
-	/*
-	 * BUG: We should really really pick off purely horizontal and purely
-	 * vertical lines and handle them separately with calls to memimagedraw
-	 * on rectangles.
-	 */
-
-	int hor;
-	int sin, cos, dx, dy, t;
-	Rectangle oclipr, r;
-	Point q, pts[10], *pp, d;
-
-	if(radius < 0)
-		return;
-	if(rectclip(&clipr, dst->r) == 0)
-		return;
-	if(rectclip(&clipr, dst->clipr) == 0)
-		return;
-	d = subpt(sp, p0);
-	if(rectclip(&clipr, rectsubpt(src->clipr, d)) == 0)
-		return;
-	if((src->flags&Frepl)==0 && rectclip(&clipr, rectsubpt(src->r, d))==0)
-		return;
-	/* this means that only verline() handles degenerate lines (p0==p1) */
-	hor = (abs(p1.x-p0.x) > abs(p1.y-p0.y));
-	/*
-	 * Clipping is a little peculiar.  We can't use Sutherland-Cohen
-	 * clipping because lines are wide.  But this is probably just fine:
-	 * we do all math with the original p0 and p1, but clip when deciding
-	 * what pixels to draw.  This means the layer code can call this routine,
-	 * using clipr to define the region being written, and get the same set
-	 * of pixels regardless of the dicing.
-	 */
-	if((hor && p0.x>p1.x) || (!hor && p0.y>p1.y)){
-		q = p0;
-		p0 = p1;
-		p1 = q;
-		t = end0;
-		end0 = end1;
-		end1 = t;
-	}
-
-	if((p0.x == p1.x || p0.y == p1.y) && (end0&0x1F) == Endsquare && (end1&0x1F) == Endsquare){
-		r.min = p0;
-		r.max = p1;
-		if(p0.x == p1.x){
-			r.min.x -= radius;
-			r.max.x += radius+1;
-		}
-		else{
-			r.min.y -= radius;
-			r.max.y += radius+1;
-		}
-		oclipr = dst->clipr;
-		dst->clipr = clipr;
-		memimagedraw(dst, r, src, sp, memopaque, sp, op);
-		dst->clipr = oclipr;
-		return;
-	}
-
-/*    Hard: */
-	/* draw thick line using polygon fill */
-	icossin2(p1.x-p0.x, p1.y-p0.y, &cos, &sin);
-	dx = (sin*(2*radius+1))/2;
-	dy = (cos*(2*radius+1))/2;
-	pp = pts;
-	oclipr = dst->clipr;
-	dst->clipr = clipr;
-	q.x = ICOSSCALE*p0.x+ICOSSCALE/2-cos/2;
-	q.y = ICOSSCALE*p0.y+ICOSSCALE/2-sin/2;
-	switch(end0 & 0x1F){
-	case Enddisc:
-		discend(p0, radius, dst, src, d, op);
-		/* fall through */
-	case Endsquare:
-	default:
-		pp->x = q.x-dx;
-		pp->y = q.y+dy;
-		pp++;
-		pp->x = q.x+dx;
-		pp->y = q.y-dy;
-		pp++;
-		break;
-	case Endarrow:
-		arrowend(q, pp, end0, -sin, -cos, radius);
-		_memfillpolysc(dst, pts, 5, ~0, src, addpt(pts[0], mulpt(d, ICOSSCALE)), 1, 10, 1, op);
-		pp[1] = pp[4];
-		pp += 2;
-	}
-	q.x = ICOSSCALE*p1.x+ICOSSCALE/2+cos/2;
-	q.y = ICOSSCALE*p1.y+ICOSSCALE/2+sin/2;
-	switch(end1 & 0x1F){
-	case Enddisc:
-		discend(p1, radius, dst, src, d, op);
-		/* fall through */
-	case Endsquare:
-	default:
-		pp->x = q.x+dx;
-		pp->y = q.y-dy;
-		pp++;
-		pp->x = q.x-dx;
-		pp->y = q.y+dy;
-		pp++;
-		break;
-	case Endarrow:
-		arrowend(q, pp, end1, sin, cos, radius);
-		_memfillpolysc(dst, pp, 5, ~0, src, addpt(pts[0], mulpt(d, ICOSSCALE)), 1, 10, 1, op);
-		pp[1] = pp[4];
-		pp += 2;
-	}
-	_memfillpolysc(dst, pts, pp-pts, ~0, src, addpt(pts[0], mulpt(d, ICOSSCALE)), 0, 10, 1, op);
-	dst->clipr = oclipr;
-	return;
-}
-
-void
-memimageline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, int op)
-{
-	_memimageline(dst, p0, p1, end0, end1, radius, src, sp, dst->clipr, op);
-}
-
-/*
- * Simple-minded conservative code to compute bounding box of line.
- * Result is probably a little larger than it needs to be.
- */
-static
-void
-addbbox(Rectangle *r, Point p)
-{
-	if(r->min.x > p.x)
-		r->min.x = p.x;
-	if(r->min.y > p.y)
-		r->min.y = p.y;
-	if(r->max.x < p.x+1)
-		r->max.x = p.x+1;
-	if(r->max.y < p.y+1)
-		r->max.y = p.y+1;
-}
-
-int
-memlineendsize(int end)
-{
-	int x3;
-
-	if((end&0x3F) != Endarrow)
-		return 0;
-	if(end == Endarrow)
-		x3 = Arrow3;
-	else
-		x3 = (end>>23) & 0x1FF;
-	return x3;
-}
-
-Rectangle
-memlinebbox(Point p0, Point p1, int end0, int end1, int radius)
-{
-	Rectangle r, r1;
-	int extra;
-
-	r.min.x = 10000000;
-	r.min.y = 10000000;
-	r.max.x = -10000000;
-	r.max.y = -10000000;
-	extra = lmax(memlineendsize(end0), memlineendsize(end1));
-	r1 = insetrect(canonrect(Rpt(p0, p1)), -(radius+extra));
-	addbbox(&r, r1.min);
-	addbbox(&r, r1.max);
-	return r;
-}
blob - 6788fa90b3a78b55526c106beac8620ff9269e7b (mode 644)
blob + /dev/null
--- src/libdraw/md-load.c
+++ /dev/null
@@ -1,72 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-int
-_loadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
-{
-	int y, l, lpart, rpart, mx, m, mr;
-	uchar *q;
-
-	if(!rectinrect(r, i->r))
-		return -1;
-	l = bytesperline(r, i->depth);
-	if(ndata < l*Dy(r))
-		return -1;
-	ndata = l*Dy(r);
-	q = byteaddr(i, r.min);
-	mx = 7/i->depth;
-	lpart = (r.min.x & mx) * i->depth;
-	rpart = (r.max.x & mx) * i->depth;
-	m = 0xFF >> lpart;
-	/* may need to do bit insertion on edges */
-	if(l == 1){	/* all in one byte */
-		if(rpart)
-			m ^= 0xFF >> rpart;
-		for(y=r.min.y; y<r.max.y; y++){
-			*q ^= (*data^*q) & m;
-			q += i->width*sizeof(u32int);
-			data++;
-		}
-		return ndata;
-	}
-	if(lpart==0 && rpart==0){	/* easy case */
-		for(y=r.min.y; y<r.max.y; y++){
-			memmove(q, data, l);
-			q += i->width*sizeof(u32int);
-			data += l;
-		}
-		return ndata;
-	}
-	mr = 0xFF ^ (0xFF >> rpart);
-	if(lpart!=0 && rpart==0){
-		for(y=r.min.y; y<r.max.y; y++){
-			*q ^= (*data^*q) & m;
-			if(l > 1)
-				memmove(q+1, data+1, l-1);
-			q += i->width*sizeof(u32int);
-			data += l;
-		}
-		return ndata;
-	}
-	if(lpart==0 && rpart!=0){
-		for(y=r.min.y; y<r.max.y; y++){
-			if(l > 1)
-				memmove(q, data, l-1);
-			q[l-1] ^= (data[l-1]^q[l-1]) & mr;
-			q += i->width*sizeof(u32int);
-			data += l;
-		}
-		return ndata;
-	}
-	for(y=r.min.y; y<r.max.y; y++){
-		*q ^= (*data^*q) & m;
-		if(l > 2)
-			memmove(q+1, data+1, l-2);
-		q[l-1] ^= (data[l-1]^q[l-1]) & mr;
-		q += i->width*sizeof(u32int);
-		data += l;
-	}
-	return ndata;
-}
blob - e8d5efc394486da4f81a362839441ed54c1f5030 (mode 644)
blob + /dev/null
--- src/libdraw/md-mkcmap.c
+++ /dev/null
@@ -1,79 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-/*
-struct Memcmap
-{
-	uchar	cmap2rgb[3*256];
-	uchar	rgb2cmap[16*16*16];
-};
-*/
-
-static Memcmap*
-mkcmap(void)
-{
-	static Memcmap def;
-
-	int i, rgb, r, g, b;
-
-	for(i=0; i<256; i++){
-		rgb = cmap2rgb(i);
-		r = (rgb>>16)&0xff;
-		g = (rgb>>8)&0xff;
-		b = rgb&0xff;
-		def.cmap2rgb[3*i] = r;
-		def.cmap2rgb[3*i+1] = g;
-		def.cmap2rgb[3*i+2] = b;
-	}
-
-	for(r=0; r<16; r++)
-	for(g=0; g<16; g++)
-	for(b=0; b<16; b++)
-		def.rgb2cmap[r*16*16+g*16+b] = rgb2cmap(r*0x11, g*0x11, b*0x11);
-	return &def;
-}
-
-void
-main(int argc, char **argv)
-{
-	Memcmap *c;
-	int i, j, inferno;
-
-	inferno = 0;
-	ARGBEGIN{
-	case 'i':
-		inferno = 1;
-	}ARGEND
-
-	memimageinit();
-	c = mkcmap();
-	if(!inferno)
-		print("#include <u.h>\n#include <libc.h>\n");
-	else
-		print("#include \"lib9.h\"\n");
-	print("#include <draw.h>\n");
-	print("#include <memdraw.h>\n\n");
-	print("static Memcmap def = {\n");
-	print("/* cmap2rgb */ {\n");
-	for(i=0; i<sizeof(c->cmap2rgb); ){
-		print("\t");
-		for(j=0; j<16; j++, i++)
-			print("0x%2.2ux,", c->cmap2rgb[i]);
-		print("\n");
-	}
-	print("},\n");
-	print("/* rgb2cmap */ {\n");
-	for(i=0; i<sizeof(c->rgb2cmap);){
-		print("\t");
-		for(j=0; j<16; j++, i++)
-			print("0x%2.2ux,", c->rgb2cmap[i]);
-		print("\n");
-	}
-	print("}\n");
-	print("};\n");
-	print("Memcmap *memdefcmap = &def;\n");
-	print("void _memmkcmap(void){}\n");
-	exits(0);
-}
blob - c8d926e4a69378605dcfb59f83ebbc8e8c24f700 (mode 644)
blob + /dev/null
--- src/libdraw/md-openmemsubfont.c
+++ /dev/null
@@ -1,53 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-Memsubfont*
-openmemsubfont(char *name)
-{
-	Memsubfont *sf;
-	Memimage *i;
-	Fontchar *fc;
-	int fd, n;
-	char hdr[3*12+4+1];
-	uchar *p;
-
-	fd = open(name, OREAD);
-	if(fd < 0)
-		return nil;
-	p = nil;
-	i = readmemimage(fd);
-	if(i == nil)
-		goto Err;
-	if(read(fd, hdr, 3*12) != 3*12){
-		werrstr("openmemsubfont: header read error: %r");
-		goto Err;
-	}
-	n = atoi(hdr);
-	p = malloc(6*(n+1));
-	if(p == nil)
-		goto Err;
-	if(read(fd, p, 6*(n+1)) != 6*(n+1)){
-		werrstr("openmemsubfont: fontchar read error: %r");
-		goto Err;
-	}
-	fc = malloc(sizeof(Fontchar)*(n+1));
-	if(fc == nil)
-		goto Err;
-	_unpackinfo(fc, p, n);
-	sf = allocmemsubfont(name, n, atoi(hdr+12), atoi(hdr+24), fc, i);
-	if(sf == nil){
-		free(fc);
-		goto Err;
-	}
-	free(p);
-	return sf;
-Err:
-	close(fd);
-	if (i != nil)
-		freememimage(i);
-	if (p != nil)
-		free(p);
-	return nil;
-}
blob - d16c0a92a7bb0407aa5be4a7553b84a8a82ae966 (mode 644)
blob + /dev/null
--- src/libdraw/md-poly.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-void
-mempoly(Memimage *dst, Point *vert, int nvert, int end0, int end1, int radius, Memimage *src, Point sp, int op)
-{
-	int i, e0, e1;
-	Point d;
-
-	if(nvert < 2)
-		return;
-	d = subpt(sp, vert[0]);
-	for(i=1; i<nvert; i++){
-		e0 = e1 = Enddisc;
-		if(i == 1)
-			e0 = end0;
-		if(i == nvert-1)
-			e1 = end1;
-		memline(dst, vert[i-1], vert[i], e0, e1, radius, src, addpt(d, vert[i-1]), op);
-	}
-}
blob - d7a535d7f2692e7cc411d51356f635841949dfb2 (mode 644)
blob + /dev/null
--- src/libdraw/md-read.c
+++ /dev/null
@@ -1,111 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-Memimage*
-readmemimage(int fd)
-{
-	char hdr[5*12+1];
-	int dy;
-	u32int chan;
-	uint l, n;
-	int m, j;
-	int new, miny, maxy;
-	Rectangle r;
-	uchar *tmp;
-	int ldepth, chunk;
-	Memimage *i;
-
-	if(readn(fd, hdr, 11) != 11){
-		werrstr("readimage: short header");
-		return nil;
-	}
-	if(memcmp(hdr, "compressed\n", 11) == 0)
-		return creadmemimage(fd);
-	if(readn(fd, hdr+11, 5*12-11) != 5*12-11){
-		werrstr("readimage: short header (2)");
-		return nil;
-	}
-
-	/*
-	 * distinguish new channel descriptor from old ldepth.
-	 * channel descriptors have letters as well as numbers,
-	 * while ldepths are a single digit formatted as %-11d.
-	 */
-	new = 0;
-	for(m=0; m<10; m++){
-		if(hdr[m] != ' '){
-			new = 1;
-			break;
-		}
-	}
-	if(hdr[11] != ' '){
-		werrstr("readimage: bad format");
-		return nil;
-	}
-	if(new){
-		hdr[11] = '\0';
-		if((chan = strtochan(hdr)) == 0){
-			werrstr("readimage: bad channel string %s", hdr);
-			return nil;
-		}
-	}else{
-		ldepth = ((int)hdr[10])-'0';
-		if(ldepth<0 || ldepth>3){
-			werrstr("readimage: bad ldepth %d", ldepth);
-			return nil;
-		}
-		chan = drawld2chan[ldepth];
-	}
-
-	r.min.x = atoi(hdr+1*12);
-	r.min.y = atoi(hdr+2*12);
-	r.max.x = atoi(hdr+3*12);
-	r.max.y = atoi(hdr+4*12);
-	if(r.min.x>r.max.x || r.min.y>r.max.y){
-		werrstr("readimage: bad rectangle");
-		return nil;
-	}
-
-	miny = r.min.y;
-	maxy = r.max.y;
-
-	l = bytesperline(r, chantodepth(chan));
-	i = allocmemimage(r, chan);
-	if(i == nil)
-		return nil;
-	chunk = 32*1024;
-	if(chunk < l)
-		chunk = l;
-	tmp = malloc(chunk);
-	if(tmp == nil)
-		goto Err;
-	while(maxy > miny){
-		dy = maxy - miny;
-		if(dy*l > chunk)
-			dy = chunk/l;
-		if(dy <= 0){
-			werrstr("readmemimage: image too wide for buffer");
-			goto Err;
-		}
-		n = dy*l;
-		m = readn(fd, tmp, n);
-		if(m != n){
-			werrstr("readmemimage: read count %d not %d: %r", m, n);
-   Err:
- 			freememimage(i);
-			free(tmp);
-			return nil;
-		}
-		if(!new)	/* an old image: must flip all the bits */
-			for(j=0; j<chunk; j++)
-				tmp[j] ^= 0xFF;
-
-		if(loadmemimage(i, Rect(r.min.x, miny, r.max.x, miny+dy), tmp, chunk) <= 0)
-			goto Err;
-		miny += dy;
-	}
-	free(tmp);
-	return i;
-}
blob - 6ae19c012513ebfe5d368232c19228cca995049c (mode 644)
blob + /dev/null
--- src/libdraw/md-string.c
+++ /dev/null
@@ -1,66 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-Point
-memimagestring(Memimage *b, Point p, Memimage *color, Point cp, Memsubfont *f, char *cs)
-{
-	int w, width;
-	uchar *s;
-	Rune c;
-	Fontchar *i;
-
-	s = (uchar*)cs;
-	for(; c=*s; p.x+=width, cp.x+=width){
-		width = 0;
-		if(c < Runeself)
-			s++;
-		else{
-			w = chartorune(&c, (char*)s);
-			if(w == 0){
-				s++;
-				continue;
-			}
-			s += w;
-		}
-		if(c >= f->n)
-			continue;
-		i = f->info+c;
-		width = i->width;
-		memdraw(b, Rect(p.x+i->left, p.y+i->top, p.x+i->left+(i[1].x-i[0].x), p.y+i->bottom),
-			color, cp, f->bits, Pt(i->x, i->top), SoverD);
-	}
-	return p;
-}
-
-Point
-memsubfontwidth(Memsubfont *f, char *cs)
-{
-	Rune c;
-	Point p;
-	uchar *s;
-	Fontchar *i;
-	int w, width;
-
-	p = Pt(0, f->height);
-	s = (uchar*)cs;
-	for(; c=*s; p.x+=width){
-		width = 0;
-		if(c < Runeself)
-			s++;
-		else{
-			w = chartorune(&c, (char*)s);
-			if(w == 0){
-				s++;
-				continue;
-			}
-			s += w;
-		}
-		if(c >= f->n)
-			continue;
-		i = f->info+c;
-		width = i->width;
-	}
-	return p;
-}
blob - e2bdee5c02d1af5f0551f015329c5ff6278ee58c (mode 644)
blob + /dev/null
--- src/libdraw/md-subfont.c
+++ /dev/null
@@ -1,34 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-Memsubfont*
-allocmemsubfont(char *name, int n, int height, int ascent, Fontchar *info, Memimage *i)
-{
-	Memsubfont *f;
-
-	f = malloc(sizeof(Memsubfont));
-	if(f == 0)
-		return 0;
-	f->n = n;
-	f->height = height;
-	f->ascent = ascent;
-	f->info = info;
-	f->bits = i;
-	if(name)
-		f->name = strdup(name);
-	else
-		f->name = 0;
-	return f;
-}
-
-void
-freememsubfont(Memsubfont *f)
-{
-	if(f == 0)
-		return;
-	free(f->info);	/* note: f->info must have been malloc'ed! */
-	freememimage(f->bits);
-	free(f);
-}
blob - 86835757b3dcf34a83621d1c04b04594c8e397e5 (mode 644)
blob + /dev/null
--- src/libdraw/md-unload.c
+++ /dev/null
@@ -1,25 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-int
-_unloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
-{
-	int y, l;
-	uchar *q;
-
-	if(!rectinrect(r, i->r))
-		return -1;
-	l = bytesperline(r, i->depth);
-	if(ndata < l*Dy(r))
-		return -1;
-	ndata = l*Dy(r);
-	q = byteaddr(i, r.min);
-	for(y=r.min.y; y<r.max.y; y++){
-		memmove(data, q, l);
-		q += i->width*sizeof(u32int);
-		data += l;
-	}
-	return ndata;
-}
blob - c03c58e8728711e66d2a458c8341e737df9f3a71 (mode 644)
blob + /dev/null
--- src/libdraw/md-write.c
+++ /dev/null
@@ -1,183 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-#define	CHUNK	8000
-
-#define	HSHIFT	3	/* HSHIFT==5 runs slightly faster, but hash table is 64x bigger */
-#define	NHASH	(1<<(HSHIFT*NMATCH))
-#define	HMASK	(NHASH-1)
-#define	hupdate(h, c)	((((h)<<HSHIFT)^(c))&HMASK)
-typedef struct Hlist Hlist;
-struct Hlist{
-	uchar *s;
-	Hlist *next, *prev;
-};
-
-int
-writememimage(int fd, Memimage *i)
-{
-	uchar *outbuf, *outp, *eout;		/* encoded data, pointer, end */
-	uchar *loutp;				/* start of encoded line */
-	Hlist *hash;				/* heads of hash chains of past strings */
-	Hlist *chain, *hp;			/* hash chain members, pointer */
-	Hlist *cp;				/* next Hlist to fall out of window */
-	int h;					/* hash value */
-	uchar *line, *eline;			/* input line, end pointer */
-	uchar *data, *edata;			/* input buffer, end pointer */
-	u32int n;				/* length of input buffer */
-	u32int nb;				/* # of bytes returned by unloadimage */
-	int bpl;				/* input line length */
-	int offs, runlen;			/* offset, length of consumed data */
-	uchar dumpbuf[NDUMP];			/* dump accumulator */
-	int ndump;				/* length of dump accumulator */
-	int miny, dy;				/* y values while unloading input */
-	int ncblock;				/* size of compressed blocks */
-	Rectangle r;
-	uchar *p, *q, *s, *es, *t;
-	char hdr[11+5*12+1];
-	char cbuf[20];
-
-	r = i->r;
-	bpl = bytesperline(r, i->depth);
-	n = Dy(r)*bpl;
-	data = malloc(n);
-	ncblock = _compblocksize(r, i->depth);
-	outbuf = malloc(ncblock);
-	hash = malloc(NHASH*sizeof(Hlist));
-	chain = malloc(NMEM*sizeof(Hlist));
-	if(data == 0 || outbuf == 0 || hash == 0 || chain == 0){
-	ErrOut:
-		free(data);
-		free(outbuf);
-		free(hash);
-		free(chain);
-		return -1;
-	}
-	for(miny = r.min.y; miny != r.max.y; miny += dy){
-		dy = r.max.y-miny;
-		if(dy*bpl > CHUNK)
-			dy = CHUNK/bpl;
-		nb = unloadmemimage(i, Rect(r.min.x, miny, r.max.x, miny+dy),
-			data+(miny-r.min.y)*bpl, dy*bpl);
-		if(nb != dy*bpl)
-			goto ErrOut;
-	}
-	sprint(hdr, "compressed\n%11s %11d %11d %11d %11d ",
-		chantostr(cbuf, i->chan), r.min.x, r.min.y, r.max.x, r.max.y);
-	if(write(fd, hdr, 11+5*12) != 11+5*12)
-		goto ErrOut;
-	edata = data+n;
-	eout = outbuf+ncblock;
-	line = data;
-	r.max.y = r.min.y;
-	while(line != edata){
-		memset(hash, 0, NHASH*sizeof(Hlist));
-		memset(chain, 0, NMEM*sizeof(Hlist));
-		cp = chain;
-		h = 0;
-		outp = outbuf;
-		for(n = 0; n != NMATCH; n++)
-			h = hupdate(h, line[n]);
-		loutp = outbuf;
-		while(line != edata){
-			ndump = 0;
-			eline = line+bpl;
-			for(p = line; p != eline; ){
-				if(eline-p < NRUN)
-					es = eline;
-				else
-					es = p+NRUN;
-				q = 0;
-				runlen = 0;
-				for(hp = hash[h].next; hp; hp = hp->next){
-					s = p + runlen;
-					if(s >= es)
-						continue;
-					t = hp->s + runlen;
-					for(; s >= p; s--)
-						if(*s != *t--)
-							goto matchloop;
-					t += runlen+2;
-					s += runlen+2;
-					for(; s < es; s++)
-						if(*s != *t++)
-							break;
-					n = s-p;
-					if(n > runlen){
-						runlen = n;
-						q = hp->s;
-						if(n == NRUN)
-							break;
-					}
-			matchloop: ;
-				}
-				if(runlen < NMATCH){
-					if(ndump == NDUMP){
-						if(eout-outp < ndump+1)
-							goto Bfull;
-						*outp++ = ndump-1+128;
-						memmove(outp, dumpbuf, ndump);
-						outp += ndump;
-						ndump = 0;
-					}
-					dumpbuf[ndump++] = *p;
-					runlen = 1;
-				}
-				else{
-					if(ndump != 0){
-						if(eout-outp < ndump+1)
-							goto Bfull;
-						*outp++ = ndump-1+128;
-						memmove(outp, dumpbuf, ndump);
-						outp += ndump;
-						ndump = 0;
-					}
-					offs = p-q-1;
-					if(eout-outp < 2)
-						goto Bfull;
-					*outp++ = ((runlen-NMATCH)<<2) + (offs>>8);
-					*outp++ = offs&255;
-				}
-				for(q = p+runlen; p != q; p++){
-					if(cp->prev)
-						cp->prev->next = 0;
-					cp->next = hash[h].next;
-					cp->prev = &hash[h];
-					if(cp->next)
-						cp->next->prev = cp;
-					cp->prev->next = cp;
-					cp->s = p;
-					if(++cp == &chain[NMEM])
-						cp = chain;
-					if(edata-p > NMATCH)
-						h = hupdate(h, p[NMATCH]);
-				}
-			}
-			if(ndump != 0){
-				if(eout-outp < ndump+1)
-					goto Bfull;
-				*outp++ = ndump-1+128;
-				memmove(outp, dumpbuf, ndump);
-				outp += ndump;
-			}
-			line = eline;
-			loutp = outp;
-			r.max.y++;
-		}
-	Bfull:
-		if(loutp == outbuf)
-			goto ErrOut;
-		n = loutp-outbuf;
-		sprint(hdr, "%11d %11ld ", r.max.y, n);
-		write(fd, hdr, 2*12);
-		write(fd, outbuf, n);
-		r.min.y = r.max.y;
-	}
-	free(data);
-	free(outbuf);
-	free(hash);
-	free(chain);
-	return 0;
-}
blob - da115f31a1f1796c3df08277743aaa58afd44882
blob + f1c981dbd0bf4ba060d1f4e4faf334642d308008
--- src/libdraw/mkfile
+++ src/libdraw/mkfile
@@ -17,6 +17,8 @@ OFILES=\
 	debug.$O\
 	defont.$O\
 	draw.$O\
+	drawclient.$O\
+	drawfcall.$O\
 	drawrepl.$O\
 	egetrect.$O\
 	ellipse.$O\
@@ -29,11 +31,12 @@ OFILES=\
 	icossin.$O\
 	icossin2.$O\
 	init.$O\
+	keyboard.$O\
 	line.$O\
-	latin1.$O\
 	loadimage.$O\
 	menuhit.$O\
 	mkfont.$O\
+	mouse.$O\
 	openfont.$O\
 	poly.$O\
 	readimage.$O\
@@ -42,6 +45,7 @@ OFILES=\
 	replclipr.$O\
 	rgb.$O\
 	scroll.$O\
+	snarf.$O\
 	string.$O\
 	stringbg.$O\
 	stringsubfont.$O\
@@ -53,79 +57,17 @@ OFILES=\
 	window.$O\
 	writeimage.$O\
 	writesubfont.$O\
-	md-alloc.$O\
-	md-arc.$O\
-	md-cload.$O\
-	md-cmap.$O\
-	md-cread.$O\
-	md-defont.$O\
-	md-draw.$O\
-	md-ellipse.$O\
-	md-fillpoly.$O\
-	md-hwdraw.$O\
-	md-iprint.$O\
-	md-line.$O\
-	md-load.$O\
-	md-openmemsubfont.$O\
-	md-poly.$O\
-	md-read.$O\
-	md-string.$O\
-	md-subfont.$O\
-	md-unload.$O\
-	md-write.$O\
-	ml-draw.$O\
-	ml-lalloc.$O\
-	ml-layerop.$O\
-	ml-ldelete.$O\
-	ml-lhide.$O\
-	ml-line.$O\
-	ml-load.$O\
-	ml-lorigin.$O\
-	ml-lsetrefresh.$O\
-	ml-ltofront.$O\
-	ml-ltorear.$O\
-	ml-unload.$O\
-	devdraw.$O\
+	wsys.$O\
 	unix.$O\
 
 HFILES=\
 	$PLAN9/include/draw.h\
-	$PLAN9/include/memdraw.h\
-	$PLAN9/include/memlayer.h\
+	$PLAN9/include/drawfcall.h\
+	$PLAN9/include/mux.h\
 	$PLAN9/include/event.h\
 	$PLAN9/include/cursor.h\
 	$PLAN9/include/mouse.h\
 	$PLAN9/include/keyboard.h\
 
-# some of these should move to wsysofiles
-
-XHFILES=\
-	x11-inc.h\
-	x11-memdraw.h\
-
-<|sh ./mkwsysrules.sh
-
-WSYSOFILES=\
-	$WSYSTYPE-alloc.$O\
-	$WSYSTYPE-cload.$O\
-	$WSYSTYPE-draw.$O\
-	$WSYSTYPE-event.$O\
-	$WSYSTYPE-fill.$O\
-	$WSYSTYPE-get.$O\
-	$WSYSTYPE-init.$O\
-	$WSYSTYPE-itrans.$O\
-	$WSYSTYPE-keyboard.$O\
-	$WSYSTYPE-keysym2ucs.$O\
-	$WSYSTYPE-load.$O\
-	$WSYSTYPE-mouse.$O\
-	$WSYSTYPE-pixelbits.$O\
-	$WSYSTYPE-unload.$O\
-	$WSYSTYPE-wsys.$O\
-
-OFILES=$OFILES $WSYSOFILES
-
 <$PLAN9/src/mksyslib
 
-test: test.o $PLAN9/lib/$LIB
-	gcc -o test test.o -L$PLAN9/lib -ldraw -l9 -lfmt -lutf -L$X11/lib -lX11 -lm
-
blob - c352a0b2c3fbceaab100c4d5af5f7ad829dd0921 (mode 644)
blob + /dev/null
--- src/libdraw/ml-draw.c
+++ /dev/null
@@ -1,192 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include <memlayer.h>
-
-struct Draw
-{
-	Point	deltas;
-	Point	deltam;
-	Memlayer		*dstlayer;
-	Memimage	*src;
-	Memimage	*mask;
-	int	op;
-};
-
-static
-void
-ldrawop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave)
-{
-	struct Draw *d;
-	Point p0, p1;
-	Rectangle oclipr, srcr, r, mr;
-	int ok;
-
-	d = etc;
-	if(insave && d->dstlayer->save==nil)
-		return;
-
-	p0 = addpt(screenr.min, d->deltas);
-	p1 = addpt(screenr.min, d->deltam);
-
-	if(insave){
-		r = rectsubpt(screenr, d->dstlayer->delta);
-		clipr = rectsubpt(clipr, d->dstlayer->delta);
-	}else
-		r = screenr;
-
-	/* now in logical coordinates */
-
-	/* clipr may have narrowed what we should draw on, so clip if necessary */
-	if(!rectinrect(r, clipr)){
-		oclipr = dst->clipr;
-		dst->clipr = clipr;
-		ok = drawclip(dst, &r, d->src, &p0, d->mask, &p1, &srcr, &mr);
-		dst->clipr = oclipr;
-		if(!ok)
-			return;
-	}
-	memdraw(dst, r, d->src, p0, d->mask, p1, d->op);
-}
-
-void
-memdraw(Memimage *dst, Rectangle r, Memimage *src, Point p0, Memimage *mask, Point p1, int op)
-{
-	struct Draw d;
-	Rectangle srcr, tr, mr;
-	Memlayer *dl, *sl;
-
-	if(drawdebug)
-		iprint("memdraw %p %R %p %P %p %P\n", dst, r, src, p0, mask, p1);
-
-	if(mask == nil)
-		mask = memopaque;
-
-	if(mask->layer){
-if(drawdebug)	iprint("mask->layer != nil\n");
-		return;	/* too hard, at least for now */
-	}
-
-    Top:
-	if(dst->layer==nil && src->layer==nil){
-		memimagedraw(dst, r, src, p0, mask, p1, op);
-		return;
-	}
-
-	if(drawclip(dst, &r, src, &p0, mask, &p1, &srcr, &mr) == 0){
-if(drawdebug)	iprint("drawclip dstcr %R srccr %R maskcr %R\n", dst->clipr, src->clipr, mask->clipr);
-		return;
-	}
-
-	/*
- 	 * Convert to screen coordinates.
-	 */
-	dl = dst->layer;
-	if(dl != nil){
-		r.min.x += dl->delta.x;
-		r.min.y += dl->delta.y;
-		r.max.x += dl->delta.x;
-		r.max.y += dl->delta.y;
-	}
-    Clearlayer:
-	if(dl!=nil && dl->clear){
-		if(src == dst){
-			p0.x += dl->delta.x;
-			p0.y += dl->delta.y;
-			src = dl->screen->image;
-		}
-		dst = dl->screen->image;
-		goto Top;
-	}
-
-	sl = src->layer;
-	if(sl != nil){
-		p0.x += sl->delta.x;
-		p0.y += sl->delta.y;
-		srcr.min.x += sl->delta.x;
-		srcr.min.y += sl->delta.y;
-		srcr.max.x += sl->delta.x;
-		srcr.max.y += sl->delta.y;
-	}
-
-	/*
-	 * Now everything is in screen coordinates.
-	 * mask is an image.  dst and src are images or obscured layers.
-	 */
-
-	/*
-	 * if dst and src are the same layer, just draw in save area and expose.
-	 */
-	if(dl!=nil && dst==src){
-		if(dl->save == nil)
-			return;	/* refresh function makes this case unworkable */
-		if(rectXrect(r, srcr)){
-			tr = r;
-			if(srcr.min.x < tr.min.x){
-				p1.x += tr.min.x - srcr.min.x;
-				tr.min.x = srcr.min.x;
-			}
-			if(srcr.min.y < tr.min.y){
-				p1.y += tr.min.x - srcr.min.x;
-				tr.min.y = srcr.min.y;
-			}
-			if(srcr.max.x > tr.max.x)
-				tr.max.x = srcr.max.x;
-			if(srcr.max.y > tr.max.y)
-				tr.max.y = srcr.max.y;
-			memlhide(dst, tr);
-		}else{
-			memlhide(dst, r);
-			memlhide(dst, srcr);
-		}
-		memdraw(dl->save, rectsubpt(r, dl->delta), dl->save,
-			subpt(srcr.min, src->layer->delta), mask, p1, op);
-		memlexpose(dst, r);
-		return;
-	}
-
-	if(sl){
-		if(sl->clear){
-			src = sl->screen->image;
-			if(dl != nil){
-				r.min.x -= dl->delta.x;
-				r.min.y -= dl->delta.y;
-				r.max.x -= dl->delta.x;
-				r.max.y -= dl->delta.y;
-			}
-			goto Top;
-		}
-		/* relatively rare case; use save area */
-		if(sl->save == nil)
-			return;	/* refresh function makes this case unworkable */
-		memlhide(src, srcr);
-		/* convert back to logical coordinates */
-		p0.x -= sl->delta.x;
-		p0.y -= sl->delta.y;
-		srcr.min.x -= sl->delta.x;
-		srcr.min.y -= sl->delta.y;
-		srcr.max.x -= sl->delta.x;
-		srcr.max.y -= sl->delta.y;
-		src = src->layer->save;
-	}
-
-	/*
-	 * src is now an image.  dst may be an image or a clear layer
-	 */
-	if(dst->layer==nil)
-		goto Top;
-	if(dst->layer->clear)
-		goto Clearlayer;
-
-	/*
-	 * dst is an obscured layer
-	 */
-	d.deltas = subpt(p0, r.min);
-	d.deltam = subpt(p1, r.min);
-	d.dstlayer = dl;
-	d.src = src;
-	d.op = op;
-	d.mask = mask;
-	_memlayerop(ldrawop, dst, r, r, &d);
-}
blob - 17d934d319271a9fc2e8d1c44faebad413d7339b (mode 644)
blob + /dev/null
--- src/libdraw/ml-lalloc.c
+++ /dev/null
@@ -1,79 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include <memlayer.h>
-
-Memimage*
-memlalloc(Memscreen *s, Rectangle screenr, Refreshfn refreshfn, void *refreshptr, u32int val)
-{
-	Memlayer *l;
-	Memimage *n;
-	static Memimage *paint;
-
-	if(paint == nil){
-		paint = allocmemimage(Rect(0,0,1,1), RGBA32);
-		if(paint == nil)
-			return nil;
-		paint->flags |= Frepl;
-		paint->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
-	}
-
-	n = allocmemimaged(screenr, s->image->chan, s->image->data, nil);
-	if(n == nil)
-		return nil;
-	l = malloc(sizeof(Memlayer));
-	if(l == nil){
-		free(n);
-		return nil;
-	}
-
-	l->screen = s;
-	if(refreshfn)
-		l->save = nil;
-	else{
-		l->save = allocmemimage(screenr, s->image->chan);
-		if(l->save == nil){
-			free(l);
-			free(n);
-			return nil;
-		}
-		/* allocmemimage doesn't initialize memory; this paints save area */
-		if(val != DNofill)
-			memfillcolor(l->save, val);
-	}
-	l->refreshfn = refreshfn;
-	l->refreshptr = nil;	/* don't set it until we're done */
-	l->screenr = screenr;
-	l->delta = Pt(0,0);
-
-	n->data->ref++;
-	n->zero = s->image->zero;
-	n->width = s->image->width;
-	n->layer = l;
-
-	/* start with new window behind all existing ones */
-	l->front = s->rearmost;
-	l->rear = nil;
-	if(s->rearmost)
-		s->rearmost->layer->rear = n;
-	s->rearmost = n;
-	if(s->frontmost == nil)
-		s->frontmost = n;
-	l->clear = 0;
-
-	/* now pull new window to front */
-	_memltofrontfill(n, val != DNofill);
-	l->refreshptr = refreshptr;
-
-	/*
-	 * paint with requested color; previously exposed areas are already right
-	 * if this window has backing store, but just painting the whole thing is simplest.
-	 */
-	if(val != DNofill){
-		memsetchan(paint, n->chan);
-		memfillcolor(paint, val);
-		memdraw(n, n->r, paint, n->r.min, nil, n->r.min, S);
-	}
-	return n;
-}
blob - 800ffc859e7ce4be661c1f52bbda287f82cb63fb (mode 644)
blob + /dev/null
--- src/libdraw/ml-layerop.c
+++ /dev/null
@@ -1,112 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include <memlayer.h>
-
-#define	RECUR(a,b,c,d)	_layerop(fn, i, Rect(a.x, b.y, c.x, d.y), clipr, etc, front->layer->rear);
-
-static void
-_layerop(
-	void (*fn)(Memimage*, Rectangle, Rectangle, void*, int),
-	Memimage *i,
-	Rectangle r,
-	Rectangle clipr,
-	void *etc,
-	Memimage *front)
-{
-	Rectangle fr;
-
-    Top:
-	if(front == i){
-		/* no one is in front of this part of window; use the screen */
-		fn(i->layer->screen->image, r, clipr, etc, 0);
-		return;
-	}
-	fr = front->layer->screenr;
-	if(rectXrect(r, fr) == 0){
-		/* r doesn't touch this window; continue on next rearmost */
-		/* assert(front && front->layer && front->layer->screen && front->layer->rear); */
-		front = front->layer->rear;
-		goto Top;
-	}
-	if(fr.max.y < r.max.y){
-		RECUR(r.min, fr.max, r.max, r.max);
-		r.max.y = fr.max.y;
-	}
-	if(r.min.y < fr.min.y){
-		RECUR(r.min, r.min, r.max, fr.min);
-		r.min.y = fr.min.y;
-	}
-	if(fr.max.x < r.max.x){
-		RECUR(fr.max, r.min, r.max, r.max);
-		r.max.x = fr.max.x;
-	}
-	if(r.min.x < fr.min.x){
-		RECUR(r.min, r.min, fr.min, r.max);
-		r.min.x = fr.min.x;
-	}
-	/* r is covered by front, so put in save area */
-	(*fn)(i->layer->save, r, clipr, etc, 1);
-}
-
-/*
- * Assumes incoming rectangle has already been clipped to i's logical r and clipr
- */
-void
-_memlayerop(
-	void (*fn)(Memimage*, Rectangle, Rectangle, void*, int),
-	Memimage *i,
-	Rectangle screenr,	/* clipped to window boundaries */
-	Rectangle clipr,		/* clipped also to clipping rectangles of hierarchy */
-	void *etc)
-{
-	Memlayer *l;
-	Rectangle r, scr;
-
-	l = i->layer;
-	if(!rectclip(&screenr, l->screenr))
-		return;
-	if(l->clear){
-		fn(l->screen->image, screenr, clipr, etc, 0);
-		return;
-	}
-	r = screenr;
-	scr = l->screen->image->clipr;
-
-	/*
-	 * Do the piece on the screen
-	 */
-	if(rectclip(&screenr, scr))
-		_layerop(fn, i, screenr, clipr, etc, l->screen->frontmost);
-	if(rectinrect(r, scr))
-		return;
-
-	/*
-	 * Do the piece off the screen
-	*/
-	if(!rectXrect(r, scr)){
-		/* completely offscreen; easy */
-		fn(l->save, r, clipr, etc, 1);
-		return;
-	}
-	if(r.min.y < scr.min.y){
-		/* above screen */
-		fn(l->save, Rect(r.min.x, r.min.y, r.max.x, scr.min.y), clipr, etc, 1);
-		r.min.y = scr.min.y;
-	}
-	if(r.max.y > scr.max.y){
-		/* below screen */
-		fn(l->save, Rect(r.min.x, scr.max.y, r.max.x, r.max.y), clipr, etc, 1);
-		r.max.y = scr.max.y;
-	}
-	if(r.min.x < scr.min.x){
-		/* left of screen */
-		fn(l->save, Rect(r.min.x, r.min.y, scr.min.x, r.max.y), clipr, etc, 1);
-		r.min.x = scr.min.x;
-	}
-	if(r.max.x > scr.max.x){
-		/* right of screen */
-		fn(l->save, Rect(scr.max.x, r.min.y, r.max.x, r.max.y), clipr, etc, 1);
-	}
-}
blob - 34cd6eadbc2a9d1c8ab46f5dd8caa286945d88be (mode 644)
blob + /dev/null
--- src/libdraw/ml-ldelete.c
+++ /dev/null
@@ -1,67 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include <memlayer.h>
-
-void
-memldelete(Memimage *i)
-{
-	Memscreen *s;
-	Memlayer *l;
-
-	l = i->layer;
-	/* free backing store and disconnect refresh, to make pushback fast */
-	freememimage(l->save);
-	l->save = nil;
-	l->refreshptr = nil;
-	memltorear(i);
-
-	/* window is now the rearmost;  clean up screen structures and deallocate */
-	s = i->layer->screen;
-	if(s->fill){
-		i->clipr = i->r;
-		memdraw(i, i->r, s->fill, i->r.min, nil, i->r.min, S);
-	}
-	if(l->front){
-		l->front->layer->rear = nil;
-		s->rearmost = l->front;
-	}else{
-		s->frontmost = nil;
-		s->rearmost = nil;
-	}
-	free(l);
-	freememimage(i);
-}
-
-/*
- * Just free the data structures, don't do graphics
- */
-void
-memlfree(Memimage *i)
-{
-	Memlayer *l;
-
-	l = i->layer;
-	freememimage(l->save);
-	free(l);
-	freememimage(i);
-}
-
-void
-_memlsetclear(Memscreen *s)
-{
-	Memimage *i, *j;
-	Memlayer *l;
-
-	for(i=s->rearmost; i; i=i->layer->front){
-		l = i->layer;
-		l->clear = rectinrect(l->screenr, l->screen->image->clipr);
-		if(l->clear)
-			for(j=l->front; j; j=j->layer->front)
-				if(rectXrect(l->screenr, j->layer->screenr)){
-					l->clear = 0;
-					break;
-				}
-	}
-}
blob - d6aaa55fe2ce93dc01b060d7b567135f73b43f4e (mode 644)
blob + /dev/null
--- src/libdraw/ml-lhide.c
+++ /dev/null
@@ -1,67 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include <memlayer.h>
-
-/*
- * Hide puts that portion of screenr now on the screen into the window's save area.
- * Expose puts that portion of screenr now in the save area onto the screen.
- *
- * Hide and Expose both require that the layer structures in the screen
- * match the geometry they are being asked to update, that is, they update the
- * save area (hide) or screen (expose) based on what those structures tell them.
- * This means they must be called at the correct time during window shuffles.
- */
-
-static
-void
-lhideop(Memimage *src, Rectangle screenr, Rectangle clipr, void *etc, int insave)
-{
-	Rectangle r;
-	Memlayer *l;
-
-	USED(clipr.min.x);
-	USED(insave);
-	l = etc;
-	if(src != l->save){	/* do nothing if src is already in save area */
-		r = rectsubpt(screenr, l->delta);
-		memdraw(l->save, r, src, screenr.min, nil, screenr.min, S);
-	}
-}
-
-void
-memlhide(Memimage *i, Rectangle screenr)
-{
-	if(i->layer->save == nil)
-		return;
-	if(rectclip(&screenr, i->layer->screen->image->r) == 0)
-		return;
-	_memlayerop(lhideop, i, screenr, screenr, i->layer);
-}
-
-static
-void
-lexposeop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave)
-{
-	Memlayer *l;
-	Rectangle r;
-
-	USED(clipr.min.x);
-	if(insave)	/* if dst is save area, don't bother */
-		return;
-	l = etc;
-	r = rectsubpt(screenr, l->delta);
-	if(l->save)
-		memdraw(dst, screenr, l->save, r.min, nil, r.min, S);
-	else
-		l->refreshfn(dst, r, l->refreshptr);
-}
-
-void
-memlexpose(Memimage *i, Rectangle screenr)
-{
-	if(rectclip(&screenr, i->layer->screen->image->r) == 0)
-		return;
-	_memlayerop(lexposeop, i, screenr, screenr, i->layer);
-}
blob - f74930ef0440253c6e3a26f22dde7a1b46594a38 (mode 644)
blob + /dev/null
--- src/libdraw/ml-line.c
+++ /dev/null
@@ -1,122 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include <memlayer.h>
-
-struct Lline
-{
-	Point			p0;
-	Point			p1;
-	Point			delta;
-	int			end0;
-	int			end1;
-	int			radius;
-	Point			sp;
-	Memlayer		*dstlayer;
-	Memimage	*src;
-	int			op;
-};
-
-static void llineop(Memimage*, Rectangle, Rectangle, void*, int);
-
-static
-void
-_memline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, Rectangle clipr, int op)
-{
-	Rectangle r;
-	struct Lline ll;
-	Point d;
-	int srcclipped;
-	Memlayer *dl;
-
-	if(radius < 0)
-		return;
-	if(src->layer)	/* can't draw line with layered source */
-		return;
-	srcclipped = 0;
-
-   Top:
-	dl = dst->layer;
-	if(dl == nil){
-		_memimageline(dst, p0, p1, end0, end1, radius, src, sp, clipr, op);
-		return;
-	}
-	if(!srcclipped){
-		d = subpt(sp, p0);
-		if(rectclip(&clipr, rectsubpt(src->clipr, d)) == 0)
-			return;
-		if((src->flags&Frepl)==0 && rectclip(&clipr, rectsubpt(src->r, d))==0)
-			return;
-		srcclipped = 1;
-	}
-
-	/* dst is known to be a layer */
-	p0.x += dl->delta.x;
-	p0.y += dl->delta.y;
-	p1.x += dl->delta.x;
-	p1.y += dl->delta.y;
-	clipr.min.x += dl->delta.x;
-	clipr.min.y += dl->delta.y;
-	clipr.max.x += dl->delta.x;
-	clipr.max.y += dl->delta.y;
-	if(dl->clear){
-		dst = dst->layer->screen->image;
-		goto Top;
-	}
-
-	/* XXX */
-	/* this is not the correct set of tests */
-/*	if(log2[dst->depth] != log2[src->depth] || log2[dst->depth]!=3) */
-/*		return; */
-
-	/* can't use sutherland-cohen clipping because lines are wide */
-	r = memlinebbox(p0, p1, end0, end1, radius);
-	/*
-	 * r is now a bounding box for the line;
-	 * use it as a clipping rectangle for subdivision
-	 */
-	if(rectclip(&r, clipr) == 0)
-		return;
-	ll.p0 = p0;
-	ll.p1 = p1;
-	ll.end0 = end0;
-	ll.end1 = end1;
-	ll.sp = sp;
-	ll.dstlayer = dst->layer;
-	ll.src = src;
-	ll.radius = radius;
-	ll.delta = dl->delta;
-	ll.op = op;
-	_memlayerop(llineop, dst, r, r, &ll);
-}
-
-static
-void
-llineop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave)
-{
-	struct Lline *ll;
-	Point p0, p1;
-
-	USED(screenr.min.x);
-	ll = etc;
-	if(insave && ll->dstlayer->save==nil)
-		return;
-	if(!rectclip(&clipr, screenr))
-		return;
-	if(insave){
-		p0 = subpt(ll->p0, ll->delta);
-		p1 = subpt(ll->p1, ll->delta);
-		clipr = rectsubpt(clipr, ll->delta);
-	}else{
-		p0 = ll->p0;
-		p1 = ll->p1;
-	}
-	_memline(dst, p0, p1, ll->end0, ll->end1, ll->radius, ll->src, ll->sp, clipr, ll->op);
-}
-
-void
-memline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, int op)
-{
-	_memline(dst, p0, p1, end0, end1, radius, src, sp, dst->clipr, op);
-}
blob - d211564be0c81883cfa425d4e8a6f1c14edf8e95 (mode 644)
blob + /dev/null
--- src/libdraw/ml-load.c
+++ /dev/null
@@ -1,55 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include <memlayer.h>
-
-int
-memload(Memimage *dst, Rectangle r, uchar *data, int n, int iscompressed)
-{
-	int (*loadfn)(Memimage*, Rectangle, uchar*, int);
-	Memimage *tmp;
-	Memlayer *dl;
-	Rectangle lr;
-	int dx;
-
-	loadfn = loadmemimage;
-	if(iscompressed)
-		loadfn = cloadmemimage;
-
-    Top:
-	dl = dst->layer;
-	if(dl == nil)
-		return loadfn(dst, r, data, n);
-
-	/*
- 	 * Convert to screen coordinates.
-	 */
-	lr = r;
-	r.min.x += dl->delta.x;
-	r.min.y += dl->delta.y;
-	r.max.x += dl->delta.x;
-	r.max.y += dl->delta.y;
-	dx = dl->delta.x&(7/dst->depth);
-	if(dl->clear && dx==0){
-		dst = dl->screen->image;
-		goto Top;
-	}
-
-	/*
-	 * dst is an obscured layer or data is unaligned
-	 */
-	if(dl->save && dx==0){
-		n = loadfn(dl->save, lr, data, n);
-		if(n > 0)
-			memlexpose(dst, r);
-		return n;
-	}
-	tmp = allocmemimage(lr, dst->chan);
-	if(tmp == nil)
-		return -1;
-	n = loadfn(tmp, lr, data, n);
-	memdraw(dst, lr, tmp, lr.min, nil, lr.min, S);
-	freememimage(tmp);
-	return n;
-}
blob - 0926ee8d216bd66119a4dc3c1a2932e2bb587287 (mode 644)
blob + /dev/null
--- src/libdraw/ml-lorigin.c
+++ /dev/null
@@ -1,107 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include <memlayer.h>
-
-/*
- * Place i so i->r.min = log, i->layer->screenr.min == scr.
-*/
-int
-memlorigin(Memimage *i, Point log, Point scr)
-{
-	Memlayer *l;
-	Memscreen *s;
-	Memimage *t, *shad, *nsave;
-	Rectangle x, newr, oldr;
-	Point delta;
-	int overlap, eqlog, eqscr, wasclear;
-
-	l = i->layer;
-	s = l->screen;
-	oldr = l->screenr;
-	newr = Rect(scr.x, scr.y, scr.x+Dx(oldr), scr.y+Dy(oldr));
-	eqscr = eqpt(scr, oldr.min);
-	eqlog = eqpt(log, i->r.min);
-	if(eqscr && eqlog)
-		return 0;
-	nsave = nil;
-	if(eqlog==0 && l->save!=nil){
-		nsave = allocmemimage(Rect(log.x, log.y, log.x+Dx(oldr), log.y+Dy(oldr)), i->chan);
-		if(nsave == nil)
-			return -1;
-	}
-
-	/*
-	 * Bring it to front and move logical coordinate system.
-	 */
-	memltofront(i);
-	wasclear = l->clear;
-	if(nsave){
-		if(!wasclear)
-			memimagedraw(nsave, nsave->r, l->save, l->save->r.min, nil, Pt(0,0), S);
-		freememimage(l->save);
-		l->save = nsave;
-	}
-	delta = subpt(log, i->r.min);
-	i->r = rectaddpt(i->r, delta);
-	i->clipr = rectaddpt(i->clipr, delta);
-	l->delta = subpt(l->screenr.min, i->r.min);
-	if(eqscr)
-		return 0;
-
-	/*
-	 * To clean up old position, make a shadow window there, don't paint it,
-	 * push it behind this one, and (later) delete it.  Because the refresh function
-	 * for this fake window is a no-op, this will cause no graphics action except
-	 * to restore the background and expose the windows previously hidden.
-	 */
-	shad = memlalloc(s, oldr, memlnorefresh, nil, DNofill);
-	if(shad == nil)
-		return -1;
-	s->frontmost = i;
-	if(s->rearmost == i)
-		s->rearmost = shad;
-	else
-		l->rear->layer->front = shad;
-	shad->layer->front = i;
-	shad->layer->rear = l->rear;
-	l->rear = shad;
-	l->front = nil;
-	shad->layer->clear = 0;
-
-	/*
-	 * Shadow is now holding down the fort at the old position.
-	 * Move the window and hide things obscured by new position.
-	 */
-	for(t=l->rear->layer->rear; t!=nil; t=t->layer->rear){
-		x = newr;
-		overlap = rectclip(&x, t->layer->screenr);
-		if(overlap){
-			memlhide(t, x);
-			t->layer->clear = 0;
-		}
-	}
-	l->screenr = newr;
-	l->delta = subpt(scr, i->r.min);
-	l->clear = rectinrect(newr, l->screen->image->clipr);
-
-	/*
-	 * Everything's covered.  Copy to new position and delete shadow window.
-	 */
-	if(wasclear)
-		memdraw(s->image, newr, s->image, oldr.min, nil, Pt(0,0), S);
-	else
-		memlexpose(i, newr);
-	memldelete(shad);
-
-	return 1;
-}
-
-void
-memlnorefresh(Memimage *l, Rectangle r, void *v)
-{
-	USED(l);
-	USED(r.min.x);
-	USED(v);
-}
blob - 526bd668a533cedbf0970ef1153c08e4795bc1f1 (mode 644)
blob + /dev/null
--- src/libdraw/ml-lsetrefresh.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include <memlayer.h>
-
-int
-memlsetrefresh(Memimage *i, Refreshfn fn, void *ptr)
-{
-	Memlayer *l;
-
-	l = i->layer;
-	if(l->refreshfn!=0 && fn!=0){	/* just change functions */
-		l->refreshfn = fn;
-		l->refreshptr = ptr;
-		return 1;
-	}
-
-	if(l->refreshfn == 0){	/* is using backup image; just free it */
-		freememimage(l->save);
-		l->save = nil;
-		l->refreshfn = fn;
-		l->refreshptr = ptr;
-		return 1;
-	}
-
-	l->save = allocmemimage(i->r, i->chan);
-	if(l->save == nil)
-		return 0;
-	/* easiest way is just to update the entire save area */
-	l->refreshfn(i, i->r, l->refreshptr);
-	l->refreshfn = 0;
-	l->refreshptr = nil;
-	return 1;
-}
blob - 447b40bdfdf51ccccab7932bdb72c2df30b26c00 (mode 644)
blob + /dev/null
--- src/libdraw/ml-ltofront.c
+++ /dev/null
@@ -1,80 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include <memlayer.h>
-
-/*
- * Pull i towards top of screen, just behind front
-*/
-static
-void
-_memltofront(Memimage *i, Memimage *front, int fill)
-{
-	Memlayer *l;
-	Memscreen *s;
-	Memimage *f, *ff, *rr;
-	Rectangle x;
-	int overlap;
-
-	l = i->layer;
-	s = l->screen;
-	while(l->front != front){
-		f = l->front;
-		x = l->screenr;
-		overlap = rectclip(&x, f->layer->screenr);
-		if(overlap){
-			memlhide(f, x);
-			f->layer->clear = 0;
-		}
-		/* swap l and f in screen's list */
-		ff = f->layer->front;
-		rr = l->rear;
-		if(ff == nil)
-			s->frontmost = i;
-		else
-			ff->layer->rear = i;
-		if(rr == nil)
-			s->rearmost = f;
-		else
-			rr->layer->front = f;
-		l->front = ff;
-		l->rear = f;
-		f->layer->front = i;
-		f->layer->rear = rr;
-		if(overlap && fill)
-			memlexpose(i, x);
-	}
-}
-
-void
-_memltofrontfill(Memimage *i, int fill)
-{
-	_memltofront(i, nil, fill);
-	_memlsetclear(i->layer->screen);
-}
-
-void
-memltofront(Memimage *i)
-{
-	_memltofront(i, nil, 1);
-	_memlsetclear(i->layer->screen);
-}
-
-void
-memltofrontn(Memimage **ip, int n)
-{
-	Memimage *i, *front;
-	Memscreen *s;
-
-	if(n == 0)
-		return;
-	front = nil;
-	while(--n >= 0){
-		i = *ip++;
-		_memltofront(i, front, 1);
-		front = i;
-	}
-	s = front->layer->screen;
-	_memlsetclear(s);
-}
blob - d53e8cc95e3a3c757c886690a9f47b2c007990d7 (mode 644)
blob + /dev/null
--- src/libdraw/ml-ltorear.c
+++ /dev/null
@@ -1,69 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include <memlayer.h>
-
-void
-_memltorear(Memimage *i, Memimage *rear)
-{
-	Memlayer *l;
-	Memscreen *s;
-	Memimage *f, *r, *rr;
-	Rectangle x;
-	int overlap;
-
-	l = i->layer;
-	s = l->screen;
-	while(l->rear != rear){
-		r = l->rear;
-		x = l->screenr;
-		overlap = rectclip(&x, r->layer->screenr);
-		if(overlap){
-			memlhide(i, x);
-			l->clear = 0;
-		}
-		/* swap l and r in screen's list */
-		rr = r->layer->rear;
-		f = l->front;
-		if(rr == nil)
-			s->rearmost = i;
-		else
-			rr->layer->front = i;
-		if(f == nil)
-			s->frontmost = r;
-		else
-			f->layer->rear = r;
-		l->rear = rr;
-		l->front = r;
-		r->layer->rear = i;
-		r->layer->front = f;
-		if(overlap)
-			memlexpose(r, x);
-	}
-}
-
-void
-memltorear(Memimage *i)
-{
-	_memltorear(i, nil);
-	_memlsetclear(i->layer->screen);
-}
-
-void
-memltorearn(Memimage **ip, int n)
-{
-	Memimage *i, *rear;
-	Memscreen *s;
-
-	if(n == 0)
-		return;
-	rear = nil;
-	while(--n >= 0){
-		i = *ip++;
-		_memltorear(i, rear);
-		rear = i;
-	}
-	s = rear->layer->screen;
-	_memlsetclear(s);
-}
blob - b953411771b7a2800631983b5fefa3528a1a865f (mode 644)
blob + /dev/null
--- src/libdraw/ml-unload.c
+++ /dev/null
@@ -1,52 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include <memlayer.h>
-
-int
-memunload(Memimage *src, Rectangle r, uchar *data, int n)
-{
-	Memimage *tmp;
-	Memlayer *dl;
-	Rectangle lr;
-	int dx;
-
-    Top:
-	dl = src->layer;
-	if(dl == nil)
-		return unloadmemimage(src, r, data, n);
-
-	/*
- 	 * Convert to screen coordinates.
-	 */
-	lr = r;
-	r.min.x += dl->delta.x;
-	r.min.y += dl->delta.y;
-	r.max.x += dl->delta.x;
-	r.max.y += dl->delta.y;
-	dx = dl->delta.x&(7/src->depth);
-	if(dl->clear && dx==0){
-		src = dl->screen->image;
-		goto Top;
-	}
-
-	/*
-	 * src is an obscured layer or data is unaligned
-	 */
-	if(dl->save && dx==0){
-		if(dl->refreshfn != 0)
-			return -1;	/* can't unload window if it's not Refbackup */
-		if(n > 0)
-			memlhide(src, r);
-		n = unloadmemimage(dl->save, lr, data, n);
-		return n;
-	}
-	tmp = allocmemimage(lr, src->chan);
-	if(tmp == nil)
-		return -1;
-	memdraw(tmp, lr, src, lr.min, nil, lr.min, S);
-	n = unloadmemimage(tmp, lr, data, n);
-	freememimage(tmp);
-	return n;
-}
blob - 3b3cbb6befd9a5f84d935e2f30a6760d709388bc
blob + 5c6d0970a3246e82be1d227477e1a505e7ea3059
--- src/libdraw/mouse.c
+++ src/libdraw/mouse.c
@@ -6,10 +6,10 @@
 #include <mouse.h>
 
 void
-moveto(Mousectl *m, Point pt)
+moveto(Mousectl *mc, Point pt)
 {
-	fprint(m->mfd, "m%d %d", pt.x, pt.y);
-	m->xy = pt;
+	_displaymoveto(mc->display, pt);
+	mc->m.xy = pt;
 }
 
 void
@@ -18,24 +18,20 @@ closemouse(Mousectl *mc)
 	if(mc == nil)
 		return;
 
-	postnote(PNPROC, mc->pid, "kill");
+/*	postnote(PNPROC, mc->pid, "kill"); */
 
-	do; while(nbrecv(mc->c, &mc->Mouse) > 0);
-
-	close(mc->mfd);
-	close(mc->cfd);
-	free(mc->file);
-	free(mc->c);
-	free(mc->resizec);
+	do; while(nbrecv(mc->c, &mc->m) > 0);
+	chanfree(mc->c);
+	chanfree(mc->resizec);
 	free(mc);
 }
 
 int
 readmouse(Mousectl *mc)
 {
-	if(mc->image)
-		flushimage(mc->image->display, 1);
-	if(recv(mc->c, &mc->Mouse) < 0){
+	if(mc->display)
+		flushimage(mc->display, 1);
+	if(recv(mc->c, &mc->m) < 0){
 		fprint(2, "readmouse: %r\n");
 		return -1;
 	}
@@ -46,45 +42,27 @@ static
 void
 _ioproc(void *arg)
 {
-	int n, nerr, one;
-	char buf[1+5*12];
+	int one, resized;
 	Mouse m;
 	Mousectl *mc;
 
 	mc = arg;
 	threadsetname("mouseproc");
-	one = 1;
 	memset(&m, 0, sizeof m);
-	mc->pid = getpid();
-	nerr = 0;
+	one = 1;
+	resized = 0;
 	for(;;){
-		n = read(mc->mfd, buf, sizeof buf);
-		if(n != 1+4*12){
-			yield();	/* if error is due to exiting, we'll exit here */
-			fprint(2, "mouse: bad count %d not 49: %r\n", n);
-			if(n<0 || ++nerr>10)
-				threadexits("read error");
-			continue;
-		}
-		nerr = 0;
-		switch(buf[0]){
-		case 'r':
+		if(_displayrdmouse(mc->display, &m, &resized) < 0)
+			threadexits("read error");
+		if(resized)
 			send(mc->resizec, &one);
-			/* fall through */
-		case 'm':
-			m.xy.x = atoi(buf+1+0*12);
-			m.xy.y = atoi(buf+1+1*12);
-			m.buttons = atoi(buf+1+2*12);
-			m.msec = atoi(buf+1+3*12);
-			send(mc->c, &m);
-			/*
-			 * mc->Mouse is updated after send so it doesn't have wrong value if we block during send.
-			 * This means that programs should receive into mc->Mouse (see readmouse() above) if
-			 * they want full synchrony.
-			 */
-			mc->Mouse = m;
-			break;
-		}
+		send(mc->c, &m);
+		/*
+		 * mc->m is updated after send so it doesn't have wrong value if we block during send.
+		 * This means that programs should receive into mc->Mouse (see readmouse() above) if
+		 * they want full synchrony.
+		 */
+		mc->m = m;
 	}
 }
 
@@ -92,50 +70,21 @@ Mousectl*
 initmouse(char *file, Image *i)
 {
 	Mousectl *mc;
-	char *t, *sl;
 
 	mc = mallocz(sizeof(Mousectl), 1);
-	if(file == nil)
-		file = "/dev/mouse";
-	mc->file = strdup(file);
-	mc->mfd = open(file, ORDWR|OCEXEC);
-	if(mc->mfd<0 && strcmp(file, "/dev/mouse")==0){
-		bind("#m", "/dev", MAFTER);
-		mc->mfd = open(file, ORDWR|OCEXEC);
-	}
-	if(mc->mfd < 0){
-		free(mc);
-		return nil;
-	}
-	t = malloc(strlen(file)+16);
-	strcpy(t, file);
-	sl = utfrrune(t, '/');
-	if(sl)
-		strcpy(sl, "/cursor");
-	else
-		strcpy(t, "/dev/cursor");
-	mc->cfd = open(t, ORDWR|OCEXEC);
-	free(t);
-	mc->image = i;
+	if(i)
+		mc->display = i->display;
 	mc->c = chancreate(sizeof(Mouse), 0);
 	chansetname(mc->c, "mousec");
 	mc->resizec = chancreate(sizeof(int), 2);
 	chansetname(mc->resizec, "resizec");
-	proccreate(_ioproc, mc, 4096);
+	proccreate(_ioproc, mc, 32*1024);
 	return mc;
 }
 
 void
 setcursor(Mousectl *mc, Cursor *c)
 {
-	char curs[2*4+2*2*16];
-
-	if(c == nil)
-		write(mc->cfd, curs, 0);
-	else{
-		BPLONG(curs+0*4, c->offset.x);
-		BPLONG(curs+1*4, c->offset.y);
-		memmove(curs+2*4, c->clr, 2*2*16);
-		write(mc->cfd, curs, sizeof curs);
-	}
+	_displaycursor(mc->display, c);
 }
+
blob - 2c92f6feefdfeccbbb2f0eadba4a8dc3f07e4871 (mode 644)
blob + /dev/null
--- src/libdraw/nowsys-alloc.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-Memimage*
-allocmemimage(Rectangle r, u32int chan)
-{
-	return _allocmemimage(r, chan);
-}
-
-void
-freememimage(Memimage *m)
-{
-	_freememimage(m);
-}
-
blob - 3d5261d12e938d72f580f8e51c5b414a266a8307 (mode 644)
blob + /dev/null
--- src/libdraw/nowsys-cload.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-int
-cloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
-{
-	return _cloadmemimage(i, r, data, ndata);
-}
-
blob - 5eac24f0d43a27315dfc8351012a8f13f553c97e (mode 644)
blob + /dev/null
--- src/libdraw/nowsys-draw.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-void
-memimagedraw(Memimage *dst, Rectangle r, Memimage *src, Point sp,
-	Memimage *mask, Point mp, int op)
-{
-	Memdrawparam *par;
-	
-	if((par = _memimagedrawsetup(dst, r, src, sp, mask, mp, op)) == nil)
-		return;
-	_memimagedraw(par);
-}
blob - 0f168e0f5eb5e958f0079acff2a275ceaec6ce4a (mode 644)
blob + /dev/null
--- src/libdraw/nowsys-event.c
+++ /dev/null
@@ -1,83 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <cursor.h>
-#include <event.h>
-
-static int
-bad(void)
-{
-	sysfatal("compiled with no window system support");
-	return 0;
-}
-
-ulong
-event(Event *e)
-{
-	USED(e);
-	return bad();
-}
-
-ulong
-eread(ulong keys, Event *e)
-{
-	USED(keys);
-	USED(e);
-	return bad();
-}
-
-void
-einit(ulong keys)
-{
-	USED(keys);
-	bad();
-}
-
-int
-ekbd(void)
-{
-	return bad();
-}
-
-Mouse
-emouse(void)
-{
-	Mouse m;
-	
-	bad();
-	return m;
-}
-
-int
-ecanread(ulong keys)
-{
-	USED(keys);
-	return bad();
-}
-
-int
-ecanmouse(void)
-{
-	return bad();
-}
-
-int
-ecankbd(void)
-{
-	return bad();
-}
-
-void
-emoveto(Point p)
-{
-/* 	USED(p); */
-	bad();
-}
-
-void
-esetcursor(Cursor *c)
-{
-	USED(c);
-	bad();
-}
-
blob - d75459f1780b5ed24f9e690dea080479877b60b7 (mode 644)
blob + /dev/null
--- src/libdraw/nowsys-fill.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-void
-memfillcolor(Memimage *m, u32int val)
-{
-	_memfillcolor(m, val);
-}
-
blob - 2481df1823e074de1ba2acd5944f6069517d7793 (mode 644)
blob + /dev/null
--- src/libdraw/nowsys-get.c
+++ /dev/null
@@ -1,3 +0,0 @@
-/* so that there's *something* in this file */
-int __nowsys__get(void) {return 0;}
-
blob - 763be54019b21d7a14b85ad7996690d5e97785aa (mode 644)
blob + /dev/null
--- src/libdraw/nowsys-init.c
+++ /dev/null
@@ -1,47 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <keyboard.h>
-#include <mouse.h>
-#include <cursor.h>
-
-char *winsize;
-
-static int
-bad(void)
-{
-	sysfatal("compiled with no window system support");
-	return 0;
-}
-
-Display*
-_initdisplay(void (*error)(Display*, char*), char *label)
-{
-	USED(error);
-	USED(label);
-	
-	bad();
-	return nil;
-}
-
-int
-getwindow(Display *d, int ref)
-{
-	USED(d);
-	USED(ref);
-	return bad();
-}
-
-int
-drawsetlabel(char *label)
-{
-	USED(label);
-	return bad();
-}
-
-void
-_flushmemscreen(Rectangle r)
-{
-	bad();
-}
-
blob - 8c60c6bf2c597b0326a020822b824151e763ca42 (mode 644)
blob + /dev/null
--- src/libdraw/nowsys-itrans.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include <u.h>
-#include <libc.h>
- 
-static int
-bad(void)
-{
-    sysfatal("compiled with no window system support");
-    return 0;
-}
-
-void
-putsnarf(char *data)
-{
-	USED(data);
-	bad();
-}
-
-char*
-getsnarf(void)
-{
-	bad();
-	return nil;
-}
blob - 3b78b5bcc164d095cf9538fa75d991e1607a23d6 (mode 644)
blob + /dev/null
--- src/libdraw/nowsys-keyboard.c
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <thread.h>
-#include <cursor.h>
-#include <keyboard.h>
-
-static int
-bad(void)
-{
-	sysfatal("compiled with no window system support");
-	return 0;
-}
-
-void
-closekeyboard(Keyboardctl *mc)
-{
-	USED(mc);
-	bad();
-}
-
-Keyboardctl*
-initkeyboard(char *file)
-{
-	USED(file);
-	bad();
-	return nil;
-}
blob - fa8ac518ee992e4b9efa340828d474a5c8636ef0 (mode 644)
blob + /dev/null
--- src/libdraw/nowsys-keysym2ucs.c
+++ /dev/null
@@ -1,2 +0,0 @@
-/* so that there's *something* in this file */
-int __nowsys__itrans(void) {return 0;}
blob - b0d5fcee18d715c9b7f1327dcf6b113bc45328e1 (mode 644)
blob + /dev/null
--- src/libdraw/nowsys-load.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-int
-loadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
-{
-	return _loadmemimage(i, r, data, ndata);
-}
-
blob - af1bf990e7977f7fa4b7c945a650d269c9fcda13 (mode 644)
blob + /dev/null
--- src/libdraw/nowsys-mouse.c
+++ /dev/null
@@ -1,61 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <thread.h>
-#include <cursor.h>
-#include <mouse.h>
-
-int _wantfocuschanges;
-static int
-bad(void)
-{
-	sysfatal("compiled with no window system support");
-	return 0;
-}
-
-void
-moveto(Mousectl *m, Point pt)
-{
-	USED(m);
-/*	USED(pt); */
-	bad();
-}
-
-void
-closemouse(Mousectl *mc)
-{
-	USED(mc);
-	bad();
-}
-
-int
-readmouse(Mousectl *mc)
-{
-	USED(mc);
-	return bad();
-}
-
-Mousectl*
-initmouse(char *file, Image *i)
-{
-	USED(file);
-	USED(i);
-	bad();
-	return nil;
-}
-
-void
-setcursor(Mousectl *mc, Cursor *c)
-{
-	USED(mc);
-	USED(c);
-	bad();
-}
-
-void
-bouncemouse(Mouse *m)
-{
-	USED(m);
-	bad();
-}
-
blob - de744b969e175db57481c82750ffaf1b0717f17d (mode 644)
blob + /dev/null
--- src/libdraw/nowsys-pixelbits.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-u32int
-pixelbits(Memimage *m, Point p)
-{
-	return _pixelbits(m, p);
-}
-
-
blob - 3859321379e5384073273728aa498d1209fdb41d (mode 644)
blob + /dev/null
--- src/libdraw/nowsys-unload.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-
-int
-unloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
-{
-	return _unloadmemimage(i, r, data, ndata);
-}
-
blob - c5b50ad7775203743dcda7f6c84fc17e80f79520 (mode 644)
blob + /dev/null
--- src/libdraw/nowsys-wsys.c
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-
-static int
-bad(void)
-{
-	sysfatal("compiled with no window system support");
-	return 0;
-}
-
-void
-drawtopwindow(void)
-{
-	bad();
-}
-
-void
-drawresizewindow(Rectangle r)
-{	
-	bad();
-}
blob - c203b9c293823ae9257313b9126eeee86ea85aa9
blob + 2a688b58cebfb4a646118c423cf4fbf6bf93292e
--- src/libdraw/unloadimage.c
+++ src/libdraw/unloadimage.c
@@ -43,7 +43,7 @@ unloadimage(Image *i, Rectangle r, uchar *data, int nd
 		BPLONG(a+17, r.min.y+dy);
 		if(flushimage(d, 0) < 0)
 			return -1;
-		n = _drawmsgread(d, data+ntot, ndata-ntot);
+		n = _displayrddraw(d, data+ntot, ndata-ntot);
 		if(n < 0)
 			return n;
 		ntot += n;
blob - 5792864ffd5abc741208cfcbe361b0f17e18df3a (mode 644)
blob + /dev/null
--- src/libdraw/x11-alloc.c
+++ /dev/null
@@ -1,122 +0,0 @@
-#include <u.h>
-#include "x11-inc.h"
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include "x11-memdraw.h"
-
-/*
- * Allocate a Memimage with an optional pixmap backing on the X server.
- */
-Memimage*
-_xallocmemimage(Rectangle r, u32int chan, int pixmap)
-{
-	int d, offset;
-	Memimage *m;
-	Xmem *xm;
-	XImage *xi;
-
-	m = _allocmemimage(r, chan);
-	if(chan != GREY1 && chan != _x.chan)
-		return m;
-	if(_x.display == 0)
-		return m;
-
-	/*
-	 * For bootstrapping, don't bother storing 1x1 images
-	 * on the X server.  Memimageinit needs to allocate these
-	 * and we memimageinit before we do the rest of the X stuff.
-	 * Of course, 1x1 images on the server are useless anyway.
-	 */
-	if(Dx(r)==1 && Dy(r)==1)
-		return m;
-
-	xm = mallocz(sizeof(Xmem), 1);
-	if(xm == nil){
-		freememimage(m);
-		return nil;
-	}
-
-	/*
-	 * Allocate backing store.
-	 */
-	if(chan == GREY1)
-		d = 1;
-	else
-		d = _x.depth;
-	if(pixmap != PMundef)
-		xm->pixmap = pixmap;
-	else
-		xm->pixmap = XCreatePixmap(_x.display, _x.drawable, Dx(r), Dy(r), d);
-
-	/*
-	 * We want to align pixels on word boundaries.
-	 */
-	if(m->depth == 24)
-		offset = r.min.x&3;
-	else
-		offset = r.min.x&(31/m->depth);
-	r.min.x -= offset;
-	assert(wordsperline(r, m->depth) <= m->width);
-
-	/*
-	 * Wrap our data in an XImage structure.
-	 */
-	xi = XCreateImage(_x.display, _x.vis, d,
-		ZPixmap, 0, (char*)m->data->bdata, Dx(r), Dy(r),
-		32, m->width*sizeof(u32int));
-	if(xi == nil){
-		freememimage(m);
-		if(xm->pixmap != pixmap)
-			XFreePixmap(_x.display, xm->pixmap);
-		return nil;
-	}
-
-	xm->xi = xi;
-	xm->r = r;
-
-	/*
-	 * Set the XImage parameters so that it looks exactly like
-	 * a Memimage -- we're using the same data.
-	 */
-	if(m->depth < 8 || m->depth == 24)
-		xi->bitmap_unit = 8;
-	else
-		xi->bitmap_unit = m->depth;
-	xi->byte_order = LSBFirst;
-	xi->bitmap_bit_order = MSBFirst;
-	xi->bitmap_pad = 32;
-	XInitImage(xi);
-	XFlush(_x.display);
-
-	m->X = xm;
-	return m;
-}
-
-Memimage*
-allocmemimage(Rectangle r, u32int chan)
-{
-	return _xallocmemimage(r, chan, PMundef);
-}
-
-void
-freememimage(Memimage *m)
-{
-	Xmem *xm;
-
-	if(m == nil)
-		return;
-
-	xm = m->X;
-	if(xm && m->data->ref == 1){
-		if(xm->xi){
-			xm->xi->data = nil;
-			XFree(xm->xi);
-		}
-		XFreePixmap(_x.display, xm->pixmap);
-		free(xm);
-		m->X = nil;
-	}
-	_freememimage(m);
-}
-
blob - 33e3170a52527aa897bf1460928201a8ca5eeb98 (mode 644)
blob + /dev/null
--- src/libdraw/x11-cload.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <u.h>
-#include "x11-inc.h"
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include "x11-memdraw.h"
-
-int
-cloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
-{
-	int n;
-
-	n = _cloadmemimage(i, r, data, ndata);
-	if(n > 0 && i->X)
-		_xputxdata(i, r);
-	return n;
-}
-
blob - 6c41daffd1cf889f03ce7842461391e1ba9b4ea5 (mode 644)
blob + /dev/null
--- src/libdraw/x11-draw.c
+++ /dev/null
@@ -1,144 +0,0 @@
-#include <u.h>
-#include "x11-inc.h"
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include "x11-memdraw.h"
-
-static int xdraw(Memdrawparam*);
-
-/*
- * The X acceleration doesn't fit into the standard hwaccel
- * model because we have the extra steps of pulling the image
- * data off the server and putting it back when we're done.
- */
-void
-memimagedraw(Memimage *dst, Rectangle r, Memimage *src, Point sp,
-	Memimage *mask, Point mp, int op)
-{
-	Memdrawparam *par;
-
-	if((par = _memimagedrawsetup(dst, r, src, sp, mask, mp, op)) == nil)
-		return;
-
-	/* only fetch dst data if we need it */
-	if((par->state&(Simplemask|Fullmask)) != (Simplemask|Fullmask))
-		_xgetxdata(par->dst, par->r);
-
-	/* always fetch source and mask */
-	_xgetxdata(par->src, par->sr);
-	_xgetxdata(par->mask, par->mr);
-
-	/* now can run memimagedraw on the in-memory bits */
-	_memimagedraw(par);
-
-	if(xdraw(par))
-		return;
-
-	/* put bits back on x server */
-	_xputxdata(par->dst, par->r);
-}
-
-static int
-xdraw(Memdrawparam *par)
-{
-	u32int sdval;
-	uint m, state;
-	Memimage *src, *dst, *mask;
-	Point dp, mp, sp;
-	Rectangle r;
-	Xmem *xdst, *xmask, *xsrc;
-	XGC gc;
-
-	if(par->dst->X == nil)
-		return 0;
-
-	dst   = par->dst;
-	mask  = par->mask;
-	r     = par->r;
-	src   = par->src;
-	state = par->state;
-
-	/*
-	 * If we have an opaque mask and source is one opaque pixel,
-	 * we can convert to the destination format and just XFillRectangle.
-	 */
-	m = Simplesrc|Fullsrc|Simplemask|Fullmask;
-	if((state&m) == m){
-		_xfillcolor(dst, r, par->sdval);
-	/*	xdirtyxdata(dst, r); */
-		return 1;
-	}
-
-	/*
-	 * If no source alpha and an opaque mask, we can just copy
-	 * the source onto the destination.  If the channels are the
-	 * same and the source is not replicated, XCopyArea works.
-	 */
-	m = Simplemask|Fullmask;
-	if((state&(m|Replsrc))==m && src->chan==dst->chan && src->X){
-		xdst = dst->X;
-		xsrc = src->X;
-		dp = subpt(r.min,       dst->r.min);
-		sp = subpt(par->sr.min, src->r.min);
-		gc = dst->chan==GREY1 ?  _x.gccopy0 : _x.gccopy;
-
-		XCopyArea(_x.display, xsrc->pixmap, xdst->pixmap, gc,
-			sp.x, sp.y, Dx(r), Dy(r), dp.x, dp.y);
-	/*	xdirtyxdata(dst, r); */
-		return 1;
-	}
-
-	/*
-	 * If no source alpha, a 1-bit mask, and a simple source,
-	 * we can copy through the mask onto the destination.
-	 */
-	if(dst->X && mask->X && !(mask->flags&Frepl)
-	&& mask->chan==GREY1 && (state&Simplesrc)){
-		xdst = dst->X;
-		xmask = mask->X;
-		sdval = par->sdval;
-
-		dp = subpt(r.min, dst->r.min);
-		mp = subpt(r.min, subpt(par->mr.min, mask->r.min));
-
-		if(dst->chan == GREY1){
-			gc = _x.gcsimplesrc0;
-			if(_x.gcsimplesrc0color != sdval){
-				XSetForeground(_x.display, gc, sdval);
-				_x.gcsimplesrc0color = sdval;
-			}
-			if(_x.gcsimplesrc0pixmap != xmask->pixmap){
-				XSetStipple(_x.display, gc, xmask->pixmap);
-				_x.gcsimplesrc0pixmap = xmask->pixmap;
-			}
-		}else{
-			/* this doesn't work on rob's mac?  */
-			return 0;
-			/* gc = _x.gcsimplesrc;
-			if(dst->chan == CMAP8 && _x.usetable)
-				sdval = _x.tox11[sdval];
-
-			if(_x.gcsimplesrccolor != sdval){
-				XSetForeground(_x.display, gc, sdval);
-				_x.gcsimplesrccolor = sdval;
-			}
-			if(_x.gcsimplesrcpixmap != xmask->pixmap){
-				XSetStipple(_x.display, gc, xmask->pixmap);
-				_x.gcsimplesrcpixmap = xmask->pixmap;
-			}
-			*/
-		}
-		XSetTSOrigin(_x.display, gc, mp.x, mp.y);
-		XFillRectangle(_x.display, xdst->pixmap, gc, dp.x, dp.y,
-			Dx(r), Dy(r));
-	/*	xdirtyxdata(dst, r); */
-		return 1;
-	}
-
-	/*
-	 * Can't accelerate.
-	 */
-	return 0;
-}
-
blob - 2d8e9ea4ffd380e135b6e2b34d95f8a3507ad435 (mode 644)
blob + /dev/null
--- src/libdraw/x11-event.c
+++ /dev/null
@@ -1,187 +0,0 @@
-#include <u.h>
-#include "x11-inc.h"
-#include <libc.h>
-#include <draw.h>
-#include <cursor.h>
-#include <event.h>
-#include <memdraw.h>
-#include "x11-memdraw.h"
-
-/*
- * Should change this to support etimer and estartfn again.
- * The main eread() would prepare a select mask from the keys
- * and then call select() to wait for input.  Then it would read an
- * event from the readied fd and return it.  Use XCheckWindowEvent
- * to poll the X connection.
- */
-
-ulong
-event(Event *e)
-{
-	return eread(~0UL, e);
-}
-
-static void
-eflush(void)
-{
-	/* avoid generating a message if there's nothing to show. */
-	/* this test isn't perfect, though; could do flushimage(display, 0) then call extract */
-	/* also: make sure we don't interfere if we're multiprocessing the display */
-	if(display->locking){
-		/* if locking is being done by program, this means it can't depend on automatic flush in emouse() etc. */
-		if(canqlock(&display->qlock)){
-			if(display->bufp > display->buf)
-				flushimage(display, 1);
-			unlockdisplay(display);
-		}
-	}else
-		if(display->bufp > display->buf)
-			flushimage(display, 1);
-}
-
-ulong
-eread(ulong keys, Event *e)
-{
-	int r;
-	ulong xmask;
-	XEvent xevent;
-
-	xmask = ExposureMask;
-
-	eflush();
-
-	if(keys&Emouse)
-		xmask |= MouseMask|StructureNotifyMask;
-	if(keys&Ekeyboard){
-		xmask |= KeyPressMask;
-		if((r = _xtoplan9kbd(nil)) >= 0){
-			e->kbdc = r;
-			return Ekeyboard;
-		}
-	}
-
-	xmask |= EnterWindowMask|LeaveWindowMask;
-
-	XSelectInput(_x.display, _x.drawable, xmask);
-again:
-	XWindowEvent(_x.display, _x.drawable, xmask, &xevent);
-
-	switch(xevent.type){
-	case Expose:
-		_xexpose(&xevent, _x.display);
-		goto again;
-	case DestroyNotify:
-		if(_xdestroy(&xevent, _x.display))
-			postnote(PNGROUP, getpgrp(), "hangup");
-		goto again;
-	case ConfigureNotify:
-		if(_xconfigure(&xevent, _x.display))
-			eresized(1);
-		goto again;
-	case ButtonPress:
-	case ButtonRelease:
-	case MotionNotify:
-		if(_xtoplan9mouse(_x.display, &xevent, &e->mouse) < 0)
-			goto again;
-		return Emouse;
-	case KeyPress:
-		e->kbdc = _xtoplan9kbd(&xevent);
-		if(e->kbdc == -1)
-			goto again;
-		return Ekeyboard;
-	default:
-		goto again;
-	}
-}
-
-void
-einit(ulong keys)
-{
-	keys &= ~(Emouse|Ekeyboard);
-	if(keys){
-		fprint(2, "unknown keys in einit\n");
-		abort();
-	}
-}
-
-int
-ekbd(void)
-{
-	Event e;
-
-	eread(Ekeyboard, &e);
-	return e.kbdc;
-}
-
-Mouse
-emouse(void)
-{
-	Event e;
-
-	eread(Emouse, &e);
-	return e.mouse;
-}
-
-int
-ecanread(ulong keys)
-{
-	int can;
-
-	can = 0;
-	if(keys&Emouse)
-		can |= ecanmouse();
-	if(keys&Ekeyboard)
-		can |= ecankbd();
-	return can;
-}
-
-int
-ecanmouse(void)
-{
-	XEvent xe;
-	Mouse m;
-
-	eflush();
-again:
-	if(XCheckWindowEvent(_x.display, _x.drawable, MouseMask, &xe)){
-		if(_xtoplan9mouse(_x.display, &xe, &m) < 0)
-			goto again;
-		XPutBackEvent(_x.display, &xe);
-		return 1;
-	}
-	return 0;
-}
-
-int
-ecankbd(void)
-{
-	XEvent xe;
-	int r;
-
-	eflush();
-	if((r = _xtoplan9kbd(nil)) >= 0){
-		_xtoplan9kbd((XEvent*)-1);
-		return 1;
-	}
-again:
-	if(XCheckWindowEvent(_x.display, _x.drawable, KeyPressMask, &xe)){
-		if(_xtoplan9kbd(&xe) == -1)
-			goto again;
-		XPutBackEvent(_x.display, &xe);
-		return 1;
-	}
-	return 0;
-}
-
-void
-emoveto(Point p)
-{
-	_xmoveto(p);
-}
-
-void
-esetcursor(Cursor *c)
-{
-	_xsetcursor(c);
-}
-
blob - fc43a684f7c42dcfb4a19643c00377221f5bd5b2 (mode 644)
blob + /dev/null
--- src/libdraw/x11-fill.c
+++ /dev/null
@@ -1,56 +0,0 @@
-#include <u.h>
-#include "x11-inc.h"
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include "x11-memdraw.h"
-
-void
-memfillcolor(Memimage *m, u32int val)
-{
-	_memfillcolor(m, val);
-	if(m->X == nil)
-		return;
-	if((val & 0xFF) == 0xFF)	/* full alpha */
-		_xfillcolor(m, m->r, _rgbatoimg(m, val));
-	else
-		_xputxdata(m, m->r);
-}
-
-void
-_xfillcolor(Memimage *m, Rectangle r, u32int v)
-{
-	Point p;
-	Xmem *xm;
-	XGC gc;
-	
-	xm = m->X;
-	assert(xm != nil);
-
-	/*
-	 * Set up fill context appropriately.
-	 */
-	if(m->chan == GREY1){
-		gc = _x.gcfill0;
-		if(_x.gcfill0color != v){
-			XSetForeground(_x.display, gc, v);
-			_x.gcfill0color = v;
-		}
-	}else{
-		if(m->chan == CMAP8 && _x.usetable)
-			v = _x.tox11[v];
-		gc = _x.gcfill;
-		if(_x.gcfillcolor != v){
-			XSetForeground(_x.display, gc, v);
-			_x.gcfillcolor = v;
-		}
-	}
-
-	/*
-	 * XFillRectangle takes coordinates relative to image rectangle.
-	 */
-	p = subpt(r.min, m->r.min);
-	XFillRectangle(_x.display, xm->pixmap, gc, p.x, p.y, Dx(r), Dy(r));
-}
-
-
blob - 395f45559c7c5461e0c2fe47c3e2202f50d106d1 (mode 644)
blob + /dev/null
--- src/libdraw/x11-get.c
+++ /dev/null
@@ -1,112 +0,0 @@
-#include <u.h>
-#include "x11-inc.h"
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include "x11-memdraw.h"
-
-static void
-addrect(Rectangle *rp, Rectangle r)
-{
-	if(rp->min.x >= rp->max.x)
-		*rp = r;
-	else
-		combinerect(rp, r);
-}
-
-XImage*
-_xgetxdata(Memimage *m, Rectangle r)
-{
-	int x, y;
-	uchar *p;
-	Point tp, xdelta, delta;
-	Xmem *xm;
-	
-	xm = m->X;
-	if(xm == nil)
-		return nil;
-
-	if(xm->dirty == 0)
-		return xm->xi;
-
-	abort();	/* should never call this now */
-
-	r = xm->dirtyr;
-	if(Dx(r)==0 || Dy(r)==0)
-		return xm->xi;
-
-	delta = subpt(r.min, m->r.min);
-
-	tp = xm->r.min;	/* need temp for Digital UNIX */
-	xdelta = subpt(r.min, tp);
-
-	XGetSubImage(_x.display, xm->pixmap, delta.x, delta.y, Dx(r), Dy(r),
-		AllPlanes, ZPixmap, xm->xi, xdelta.x, delta.y);
-
-	if(_x.usetable && m->chan==CMAP8){
-		for(y=r.min.y; y<r.max.y; y++)
-		for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
-			*p = _x.toplan9[*p];
-	}
-	xm->dirty = 0;
-	xm->dirtyr = Rect(0,0,0,0);
-	return xm->xi;
-}
-
-void
-_xputxdata(Memimage *m, Rectangle r)
-{
-	int offset, x, y;
-	uchar *p;
-	Point tp, xdelta, delta;
-	Xmem *xm;
-	XGC gc;
-	XImage *xi;
-
-	xm = m->X;
-	if(xm == nil)
-		return;
-
-	xi = xm->xi;
-	gc = m->chan==GREY1 ? _x.gccopy0 : _x.gccopy;
-	if(m->depth == 24)
-		offset = r.min.x & 3;
-	else
-		offset = r.min.x & (31/m->depth);
-
-	delta = subpt(r.min, m->r.min);
-
-	tp = xm->r.min;	/* need temporary on Digital UNIX */
-	xdelta = subpt(r.min, tp);
-
-	if(_x.usetable && m->chan==CMAP8){
-		for(y=r.min.y; y<r.max.y; y++)
-		for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
-			*p = _x.tox11[*p];
-	}
-
-	XPutImage(_x.display, xm->pixmap, gc, xi, xdelta.x, xdelta.y, delta.x, delta.y,
-		Dx(r), Dy(r));
-	
-	if(_x.usetable && m->chan==CMAP8){
-		for(y=r.min.y; y<r.max.y; y++)
-		for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
-			*p = _x.toplan9[*p];
-	}
-}
-
-void
-_xdirtyxdata(Memimage *m, Rectangle r)
-{
-	Xmem *xm;
-
-	xm = m->X;
-	if(xm == nil)
-		return;
-
-	xm->dirty = 1;
-	addrect(&xm->dirtyr, r);
-}
-
-
-
blob - 4baf4b1afca1b06cee1cbe12d5a32c2b33449bc5 (mode 644)
blob + /dev/null
--- src/libdraw/x11-inc.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#define Colormap	XColormap
-#define Cursor		XCursor
-#define Display		XDisplay
-#define Drawable	XDrawable
-#define Font		XFont
-#define GC		XGC
-#define Point		XPoint
-#define Rectangle	XRectangle
-#define Screen		XScreen
-#define Visual		XVisual
-#define Window		XWindow
-
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#include <X11/Xutil.h>
-#include <X11/keysym.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-
-#undef Colormap
-#undef Cursor
-#undef Display
-#undef Drawable
-#undef Font
-#undef GC
-#undef Point
-#undef Rectangle
-#undef Screen
-#undef Visual
-#undef Window
-
blob - b824441b49efb6233da511e9c4be98175204b8ba (mode 644)
blob + /dev/null
--- src/libdraw/x11-init.c
+++ /dev/null
@@ -1,940 +0,0 @@
-/*
- * Some of the stuff in this file is not X-dependent and should be elsewhere.
- */
-#include <u.h>
-#include "x11-inc.h"
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include <keyboard.h>
-#include <mouse.h>
-#include <cursor.h>
-#include "x11-memdraw.h"
-
-char *winsize;
-static int parsewinsize(char*, Rectangle*, int*);
-
-static Memimage	*xattach(char*);
-static void	plan9cmap(void);
-static int	setupcmap(XWindow);
-static int	xreplacescreenimage(void);
-static XGC	xgc(XDrawable, int, int);
-static Image	*getimage0(Display*, Image*);
-
-Xprivate _x;
-
-Display*
-_initdisplay(void (*error)(Display*, char*), char *label)
-{
-	Display *d;
-	Memimage *m;
-
-	/*
-	 * This rfork(RFNOTEG) isn't exactly right,
-	 * but we need some way to signal window 
-	 * closes.  Right now we post a hangup
-	 * note to the note group, which kills a whole
-	 * lot more than just the current program
-	 * if we don't do this.
-	 */
-	/*
-	 * Actually, I don't know what I changed but
-	 * this appears not to be necessary anymore.
-	 * I'll regret this probably.
-	rfork(RFNOTEG);
-	*/
-	memimageinit();
-
-	d = mallocz(sizeof(Display), 1);
-	if(d == nil)
-		return nil;
-
-	d->buf = malloc(16000+5);
-	d->obuf = malloc(16000);
-	if(d->buf == nil || d->obuf == nil){
-		free(d->buf);
-		free(d->obuf);
-		free(d);
-		return nil;
-	}
-	d->bufsize = 16000;
-	d->obufsize = 16000;
-	d->bufp = d->buf;
-	d->obufp = d->obuf;
-
-	m = xattach(label);
-	if(m == nil){
-		free(d);
-		return nil;
-	}
-
-	d->error = error;
-	_initdisplaymemimage(d, m);
-	d->image = getimage0(d, 0);
-	
-	return d;
-}
-
-static Image*
-getimage0(Display *d, Image *image)
-{
-	char info[12*12+1];
-	uchar *a;
-	int n;
-	extern int _freeimage1(Image*);
-
-	/*
-	 * If there's an old screen, it has id 0.  The 'J' request below
-	 * will try to install the new screen as id 0, so the old one 
-	 * must be freed first.
-	 */
-	if(image){
-		_freeimage1(image);
-		memset(image, 0, sizeof(Image));
-	}
-
-	a = bufimage(d, 2);
-	a[0] = 'J';
-	a[1] = 'I';
-	if(flushimage(d, 0) < 0){
-		fprint(2, "cannot read screen info: %r\n");
-		abort();
-	}
-
-	n = _drawmsgread(d, info, sizeof info);
-	if(n != 12*12){
-		fprint(2, "short screen info\n");
-		abort();
-	}
-
-	if(image == nil){
-		image = mallocz(sizeof(Image), 1);
-		if(image == nil){
-			fprint(2, "cannot allocate image: %r\n");
-			abort();
-		}
-	}
-
-	image->display = d;
-	image->id = 0;
-	image->chan = strtochan(info+2*12);
-	image->depth = chantodepth(image->chan);
-	image->repl = atoi(info+3*12);
-	image->r.min.x = atoi(info+4*12);
-	image->r.min.y = atoi(info+5*12);
-	image->r.max.x = atoi(info+6*12);
-	image->r.max.y = atoi(info+7*12);
-	image->clipr.min.x = atoi(info+8*12);
-	image->clipr.min.y = atoi(info+9*12);
-	image->clipr.max.x = atoi(info+10*12);
-	image->clipr.max.y = atoi(info+11*12);
-	return image;
-}
-
-int
-getwindow(Display *d, int ref)
-{
-	Image *i;
-	Image *oi;
-
-	if(_x.destroyed){
-		postnote(PNGROUP, getpgrp(), "hangup");
-		return -1;
-	}
-	if(xreplacescreenimage() == 0)
-		return 0;
-
-	/*
-	 * Libdraw promises not to change the value of "screen",
-	 * so we have to reuse the image structure
-	 * memory we already have.
-	 */
-	oi = d->image;
-	i = getimage0(d, oi);
-	d->image = i;
-	/* fprint(2, "getwindow %p -> %p\n", oi, i); */
-
-	freescreen(_screen);
-	_screen = allocscreen(i, d->white, 0);
-	_freeimage1(screen);
-	screen = _allocwindow(screen, _screen, i->r, ref, DWhite);
-	d->screenimage = screen;
-	return 0;
-}
-
-static int
-xerror(XDisplay *d, XErrorEvent *e)
-{
-	char buf[200];
-
-	if(e->request_code == 42) /* XSetInputFocus */
-		return 0;
-	if(e->request_code == 18) /* XChangeProperty */
-		return 0;
-
-	print("X error: error_code=%d, request_code=%d, minor=%d disp=%p\n",
-		e->error_code, e->request_code, e->minor_code, d);
-	XGetErrorText(d, e->error_code, buf, sizeof buf);
-	print("%s\n", buf);
-	return 0;
-}
-
-static int
-xioerror(XDisplay *d)
-{
-	/*print("X I/O error\n"); */
-	sysfatal("X I/O error\n");
-	abort();
-	return -1;
-}
-
-
-static Memimage*
-xattach(char *label)
-{
-	char *argv[2], *disp;
-	int i, havemin, height, mask, n, width, x, xrootid, y;
-	Rectangle r;
-	XClassHint classhint;
-	XDrawable pmid;
-	XPixmapFormatValues *pfmt;
-	XScreen *xscreen;
-	XSetWindowAttributes attr;
-	XSizeHints normalhint;
-	XTextProperty name;
-	XVisualInfo xvi;
-	XWindow xrootwin;
-	XWindowAttributes wattr;
-	XWMHints hint;
-	Atom atoms[2];
-
-	/*
-	if(XInitThreads() == 0){
-		fprint(2, "XInitThreads failed\n");
-		abort();
-	}
-	*/
-
-	/*
-	 * Connect to X server.
-	 */
-	_x.display = XOpenDisplay(NULL);
-	if(_x.display == nil){
-		disp = getenv("DISPLAY");
-		werrstr("XOpenDisplay %s: %r", disp ? disp : ":0");
-		free(disp);
-		return nil;
-	}
-	XSetErrorHandler(xerror);
-	XSetIOErrorHandler(xioerror);
-	xrootid = DefaultScreen(_x.display);
-	xrootwin = DefaultRootWindow(_x.display);
-
-	/* 
-	 * Figure out underlying screen format.
-	 */
-	if(XMatchVisualInfo(_x.display, xrootid, 16, TrueColor, &xvi)
-	|| XMatchVisualInfo(_x.display, xrootid, 16, DirectColor, &xvi)){
-		_x.vis = xvi.visual;
-		_x.depth = 16;
-	}
-	else
-	if(XMatchVisualInfo(_x.display, xrootid, 15, TrueColor, &xvi)
-	|| XMatchVisualInfo(_x.display, xrootid, 15, DirectColor, &xvi)){
-		_x.vis = xvi.visual;
-		_x.depth = 15;
-	}
-	else
-	if(XMatchVisualInfo(_x.display, xrootid, 24, TrueColor, &xvi)
-	|| XMatchVisualInfo(_x.display, xrootid, 24, DirectColor, &xvi)){
-		_x.vis = xvi.visual;
-		_x.depth = 24;
-	}
-	else
-	if(XMatchVisualInfo(_x.display, xrootid, 8, PseudoColor, &xvi)
-	|| XMatchVisualInfo(_x.display, xrootid, 8, StaticColor, &xvi)){
-		if(_x.depth > 8){
-			werrstr("can't deal with colormapped depth %d screens",
-				_x.depth);
-			goto err0;
-		}
-		_x.vis = xvi.visual;
-		_x.depth = 8;
-	}
-	else{
-		_x.depth = DefaultDepth(_x.display, xrootid);
-		if(_x.depth != 8){
-			werrstr("can't understand depth %d screen", _x.depth);
-			goto err0;
-		}
-		_x.vis = DefaultVisual(_x.display, xrootid);
-	}
-
-	if(DefaultDepth(_x.display, xrootid) == _x.depth)
-		_x.usetable = 1;
-
-	/*
-	 * _x.depth is only the number of significant pixel bits,
-	 * not the total number of pixel bits.  We need to walk the
-	 * display list to find how many actual bits are used
-	 * per pixel.
-	 */
-	_x.chan = 0;
-	pfmt = XListPixmapFormats(_x.display, &n);
-	for(i=0; i<n; i++){
-		if(pfmt[i].depth == _x.depth){
-			switch(pfmt[i].bits_per_pixel){
-			case 1:	/* untested */
-				_x.chan = GREY1;
-				break;
-			case 2:	/* untested */
-				_x.chan = GREY2;
-				break;
-			case 4:	/* untested */
-				_x.chan = GREY4;
-				break;
-			case 8:
-				_x.chan = CMAP8;
-				break;
-			case 15:
-				_x.chan = RGB15;
-				break;
-			case 16: /* how to tell RGB15? */
-				_x.chan = RGB16;
-				break;
-			case 24: /* untested (impossible?) */
-				_x.chan = RGB24;
-				break;
-			case 32:
-				_x.chan = XRGB32;
-				break;
-			}
-		}
-	}
-	if(_x.chan == 0){
-		werrstr("could not determine screen pixel format");
-		goto err0;
-	}
-
-	/*
-	 * Set up color map if necessary.
-	 */
-	xscreen = DefaultScreenOfDisplay(_x.display);
-	_x.cmap = DefaultColormapOfScreen(xscreen);
-	if(_x.vis->class != StaticColor){
-		plan9cmap();
-		setupcmap(xrootwin);
-	}
-
-	/*
-	 * We get to choose the initial rectangle size.
-	 * This is arbitrary.  In theory we should read the
-	 * command line and allow the traditional X options.
-	 */
-	mask = 0;
-	x = 0;
-	y = 0;
-	if(winsize){
-		if(parsewinsize(winsize, &r, &havemin) < 0)
-			sysfatal("%r");
-	}else{
-		/*
-		 * Parse the various X resources.  Thanks to Peter Canning.
-		 */
-		char *screen_resources, *display_resources, *geom, 
-			*geomrestype, *home, *file;
-		XrmDatabase database;
-		XrmValue geomres;
-
-		database = XrmGetDatabase(_x.display);
-		screen_resources = XScreenResourceString(xscreen);
-		if(screen_resources != nil){
-			XrmCombineDatabase(XrmGetStringDatabase(screen_resources), &database, False);
-			XFree(screen_resources);
-		}
-
-		display_resources = XResourceManagerString(_x.display);
-		if(display_resources == nil){
-			home = getenv("HOME");
-			if(home!=nil && (file=smprint("%s/.Xdefaults", home)) != nil){
-				XrmCombineFileDatabase(file, &database, False);
-				free(file);
-			}
-			free(home);
-		}else
-			XrmCombineDatabase(XrmGetStringDatabase(display_resources), &database, False);
-
-		geom = smprint("%s.geometry", label);
-		if(geom && XrmGetResource(database, geom, nil, &geomrestype, &geomres))
-			mask = XParseGeometry(geomres.addr, &x, &y, (uint*)&width, (uint*)&height);
-		free(geom);
-
-		if((mask & WidthValue) && (mask & HeightValue)){
-			r = Rect(0, 0, width, height);
-		}else{
-			r = Rect(0, 0, WidthOfScreen(xscreen)*3/4,
-					HeightOfScreen(xscreen)*3/4);
-			if(Dx(r) > Dy(r)*3/2)
-				r.max.x = r.min.x + Dy(r)*3/2;
-			if(Dy(r) > Dx(r)*3/2)
-				r.max.y = r.min.y + Dx(r)*3/2;
-		}
-		if(mask & XNegative){
-			x += WidthOfScreen(xscreen);
-		}
-		if(mask & YNegative){
-			y += HeightOfScreen(xscreen);
-		}
-		havemin = 0;
-	}
-
-	memset(&attr, 0, sizeof attr);
-	attr.colormap = _x.cmap;
-	attr.background_pixel = ~0;
-	attr.border_pixel = 0;
-	_x.drawable = XCreateWindow(
-		_x.display,	/* display */
-		xrootwin,	/* parent */
-		x,		/* x */
-		y,		/* y */
-		Dx(r),		/* width */
-	 	Dy(r),		/* height */
-		0,		/* border width */
-		_x.depth,	/* depth */
-		InputOutput,	/* class */
-		_x.vis,		/* visual */
-				/* valuemask */
-		CWBackPixel|CWBorderPixel|CWColormap,
-		&attr		/* attributes (the above aren't?!) */
-	);
-
-	/*
-	 * Label and other properties required by ICCCCM.
-	 */
-	memset(&name, 0, sizeof name);
-	if(label == nil)
-		label = "pjw-face-here";
-	name.value = (uchar*)label;
-	name.encoding = XA_STRING;
-	name.format = 8;
-	name.nitems = strlen((char*)name.value);
-
-	memset(&normalhint, 0, sizeof normalhint);
-	normalhint.flags = PSize|PMaxSize;
-	if(winsize){
-		normalhint.flags &= ~PSize;
-		normalhint.flags |= USSize;
-		normalhint.width = Dx(r);
-		normalhint.height = Dy(r);
-	}else{
-		if((mask & WidthValue) && (mask & HeightValue)){
-			normalhint.flags &= ~PSize;
-			normalhint.flags |= USSize;
-			normalhint.width = width;
-			normalhint.height = height;
-		}
-		if((mask & WidthValue) && (mask & HeightValue)){
-			normalhint.flags |= USPosition;
-			normalhint.x = x;
-			normalhint.y = y;
-		}
-	}
-
-	normalhint.max_width = WidthOfScreen(xscreen);
-	normalhint.max_height = HeightOfScreen(xscreen);
-
-	memset(&hint, 0, sizeof hint);
-	hint.flags = InputHint|StateHint;
-	hint.input = 1;
-	hint.initial_state = NormalState;
-
-	memset(&classhint, 0, sizeof classhint);
-	classhint.res_name = label;
-	classhint.res_class = label;
-
-	argv[0] = label;
-	argv[1] = nil;
-
-	XSetWMProperties(
-		_x.display,	/* display */
-		_x.drawable,	/* window */
-		&name,		/* XA_WM_NAME property */
-		&name,		/* XA_WM_ICON_NAME property */
-		argv,		/* XA_WM_COMMAND */
-		1,		/* argc */
-		&normalhint,	/* XA_WM_NORMAL_HINTS */
-		&hint,		/* XA_WM_HINTS */
-		&classhint	/* XA_WM_CLASSHINTS */
-	);
-	XFlush(_x.display);
-
-	if(havemin){
-		XWindowChanges ch;
-
-		memset(&ch, 0, sizeof ch);
-		ch.x = r.min.x;
-		ch.y = r.min.y;
-		XConfigureWindow(_x.display, _x.drawable, CWX|CWY, &ch);
-		/*
-		 * Must pretend origin is 0,0 for X.
-		 */
-		r = Rect(0,0,Dx(r),Dy(r));
-	}
-	/*
-	 * Look up clipboard atom.
-	 */
-	_x.clipboard = XInternAtom(_x.display, "CLIPBOARD", False);
-	_x.utf8string = XInternAtom(_x.display, "UTF8_STRING", False);
-	_x.targets = XInternAtom(_x.display, "TARGETS", False);
-	_x.text = XInternAtom(_x.display, "TEXT", False);
-	_x.compoundtext = XInternAtom(_x.display, "COMPOUND_TEXT", False);
-	_x.takefocus = XInternAtom(_x.display, "WM_TAKE_FOCUS", False);
-	_x.losefocus = XInternAtom(_x.display, "_9WM_LOSE_FOCUS", False);
-	_x.wmprotos = XInternAtom(_x.display, "WM_PROTOCOLS", False);
-
-	atoms[0] = _x.takefocus;
-	atoms[1] = _x.losefocus;
-	XChangeProperty(_x.display, _x.drawable, _x.wmprotos, XA_ATOM, 32,
-		PropModeReplace, (uchar*)atoms, 2);
-
-	/*
-	 * Put the window on the screen, check to see what size we actually got.
-	 */
-	XMapWindow(_x.display, _x.drawable);
-	XSync(_x.display, False);
-
-	if(!XGetWindowAttributes(_x.display, _x.drawable, &wattr))
-		fprint(2, "XGetWindowAttributes failed\n");
-	else if(wattr.width && wattr.height){
-		if(wattr.width != Dx(r) || wattr.height != Dy(r)){
-			r.max.x = wattr.width;
-			r.max.y = wattr.height;
-		}
-	}else
-		fprint(2, "XGetWindowAttributes: bad attrs\n");
-
-	/*
-	 * Allocate our local backing store.
-	 */
-	_x.screenr = r;
-	_x.screenpm = XCreatePixmap(_x.display, _x.drawable, Dx(r), Dy(r), _x.depth);
-	_x.nextscreenpm = _x.screenpm;
-	_x.screenimage = _xallocmemimage(r, _x.chan, _x.screenpm);
-
-	/*
-	 * Allocate some useful graphics contexts for the future.
-	 */
-	_x.gcfill	= xgc(_x.screenpm, FillSolid, -1);
-	_x.gccopy	= xgc(_x.screenpm, -1, -1);
-	_x.gcsimplesrc 	= xgc(_x.screenpm, FillStippled, -1);
-	_x.gczero	= xgc(_x.screenpm, -1, -1);
-	_x.gcreplsrc	= xgc(_x.screenpm, FillTiled, -1);
-
-	pmid = XCreatePixmap(_x.display, _x.drawable, 1, 1, 1);
-	_x.gcfill0	= xgc(pmid, FillSolid, 0);
-	_x.gccopy0	= xgc(pmid, -1, -1);
-	_x.gcsimplesrc0	= xgc(pmid, FillStippled, -1);
-	_x.gczero0	= xgc(pmid, -1, -1);
-	_x.gcreplsrc0	= xgc(pmid, FillTiled, -1);
-	XFreePixmap(_x.display, pmid);
-
-	/*
-	 * Lots of display connections for various procs.
-	 */
-	_x.kbdcon	= XOpenDisplay(NULL);
-	_x.mousecon	= XOpenDisplay(NULL);
-	_x.snarfcon	= XOpenDisplay(NULL);
-
-	if(0) fprint(2, "x: display=%p kbd=%p mouse=%p snarf=%p\n",
-		_x.display, _x.kbdcon, _x.mousecon, _x.snarfcon);
-
-	return _x.screenimage;
-
-err0:
-	/*
-	 * Should do a better job of cleaning up here.
-	 */
-	XCloseDisplay(_x.display);
-	return nil;
-}
-
-int
-drawsetlabel(char *label)
-{
-	XTextProperty name;
-
-	/*
-	 * Label and other properties required by ICCCCM.
-	 */
-	memset(&name, 0, sizeof name);
-	if(label == nil)
-		label = "pjw-face-here";
-	name.value = (uchar*)label;
-	name.encoding = XA_STRING;
-	name.format = 8;
-	name.nitems = strlen((char*)name.value);
-
-	XSetWMProperties(
-		_x.display,	/* display */
-		_x.drawable,	/* window */
-		&name,		/* XA_WM_NAME property */
-		&name,		/* XA_WM_ICON_NAME property */
-		nil,		/* XA_WM_COMMAND */
-		0,		/* argc */
-		nil,		/* XA_WM_NORMAL_HINTS */
-		nil,		/* XA_WM_HINTS */
-		nil	/* XA_WM_CLASSHINTS */
-	);
-	XFlush(_x.display);
-	return 0;
-}
-
-/*
- * Create a GC with a particular fill style and XXX.
- * Disable generation of GraphicsExpose/NoExpose events in the GC.
- */
-static XGC
-xgc(XDrawable d, int fillstyle, int foreground)
-{
-	XGC gc;
-	XGCValues v;
-
-	memset(&v, 0, sizeof v);
-	v.function = GXcopy;
-	v.graphics_exposures = False;
-	gc = XCreateGC(_x.display, d, GCFunction|GCGraphicsExposures, &v);
-	if(fillstyle != -1)
-		XSetFillStyle(_x.display, gc, fillstyle);
-	if(foreground != -1)
-		XSetForeground(_x.display, gc, 0);
-	return gc;
-}
-
-
-/*
- * Initialize map with the Plan 9 rgbv color map.
- */
-static void
-plan9cmap(void)
-{
-	int r, g, b, cr, cg, cb, v, num, den, idx, v7, idx7;
-	static int once;
-
-	if(once)
-		return;
-	once = 1;
-
-	for(r=0; r!=4; r++)
-	for(g = 0; g != 4; g++)
-	for(b = 0; b!=4; b++)
-	for(v = 0; v!=4; v++){
-		den=r;
-		if(g > den)
-			den=g;
-		if(b > den)
-			den=b;
-		/* divide check -- pick grey shades */
-		if(den==0)
-			cr=cg=cb=v*17;
-		else {
-			num=17*(4*den+v);
-			cr=r*num/den;
-			cg=g*num/den;
-			cb=b*num/den;
-		}
-		idx = r*64 + v*16 + ((g*4 + b + v - r) & 15);
-		_x.map[idx].red = cr*0x0101;
-		_x.map[idx].green = cg*0x0101;
-		_x.map[idx].blue = cb*0x0101;
-		_x.map[idx].pixel = idx;
-		_x.map[idx].flags = DoRed|DoGreen|DoBlue;
-
-		v7 = v >> 1;
-		idx7 = r*32 + v7*16 + g*4 + b;
-		if((v & 1) == v7){
-			_x.map7to8[idx7][0] = idx;
-			if(den == 0) { 		/* divide check -- pick grey shades */
-				cr = ((255.0/7.0)*v7)+0.5;
-				cg = cr;
-				cb = cr;
-			}
-			else {
-				num=17*15*(4*den+v7*2)/14;
-				cr=r*num/den;
-				cg=g*num/den;
-				cb=b*num/den;
-			}
-			_x.map7[idx7].red = cr*0x0101;
-			_x.map7[idx7].green = cg*0x0101;
-			_x.map7[idx7].blue = cb*0x0101;
-			_x.map7[idx7].pixel = idx7;
-			_x.map7[idx7].flags = DoRed|DoGreen|DoBlue;
-		}
-		else
-			_x.map7to8[idx7][1] = idx;
-	}
-}
-
-/*
- * Initialize and install the rgbv color map as a private color map
- * for this application.  It gets the best colors when it has the
- * cursor focus.
- *
- * We always choose the best depth possible, but that might not
- * be the default depth.  On such "suboptimal" systems, we have to allocate an
- * empty color map anyway, according to Axel Belinfante.
- */
-static int 
-setupcmap(XWindow w)
-{
-	char buf[30];
-	int i;
-	u32int p, pp;
-	XColor c;
-
-	if(_x.depth <= 1)
-		return 0;
-
-	if(_x.depth >= 24) {
-		if(_x.usetable == 0)
-			_x.cmap = XCreateColormap(_x.display, w, _x.vis, AllocNone); 
-
-		/*
-		 * The pixel value returned from XGetPixel needs to
-		 * be converted to RGB so we can call rgb2cmap()
-		 * to translate between 24 bit X and our color. Unfortunately,
-		 * the return value appears to be display server endian 
-		 * dependant. Therefore, we run some heuristics to later
-		 * determine how to mask the int value correctly.
-		 * Yeah, I know we can look at _x.vis->byte_order but 
-		 * some displays say MSB even though they run on LSB.
-		 * Besides, this is more anal.
-		 */
-		c = _x.map[19];	/* known to have different R, G, B values */
-		if(!XAllocColor(_x.display, _x.cmap, &c)){
-			werrstr("XAllocColor: %r");
-			return -1;
-		}
-		p  = c.pixel;
-		pp = rgb2cmap((p>>16)&0xff,(p>>8)&0xff,p&0xff);
-		if(pp != _x.map[19].pixel) {
-			/* check if endian is other way */
-			pp = rgb2cmap(p&0xff,(p>>8)&0xff,(p>>16)&0xff);
-			if(pp != _x.map[19].pixel){
-				werrstr("cannot detect X server byte order");
-				return -1;
-			}
-
-			switch(_x.chan){
-			case RGB24:
-				_x.chan = BGR24;
-				break;
-			case XRGB32:
-				_x.chan = XBGR32;
-				break;
-			default:
-				werrstr("cannot byteswap channel %s",
-					chantostr(buf, _x.chan));
-				break;
-			}
-		}
-	}else if(_x.vis->class == TrueColor || _x.vis->class == DirectColor){
-		/*
-		 * Do nothing.  We have no way to express a
-		 * mixed-endian 16-bit screen, so pretend they don't exist.
-		 */
-		if(_x.usetable == 0)
-			_x.cmap = XCreateColormap(_x.display, w, _x.vis, AllocNone);
-	}else if(_x.vis->class == PseudoColor){
-		if(_x.usetable == 0){
-			_x.cmap = XCreateColormap(_x.display, w, _x.vis, AllocAll); 
-			XStoreColors(_x.display, _x.cmap, _x.map, 256);
-			for(i = 0; i < 256; i++){
-				_x.tox11[i] = i;
-				_x.toplan9[i] = i;
-			}
-		}else{
-			for(i = 0; i < 128; i++){
-				c = _x.map7[i];
-				if(!XAllocColor(_x.display, _x.cmap, &c)){
-					werrstr("can't allocate colors in 7-bit map");
-					return -1;
-				}
-				_x.tox11[_x.map7to8[i][0]] = c.pixel;
-				_x.tox11[_x.map7to8[i][1]] = c.pixel;
-				_x.toplan9[c.pixel] = _x.map7to8[i][0];
-			}
-		}
-	}else{
-		werrstr("unsupported visual class %d", _x.vis->class);
-		return -1;
-	}
-	return 0;
-}
-
-void
-_flushmemscreen(Rectangle r)
-{
-	if(_x.nextscreenpm != _x.screenpm){
-		qlock(&_x.screenlock);
-		XSync(_x.display, False);
-		XFreePixmap(_x.display, _x.screenpm);
-		_x.screenpm = _x.nextscreenpm;
-		qunlock(&_x.screenlock);
-	}
-
-	if(r.min.x >= r.max.x || r.min.y >= r.max.y)
-		return;
-	XCopyArea(_x.display, _x.screenpm, _x.drawable, _x.gccopy, r.min.x, r.min.y,
-		Dx(r), Dy(r), r.min.x, r.min.y);
-	XFlush(_x.display);
-}
-
-void
-_xexpose(XEvent *e, XDisplay *xd)
-{
-	XExposeEvent *xe;
-	Rectangle r;
-
-	qlock(&_x.screenlock);
-	if(_x.screenpm != _x.nextscreenpm){
-		qunlock(&_x.screenlock);
-		return;
-	}
-	xe = (XExposeEvent*)e;
-	r.min.x = xe->x;
-	r.min.y = xe->y;
-	r.max.x = xe->x+xe->width;
-	r.max.y = xe->y+xe->height;
-	XCopyArea(xd, _x.screenpm, _x.drawable, _x.gccopy, r.min.x, r.min.y,
-		Dx(r), Dy(r), r.min.x, r.min.y);
-	XSync(xd, False);
-	qunlock(&_x.screenlock);
-}
-
-int
-_xdestroy(XEvent *e, XDisplay *xd)
-{
-	XDestroyWindowEvent *xe;
-
-	xe = (XDestroyWindowEvent*)e;
-	if(xe->window == _x.drawable){
-		_x.destroyed = 1;
-		return 1;
-	}
-	return 0;
-}
-
-int
-_xconfigure(XEvent *e, XDisplay *xd)
-{
-	Rectangle r;
-	XConfigureEvent *xe = (XConfigureEvent*)e;
-
-	if(xe->width == Dx(_x.screenr) && xe->height == Dy(_x.screenr))
-		return 0;
-	if(xe->width==0 || xe->height==0)
-		fprint(2, "ignoring resize to %dx%d\n", xe->width, xe->height);
-	r = Rect(0, 0, xe->width, xe->height);
-	qlock(&_x.screenlock);
-	if(_x.screenpm != _x.nextscreenpm){
-		XCopyArea(xd, _x.screenpm, _x.drawable, _x.gccopy, r.min.x, r.min.y,
-			Dx(r), Dy(r), r.min.x, r.min.y);
-		XSync(xd, False);
-	}
-	qunlock(&_x.screenlock);
-	_x.newscreenr = r;
-	return 1;
-}
-
-static int
-xreplacescreenimage(void)
-{
-	Memimage *m;
-	XDrawable pixmap;
-	Rectangle r;
-
-	r = _x.newscreenr;
-	if(eqrect(_x.screenr, r))
-		return 0;
-
-	pixmap = XCreatePixmap(_x.display, _x.drawable, Dx(r), Dy(r), _x.depth);
-	m = _xallocmemimage(r, _x.chan, pixmap);
-	if(_x.nextscreenpm != _x.screenpm)
-		XFreePixmap(_x.display, _x.nextscreenpm);
-	_x.nextscreenpm = pixmap;
-	_x.screenr = r;
-	_drawreplacescreenimage(m);
-	return 1;
-}
-
-static int
-parsewinsize(char *s, Rectangle *r, int *havemin)
-{
-	char c, *os;
-	int i, j, k, l;
-
-	os = s;
-	*havemin = 0;
-	*r = Rect(0,0,0,0);
-	if(!isdigit((uchar)*s))
-		goto oops;
-	i = strtol(s, &s, 0);
-	if(*s == 'x'){
-		s++;
-		if(!isdigit((uchar)*s))
-			goto oops;
-		j = strtol(s, &s, 0);
-		r->max.x = i;
-		r->max.y = j;
-		if(*s == 0)
-			return 0;
-		if(*s != '@')
-			goto oops;
-
-		s++;
-		if(!isdigit((uchar)*s))
-			goto oops;
-		i = strtol(s, &s, 0);
-		if(*s != ',' && *s != ' ')
-			goto oops;
-		s++;
-		if(!isdigit((uchar)*s))
-			goto oops;
-		j = strtol(s, &s, 0);
-		if(*s != 0)
-			goto oops;
-		*r = rectaddpt(*r, Pt(i,j));
-		*havemin = 1;
-		return 0;
-	}
-
-	c = *s;
-	if(c != ' ' && c != ',')
-		goto oops;
-	s++;
-	if(!isdigit((uchar)*s))
-		goto oops;
-	j = strtol(s, &s, 0);
-	if(*s != c)
-		goto oops;
-	s++;
-	if(!isdigit((uchar)*s))
-		goto oops;
-	k = strtol(s, &s, 0);
-	if(*s != c)
-		goto oops;
-	s++;
-	if(!isdigit((uchar)*s))
-		goto oops;
-	l = strtol(s, &s, 0);
-	if(*s != 0)
-		goto oops;
-	*r = Rect(i,j,k,l);
-	*havemin = 1;
-	return 0;
-
-oops:
-	werrstr("bad syntax in window size '%s'", os);
-	return -1;
-}
blob - d8c1ff6bc4ff01dcea4a1942ebde76bc9300455b (mode 644)
blob + /dev/null
--- src/libdraw/x11-itrans.c
+++ /dev/null
@@ -1,675 +0,0 @@
-/* input event and data structure translation */
-
-#include <u.h>
-#include "x11-inc.h"
-#ifdef __APPLE__
-#define APPLESNARF
-#define Boolean AppleBoolean
-#define Rect AppleRect
-#define EventMask AppleEventMask
-#define Point ApplePoint
-#define Cursor AppleCursor
-#include <Carbon/Carbon.h>
-AUTOFRAMEWORK(Carbon)
-#undef Boolean
-#undef Rect
-#undef EventMask
-#undef Point
-#undef Cursor
-#endif
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include <mouse.h>
-#include <cursor.h>
-#include <keyboard.h>
-#include "x11-memdraw.h"
-#include "x11-keysym2ucs.h"
-#undef time
-
-static KeySym
-__xtoplan9kbd(XEvent *e)
-{
-	KeySym k;
-
-	if(e->xany.type != KeyPress)
-		return -1;
-	needstack(64*1024);	/* X has some *huge* buffers in openobject */
-		/* and they're even bigger on SuSE */
-	XLookupString((XKeyEvent*)e,NULL,0,&k,NULL);
-	if(k == XK_Multi_key || k == NoSymbol)
-		return -1;
-
-	if(k&0xFF00){
-		switch(k){
-		case XK_BackSpace:
-		case XK_Tab:
-		case XK_Escape:
-		case XK_Delete:
-		case XK_KP_0:
-		case XK_KP_1:
-		case XK_KP_2:
-		case XK_KP_3:
-		case XK_KP_4:
-		case XK_KP_5:
-		case XK_KP_6:
-		case XK_KP_7:
-		case XK_KP_8:
-		case XK_KP_9:
-		case XK_KP_Divide:
-		case XK_KP_Multiply:
-		case XK_KP_Subtract:
-		case XK_KP_Add:
-		case XK_KP_Decimal:
-			k &= 0x7F;
-			break;
-		case XK_Linefeed:
-			k = '\r';
-			break;
-		case XK_KP_Space:
-			k = ' ';
-			break;
-		case XK_Home:
-		case XK_KP_Home:
-			k = Khome;
-			break;
-		case XK_Left:
-		case XK_KP_Left:
-			k = Kleft;
-			break;
-		case XK_Up:
-		case XK_KP_Up:
-			k = Kup;
-			break;
-		case XK_Down:
-		case XK_KP_Down:
-			k = Kdown;
-			break;
-		case XK_Right:
-		case XK_KP_Right:
-			k = Kright;
-			break;
-		case XK_Page_Down:
-		case XK_KP_Page_Down:
-			k = Kpgdown;
-			break;
-		case XK_End:
-		case XK_KP_End:
-			k = Kend;
-			break;
-		case XK_Page_Up:	
-		case XK_KP_Page_Up:
-			k = Kpgup;
-			break;
-		case XK_Insert:
-		case XK_KP_Insert:
-			k = Kins;
-			break;
-		case XK_KP_Enter:
-		case XK_Return:
-			k = '\n';
-			break;
-		case XK_Alt_L:
-		case XK_Meta_L:	/* Shift Alt on PCs */
-		case XK_Alt_R:
-		case XK_Meta_R:	/* Shift Alt on PCs */
-			k = Kalt;
-			break;
-		default:		/* not ISO-1 or tty control */
-			if(k>0xff) {
-				k = _p9keysym2ucs(k);
-				if(k==-1) return -1;
-			}
-		}
-	}
-
-	/* Compensate for servers that call a minus a hyphen */
-	if(k == XK_hyphen)
-		k = XK_minus;
-	/* Do control mapping ourselves if translator doesn't */
-	if(e->xkey.state&ControlMask)
-		k &= 0x9f;
-	if(k == NoSymbol) {
-		return -1;
-	}
-
-	return k+0;
-}
-
-static Rune*
-xtoplan9latin1(XEvent *e)
-{
-	static Rune k[10];
-	static int alting, nk;
-	int n;
-	int r;
-
-	r = __xtoplan9kbd(e);
-	if(r < 0)
-		return nil;
-	if(alting){
-		/*
-		 * Kludge for Mac's X11 3-button emulation.
-		 * It treats Command+Button as button 3, but also
-		 * ends up sending XK_Meta_L twice.
-		 */
-		if(r == Kalt){
-			alting = 0;
-			return nil;
-		}
-		k[nk++] = r;
-		n = _latin1(k, nk);
-		if(n > 0){
-			alting = 0;
-			k[0] = n;
-			k[1] = 0;
-			return k;
-		}
-		if(n == -1){
-			alting = 0;
-			k[nk] = 0;
-			return k;
-		}
-		/* n < -1, need more input */
-		return nil;
-	}else if(r == Kalt){
-		alting = 1;
-		nk = 0;
-		return nil;
-	}else{
-		k[0] = r;
-		k[1] = 0;
-		return k;
-	}
-}
-
-int
-_xtoplan9kbd(XEvent *e)
-{
-	static Rune *r;
-
-	if(e == (XEvent*)-1){
-		assert(r);
-		r--;
-		return 0;
-	}
-	if(e)
-		r = xtoplan9latin1(e);
-	if(r && *r)
-		return *r++;
-	return -1;
-}
-
-int
-_xtoplan9mouse(XDisplay *xd, XEvent *e, Mouse *m)
-{
-	int s;
-	XButtonEvent *be;
-	XMotionEvent *me;
-
-	if(_x.putsnarf != _x.assertsnarf){
-		_x.assertsnarf = _x.putsnarf;
-		XSetSelectionOwner(_x.mousecon, XA_PRIMARY, _x.drawable, CurrentTime);
-		if(_x.clipboard != None)
-			XSetSelectionOwner(_x.mousecon, _x.clipboard, _x.drawable, CurrentTime);
-		XFlush(xd);
-	}
-
-	switch(e->type){
-	case ButtonPress:
-		be = (XButtonEvent*)e;
-		/* 
-		 * Fake message, just sent to make us announce snarf.
-		 * Apparently state and button are 16 and 8 bits on
-		 * the wire, since they are truncated by the time they
-		 * get to us.
-		 */
-		if(be->send_event
-		&& (~be->state&0xFFFF)==0
-		&& (~be->button&0xFF)==0)
-			return -1;
-		/* BUG? on mac need to inherit these from elsewhere? */
-		m->xy.x = be->x;
-		m->xy.y = be->y;
-		s = be->state;
-		m->msec = be->time;
-		switch(be->button){
-		case 1:
-			s |= Button1Mask;
-			break;
-		case 2:
-			s |= Button2Mask;
-			break;
-		case 3:
-			s |= Button3Mask;
-			break;
-		case 4:
-			s |= Button4Mask;
-			break;
-		case 5:
-			s |= Button5Mask;
-			break;
-		}
-		break;
-	case ButtonRelease:
-		be = (XButtonEvent*)e;
-		m->xy.x = be->x;
-		m->xy.y = be->y;
-		s = be->state;
-		m->msec = be->time;
-		switch(be->button){
-		case 1:
-			s &= ~Button1Mask;
-			break;
-		case 2:
-			s &= ~Button2Mask;
-			break;
-		case 3:
-			s &= ~Button3Mask;
-			break;
-		case 4:
-			s &= ~Button4Mask;
-			break;
-		case 5:
-			s &= ~Button5Mask;
-			break;
-		}
-		break;
-
-	case MotionNotify:
-		me = (XMotionEvent*)e;
-		s = me->state;
-		m->xy.x = me->x;
-		m->xy.y = me->y;
-		m->msec = me->time;
-		break;
-
-	default:
-		return -1;
-	}
-
-	m->buttons = 0;
-	if(s & Button1Mask)
-		m->buttons |= 1;
-	if(s & Button2Mask)
-		m->buttons |= 2;
-	if(s & Button3Mask)
-		m->buttons |= 4;
-	if(s & Button4Mask)
-		m->buttons |= 8;
-	if(s & Button5Mask)
-		m->buttons |= 16;
-	return 0;
-}
-
-void
-_xmoveto(Point p)
-{
-	XWarpPointer(_x.display, None, _x.drawable, 0, 0, 0, 0, p.x, p.y);
-	XFlush(_x.display);
-}
-
-static int
-revbyte(int b)
-{
-	int r;
-
-	r = 0;
-	r |= (b&0x01) << 7;
-	r |= (b&0x02) << 5;
-	r |= (b&0x04) << 3;
-	r |= (b&0x08) << 1;
-	r |= (b&0x10) >> 1;
-	r |= (b&0x20) >> 3;
-	r |= (b&0x40) >> 5;
-	r |= (b&0x80) >> 7;
-	return r;
-}
-
-static void
-xcursorarrow(void)
-{
-	if(_x.cursor != 0){
-		XFreeCursor(_x.display, _x.cursor);
-		_x.cursor = 0;
-	}
-	XUndefineCursor(_x.display, _x.drawable);
-	XFlush(_x.display);
-}
-
-
-void
-_xsetcursor(Cursor *c)
-{
-	XColor fg, bg;
-	XCursor xc;
-	Pixmap xsrc, xmask;
-	int i;
-	uchar src[2*16], mask[2*16];
-
-	if(c == nil){
-		xcursorarrow();
-		return;
-	}
-	for(i=0; i<2*16; i++){
-		src[i] = revbyte(c->set[i]);
-		mask[i] = revbyte(c->set[i] | c->clr[i]);
-	}
-
-	fg = _x.map[0];
-	bg = _x.map[255];
-	xsrc = XCreateBitmapFromData(_x.display, _x.drawable, (char*)src, 16, 16);
-	xmask = XCreateBitmapFromData(_x.display, _x.drawable, (char*)mask, 16, 16);
-	xc = XCreatePixmapCursor(_x.display, xsrc, xmask, &fg, &bg, -c->offset.x, -c->offset.y);
-	if(xc != 0) {
-		XDefineCursor(_x.display, _x.drawable, xc);
-		if(_x.cursor != 0)
-			XFreeCursor(_x.display, _x.cursor);
-		_x.cursor = xc;
-	}
-	XFreePixmap(_x.display, xsrc);
-	XFreePixmap(_x.display, xmask);
-	XFlush(_x.display);
-}
-
-struct {
-	QLock lk;
-	char buf[SnarfSize];
-#ifdef APPLESNARF
-	Rune rbuf[SnarfSize];
-	PasteboardRef apple;
-#endif
-} clip;
-
-char*
-_xgetsnarf(XDisplay *xd)
-{
-	uchar *data, *xdata;
-	Atom clipboard, type, prop;
-	ulong len, lastlen, dummy;
-	int fmt, i;
-	XWindow w;
-
-	qlock(&clip.lk);
-	/*
-	 * Have we snarfed recently and the X server hasn't caught up?
-	 */
-	if(_x.putsnarf != _x.assertsnarf)
-		goto mine;
-
-	/*
-	 * Is there a primary selection (highlighted text in an xterm)?
-	 */
-	clipboard = XA_PRIMARY;
-	w = XGetSelectionOwner(xd, XA_PRIMARY);
-	if(w == _x.drawable){
-	mine:
-		data = (uchar*)strdup(clip.buf);
-		goto out;
-	}
-
-	/*
-	 * If not, is there a clipboard selection?
-	 */
-	if(w == None && _x.clipboard != None){
-		clipboard = _x.clipboard;
-		w = XGetSelectionOwner(xd, _x.clipboard);
-		if(w == _x.drawable)
-			goto mine;
-	}
-
-	/*
-	 * If not, give up.
-	 */
-	if(w == None){
-		data = nil;
-		goto out;
-	}
-		
-	/*
-	 * We should be waiting for SelectionNotify here, but it might never
-	 * come, and we have no way to time out.  Instead, we will clear
-	 * local property #1, request our buddy to fill it in for us, and poll
-	 * until he's done or we get tired of waiting.
-	 *
-	 * We should try to go for _x.utf8string instead of XA_STRING,
-	 * but that would add to the polling.
-	 */
-	prop = 1;
-	XChangeProperty(xd, _x.drawable, prop, XA_STRING, 8, PropModeReplace, (uchar*)"", 0);
-	XConvertSelection(xd, clipboard, XA_STRING, prop, _x.drawable, CurrentTime);
-	XFlush(xd);
-	lastlen = 0;
-	for(i=0; i<10 || (lastlen!=0 && i<30); i++){
-		usleep(100*1000);
-		XGetWindowProperty(xd, _x.drawable, prop, 0, 0, 0, AnyPropertyType,
-			&type, &fmt, &dummy, &len, &data);
-		if(lastlen == len && len > 0)
-			break;
-		lastlen = len;
-	}
-	if(i == 10){
-		data = nil;
-		goto out;
-	}
-	/* get the property */
-	data = nil;
-	XGetWindowProperty(xd, _x.drawable, prop, 0, SnarfSize/sizeof(ulong), 0, 
-		AnyPropertyType, &type, &fmt, &len, &dummy, &xdata);
-	if((type != XA_STRING && type != _x.utf8string) || len == 0){
-		if(xdata)
-			XFree(xdata);
-		data = nil;
-	}else{
-		if(xdata){
-			data = (uchar*)strdup((char*)xdata);
-			XFree(xdata);
-		}else
-			data = nil;
-	}
-out:
-	qunlock(&clip.lk);
-	return (char*)data;
-}
-
-void
-_xputsnarf(XDisplay *xd, char *data)
-{
-	XButtonEvent e;
-
-	if(strlen(data) >= SnarfSize)
-		return;
-	qlock(&clip.lk);
-	strcpy(clip.buf, data);
-	/* leave note for mouse proc to assert selection ownership */
-	_x.putsnarf++;
-
-	/* send mouse a fake event so snarf is announced */
-	memset(&e, 0, sizeof e);
-	e.type = ButtonPress;
-	e.window = _x.drawable;
-	e.state = ~0;
-	e.button = ~0;
-	XSendEvent(xd, _x.drawable, True, ButtonPressMask, (XEvent*)&e);
-	XFlush(xd);
-	qunlock(&clip.lk);
-}
-
-int
-_xselect(XEvent *e, XDisplay *xd)
-{
-	char *name;
-	XEvent r;
-	XSelectionRequestEvent *xe;
-	Atom a[4];
-
-	memset(&r, 0, sizeof r);
-	xe = (XSelectionRequestEvent*)e;
-if(0) fprint(2, "xselect target=%d requestor=%d property=%d selection=%d\n",
-	xe->target, xe->requestor, xe->property, xe->selection);
-	r.xselection.property = xe->property;
-	if(xe->target == _x.targets){
-		a[0] = XA_STRING;
-		a[1] = _x.utf8string;
-		a[2] = _x.text;
-		a[3] = _x.compoundtext;
-
-		XChangeProperty(xd, xe->requestor, xe->property, xe->target,
-			8, PropModeReplace, (uchar*)a, sizeof a);
-	}else if(xe->target == XA_STRING 
-	|| xe->target == _x.utf8string 
-	|| xe->target == _x.text 
-	|| xe->target == _x.compoundtext
-	|| ((name = XGetAtomName(xd, xe->target)) && strcmp(name, "text/plain;charset=UTF-8") == 0)){
-		/* text/plain;charset=UTF-8 seems nonstandard but is used by Synergy */
-		/* if the target is STRING we're supposed to reply with Latin1 XXX */
-		qlock(&clip.lk);
-		XChangeProperty(xd, xe->requestor, xe->property, xe->target,
-			8, PropModeReplace, (uchar*)clip.buf, strlen(clip.buf));
-		qunlock(&clip.lk);
-	}else{
-		if(strcmp(name, "TIMESTAMP") != 0)
-			fprint(2, "%s: cannot handle selection request for '%s' (%d)\n", argv0, name, (int)xe->target);
-		r.xselection.property = None;
-	}
-
-	r.xselection.display = xe->display;
-	/* r.xselection.property filled above */
-	r.xselection.target = xe->target;
-	r.xselection.type = SelectionNotify;
-	r.xselection.requestor = xe->requestor;
-	r.xselection.time = xe->time;
-	r.xselection.send_event = True;
-	r.xselection.selection = xe->selection;
-	XSendEvent(xd, xe->requestor, False, 0, &r);
-	XFlush(xd);
-	return 0;
-}
-
-#ifdef APPLESNARF
-char*
-applegetsnarf(void)
-{
-	char *s, *t;
-	CFArrayRef flavors;
-	CFDataRef data;
-	CFIndex nflavor, ndata, j;
-	CFStringRef type;
-	ItemCount nitem;
-	PasteboardItemID id;
-	PasteboardSyncFlags flags;
-	UInt32 i;
-
-/*	fprint(2, "applegetsnarf\n"); */
-	qlock(&clip.lk);
-	if(clip.apple == nil){
-		if(PasteboardCreate(kPasteboardClipboard, &clip.apple) != noErr){
-			fprint(2, "apple pasteboard create failed\n");
-			qunlock(&clip.lk);
-			return nil;
-		}
-	}
-	flags = PasteboardSynchronize(clip.apple);
-	if(flags&kPasteboardClientIsOwner){
-		s = strdup(clip.buf);
-		qunlock(&clip.lk);
-		return s;
-	}
-	if(PasteboardGetItemCount(clip.apple, &nitem) != noErr){
-		fprint(2, "apple pasteboard get item count failed\n");
-		qunlock(&clip.lk);
-		return nil;
-	}
-	for(i=1; i<=nitem; i++){
-		if(PasteboardGetItemIdentifier(clip.apple, i, &id) != noErr)
-			continue;
-		if(PasteboardCopyItemFlavors(clip.apple, id, &flavors) != noErr)
-			continue;
-		nflavor = CFArrayGetCount(flavors);
-		for(j=0; j<nflavor; j++){
-			type = (CFStringRef)CFArrayGetValueAtIndex(flavors, j);
-			if(!UTTypeConformsTo(type, CFSTR("public.utf16-plain-text")))
-				continue;
-			if(PasteboardCopyItemFlavorData(clip.apple, id, type, &data) != noErr)
-				continue;
-			ndata = CFDataGetLength(data);
-			qunlock(&clip.lk);
-			s = smprint("%.*S", ndata/2, (Rune*)CFDataGetBytePtr(data));
-			CFRelease(flavors);
-			CFRelease(data);
-			for(t=s; *t; t++)
-				if(*t == '\r')
-					*t = '\n';
-			return s;
-		}
-		CFRelease(flavors);
-	}
-	qunlock(&clip.lk);
-	return nil;		
-}
-
-void
-appleputsnarf(char *s)
-{
-	CFDataRef cfdata;
-	PasteboardSyncFlags flags;
-
-/*	fprint(2, "appleputsnarf\n"); */
-
-	if(strlen(s) >= SnarfSize)
-		return;
-	qlock(&clip.lk);
-	strcpy(clip.buf, s);
-	runesnprint(clip.rbuf, nelem(clip.rbuf), "%s", s);
-	if(clip.apple == nil){
-		if(PasteboardCreate(kPasteboardClipboard, &clip.apple) != noErr){
-			fprint(2, "apple pasteboard create failed\n");
-			qunlock(&clip.lk);
-			return;
-		}
-	}
-	if(PasteboardClear(clip.apple) != noErr){
-		fprint(2, "apple pasteboard clear failed\n");
-		qunlock(&clip.lk);
-		return;
-	}
-	flags = PasteboardSynchronize(clip.apple);
-	if((flags&kPasteboardModified) || !(flags&kPasteboardClientIsOwner)){
-		fprint(2, "apple pasteboard cannot assert ownership\n");
-		qunlock(&clip.lk);
-		return;
-	}
-	cfdata = CFDataCreate(kCFAllocatorDefault, 
-		(uchar*)clip.rbuf, runestrlen(clip.rbuf)*2);
-	if(cfdata == nil){
-		fprint(2, "apple pasteboard cfdatacreate failed\n");
-		qunlock(&clip.lk);
-		return;
-	}
-	if(PasteboardPutItemFlavor(clip.apple, (PasteboardItemID)1,
-		CFSTR("public.utf16-plain-text"), cfdata, 0) != noErr){
-		fprint(2, "apple pasteboard putitem failed\n");
-		CFRelease(cfdata);
-		qunlock(&clip.lk);
-		return;
-	}
-	/* CFRelease(cfdata); ??? */
-	qunlock(&clip.lk);
-}
-#endif	/* APPLESNARF */
-
-void
-putsnarf(char *data)
-{
-#ifdef APPLESNARF
-	appleputsnarf(data);
-#endif
-	_xputsnarf(_x.snarfcon, data);
-}
-
-char*
-getsnarf(void)
-{
-	return _xgetsnarf(_x.snarfcon);
-}
-
blob - 77fa78ba106ca1d40345ce482d81302d5813d662 (mode 644)
blob + /dev/null
--- src/libdraw/x11-keyboard.c
+++ /dev/null
@@ -1,78 +0,0 @@
-#include <u.h>
-#include "x11-inc.h"
-#include <libc.h>
-#include <draw.h>
-#include <thread.h>
-#include <memdraw.h>
-#include <keyboard.h>
-#include "x11-memdraw.h"
-
-void
-closekeyboard(Keyboardctl *kc)
-{
-	if(kc == nil)
-		return;
-
-/*	postnote(PNPROC, kc->pid, "kill");
-*/
-
-#ifdef BUG
-	/* Drain the channel */
-	while(?kc->c)
-		<-kc->c;
-#endif
-
-	close(kc->ctlfd);
-	close(kc->consfd);
-	free(kc->file);
-	free(kc->c);
-	free(kc);
-}
-
-static
-void
-_ioproc(void *arg)
-{
-	int i;
-	int fd;
-	Keyboardctl *kc;
-	Rune r;
-	XEvent xevent;
-
-	kc = arg;
-	threadsetname("kbdproc");
-	kc->pid = getpid();
-	fd = XConnectionNumber(_x.kbdcon);
-	XSelectInput(_x.kbdcon, _x.drawable, KeyPressMask);
-	for(;;){
-		XWindowEvent(_x.kbdcon, _x.drawable, KeyPressMask, &xevent);
-		switch(xevent.type){
-		case KeyPress:
-			i = _xtoplan9kbd(&xevent);
-			if(i == -1)
-				continue;
-			r = i;
-			send(kc->c, &r);
-			while((i=_xtoplan9kbd(nil)) >= 0){
-				r = i;
-				send(kc->c, &r);
-			}
-			break;
-		}
-	}
-}
-
-Keyboardctl*
-initkeyboard(char *file)
-{
-	Keyboardctl *kc;
-
-	kc = mallocz(sizeof(Keyboardctl), 1);
-	if(kc == nil)
-		return nil;
-	kc->c = chancreate(sizeof(Rune), 20);
-	chansetname(kc->c, "kbdc");
-	proccreate(_ioproc, kc, 256*1024);
-	return kc;
-}
-
blob - 572f01d393ebdeeafa5584f2f191d0ee6f00d9ff (mode 644)
blob + /dev/null
--- src/libdraw/x11-keysym2ucs.c
+++ /dev/null
@@ -1,857 +0,0 @@
-/* $XFree86: xc/programs/xterm/keysym2ucs.c,v 1.5 2001/06/18 19:09:26 dickey Exp $
- * This module converts keysym values into the corresponding ISO 10646
- * (UCS, Unicode) values.
- *
- * The array keysymtab[] contains pairs of X11 keysym values for graphical
- * characters and the corresponding Unicode value. The function
- * keysym2ucs() maps a keysym onto a Unicode value using a binary search,
- * therefore keysymtab[] must remain SORTED by keysym value.
- *
- * The keysym -> UTF-8 conversion will hopefully one day be provided
- * by Xlib via XmbLookupString() and should ideally not have to be
- * done in X applications. But we are not there yet.
- *
- * We allow to represent any UCS character in the range U-00000000 to
- * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.
- * This admittedly does not cover the entire 31-bit space of UCS, but
- * it does cover all of the characters up to U-10FFFF, which can be
- * represented by UTF-16, and more, and it is very unlikely that higher
- * UCS codes will ever be assigned by ISO. So to get Unicode character
- * U+ABCD you can directly use keysym 0x0100abcd.
- *
- * NOTE: The comments in the table below contain the actual character
- * encoded in UTF-8, so for viewing and editing best use an editor in
- * UTF-8 mode.
- *
- * Author: Markus G. Kuhn <mkuhn@acm.org>, University of Cambridge, April 2001
- *
- * Special thanks to Richard Verhoeven <river@win.tue.nl> for preparing
- * an initial draft of the mapping table.
- *
- * This software is in the public domain. Share and enjoy!
- *
- * AUTOMATICALLY GENERATED FILE, DO NOT EDIT !!! (unicode/convmap.pl)
- */
-
-#ifndef KEYSYM2UCS_INCLUDED
-  
-#include "x11-keysym2ucs.h"
-#define VISIBLE /* */
-
-#else
-
-#define VISIBLE static
-
-#endif
-
-static struct codepair {
-  unsigned short keysym;
-  unsigned short ucs;
-} keysymtab[] = {
-  { 0x01a1, 0x0104 }, /*                     Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */
-  { 0x01a2, 0x02d8 }, /*                       breve ˘ BREVE */
-  { 0x01a3, 0x0141 }, /*                     Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */
-  { 0x01a5, 0x013d }, /*                      Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */
-  { 0x01a6, 0x015a }, /*                      Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */
-  { 0x01a9, 0x0160 }, /*                      Scaron Š LATIN CAPITAL LETTER S WITH CARON */
-  { 0x01aa, 0x015e }, /*                    Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */
-  { 0x01ab, 0x0164 }, /*                      Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */
-  { 0x01ac, 0x0179 }, /*                      Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */
-  { 0x01ae, 0x017d }, /*                      Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */
-  { 0x01af, 0x017b }, /*                   Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */
-  { 0x01b1, 0x0105 }, /*                     aogonek ą LATIN SMALL LETTER A WITH OGONEK */
-  { 0x01b2, 0x02db }, /*                      ogonek ˛ OGONEK */
-  { 0x01b3, 0x0142 }, /*                     lstroke ł LATIN SMALL LETTER L WITH STROKE */
-  { 0x01b5, 0x013e }, /*                      lcaron ľ LATIN SMALL LETTER L WITH CARON */
-  { 0x01b6, 0x015b }, /*                      sacute ś LATIN SMALL LETTER S WITH ACUTE */
-  { 0x01b7, 0x02c7 }, /*                       caron ˇ CARON */
-  { 0x01b9, 0x0161 }, /*                      scaron š LATIN SMALL LETTER S WITH CARON */
-  { 0x01ba, 0x015f }, /*                    scedilla ş LATIN SMALL LETTER S WITH CEDILLA */
-  { 0x01bb, 0x0165 }, /*                      tcaron ť LATIN SMALL LETTER T WITH CARON */
-  { 0x01bc, 0x017a }, /*                      zacute ź LATIN SMALL LETTER Z WITH ACUTE */
-  { 0x01bd, 0x02dd }, /*                 doubleacute ˝ DOUBLE ACUTE ACCENT */
-  { 0x01be, 0x017e }, /*                      zcaron ž LATIN SMALL LETTER Z WITH CARON */
-  { 0x01bf, 0x017c }, /*                   zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */
-  { 0x01c0, 0x0154 }, /*                      Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */
-  { 0x01c3, 0x0102 }, /*                      Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */
-  { 0x01c5, 0x0139 }, /*                      Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */
-  { 0x01c6, 0x0106 }, /*                      Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */
-  { 0x01c8, 0x010c }, /*                      Ccaron Č LATIN CAPITAL LETTER C WITH CARON */
-  { 0x01ca, 0x0118 }, /*                     Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */
-  { 0x01cc, 0x011a }, /*                      Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */
-  { 0x01cf, 0x010e }, /*                      Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */
-  { 0x01d0, 0x0110 }, /*                     Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */
-  { 0x01d1, 0x0143 }, /*                      Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */
-  { 0x01d2, 0x0147 }, /*                      Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */
-  { 0x01d5, 0x0150 }, /*                Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */
-  { 0x01d8, 0x0158 }, /*                      Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */
-  { 0x01d9, 0x016e }, /*                       Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */
-  { 0x01db, 0x0170 }, /*                Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */
-  { 0x01de, 0x0162 }, /*                    Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */
-  { 0x01e0, 0x0155 }, /*                      racute ŕ LATIN SMALL LETTER R WITH ACUTE */
-  { 0x01e3, 0x0103 }, /*                      abreve ă LATIN SMALL LETTER A WITH BREVE */
-  { 0x01e5, 0x013a }, /*                      lacute ĺ LATIN SMALL LETTER L WITH ACUTE */
-  { 0x01e6, 0x0107 }, /*                      cacute ć LATIN SMALL LETTER C WITH ACUTE */
-  { 0x01e8, 0x010d }, /*                      ccaron č LATIN SMALL LETTER C WITH CARON */
-  { 0x01ea, 0x0119 }, /*                     eogonek ę LATIN SMALL LETTER E WITH OGONEK */
-  { 0x01ec, 0x011b }, /*                      ecaron ě LATIN SMALL LETTER E WITH CARON */
-  { 0x01ef, 0x010f }, /*                      dcaron ď LATIN SMALL LETTER D WITH CARON */
-  { 0x01f0, 0x0111 }, /*                     dstroke đ LATIN SMALL LETTER D WITH STROKE */
-  { 0x01f1, 0x0144 }, /*                      nacute ń LATIN SMALL LETTER N WITH ACUTE */
-  { 0x01f2, 0x0148 }, /*                      ncaron ň LATIN SMALL LETTER N WITH CARON */
-  { 0x01f5, 0x0151 }, /*                odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */
-  { 0x01f8, 0x0159 }, /*                      rcaron ř LATIN SMALL LETTER R WITH CARON */
-  { 0x01f9, 0x016f }, /*                       uring ů LATIN SMALL LETTER U WITH RING ABOVE */
-  { 0x01fb, 0x0171 }, /*                udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */
-  { 0x01fe, 0x0163 }, /*                    tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */
-  { 0x01ff, 0x02d9 }, /*                    abovedot ˙ DOT ABOVE */
-  { 0x02a1, 0x0126 }, /*                     Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */
-  { 0x02a6, 0x0124 }, /*                 Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */
-  { 0x02a9, 0x0130 }, /*                   Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */
-  { 0x02ab, 0x011e }, /*                      Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */
-  { 0x02ac, 0x0134 }, /*                 Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */
-  { 0x02b1, 0x0127 }, /*                     hstroke ħ LATIN SMALL LETTER H WITH STROKE */
-  { 0x02b6, 0x0125 }, /*                 hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */
-  { 0x02b9, 0x0131 }, /*                    idotless ı LATIN SMALL LETTER DOTLESS I */
-  { 0x02bb, 0x011f }, /*                      gbreve ğ LATIN SMALL LETTER G WITH BREVE */
-  { 0x02bc, 0x0135 }, /*                 jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */
-  { 0x02c5, 0x010a }, /*                   Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */
-  { 0x02c6, 0x0108 }, /*                 Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */
-  { 0x02d5, 0x0120 }, /*                   Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */
-  { 0x02d8, 0x011c }, /*                 Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */
-  { 0x02dd, 0x016c }, /*                      Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */
-  { 0x02de, 0x015c }, /*                 Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */
-  { 0x02e5, 0x010b }, /*                   cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */
-  { 0x02e6, 0x0109 }, /*                 ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */
-  { 0x02f5, 0x0121 }, /*                   gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */
-  { 0x02f8, 0x011d }, /*                 gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */
-  { 0x02fd, 0x016d }, /*                      ubreve ŭ LATIN SMALL LETTER U WITH BREVE */
-  { 0x02fe, 0x015d }, /*                 scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */
-  { 0x03a2, 0x0138 }, /*                         kra ĸ LATIN SMALL LETTER KRA */
-  { 0x03a3, 0x0156 }, /*                    Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */
-  { 0x03a5, 0x0128 }, /*                      Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */
-  { 0x03a6, 0x013b }, /*                    Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */
-  { 0x03aa, 0x0112 }, /*                     Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */
-  { 0x03ab, 0x0122 }, /*                    Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */
-  { 0x03ac, 0x0166 }, /*                      Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */
-  { 0x03b3, 0x0157 }, /*                    rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */
-  { 0x03b5, 0x0129 }, /*                      itilde ĩ LATIN SMALL LETTER I WITH TILDE */
-  { 0x03b6, 0x013c }, /*                    lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */
-  { 0x03ba, 0x0113 }, /*                     emacron ē LATIN SMALL LETTER E WITH MACRON */
-  { 0x03bb, 0x0123 }, /*                    gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */
-  { 0x03bc, 0x0167 }, /*                      tslash ŧ LATIN SMALL LETTER T WITH STROKE */
-  { 0x03bd, 0x014a }, /*                         ENG Ŋ LATIN CAPITAL LETTER ENG */
-  { 0x03bf, 0x014b }, /*                         eng ŋ LATIN SMALL LETTER ENG */
-  { 0x03c0, 0x0100 }, /*                     Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */
-  { 0x03c7, 0x012e }, /*                     Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */
-  { 0x03cc, 0x0116 }, /*                   Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */
-  { 0x03cf, 0x012a }, /*                     Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */
-  { 0x03d1, 0x0145 }, /*                    Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */
-  { 0x03d2, 0x014c }, /*                     Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */
-  { 0x03d3, 0x0136 }, /*                    Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */
-  { 0x03d9, 0x0172 }, /*                     Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */
-  { 0x03dd, 0x0168 }, /*                      Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */
-  { 0x03de, 0x016a }, /*                     Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */
-  { 0x03e0, 0x0101 }, /*                     amacron ā LATIN SMALL LETTER A WITH MACRON */
-  { 0x03e7, 0x012f }, /*                     iogonek į LATIN SMALL LETTER I WITH OGONEK */
-  { 0x03ec, 0x0117 }, /*                   eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */
-  { 0x03ef, 0x012b }, /*                     imacron ī LATIN SMALL LETTER I WITH MACRON */
-  { 0x03f1, 0x0146 }, /*                    ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */
-  { 0x03f2, 0x014d }, /*                     omacron ō LATIN SMALL LETTER O WITH MACRON */
-  { 0x03f3, 0x0137 }, /*                    kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */
-  { 0x03f9, 0x0173 }, /*                     uogonek ų LATIN SMALL LETTER U WITH OGONEK */
-  { 0x03fd, 0x0169 }, /*                      utilde ũ LATIN SMALL LETTER U WITH TILDE */
-  { 0x03fe, 0x016b }, /*                     umacron ū LATIN SMALL LETTER U WITH MACRON */
-  { 0x047e, 0x203e }, /*                    overline ‾ OVERLINE */
-  { 0x04a1, 0x3002 }, /*               kana_fullstop 。 IDEOGRAPHIC FULL STOP */
-  { 0x04a2, 0x300c }, /*         kana_openingbracket 「 LEFT CORNER BRACKET */
-  { 0x04a3, 0x300d }, /*         kana_closingbracket 」 RIGHT CORNER BRACKET */
-  { 0x04a4, 0x3001 }, /*                  kana_comma 、 IDEOGRAPHIC COMMA */
-  { 0x04a5, 0x30fb }, /*            kana_conjunctive ・ KATAKANA MIDDLE DOT */
-  { 0x04a6, 0x30f2 }, /*                     kana_WO ヲ KATAKANA LETTER WO */
-  { 0x04a7, 0x30a1 }, /*                      kana_a ァ KATAKANA LETTER SMALL A */
-  { 0x04a8, 0x30a3 }, /*                      kana_i ィ KATAKANA LETTER SMALL I */
-  { 0x04a9, 0x30a5 }, /*                      kana_u ゥ KATAKANA LETTER SMALL U */
-  { 0x04aa, 0x30a7 }, /*                      kana_e ェ KATAKANA LETTER SMALL E */
-  { 0x04ab, 0x30a9 }, /*                      kana_o ォ KATAKANA LETTER SMALL O */
-  { 0x04ac, 0x30e3 }, /*                     kana_ya ャ KATAKANA LETTER SMALL YA */
-  { 0x04ad, 0x30e5 }, /*                     kana_yu ュ KATAKANA LETTER SMALL YU */
-  { 0x04ae, 0x30e7 }, /*                     kana_yo ョ KATAKANA LETTER SMALL YO */
-  { 0x04af, 0x30c3 }, /*                    kana_tsu ッ KATAKANA LETTER SMALL TU */
-  { 0x04b0, 0x30fc }, /*              prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */
-  { 0x04b1, 0x30a2 }, /*                      kana_A ア KATAKANA LETTER A */
-  { 0x04b2, 0x30a4 }, /*                      kana_I イ KATAKANA LETTER I */
-  { 0x04b3, 0x30a6 }, /*                      kana_U ウ KATAKANA LETTER U */
-  { 0x04b4, 0x30a8 }, /*                      kana_E エ KATAKANA LETTER E */
-  { 0x04b5, 0x30aa }, /*                      kana_O オ KATAKANA LETTER O */
-  { 0x04b6, 0x30ab }, /*                     kana_KA カ KATAKANA LETTER KA */
-  { 0x04b7, 0x30ad }, /*                     kana_KI キ KATAKANA LETTER KI */
-  { 0x04b8, 0x30af }, /*                     kana_KU ク KATAKANA LETTER KU */
-  { 0x04b9, 0x30b1 }, /*                     kana_KE ケ KATAKANA LETTER KE */
-  { 0x04ba, 0x30b3 }, /*                     kana_KO コ KATAKANA LETTER KO */
-  { 0x04bb, 0x30b5 }, /*                     kana_SA サ KATAKANA LETTER SA */
-  { 0x04bc, 0x30b7 }, /*                    kana_SHI シ KATAKANA LETTER SI */
-  { 0x04bd, 0x30b9 }, /*                     kana_SU ス KATAKANA LETTER SU */
-  { 0x04be, 0x30bb }, /*                     kana_SE セ KATAKANA LETTER SE */
-  { 0x04bf, 0x30bd }, /*                     kana_SO ソ KATAKANA LETTER SO */
-  { 0x04c0, 0x30bf }, /*                     kana_TA タ KATAKANA LETTER TA */
-  { 0x04c1, 0x30c1 }, /*                    kana_CHI チ KATAKANA LETTER TI */
-  { 0x04c2, 0x30c4 }, /*                    kana_TSU ツ KATAKANA LETTER TU */
-  { 0x04c3, 0x30c6 }, /*                     kana_TE テ KATAKANA LETTER TE */
-  { 0x04c4, 0x30c8 }, /*                     kana_TO ト KATAKANA LETTER TO */
-  { 0x04c5, 0x30ca }, /*                     kana_NA ナ KATAKANA LETTER NA */
-  { 0x04c6, 0x30cb }, /*                     kana_NI ニ KATAKANA LETTER NI */
-  { 0x04c7, 0x30cc }, /*                     kana_NU ヌ KATAKANA LETTER NU */
-  { 0x04c8, 0x30cd }, /*                     kana_NE ネ KATAKANA LETTER NE */
-  { 0x04c9, 0x30ce }, /*                     kana_NO ノ KATAKANA LETTER NO */
-  { 0x04ca, 0x30cf }, /*                     kana_HA ハ KATAKANA LETTER HA */
-  { 0x04cb, 0x30d2 }, /*                     kana_HI ヒ KATAKANA LETTER HI */
-  { 0x04cc, 0x30d5 }, /*                     kana_FU フ KATAKANA LETTER HU */
-  { 0x04cd, 0x30d8 }, /*                     kana_HE ヘ KATAKANA LETTER HE */
-  { 0x04ce, 0x30db }, /*                     kana_HO ホ KATAKANA LETTER HO */
-  { 0x04cf, 0x30de }, /*                     kana_MA マ KATAKANA LETTER MA */
-  { 0x04d0, 0x30df }, /*                     kana_MI ミ KATAKANA LETTER MI */
-  { 0x04d1, 0x30e0 }, /*                     kana_MU ム KATAKANA LETTER MU */
-  { 0x04d2, 0x30e1 }, /*                     kana_ME メ KATAKANA LETTER ME */
-  { 0x04d3, 0x30e2 }, /*                     kana_MO モ KATAKANA LETTER MO */
-  { 0x04d4, 0x30e4 }, /*                     kana_YA ヤ KATAKANA LETTER YA */
-  { 0x04d5, 0x30e6 }, /*                     kana_YU ユ KATAKANA LETTER YU */
-  { 0x04d6, 0x30e8 }, /*                     kana_YO ヨ KATAKANA LETTER YO */
-  { 0x04d7, 0x30e9 }, /*                     kana_RA ラ KATAKANA LETTER RA */
-  { 0x04d8, 0x30ea }, /*                     kana_RI リ KATAKANA LETTER RI */
-  { 0x04d9, 0x30eb }, /*                     kana_RU ル KATAKANA LETTER RU */
-  { 0x04da, 0x30ec }, /*                     kana_RE レ KATAKANA LETTER RE */
-  { 0x04db, 0x30ed }, /*                     kana_RO ロ KATAKANA LETTER RO */
-  { 0x04dc, 0x30ef }, /*                     kana_WA ワ KATAKANA LETTER WA */
-  { 0x04dd, 0x30f3 }, /*                      kana_N ン KATAKANA LETTER N */
-  { 0x04de, 0x309b }, /*                 voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */
-  { 0x04df, 0x309c }, /*             semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */
-  { 0x05ac, 0x060c }, /*                Arabic_comma ، ARABIC COMMA */
-  { 0x05bb, 0x061b }, /*            Arabic_semicolon ؛ ARABIC SEMICOLON */
-  { 0x05bf, 0x061f }, /*        Arabic_question_mark ؟ ARABIC QUESTION MARK */
-  { 0x05c1, 0x0621 }, /*                Arabic_hamza ء ARABIC LETTER HAMZA */
-  { 0x05c2, 0x0622 }, /*          Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */
-  { 0x05c3, 0x0623 }, /*          Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */
-  { 0x05c4, 0x0624 }, /*           Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */
-  { 0x05c5, 0x0625 }, /*       Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */
-  { 0x05c6, 0x0626 }, /*           Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */
-  { 0x05c7, 0x0627 }, /*                 Arabic_alef ا ARABIC LETTER ALEF */
-  { 0x05c8, 0x0628 }, /*                  Arabic_beh ب ARABIC LETTER BEH */
-  { 0x05c9, 0x0629 }, /*           Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */
-  { 0x05ca, 0x062a }, /*                  Arabic_teh ت ARABIC LETTER TEH */
-  { 0x05cb, 0x062b }, /*                 Arabic_theh ث ARABIC LETTER THEH */
-  { 0x05cc, 0x062c }, /*                 Arabic_jeem ج ARABIC LETTER JEEM */
-  { 0x05cd, 0x062d }, /*                  Arabic_hah ح ARABIC LETTER HAH */
-  { 0x05ce, 0x062e }, /*                 Arabic_khah خ ARABIC LETTER KHAH */
-  { 0x05cf, 0x062f }, /*                  Arabic_dal د ARABIC LETTER DAL */
-  { 0x05d0, 0x0630 }, /*                 Arabic_thal ذ ARABIC LETTER THAL */
-  { 0x05d1, 0x0631 }, /*                   Arabic_ra ر ARABIC LETTER REH */
-  { 0x05d2, 0x0632 }, /*                 Arabic_zain ز ARABIC LETTER ZAIN */
-  { 0x05d3, 0x0633 }, /*                 Arabic_seen س ARABIC LETTER SEEN */
-  { 0x05d4, 0x0634 }, /*                Arabic_sheen ش ARABIC LETTER SHEEN */
-  { 0x05d5, 0x0635 }, /*                  Arabic_sad ص ARABIC LETTER SAD */
-  { 0x05d6, 0x0636 }, /*                  Arabic_dad ض ARABIC LETTER DAD */
-  { 0x05d7, 0x0637 }, /*                  Arabic_tah ط ARABIC LETTER TAH */
-  { 0x05d8, 0x0638 }, /*                  Arabic_zah ظ ARABIC LETTER ZAH */
-  { 0x05d9, 0x0639 }, /*                  Arabic_ain ع ARABIC LETTER AIN */
-  { 0x05da, 0x063a }, /*                Arabic_ghain غ ARABIC LETTER GHAIN */
-  { 0x05e0, 0x0640 }, /*              Arabic_tatweel ـ ARABIC TATWEEL */
-  { 0x05e1, 0x0641 }, /*                  Arabic_feh ف ARABIC LETTER FEH */
-  { 0x05e2, 0x0642 }, /*                  Arabic_qaf ق ARABIC LETTER QAF */
-  { 0x05e3, 0x0643 }, /*                  Arabic_kaf ك ARABIC LETTER KAF */
-  { 0x05e4, 0x0644 }, /*                  Arabic_lam ل ARABIC LETTER LAM */
-  { 0x05e5, 0x0645 }, /*                 Arabic_meem م ARABIC LETTER MEEM */
-  { 0x05e6, 0x0646 }, /*                 Arabic_noon ن ARABIC LETTER NOON */
-  { 0x05e7, 0x0647 }, /*                   Arabic_ha ه ARABIC LETTER HEH */
-  { 0x05e8, 0x0648 }, /*                  Arabic_waw و ARABIC LETTER WAW */
-  { 0x05e9, 0x0649 }, /*          Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */
-  { 0x05ea, 0x064a }, /*                  Arabic_yeh ي ARABIC LETTER YEH */
-  { 0x05eb, 0x064b }, /*             Arabic_fathatan ً ARABIC FATHATAN */
-  { 0x05ec, 0x064c }, /*             Arabic_dammatan ٌ ARABIC DAMMATAN */
-  { 0x05ed, 0x064d }, /*             Arabic_kasratan ٍ ARABIC KASRATAN */
-  { 0x05ee, 0x064e }, /*                Arabic_fatha َ ARABIC FATHA */
-  { 0x05ef, 0x064f }, /*                Arabic_damma ُ ARABIC DAMMA */
-  { 0x05f0, 0x0650 }, /*                Arabic_kasra ِ ARABIC KASRA */
-  { 0x05f1, 0x0651 }, /*               Arabic_shadda ّ ARABIC SHADDA */
-  { 0x05f2, 0x0652 }, /*                Arabic_sukun ْ ARABIC SUKUN */
-  { 0x06a1, 0x0452 }, /*                 Serbian_dje ђ CYRILLIC SMALL LETTER DJE */
-  { 0x06a2, 0x0453 }, /*               Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */
-  { 0x06a3, 0x0451 }, /*                 Cyrillic_io ё CYRILLIC SMALL LETTER IO */
-  { 0x06a4, 0x0454 }, /*                Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */
-  { 0x06a5, 0x0455 }, /*               Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */
-  { 0x06a6, 0x0456 }, /*                 Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */
-  { 0x06a7, 0x0457 }, /*                Ukrainian_yi ї CYRILLIC SMALL LETTER YI */
-  { 0x06a8, 0x0458 }, /*                 Cyrillic_je ј CYRILLIC SMALL LETTER JE */
-  { 0x06a9, 0x0459 }, /*                Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */
-  { 0x06aa, 0x045a }, /*                Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */
-  { 0x06ab, 0x045b }, /*                Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */
-  { 0x06ac, 0x045c }, /*               Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */
-  { 0x06ae, 0x045e }, /*         Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */
-  { 0x06af, 0x045f }, /*               Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */
-  { 0x06b0, 0x2116 }, /*                  numerosign № NUMERO SIGN */
-  { 0x06b1, 0x0402 }, /*                 Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */
-  { 0x06b2, 0x0403 }, /*               Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */
-  { 0x06b3, 0x0401 }, /*                 Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */
-  { 0x06b4, 0x0404 }, /*                Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */
-  { 0x06b5, 0x0405 }, /*               Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */
-  { 0x06b6, 0x0406 }, /*                 Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */
-  { 0x06b7, 0x0407 }, /*                Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */
-  { 0x06b8, 0x0408 }, /*                 Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */
-  { 0x06b9, 0x0409 }, /*                Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */
-  { 0x06ba, 0x040a }, /*                Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */
-  { 0x06bb, 0x040b }, /*                Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */
-  { 0x06bc, 0x040c }, /*               Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */
-  { 0x06be, 0x040e }, /*         Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */
-  { 0x06bf, 0x040f }, /*               Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */
-  { 0x06c0, 0x044e }, /*                 Cyrillic_yu ю CYRILLIC SMALL LETTER YU */
-  { 0x06c1, 0x0430 }, /*                  Cyrillic_a а CYRILLIC SMALL LETTER A */
-  { 0x06c2, 0x0431 }, /*                 Cyrillic_be б CYRILLIC SMALL LETTER BE */
-  { 0x06c3, 0x0446 }, /*                Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */
-  { 0x06c4, 0x0434 }, /*                 Cyrillic_de д CYRILLIC SMALL LETTER DE */
-  { 0x06c5, 0x0435 }, /*                 Cyrillic_ie е CYRILLIC SMALL LETTER IE */
-  { 0x06c6, 0x0444 }, /*                 Cyrillic_ef ф CYRILLIC SMALL LETTER EF */
-  { 0x06c7, 0x0433 }, /*                Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */
-  { 0x06c8, 0x0445 }, /*                 Cyrillic_ha х CYRILLIC SMALL LETTER HA */
-  { 0x06c9, 0x0438 }, /*                  Cyrillic_i и CYRILLIC SMALL LETTER I */
-  { 0x06ca, 0x0439 }, /*             Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */
-  { 0x06cb, 0x043a }, /*                 Cyrillic_ka к CYRILLIC SMALL LETTER KA */
-  { 0x06cc, 0x043b }, /*                 Cyrillic_el л CYRILLIC SMALL LETTER EL */
-  { 0x06cd, 0x043c }, /*                 Cyrillic_em м CYRILLIC SMALL LETTER EM */
-  { 0x06ce, 0x043d }, /*                 Cyrillic_en н CYRILLIC SMALL LETTER EN */
-  { 0x06cf, 0x043e }, /*                  Cyrillic_o о CYRILLIC SMALL LETTER O */
-  { 0x06d0, 0x043f }, /*                 Cyrillic_pe п CYRILLIC SMALL LETTER PE */
-  { 0x06d1, 0x044f }, /*                 Cyrillic_ya я CYRILLIC SMALL LETTER YA */
-  { 0x06d2, 0x0440 }, /*                 Cyrillic_er р CYRILLIC SMALL LETTER ER */
-  { 0x06d3, 0x0441 }, /*                 Cyrillic_es с CYRILLIC SMALL LETTER ES */
-  { 0x06d4, 0x0442 }, /*                 Cyrillic_te т CYRILLIC SMALL LETTER TE */
-  { 0x06d5, 0x0443 }, /*                  Cyrillic_u у CYRILLIC SMALL LETTER U */
-  { 0x06d6, 0x0436 }, /*                Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */
-  { 0x06d7, 0x0432 }, /*                 Cyrillic_ve в CYRILLIC SMALL LETTER VE */
-  { 0x06d8, 0x044c }, /*           Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */
-  { 0x06d9, 0x044b }, /*               Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */
-  { 0x06da, 0x0437 }, /*                 Cyrillic_ze з CYRILLIC SMALL LETTER ZE */
-  { 0x06db, 0x0448 }, /*                Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */
-  { 0x06dc, 0x044d }, /*                  Cyrillic_e э CYRILLIC SMALL LETTER E */
-  { 0x06dd, 0x0449 }, /*              Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */
-  { 0x06de, 0x0447 }, /*                Cyrillic_che ч CYRILLIC SMALL LETTER CHE */
-  { 0x06df, 0x044a }, /*           Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */
-  { 0x06e0, 0x042e }, /*                 Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */
-  { 0x06e1, 0x0410 }, /*                  Cyrillic_A А CYRILLIC CAPITAL LETTER A */
-  { 0x06e2, 0x0411 }, /*                 Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */
-  { 0x06e3, 0x0426 }, /*                Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */
-  { 0x06e4, 0x0414 }, /*                 Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */
-  { 0x06e5, 0x0415 }, /*                 Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */
-  { 0x06e6, 0x0424 }, /*                 Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */
-  { 0x06e7, 0x0413 }, /*                Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */
-  { 0x06e8, 0x0425 }, /*                 Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */
-  { 0x06e9, 0x0418 }, /*                  Cyrillic_I И CYRILLIC CAPITAL LETTER I */
-  { 0x06ea, 0x0419 }, /*             Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */
-  { 0x06eb, 0x041a }, /*                 Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */
-  { 0x06ec, 0x041b }, /*                 Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */
-  { 0x06ed, 0x041c }, /*                 Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */
-  { 0x06ee, 0x041d }, /*                 Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */
-  { 0x06ef, 0x041e }, /*                  Cyrillic_O О CYRILLIC CAPITAL LETTER O */
-  { 0x06f0, 0x041f }, /*                 Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */
-  { 0x06f1, 0x042f }, /*                 Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */
-  { 0x06f2, 0x0420 }, /*                 Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */
-  { 0x06f3, 0x0421 }, /*                 Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */
-  { 0x06f4, 0x0422 }, /*                 Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */
-  { 0x06f5, 0x0423 }, /*                  Cyrillic_U У CYRILLIC CAPITAL LETTER U */
-  { 0x06f6, 0x0416 }, /*                Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */
-  { 0x06f7, 0x0412 }, /*                 Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */
-  { 0x06f8, 0x042c }, /*           Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */
-  { 0x06f9, 0x042b }, /*               Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */
-  { 0x06fa, 0x0417 }, /*                 Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */
-  { 0x06fb, 0x0428 }, /*                Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */
-  { 0x06fc, 0x042d }, /*                  Cyrillic_E Э CYRILLIC CAPITAL LETTER E */
-  { 0x06fd, 0x0429 }, /*              Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */
-  { 0x06fe, 0x0427 }, /*                Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */
-  { 0x06ff, 0x042a }, /*           Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */
-  { 0x07a1, 0x0386 }, /*           Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */
-  { 0x07a2, 0x0388 }, /*         Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */
-  { 0x07a3, 0x0389 }, /*             Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */
-  { 0x07a4, 0x038a }, /*            Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */
-  { 0x07a5, 0x03aa }, /*         Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
-  { 0x07a7, 0x038c }, /*         Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */
-  { 0x07a8, 0x038e }, /*         Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */
-  { 0x07a9, 0x03ab }, /*       Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */
-  { 0x07ab, 0x038f }, /*           Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */
-  { 0x07ae, 0x0385 }, /*        Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */
-  { 0x07af, 0x2015 }, /*              Greek_horizbar ― HORIZONTAL BAR */
-  { 0x07b1, 0x03ac }, /*           Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */
-  { 0x07b2, 0x03ad }, /*         Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */
-  { 0x07b3, 0x03ae }, /*             Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */
-  { 0x07b4, 0x03af }, /*            Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */
-  { 0x07b5, 0x03ca }, /*          Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */
-  { 0x07b6, 0x0390 }, /*    Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */
-  { 0x07b7, 0x03cc }, /*         Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */
-  { 0x07b8, 0x03cd }, /*         Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */
-  { 0x07b9, 0x03cb }, /*       Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */
-  { 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */
-  { 0x07bb, 0x03ce }, /*           Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */
-  { 0x07c1, 0x0391 }, /*                 Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */
-  { 0x07c2, 0x0392 }, /*                  Greek_BETA Β GREEK CAPITAL LETTER BETA */
-  { 0x07c3, 0x0393 }, /*                 Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */
-  { 0x07c4, 0x0394 }, /*                 Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */
-  { 0x07c5, 0x0395 }, /*               Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */
-  { 0x07c6, 0x0396 }, /*                  Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */
-  { 0x07c7, 0x0397 }, /*                   Greek_ETA Η GREEK CAPITAL LETTER ETA */
-  { 0x07c8, 0x0398 }, /*                 Greek_THETA Θ GREEK CAPITAL LETTER THETA */
-  { 0x07c9, 0x0399 }, /*                  Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */
-  { 0x07ca, 0x039a }, /*                 Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */
-  { 0x07cb, 0x039b }, /*                Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */
-  { 0x07cc, 0x039c }, /*                    Greek_MU Μ GREEK CAPITAL LETTER MU */
-  { 0x07cd, 0x039d }, /*                    Greek_NU Ν GREEK CAPITAL LETTER NU */
-  { 0x07ce, 0x039e }, /*                    Greek_XI Ξ GREEK CAPITAL LETTER XI */
-  { 0x07cf, 0x039f }, /*               Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */
-  { 0x07d0, 0x03a0 }, /*                    Greek_PI Π GREEK CAPITAL LETTER PI */
-  { 0x07d1, 0x03a1 }, /*                   Greek_RHO Ρ GREEK CAPITAL LETTER RHO */
-  { 0x07d2, 0x03a3 }, /*                 Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */
-  { 0x07d4, 0x03a4 }, /*                   Greek_TAU Τ GREEK CAPITAL LETTER TAU */
-  { 0x07d5, 0x03a5 }, /*               Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */
-  { 0x07d6, 0x03a6 }, /*                   Greek_PHI Φ GREEK CAPITAL LETTER PHI */
-  { 0x07d7, 0x03a7 }, /*                   Greek_CHI Χ GREEK CAPITAL LETTER CHI */
-  { 0x07d8, 0x03a8 }, /*                   Greek_PSI Ψ GREEK CAPITAL LETTER PSI */
-  { 0x07d9, 0x03a9 }, /*                 Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */
-  { 0x07e1, 0x03b1 }, /*                 Greek_alpha α GREEK SMALL LETTER ALPHA */
-  { 0x07e2, 0x03b2 }, /*                  Greek_beta β GREEK SMALL LETTER BETA */
-  { 0x07e3, 0x03b3 }, /*                 Greek_gamma γ GREEK SMALL LETTER GAMMA */
-  { 0x07e4, 0x03b4 }, /*                 Greek_delta δ GREEK SMALL LETTER DELTA */
-  { 0x07e5, 0x03b5 }, /*               Greek_epsilon ε GREEK SMALL LETTER EPSILON */
-  { 0x07e6, 0x03b6 }, /*                  Greek_zeta ζ GREEK SMALL LETTER ZETA */
-  { 0x07e7, 0x03b7 }, /*                   Greek_eta η GREEK SMALL LETTER ETA */
-  { 0x07e8, 0x03b8 }, /*                 Greek_theta θ GREEK SMALL LETTER THETA */
-  { 0x07e9, 0x03b9 }, /*                  Greek_iota ι GREEK SMALL LETTER IOTA */
-  { 0x07ea, 0x03ba }, /*                 Greek_kappa κ GREEK SMALL LETTER KAPPA */
-  { 0x07eb, 0x03bb }, /*                Greek_lambda λ GREEK SMALL LETTER LAMDA */
-  { 0x07ec, 0x03bc }, /*                    Greek_mu μ GREEK SMALL LETTER MU */
-  { 0x07ed, 0x03bd }, /*                    Greek_nu ν GREEK SMALL LETTER NU */
-  { 0x07ee, 0x03be }, /*                    Greek_xi ξ GREEK SMALL LETTER XI */
-  { 0x07ef, 0x03bf }, /*               Greek_omicron ο GREEK SMALL LETTER OMICRON */
-  { 0x07f0, 0x03c0 }, /*                    Greek_pi π GREEK SMALL LETTER PI */
-  { 0x07f1, 0x03c1 }, /*                   Greek_rho ρ GREEK SMALL LETTER RHO */
-  { 0x07f2, 0x03c3 }, /*                 Greek_sigma σ GREEK SMALL LETTER SIGMA */
-  { 0x07f3, 0x03c2 }, /*       Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */
-  { 0x07f4, 0x03c4 }, /*                   Greek_tau τ GREEK SMALL LETTER TAU */
-  { 0x07f5, 0x03c5 }, /*               Greek_upsilon υ GREEK SMALL LETTER UPSILON */
-  { 0x07f6, 0x03c6 }, /*                   Greek_phi φ GREEK SMALL LETTER PHI */
-  { 0x07f7, 0x03c7 }, /*                   Greek_chi χ GREEK SMALL LETTER CHI */
-  { 0x07f8, 0x03c8 }, /*                   Greek_psi ψ GREEK SMALL LETTER PSI */
-  { 0x07f9, 0x03c9 }, /*                 Greek_omega ω GREEK SMALL LETTER OMEGA */
-  { 0x08a1, 0x23b7 }, /*                 leftradical ⎷ ??? */
-  { 0x08a2, 0x250c }, /*              topleftradical ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */
-  { 0x08a3, 0x2500 }, /*              horizconnector ─ BOX DRAWINGS LIGHT HORIZONTAL */
-  { 0x08a4, 0x2320 }, /*                 topintegral ⌠ TOP HALF INTEGRAL */
-  { 0x08a5, 0x2321 }, /*                 botintegral ⌡ BOTTOM HALF INTEGRAL */
-  { 0x08a6, 0x2502 }, /*               vertconnector │ BOX DRAWINGS LIGHT VERTICAL */
-  { 0x08a7, 0x23a1 }, /*            topleftsqbracket ⎡ ??? */
-  { 0x08a8, 0x23a3 }, /*            botleftsqbracket ⎣ ??? */
-  { 0x08a9, 0x23a4 }, /*           toprightsqbracket ⎤ ??? */
-  { 0x08aa, 0x23a6 }, /*           botrightsqbracket ⎦ ??? */
-  { 0x08ab, 0x239b }, /*               topleftparens ⎛ ??? */
-  { 0x08ac, 0x239d }, /*               botleftparens ⎝ ??? */
-  { 0x08ad, 0x239e }, /*              toprightparens ⎞ ??? */
-  { 0x08ae, 0x23a0 }, /*              botrightparens ⎠ ??? */
-  { 0x08af, 0x23a8 }, /*        leftmiddlecurlybrace ⎨ ??? */
-  { 0x08b0, 0x23ac }, /*       rightmiddlecurlybrace ⎬ ??? */
-/*  0x08b1                          topleftsummation ? ??? */
-/*  0x08b2                          botleftsummation ? ??? */
-/*  0x08b3                 topvertsummationconnector ? ??? */
-/*  0x08b4                 botvertsummationconnector ? ??? */
-/*  0x08b5                         toprightsummation ? ??? */
-/*  0x08b6                         botrightsummation ? ??? */
-/*  0x08b7                      rightmiddlesummation ? ??? */
-  { 0x08bc, 0x2264 }, /*               lessthanequal ≤ LESS-THAN OR EQUAL TO */
-  { 0x08bd, 0x2260 }, /*                    notequal ≠ NOT EQUAL TO */
-  { 0x08be, 0x2265 }, /*            greaterthanequal ≥ GREATER-THAN OR EQUAL TO */
-  { 0x08bf, 0x222b }, /*                    integral ∫ INTEGRAL */
-  { 0x08c0, 0x2234 }, /*                   therefore ∴ THEREFORE */
-  { 0x08c1, 0x221d }, /*                   variation ∝ PROPORTIONAL TO */
-  { 0x08c2, 0x221e }, /*                    infinity ∞ INFINITY */
-  { 0x08c5, 0x2207 }, /*                       nabla ∇ NABLA */
-  { 0x08c8, 0x223c }, /*                 approximate ∼ TILDE OPERATOR */
-  { 0x08c9, 0x2243 }, /*                similarequal ≃ ASYMPTOTICALLY EQUAL TO */
-  { 0x08cd, 0x21d4 }, /*                    ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */
-  { 0x08ce, 0x21d2 }, /*                     implies ⇒ RIGHTWARDS DOUBLE ARROW */
-  { 0x08cf, 0x2261 }, /*                   identical ≡ IDENTICAL TO */
-  { 0x08d6, 0x221a }, /*                     radical √ SQUARE ROOT */
-  { 0x08da, 0x2282 }, /*                  includedin ⊂ SUBSET OF */
-  { 0x08db, 0x2283 }, /*                    includes ⊃ SUPERSET OF */
-  { 0x08dc, 0x2229 }, /*                intersection ∩ INTERSECTION */
-  { 0x08dd, 0x222a }, /*                       union ∪ UNION */
-  { 0x08de, 0x2227 }, /*                  logicaland ∧ LOGICAL AND */
-  { 0x08df, 0x2228 }, /*                   logicalor ∨ LOGICAL OR */
-  { 0x08ef, 0x2202 }, /*           partialderivative ∂ PARTIAL DIFFERENTIAL */
-  { 0x08f6, 0x0192 }, /*                    function ƒ LATIN SMALL LETTER F WITH HOOK */
-  { 0x08fb, 0x2190 }, /*                   leftarrow ← LEFTWARDS ARROW */
-  { 0x08fc, 0x2191 }, /*                     uparrow ↑ UPWARDS ARROW */
-  { 0x08fd, 0x2192 }, /*                  rightarrow → RIGHTWARDS ARROW */
-  { 0x08fe, 0x2193 }, /*                   downarrow ↓ DOWNWARDS ARROW */
-/*  0x09df                                     blank ? ??? */
-  { 0x09e0, 0x25c6 }, /*                soliddiamond ◆ BLACK DIAMOND */
-  { 0x09e1, 0x2592 }, /*                checkerboard ▒ MEDIUM SHADE */
-  { 0x09e2, 0x2409 }, /*                          ht ␉ SYMBOL FOR HORIZONTAL TABULATION */
-  { 0x09e3, 0x240c }, /*                          ff ␌ SYMBOL FOR FORM FEED */
-  { 0x09e4, 0x240d }, /*                          cr ␍ SYMBOL FOR CARRIAGE RETURN */
-  { 0x09e5, 0x240a }, /*                          lf ␊ SYMBOL FOR LINE FEED */
-  { 0x09e8, 0x2424 }, /*                          nl ␤ SYMBOL FOR NEWLINE */
-  { 0x09e9, 0x240b }, /*                          vt ␋ SYMBOL FOR VERTICAL TABULATION */
-  { 0x09ea, 0x2518 }, /*              lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */
-  { 0x09eb, 0x2510 }, /*               uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */
-  { 0x09ec, 0x250c }, /*                upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */
-  { 0x09ed, 0x2514 }, /*               lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */
-  { 0x09ee, 0x253c }, /*               crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
-  { 0x09ef, 0x23ba }, /*              horizlinescan1 ⎺ HORIZONTAL SCAN LINE-1 (Unicode 3.2 draft) */
-  { 0x09f0, 0x23bb }, /*              horizlinescan3 ⎻ HORIZONTAL SCAN LINE-3 (Unicode 3.2 draft) */
-  { 0x09f1, 0x2500 }, /*              horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */
-  { 0x09f2, 0x23bc }, /*              horizlinescan7 ⎼ HORIZONTAL SCAN LINE-7 (Unicode 3.2 draft) */
-  { 0x09f3, 0x23bd }, /*              horizlinescan9 ⎽ HORIZONTAL SCAN LINE-9 (Unicode 3.2 draft) */
-  { 0x09f4, 0x251c }, /*                       leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
-  { 0x09f5, 0x2524 }, /*                      rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */
-  { 0x09f6, 0x2534 }, /*                        bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */
-  { 0x09f7, 0x252c }, /*                        topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */
-  { 0x09f8, 0x2502 }, /*                     vertbar │ BOX DRAWINGS LIGHT VERTICAL */
-  { 0x0aa1, 0x2003 }, /*                     emspace   EM SPACE */
-  { 0x0aa2, 0x2002 }, /*                     enspace   EN SPACE */
-  { 0x0aa3, 0x2004 }, /*                    em3space   THREE-PER-EM SPACE */
-  { 0x0aa4, 0x2005 }, /*                    em4space   FOUR-PER-EM SPACE */
-  { 0x0aa5, 0x2007 }, /*                  digitspace   FIGURE SPACE */
-  { 0x0aa6, 0x2008 }, /*                  punctspace   PUNCTUATION SPACE */
-  { 0x0aa7, 0x2009 }, /*                   thinspace   THIN SPACE */
-  { 0x0aa8, 0x200a }, /*                   hairspace   HAIR SPACE */
-  { 0x0aa9, 0x2014 }, /*                      emdash — EM DASH */
-  { 0x0aaa, 0x2013 }, /*                      endash – EN DASH */
-/*  0x0aac                               signifblank ? ??? */
-  { 0x0aae, 0x2026 }, /*                    ellipsis … HORIZONTAL ELLIPSIS */
-  { 0x0aaf, 0x2025 }, /*             doubbaselinedot ‥ TWO DOT LEADER */
-  { 0x0ab0, 0x2153 }, /*                    onethird ⅓ VULGAR FRACTION ONE THIRD */
-  { 0x0ab1, 0x2154 }, /*                   twothirds ⅔ VULGAR FRACTION TWO THIRDS */
-  { 0x0ab2, 0x2155 }, /*                    onefifth ⅕ VULGAR FRACTION ONE FIFTH */
-  { 0x0ab3, 0x2156 }, /*                   twofifths ⅖ VULGAR FRACTION TWO FIFTHS */
-  { 0x0ab4, 0x2157 }, /*                 threefifths ⅗ VULGAR FRACTION THREE FIFTHS */
-  { 0x0ab5, 0x2158 }, /*                  fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */
-  { 0x0ab6, 0x2159 }, /*                    onesixth ⅙ VULGAR FRACTION ONE SIXTH */
-  { 0x0ab7, 0x215a }, /*                  fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */
-  { 0x0ab8, 0x2105 }, /*                      careof ℅ CARE OF */
-  { 0x0abb, 0x2012 }, /*                     figdash ‒ FIGURE DASH */
-  { 0x0abc, 0x2329 }, /*            leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */
-/*  0x0abd                              decimalpoint ? ??? */
-  { 0x0abe, 0x232a }, /*           rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */
-/*  0x0abf                                    marker ? ??? */
-  { 0x0ac3, 0x215b }, /*                   oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */
-  { 0x0ac4, 0x215c }, /*                threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */
-  { 0x0ac5, 0x215d }, /*                 fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */
-  { 0x0ac6, 0x215e }, /*                seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */
-  { 0x0ac9, 0x2122 }, /*                   trademark ™ TRADE MARK SIGN */
-  { 0x0aca, 0x2613 }, /*               signaturemark ☓ SALTIRE */
-/*  0x0acb                         trademarkincircle ? ??? */
-  { 0x0acc, 0x25c1 }, /*            leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */
-  { 0x0acd, 0x25b7 }, /*           rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */
-  { 0x0ace, 0x25cb }, /*                emopencircle ○ WHITE CIRCLE */
-  { 0x0acf, 0x25af }, /*             emopenrectangle ▯ WHITE VERTICAL RECTANGLE */
-  { 0x0ad0, 0x2018 }, /*         leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */
-  { 0x0ad1, 0x2019 }, /*        rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */
-  { 0x0ad2, 0x201c }, /*         leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */
-  { 0x0ad3, 0x201d }, /*        rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */
-  { 0x0ad4, 0x211e }, /*                prescription ℞ PRESCRIPTION TAKE */
-  { 0x0ad6, 0x2032 }, /*                     minutes ′ PRIME */
-  { 0x0ad7, 0x2033 }, /*                     seconds ″ DOUBLE PRIME */
-  { 0x0ad9, 0x271d }, /*                  latincross ✝ LATIN CROSS */
-/*  0x0ada                                  hexagram ? ??? */
-  { 0x0adb, 0x25ac }, /*            filledrectbullet ▬ BLACK RECTANGLE */
-  { 0x0adc, 0x25c0 }, /*         filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */
-  { 0x0add, 0x25b6 }, /*        filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */
-  { 0x0ade, 0x25cf }, /*              emfilledcircle ● BLACK CIRCLE */
-  { 0x0adf, 0x25ae }, /*                emfilledrect ▮ BLACK VERTICAL RECTANGLE */
-  { 0x0ae0, 0x25e6 }, /*            enopencircbullet ◦ WHITE BULLET */
-  { 0x0ae1, 0x25ab }, /*          enopensquarebullet ▫ WHITE SMALL SQUARE */
-  { 0x0ae2, 0x25ad }, /*              openrectbullet ▭ WHITE RECTANGLE */
-  { 0x0ae3, 0x25b3 }, /*             opentribulletup △ WHITE UP-POINTING TRIANGLE */
-  { 0x0ae4, 0x25bd }, /*           opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */
-  { 0x0ae5, 0x2606 }, /*                    openstar ☆ WHITE STAR */
-  { 0x0ae6, 0x2022 }, /*          enfilledcircbullet • BULLET */
-  { 0x0ae7, 0x25aa }, /*            enfilledsqbullet ▪ BLACK SMALL SQUARE */
-  { 0x0ae8, 0x25b2 }, /*           filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */
-  { 0x0ae9, 0x25bc }, /*         filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */
-  { 0x0aea, 0x261c }, /*                 leftpointer ☜ WHITE LEFT POINTING INDEX */
-  { 0x0aeb, 0x261e }, /*                rightpointer ☞ WHITE RIGHT POINTING INDEX */
-  { 0x0aec, 0x2663 }, /*                        club ♣ BLACK CLUB SUIT */
-  { 0x0aed, 0x2666 }, /*                     diamond ♦ BLACK DIAMOND SUIT */
-  { 0x0aee, 0x2665 }, /*                       heart ♥ BLACK HEART SUIT */
-  { 0x0af0, 0x2720 }, /*                maltesecross ✠ MALTESE CROSS */
-  { 0x0af1, 0x2020 }, /*                      dagger † DAGGER */
-  { 0x0af2, 0x2021 }, /*                doubledagger ‡ DOUBLE DAGGER */
-  { 0x0af3, 0x2713 }, /*                   checkmark ✓ CHECK MARK */
-  { 0x0af4, 0x2717 }, /*                 ballotcross ✗ BALLOT X */
-  { 0x0af5, 0x266f }, /*                musicalsharp ♯ MUSIC SHARP SIGN */
-  { 0x0af6, 0x266d }, /*                 musicalflat ♭ MUSIC FLAT SIGN */
-  { 0x0af7, 0x2642 }, /*                  malesymbol ♂ MALE SIGN */
-  { 0x0af8, 0x2640 }, /*                femalesymbol ♀ FEMALE SIGN */
-  { 0x0af9, 0x260e }, /*                   telephone ☎ BLACK TELEPHONE */
-  { 0x0afa, 0x2315 }, /*           telephonerecorder ⌕ TELEPHONE RECORDER */
-  { 0x0afb, 0x2117 }, /*         phonographcopyright ℗ SOUND RECORDING COPYRIGHT */
-  { 0x0afc, 0x2038 }, /*                       caret ‸ CARET */
-  { 0x0afd, 0x201a }, /*          singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */
-  { 0x0afe, 0x201e }, /*          doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */
-/*  0x0aff                                    cursor ? ??? */
-  { 0x0ba3, 0x003c }, /*                   leftcaret < LESS-THAN SIGN */
-  { 0x0ba6, 0x003e }, /*                  rightcaret > GREATER-THAN SIGN */
-  { 0x0ba8, 0x2228 }, /*                   downcaret ∨ LOGICAL OR */
-  { 0x0ba9, 0x2227 }, /*                     upcaret ∧ LOGICAL AND */
-  { 0x0bc0, 0x00af }, /*                     overbar ¯ MACRON */
-  { 0x0bc2, 0x22a5 }, /*                    downtack ⊥ UP TACK */
-  { 0x0bc3, 0x2229 }, /*                      upshoe ∩ INTERSECTION */
-  { 0x0bc4, 0x230a }, /*                   downstile ⌊ LEFT FLOOR */
-  { 0x0bc6, 0x005f }, /*                    underbar _ LOW LINE */
-  { 0x0bca, 0x2218 }, /*                         jot ∘ RING OPERATOR */
-  { 0x0bcc, 0x2395 }, /*                        quad ⎕ APL FUNCTIONAL SYMBOL QUAD */
-  { 0x0bce, 0x22a4 }, /*                      uptack ⊤ DOWN TACK */
-  { 0x0bcf, 0x25cb }, /*                      circle ○ WHITE CIRCLE */
-  { 0x0bd3, 0x2308 }, /*                     upstile ⌈ LEFT CEILING */
-  { 0x0bd6, 0x222a }, /*                    downshoe ∪ UNION */
-  { 0x0bd8, 0x2283 }, /*                   rightshoe ⊃ SUPERSET OF */
-  { 0x0bda, 0x2282 }, /*                    leftshoe ⊂ SUBSET OF */
-  { 0x0bdc, 0x22a2 }, /*                    lefttack ⊢ RIGHT TACK */
-  { 0x0bfc, 0x22a3 }, /*                   righttack ⊣ LEFT TACK */
-  { 0x0cdf, 0x2017 }, /*        hebrew_doublelowline ‗ DOUBLE LOW LINE */
-  { 0x0ce0, 0x05d0 }, /*                hebrew_aleph א HEBREW LETTER ALEF */
-  { 0x0ce1, 0x05d1 }, /*                  hebrew_bet ב HEBREW LETTER BET */
-  { 0x0ce2, 0x05d2 }, /*                hebrew_gimel ג HEBREW LETTER GIMEL */
-  { 0x0ce3, 0x05d3 }, /*                hebrew_dalet ד HEBREW LETTER DALET */
-  { 0x0ce4, 0x05d4 }, /*                   hebrew_he ה HEBREW LETTER HE */
-  { 0x0ce5, 0x05d5 }, /*                  hebrew_waw ו HEBREW LETTER VAV */
-  { 0x0ce6, 0x05d6 }, /*                 hebrew_zain ז HEBREW LETTER ZAYIN */
-  { 0x0ce7, 0x05d7 }, /*                 hebrew_chet ח HEBREW LETTER HET */
-  { 0x0ce8, 0x05d8 }, /*                  hebrew_tet ט HEBREW LETTER TET */
-  { 0x0ce9, 0x05d9 }, /*                  hebrew_yod י HEBREW LETTER YOD */
-  { 0x0cea, 0x05da }, /*            hebrew_finalkaph ך HEBREW LETTER FINAL KAF */
-  { 0x0ceb, 0x05db }, /*                 hebrew_kaph כ HEBREW LETTER KAF */
-  { 0x0cec, 0x05dc }, /*                hebrew_lamed ל HEBREW LETTER LAMED */
-  { 0x0ced, 0x05dd }, /*             hebrew_finalmem ם HEBREW LETTER FINAL MEM */
-  { 0x0cee, 0x05de }, /*                  hebrew_mem מ HEBREW LETTER MEM */
-  { 0x0cef, 0x05df }, /*             hebrew_finalnun ן HEBREW LETTER FINAL NUN */
-  { 0x0cf0, 0x05e0 }, /*                  hebrew_nun נ HEBREW LETTER NUN */
-  { 0x0cf1, 0x05e1 }, /*               hebrew_samech ס HEBREW LETTER SAMEKH */
-  { 0x0cf2, 0x05e2 }, /*                 hebrew_ayin ע HEBREW LETTER AYIN */
-  { 0x0cf3, 0x05e3 }, /*              hebrew_finalpe ף HEBREW LETTER FINAL PE */
-  { 0x0cf4, 0x05e4 }, /*                   hebrew_pe פ HEBREW LETTER PE */
-  { 0x0cf5, 0x05e5 }, /*            hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */
-  { 0x0cf6, 0x05e6 }, /*                 hebrew_zade צ HEBREW LETTER TSADI */
-  { 0x0cf7, 0x05e7 }, /*                 hebrew_qoph ק HEBREW LETTER QOF */
-  { 0x0cf8, 0x05e8 }, /*                 hebrew_resh ר HEBREW LETTER RESH */
-  { 0x0cf9, 0x05e9 }, /*                 hebrew_shin ש HEBREW LETTER SHIN */
-  { 0x0cfa, 0x05ea }, /*                  hebrew_taw ת HEBREW LETTER TAV */
-  { 0x0da1, 0x0e01 }, /*                  Thai_kokai ก THAI CHARACTER KO KAI */
-  { 0x0da2, 0x0e02 }, /*                Thai_khokhai ข THAI CHARACTER KHO KHAI */
-  { 0x0da3, 0x0e03 }, /*               Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */
-  { 0x0da4, 0x0e04 }, /*               Thai_khokhwai ค THAI CHARACTER KHO KHWAI */
-  { 0x0da5, 0x0e05 }, /*                Thai_khokhon ฅ THAI CHARACTER KHO KHON */
-  { 0x0da6, 0x0e06 }, /*             Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */
-  { 0x0da7, 0x0e07 }, /*                 Thai_ngongu ง THAI CHARACTER NGO NGU */
-  { 0x0da8, 0x0e08 }, /*                Thai_chochan จ THAI CHARACTER CHO CHAN */
-  { 0x0da9, 0x0e09 }, /*               Thai_choching ฉ THAI CHARACTER CHO CHING */
-  { 0x0daa, 0x0e0a }, /*               Thai_chochang ช THAI CHARACTER CHO CHANG */
-  { 0x0dab, 0x0e0b }, /*                   Thai_soso ซ THAI CHARACTER SO SO */
-  { 0x0dac, 0x0e0c }, /*                Thai_chochoe ฌ THAI CHARACTER CHO CHOE */
-  { 0x0dad, 0x0e0d }, /*                 Thai_yoying ญ THAI CHARACTER YO YING */
-  { 0x0dae, 0x0e0e }, /*                Thai_dochada ฎ THAI CHARACTER DO CHADA */
-  { 0x0daf, 0x0e0f }, /*                Thai_topatak ฏ THAI CHARACTER TO PATAK */
-  { 0x0db0, 0x0e10 }, /*                Thai_thothan ฐ THAI CHARACTER THO THAN */
-  { 0x0db1, 0x0e11 }, /*          Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */
-  { 0x0db2, 0x0e12 }, /*             Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */
-  { 0x0db3, 0x0e13 }, /*                  Thai_nonen ณ THAI CHARACTER NO NEN */
-  { 0x0db4, 0x0e14 }, /*                  Thai_dodek ด THAI CHARACTER DO DEK */
-  { 0x0db5, 0x0e15 }, /*                  Thai_totao ต THAI CHARACTER TO TAO */
-  { 0x0db6, 0x0e16 }, /*               Thai_thothung ถ THAI CHARACTER THO THUNG */
-  { 0x0db7, 0x0e17 }, /*              Thai_thothahan ท THAI CHARACTER THO THAHAN */
-  { 0x0db8, 0x0e18 }, /*               Thai_thothong ธ THAI CHARACTER THO THONG */
-  { 0x0db9, 0x0e19 }, /*                   Thai_nonu น THAI CHARACTER NO NU */
-  { 0x0dba, 0x0e1a }, /*               Thai_bobaimai บ THAI CHARACTER BO BAIMAI */
-  { 0x0dbb, 0x0e1b }, /*                  Thai_popla ป THAI CHARACTER PO PLA */
-  { 0x0dbc, 0x0e1c }, /*               Thai_phophung ผ THAI CHARACTER PHO PHUNG */
-  { 0x0dbd, 0x0e1d }, /*                   Thai_fofa ฝ THAI CHARACTER FO FA */
-  { 0x0dbe, 0x0e1e }, /*                Thai_phophan พ THAI CHARACTER PHO PHAN */
-  { 0x0dbf, 0x0e1f }, /*                  Thai_fofan ฟ THAI CHARACTER FO FAN */
-  { 0x0dc0, 0x0e20 }, /*             Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */
-  { 0x0dc1, 0x0e21 }, /*                   Thai_moma ม THAI CHARACTER MO MA */
-  { 0x0dc2, 0x0e22 }, /*                  Thai_yoyak ย THAI CHARACTER YO YAK */
-  { 0x0dc3, 0x0e23 }, /*                  Thai_rorua ร THAI CHARACTER RO RUA */
-  { 0x0dc4, 0x0e24 }, /*                     Thai_ru ฤ THAI CHARACTER RU */
-  { 0x0dc5, 0x0e25 }, /*                 Thai_loling ล THAI CHARACTER LO LING */
-  { 0x0dc6, 0x0e26 }, /*                     Thai_lu ฦ THAI CHARACTER LU */
-  { 0x0dc7, 0x0e27 }, /*                 Thai_wowaen ว THAI CHARACTER WO WAEN */
-  { 0x0dc8, 0x0e28 }, /*                 Thai_sosala ศ THAI CHARACTER SO SALA */
-  { 0x0dc9, 0x0e29 }, /*                 Thai_sorusi ษ THAI CHARACTER SO RUSI */
-  { 0x0dca, 0x0e2a }, /*                  Thai_sosua ส THAI CHARACTER SO SUA */
-  { 0x0dcb, 0x0e2b }, /*                  Thai_hohip ห THAI CHARACTER HO HIP */
-  { 0x0dcc, 0x0e2c }, /*                Thai_lochula ฬ THAI CHARACTER LO CHULA */
-  { 0x0dcd, 0x0e2d }, /*                   Thai_oang อ THAI CHARACTER O ANG */
-  { 0x0dce, 0x0e2e }, /*               Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */
-  { 0x0dcf, 0x0e2f }, /*              Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */
-  { 0x0dd0, 0x0e30 }, /*                  Thai_saraa ะ THAI CHARACTER SARA A */
-  { 0x0dd1, 0x0e31 }, /*             Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */
-  { 0x0dd2, 0x0e32 }, /*                 Thai_saraaa า THAI CHARACTER SARA AA */
-  { 0x0dd3, 0x0e33 }, /*                 Thai_saraam ำ THAI CHARACTER SARA AM */
-  { 0x0dd4, 0x0e34 }, /*                  Thai_sarai ิ THAI CHARACTER SARA I */
-  { 0x0dd5, 0x0e35 }, /*                 Thai_saraii ี THAI CHARACTER SARA II */
-  { 0x0dd6, 0x0e36 }, /*                 Thai_saraue ึ THAI CHARACTER SARA UE */
-  { 0x0dd7, 0x0e37 }, /*                Thai_sarauee ื THAI CHARACTER SARA UEE */
-  { 0x0dd8, 0x0e38 }, /*                  Thai_sarau ุ THAI CHARACTER SARA U */
-  { 0x0dd9, 0x0e39 }, /*                 Thai_sarauu ู THAI CHARACTER SARA UU */
-  { 0x0dda, 0x0e3a }, /*                Thai_phinthu ฺ THAI CHARACTER PHINTHU */
-/*  0x0dde                    Thai_maihanakat_maitho ? ??? */
-  { 0x0ddf, 0x0e3f }, /*                   Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */
-  { 0x0de0, 0x0e40 }, /*                  Thai_sarae เ THAI CHARACTER SARA E */
-  { 0x0de1, 0x0e41 }, /*                 Thai_saraae แ THAI CHARACTER SARA AE */
-  { 0x0de2, 0x0e42 }, /*                  Thai_sarao โ THAI CHARACTER SARA O */
-  { 0x0de3, 0x0e43 }, /*          Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */
-  { 0x0de4, 0x0e44 }, /*         Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */
-  { 0x0de5, 0x0e45 }, /*            Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */
-  { 0x0de6, 0x0e46 }, /*               Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */
-  { 0x0de7, 0x0e47 }, /*              Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */
-  { 0x0de8, 0x0e48 }, /*                  Thai_maiek ่ THAI CHARACTER MAI EK */
-  { 0x0de9, 0x0e49 }, /*                 Thai_maitho ้ THAI CHARACTER MAI THO */
-  { 0x0dea, 0x0e4a }, /*                 Thai_maitri ๊ THAI CHARACTER MAI TRI */
-  { 0x0deb, 0x0e4b }, /*            Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */
-  { 0x0dec, 0x0e4c }, /*            Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */
-  { 0x0ded, 0x0e4d }, /*               Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */
-  { 0x0df0, 0x0e50 }, /*                 Thai_leksun ๐ THAI DIGIT ZERO */
-  { 0x0df1, 0x0e51 }, /*                Thai_leknung ๑ THAI DIGIT ONE */
-  { 0x0df2, 0x0e52 }, /*                Thai_leksong ๒ THAI DIGIT TWO */
-  { 0x0df3, 0x0e53 }, /*                 Thai_leksam ๓ THAI DIGIT THREE */
-  { 0x0df4, 0x0e54 }, /*                  Thai_leksi ๔ THAI DIGIT FOUR */
-  { 0x0df5, 0x0e55 }, /*                  Thai_lekha ๕ THAI DIGIT FIVE */
-  { 0x0df6, 0x0e56 }, /*                 Thai_lekhok ๖ THAI DIGIT SIX */
-  { 0x0df7, 0x0e57 }, /*                Thai_lekchet ๗ THAI DIGIT SEVEN */
-  { 0x0df8, 0x0e58 }, /*                Thai_lekpaet ๘ THAI DIGIT EIGHT */
-  { 0x0df9, 0x0e59 }, /*                 Thai_lekkao ๙ THAI DIGIT NINE */
-  { 0x0ea1, 0x3131 }, /*               Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */
-  { 0x0ea2, 0x3132 }, /*          Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */
-  { 0x0ea3, 0x3133 }, /*           Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */
-  { 0x0ea4, 0x3134 }, /*                Hangul_Nieun ㄴ HANGUL LETTER NIEUN */
-  { 0x0ea5, 0x3135 }, /*           Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */
-  { 0x0ea6, 0x3136 }, /*           Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */
-  { 0x0ea7, 0x3137 }, /*               Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */
-  { 0x0ea8, 0x3138 }, /*          Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */
-  { 0x0ea9, 0x3139 }, /*                Hangul_Rieul ㄹ HANGUL LETTER RIEUL */
-  { 0x0eaa, 0x313a }, /*          Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */
-  { 0x0eab, 0x313b }, /*           Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */
-  { 0x0eac, 0x313c }, /*           Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */
-  { 0x0ead, 0x313d }, /*            Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */
-  { 0x0eae, 0x313e }, /*           Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */
-  { 0x0eaf, 0x313f }, /*          Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */
-  { 0x0eb0, 0x3140 }, /*           Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */
-  { 0x0eb1, 0x3141 }, /*                Hangul_Mieum ㅁ HANGUL LETTER MIEUM */
-  { 0x0eb2, 0x3142 }, /*                Hangul_Pieub ㅂ HANGUL LETTER PIEUP */
-  { 0x0eb3, 0x3143 }, /*           Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */
-  { 0x0eb4, 0x3144 }, /*            Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */
-  { 0x0eb5, 0x3145 }, /*                 Hangul_Sios ㅅ HANGUL LETTER SIOS */
-  { 0x0eb6, 0x3146 }, /*            Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */
-  { 0x0eb7, 0x3147 }, /*                Hangul_Ieung ㅇ HANGUL LETTER IEUNG */
-  { 0x0eb8, 0x3148 }, /*                Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */
-  { 0x0eb9, 0x3149 }, /*           Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */
-  { 0x0eba, 0x314a }, /*                Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */
-  { 0x0ebb, 0x314b }, /*               Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */
-  { 0x0ebc, 0x314c }, /*                Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */
-  { 0x0ebd, 0x314d }, /*               Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */
-  { 0x0ebe, 0x314e }, /*                Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */
-  { 0x0ebf, 0x314f }, /*                    Hangul_A ㅏ HANGUL LETTER A */
-  { 0x0ec0, 0x3150 }, /*                   Hangul_AE ㅐ HANGUL LETTER AE */
-  { 0x0ec1, 0x3151 }, /*                   Hangul_YA ㅑ HANGUL LETTER YA */
-  { 0x0ec2, 0x3152 }, /*                  Hangul_YAE ㅒ HANGUL LETTER YAE */
-  { 0x0ec3, 0x3153 }, /*                   Hangul_EO ㅓ HANGUL LETTER EO */
-  { 0x0ec4, 0x3154 }, /*                    Hangul_E ㅔ HANGUL LETTER E */
-  { 0x0ec5, 0x3155 }, /*                  Hangul_YEO ㅕ HANGUL LETTER YEO */
-  { 0x0ec6, 0x3156 }, /*                   Hangul_YE ㅖ HANGUL LETTER YE */
-  { 0x0ec7, 0x3157 }, /*                    Hangul_O ㅗ HANGUL LETTER O */
-  { 0x0ec8, 0x3158 }, /*                   Hangul_WA ㅘ HANGUL LETTER WA */
-  { 0x0ec9, 0x3159 }, /*                  Hangul_WAE ㅙ HANGUL LETTER WAE */
-  { 0x0eca, 0x315a }, /*                   Hangul_OE ㅚ HANGUL LETTER OE */
-  { 0x0ecb, 0x315b }, /*                   Hangul_YO ㅛ HANGUL LETTER YO */
-  { 0x0ecc, 0x315c }, /*                    Hangul_U ㅜ HANGUL LETTER U */
-  { 0x0ecd, 0x315d }, /*                  Hangul_WEO ㅝ HANGUL LETTER WEO */
-  { 0x0ece, 0x315e }, /*                   Hangul_WE ㅞ HANGUL LETTER WE */
-  { 0x0ecf, 0x315f }, /*                   Hangul_WI ㅟ HANGUL LETTER WI */
-  { 0x0ed0, 0x3160 }, /*                   Hangul_YU ㅠ HANGUL LETTER YU */
-  { 0x0ed1, 0x3161 }, /*                   Hangul_EU ㅡ HANGUL LETTER EU */
-  { 0x0ed2, 0x3162 }, /*                   Hangul_YI ㅢ HANGUL LETTER YI */
-  { 0x0ed3, 0x3163 }, /*                    Hangul_I ㅣ HANGUL LETTER I */
-  { 0x0ed4, 0x11a8 }, /*             Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */
-  { 0x0ed5, 0x11a9 }, /*        Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */
-  { 0x0ed6, 0x11aa }, /*         Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */
-  { 0x0ed7, 0x11ab }, /*              Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */
-  { 0x0ed8, 0x11ac }, /*         Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */
-  { 0x0ed9, 0x11ad }, /*         Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */
-  { 0x0eda, 0x11ae }, /*             Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */
-  { 0x0edb, 0x11af }, /*              Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */
-  { 0x0edc, 0x11b0 }, /*        Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */
-  { 0x0edd, 0x11b1 }, /*         Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */
-  { 0x0ede, 0x11b2 }, /*         Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */
-  { 0x0edf, 0x11b3 }, /*          Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */
-  { 0x0ee0, 0x11b4 }, /*         Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */
-  { 0x0ee1, 0x11b5 }, /*        Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */
-  { 0x0ee2, 0x11b6 }, /*         Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */
-  { 0x0ee3, 0x11b7 }, /*              Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */
-  { 0x0ee4, 0x11b8 }, /*              Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */
-  { 0x0ee5, 0x11b9 }, /*          Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */
-  { 0x0ee6, 0x11ba }, /*               Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */
-  { 0x0ee7, 0x11bb }, /*          Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */
-  { 0x0ee8, 0x11bc }, /*              Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */
-  { 0x0ee9, 0x11bd }, /*              Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */
-  { 0x0eea, 0x11be }, /*              Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */
-  { 0x0eeb, 0x11bf }, /*             Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */
-  { 0x0eec, 0x11c0 }, /*              Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */
-  { 0x0eed, 0x11c1 }, /*             Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */
-  { 0x0eee, 0x11c2 }, /*              Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */
-  { 0x0eef, 0x316d }, /*     Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */
-  { 0x0ef0, 0x3171 }, /*    Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */
-  { 0x0ef1, 0x3178 }, /*    Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */
-  { 0x0ef2, 0x317f }, /*              Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */
-  { 0x0ef3, 0x3181 }, /*    Hangul_KkogjiDalrinIeung ㆁ HANGUL LETTER YESIEUNG */
-  { 0x0ef4, 0x3184 }, /*   Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */
-  { 0x0ef5, 0x3186 }, /*          Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */
-  { 0x0ef6, 0x318d }, /*                Hangul_AraeA ㆍ HANGUL LETTER ARAEA */
-  { 0x0ef7, 0x318e }, /*               Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */
-  { 0x0ef8, 0x11eb }, /*            Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */
-  { 0x0ef9, 0x11f0 }, /*  Hangul_J_KkogjiDalrinIeung ᇰ HANGUL JONGSEONG YESIEUNG */
-  { 0x0efa, 0x11f9 }, /*        Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */
-  { 0x0eff, 0x20a9 }, /*                  Korean_Won ₩ WON SIGN */
-  { 0x13a4, 0x20ac }, /*                        Euro € EURO SIGN */
-  { 0x13bc, 0x0152 }, /*                          OE ΠLATIN CAPITAL LIGATURE OE */
-  { 0x13bd, 0x0153 }, /*                          oe œ LATIN SMALL LIGATURE OE */
-  { 0x13be, 0x0178 }, /*                  Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */
-  { 0x20ac, 0x20ac }, /*                    EuroSign € EURO SIGN */
-};
-
-VISIBLE
-long _p9keysym2ucs(KeySym keysym)
-{
-    int min = 0;
-    int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
-    int mid;
-
-    /* first check for Latin-1 characters (1:1 mapping) */
-    if ((keysym >= 0x0020 && keysym <= 0x007e) ||
-        (keysym >= 0x00a0 && keysym <= 0x00ff))
-        return keysym;
-
-    /* also check for directly encoded 24-bit UCS characters */
-    if ((keysym & 0xff000000) == 0x01000000)
-	return keysym & 0x00ffffff;
-
-    /* binary search in table */
-    while (max >= min) {
-	mid = (min + max) / 2;
-	if (keysymtab[mid].keysym < keysym)
-	    min = mid + 1;
-	else if (keysymtab[mid].keysym > keysym)
-	    max = mid - 1;
-	else {
-	    /* found it */
-	    return keysymtab[mid].ucs;
-	}
-    }
-
-    /* no matching Unicode value found */
-    return -1;
-}
blob - 77050e1b74c4008782d2e2642f8d9f7b8ba049af (mode 644)
blob + /dev/null
--- src/libdraw/x11-keysym2ucs.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* $XFree86: xc/programs/xterm/keysym2ucs.h,v 1.1 1999/06/12 15:37:18 dawes Exp $ */
-/*
- * This module converts keysym values into the corresponding ISO 10646-1
- * (UCS, Unicode) values.
- */
-
-#include <X11/X.h>
-
-long _p9keysym2ucs(KeySym keysym);
blob - a7446f37dda49dee73b4b595e685401fd333f08a (mode 644)
blob + /dev/null
--- src/libdraw/x11-load.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <u.h>
-#include "x11-inc.h"
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include "x11-memdraw.h"
-
-int
-loadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
-{
-	int n;
-
-	n = _loadmemimage(i, r, data, ndata);
-	if(n > 0 && i->X)
-		_xputxdata(i, r);
-	return n;
-}
-
blob - c8d5e661b746cb4bfdd099972f0a446861d1ba87 (mode 644)
blob + /dev/null
--- src/libdraw/x11-memdraw.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Structure pointed to by X field of Memimage
- */
-
-typedef struct Xmem Xmem;
-typedef struct Xprivate Xprivate;
-
-enum
-{
-	PMundef = ~0
-};
-
-struct Xmem
-{
-	int		pixmap;	/* pixmap id */
-	XImage		*xi;	/* local image */
-	int		dirty;	/* is the X server ahead of us?  */
-	Rectangle	dirtyr;	/* which pixels? */
-	Rectangle	r;	/* size of image */
-};
-
-struct Xprivate {
-	u32int		chan;
-	XColormap	cmap;
-	XCursor		cursor;
-	XDisplay	*display;
-	int		depth;				/* of screen */
-	XDrawable	drawable;
-	XColor		map[256];
-	XColor		map7[128];
-	uchar		map7to8[128][2];
-	XGC		gccopy;
-	XGC		gccopy0;
-	XGC		gcfill;
-	u32int		gcfillcolor;
-	XGC		gcfill0;
-	u32int		gcfill0color;
-	XGC		gcreplsrc;
-	u32int		gcreplsrctile;
-	XGC		gcreplsrc0;
-	u32int		gcreplsrc0tile;
-	XGC		gcsimplesrc;
-	u32int		gcsimplesrccolor;
-	u32int		gcsimplesrcpixmap;
-	XGC		gcsimplesrc0;
-	u32int		gcsimplesrc0color;
-	u32int		gcsimplesrc0pixmap;
-	XGC		gczero;
-	u32int		gczeropixmap;
-	XGC		gczero0;
-	u32int		gczero0pixmap;
-	XDisplay	*kbdcon;
-	XDisplay	*mousecon;
-	Rectangle	newscreenr;
-	Memimage*	screenimage;
-	QLock		screenlock;
-	XDrawable	screenpm;
-	XDrawable	nextscreenpm;
-	Rectangle	screenr;
-	XDisplay	*snarfcon;
-	int		toplan9[256];
-	int		tox11[256];
-	int		usetable;
-	XVisual		*vis;
-	Atom		clipboard;
-	Atom		utf8string;
-	Atom		targets;
-	Atom		text;
-	Atom		compoundtext;
-	Atom		takefocus;
-	Atom		losefocus;
-	Atom		wmprotos;
-	uint		putsnarf;
-	uint		assertsnarf;
-	int		destroyed;
-};
-
-extern Xprivate _x;
-
-extern Memimage *_xallocmemimage(Rectangle, u32int, int);
-extern XImage	*_xallocxdata(Memimage*, Rectangle);
-extern void	_xdirtyxdata(Memimage*, Rectangle);
-extern void	_xfillcolor(Memimage*, Rectangle, u32int);
-extern void	_xfreexdata(Memimage*);
-extern XImage	*_xgetxdata(Memimage*, Rectangle);
-extern void	_xputxdata(Memimage*, Rectangle);
-extern void	_initdisplaymemimage(Display*, Memimage*);
-
-struct Mouse;
-extern int	_xtoplan9mouse(XDisplay*, XEvent*, struct Mouse*);
-extern int	_xtoplan9kbd(XEvent*);
-extern void	_xexpose(XEvent*, XDisplay*);
-extern int	_xselect(XEvent*, XDisplay*);
-extern int	_xconfigure(XEvent*, XDisplay*);
-extern int	_xdestroy(XEvent*, XDisplay*);
-extern void	_flushmemscreen(Rectangle);
-extern void	_xmoveto(Point);
-struct Cursor;
-extern void	_xsetcursor(struct Cursor*);
-
-#define MouseMask (\
-	ButtonPressMask|\
-	ButtonReleaseMask|\
-	PointerMotionMask|\
-	Button1MotionMask|\
-	Button2MotionMask|\
-	Button3MotionMask)
-
blob - 4440639549f0028761116d3ef55e33722195a50f (mode 644)
blob + /dev/null
--- src/libdraw/x11-mouse.c
+++ /dev/null
@@ -1,221 +0,0 @@
-#include <u.h>
-#include "x11-inc.h"
-#include <libc.h>
-#include <draw.h>
-#include <thread.h>
-#include <cursor.h>
-#include <mouse.h>
-#include <memdraw.h>
-#include "x11-memdraw.h"
-
-int _windowhasfocus = 1;
-int _wantfocuschanges;
-
-void
-moveto(Mousectl *m, Point pt)
-{
-	_xmoveto(pt);
-}
-
-void
-closemouse(Mousectl *mc)
-{
-	if(mc == nil)
-		return;
-
-/*	postnote(PNPROC, mc->pid, "kill");
-*/
-	do; while(nbrecv(mc->c, &mc->m) > 0);
-	close(mc->mfd);
-	close(mc->cfd);
-	free(mc->file);
-	chanfree(mc->c);
-	chanfree(mc->resizec);
-	free(mc);
-}
-
-int
-readmouse(Mousectl *mc)
-{
-	if(mc->display)
-		flushimage(mc->display, 1);
-	if(recv(mc->c, &mc->m) < 0){
-		fprint(2, "readmouse: %r\n");
-		return -1;
-	}
-	return 0;
-}
-
-/*
- * This is necessary because some X libraries (e.g., on FC3)
- * use an inordinate amount of stack space to do _xsetcursor.
- * Perhaps instead there should be a generic "run this X routine"
- * stack that you send a function and argument to.
- */
-static
-void
-_cursorproc(void *arg)
-{
-	Mousectl *mc;
-	Cursor *c;
-	
-	mc = arg;
-	threadsetname("cursorproc (sigh)");
-	for(;;){
-		c = recvp(mc->ccursor);
-		_xsetcursor(c);
-		sendp(mc->ccursorwait, nil);
-	}
-}
-
-static
-void
-_ioproc(void *arg)
-{
-	int fd, one, buttons;
-	Atom a;
-	ulong mask;
-	Mouse m;
-	Mousectl *mc;
-	XEvent xevent;
-
-	one = 1;
-	mc = arg;
-	threadsetname("mouseproc");
-	memset(&m, 0, sizeof m);
-	mc->pid = getpid();
-	mask = MouseMask|ExposureMask|StructureNotifyMask;
-	XSelectInput(_x.mousecon, _x.drawable, mask);
-	fd = XConnectionNumber(_x.mousecon);
-	buttons = 0;
-	for(;;){
-		XNextEvent(_x.mousecon, &xevent);
-		switch(xevent.type){
-		case Expose:
-			_xexpose(&xevent, _x.mousecon);
-			continue;
-		case DestroyNotify:
-			if(_xdestroy(&xevent, _x.mousecon)){
-				/* drain it before sending */
-				/* apps that care can notice we sent a 0 */
-				/* otherwise we'll have getwindow send SIGHUP */
-				nbrecv(mc->resizec, 0);
-				nbrecv(mc->resizec, 0);
-				send(mc->resizec, 0);
-			}
-			continue;
-		case ConfigureNotify:
-			if(_xconfigure(&xevent, _x.mousecon))
-				nbsend(mc->resizec, &one);
-			continue;
-		case SelectionRequest:
-			_xselect(&xevent, _x.mousecon);
-			continue;
-		case ButtonPress:
-		case ButtonRelease:
-		case MotionNotify:
-			/* If the motion notifications are backing up, skip over some. */
-			if(0 && xevent.type == MotionNotify){
-				while(XCheckWindowEvent(_x.mousecon, _x.drawable, MouseMask, &xevent)){
-					if(xevent.type != MotionNotify)
-						break;
-				}
-			}
-			m.buttons = buttons;
-			if(_xtoplan9mouse(_x.mousecon, &xevent, &m) < 0)
-				continue;
-			buttons = m.buttons;
-			send(mc->c, &m);
-			/*
-			 * mc->Mouse is updated after send so it doesn't have wrong value if we block during send.
-			 * This means that programs should receive into mc->Mouse (see readmouse() above) if
-			 * they want full synchrony.
-			 */
-			mc->m = m;
-			break;
-		case ClientMessage:
-			if(xevent.xclient.message_type == _x.wmprotos){
-				a = xevent.xclient.data.l[0];
-				if(_wantfocuschanges && a == _x.takefocus){
-					_windowhasfocus = 1;
-					_x.newscreenr = _x.screenr;
-					nbsend(mc->resizec, &one);
-				}else if(_wantfocuschanges && a == _x.losefocus){
-					_windowhasfocus = 0;
-					_x.newscreenr = _x.screenr;
-					nbsend(mc->resizec, &one);
-				}
-			}
-			break;
-		}
-	}
-}
-
-Mousectl*
-initmouse(char *file, Image *i)
-{
-	Mousectl *mc;
-
-	mc = mallocz(sizeof(Mousectl), 1);
-	if(i)
-		mc->display = i->display;
-	mc->c = chancreate(sizeof(Mouse), 0);
-	chansetname(mc->c, "mousec");
-	mc->resizec = chancreate(sizeof(int), 2);
-	chansetname(mc->resizec, "resizec");
-	mc->ccursor = chancreate(sizeof(void*), 0);
-	chansetname(mc->ccursor, "ccursor");
-	mc->ccursorwait = chancreate(sizeof(void*), 0);
-	chansetname(mc->ccursor, "ccursorwait");
-	proccreate(_ioproc, mc, 256*1024);
-	proccreate(_cursorproc, mc, 256*1024);	/* sigh */
-	return mc;
-}
-
-void
-setcursor(Mousectl *mc, Cursor *c)
-{
-	qlock(&mc->cursorlock);
-	sendp(mc->ccursor, c);
-	recvp(mc->ccursorwait);
-	qunlock(&mc->cursorlock);
-}
-
-/*
- * Send the mouse event back to the window manager.
- * So that 9term can tell rio to pop up its button3 menu.
- * Note that we're using _x.mousecon in a few places,
- * so we have to be sure that the mouse proc isn't using it
- * when we call!  This is all a bit wonky and should be 
- * avoided unless you know what you're doing.
- */
-void
-bouncemouse(Mouse *m)
-{
-	XButtonEvent e;
-	XWindow dw;
-
-	e.type = ButtonPress;
-	e.state = 0;
-	e.button = 0;
-	if(m->buttons&1)
-		e.button = 1;
-	else if(m->buttons&2)
-		e.button = 2;
-	else if(m->buttons&4)
-		e.button = 3;
-	e.same_screen = 1;
-	XTranslateCoordinates(_x.display, _x.drawable,
-		DefaultRootWindow(_x.display),
-		m->xy.x, m->xy.y, &e.x_root, &e.y_root, &dw);
-	e.root = DefaultRootWindow(_x.mousecon);
-	e.window = e.root;
-	e.subwindow = None;
-	e.x = e.x_root;
-	e.y = e.y_root;
-#undef time
-	e.time = CurrentTime;
-	XUngrabPointer(_x.mousecon, m->msec);
-	XSendEvent(_x.mousecon, e.root, True, ButtonPressMask, (XEvent*)&e);
-	XFlush(_x.mousecon);
-}
blob - 5cbdded84267122b86eac07b0ff296456c1691c1 (mode 644)
blob + /dev/null
--- src/libdraw/x11-pixelbits.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <u.h>
-#include "x11-inc.h"
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include "x11-memdraw.h"
-
-u32int
-pixelbits(Memimage *m, Point p)
-{
-	if(m->X)
-		_xgetxdata(m, Rect(p.x, p.y, p.x+1, p.y+1));
-	return _pixelbits(m, p);
-}
-
-
blob - d01a232ff99e9d228100ff1724e918f3c2a7f52f (mode 644)
blob + /dev/null
--- src/libdraw/x11-unload.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <u.h>
-#include "x11-inc.h"
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include "x11-memdraw.h"
-
-int
-unloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
-{
-	if(i->X)
-		_xgetxdata(i, r);
-	return _unloadmemimage(i, r, data, ndata);
-}
-
blob - 582b68e1d86fe10ef54bc1b4b199afe0012843cd (mode 644)
blob + /dev/null
--- src/libdraw/x11-wsys.c
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <u.h>
-#include "x11-inc.h"
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include "x11-memdraw.h"
-
-void
-drawtopwindow(void)
-{
-	XMapRaised(_x.display, _x.drawable);
-	XFlush(_x.display);
-	/*
-	 * Should not be using kbdcon since we're not running
-	 * in the kbdproc, but this is necessary to make the keyboard
-	 * take focus if the window is hidden when drawtopwindow
-	 * is called.  Let's hope that XSetInputFocus is only a write 
-	 * on the fd, and so it's okay to do even though the kbdproc
-	 * is reading at the same time.
-	 */
-	XSetInputFocus(_x.kbdcon, _x.drawable, RevertToPointerRoot,
-		CurrentTime);
-	XFlush(_x.kbdcon);
-}
-
-void
-drawresizewindow(Rectangle r)
-{
-/*	XConfigureRequestEvent e; */
-	XWindowChanges e;
-	int value_mask;
-
-	memset(&e, 0, sizeof e);
-	value_mask = CWWidth|CWHeight;
-/*	e.x = r.min.x; */
-/*	e.y = r.min.y; */
-	e.width = Dx(r);
-	e.height = Dy(r);
-	XConfigureWindow(_x.display, _x.drawable, value_mask, &e);
-	XFlush(_x.display);
-}