shithub: fork

Download patch

ref: 8b56be517e51869c58e5eba7bdb5a22bd1361d40
parent: bfdf9e3c44c822a456db6664ea7eff8ce9e15854
author: qwx <qwx@sciops.net>
date: Sat Aug 26 02:45:41 EDT 2023

remove vnc: patch no longer necessary after last update

--- a/sys/src/cmd/vnc/auth.c
+++ /dev/null
@@ -1,171 +1,0 @@
-#include "vnc.h"
-#include <libsec.h>
-#include <auth.h>
-
-int
-vncsrvhandshake(Vnc *v)
-{
-	char msg[VerLen+1];
-
-	vncwrbytes(v, "RFB 003.003\n", VerLen);
-	vncflush(v);
-
-	vncrdbytes(v, msg, VerLen);
-	if(verbose)
-		fprint(2, "client version: %s\n", msg);
-	return 0;
-}
-
-int
-vnchandshake(Vnc *v)
-{
-	char msg[VerLen + 1];
-
-	msg[VerLen] = 0;
-	vncrdbytes(v, msg, VerLen);
-
-	if(verbose)
-		fprint(2, "server version: %s\n", msg);
-
-	if(strncmp(msg, "RFB 003.003\n", VerLen) == 0)
-		v->vers = 33;
-	else if(strncmp(msg, "RFB 003.007\n", VerLen) == 0)
-		v->vers = 37;
-	else if(strncmp(msg, "RFB 003.008\n", VerLen) == 0)
-		v->vers = 38;
-	else if(strncmp(msg, "RFB 003.889\n", VerLen) == 0)
-		v->vers = 38;  /* Darwin */
-	else if(strncmp(msg, "RFB 004.000\n", VerLen) == 0)
-		v->vers = 38;
-	else /* RFC6143: Any other should be treated as 3.3. */
-		v->vers = 33;
-
-	strcpy(msg, "RFB 003.008\n");
-	vncwrbytes(v, msg, VerLen);
-	vncflush(v);
-	return 0;
-}
-
-int
-vncauth(Vnc *v, char *keypattern)
-{
-	uchar chal[VncChalLen];
-	ulong auth, type;
-	int i, ntypes;
-	char *err;
-
-	if(keypattern == nil)
-		keypattern = "";
-
-	auth = AFailed;
-	if(v->vers == 33)
-		auth = vncrdlong(v);
-	else{
-		ntypes = vncrdchar(v);
-		for(i = 0; i < ntypes; i++){
-			type = vncrdchar(v);
-			if(verbose)
-				fprint(2, "auth type %uld\n", type);
-			if(type > auth && type <= AVncAuth)
-				auth = type;
-		}
-		if(auth == AFailed){
-			werrstr("no supported auth types");
-			return -1;
-		}
-	}
-
-	switch(auth){
-	default:
-		werrstr("unknown auth type 0x%lux", auth);
-		if(verbose)
-			fprint(2, "unknown auth type 0x%lux\n", auth);
-		return -1;
-
-	case AFailed:
-		err = vncrdstring(v);
-		werrstr("%s", err);
-		if(verbose)
-			fprint(2, "auth failed: %s\n", err);
-		return -1;
-
-	case ANoAuth:
-		if(v->vers == 38){
-			vncwrchar(v, auth);
-			vncflush(v);
-		}
-		if(verbose)
-			fprint(2, "no auth needed\n");
-		break;
-
-	case AVncAuth:
-		if(v->vers == 38){
-			vncwrchar(v, auth);
-			vncflush(v);
-		}
-
-		vncrdbytes(v, chal, VncChalLen);
-		if(auth_respond(chal, VncChalLen, nil, 0, chal, VncChalLen, auth_getkey,
-			"proto=vnc role=client server=%s %s", v->srvaddr, keypattern) != VncChalLen){
-			return -1;
-		}
-		vncwrbytes(v, chal, VncChalLen);
-		vncflush(v);
-		break;
-	}
-
-	/* in version 3.8 the auth status is always sent, in 3.3 and 3.7, only in AVncAuth */
-	if(v->vers == 38 || auth == AVncAuth){
-		auth = vncrdlong(v); /* auth status */
-		switch(auth){
-		default:
-			werrstr("unknown server response 0x%lux", auth);
-			return -1;
-		case VncAuthFailed:
-			err = (v->vers == 38) ? vncrdstring(v) : "rejected";
-			werrstr("%s", err);
-			if(verbose)
-				fprint(2, "auth failed: %s\n", err);
-			return -1;
-		case VncAuthTooMany:
-			werrstr("server says too many tries");
-			return -1;
-		case VncAuthOK:
-			break;
-		}
-	}
-	return 0;
-}
-
-int
-vncsrvauth(Vnc *v)
-{
-	Chalstate *c;
-	AuthInfo *ai;
-
-	if((c = auth_challenge("proto=vnc role=server user=%q", getuser()))==nil)
-		sysfatal("vncchal: %r");
-	if(c->nchal != VncChalLen)
-		sysfatal("vncchal got %d bytes wanted %d", c->nchal, VncChalLen);
-	vncwrlong(v, AVncAuth);
-	vncwrbytes(v, c->chal, VncChalLen);
-	vncflush(v);
-
-	vncrdbytes(v, c->chal, VncChalLen);
-	c->resp = c->chal;
-	c->nresp = VncChalLen;
-	ai = auth_response(c);
-	auth_freechal(c);
-	if(ai == nil){
-		fprint(2, "vnc auth failed: server factotum: %r\n");
-		vncwrlong(v, VncAuthFailed);
-		vncflush(v);
-		return -1;
-	}
-	auth_freeAI(ai);
-	vncwrlong(v, VncAuthOK);
-	vncflush(v);
-
-	return 0;
-}
-
--- a/sys/src/cmd/vnc/chan.c
+++ /dev/null
@@ -1,203 +1,0 @@
-#include	<u.h>
-#include	<libc.h>
-#include	"compat.h"
-#include	"error.h"
-
-Chan*
-newchan(void)
-{
-	Chan *c;
-
-	c = smalloc(sizeof(Chan));
-
-	/* if you get an error before associating with a dev,
-	   close calls rootclose, a nop */
-	c->type = 0;
-	c->flag = 0;
-	c->ref = 1;
-	c->dev = 0;
-	c->offset = 0;
-	c->iounit = 0;
-	c->aux = 0;
-	c->name = 0;
-	return c;
-}
-
-void
-chanfree(Chan *c)
-{
-	c->flag = CFREE;
-
-	cnameclose(c->name);
-	free(c);
-}
-
-void
-cclose(Chan *c)
-{
-	if(c->flag&CFREE)
-		panic("cclose %#p", getcallerpc(&c));
-	if(decref(c))
-		return;
-
-	if(!waserror()){
-		devtab[c->type]->close(c);
-		poperror();
-	}
-
-	chanfree(c);
-}
-
-Chan*
-cclone(Chan *c)
-{
-	Chan *nc;
-	Walkqid *wq;
-
-	wq = devtab[c->type]->walk(c, nil, nil, 0);
-	if(wq == nil)
-		error("clone failed");
-	nc = wq->clone;
-	free(wq);
-	nc->name = c->name;
-	if(c->name)
-		incref(c->name);
-	return nc;
-}
-
-enum
-{
-	CNAMESLOP	= 20
-};
-
-static Ref ncname;
-
-void cleancname(Cname*);
-
-int
-isdotdot(char *p)
-{
-	return p[0]=='.' && p[1]=='.' && p[2]=='\0';
-}
-
-int
-incref(Ref *r)
-{
-	int x;
-
-	lock(r);
-	x = ++r->ref;
-	unlock(r);
-	return x;
-}
-
-int
-decref(Ref *r)
-{
-	int x;
-
-	lock(r);
-	x = --r->ref;
-	unlock(r);
-	if(x < 0)
-		panic("decref");
-
-	return x;
-}
-
-Cname*
-newcname(char *s)
-{
-	Cname *n;
-	int i;
-
-	n = smalloc(sizeof(Cname));
-	i = strlen(s);
-	n->len = i;
-	n->alen = i+CNAMESLOP;
-	n->s = smalloc(n->alen);
-	memmove(n->s, s, i+1);
-	n->ref = 1;
-	incref(&ncname);
-	return n;
-}
-
-void
-cnameclose(Cname *n)
-{
-	if(n == nil)
-		return;
-	if(decref(n))
-		return;
-	decref(&ncname);
-	free(n->s);
-	free(n);
-}
-
-Cname*
-addelem(Cname *n, char *s)
-{
-	int i, a;
-	char *t;
-	Cname *new;
-
-	if(s[0]=='.' && s[1]=='\0')
-		return n;
-
-	if(n->ref > 1){
-		/* copy on write */
-		new = newcname(n->s);
-		cnameclose(n);
-		n = new;
-	}
-
-	i = strlen(s);
-	if(n->len+1+i+1 > n->alen){
-		a = n->len+1+i+1 + CNAMESLOP;
-		t = smalloc(a);
-		memmove(t, n->s, n->len+1);
-		free(n->s);
-		n->s = t;
-		n->alen = a;
-	}
-	if(n->len>0 && n->s[n->len-1]!='/' && s[0]!='/')	/* don't insert extra slash if one is present */
-		n->s[n->len++] = '/';
-	memmove(n->s+n->len, s, i+1);
-	n->len += i;
-	if(isdotdot(s))
-		cleancname(n);
-	return n;
-}
-
-/*
- * In place, rewrite name to compress multiple /, eliminate ., and process ..
- */
-void
-cleancname(Cname *n)
-{
-	char *p;
-
-	if(n->s[0] == '#'){
-		p = strchr(n->s, '/');
-		if(p == nil)
-			return;
-		cleanname(p);
-
-		/*
-		 * The correct name is #i rather than #i/,
-		 * but the correct name of #/ is #/.
-		 */
-		if(strcmp(p, "/")==0 && n->s[1] != '/')
-			*p = '\0';
-	}else
-		cleanname(n->s);
-	n->len = strlen(n->s);
-}
-
-void
-isdir(Chan *c)
-{
-	if(c->qid.type & QTDIR)
-		return;
-	error(Enotdir);
-}
--- a/sys/src/cmd/vnc/color.c
+++ /dev/null
@@ -1,194 +1,0 @@
-#include "vnc.h"
-#include "vncv.h"
-
-enum {
-	RGB12 = CHAN4(CIgnore, 4, CRed, 4, CGreen, 4, CBlue, 4),
-	BGR12 = CHAN4(CIgnore, 4, CBlue, 4, CGreen, 4, CRed, 4),
-	BGR8 = CHAN3(CBlue, 2, CGreen, 3, CRed, 3),
-};
-
-void (*cvtpixels)(uchar*, uchar*, int);
-
-static void
-chan2fmt(Pixfmt *fmt, ulong chan)
-{
-	ulong c, rc, shift;
-
-	shift = 0;
-	for(rc = chan; rc; rc >>=8){
-		c = rc & 0xFF;
-		switch(TYPE(c)){
-		case CRed:
-			fmt->red = (Colorfmt){(1<<NBITS(c))-1, shift};
-			break;
-		case CBlue:
-			fmt->blue = (Colorfmt){(1<<NBITS(c))-1, shift};
-			break;
-		case CGreen:
-			fmt->green = (Colorfmt){(1<<NBITS(c))-1, shift};
-			break;
-		}
-		shift += NBITS(c);
-	}
-}
-
-/*
- * convert 32-bit data to 24-bit data by skipping
- * the last of every four bytes.  we skip the last
- * because we keep the server in little endian mode.
- */
-static void
-cvt32to24(uchar *dst, uchar *src, int npixel)
-{
-	int i;
-
-	for(i=0; i<npixel; i++){
-		*dst++ = *src++;
-		*dst++ = *src++;
-		*dst++ = *src++;
-		src++;
-	}
-}
-
-/*
- * convert RGB12 (x4r4g4b4) into CMAP8
- */
-static uchar rgb12[16*16*16];
-static void
-mkrgbtab(void)
-{
-	int r, g, b;
-
-	for(r=0; r<16; r++)
-	for(g=0; g<16; g++)
-	for(b=0; b<16; b++)
-		rgb12[r*256+g*16+b] = rgb2cmap(r*0x11, g*0x11, b*0x11);
-}
-
-static void
-cvtrgb12tocmap8(uchar *dst, uchar *src, int npixel)
-{
-	int i, s;
-
-	for(i=0; i<npixel; i++){
-		s = (src[0] | (src[1]<<8)) & 0xFFF;
-		*dst++ = rgb12[s];
-		src += 2;
-	}
-}
-
-/*
- * convert BGR8 (b2g3r3, default VNC format) to CMAP8 
- * some bits are lost.
- */
-static uchar bgr8[256];
-static void
-mkbgrtab(void)
-{
-	int i, r, g, b;
-
-	for(i=0; i<256; i++){
-		b = i>>6;
-		b = (b<<6)|(b<<4)|(b<<2)|b;
-		g = (i>>3) & 7;
-		g = (g<<5)|(g<<2)|(g>>1);
-		r = i & 7;
-		r = (r<<5)|(r<<2)|(r>>1);
-		bgr8[i] = rgb2cmap(r, g, b);
-	}
-}
-
-static void
-cvtbgr332tocmap8(uchar *dst, uchar *src, int npixel)
-{
-	uchar *ed;
-
-	ed = dst+npixel;
-	while(dst < ed)
-		*dst++ = bgr8[*src++];
-}
-
-static void
-cvt16to32(uchar *dst, uchar *src, int npixel)
-{
-	uchar *ed;
-	int w, r, g, b;
-
-	ed = dst+npixel*4;
-	while(dst < ed){
-		w = src[1]<<8 | src[0];
-		b = (w >> 11) & 0x1F;
-		g = (w >> 5) & 0x3F;
-		r = (w >> 0) & 0x1F;
-		dst[0] = b<<(8-5);
-		dst[1] = g<<(8-6);
-		dst[2] = r<<(8-5);
-		dst += 4;
-		src += 2;
-	}
-}
-
-void
-choosecolor(Vnc *v)
-{
-	int bpp, depth;
-	ulong chan;
-
-	chan = screen->chan;
-	depth = screen->depth;
-	bpp = depth;
-	if((bpp / 8) * 8 != bpp)
-		sysfatal("screen not supported");
-/*
-	if(bpp == 32 && v->Pixfmt.bpp == 16){
-		cvtpixels = cvt16to32;
-		goto Done;
-	}
-*/
-	if(bpp == 24){
-		if(verbose)
-			fprint(2, "24bit emulation using 32bpp\n");
-		bpp = 32;
-		cvtpixels = cvt32to24;
-	}
-
-	if(chan == CMAP8){
-		if(bpp12){
-			if(verbose)
-				fprint(2, "8bit emulation using 12bpp\n");
-			bpp = 16;
-			depth = 12;
-			chan = RGB12;
-			cvtpixels = cvtrgb12tocmap8;
-			mkrgbtab();
-		}else{
-			if(verbose)
-				fprint(2, "8bit emulation using 6bpp\n");	/* 6: we throw away 1 r, g bit */
-			bpp = 8;
-			depth = 8;
-			chan = BGR8;
-			cvtpixels = cvtbgr332tocmap8;
-			mkbgrtab();
-		}
-	}
-
-	v->bpp = bpp;
-	v->depth = depth;
-	v->truecolor = 1;
-	v->bigendian = 0;
-	chan2fmt(v, chan);
-	if(v->red.max == 0 || v->green.max == 0 || v->blue.max == 0)
-		sysfatal("screen not supported");
-
-Done:
-	if(verbose)
-		fprint(2, "%d bpp, %d depth, 0x%lx chan, %d truecolor, %d bigendian\n",
-			v->bpp, v->depth, screen->chan, v->truecolor, v->bigendian);
-
-	/* send information to server */
-	vncwrchar(v, MPixFmt);
-	vncwrchar(v, 0);	/* padding */
-	vncwrshort(v, 0);
-	vncwrpixfmt(v, &v->Pixfmt);
-	vncflush(v);
-}
--- a/sys/src/cmd/vnc/compat.c
+++ /dev/null
@@ -1,250 +1,0 @@
-#include	<u.h>
-#include	<libc.h>
-#include	"compat.h"
-#include	"error.h"
-
-#include	"errstr.h"
-
-ulong	kerndate;
-Proc	**privup;
-char	*eve;
-extern void *mainmem;
-
-void
-_assert(char *fmt)
-{
-	panic("assert failed: %s", fmt);
-}
-
-int
-errdepth(int ed)
-{
-	if(ed >= 0 && up->nerrlab != ed)
-		panic("unbalanced error depth: expected %d got %d\n", ed, up->nerrlab);
-	return up->nerrlab;
-}
-
-void
-newup(char *name)
-{
-	up = smalloc(sizeof(Proc));
-	up->user = eve;
-	strncpy(up->name, name, KNAMELEN-1);
-	up->name[KNAMELEN-1] = '\0';
-}
-
-void
-kproc(char *name, void (*f)(void *), void *a)
-{
-	int pid;
-
-	pid = rfork(RFPROC|RFMEM|RFNOWAIT);
-	switch(pid){
-	case -1:
-		panic("can't make new thread: %r");
-	case 0:
-		break;
-	default:
-		return;
-	}
-
-	newup(name);
-	if(!waserror())
-		(*f)(a);
-	_exits(nil);
-}
-
-void
-kexit(void)
-{
-	_exits(nil);
-}
-
-void
-initcompat(void)
-{
-	rfork(RFREND);
-	privup = privalloc();
-	kerndate = seconds();
-	eve = getuser();
-	newup("main");
-}
-
-int
-openmode(ulong o)
-{
-	o &= ~(OTRUNC|OCEXEC|ORCLOSE);
-	if(o > OEXEC)
-		error(Ebadarg);
-	if(o == OEXEC)
-		return OREAD;
-	return o;
-}
-
-void
-panic(char *fmt, ...)
-{
-	char buf[512];
-	char buf2[512];
-	va_list va;
-
-	va_start(va, fmt);
-	vseprint(buf, buf+sizeof(buf), fmt, va);
-	va_end(va);
-	sprint(buf2, "panic: %s\n", buf);
-	write(2, buf2, strlen(buf2));
-
-	exits("error");
-}
-
-void*
-smalloc(ulong n)
-{
-	void *p;
-
-	p = mallocz(n, 1);
-	if(p == nil)
-		panic("out of memory");
-	setmalloctag(p, getcallerpc(&n));
-	return p;
-}
-
-long
-seconds(void)
-{
-	return time(nil);
-}
-
-void
-error(char *err)
-{
-	strncpy(up->error, err, ERRMAX);
-	nexterror();
-}
-
-void
-nexterror(void)
-{
-	longjmp(up->errlab[--up->nerrlab], 1);
-}
-
-int
-readstr(ulong off, char *buf, ulong n, char *str)
-{
-	int size;
-
-	size = strlen(str);
-	if(off >= size)
-		return 0;
-	if(off+n > size)
-		n = size-off;
-	memmove(buf, str+off, n);
-	return n;
-}
-
-void
-_rendsleep(void* tag)
-{
-	void *value;
-
-	for(;;){
-		value = rendezvous(tag, (void*)0x22a891b8);
-		if(value == (void*)0x7f7713f9)
-			break;
-		if(tag != (void*)~0)
-			panic("_rendsleep: rendezvous mismatch");
-	}
-}
-
-void
-_rendwakeup(void* tag)
-{
-	void *value;
-
-	for(;;){
-		value = rendezvous(tag, (void*)0x7f7713f9);
-		if(value == (void*)0x22a891b8)
-			break;
-		if(tag != (void*)~0)
-			panic("_rendwakeup: rendezvous mismatch");
-	}
-}
-
-void
-rendsleep(Rendez *r, int (*f)(void*), void *arg)
-{
-	lock(&up->rlock);
-	up->r = r;
-	unlock(&up->rlock);
-
-	lock(r);
-
-	/*
-	 * if condition happened, never mind
-	 */
-	if(up->intr || f(arg)){
-		unlock(r);
-		goto Done;
-	}
-
-	/*
-	 * now we are committed to
-	 * change state and call scheduler
-	 */
-	if(r->p)
-		panic("double sleep");
-	r->p = up;
-	unlock(r);
-
-	_rendsleep(r);
-
-Done:
-	lock(&up->rlock);
-	up->r = 0;
-	if(up->intr){
-		up->intr = 0;
-		unlock(&up->rlock);
-		error(Eintr);
-	}
-	unlock(&up->rlock);
-}
-
-int
-rendwakeup(Rendez *r)
-{
-	Proc *p;
-	int rv;
-
-	lock(r);
-	p = r->p;
-	rv = 0;
-	if(p){
-		r->p = nil;
-		_rendwakeup(r);
-		rv = 1;
-	}
-	unlock(r);
-	return rv;
-}
-
-void
-rendintr(void *v)
-{
-	Proc *p;
-
-	p = v;
-	lock(&p->rlock);
-	p->intr = 1;
-	if(p->r)
-		rendwakeup(p->r);
-	unlock(&p->rlock);
-}
-
-void
-rendclearintr(void)
-{
-	lock(&up->rlock);
-	up->intr = 0;
-	unlock(&up->rlock);
-}
-
--- a/sys/src/cmd/vnc/compat.h
+++ /dev/null
@@ -1,168 +1,0 @@
-#define Rendez KRendez
-
-typedef struct Block	Block;
-typedef struct Chan	Chan;
-typedef struct Cname	Cname;
-typedef struct Dev	Dev;
-typedef struct Dirtab	Dirtab;
-typedef struct Proc	Proc;
-typedef struct Ref	Ref;
-typedef struct Rendez	Rendez;
-typedef struct Walkqid Walkqid;
-typedef int    Devgen(Chan*, Dirtab*, int, int, Dir*);
-
-enum
-{
-	KNAMELEN	= 28,
-	NERR		= 15,
-
-	COPEN		= 0x0001,		/* for i/o */
-	CFREE		= 0x0010,		/* not in use */
-};
-
-struct Ref
-{
-	Lock;
-	int	ref;
-};
-
-struct Rendez
-{
-	Lock;
-	Proc	*p;
-};
-
-struct Chan
-{
-	Ref;
-	Chan*	next;			/* allocation */
-	Chan*	link;
-	vlong	offset;			/* in file */
-	ushort	type;
-	ulong	dev;
-	ushort	mode;			/* read/write */
-	ushort	flag;
-	Qid	qid;
-	int	fid;			/* for devmnt */
-	ulong	iounit;			/* chunk size for i/o; 0==default */
-	void*	aux;
-	Cname	*name;
-};
-
-struct Cname
-{
-	Ref;
-	int	alen;			/* allocated length */
-	int	len;			/* strlen(s) */
-	char	*s;
-};
-
-struct Dev
-{
-	int	dc;
-	char*	name;
-
-	void	(*reset)(void);
-	void	(*init)(void);
-	Chan*	(*attach)(char*);
-	Walkqid*	(*walk)(Chan*, Chan*, char**, int);
-	int	(*stat)(Chan*, uchar*, int);
-	Chan*	(*open)(Chan*, int);
-	void	(*create)(Chan*, char*, int, ulong);
-	void	(*close)(Chan*);
-	long	(*read)(Chan*, void*, long, vlong);
-	Block*	(*bread)(Chan*, long, ulong);
-	long	(*write)(Chan*, void*, long, vlong);
-	long	(*bwrite)(Chan*, Block*, ulong);
-	void	(*remove)(Chan*);
-	int	(*wstat)(Chan*, uchar*, int);
-};
-
-struct Dirtab
-{
-	char	name[KNAMELEN];
-	Qid	qid;
-	vlong length;
-	long	perm;
-};
-
-struct Walkqid
-{
-	Chan	*clone;
-	int	nqid;
-	Qid	qid[1];
-};
-
-struct Proc
-{
-	Lock	rlock;		/* for rendsleep, rendwakeup, intr */
-	Rendez	*r;
-	int	intr;
-
-	char	name[KNAMELEN];
-	char	*user;
-	char	error[ERRMAX];
-	int	nerrlab;
-	jmp_buf	errlab[NERR];
-	char	genbuf[128];	/* buffer used e.g. for last name element from namec */
-};
-
-#define DEVDOTDOT -1
-
-extern	Proc	**privup;
-#define	up	(*privup)
-extern  char	*eve;
-extern	Dev*	devtab[];
-
-Chan*		cclone(Chan*);
-void		cclose(Chan*);
-void		cnameclose(Cname*);
-int		decref(Ref*);
-Chan*		devattach(int, char*);
-Block*		devbread(Chan*, long, ulong);
-long		devbwrite(Chan*, Block*, ulong);
-void		devcreate(Chan*, char*, int, ulong);
-void		devdir(Chan*, Qid, char*, vlong, char*, long, Dir*);
-long		devdirread(Chan*, char*, long, Dirtab*, int, Devgen*);
-Devgen		devgen;
-void		devinit(void);
-Chan*		devopen(Chan*, int, Dirtab*, int, Devgen*);
-void		devremove(Chan*);
-void		devreset(void);
-int		devstat(Chan*, uchar*, int, Dirtab*, int, Devgen*);
-Walkqid*		devwalk(Chan*, Chan*, char**, int, Dirtab*, int, Devgen*);
-int		devwstat(Chan*, uchar*, int);
-void		error(char*);
-int		incref(Ref*);
-void		isdir(Chan*);
-void		kproc(char*, void(*)(void*), void*);
-void		mkqid(Qid*, vlong, ulong, int);
-void		nexterror(void);
-Chan*		newchan(void);
-Cname*		newcname(char*);
-int		openmode(ulong);
-void		panic(char*, ...);
-int		readstr(ulong, char*, ulong, char*);
-long		seconds(void);
-void*		smalloc(ulong);
-
-#define		poperror()	up->nerrlab--
-#define		waserror()	(up->nerrlab++, setjmp(up->errlab[up->nerrlab-1]))
-
-void		initcompat(void);
-void		rendintr(void *v);
-void		rendclearintr(void);
-void		rendsleep(Rendez*, int(*)(void*), void*);
-int		rendwakeup(Rendez*);
-void		kexit(void);
-int		sysexport(int fd, Chan **roots, int nroots);
-int		errdepth(int ed);
-void		newup(char *name);
-
-int		exporter(Dev**, int*, int*);
-int		mounter(char *mntpt, int how, int fds, int n);
-void		shutdown(void);
-
-void		screeninit(int, int, char*);
-
-#pragma	varargck	argpos	panic		1
--- a/sys/src/cmd/vnc/dev.c
+++ /dev/null
@@ -1,339 +1,0 @@
-#include	<u.h>
-#include	<libc.h>
-#include	<fcall.h>
-#include	"compat.h"
-#include	"error.h"
-
-extern ulong	kerndate;
-
-void
-mkqid(Qid *q, vlong path, ulong vers, int type)
-{
-	q->type = type;
-	q->vers = vers;
-	q->path = path;
-}
-
-int
-devno(int c, int user)
-{
-	int i;
-
-	for(i = 0; devtab[i] != nil; i++){
-		if(devtab[i]->dc == c)
-			return i;
-	}
-	if(user == 0)
-		panic("devno %C 0x%ux", c, c);
-
-	return -1;
-}
-
-void
-devdir(Chan *c, Qid qid, char *n, vlong length, char *user, long perm, Dir *db)
-{
-	db->name = n;
-	db->qid = qid;
-	db->type = devtab[c->type]->dc;
-	db->dev = c->dev;
-	db->mode = (qid.type << 24) | perm;
-	db->atime = seconds();
-	db->mtime = kerndate;
-	db->length = length;
-	db->uid = user;
-	db->gid = eve;
-	db->muid = user;
-}
-
-/*
- * the zeroth element of the table MUST be the directory itself for ..
-*/
-int
-devgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp)
-{
-	if(tab == 0)
-		return -1;
-	if(i != DEVDOTDOT){
-		i++; /* skip first element for . itself */
-		if(i >= ntab)
-			return -1;
-		tab += i;
-	}
-	devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
-	return 1;
-}
-
-void
-devreset(void)
-{
-}
-
-void
-devinit(void)
-{
-}
-
-Chan*
-devattach(int tc, char *spec)
-{
-	Chan *c;
-	char *buf;
-
-	c = newchan();
-	mkqid(&c->qid, 0, 0, QTDIR);
-	c->type = devno(tc, 0);
-	if(spec == nil)
-		spec = "";
-	buf = smalloc(4+strlen(spec)+1);
-	sprint(buf, "#%C%s", tc, spec);
-	c->name = newcname(buf);
-	free(buf);
-	return c;
-}
-
-
-Chan*
-devclone(Chan *c)
-{
-	Chan *nc;
-
-	if(c->flag & COPEN)
-		panic("clone of open file type %C\n", devtab[c->type]->dc);
-
-	nc = newchan();
-
-	nc->type = c->type;
-	nc->dev = c->dev;
-	nc->mode = c->mode;
-	nc->qid = c->qid;
-	nc->offset = c->offset;
-	nc->aux = c->aux;
-	return nc;
-}
-
-Walkqid*
-devwalk(Chan *c, Chan *nc, char **name, int nname, Dirtab *tab, int ntab, Devgen *gen)
-{
-	int i, j, alloc;
-	Walkqid *wq;
-	char *n;
-	Dir dir;
-
-	isdir(c);
-
-	alloc = 0;
-	wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
-	if(waserror()){
-		if(alloc && wq->clone!=nil)
-			cclose(wq->clone);
-		free(wq);
-		return nil;
-	}
-	if(nc == nil){
-		nc = devclone(c);
-		nc->type = 0;	/* device doesn't know about this channel yet */
-		alloc = 1;
-	}
-	wq->clone = nc;
-
-	for(j=0; j<nname; j++){
-		isdir(nc);
-		n = name[j];
-		if(strcmp(n, ".") == 0){
-    Accept:
-			wq->qid[wq->nqid++] = nc->qid;
-			continue;
-		}
-		if(strcmp(n, "..") == 0){
-			(*gen)(nc, tab, ntab, DEVDOTDOT, &dir);
-			nc->qid = dir.qid;
-			goto Accept;
-		}
-		for(i=0;; i++){
-			switch((*gen)(nc, tab, ntab, i, &dir)){
-			case -1:
-				if(j == 0)
-					error(Enonexist);
-				strncpy(up->error, Enonexist, ERRMAX);
-				goto Done;
-			case 0:
-				continue;
-			case 1:
-				if(strcmp(n, dir.name) == 0){
-					nc->qid = dir.qid;
-					goto Accept;
-				}
-				continue;
-			}
-		}
-	}
-	/*
-	 * We processed at least one name, so will return some data.
-	 * If we didn't process all nname entries succesfully, we drop
-	 * the cloned channel and return just the Qids of the walks.
-	 */
-Done:
-	poperror();
-	if(wq->nqid < nname){
-		if(alloc)
-			cclose(wq->clone);
-		wq->clone = nil;
-	}else if(wq->clone){
-		/* attach cloned channel to same device */
-		wq->clone->type = c->type;
-	}
-	return wq;
-}
-
-int
-devstat(Chan *c, uchar *db, int n, Dirtab *tab, int ntab, Devgen *gen)
-{
-	int i;
-	Dir dir;
-	char *p, *elem;
-
-	for(i=0;; i++)
-		switch((*gen)(c, tab, ntab, i, &dir)){
-		case -1:
-			if(c->qid.type & QTDIR){
-				if(c->name == nil)
-					elem = "???";
-				else if(strcmp(c->name->s, "/") == 0)
-					elem = "/";
-				else
-					for(elem=p=c->name->s; *p; p++)
-						if(*p == '/')
-							elem = p+1;
-				devdir(c, c->qid, elem, 0, eve, DMDIR|0555, &dir);
-				return convD2M(&dir, db, n);
-			}
-
-			error(Enonexist);
-		case 0:
-			break;
-		case 1:
-			if(c->qid.path == dir.qid.path){
-				return convD2M(&dir, db, n);
-			}
-			break;
-		}
-}
-
-long
-devdirread(Chan *c, char *d, long n, Dirtab *tab, int ntab, Devgen *gen)
-{
-	long k, m, dsz;
-	struct{
-		Dir;
-		char slop[100];
-	}dir;
-
-	k = c->offset;
-	for(m=0; m<n; k++){
-		switch((*gen)(c, tab, ntab, k, &dir)){
-		case -1:
-			return m;
-
-		case 0:
-			c->offset++;	/* BUG??? (was DIRLEN: skip entry) */
-			break;
-
-		case 1:
-			dsz = convD2M(&dir, (uchar*)d, n-m);
-			if(dsz <= BIT16SZ){	/* <= not < because this isn't stat; read is stuck */
-				if(m == 0)
-					return -1;
-				return m;
-			}
-			m += dsz;
-			d += dsz;
-			break;
-		}
-	}
-
-	return m;
-}
-
-/*
- * error(Eperm) if open permission not granted for up->user.
- */
-void
-devpermcheck(char *fileuid, ulong perm, int omode)
-{
-	ulong t;
-	static int access[] = { 0400, 0200, 0600, 0100 };
-
-	if(strcmp(up->user, fileuid) == 0)
-		perm <<= 0;
-	else
-	if(strcmp(up->user, eve) == 0)
-		perm <<= 3;
-	else
-		perm <<= 6;
-
-	t = access[omode&3];
-	if((t&perm) != t)
-		error(Eperm);
-}
-
-Chan*
-devopen(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen)
-{
-	int i;
-	Dir dir;
-
-	for(i=0;; i++){
-		switch((*gen)(c, tab, ntab, i, &dir)){
-		case -1:
-			goto Return;
-		case 0:
-			break;
-		case 1:
-			if(c->qid.path == dir.qid.path){
-				devpermcheck(dir.uid, dir.mode, omode);
-				goto Return;
-			}
-			break;
-		}
-	}
-Return:
-	c->offset = 0;
-	if((c->qid.type&QTDIR) && omode!=OREAD)
-		error(Eperm);
-	c->mode = openmode(omode);
-	c->flag |= COPEN;
-	return c;
-}
-
-void
-devcreate(Chan*, char*, int, ulong)
-{
-	error(Eperm);
-}
-
-Block*
-devbread(Chan *, long, ulong)
-{
-	panic("no block read");
-	return nil;
-}
-
-long
-devbwrite(Chan *, Block *, ulong)
-{
-	panic("no block write");
-	return 0;
-}
-
-void
-devremove(Chan*)
-{
-	error(Eperm);
-}
-
-int
-devwstat(Chan*, uchar*, int)
-{
-	error(Eperm);
-	return 0;
-}
--- a/sys/src/cmd/vnc/devcons.c
+++ /dev/null
@@ -1,186 +1,0 @@
-#include	<u.h>
-#include	<libc.h>
-#include	"compat.h"
-#include	"kbd.h"
-#include	"error.h"
-
-Snarf	snarf = {
-	.vers =	1
-};
-
-enum{
-	Qdir,
-	Qcons,
-	Qconsctl,
-	Qsnarf,
-};
-
-static Dirtab consdir[]={
-	".",		{Qdir, 0, QTDIR},	0,		DMDIR|0555,
-	"cons",		{Qcons},	0,		0660,
-	"consctl",	{Qconsctl},	0,		0220,
-	"snarf",	{Qsnarf},	0,		0600,
-};
-
-static Chan*
-consattach(char *spec)
-{
-	return devattach('c', spec);
-}
-
-static Walkqid*
-conswalk(Chan *c, Chan *nc, char **name, int nname)
-{
-	return devwalk(c, nc, name,nname, consdir, nelem(consdir), devgen);
-}
-
-static int
-consstat(Chan *c, uchar *dp, int n)
-{
-	return devstat(c, dp, n, consdir, nelem(consdir), devgen);
-}
-
-static Chan*
-consopen(Chan *c, int omode)
-{
-	c->aux = nil;
-	c = devopen(c, omode, consdir, nelem(consdir), devgen);
-	switch((ulong)c->qid.path){
-	case Qconsctl:
-		break;
-	case Qsnarf:
-		if((c->mode&3) == OWRITE || (c->mode&3) == ORDWR)
-			c->aux = smalloc(sizeof(Snarf));
-		break;
-	}
-	return c;
-}
-
-void
-setsnarf(char *buf, int n, int *vers)
-{
-	int i;
-
-	qlock(&snarf);
-	snarf.vers++;
-	if(vers)
-		*vers = snarf.vers;	
-	for(i = 0; i < nelem(consdir); i++){
-		if(consdir[i].qid.type == Qsnarf){
-			consdir[i].qid.vers = snarf.vers;
-			break;
-		}
-	}
-	free(snarf.buf);
-	snarf.n = n;
-	snarf.buf = buf;
-	qunlock(&snarf);
-}
-
-static void
-consclose(Chan *c)
-{
-	Snarf *t;
-
-	switch((ulong)c->qid.path){
-	/* last close of control file turns off raw */
-	case Qconsctl:
-		break;
-	/* odd behavior but really ok: replace snarf buffer when /dev/snarf is closed */
-	case Qsnarf:
-		t = c->aux;
-		if(t == nil)
-			break;
-		setsnarf(t->buf, t->n, 0);
-		t->buf = nil;	/* setsnarf took it */
-		free(t);
-		c->aux = nil;
-		break;
-	}
-}
-
-static long
-consread(Chan *c, void *buf, long n, vlong off)
-{
-	if(n <= 0)
-		return n;
-	switch((ulong)c->qid.path){
-	case Qsnarf:
-		qlock(&snarf);
-		if(off < snarf.n){
-			if(off + n > snarf.n)
-				n = snarf.n - off;
-			memmove(buf, snarf.buf+off, n);
-		}else
-			n = 0;
-		qunlock(&snarf);
-		return n;
-
-	case Qdir:
-		return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
-
-	case Qcons:
-		error(Egreg);
-		return -1;
-
-	default:
-		print("consread 0x%llux\n", c->qid.path);
-		error(Egreg);
-	}
-	return -1;		/* never reached */
-}
-
-static long
-conswrite(Chan *c, void *va, long n, vlong)
-{
-	Snarf *t;
-	char *a;
-
-	switch((ulong)c->qid.path){
-	case Qcons:
-		screenputs(va, n);
-		break;
-
-	case Qconsctl:
-		error(Egreg);
-		break;
-
-	case Qsnarf:
-		t = c->aux;
-		/* always append only */
-		if(t->n > MAXSNARF)	/* avoid thrashing when people cut huge text */
-			error("snarf buffer too big");
-		a = realloc(t->buf, t->n + n + 1);
-		if(a == nil)
-			error("snarf buffer too big");
-		t->buf = a;
-		memmove(t->buf+t->n, va, n);
-		t->n += n;
-		t->buf[t->n] = '\0';
-		break;
-	default:
-		print("conswrite: 0x%llux\n", c->qid.path);
-		error(Egreg);
-	}
-	return n;
-}
-
-Dev consdevtab = {
-	'c',
-	"cons",
-
-	devreset,
-	devinit,
-	consattach,
-	conswalk,
-	consstat,
-	consopen,
-	devcreate,
-	consclose,
-	consread,
-	devbread,
-	conswrite,
-	devbwrite,
-	devremove,
-	devwstat,
-};
--- a/sys/src/cmd/vnc/devdraw.c
+++ /dev/null
@@ -1,2134 +1,0 @@
-#include	<u.h>
-#include	<libc.h>
-#include	"compat.h"
-#include	"error.h"
-
-#define	Image	IMAGE
-#include	<draw.h>
-#include	<memdraw.h>
-#include	<memlayer.h>
-#include	<cursor.h>
-#include	"screen.h"
-
-enum
-{
-	Qtopdir		= 0,
-	Qnew,
-	Qwinname,
-	Q3rd,
-	Q2nd,
-	Qcolormap,
-	Qctl,
-	Qdata,
-	Qrefresh,
-};
-
-/*
- * Qid path is:
- *	 4 bits of file type (qids above)
- *	24 bits of mux slot number +1; 0 means not attached to client
- */
-#define	QSHIFT	4	/* location in qid of client # */
-
-#define	QID(q)		((((ulong)(q).path)&0x0000000F)>>0)
-#define	CLIENTPATH(q)	((((ulong)q)&0x7FFFFFF0)>>QSHIFT)
-#define	CLIENT(q)	CLIENTPATH((q).path)
-
-#define	NHASH		(1<<5)
-#define	HASHMASK	(NHASH-1)
-
-typedef struct Client Client;
-typedef struct Draw Draw;
-typedef struct DImage DImage;
-typedef struct DScreen DScreen;
-typedef struct CScreen CScreen;
-typedef struct FChar FChar;
-typedef struct Refresh Refresh;
-typedef struct Refx Refx;
-typedef struct DName DName;
-
-struct Draw
-{
-	int		clientid;
-	int		nclient;
-	Client**	client;
-	int		nname;
-	DName*		name;
-	int		vers;
-	int		softscreen;
-};
-
-struct Client
-{
-	Ref		r;
-	DImage*		dimage[NHASH];
-	CScreen*	cscreen;
-	Refresh*	refresh;
-	Rendez		refrend;
-	QLock		refq;
-	uchar*		readdata;
-	int		nreaddata;
-	int		busy;
-	int		clientid;
-	int		slot;
-	int		refreshme;
-	int		infoid;
-	int		op;
-};
-
-struct Refresh
-{
-	DImage*		dimage;
-	Rectangle	r;
-	Refresh*	next;
-};
-
-struct Refx
-{
-	Client*		client;
-	DImage*		dimage;
-};
-
-struct DName
-{
-	char		*name;
-	Client		*client;
-	DImage*		dimage;
-	int		vers;
-};
-
-struct FChar
-{
-	int		minx;	/* left edge of bits */
-	int		maxx;	/* right edge of bits */
-	uchar		miny;	/* first non-zero scan-line */
-	uchar		maxy;	/* last non-zero scan-line + 1 */
-	schar		left;	/* offset of baseline */
-	uchar		width;	/* width of baseline */
-};
-
-/*
- * Reference counts in DImages:
- *	one per open by original client
- *	one per screen image or fill
- * 	one per image derived from this one by name
- */
-struct DImage
-{
-	int		id;
-	int		ref;
-	char		*name;
-	int		vers;
-	Memimage*	image;
-	int		ascent;
-	int		nfchar;
-	FChar*		fchar;
-	DScreen*	dscreen;	/* 0 if not a window */
-	DImage*		fromname;	/* image this one is derived from, by name */
-	DImage*		next;
-};
-
-struct CScreen
-{
-	DScreen*	dscreen;
-	CScreen*	next;
-};
-
-struct DScreen
-{
-	int		id;
-	int		public;
-	int		ref;
-	DImage		*dimage;
-	DImage		*dfill;
-	Memscreen*	screen;
-	Client*		owner;
-	DScreen*	next;
-};
-
-static	Draw		sdraw;
-	QLock	drawlock;
-
-static	Memimage	*screenimage;
-static	DImage*	screendimage;
-static	char	screenname[40];
-static	int	screennameid;
-
-static	Rectangle	flushrect;
-static	int		waste;
-static	DScreen*	dscreen;
-extern	void		flushmemscreen(Rectangle);
-	void		drawmesg(Client*, void*, int);
-	void		drawuninstall(Client*, int);
-	void		drawfreedimage(DImage*);
-	Client*		drawclientofpath(ulong);
-	DImage*	allocdimage(Memimage*);
-
-static	char Enodrawimage[] =	"unknown id for draw image";
-static	char Enodrawscreen[] =	"unknown id for draw screen";
-static	char Eshortdraw[] =	"short draw message";
-static	char Eshortread[] =	"draw read too short";
-static	char Eimageexists[] =	"image id in use";
-static	char Escreenexists[] =	"screen id in use";
-static	char Edrawmem[] =	"image memory allocation failed";
-static	char Ereadoutside[] =	"readimage outside image";
-static	char Ewriteoutside[] =	"writeimage outside image";
-static	char Enotfont[] =	"image not a font";
-static	char Eindex[] =		"character index out of range";
-static	char Enoclient[] =	"no such draw client";
-static	char Enameused[] =	"image name in use";
-static	char Enoname[] =	"no image with that name";
-static	char Eoldname[] =	"named image no longer valid";
-static	char Enamed[] = 	"image already has name";
-static	char Ewrongname[] = 	"wrong name for image";
-
-static void
-dlock(void)
-{
-	qlock(&drawlock);
-}
-
-static int
-candlock(void)
-{
-	return canqlock(&drawlock);
-}
-
-static void
-dunlock(void)
-{
-	qunlock(&drawlock);
-}
-
-static int
-drawgen(Chan *c, Dirtab*, int, int s, Dir *dp)
-{
-	int t;
-	Qid q;
-	ulong path;
-	Client *cl;
-
-	q.vers = 0;
-
-	if(s == DEVDOTDOT){
-		switch(QID(c->qid)){
-		case Qtopdir:
-		case Q2nd:
-			mkqid(&q, Qtopdir, 0, QTDIR);
-			devdir(c, q, "#i", 0, eve, 0500, dp);
-			break;
-		case Q3rd:
-			cl = drawclientofpath(c->qid.path);
-			if(cl == nil)
-				strcpy(up->genbuf, "??");
-			else
-				sprint(up->genbuf, "%d", cl->clientid);
-			mkqid(&q, Q2nd, 0, QTDIR);
-			devdir(c, q, up->genbuf, 0, eve, 0500, dp);
-			break;
-		default:
-			panic("drawwalk %llux", c->qid.path);
-		}
-		return 1;
-	}
-
-	/*
-	 * Top level directory contains the name of the device.
-	 */
-	t = QID(c->qid);
-	switch(t){
-	case Qtopdir:
-		if(s == 0){
-			mkqid(&q, Q2nd, 0, QTDIR);
-			devdir(c, q, "draw", 0, eve, 0555, dp);
-			return 1;
-		}
-		if(s == 1){
-	case Qwinname:
-			mkqid(&q, Qwinname, 0, QTFILE);
-			devdir(c, q, "winname", 0, eve, 0444, dp);
-			return 1;
-		}
-		return -1;
-	}
-
-	/*
-	 * Second level contains "new" plus all the clients.
-	 */
-	switch(t){
-	case Q2nd:
-		if(s == 0){
-	case Qnew:
-			mkqid(&q, Qnew, 0, QTFILE);
-			devdir(c, q, "new", 0, eve, 0666, dp);
-			return 1;
-		}
-		if(s <= sdraw.nclient){
-			cl = sdraw.client[s-1];
-			if(cl == nil)
-				return 0;
-			sprint(up->genbuf, "%d", cl->clientid);
-			mkqid(&q, (s<<QSHIFT)|Q3rd, 0, QTDIR);
-			devdir(c, q, up->genbuf, 0, eve, 0555, dp);
-			return 1;
-		}
-		return -1;
-	}
-
-	/*
-	 * Third level.
-	 */
-	path = c->qid.path&~((1<<QSHIFT)-1);	/* slot component */
-	q.vers = c->qid.vers;
-	q.type = QTFILE;
-	switch(s){
-	case 0:
-		q.path = path|Qcolormap;
-		devdir(c, q, "colormap", 0, eve, 0600, dp);
-		break;
-	case 1:
-		q.path = path|Qctl;
-		devdir(c, q, "ctl", 0, eve, 0600, dp);
-		break;
-	case 2:
-		q.path = path|Qdata;
-		devdir(c, q, "data", 0, eve, 0600, dp);
-		break;
-	case 3:
-		q.path = path|Qrefresh;
-		devdir(c, q, "refresh", 0, eve, 0400, dp);
-		break;
-	default:
-		return -1;
-	}
-	return 1;
-}
-
-static
-int
-drawrefactive(void *a)
-{
-	Client *c;
-
-	c = a;
-	return c->refreshme || c->refresh!=0;
-}
-
-static
-void
-drawrefreshscreen(DImage *l, Client *client)
-{
-	while(l != nil && l->dscreen == nil)
-		l = l->fromname;
-	if(l != nil && l->dscreen->owner != client)
-		l->dscreen->owner->refreshme = 1;
-}
-
-static
-void
-drawrefresh(Memimage*, Rectangle r, void *v)
-{
-	Refx *x;
-	DImage *d;
-	Client *c;
-	Refresh *ref;
-
-	if(v == 0)
-		return;
-	x = v;
-	c = x->client;
-	d = x->dimage;
-	for(ref=c->refresh; ref; ref=ref->next)
-		if(ref->dimage == d){
-			combinerect(&ref->r, r);
-			return;
-		}
-	ref = malloc(sizeof(Refresh));
-	if(ref){
-		ref->dimage = d;
-		ref->r = r;
-		ref->next = c->refresh;
-		c->refresh = ref;
-	}
-}
-
-static void
-addflush(Rectangle r)
-{
-	int abb, ar, anbb;
-	Rectangle nbb;
-
-	if(sdraw.softscreen==0 || screenimage == nil || !rectclip(&r, screenimage->r))
-		return;
-	if(flushrect.min.x >= flushrect.max.x){
-		flushrect = r;
-		waste = 0;
-		return;
-	}
-	/* VNC uses a region to compute the minimum bounding area.
-	 * The waste is far less than that of a bounding box. see region.c
-	 */
-	if(1){
-		flushmemscreen(flushrect);
-		flushrect = r;
-		return;
-	}
-	nbb = flushrect;
-	combinerect(&nbb, r);
-	ar = Dx(r)*Dy(r);
-	abb = Dx(flushrect)*Dy(flushrect);
-	anbb = Dx(nbb)*Dy(nbb);
-	/*
-	 * Area of new waste is area of new bb minus area of old bb,
-	 * less the area of the new segment, which we assume is not waste.
-	 * This could be negative, but that's OK.
-	 */
-	waste += anbb-abb - ar;
-	if(waste < 0)
-		waste = 0;
-	/*
-	 * absorb if:
-	 *	total area is small
-	 *	waste is less than half total area
-	 * 	rectangles touch
-	 */
-	if(anbb<=1024 || waste*2<anbb || rectXrect(flushrect, r)){
-		flushrect = nbb;
-		return;
-	}
-	/* emit current state */
-	if(flushrect.min.x < flushrect.max.x)
-		flushmemscreen(flushrect);
-	flushrect = r;
-	waste = 0;
-}
-
-static
-void
-dstflush(int dstid, Memimage *dst, Rectangle r)
-{
-	Memlayer *l;
-
-	if(dstid == 0){
-		//combinerect(&flushrect, r);
-		addflush(r); // for VNC, see comments in addflush
-		return;
-	}
-	if(screenimage == nil || dst == nil || (l = dst->layer) == nil)
-		return;
-	do{
-		if(l->screen->image->data != screenimage->data)
-			return;
-		r = rectaddpt(r, l->delta);
-		l = l->screen->image->layer;
-	}while(l);
-	addflush(r);
-}
-
-void
-drawflush(void)
-{
-	if(screenimage && flushrect.min.x < flushrect.max.x)
-		flushmemscreen(flushrect);
-	flushrect = Rect(10000, 10000, -10000, -10000);
-}
-
-static
-int
-drawcmp(char *a, char *b, int n)
-{
-	if(strlen(a) != n)
-		return 1;
-	return memcmp(a, b, n);
-}
-
-DName*
-drawlookupname(int n, char *str)
-{
-	DName *name, *ename;
-
-	name = sdraw.name;
-	ename = &name[sdraw.nname];
-	for(; name<ename; name++)
-		if(drawcmp(name->name, str, n) == 0)
-			return name;
-	return 0;
-}
-
-int
-drawgoodname(DImage *d)
-{
-	DName *n;
-
-	/* if window, validate the screen's own images */
-	if(d->dscreen)
-		if(drawgoodname(d->dscreen->dimage) == 0
-		|| drawgoodname(d->dscreen->dfill) == 0)
-			return 0;
-	if(d->name == nil)
-		return 1;
-	n = drawlookupname(strlen(d->name), d->name);
-	if(n==nil || n->vers!=d->vers)
-		return 0;
-	return 1;
-}
-
-DImage*
-drawlookup(Client *client, int id, int checkname)
-{
-	DImage *d;
-
-	d = client->dimage[id&HASHMASK];
-	while(d){
-		if(d->id == id){
-			if(checkname && !drawgoodname(d))
-				error(Eoldname);
-			return d;
-		}
-		d = d->next;
-	}
-	return 0;
-}
-
-DScreen*
-drawlookupdscreen(int id)
-{
-	DScreen *s;
-
-	s = dscreen;
-	while(s){
-		if(s->id == id)
-			return s;
-		s = s->next;
-	}
-	return 0;
-}
-
-DScreen*
-drawlookupscreen(Client *client, int id, CScreen **cs)
-{
-	CScreen *s;
-
-	s = client->cscreen;
-	while(s){
-		if(s->dscreen->id == id){
-			*cs = s;
-			return s->dscreen;
-		}
-		s = s->next;
-	}
-	error(Enodrawscreen);
-	return 0;
-}
-
-DImage*
-allocdimage(Memimage *i)
-{
-	DImage *d;
-
-	d = malloc(sizeof(DImage));
-	if(d == 0)
-		return 0;
-	d->ref = 1;
-	d->name = 0;
-	d->vers = 0;
-	d->image = i;
-	d->dscreen = 0;
-	d->nfchar = 0;
-	d->fchar = 0;
-	d->fromname = 0;
-	return d;
-}
-
-Memimage*
-drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen)
-{
-	DImage *d;
-
-	d = allocdimage(i);
-	if(d == 0)
-		return 0;
-	d->id = id;
-	d->dscreen = dscreen;
-	d->next = client->dimage[id&HASHMASK];
-	client->dimage[id&HASHMASK] = d;
-	return i;
-}
-
-Memscreen*
-drawinstallscreen(Client *client, DScreen *d, int id, DImage *dimage, DImage *dfill, int public)
-{
-	Memscreen *s;
-	CScreen *c;
-
-	c = malloc(sizeof(CScreen));
-	if(dimage && dimage->image && dimage->image->chan == 0)
-		panic("bad image %p in drawinstallscreen", dimage->image);
-
-	if(c == 0)
-		return 0;
-	if(d == 0){
-		d = malloc(sizeof(DScreen));
-		if(d == 0){
-			free(c);
-			return 0;
-		}
-		s = malloc(sizeof(Memscreen));
-		if(s == 0){
-			free(c);
-			free(d);
-			return 0;
-		}
-		s->frontmost = 0;
-		s->rearmost = 0;
-		d->dimage = dimage;
-		if(dimage){
-			s->image = dimage->image;
-			dimage->ref++;
-		}
-		d->dfill = dfill;
-		if(dfill){
-			s->fill = dfill->image;
-			dfill->ref++;
-		}
-		d->ref = 0;
-		d->id = id;
-		d->screen = s;
-		d->public = public;
-		d->next = dscreen;
-		d->owner = client;
-		dscreen = d;
-	}
-	c->dscreen = d;
-	d->ref++;
-	c->next = client->cscreen;
-	client->cscreen = c;
-	return d->screen;
-}
-
-void
-drawdelname(DName *name)
-{
-	int i;
-
-	free(name->name);
-	i = name-sdraw.name;
-	memmove(name, name+1, (sdraw.nname-(i+1))*sizeof(DName));
-	sdraw.nname--;
-}
-
-void
-drawfreedscreen(DScreen *this)
-{
-	DScreen *ds, *next;
-
-	this->ref--;
-	if(this->ref < 0)
-		print("negative ref in drawfreedscreen\n");
-	if(this->ref > 0)
-		return;
-	ds = dscreen;
-	if(ds == this){
-		dscreen = this->next;
-		goto Found;
-	}
-	while(next = ds->next){	/* assign = */
-		if(next == this){
-			ds->next = this->next;
-			goto Found;
-		}
-		ds = next;
-	}
-	error(Enodrawimage);
-
-    Found:
-	if(this->dimage)
-		drawfreedimage(this->dimage);
-	if(this->dfill)
-		drawfreedimage(this->dfill);
-	free(this->screen);
-	free(this);
-}
-
-void
-drawfreedimage(DImage *dimage)
-{
-	int i;
-	Memimage *l;
-	DScreen *ds;
-
-	dimage->ref--;
-	if(dimage->ref < 0)
-		print("negative ref in drawfreedimage\n");
-	if(dimage->ref > 0)
-		return;
-
-	/* any names? */
-	for(i=0; i<sdraw.nname; )
-		if(sdraw.name[i].dimage == dimage)
-			drawdelname(sdraw.name+i);
-		else
-			i++;
-	if(dimage->fromname){	/* acquired by name; owned by someone else*/
-		drawfreedimage(dimage->fromname);
-		goto Return;
-	}
-	ds = dimage->dscreen;
-	if(ds){
-		l = dimage->image;
-		if(screenimage && l->data == screenimage->data)
-			addflush(l->layer->screenr);
-		if(l->layer->refreshfn == drawrefresh)	/* else true owner will clean up */
-			free(l->layer->refreshptr);
-		l->layer->refreshptr = nil;
-		if(drawgoodname(dimage))
-			memldelete(l);
-		else
-			memlfree(l);
-		drawfreedscreen(ds);
-	}else
-		freememimage(dimage->image);
-    Return:
-	free(dimage->fchar);
-	free(dimage);
-}
-
-void
-drawuninstallscreen(Client *client, CScreen *this)
-{
-	CScreen *cs, *next;
-
-	cs = client->cscreen;
-	if(cs == this){
-		client->cscreen = this->next;
-		drawfreedscreen(this->dscreen);
-		free(this);
-		return;
-	}
-	while(next = cs->next){	/* assign = */
-		if(next == this){
-			cs->next = this->next;
-			drawfreedscreen(this->dscreen);
-			free(this);
-			return;
-		}
-		cs = next;
-	}
-}
-
-void
-drawuninstall(Client *client, int id)
-{
-	DImage *d, *next;
-
-	d = client->dimage[id&HASHMASK];
-	if(d == 0)
-		error(Enodrawimage);
-	if(d->id == id){
-		client->dimage[id&HASHMASK] = d->next;
-		drawfreedimage(d);
-		return;
-	}
-	while(next = d->next){	/* assign = */
-		if(next->id == id){
-			d->next = next->next;
-			drawfreedimage(next);
-			return;
-		}
-		d = next;
-	}
-	error(Enodrawimage);
-}
-
-void
-drawaddname(Client *client, DImage *di, int n, char *str)
-{
-	DName *name, *ename, *new, *t;
-
-	name = sdraw.name;
-	ename = &name[sdraw.nname];
-	for(; name<ename; name++)
-		if(drawcmp(name->name, str, n) == 0)
-			error(Enameused);
-	t = smalloc((sdraw.nname+1)*sizeof(DName));
-	memmove(t, sdraw.name, sdraw.nname*sizeof(DName));
-	free(sdraw.name);
-	sdraw.name = t;
-	new = &sdraw.name[sdraw.nname++];
-	new->name = smalloc(n+1);
-	memmove(new->name, str, n);
-	new->name[n] = 0;
-	new->dimage = di;
-	new->client = client;
-	new->vers = ++sdraw.vers;
-}
-
-Client*
-drawnewclient(void)
-{
-	Client *cl, **cp;
-	int i;
-
-	for(i=0; i<sdraw.nclient; i++){
-		cl = sdraw.client[i];
-		if(cl == 0)
-			break;
-	}
-	if(i == sdraw.nclient){
-		cp = malloc((sdraw.nclient+1)*sizeof(Client*));
-		if(cp == 0)
-			return 0;
-		memmove(cp, sdraw.client, sdraw.nclient*sizeof(Client*));
-		free(sdraw.client);
-		sdraw.client = cp;
-		sdraw.nclient++;
-		cp[i] = 0;
-	}
-	cl = malloc(sizeof(Client));
-	if(cl == 0)
-		return 0;
-	memset(cl, 0, sizeof(Client));
-	cl->slot = i;
-	cl->clientid = ++sdraw.clientid;
-	cl->op = SoverD;
-	sdraw.client[i] = cl;
-	return cl;
-}
-
-static int
-drawclientop(Client *cl)
-{
-	int op;
-
-	op = cl->op;
-	cl->op = SoverD;
-	return op;
-}
-
-int
-drawhasclients(void)
-{
-	/*
-	 * if draw has ever been used, we can't resize the frame buffer,
-	 * even if all clients have exited (nclients is cumulative); it's too
-	 * hard to make work.
-	 */
-	return sdraw.nclient != 0;
-}
-
-Client*
-drawclientofpath(ulong path)
-{
-	Client *cl;
-	int slot;
-
-	slot = CLIENTPATH(path);
-	if(slot == 0)
-		return nil;
-	cl = sdraw.client[slot-1];
-	if(cl==0 || cl->clientid==0)
-		return nil;
-	return cl;
-}
-
-
-Client*
-drawclient(Chan *c)
-{
-	Client *client;
-
-	client = drawclientofpath(c->qid.path);
-	if(client == nil)
-		error(Enoclient);
-	return client;
-}
-
-Memimage*
-drawimage(Client *client, uchar *a)
-{
-	DImage *d;
-
-	d = drawlookup(client, BGLONG(a), 1);
-	if(d == nil)
-		error(Enodrawimage);
-	return d->image;
-}
-
-void
-drawrectangle(Rectangle *r, uchar *a)
-{
-	r->min.x = BGLONG(a+0*4);
-	r->min.y = BGLONG(a+1*4);
-	r->max.x = BGLONG(a+2*4);
-	r->max.y = BGLONG(a+3*4);
-}
-
-void
-drawpoint(Point *p, uchar *a)
-{
-	p->x = BGLONG(a+0*4);
-	p->y = BGLONG(a+1*4);
-}
-
-Point
-drawchar(Memimage *dst, Memimage *rdst, Point p, Memimage *src, Point *sp, DImage *font, int index, int op)
-{
-	FChar *fc;
-	Rectangle r;
-	Point sp1;
-	static Memimage *tmp;
-
-	fc = &font->fchar[index];
-	r.min.x = p.x+fc->left;
-	r.min.y = p.y-(font->ascent-fc->miny);
-	r.max.x = r.min.x+(fc->maxx-fc->minx);
-	r.max.y = r.min.y+(fc->maxy-fc->miny);
-	sp1.x = sp->x+fc->left;
-	sp1.y = sp->y+fc->miny;
-
-	/*
-	 * If we're drawing greyscale fonts onto a VGA screen,
-	 * it's very costly to read the screen memory to do the
-	 * alpha blending inside memdraw.  If this is really a stringbg,
-	 * then rdst is the bg image (in main memory) which we can
-	 * refer to for the underlying dst pixels instead of reading dst
-	 * directly.
-	 */
-	if(ishwimage(dst) && !ishwimage(rdst) && font->image->depth > 1){
-		if(tmp == nil || tmp->chan != dst->chan || Dx(tmp->r) < Dx(r) || Dy(tmp->r) < Dy(r)){
-			if(tmp)
-				freememimage(tmp);
-			tmp = allocmemimage(Rect(0,0,Dx(r),Dy(r)), dst->chan);
-			if(tmp == nil)
-				goto fallback;
-		}
-		memdraw(tmp, Rect(0,0,Dx(r),Dy(r)), rdst, r.min, memopaque, ZP, S);
-		memdraw(tmp, Rect(0,0,Dx(r),Dy(r)), src, sp1, font->image, Pt(fc->minx, fc->miny), op);
-		memdraw(dst, r, tmp, ZP, memopaque, ZP, S);
-	}else{
-	fallback:
-		memdraw(dst, r, src, sp1, font->image, Pt(fc->minx, fc->miny), op);
-	}
-
-	p.x += fc->width;
-	sp->x += fc->width;
-	return p;
-}
-
-static DImage*
-makescreenimage(void)
-{
-	int width, depth;
-	ulong chan;
-	DImage *di;
-	Memdata *md;
-	Memimage *i;
-	Rectangle r;
-
-	if((md = attachscreen(&r, &chan, &depth, &width, &sdraw.softscreen)) == nil)
-		return nil;
-	assert(md->ref > 0);
-	if((i = allocmemimaged(r, chan, md)) == nil){
-		if(--md->ref == 0 && md->allocd)
-			free(md);
-		return nil;
-	}
-	i->width = width;
-	i->clipr = r;
-	di = allocdimage(i);
-	if(di == nil){
-		freememimage(i);	/* frees md */
-		return nil;
-	}
-	if(!waserror()){
-		snprint(screenname, sizeof screenname, "noborder.screen.%d", ++screennameid);
-		drawaddname(nil, di, strlen(screenname), screenname);
-		poperror();
-	}
-	return di;
-}
-
-static int
-initscreenimage(void)
-{
-	if(screenimage != nil)
-		return 1;
-
-	screendimage = makescreenimage();
-	if(screendimage == nil)
-		return 0;
-	screenimage = screendimage->image;
-// iprint("initscreenimage %p %p\n", screendimage, screenimage);
-	mouseresize();
-	return 1;
-}
-
-void
-deletescreenimage(void)
-{
-	dlock();
-	if(screenimage){
-		/* will be freed via screendimage; disable */
-		screenimage->clipr = ZR;
-		screenimage = nil;
-	}
-	if(screendimage){
-		drawfreedimage(screendimage);
-		screendimage = nil;
-	}
-	dunlock();
-}
-
-void
-resetscreenimage(void)
-{
-	dlock();
-	initscreenimage();
-	dunlock();
-}
-
-static Chan*
-drawattach(char *spec)
-{
-	dlock();
-	if(!initscreenimage()){
-		dunlock();
-		error("no frame buffer");
-	}
-	dunlock();
-	return devattach('i', spec);
-}
-
-static Walkqid*
-drawwalk(Chan *c, Chan *nc, char **name, int nname)
-{
-	if(screenimage == nil)
-		error("no frame buffer");
-	return devwalk(c, nc, name, nname, 0, 0, drawgen);
-}
-
-static int
-drawstat(Chan *c, uchar *db, int n)
-{
-	return devstat(c, db, n, 0, 0, drawgen);
-}
-
-static Chan*
-drawopen(Chan *c, int omode)
-{
-	Client *cl;
-	DName *dn;
-	DImage *di;
-
-	if(c->qid.type & QTDIR){
-		c = devopen(c, omode, 0, 0, drawgen);
-		c->iounit = IOUNIT;
-	}
-
-	dlock();
-	if(waserror()){
-		dunlock();
-		nexterror();
-	}
-
-	if(QID(c->qid) == Qnew){
-		cl = drawnewclient();
-		if(cl == 0)
-			error(Enodev);
-		c->qid.path = Qctl|((cl->slot+1)<<QSHIFT);
-	}
-
-	switch(QID(c->qid)){
-	case Qwinname:
-		break;
-
-	case Qnew:
-		break;
-
-	case Qctl:
-		cl = drawclient(c);
-		if(cl->busy)
-			error(Einuse);
-		cl->busy = 1;
-		flushrect = Rect(10000, 10000, -10000, -10000);
-		dn = drawlookupname(strlen(screenname), screenname);
-		if(dn == 0)
-			error("draw: cannot happen 2");
-		if(drawinstall(cl, 0, dn->dimage->image, 0) == 0)
-			error(Edrawmem);
-		di = drawlookup(cl, 0, 0);
-		if(di == 0)
-			error("draw: cannot happen 1");
-		di->vers = dn->vers;
-		di->name = smalloc(strlen(screenname)+1);
-		strcpy(di->name, screenname);
-		di->fromname = dn->dimage;
-		di->fromname->ref++;
-		incref(&cl->r);
-		break;
-
-	case Qcolormap:
-	case Qdata:
-	case Qrefresh:
-		cl = drawclient(c);
-		incref(&cl->r);
-		break;
-	}
-	dunlock();
-	poperror();
-	c->mode = openmode(omode);
-	c->flag |= COPEN;
-	c->offset = 0;
-	c->iounit = IOUNIT;
-	return c;
-}
-
-static void
-drawclose(Chan *c)
-{
-	int i;
-	DImage *d, **dp;
-	Client *cl;
-	Refresh *r;
-
-	if(QID(c->qid) < Qcolormap)	/* Qtopdir, Qnew, Q3rd, Q2nd have no client */
-		return;
-	dlock();
-	if(waserror()){
-		dunlock();
-		nexterror();
-	}
-
-	cl = drawclient(c);
-	if(QID(c->qid) == Qctl)
-		cl->busy = 0;
-	if((c->flag&COPEN) && (decref(&cl->r)==0)){
-		while(r = cl->refresh){	/* assign = */
-			cl->refresh = r->next;
-			free(r);
-		}
-		/* free names */
-		for(i=0; i<sdraw.nname; )
-			if(sdraw.name[i].client == cl)
-				drawdelname(sdraw.name+i);
-			else
-				i++;
-		while(cl->cscreen)
-			drawuninstallscreen(cl, cl->cscreen);
-		/* all screens are freed, so now we can free images */
-		dp = cl->dimage;
-		for(i=0; i<NHASH; i++){
-			while((d = *dp) != nil){
-				*dp = d->next;
-				drawfreedimage(d);
-			}
-			dp++;
-		}
-		sdraw.client[cl->slot] = 0;
-		drawflush();	/* to erase visible, now dead windows */
-		free(cl);
-	}
-	dunlock();
-	poperror();
-}
-
-long
-drawread(Chan *c, void *a, long n, vlong off)
-{
-	int index, m;
-	ulong red, green, blue;
-	Client *cl;
-	uchar *p;
-	Refresh *r;
-	DImage *di;
-	Memimage *i;
-	ulong offset = off;
-	char buf[16];
-
-	if(c->qid.type & QTDIR)
-		return devdirread(c, a, n, 0, 0, drawgen);
-	if(QID(c->qid) == Qwinname)
-		return readstr(off, a, n, screenname);
-
-	cl = drawclient(c);
-	dlock();
-	if(waserror()){
-		dunlock();
-		nexterror();
-	}
-	switch(QID(c->qid)){
-	case Qctl:
-		if(n < 12*12)
-			error(Eshortread);
-		if(cl->infoid < 0)
-			error(Enodrawimage);
-		if(cl->infoid == 0){
-			i = screenimage;
-			if(i == nil)
-				error(Enodrawimage);
-		}else{
-			di = drawlookup(cl, cl->infoid, 1);
-			if(di == nil)
-				error(Enodrawimage);
-			i = di->image;
-		}
-		n = sprint(a, "%11d %11d %11s %11d %11d %11d %11d %11d %11d %11d %11d %11d",
-			cl->clientid, cl->infoid, chantostr(buf, i->chan), (i->flags&Frepl)==Frepl,
-			i->r.min.x, i->r.min.y, i->r.max.x, i->r.max.y,
-			i->clipr.min.x, i->clipr.min.y, i->clipr.max.x, i->clipr.max.y);
-		((char*)a)[n++] = ' ';
-		cl->infoid = -1;
-		break;
-
-	case Qcolormap:
-		p = malloc(4*12*256+1);
-		if(p == 0)
-			error(Enomem);
-		m = 0;
-		for(index = 0; index < 256; index++){
-			getcolor(index, &red, &green, &blue);
-			m += sprint((char*)p+m, "%11d %11lud %11lud %11lud\n", index, red>>24, green>>24, blue>>24);
-		}
-		n = readstr(offset, a, n, (char*)p);
-		free(p);
-		break;
-
-	case Qdata:
-		if(cl->readdata == nil)
-			error("no draw data");
-		if(n < cl->nreaddata)
-			error(Eshortread);
-		n = cl->nreaddata;
-		memmove(a, cl->readdata, cl->nreaddata);
-		free(cl->readdata);
-		cl->readdata = nil;
-		break;
-
-	case Qrefresh:
-		if(n < 5*4)
-			error(Ebadarg);
-		for(;;){
-			if(cl->refreshme || cl->refresh)
-				break;
-			dunlock();
-			if(waserror()){
-				dlock();
-				nexterror();
-			}
-			qlock(&cl->refq);
-			if(waserror()){
-				qunlock(&cl->refq);
-				nexterror();
-			}
-			rendsleep(&cl->refrend, drawrefactive, cl);
-			poperror();
-			qunlock(&cl->refq);
-			poperror();
-			dlock();
-		}
-		p = a;
-		while(cl->refresh && n>=5*4){
-			r = cl->refresh;
-			BPLONG(p+0*4, r->dimage->id);
-			BPLONG(p+1*4, r->r.min.x);
-			BPLONG(p+2*4, r->r.min.y);
-			BPLONG(p+3*4, r->r.max.x);
-			BPLONG(p+4*4, r->r.max.y);
-			cl->refresh = r->next;
-			free(r);
-			p += 5*4;
-			n -= 5*4;
-		}
-		cl->refreshme = 0;
-		n = p-(uchar*)a;
-		break;
-	}
-	dunlock();
-	poperror();
-	return n;
-}
-
-void
-drawwakeall(void)
-{
-	Client *cl;
-	int i;
-
-	for(i=0; i<sdraw.nclient; i++){
-		cl = sdraw.client[i];
-		if(cl && (cl->refreshme || cl->refresh))
-			rendwakeup(&cl->refrend);
-	}
-}
-
-static long
-drawwrite(Chan *c, void *a, long n, vlong)
-{
-	char buf[128], *fields[4], *q;
-	Client *cl;
-	int i, m, red, green, blue, x;
-
-	if(c->qid.type & QTDIR)
-		error(Eisdir);
-	cl = drawclient(c);
-	dlock();
-	if(waserror()){
-		drawwakeall();
-		dunlock();
-		nexterror();
-	}
-	switch(QID(c->qid)){
-	case Qctl:
-		if(n != 4)
-			error("unknown draw control request");
-		cl->infoid = BGLONG((uchar*)a);
-		break;
-
-	case Qcolormap:
-		m = n;
-		n = 0;
-		while(m > 0){
-			x = m;
-			if(x > sizeof(buf)-1)
-				x = sizeof(buf)-1;
-			q = memccpy(buf, a, '\n', x);
-			if(q == 0)
-				break;
-			i = q-buf;
-			n += i;
-			a = (char*)a + i;
-			m -= i;
-			*q = 0;
-			if(tokenize(buf, fields, nelem(fields)) != 4)
-				error(Ebadarg);
-			i = strtoul(fields[0], 0, 0);
-			red = strtoul(fields[1], 0, 0);
-			green = strtoul(fields[2], 0, 0);
-			blue = strtoul(fields[3], &q, 0);
-			if(fields[3] == q)
-				error(Ebadarg);
-			if(red>255 || green>255 || blue>255 || i<0 || i>255)
-				error(Ebadarg);
-			red |= red<<8;
-			red |= red<<16;
-			green |= green<<8;
-			green |= green<<16;
-			blue |= blue<<8;
-			blue |= blue<<16;
-			setcolor(i, red, green, blue);
-		}
-		break;
-
-	case Qdata:
-		drawmesg(cl, a, n);
-		drawwakeall();
-		break;
-
-	default:
-		error(Ebadusefd);
-	}
-	dunlock();
-	poperror();
-	return n;
-}
-
-uchar*
-drawcoord(uchar *p, uchar *maxp, int oldx, int *newx)
-{
-	int b, x;
-
-	if(p >= maxp)
-		error(Eshortdraw);
-	b = *p++;
-	x = b & 0x7F;
-	if(b & 0x80){
-		if(p+1 >= maxp)
-			error(Eshortdraw);
-		x |= *p++ << 7;
-		x |= *p++ << 15;
-		if(x & (1<<22))
-			x |= ~0<<23;
-	}else{
-		if(b & 0x40)
-			x |= ~0<<7;
-		x += oldx;
-	}
-	*newx = x;
-	return p;
-}
-
-static void
-printmesg(char *fmt, uchar *a, int plsprnt)
-{
-	char buf[256];
-	char *p, *q;
-	int s;
-
-	if(1|| plsprnt==0){
-		SET(s,q,p);
-		USED(fmt, a, buf, p, q, s);
-		return;
-	}
-	q = buf;
-	*q++ = *a++;
-	for(p=fmt; *p; p++){
-		switch(*p){
-		case 'l':
-			q += sprint(q, " %ld", (long)BGLONG(a));
-			a += 4;
-			break;
-		case 'L':
-			q += sprint(q, " %.8lux", (ulong)BGLONG(a));
-			a += 4;
-			break;
-		case 'R':
-			q += sprint(q, " [%d %d %d %d]", BGLONG(a), BGLONG(a+4), BGLONG(a+8), BGLONG(a+12));
-			a += 16;
-			break;
-		case 'P':
-			q += sprint(q, " [%d %d]", BGLONG(a), BGLONG(a+4));
-			a += 8;
-			break;
-		case 'b':
-			q += sprint(q, " %d", *a++);
-			break;
-		case 's':
-			q += sprint(q, " %d", BGSHORT(a));
-			a += 2;
-			break;
-		case 'S':
-			q += sprint(q, " %.4ux", BGSHORT(a));
-			a += 2;
-			break;
-		}
-	}
-	*q++ = '\n';
-	*q = 0;
-	// iprint("%.*s", (int)(q-buf), buf);
-}
-
-void
-drawmesg(Client *client, void *av, int n)
-{
-	int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy, oesize, esize, doflush;
-	uchar *u, *a, refresh;
-	char *fmt;
-	ulong value, chan;
-	Rectangle r, clipr;
-	Point p, q, *pp, sp;
-	Memimage *i, *bg, *dst, *src, *mask;
-	Memimage *l, **lp;
-	Memscreen *scrn;
-	DImage *font, *ll, *di, *ddst, *dsrc;
-	DName *dn;
-	DScreen *dscrn;
-	FChar *fc;
-	Refx *refx;
-	CScreen *cs;
-	Refreshfn reffn;
-
-	a = av;
-	m = 0;
-	fmt = nil;
-	if(waserror()){
-		if(fmt) printmesg(fmt, a, 1);
-	/*	iprint("error: %s\n", up->errstr);	*/
-		nexterror();
-	}
-	while((n-=m) > 0){
-		USED(fmt);
-		a += m;
-		switch(*a){
-		default:
-			error("bad draw command");
-		/* new allocate: 'b' id[4] screenid[4] refresh[1] chan[4] repl[1] R[4*4] clipR[4*4] rrggbbaa[4] */
-		case 'b':
-			printmesg(fmt="LLbLbRRL", a, 0);
-			m = 1+4+4+1+4+1+4*4+4*4+4;
-			if(n < m)
-				error(Eshortdraw);
-			dstid = BGLONG(a+1);
-			scrnid = BGLONG(a+5);
-			refresh = a[9];
-			chan = BGLONG(a+10);
-			repl = a[14];
-			drawrectangle(&r, a+15);
-			drawrectangle(&clipr, a+31);
-			value = BGLONG(a+47);
-			if(drawlookup(client, dstid, 0))
-				error(Eimageexists);
-			if(scrnid){
-				dscrn = drawlookupscreen(client, scrnid, &cs);
-				scrn = dscrn->screen;
-				if(repl || chan!=scrn->image->chan)
-					error("image parameters incompatible with screen");
-				reffn = nil;
-				switch(refresh){
-				case Refbackup:
-					break;
-				case Refnone:
-					reffn = memlnorefresh;
-					break;
-				case Refmesg:
-					reffn = drawrefresh;
-					break;
-				default:
-					error("unknown refresh method");
-				}
-				l = memlalloc(scrn, r, reffn, 0, value);
-				if(l == 0)
-					error(Edrawmem);
-				addflush(l->layer->screenr);
-				l->clipr = clipr;
-				rectclip(&l->clipr, r);
-				if(drawinstall(client, dstid, l, dscrn) == 0){
-					memldelete(l);
-					error(Edrawmem);
-				}
-				dscrn->ref++;
-				if(reffn){
-					refx = nil;
-					if(reffn == drawrefresh){
-						refx = malloc(sizeof(Refx));
-						if(refx == 0){
-							drawuninstall(client, dstid);
-							error(Edrawmem);
-						}
-						refx->client = client;
-						refx->dimage = drawlookup(client, dstid, 1);
-					}
-					memlsetrefresh(l, reffn, refx);
-				}
-				continue;
-			}
-			i = allocmemimage(r, chan);
-			if(i == 0)
-				error(Edrawmem);
-			if(repl)
-				i->flags |= Frepl;
-			i->clipr = clipr;
-			if(!repl)
-				rectclip(&i->clipr, r);
-			if(drawinstall(client, dstid, i, 0) == 0){
-				freememimage(i);
-				error(Edrawmem);
-			}
-			memfillcolor(i, value);
-			continue;
-
-		/* allocate screen: 'A' id[4] imageid[4] fillid[4] public[1] */
-		case 'A':
-			printmesg(fmt="LLLb", a, 1);
-			m = 1+4+4+4+1;
-			if(n < m)
-				error(Eshortdraw);
-			dstid = BGLONG(a+1);
-			if(dstid == 0)
-				error(Ebadarg);
-			if(drawlookupdscreen(dstid))
-				error(Escreenexists);
-			ddst = drawlookup(client, BGLONG(a+5), 1);
-			dsrc = drawlookup(client, BGLONG(a+9), 1);
-			if(ddst==0 || dsrc==0)
-				error(Enodrawimage);
-			if(drawinstallscreen(client, 0, dstid, ddst, dsrc, a[13]) == 0)
-				error(Edrawmem);
-			continue;
-
-		/* set repl and clip: 'c' dstid[4] repl[1] clipR[4*4] */
-		case 'c':
-			printmesg(fmt="LbR", a, 0);
-			m = 1+4+1+4*4;
-			if(n < m)
-				error(Eshortdraw);
-			ddst = drawlookup(client, BGLONG(a+1), 1);
-			if(ddst == nil)
-				error(Enodrawimage);
-			if(ddst->name)
-				error("cannot change repl/clipr of shared image");
-			dst = ddst->image;
-			if(a[5])
-				dst->flags |= Frepl;
-			drawrectangle(&dst->clipr, a+6);
-			continue;
-
-		/* draw: 'd' dstid[4] srcid[4] maskid[4] R[4*4] P[2*4] P[2*4] */
-		case 'd':
-			printmesg(fmt="LLLRPP", a, 0);
-			m = 1+4+4+4+4*4+2*4+2*4;
-			if(n < m)
-				error(Eshortdraw);
-			dst = drawimage(client, a+1);
-			dstid = BGLONG(a+1);
-			src = drawimage(client, a+5);
-			mask = drawimage(client, a+9);
-			drawrectangle(&r, a+13);
-			drawpoint(&p, a+29);
-			drawpoint(&q, a+37);
-			op = drawclientop(client);
-			memdraw(dst, r, src, p, mask, q, op);
-			dstflush(dstid, dst, r);
-			continue;
-
-		/* toggle debugging: 'D' val[1] */
-		case 'D':
-			printmesg(fmt="b", a, 0);
-			m = 1+1;
-			if(n < m)
-				error(Eshortdraw);
-			continue;
-
-		/* ellipse: 'e' dstid[4] srcid[4] center[2*4] a[4] b[4] thick[4] sp[2*4] alpha[4] phi[4]*/
-		case 'e':
-		case 'E':
-			printmesg(fmt="LLPlllPll", a, 0);
-			m = 1+4+4+2*4+4+4+4+2*4+2*4;
-			if(n < m)
-				error(Eshortdraw);
-			dst = drawimage(client, a+1);
-			dstid = BGLONG(a+1);
-			src = drawimage(client, a+5);
-			drawpoint(&p, a+9);
-			e0 = BGLONG(a+17);
-			e1 = BGLONG(a+21);
-			if(e0<0 || e1<0)
-				error("invalid ellipse semidiameter");
-			j = BGLONG(a+25);
-			if(j < 0)
-				error("negative ellipse thickness");
-			drawpoint(&sp, a+29);
-			c = j;
-			if(*a == 'E')
-				c = -1;
-			ox = BGLONG(a+37);
-			oy = BGLONG(a+41);
-			op = drawclientop(client);
-			/* high bit indicates arc angles are present */
-			if(ox & (1<<31)){
-				if((ox & (1<<30)) == 0)
-					ox &= ~(1<<31);
-				memarc(dst, p, e0, e1, c, src, sp, ox, oy, op);
-			}else
-				memellipse(dst, p, e0, e1, c, src, sp, op);
-			dstflush(dstid, dst, Rect(p.x-e0-j, p.y-e1-j, p.x+e0+j+1, p.y+e1+j+1));
-			continue;
-
-		/* free: 'f' id[4] */
-		case 'f':
-			printmesg(fmt="L", a, 1);
-			m = 1+4;
-			if(n < m)
-				error(Eshortdraw);
-			ll = drawlookup(client, BGLONG(a+1), 0);
-			if(ll && ll->dscreen && ll->dscreen->owner != client)
-				ll->dscreen->owner->refreshme = 1;
-			drawuninstall(client, BGLONG(a+1));
-			continue;
-
-		/* free screen: 'F' id[4] */
-		case 'F':
-			printmesg(fmt="L", a, 1);
-			m = 1+4;
-			if(n < m)
-				error(Eshortdraw);
-			drawlookupscreen(client, BGLONG(a+1), &cs);
-			drawuninstallscreen(client, cs);
-			continue;
-
-		/* initialize font: 'i' fontid[4] nchars[4] ascent[1] */
-		case 'i':
-			printmesg(fmt="Llb", a, 1);
-			m = 1+4+4+1;
-			if(n < m)
-				error(Eshortdraw);
-			dstid = BGLONG(a+1);
-			if(dstid == 0)
-				error("cannot use display as font");
-			font = drawlookup(client, dstid, 1);
-			if(font == 0)
-				error(Enodrawimage);
-			if(font->image->layer)
-				error("cannot use window as font");
-			ni = BGLONG(a+5);
-			if(ni<=0 || ni>4096)
-				error("bad font size (4096 chars max)");
-			free(font->fchar);	/* should we complain if non-zero? */
-			font->fchar = malloc(ni*sizeof(FChar));
-			if(font->fchar == 0)
-				error("no memory for font");
-			memset(font->fchar, 0, ni*sizeof(FChar));
-			font->nfchar = ni;
-			font->ascent = a[9];
-			continue;
-
-		/* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4] left[1] width[1] */
-		case 'l':
-			printmesg(fmt="LLSRPbb", a, 0);
-			m = 1+4+4+2+4*4+2*4+1+1;
-			if(n < m)
-				error(Eshortdraw);
-			font = drawlookup(client, BGLONG(a+1), 1);
-			if(font == 0)
-				error(Enodrawimage);
-			if(font->nfchar == 0)
-				error(Enotfont);
-			src = drawimage(client, a+5);
-			ci = BGSHORT(a+9);
-			if(ci >= font->nfchar)
-				error(Eindex);
-			drawrectangle(&r, a+11);
-			drawpoint(&p, a+27);
-			memdraw(font->image, r, src, p, memopaque, p, S);
-			fc = &font->fchar[ci];
-			fc->minx = r.min.x;
-			fc->maxx = r.max.x;
-			fc->miny = r.min.y;
-			fc->maxy = r.max.y;
-			fc->left = a[35];
-			fc->width = a[36];
-			continue;
-
-		/* draw line: 'L' dstid[4] p0[2*4] p1[2*4] end0[4] end1[4] radius[4] srcid[4] sp[2*4] */
-		case 'L':
-			printmesg(fmt="LPPlllLP", a, 0);
-			m = 1+4+2*4+2*4+4+4+4+4+2*4;
-			if(n < m)
-				error(Eshortdraw);
-			dst = drawimage(client, a+1);
-			dstid = BGLONG(a+1);
-			drawpoint(&p, a+5);
-			drawpoint(&q, a+13);
-			e0 = BGLONG(a+21);
-			e1 = BGLONG(a+25);
-			j = BGLONG(a+29);
-			if(j < 0)
-				error("negative line width");
-			src = drawimage(client, a+33);
-			drawpoint(&sp, a+37);
-			op = drawclientop(client);
-			memline(dst, p, q, e0, e1, j, src, sp, op);
-			/* avoid memlinebbox if possible */
-			if(dstid==0 || dst->layer!=nil){
-				/* BUG: this is terribly inefficient: update maximal containing rect*/
-				r = memlinebbox(p, q, e0, e1, j);
-				dstflush(dstid, dst, insetrect(r, -(1+1+j)));
-			}
-			continue;
-
-		/* create image mask: 'm' newid[4] id[4] */
-/*
- *
-		case 'm':
-			printmesg("LL", a, 0);
-			m = 4+4;
-			if(n < m)
-				error(Eshortdraw);
-			break;
- *
- */
-
-		/* attach to a named image: 'n' dstid[4] j[1] name[j] */
-		case 'n':
-			printmesg(fmt="Lz", a, 0);
-			m = 1+4+1;
-			if(n < m)
-				error(Eshortdraw);
-			j = a[5];
-			if(j == 0)	/* give me a non-empty name please */
-				error(Eshortdraw);
-			m += j;
-			if(n < m)
-				error(Eshortdraw);
-			dstid = BGLONG(a+1);
-			if(drawlookup(client, dstid, 0))
-				error(Eimageexists);
-			dn = drawlookupname(j, (char*)a+6);
-			if(dn == nil)
-				error(Enoname);
-			if(drawinstall(client, dstid, dn->dimage->image, 0) == 0)
-				error(Edrawmem);
-			di = drawlookup(client, dstid, 0);
-			if(di == 0)
-				error("draw: cannot happen");
-			di->vers = dn->vers;
-			di->name = smalloc(j+1);
-			di->fromname = dn->dimage;
-			di->fromname->ref++;
-			memmove(di->name, a+6, j);
-			di->name[j] = 0;
-			client->infoid = dstid;
-			continue;
-
-		/* name an image: 'N' dstid[4] in[1] j[1] name[j] */
-		case 'N':
-			printmesg(fmt="Lbz", a, 0);
-			m = 1+4+1+1;
-			if(n < m)
-				error(Eshortdraw);
-			c = a[5];
-			j = a[6];
-			if(j == 0)	/* give me a non-empty name please */
-				error(Eshortdraw);
-			m += j;
-			if(n < m)
-				error(Eshortdraw);
-			di = drawlookup(client, BGLONG(a+1), 0);
-			if(di == 0)
-				error(Enodrawimage);
-			if(di->name)
-				error(Enamed);
-			if(c)
-				drawaddname(client, di, j, (char*)a+7);
-			else{
-				dn = drawlookupname(j, (char*)a+7);
-				if(dn == nil)
-					error(Enoname);
-				if(dn->dimage != di)
-					error(Ewrongname);
-				drawdelname(dn);
-			}
-			continue;
-
-		/* position window: 'o' id[4] r.min [2*4] screenr.min [2*4] */
-		case 'o':
-			printmesg(fmt="LPP", a, 0);
-			m = 1+4+2*4+2*4;
-			if(n < m)
-				error(Eshortdraw);
-			dst = drawimage(client, a+1);
-			if(dst->layer){
-				drawpoint(&p, a+5);
-				drawpoint(&q, a+13);
-				r = dst->layer->screenr;
-				ni = memlorigin(dst, p, q);
-				if(ni < 0)
-					error("image origin failed");
-				if(ni > 0){
-					addflush(r);
-					addflush(dst->layer->screenr);
-					ll = drawlookup(client, BGLONG(a+1), 1);
-					drawrefreshscreen(ll, client);
-				}
-			}
-			continue;
-
-		/* set compositing operator for next draw operation: 'O' op */
-		case 'O':
-			printmesg(fmt="b", a, 0);
-			m = 1+1;
-			if(n < m)
-				error(Eshortdraw);
-			client->op = a[1];
-			continue;
-
-		/* filled polygon: 'P' dstid[4] n[2] wind[4] ignore[2*4] srcid[4] sp[2*4] p0[2*4] dp[2*2*n] */
-		/* polygon: 'p' dstid[4] n[2] end0[4] end1[4] radius[4] srcid[4] sp[2*4] p0[2*4] dp[2*2*n] */
-		case 'p':
-		case 'P':
-			printmesg(fmt="LslllLPP", a, 0);
-			m = 1+4+2+4+4+4+4+2*4;
-			if(n < m)
-				error(Eshortdraw);
-			dstid = BGLONG(a+1);
-			dst = drawimage(client, a+1);
-			ni = BGSHORT(a+5);
-			if(ni < 0)
-				error("negative count in polygon");
-			e0 = BGLONG(a+7);
-			e1 = BGLONG(a+11);
-			j = 0;
-			if(*a == 'p'){
-				j = BGLONG(a+15);
-				if(j < 0)
-					error("negative polygon line width");
-			}
-			src = drawimage(client, a+19);
-			drawpoint(&sp, a+23);
-			drawpoint(&p, a+31);
-			ni++;
-			pp = malloc(ni*sizeof(Point));
-			if(pp == nil)
-				error(Enomem);
-			doflush = 0;
-			if(dstid==0 || (screenimage && dst->layer && dst->layer->screen->image->data == screenimage->data))
-				doflush = 1;	/* simplify test in loop */
-			ox = oy = 0;
-			esize = 0;
-			u = a+m;
-			for(y=0; y<ni; y++){
-				q = p;
-				oesize = esize;
-				u = drawcoord(u, a+n, ox, &p.x);
-				u = drawcoord(u, a+n, oy, &p.y);
-				ox = p.x;
-				oy = p.y;
-				if(doflush){
-					esize = j;
-					if(*a == 'p'){
-						if(y == 0){
-							c = memlineendsize(e0);
-							if(c > esize)
-								esize = c;
-						}
-						if(y == ni-1){
-							c = memlineendsize(e1);
-							if(c > esize)
-								esize = c;
-						}
-					}
-					if(*a=='P' && e0!=1 && e0 !=~0)
-						r = dst->clipr;
-					else if(y > 0){
-						r = Rect(q.x-oesize, q.y-oesize, q.x+oesize+1, q.y+oesize+1);
-						combinerect(&r, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1));
-					}
-					if(rectclip(&r, dst->clipr))		/* should perhaps be an arg to dstflush */
-						dstflush(dstid, dst, r);
-				}
-				pp[y] = p;
-			}
-			if(y == 1)
-				dstflush(dstid, dst, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1));
-			op = drawclientop(client);
-			if(*a == 'p')
-				mempoly(dst, pp, ni, e0, e1, j, src, sp, op);
-			else
-				memfillpoly(dst, pp, ni, e0, src, sp, op);
-			free(pp);
-			m = u-a;
-			continue;
-
-		/* read: 'r' id[4] R[4*4] */
-		case 'r':
-			printmesg(fmt="LR", a, 0);
-			m = 1+4+4*4;
-			if(n < m)
-				error(Eshortdraw);
-			i = drawimage(client, a+1);
-			drawrectangle(&r, a+5);
-			if(!rectinrect(r, i->r))
-				error(Ereadoutside);
-			c = bytesperline(r, i->depth);
-			c *= Dy(r);
-			free(client->readdata);
-			client->readdata = mallocz(c, 0);
-			if(client->readdata == nil)
-				error("readimage malloc failed");
-			client->nreaddata = memunload(i, r, client->readdata, c);
-			if(client->nreaddata < 0){
-				free(client->readdata);
-				client->readdata = nil;
-				error("bad readimage call");
-			}
-			continue;
-
-		/* string: 's' dstid[4] srcid[4] fontid[4] P[2*4] clipr[4*4] sp[2*4] ni[2] ni*(index[2]) */
-		/* stringbg: 'x' dstid[4] srcid[4] fontid[4] P[2*4] clipr[4*4] sp[2*4] ni[2] bgid[4] bgpt[2*4] ni*(index[2]) */
-		case 's':
-		case 'x':
-			printmesg(fmt="LLLPRPs", a, 0);
-			m = 1+4+4+4+2*4+4*4+2*4+2;
-			if(*a == 'x')
-				m += 4+2*4;
-			if(n < m)
-				error(Eshortdraw);
-
-			dst = drawimage(client, a+1);
-			dstid = BGLONG(a+1);
-			src = drawimage(client, a+5);
-			font = drawlookup(client, BGLONG(a+9), 1);
-			if(font == 0)
-				error(Enodrawimage);
-			if(font->nfchar == 0)
-				error(Enotfont);
-			drawpoint(&p, a+13);
-			drawrectangle(&r, a+21);
-			drawpoint(&sp, a+37);
-			ni = BGSHORT(a+45);
-			u = a+m;
-			m += ni*2;
-			if(n < m)
-				error(Eshortdraw);
-			clipr = dst->clipr;
-			dst->clipr = r;
-			op = drawclientop(client);
-			bg = dst;
-			if(*a == 'x'){
-				/* paint background */
-				bg = drawimage(client, a+47);
-				drawpoint(&q, a+51);
-				r.min.x = p.x;
-				r.min.y = p.y-font->ascent;
-				r.max.x = p.x;
-				r.max.y = r.min.y+Dy(font->image->r);
-				j = ni;
-				while(--j >= 0){
-					ci = BGSHORT(u);
-					if(ci<0 || ci>=font->nfchar){
-						dst->clipr = clipr;
-						error(Eindex);
-					}
-					r.max.x += font->fchar[ci].width;
-					u += 2;
-				}
-				memdraw(dst, r, bg, q, memopaque, ZP, op);
-				u -= 2*ni;
-			}
-			q = p;
-			while(--ni >= 0){
-				ci = BGSHORT(u);
-				if(ci<0 || ci>=font->nfchar){
-					dst->clipr = clipr;
-					error(Eindex);
-				}
-				q = drawchar(dst, bg, q, src, &sp, font, ci, op);
-				u += 2;
-			}
-			dst->clipr = clipr;
-			p.y -= font->ascent;
-			dstflush(dstid, dst, Rect(p.x, p.y, q.x, p.y+Dy(font->image->r)));
-			continue;
-
-		/* use public screen: 'S' id[4] chan[4] */
-		case 'S':
-			printmesg(fmt="Ll", a, 0);
-			m = 1+4+4;
-			if(n < m)
-				error(Eshortdraw);
-			dstid = BGLONG(a+1);
-			if(dstid == 0)
-				error(Ebadarg);
-			dscrn = drawlookupdscreen(dstid);
-			if(dscrn==0 || (dscrn->public==0 && dscrn->owner!=client))
-				error(Enodrawscreen);
-			if(dscrn->screen->image->chan != BGLONG(a+5))
-				error("inconsistent chan");
-			if(drawinstallscreen(client, dscrn, 0, 0, 0, 0) == 0)
-				error(Edrawmem);
-			continue;
-
-		/* top or bottom windows: 't' top[1] nw[2] n*id[4] */
-		case 't':
-			printmesg(fmt="bsL", a, 0);
-			m = 1+1+2;
-			if(n < m)
-				error(Eshortdraw);
-			nw = BGSHORT(a+2);
-			if(nw < 0)
-				error(Ebadarg);
-			if(nw == 0)
-				continue;
-			m += nw*4;
-			if(n < m)
-				error(Eshortdraw);
-			lp = malloc(nw*sizeof(Memimage*));
-			if(lp == 0)
-				error(Enomem);
-			if(waserror()){
-				free(lp);
-				nexterror();
-			}
-			for(j=0; j<nw; j++){
-				lp[j] = drawimage(client, a+1+1+2+j*4);
-				if(lp[j]->layer == 0)
-					error("images are not windows");
-				if(lp[j]->layer->screen != lp[0]->layer->screen)
-					error("images not on same screen");
-			}
-			if(a[1])
-				memltofrontn(lp, nw);
-			else
-				memltorearn(lp, nw);
-			if(screenimage && lp[0]->layer->screen->image->data == screenimage->data)
-				for(j=0; j<nw; j++)
-					addflush(lp[j]->layer->screenr);
-			ll = drawlookup(client, BGLONG(a+1+1+2), 1);
-			drawrefreshscreen(ll, client);
-			poperror();
-			free(lp);
-			continue;
-
-		/* visible: 'v' */
-		case 'v':
-			printmesg(fmt="", a, 0);
-			m = 1;
-			drawflush();
-			continue;
-
-		/* write: 'y' id[4] R[4*4] data[x*1] */
-		/* write from compressed data: 'Y' id[4] R[4*4] data[x*1] */
-		case 'y':
-		case 'Y':
-			printmesg(fmt="LR", a, 0);
-		//	iprint("load %c\n", *a);
-			m = 1+4+4*4;
-			if(n < m)
-				error(Eshortdraw);
-			dstid = BGLONG(a+1);
-			dst = drawimage(client, a+1);
-			drawrectangle(&r, a+5);
-			if(!rectinrect(r, dst->r))
-				error(Ewriteoutside);
-			y = memload(dst, r, a+m, n-m, *a=='Y');
-			if(y < 0)
-				error("bad writeimage call");
-			dstflush(dstid, dst, r);
-			m += y;
-			continue;
-		}
-	}
-	poperror();
-}
-
-Dev drawdevtab = {
-	'i',
-	"draw",
-
-	devreset,
-	devinit,
-	drawattach,
-	drawwalk,
-	drawstat,
-	drawopen,
-	devcreate,
-	drawclose,
-	drawread,
-	devbread,
-	drawwrite,
-	devbwrite,
-	devremove,
-	devwstat,
-};
-
-/*
- * On 8 bit displays, load the default color map
- */
-void
-drawcmap(void)
-{
-	int r, g, b, cr, cg, cb, v;
-	int num, den;
-	int i, j;
-
-	for(r=0,i=0; r!=4; r++)
-	    for(v=0; v!=4; v++,i+=16){
-		for(g=0,j=v-r; g!=4; g++)
-		    for(b=0;b!=4;b++,j++){
-			den = r;
-			if(g > den)
-				den = g;
-			if(b > den)
-				den = b;
-			if(den == 0)	/* divide check -- pick grey shades */
-				cr = cg = cb = v*17;
-			else{
-				num = 17*(4*den+v);
-				cr = r*num/den;
-				cg = g*num/den;
-				cb = b*num/den;
-			}
-			setcolor(i+(j&15),
-				cr*0x01010101, cg*0x01010101, cb*0x01010101);
-		    }
-	}
-}
--- a/sys/src/cmd/vnc/devmouse.c
+++ /dev/null
@@ -1,346 +1,0 @@
-#include	<u.h>
-#include	<libc.h>
-#include	"compat.h"
-#include	"error.h"
-
-#define	Image	IMAGE
-#include	<draw.h>
-#include	<memdraw.h>
-#include	<cursor.h>
-#include	"screen.h"
-
-typedef struct Mouseinfo	Mouseinfo;
-typedef struct Mousestate	Mousestate;
-
-struct Mousestate
-{
-	Point	xy;		/* mouse.xy */
-	int	buttons;	/* mouse.buttons */
-	ulong	counter;	/* increments every update */
-	ulong	msec;		/* time of last event */
-};
-
-struct Mouseinfo
-{
-	Lock;
-	Mousestate;
-	ulong	lastcounter;	/* value when /dev/mouse read */
-	Rendez	r;
-	Ref;
-	int	resize;
-	int	open;
-	Mousestate	queue[16];	/* circular buffer of click events */
-	ulong	ri;		/* read index into queue */
-	ulong	wi;		/* write index into queue */
-};
-
-Mouseinfo	mouse;
-Cursorinfo	cursor;
-Cursor		curs;
-
-void	Cursortocursor(Cursor*);
-int	mousechanged(void*);
-
-enum{
-	Qdir,
-	Qcursor,
-	Qmouse,
-	Qmousein,
-	Qmousectl,
-};
-
-static Dirtab mousedir[]={
-	".",	{Qdir, 0, QTDIR},	0,			DMDIR|0555,
-	"cursor",	{Qcursor},	0,			0666,
-	"mouse",	{Qmouse},	0,			0666,
-	"mousein",	{Qmousein},	0,			0222,
-	"mousectl",	{Qmousectl},	0,			0222,
-};
-
-Cursor	arrow = {
-	{ -1, -1 },
-	{ 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
-	  0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
-	  0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
-	  0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
-	},
-	{ 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
-	  0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
-	  0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
-	  0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
-	},
-};
-
-extern Memimage* gscreen;
-extern void mousewarpnote(Point);
-
-static void
-mousereset(void)
-{
-	curs = arrow;
-	Cursortocursor(&arrow);
-}
-
-static void
-mouseinit(void)
-{
-	curs = arrow;
-	Cursortocursor(&arrow);
-	cursoron();
-}
-
-static Chan*
-mouseattach(char *spec)
-{
-	return devattach('m', spec);
-}
-
-static Walkqid*
-mousewalk(Chan *c, Chan *nc, char **name, int nname)
-{
-	return devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
-}
-
-static int
-mousestat(Chan *c, uchar *db, int n)
-{
-	return devstat(c, db, n, mousedir, nelem(mousedir), devgen);
-}
-
-static Chan*
-mouseopen(Chan *c, int omode)
-{
-	int mode;
-
-	mode = openmode(omode);
-	switch((ulong)c->qid.path){
-	case Qdir:
-		if(omode != OREAD)
-			error(Eperm);
-		break;
-	case Qmousein:
-	case Qmousectl:
-		error(Egreg);
-		break;
-	case Qmouse:
-		if(_tas(&mouse.open) != 0)
-			error(Einuse);
-		mouse.lastcounter = mouse.counter;
-		/* wet floor */
-	case Qcursor:
-		incref(&mouse);
-	}
-	c->mode = mode;
-	c->flag |= COPEN;
-	c->offset = 0;
-	return c;
-}
-
-static void
-mouseclose(Chan *c)
-{
-	if((c->qid.type&QTDIR)!=0 || (c->flag&COPEN)==0)
-		return;
-	switch((ulong)c->qid.path){
-	case Qmouse:
-		mouse.open = 0;
-		/* wet floor */
-	case Qcursor:
-		if(decref(&mouse) != 0)
-			return;
-		cursoroff();
-		curs = arrow;
-		Cursortocursor(&arrow);
-		cursoron();
-	}
-}
-
-
-static long
-mouseread(Chan *c, void *va, long n, vlong off)
-{
-	char buf[1+4*12+1];
-	uchar *p;
-	ulong offset = off;
-	Mousestate m;
-
-	p = va;
-	switch((ulong)c->qid.path){
-	case Qdir:
-		return devdirread(c, va, n, mousedir, nelem(mousedir), devgen);
-
-	case Qcursor:
-		if(offset != 0)
-			return 0;
-		if(n < 2*4+2*2*16)
-			error(Eshort);
-		n = 2*4+2*2*16;
-		BPLONG(p+0, curs.offset.x);
-		BPLONG(p+4, curs.offset.y);
-		memmove(p+8, curs.clr, 2*16);
-		memmove(p+40, curs.set, 2*16);
-		return n;
-
-	case Qmouse:
-		while(mousechanged(0) == 0)
-			rendsleep(&mouse.r, mousechanged, 0);
-
-		lock(&mouse);
-		if(mouse.ri != mouse.wi)
-			m = mouse.queue[mouse.ri++ % nelem(mouse.queue)];
-		else
-			m = mouse.Mousestate;
-		unlock(&mouse);
-
-		sprint(buf, "m%11d %11d %11d %11ld ",
-			m.xy.x, m.xy.y, m.buttons, m.msec);
-
-		mouse.lastcounter = m.counter;
-		if(mouse.resize){
-			mouse.resize = 0;
-			buf[0] = 'r';
-		}
-
-		if(n > 1+4*12)
-			n = 1+4*12;
-		memmove(va, buf, n);
-		return n;
-	}
-	return 0;
-}
-
-static long
-mousewrite(Chan *c, void *va, long n, vlong)
-{
-	char *p;
-	Point pt;
-	char buf[64];
-
-	p = va;
-	switch((ulong)c->qid.path){
-	case Qdir:
-		error(Eisdir);
-
-	case Qcursor:
-		cursoroff();
-		if(n < 2*4+2*2*16){
-			curs = arrow;
-			Cursortocursor(&arrow);
-		}else{
-			n = 2*4+2*2*16;
-			curs.offset.x = BGLONG(p+0);
-			curs.offset.y = BGLONG(p+4);
-			memmove(curs.clr, p+8, 2*16);
-			memmove(curs.set, p+40, 2*16);
-			Cursortocursor(&curs);
-		}
-		cursoron();
-		return n;
-
-	case Qmouse:
-		if(n > sizeof buf-1)
-			n = sizeof buf -1;
-		memmove(buf, va, n);
-		buf[n] = 0;
-
-		pt.x = strtol(buf+1, &p, 0);
-		if(*p == 0)
-			error(Eshort);
-		pt.y = strtol(p, 0, 0);
-		absmousetrack(pt.x, pt.y, mouse.buttons, nsec()/(1000*1000LL));
-		mousewarpnote(pt);
-		return n;
-	}
-
-	error(Egreg);
-	return -1;
-}
-
-Dev mousedevtab = {
-	'm',
-	"mouse",
-
-	mousereset,
-	mouseinit,
-	mouseattach,
-	mousewalk,
-	mousestat,
-	mouseopen,
-	devcreate,
-	mouseclose,
-	mouseread,
-	devbread,
-	mousewrite,
-	devbwrite,
-	devremove,
-	devwstat,
-};
-
-void
-Cursortocursor(Cursor *c)
-{
-	lock(&cursor);
-	memmove(&cursor.Cursor, c, sizeof(Cursor));
-	setcursor(c);
-	unlock(&cursor);
-}
-
-void
-absmousetrack(int x, int y, int b, ulong msec)
-{
-	int lastb;
-
-	if(gscreen==nil)
-		return;
-
-	if(x < gscreen->clipr.min.x)
-		x = gscreen->clipr.min.x;
-	if(x >= gscreen->clipr.max.x)
-		x = gscreen->clipr.max.x-1;
-	if(y < gscreen->clipr.min.y)
-		y = gscreen->clipr.min.y;
-	if(y >= gscreen->clipr.max.y)
-		y = gscreen->clipr.max.y-1;
-
-
-	lock(&mouse);
-	mouse.xy = Pt(x, y);
-	lastb = mouse.buttons;
-	mouse.buttons = b;
-	mouse.msec = msec;
-	mouse.counter++;
-
-	/*
-	 * if the queue fills, don't queue any more events until a
-	 * reader polls the mouse.
-	 */
-	if(b != lastb && (mouse.wi-mouse.ri) < nelem(mouse.queue))
-		mouse.queue[mouse.wi++ % nelem(mouse.queue)] = mouse.Mousestate;
-	unlock(&mouse);
-
-	rendwakeup(&mouse.r);
-
-	cursoron();
-}
-
-int
-mousechanged(void*)
-{
-	return mouse.lastcounter != mouse.counter || mouse.resize != 0;
-}
-
-Point
-mousexy(void)
-{
-	return mouse.xy;
-}
-
-/*
- * notify reader that screen has been resized
- */
-void
-mouseresize(void)
-{
-	mouse.resize = 1;
-	rendwakeup(&mouse.r);
-}
--- a/sys/src/cmd/vnc/draw.c
+++ /dev/null
@@ -1,428 +1,0 @@
-#include "vnc.h"
-#include "vncv.h"
-
-static struct {
-	char	*name;
-	int	num;
-} enctab[] = {
-	"copyrect",	EncCopyRect,
-	"corre",	EncCorre,
-	"hextile",	EncHextile,
-	"raw",		EncRaw,
-	"rre",		EncRre,
-	"mousewarp",	EncMouseWarp,
-	"desktopsize",	EncDesktopSize,
-	"xdesktopsize",	EncXDesktopSize,
-};
-
-static	uchar	*pixbuf;
-static	uchar	*linebuf;
-static	int	vpixb;
-static	int	pixb;
-static	void	(*pixcp)(uchar*, uchar*);
-
-static void
-vncsetdim(Vnc *v, Rectangle dim)
-{
-	v->dim = rectsubpt(dim, dim.min);
-	linebuf = realloc(linebuf, v->dim.max.x * vpixb);
-	pixbuf = realloc(pixbuf, v->dim.max.x * pixb * v->dim.max.y);
-	if(linebuf == nil || pixbuf == nil)
-		sysfatal("can't allocate pix decompression storage");
-	lockdisplay(display);
-	adjustwin(v, 0);
-	unlockdisplay(display);
-}
-
-static void
-vncrdcolor(Vnc *v, uchar *color)
-{
-	vncrdbytes(v, color, vpixb);
-
-	if(cvtpixels)
-		(*cvtpixels)(color, color, 1);
-}
-
-void
-sendencodings(Vnc *v)
-{
-	char *f[16];
-	int enc[16], nenc, i, j, nf;
-
-	nf = tokenize(encodings, f, nelem(f));
-	nenc = 0;
-	for(i=0; i<nf; i++){
-		for(j=0; j<nelem(enctab); j++)
-			if(strcmp(f[i], enctab[j].name) == 0)
-				break;
-		if(j == nelem(enctab)){
-			print("warning: unknown encoding %s\n", f[i]);
-			continue;
-		}
-		enc[nenc++] = enctab[j].num;
-	}
-
-	vnclock(v);
-	vncwrchar(v, MSetEnc);
-	vncwrchar(v, 0);
-	vncwrshort(v, nenc);
-	for(i=0; i<nenc; i++)
-		vncwrlong(v, enc[i]);
-	vncflush(v);
-	vncunlock(v);
-}
-
-void
-requestupdate(Vnc *v, int incremental)
-{
-	Rectangle r;
-
-	lockdisplay(display);
-	flushimage(display, 1);
-	r = rectsubpt(screen->r, screen->r.min);
-	unlockdisplay(display);
-	vnclock(v);
-	if(incremental == 0 && (v->canresize&2)!=0 && !eqrect(r, v->dim)){
-		vncwrchar(v, MSetDesktopSize);
-		vncwrchar(v, 0);
-		vncwrpoint(v, r.max);
-		vncwrchar(v, 1);
-		vncwrchar(v, 0);
-		vncwrlong(v, v->screen[0].id);
-		vncwrrect(v, r);
-		vncwrlong(v, v->screen[0].flags);
-	} else 
-		rectclip(&r, v->dim);
-	vncwrchar(v, MFrameReq);
-	vncwrchar(v, incremental);
-	vncwrrect(v, r);
-	vncflush(v);
-	vncunlock(v);
-}
-
-static Rectangle
-clippixbuf(Rectangle r, int maxx, int maxy)
-{
-	int y, h, stride1, stride2;
-
-	if(r.min.x > maxx || r.min.y > maxy){
-		r.max.x = 0;
-		return r;
-	}
-	if(r.max.y > maxy)
-		r.max.y = maxy;
-	if(r.max.x <= maxx)
-		return r;
-
-	stride2 = Dx(r) * pixb;
-	r.max.x = maxx;
-	stride1 = Dx(r) * pixb;
-	h = Dy(r);
-	for(y = 0; y < h; y++)
-		memmove(&pixbuf[y * stride1], &pixbuf[y * stride2], stride1);
-
-	return r;
-}
-
-/* must be called with display locked */
-static void
-updatescreen(Rectangle r)
-{
-	int b, bb;
-
-	lockdisplay(display);
-	if(r.max.x > Dx(screen->r) || r.max.y > Dy(screen->r)){
-		r = clippixbuf(r, Dx(screen->r), Dy(screen->r));
-		if(r.max.x == 0){
-			unlockdisplay(display);
-			return;
-		}
-	}
-
-	/*
-	 * assume load image fails only because of resize
-	 */
-	b = Dx(r) * pixb * Dy(r);
-	bb = loadimage(screen, rectaddpt(r, screen->r.min), pixbuf, b);
-	if(bb != b && verbose)
-		fprint(2, "loadimage %d on %R for %R returned %d: %r\n", b, rectaddpt(r, screen->r.min), screen->r, bb);
-	unlockdisplay(display);
-}
-
-static void
-fillrect(Rectangle r, int stride, uchar *color)
-{
-	int x, xe, y, off;
-
-	y = r.min.y;
-	off = y * stride;
-	for(; y < r.max.y; y++){
-		xe = off + r.max.x * pixb;
-		for(x = off + r.min.x * pixb; x < xe; x += pixb)
-			(*pixcp)(&pixbuf[x], color);
-		off += stride;
-	}
-}
-
-static void
-loadbuf(Vnc *v, Rectangle r, int stride)
-{
-	int off, y;
-
-	if(cvtpixels){
-		y = r.min.y;
-		off = y * stride + r.min.x * pixb;
-		for(; y < r.max.y; y++){
-			vncrdbytes(v, linebuf, Dx(r) * vpixb);
-			(*cvtpixels)(&pixbuf[off], linebuf, Dx(r));
-			off += stride;
-		}
-	}else{
-		y = r.min.y;
-		off = y * stride + r.min.x * pixb;
-		for(; y < r.max.y; y++){
-			vncrdbytes(v, &pixbuf[off], Dx(r) * pixb);
-			off += stride;
-		}
-	}
-}
-
-static Rectangle
-hexrect(ushort u)
-{
-	int x, y, w, h;
-
-	x = u>>12;
-	y = (u>>8)&15;
-	w = ((u>>4)&15)+1;
-	h = (u&15)+1;
-
-	return Rect(x, y, x+w, y+h);
-}
-
-
-static void
-dohextile(Vnc *v, Rectangle r, int stride)
-{
-	ulong bg, fg, c;
-	int enc, nsub, sx, sy, w, h, th, tw;
-	Rectangle sr, ssr;
-
-	fg = bg = 0;
-	h = Dy(r);
-	w = Dx(r);
-	for(sy = 0; sy < h; sy += HextileDim){
-		th = h - sy;
-		if(th > HextileDim)
-			th = HextileDim;
-		for(sx = 0; sx < w; sx += HextileDim){
-			tw = w - sx;
-			if(tw > HextileDim)
-				tw = HextileDim;
-
-			sr = Rect(sx, sy, sx + tw, sy + th);
-			enc = vncrdchar(v);
-			if(enc & HextileRaw){
-				loadbuf(v, sr, stride);
-				continue;
-			}
-
-			if(enc & HextileBack)
-				vncrdcolor(v, (uchar*)&bg);
-			fillrect(sr, stride, (uchar*)&bg);
-
-			if(enc & HextileFore)
-				vncrdcolor(v, (uchar*)&fg);
-
-			if(enc & HextileRects){
-				nsub = vncrdchar(v);
-				(*pixcp)((uchar*)&c, (uchar*)&fg);
-				while(nsub-- > 0){
-					if(enc & HextileCols)
-						vncrdcolor(v, (uchar*)&c);
-					ssr = rectaddpt(hexrect(vncrdshort(v)), sr.min);
-					fillrect(ssr, stride, (uchar*)&c);
-				}
-			}
-		}
-	}
-}
-
-static void
-dorectangle(Vnc *v)
-{
-	ulong type;
-	long n, stride;
-	ulong color;
-	Point p;
-	Rectangle r, subr, maxr;
-
-	r = vncrdrect(v);
-	type = vncrdlong(v);
-	switch(type){
-	case EncMouseWarp:
-		mousewarp(r.min);
-		return;
-	case EncDesktopSize:
-		v->canresize |= 1;
-		vncsetdim(v, r);
-		return;
-	case EncXDesktopSize:
-		v->canresize |= 2;
-		n = vncrdlong(v)>>24;
-		if(n <= 0)
-			break;
-		v->screen[0].id = vncrdlong(v);
-		v->screen[0].rect = vncrdrect(v);
-		v->screen[0].flags = vncrdlong(v);
-		while(--n > 0){
-			vncrdlong(v);
-			vncrdrect(v);
-			vncrdlong(v);
-		}
-		vncsetdim(v, v->screen[0].rect);
-		return;
-	}
-
-	if(!rectinrect(r, v->dim))
-		sysfatal("bad rectangle from server: %R not in %R", r, v->dim);
-	maxr = rectsubpt(r, r.min);
-	stride = maxr.max.x * pixb;
-
-	switch(type){
-	default:
-		sysfatal("bad rectangle encoding from server");
-		break;
-	case EncRaw:
-		loadbuf(v, maxr, stride);
-		updatescreen(r);
-		break;
-
-	case EncCopyRect:
-		p = vncrdpoint(v);
-		lockdisplay(display);
-		p = addpt(p, screen->r.min);
-		r = rectaddpt(r, screen->r.min);
-		draw(screen, r, screen, nil, p);
-		unlockdisplay(display);
-		break;
-
-	case EncRre:
-	case EncCorre:
-		n = vncrdlong(v);
-		vncrdcolor(v, (uchar*)&color);
-		fillrect(maxr, stride, (uchar*)&color);
-		while(n-- > 0){
-			vncrdcolor(v, (uchar*)&color);
-			if(type == EncRre)
-				subr = vncrdrect(v);
-			else
-				subr = vncrdcorect(v);
-			if(!rectinrect(subr, maxr))
-				sysfatal("bad encoding from server");
-			fillrect(subr, stride, (uchar*)&color);
-		}
-		updatescreen(r);
-		break;
-
-	case EncHextile:
-		dohextile(v, r, stride);
-		updatescreen(r);
-		break;
-	}
-}
-
-static void
-pixcp8(uchar *dst, uchar *src)
-{
-	*dst = *src;
-}
-
-static void
-pixcp16(uchar *dst, uchar *src)
-{
-	*(ushort*)dst = *(ushort*)src;
-}
-
-static void
-pixcp32(uchar *dst, uchar *src)
-{
-	*(ulong*)dst = *(ulong*)src;
-}
-
-static void
-pixcp24(uchar *dst, uchar *src)
-{
-	dst[0] = src[0];
-	dst[1] = src[1];
-	dst[2] = src[2];
-}
-
-static int
-calcpixb(int bpp)
-{
-	if(bpp / 8 * 8 != bpp)
-		sysfatal("can't handle your screen");
-	return bpp / 8;
-}
-
-void
-readfromserver(Vnc *v)
-{
-	uchar type;
-	uchar junk[100];
-	long n;
-
-	vpixb = calcpixb(v->bpp);
-	pixb = calcpixb(screen->depth);
-	switch(pixb){
-	case 1:
-		pixcp = pixcp8;
-		break;
-	case 2:
-		pixcp = pixcp16;
-		break;
-	case 3:
-		pixcp = pixcp24;
-		break;
-	case 4:
-		pixcp = pixcp32;
-		break;
-	default:
-		sysfatal("can't handle your screen: bad depth %d", pixb);
-	}
-	vncsetdim(v, v->dim);
-	for(;;){
-		type = vncrdchar(v);
-		switch(type){
-		default:
-			sysfatal("bad message from server: %x", type);
-			break;
-		case MFrameUpdate:
-			vncrdchar(v);
-			n = vncrdshort(v);
-			while(n-- > 0)
-				dorectangle(v);
-			requestupdate(v, 1);
-			break;
-
-		case MSetCmap:
-			vncrdbytes(v, junk, 3);
-			n = vncrdshort(v);
-			vncgobble(v, n*3*2);
-			break;
-
-		case MBell:
-			break;
-
-		case MSAck:
-			break;
-
-		case MSCut:
-			vncrdbytes(v, junk, 3);
-			n = vncrdlong(v);
-			writesnarf(v, n);
-			break;
-		}
-	}
-}
--- a/sys/src/cmd/vnc/error.h
+++ /dev/null
@@ -1,48 +1,0 @@
-extern char Enoerror[];		/* no error */
-extern char Emount[];		/* inconsistent mount */
-extern char Eunmount[];		/* not mounted */
-extern char Eunion[];		/* not in union */
-extern char Emountrpc[];	/* mount rpc error */
-extern char Eshutdown[];	/* mounted device shut down */
-extern char Enocreate[];	/* mounted directory forbids creation */
-extern char Enonexist[];	/* file does not exist */
-extern char Eexist[];		/* file already exists */
-extern char Ebadsharp[];	/* unknown device in # filename */
-extern char Enotdir[];		/* not a directory */
-extern char Eisdir[];		/* file is a directory */
-extern char Ebadchar[];		/* bad character in file name */
-extern char Efilename[];	/* file name syntax */
-extern char Eperm[];		/* permission denied */
-extern char Ebadusefd[];	/* inappropriate use of fd */
-extern char Ebadarg[];		/* bad arg in system call */
-extern char Einuse[];		/* device or object already in use */
-extern char Eio[];		/* i/o error */
-extern char Etoobig[];		/* read or write too large */
-extern char Etoosmall[];	/* read or write too small */
-extern char Enoport[];		/* network port not available */
-extern char Ehungup[];		/* write to hungup channel */
-extern char Ebadctl[];		/* bad process or channel control request */
-extern char Enodev[];		/* no free devices */
-extern char Eprocdied[];	/* process exited */
-extern char Enochild[];		/* no living children */
-extern char Eioload[];		/* i/o error in demand load */
-extern char Enovmem[];		/* virtual memory allocation failed */
-extern char Ebadfd[];		/* fd out of range or not open */
-extern char Enofd[];			/* no free file descriptors */
-extern char Eisstream[];	/* seek on a stream */
-extern char Ebadexec[];		/* exec header invalid */
-extern char Etimedout[];	/* connection timed out */
-extern char Econrefused[];	/* connection refused */
-extern char Econinuse[];	/* connection in use */
-extern char Eintr[];		/* interrupted */
-extern char Enomem[];		/* kernel allocate failed */
-extern char Enoswap[];		/* swap space full */
-extern char Esoverlap[];	/* segments overlap */
-extern char Emouseset[];	/* mouse type already set */
-extern char Eshort[];		/* i/o count too small */
-extern char Egreg[];		/* ken has left the building */
-extern char Ebadspec[];		/* bad attach specifier */
-extern char Enoreg[];		/* process has no saved registers */
-extern char Enoattach[];	/* mount/attach disallowed */
-extern char Eshortstat[];	/* stat buffer too small */
-extern char Ebadstat[];		/* malformed stat buffer */
--- a/sys/src/cmd/vnc/errstr.h
+++ /dev/null
@@ -1,48 +1,0 @@
-char Enoerror[] = "no error";
-char Emount[] = "inconsistent mount";
-char Eunmount[] = "not mounted";
-char Eunion[] = "not in union";
-char Emountrpc[] = "mount rpc error";
-char Eshutdown[] = "mounted device shut down";
-char Enocreate[] = "mounted directory forbids creation";
-char Enonexist[] = "file does not exist";
-char Eexist[] = "file already exists";
-char Ebadsharp[] = "unknown device in # filename";
-char Enotdir[] = "not a directory";
-char Eisdir[] = "file is a directory";
-char Ebadchar[] = "bad character in file name";
-char Efilename[] = "file name syntax";
-char Eperm[] = "permission denied";
-char Ebadusefd[] = "inappropriate use of fd";
-char Ebadarg[] = "bad arg in system call";
-char Einuse[] = "device or object already in use";
-char Eio[] = "i/o error";
-char Etoobig[] = "read or write too large";
-char Etoosmall[] = "read or write too small";
-char Enoport[] = "network port not available";
-char Ehungup[] = "write to hungup channel";
-char Ebadctl[] = "bad process or channel control request";
-char Enodev[] = "no free devices";
-char Eprocdied[] = "process exited";
-char Enochild[] = "no living children";
-char Eioload[] = "i/o error in demand load";
-char Enovmem[] = "virtual memory allocation failed";
-char Ebadfd[] = "fd out of range or not open";
-char Enofd[] = "no free file descriptors";
-char Eisstream[] = "seek on a stream";
-char Ebadexec[] = "exec header invalid";
-char Etimedout[] = "connection timed out";
-char Econrefused[] = "connection refused";
-char Econinuse[] = "connection in use";
-char Eintr[] = "interrupted";
-char Enomem[] = "kernel allocate failed";
-char Enoswap[] = "swap space full";
-char Esoverlap[] = "segments overlap";
-char Emouseset[] = "mouse type already set";
-char Eshort[] = "i/o count too small";
-char Egreg[] = "ken has left the building";
-char Ebadspec[] = "bad attach specifier";
-char Enoreg[] = "process has no saved registers";
-char Enoattach[] = "mount/attach disallowed";
-char Eshortstat[] = "stat buffer too small";
-char Ebadstat[] = "malformed stat buffer";
--- a/sys/src/cmd/vnc/exporter.c
+++ /dev/null
@@ -1,94 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include "compat.h"
-
-typedef struct Exporter	Exporter;
-struct Exporter
-{
-	int	fd;
-	Chan	**roots;
-	int	nroots;
-};
-
-int
-mounter(char *mntpt, int how, int fd, int n)
-{
-	char buf[32];
-	int i, ok, mfd;
-
-	ok = 1;
-	for(i = 0; i < n; i++){
-		snprint(buf, sizeof buf, "%d", i);
-		mfd = dup(fd, -1);
-		if(mount(mfd, -1, mntpt, how, buf) == -1){
-			close(mfd);
-			fprint(2, "can't mount on %s: %r\n", mntpt);
-			ok = 0;
-			break;
-		}
-		close(mfd);
-		if(how == MREPL)
-			how = MAFTER;
-	}
-
-	close(fd);
-
-	return ok;
-}
-
-static void
-extramp(void *v)
-{
-	Exporter *ex;
-
-	rfork(RFNAMEG);
-	ex = v;
-	sysexport(ex->fd, ex->roots, ex->nroots);
-	shutdown();
-	exits(nil);
-}
-
-int
-exporter(Dev **dt, int *fd, int *sfd)
-{
-	Chan **roots;
-	Exporter ex;
-	int p[2], i, n, ed;
-
-	for(n = 0; dt[n] != nil; n++)
-		;
-	if(!n){
-		werrstr("no devices specified");
-		return 0;
-	}
-
-	ed = errdepth(-1);
-	if(waserror()){
-		werrstr(up->error);
-		return 0;
-	}
-
-	roots = smalloc(n * sizeof *roots);
-	for(i = 0; i < n; i++){
-		(*dt[i]->reset)();
-		(*dt[i]->init)();
-		roots[i] = (*dt[i]->attach)("");
-	}
-	poperror();
-	errdepth(ed);
-
-	if(pipe(p) < 0){
-		werrstr("can't make pipe: %r");
-		return 0;
-	}
-
-	*sfd = p[0];
-	*fd = p[1];
-
-	ex.fd = *sfd;
-	ex.roots = roots;
-	ex.nroots = n;
-	kproc("exporter", extramp, &ex);
-
-	return n;
-}
--- a/sys/src/cmd/vnc/exportfs.c
+++ /dev/null
@@ -1,804 +1,0 @@
-#include	<u.h>
-#include	<libc.h>
-#include	<fcall.h>
-#include	"compat.h"
-#include	"error.h"
-
-typedef	struct Fid	Fid;
-typedef	struct Export	Export;
-typedef	struct Exq	Exq;
-typedef	struct Exwork	Exwork;
-
-enum
-{
-	Nfidhash	= 32,
-	Maxfdata	= 8192,
-	Maxrpc		= IOHDRSZ + Maxfdata,
-};
-
-struct Export
-{
-	Ref	r;
-	Exq*	work;
-	Lock	fidlock;
-	Fid*	fid[Nfidhash];
-	int	io;		/* fd to read/write */
-	int	iounit;
-	int	nroots;
-	Chan	**roots;
-};
-
-struct Fid
-{
-	Fid*	next;
-	Fid**	last;
-	Chan*	chan;
-	long	offset;
-	int	fid;
-	int	ref;		/* fcalls using the fid; locked by Export.Lock */
-	int	attached;	/* fid attached or cloned but not clunked */
-};
-
-struct Exq
-{
-	Lock	lk;
-	int	responding;	/* writing out reply message */
-	int	noresponse;	/* don't respond to this one */
-	Exq*	next;
-	int	shut;		/* has been noted for shutdown */
-	Export*	export;
-	void*	slave;
-	Fcall	rpc;
-	uchar	buf[Maxrpc];
-};
-
-struct Exwork
-{
-	Lock	l;
-
-	int	ref;
-
-	int	nwaiters;	/* queue of slaves waiting for work */
-	QLock	qwait;
-	Rendez	rwait;
-
-	Exq	*head;		/* work waiting for a slave */
-	Exq	*tail;
-};
-
-Exwork exq;
-
-static void	exshutdown(Export*);
-static void	exflush(Export*, int, int);
-static void	exslave(void*);
-static void	exfree(Export*);
-static void	exportproc(Export*);
-
-static char*	Exattach(Export*, Fcall*, uchar*);
-static char*	Exauth(Export*, Fcall*, uchar*);
-static char*	Exclunk(Export*, Fcall*, uchar*);
-static char*	Excreate(Export*, Fcall*, uchar*);
-static char*	Exversion(Export*, Fcall*, uchar*);
-static char*	Exopen(Export*, Fcall*, uchar*);
-static char*	Exread(Export*, Fcall*, uchar*);
-static char*	Exremove(Export*, Fcall*, uchar*);
-static char*	Exsession(Export*, Fcall*, uchar*);
-static char*	Exstat(Export*, Fcall*, uchar*);
-static char*	Exwalk(Export*, Fcall*, uchar*);
-static char*	Exwrite(Export*, Fcall*, uchar*);
-static char*	Exwstat(Export*, Fcall*, uchar*);
-
-static char	*(*fcalls[Tmax])(Export*, Fcall*, uchar*);
-
-static char	Enofid[]   = "no such fid";
-static char	Eseekdir[] = "can't seek on a directory";
-static char	Ereaddir[] = "unaligned read of a directory";
-static int	exdebug = 0;
-
-int
-sysexport(int fd, Chan **roots, int nroots)
-{
-	Export *fs;
-
-	fs = smalloc(sizeof(Export));
-	fs->r.ref = 1;
-	fs->io = fd;
-	fs->roots = roots;
-	fs->nroots = nroots;
-
-	exportproc(fs);
-
-	return 0;
-}
-
-static void
-exportinit(void)
-{
-	lock(&exq.l);
-	exq.ref++;
-	if(fcalls[Tversion] != nil){
-		unlock(&exq.l);
-		return;
-	}
-
-	fmtinstall('F', fcallfmt);
-	fcalls[Tversion] = Exversion;
-	fcalls[Tauth] = Exauth;
-	fcalls[Tattach] = Exattach;
-	fcalls[Twalk] = Exwalk;
-	fcalls[Topen] = Exopen;
-	fcalls[Tcreate] = Excreate;
-	fcalls[Tread] = Exread;
-	fcalls[Twrite] = Exwrite;
-	fcalls[Tclunk] = Exclunk;
-	fcalls[Tremove] = Exremove;
-	fcalls[Tstat] = Exstat;
-	fcalls[Twstat] = Exwstat;
-	unlock(&exq.l);
-}
-
-static void
-exportproc(Export *fs)
-{
-	Exq *q;
-	int n, ed;
-
-	exportinit();
-	ed = errdepth(-1);
-	for(;;){
-		errdepth(ed);
-		q = smalloc(sizeof(Exq));
-
-		n = read9pmsg(fs->io, q->buf, Maxrpc);
-		if(n <= 0 || convM2S(q->buf, n, &q->rpc) != n)
-			break;
-
-		if(exdebug)
-			print("export %d <- %F\n", getpid(), &q->rpc);
-
-		if(q->rpc.type == Tflush){
-			exflush(fs, q->rpc.tag, q->rpc.oldtag);
-			free(q);
-			continue;
-		}
-
-		q->export = fs;
-		incref(&fs->r);
-
-		lock(&exq.l);
-		if(exq.head == nil)
-			exq.head = q;
-		else
-			exq.tail->next = q;
-		q->next = nil;
-		exq.tail = q;
-		n = exq.nwaiters;
-		if(n)
-			exq.nwaiters = n - 1;
-		unlock(&exq.l);
-		if(!n)
-			kproc("exportfs", exslave, nil);
-		rendwakeup(&exq.rwait);
-	}
-	free(q);
-	if(exdebug)
-		fprint(2, "export proc shutting down: %r\n");
-	exshutdown(fs);
-	exfree(fs);
-}
-
-static void
-exflush(Export *fs, int flushtag, int tag)
-{
-	Exq *q, **last;
-	Fcall fc;
-	uchar buf[Maxrpc];
-	int n;
-
-	/* hasn't been started? */
-	lock(&exq.l);
-	last = &exq.head;
-	for(q = exq.head; q != nil; q = q->next){
-		if(q->export == fs && q->rpc.tag == tag){
-			*last = q->next;
-			unlock(&exq.l);
-			exfree(fs);
-			free(q);
-			goto Respond;
-		}
-		last = &q->next;
-	}
-	unlock(&exq.l);
-
-	/* in progress? */
-	lock(&fs->r);
-	for(q = fs->work; q != nil; q = q->next){
-		if(q->rpc.tag == tag){
-			lock(&q->lk);
-			q->noresponse = 1;
-			if(!q->responding)
-				rendintr(q->slave);
-			unlock(&q->lk);
-			break;
-		}
-	}
-	unlock(&fs->r);
-
-Respond:
-	fc.type = Rflush;
-	fc.tag = flushtag;
-
-	n = convS2M(&fc, buf, Maxrpc);
-	if(n == 0)
-		panic("convS2M error on write");
-	if(write(fs->io, buf, n) != n)
-		panic("mount write");
-}
-
-static void
-exshutdown(Export *fs)
-{
-	Exq *q, **last;
-
-	lock(&exq.l);
-	last = &exq.head;
-	for(q = exq.head; q != nil; q = *last){
-		if(q->export == fs){
-			*last = q->next;
-			exfree(fs);
-			free(q);
-			continue;
-		}
-		last = &q->next;
-	}
-
-	/*
-	 * cleanly shut down the slaves if this is the last fs around
-	 */
-	exq.ref--;
-	if(!exq.ref)
-		rendwakeup(&exq.rwait);
-	unlock(&exq.l);
-
-	/*
-	 * kick any sleepers
-	 */
-	lock(&fs->r);
-	for(q = fs->work; q != nil; q = q->next){
-		lock(&q->lk);
-		q->noresponse = 1;
-		if(!q->responding)
-			rendintr(q->slave);
-		unlock(&q->lk);
-	}
-	unlock(&fs->r);
-}
-
-static void
-exfree(Export *fs)
-{
-	Fid *f, *n;
-	int i;
-
-	if(decref(&fs->r) != 0)
-		return;
-	for(i = 0; i < Nfidhash; i++){
-		for(f = fs->fid[i]; f != nil; f = n){
-			if(f->chan != nil)
-				cclose(f->chan);
-			n = f->next;
-			free(f);
-		}
-	}
-	free(fs);
-}
-
-static int
-exwork(void *)
-{
-	int work;
-
-	lock(&exq.l);
-	work = exq.head != nil || !exq.ref;
-	unlock(&exq.l);
-	return work;
-}
-
-static void
-exslave(void *)
-{
-	Export *fs;
-	Exq *q, *t, **last;
-	char *volatile err;
-	int n, ed;
-
-	while(waserror())
-		fprint(2, "exslave %d errored out of loop -- heading back in!\n", getpid());
-	ed = errdepth(-1);
-	for(;;){
-		errdepth(ed);
-		qlock(&exq.qwait);
-		if(waserror()){
-			qunlock(&exq.qwait);
-			nexterror();
-		}
-		rendsleep(&exq.rwait, exwork, nil);
-
-		lock(&exq.l);
-		if(!exq.ref){
-			unlock(&exq.l);
-			poperror();
-			qunlock(&exq.qwait);
-			break;
-		}
-		q = exq.head;
-		if(q == nil){
-			unlock(&exq.l);
-			poperror();
-			qunlock(&exq.qwait);
-			continue;
-		}
-		exq.head = q->next;
-		if(exq.head == nil)
-			exq.tail = nil;
-		poperror();
-		qunlock(&exq.qwait);
-
-		/*
-		 * put the job on the work queue before it's
-		 * visible as off of the head queue, so it's always
-		 * findable for flushes and shutdown
-		 */
-		q->slave = up;
-		q->noresponse = 0;
-		q->responding = 0;
-		rendclearintr();
-		fs = q->export;
-		lock(&fs->r);
-		q->next = fs->work;
-		fs->work = q;
-		unlock(&fs->r);
-
-		unlock(&exq.l);
-
-		if(exdebug > 1)
-			print("exslave dispatch %d %F\n", getpid(), &q->rpc);
-
-		if(waserror()){
-			print("exslave err %r\n");
-			err = up->error;
-		}else{
-			if(q->rpc.type >= Tmax || !fcalls[q->rpc.type])
-				err = "bad fcall type";
-			else
-				err = (*fcalls[q->rpc.type])(fs, &q->rpc, &q->buf[IOHDRSZ]);
-			poperror();
-		}
-
-		q->rpc.type++;
-		if(err){
-			q->rpc.type = Rerror;
-			q->rpc.ename = err;
-		}
-		n = convS2M(&q->rpc, q->buf, Maxrpc);
-
-		if(exdebug)
-			print("exslave %d -> %F\n", getpid(), &q->rpc);
-
-		lock(&q->lk);
-		if(!q->noresponse){
-			q->responding = 1;
-			unlock(&q->lk);
-			write(fs->io, q->buf, n);
-		}else
-			unlock(&q->lk);
-
-		/*
-		 * exflush might set noresponse at this point, but
-		 * setting noresponse means don't send a response now;
-		 * it's okay that we sent a response already.
-		 */
-		if(exdebug > 1)
-			print("exslave %d written %d\n", getpid(), q->rpc.tag);
-
-		lock(&fs->r);
-		last = &fs->work;
-		for(t = fs->work; t != nil; t = t->next){
-			if(t == q){
-				*last = q->next;
-				break;
-			}
-			last = &t->next;
-		}
-		unlock(&fs->r);
-
-		exfree(q->export);
-		free(q);
-
-		rendclearintr();
-		lock(&exq.l);
-		exq.nwaiters++;
-		unlock(&exq.l);
-	}
-	if(exdebug)
-		fprint(2, "export slaveshutting down\n");
-	kexit();
-}
-
-Fid*
-Exmkfid(Export *fs, int fid)
-{
-	ulong h;
-	Fid *f, *nf;
-
-	nf = mallocz(sizeof(Fid), 1);
-	if(nf == nil)
-		return nil;
-	lock(&fs->fidlock);
-	h = fid % Nfidhash;
-	for(f = fs->fid[h]; f != nil; f = f->next){
-		if(f->fid == fid){
-			unlock(&fs->fidlock);
-			free(nf);
-			return nil;
-		}
-	}
-
-	nf->next = fs->fid[h];
-	if(nf->next != nil)
-		nf->next->last = &nf->next;
-	nf->last = &fs->fid[h];
-	fs->fid[h] = nf;
-
-	nf->fid = fid;
-	nf->ref = 1;
-	nf->attached = 1;
-	nf->offset = 0;
-	nf->chan = nil;
-	unlock(&fs->fidlock);
-	return nf;
-}
-
-Fid*
-Exgetfid(Export *fs, int fid)
-{
-	Fid *f;
-	ulong h;
-
-	lock(&fs->fidlock);
-	h = fid % Nfidhash;
-	for(f = fs->fid[h]; f; f = f->next){
-		if(f->fid == fid){
-			if(f->attached == 0)
-				break;
-			f->ref++;
-			unlock(&fs->fidlock);
-			return f;
-		}
-	}
-	unlock(&fs->fidlock);
-	return nil;
-}
-
-void
-Exputfid(Export *fs, Fid *f)
-{
-	lock(&fs->fidlock);
-	f->ref--;
-	if(f->ref == 0 && f->attached == 0){
-		if(f->chan != nil)
-			cclose(f->chan);
-		f->chan = nil;
-		*f->last = f->next;
-		if(f->next != nil)
-			f->next->last = f->last;
-		unlock(&fs->fidlock);
-		free(f);
-		return;
-	}
-	unlock(&fs->fidlock);
-}
-
-static char*
-Exversion(Export *fs, Fcall *rpc, uchar *)
-{
-	if(rpc->msize < 256)
-		return "version: message size too small";
-	if(rpc->msize > Maxrpc)
-		rpc->msize = Maxrpc;
-	if(strncmp(rpc->version, "9P", 2) != 0){
-		rpc->version = "unknown";
-		return nil;
-	}
-
-	fs->iounit = rpc->msize - IOHDRSZ;
-	rpc->version = "9P2000";
-	return nil;
-}
-
-static char*
-Exauth(Export *, Fcall *, uchar *)
-{
-	return "vnc: authentication not required";
-}
-
-static char*
-Exattach(Export *fs, Fcall *rpc, uchar *)
-{
-	Fid *f;
-	int w;
-
-	w = 0;
-	if(rpc->aname != nil)
-		w = strtol(rpc->aname, nil, 10);
-	if(w < 0 || w > fs->nroots)
-		error(Ebadspec);
-	f = Exmkfid(fs, rpc->fid);
-	if(f == nil)
-		return Einuse;
-	if(waserror()){
-		f->attached = 0;
-		Exputfid(fs, f);
-		return up->error;
-	}
-	f->chan = cclone(fs->roots[w]);
-	poperror();
-	rpc->qid = f->chan->qid;
-	Exputfid(fs, f);
-	return nil;
-}
-
-static char*
-Exclunk(Export *fs, Fcall *rpc, uchar *)
-{
-	Fid *f;
-
-	f = Exgetfid(fs, rpc->fid);
-	if(f != nil){
-		f->attached = 0;
-		Exputfid(fs, f);
-	}
-	return nil;
-}
-
-static char*
-Exwalk(Export *fs, Fcall *rpc, uchar *)
-{
-	Fid *volatile f, *volatile nf;
-	Walkqid *wq;
-	Chan *c;
-	int i, nwname;
-	int volatile isnew;
-
-	f = Exgetfid(fs, rpc->fid);
-	if(f == nil)
-		return Enofid;
-	nf = nil;
-	if(waserror()){
-		Exputfid(fs, f);
-		if(nf != nil)
-			Exputfid(fs, nf);
-		return up->error;
-	}
-
-	/*
-	 * optional clone, but don't attach it until the walk succeeds.
-	 */
-	if(rpc->fid != rpc->newfid){
-		nf = Exmkfid(fs, rpc->newfid);
-		if(nf == nil)
-			error(Einuse);
-		nf->attached = 0;
-		isnew = 1;
-	}else{
-		nf = Exgetfid(fs, rpc->fid);
-		isnew = 0;
-	}
-
-	/*
-	 * let the device do the work
-	 */
-	c = f->chan;
-	nwname = rpc->nwname;
-	wq = (*devtab[c->type]->walk)(c, nf->chan, rpc->wname, nwname);
-	if(wq == nil)
-		error(Enonexist);
-
-	poperror();
-
-	/*
-	 * copy qid array
-	 */
-	for(i = 0; i < wq->nqid; i++)
-		rpc->wqid[i] = wq->qid[i];
-	rpc->nwqid = wq->nqid;
-
-	/*
-	 * update the channel if everything walked correctly.
-	 */
-	if(isnew && wq->nqid == nwname){
-		nf->chan = wq->clone;
-		nf->attached = 1;
-	}
-
-	free(wq);
-	Exputfid(fs, f);
-	Exputfid(fs, nf);
-	return nil;
-}
-
-static char*
-Exopen(Export *fs, Fcall *rpc, uchar *)
-{
-	Fid *volatile f;
-	Chan *c;
-	int iou;
-
-	f = Exgetfid(fs, rpc->fid);
-	if(f == nil)
-		return Enofid;
-	if(waserror()){
-		Exputfid(fs, f);
-		return up->error;
-	}
-	c = f->chan;
-	c = (*devtab[c->type]->open)(c, rpc->mode);
-	poperror();
-
-	f->chan = c;
-	f->offset = 0;
-	rpc->qid = f->chan->qid;
-	iou = f->chan->iounit;
-	if(iou > fs->iounit)
-		iou = fs->iounit;
-	rpc->iounit = iou;
-	Exputfid(fs, f);
-	return nil;
-}
-
-static char*
-Excreate(Export *fs, Fcall *rpc, uchar *)
-{
-	Fid *f;
-	Chan *c;
-	int iou;
-
-	f = Exgetfid(fs, rpc->fid);
-	if(f == nil)
-		return Enofid;
-	if(waserror()){
-		Exputfid(fs, f);
-		return up->error;
-	}
-	c = f->chan;
-	(*devtab[c->type]->create)(c, rpc->name, rpc->mode, rpc->perm);
-	poperror();
-
-	f->chan = c;
-	rpc->qid = f->chan->qid;
-	iou = f->chan->iounit;
-	if(iou > fs->iounit)
-		iou = fs->iounit;
-	rpc->iounit = iou;
-	Exputfid(fs, f);
-	return nil;
-}
-
-static char*
-Exread(Export *fs, Fcall *rpc, uchar *buf)
-{
-	Fid *f;
-	Chan *c;
-	long off;
-
-	f = Exgetfid(fs, rpc->fid);
-	if(f == nil)
-		return Enofid;
-
-	c = f->chan;
-
-	if(waserror()){
-		Exputfid(fs, f);
-		return up->error;
-	}
-
-	rpc->data = (char*)buf;
-	off = rpc->offset;
-	c->offset = off;
-	rpc->count = (*devtab[c->type]->read)(c, rpc->data, rpc->count, off);
-	poperror();
-	Exputfid(fs, f);
-	return nil;
-}
-
-static char*
-Exwrite(Export *fs, Fcall *rpc, uchar *)
-{
-	Fid *f;
-	Chan *c;
-
-	f = Exgetfid(fs, rpc->fid);
-	if(f == nil)
-		return Enofid;
-	if(waserror()){
-		Exputfid(fs, f);
-		return up->error;
-	}
-	c = f->chan;
-	if(c->qid.type & QTDIR)
-		error(Eisdir);
-	rpc->count = (*devtab[c->type]->write)(c, rpc->data, rpc->count, rpc->offset);
-	poperror();
-	Exputfid(fs, f);
-	return nil;
-}
-
-static char*
-Exstat(Export *fs, Fcall *rpc, uchar *buf)
-{
-	Fid *f;
-	Chan *c;
-
-	f = Exgetfid(fs, rpc->fid);
-	if(f == nil)
-		return Enofid;
-	if(waserror()){
-		Exputfid(fs, f);
-		return up->error;
-	}
-	c = f->chan;
-	rpc->stat = buf;
-	rpc->nstat = (*devtab[c->type]->stat)(c, rpc->stat, Maxrpc);
-	poperror();
-	Exputfid(fs, f);
-	return nil;
-}
-
-static char*
-Exwstat(Export *fs, Fcall *rpc, uchar *)
-{
-	Fid *f;
-	Chan *c;
-
-	f = Exgetfid(fs, rpc->fid);
-	if(f == nil)
-		return Enofid;
-	if(waserror()){
-		Exputfid(fs, f);
-		return up->error;
-	}
-	c = f->chan;
-	(*devtab[c->type]->wstat)(c, rpc->stat, rpc->nstat);
-	poperror();
-	Exputfid(fs, f);
-	return nil;
-}
-
-static char*
-Exremove(Export *fs, Fcall *rpc, uchar *)
-{
-	Fid *f;
-	Chan *c;
-
-	f = Exgetfid(fs, rpc->fid);
-	if(f == nil)
-		return Enofid;
-	if(waserror()){
-		Exputfid(fs, f);
-		return up->error;
-	}
-	c = f->chan;
-	(*devtab[c->type]->remove)(c);
-	poperror();
-
-	/*
-	 * chan is already clunked by remove.
-	 * however, we need to recover the chan,
-	 * and follow sysremove's lead in making to point to root.
-	 */
-	c->type = 0;
-
-	f->attached = 0;
-	Exputfid(fs, f);
-	return nil;
-}
--- a/sys/src/cmd/vnc/kbd.h
+++ /dev/null
@@ -1,21 +1,0 @@
-typedef struct	Snarf	Snarf;
-
-struct Snarf
-{
-	QLock;
-	int		vers;
-	int		n;
-	char		*buf;
-};
-
-enum
-{
-	MAXSNARF	= 100*1024
-};
-
-extern	Snarf		snarf;
-extern	int		kbdin;
-
-void			screenputs(char*, int);
-void			vncputc(int, int);
-void			setsnarf(char *buf, int n, int *vers);
--- a/sys/src/cmd/vnc/kbds.c
+++ /dev/null
@@ -1,74 +1,0 @@
-#include	<u.h>
-#include	<libc.h>
-#include	<keyboard.h>
-#include	"compat.h"
-#include	"kbd.h"
-#include   "ksym2utf.h"
-
-enum {
-	VKSpecial = 0xff00,
-};
-
-static Rune vnckeys[] =
-{
-[0x00]	0,	0,	0,	0,	0,	0,	0,	0,
-[0x08]	'\b',	'\t',	'\r',	0,	0,	'\n',	0,	0,
-[0x10]	0,	0,	0,	0,	Kscroll,0,	0,	0,
-[0x18]	0,	0,	0,	Kesc,	0,	0,	0,	0,
-[0x20]	0,	0,	0,	0,	0,	0,	0,	0,
-[0x28]	0,	0,	0,	0,	0,	0,	0,	0,
-[0x30]	0,	0,	0,	0,	0,	0,	0,	0,
-[0x38]	0,	0,	0,	0,	0,	0,	0,	0,
-[0x40]	0,	0,	0,	0,	0,	0,	0,	0,
-[0x48]	0,	0,	0,	0,	0,	0,	0,	0,
-[0x50]	Khome,	Kleft,	Kup,	Kright,	Kdown,	Kpgup,	Kpgdown,Kend,
-[0x58]	0,	0,	0,	0,	0,	0,	0,	0,
-[0x60]	0,	Kprint,	0,	Kins,	0,	0,	0,	0,
-[0x68]	0,	0,	0,	Kbreak,	0,	0,	0,	0,
-[0x70]	0,	0,	0,	0,	0,	0,	0,	0,
-[0x78]	0,	0,	0,	0,	0,	0,	0,	Knum,
-[0x80]	0,	0,	0,	0,	0,	0,	0,	0,
-[0x88]	0,	0,	0,	0,	0,	0,	0,	0,
-[0x90]	0,	0,	0,	0,	0,	0,	0,	0,
-[0x98]	0,	0,	0,	0,	0,	0,	0,	0,
-[0xa0]	0,	0,	0,	0,	0,	0,	0,	0,
-[0xa8]	0,	0,	'*',	'+',	0,	'-',	'.',	'/',
-[0xb0]	'0',	'1',	'2',	'3',	'4',	'5',	'6',	'7',
-[0xb8]	'8',	'9',	0,	0,	0,	'=',	0,	0,
-[0xc0]	0,	0,	0,	0,	0,	0,	0,	0,
-[0xc8]	0,	0,	0,	0,	0,	0,	0,	0,
-[0xd0]	0,	0,	0,	0,	0,	0,	0,	0,
-[0xd8]	0,	0,	0,	0,	0,	0,	0,	0,
-[0xe0]	0,	Kshift,	Kshift,	Kctl,	Kctl,	Kcaps,	Kcaps,	0,
-[0xe8]	0,	Kalt,	Kalt,	0,	0,	0,	0,	0,
-[0xf0]	0,	0,	0,	0,	0,	0,	0,	0,
-[0xf8]	0,	0,	0,	0,	0,	0,	0,	Kdel,
-};
-
-/*
- *  keyboard interrupt
- */
-void
-vncputc(int keyup, int c)
-{
-	char buf[16];
-
-	/*
- 	 *  character mapping
-	 */
-	if((c & VKSpecial) == VKSpecial){
-		c = vnckeys[c & 0xff];
-		if(c == 0)
-			return;
-	}
-	/*
-	 * map an xkeysym onto a utf-8 char
-	 */
-	if((c & 0xff00) && c < nelem(ksym2utf) && ksym2utf[c] != 0)
-		c = ksym2utf[c];
-	snprint(buf, sizeof(buf), "r%C", c);
-	if(keyup)
-		buf[0] = 'R';
-	if(kbdin >= 0)
-		write(kbdin, buf, strlen(buf)+1);
-}
--- a/sys/src/cmd/vnc/kbdv.c
+++ /dev/null
@@ -1,270 +1,0 @@
-#include "vnc.h"
-#include <keyboard.h>
-#include "utf2ksym.h"
-
-enum {
-	Xshift = 0xFFE1,
-	Xctl = 0xFFE3,
-	Xmeta = 0xFFE7,
-	Xalt = 0xFFE9,
-	Xsuper = 0xFFEB,
-};
-
-static struct {
-	Rune kbdc;
-	ulong keysym;
-} ktab[] = {
-	{'\b',		0xff08},
-	{'\t',		0xff09},
-	{'\n',		0xff0d},
-	/* {0x0b, 0xff0b}, */
-	{'\r',		0xff0d},
-	{Kesc,	0xff1b},
-	{Kins,	0xff63},
-	{Kdel,	0xffff},
-	{Khome,	0xff50},
-	{Kend,	0xff57},
-	{Kpgup,	0xff55},
-	{Kpgdown,	0xff56},
-	{Kleft,	0xff51},
-	{Kup,	0xff52},
-	{Kright,	0xff53},
-	{Kdown,	0xff54},
-	{KF|1,	0xffbe},
-	{KF|2,	0xffbf},
-	{KF|3,	0xffc0},
-	{KF|4,	0xffc1},
-	{KF|5,	0xffc2},
-	{KF|6,	0xffc3},
-	{KF|7,	0xffc4},
-	{KF|8,	0xffc5},
-	{KF|9,	0xffc6},
-	{KF|10,	0xffc7},
-	{KF|11,	0xffc8},
-	{KF|12,	0xffc9},
-
-	{Kshift, Xshift},
-	{Kalt, Xalt},
-	{Kaltgr, Xmeta},
-	{Kmod4, Xsuper},
-	{Kctl, Xctl},
-};
-
-static char shiftkey[128] = {
-	0, 0, 0, 0, 0, 0, 0, 0, /* nul soh stx etx eot enq ack bel */
-	0, 0, 0, 0, 0, 0, 0, 0, /* bs ht nl vt np cr so si */
-	0, 0, 0, 0, 0, 0, 0, 0, /* dle dc1 dc2 dc3 dc4 nak syn etb */
-	0, 0, 0, 0, 0, 0, 0, 0, /* can em sub esc fs gs rs us */
-	0, 1, 1, 1, 1, 1, 1, 0, /* sp ! " # $ % & ' */
-	1, 1, 1, 1, 0, 0, 0, 0, /* ( ) * + , - . / */
-	0, 0, 0, 0, 0, 0, 0, 0, /* 0 1 2 3 4 5 6 7 */
-	0, 0, 1, 0, 1, 0, 1, 1, /* 8 9 : ; < = > ? */
-	1, 1, 1, 1, 1, 1, 1, 1, /* @ A B C D E F G */
-	1, 1, 1, 1, 1, 1, 1, 1, /* H I J K L M N O */
-	1, 1, 1, 1, 1, 1, 1, 1, /* P Q R S T U V W */
-	1, 1, 1, 0, 0, 0, 1, 1, /* X Y Z [ \ ] ^ _ */
-	0, 0, 0, 0, 0, 0, 0, 0, /* ` a b c d e f g */
-	0, 0, 0, 0, 0, 0, 0, 0, /* h i j k l m n o */
-	0, 0, 0, 0, 0, 0, 0, 0, /* p q r s t u v w */
-	0, 0, 0, 1, 1, 1, 1, 0, /* x y z { | } ~ del  */
-};
-
-ulong
-runetoksym(Rune r)
-{
-	int i;
-
-	for(i=0; i<nelem(ktab); i++)
-		if(ktab[i].kbdc == r)
-			return ktab[i].keysym;
-	return r;
-}
-
-static void
-keyevent(Vnc *v, ulong ksym, int down)
-{
-	vnclock(v);
-	vncwrchar(v, MKey);
-	vncwrchar(v, down);
-	vncwrshort(v, 0);
-	vncwrlong(v, ksym);
-	vncflush(v);
-	vncunlock(v);
-}
-
-static void
-readcons(Vnc *v)
-{
-	char buf[256], k[10];
-	ulong ks;
-	int ctlfd, fd, kr, kn, w, shift, ctl, alt, super;
-	Rune r;
-
-	snprint(buf, sizeof buf, "%s/cons", display->devdir);
-	if((fd = open(buf, OREAD)) < 0)
-		sysfatal("open %s: %r", buf);
-
-	snprint(buf, sizeof buf, "%s/consctl", display->devdir);
-	if((ctlfd = open(buf, OWRITE)) < 0)
-		sysfatal("open %s: %r", buf);
-	write(ctlfd, "rawon", 5);
-
-	kn = 0;
-	shift = alt = ctl = super = 0;
-	for(;;){
-		while(!fullrune(k, kn)){
-			kr = read(fd, k+kn, sizeof k - kn);
-			if(kr <= 0)
-				sysfatal("bad read from kbd");
-			kn += kr;
-		}
-		w = chartorune(&r, k);
-		kn -= w;
-		memmove(k, &k[w], kn);
-		ks = runetoksym(r);
-
-		switch(r){
-		case Kalt:
-			alt = !alt;
-			keyevent(v, Xalt, alt);
-			break;
-		case Kctl:
-			ctl = !ctl;
-			keyevent(v, Xctl, ctl);
-			break;
-		case Kshift:
-			shift = !shift;
-			keyevent(v, Xshift, shift);
-			break;
-		case Kmod4:
-			super = !super;
-			keyevent(v, Xsuper, super);
-			break;
-		default:
-			if(r == ks && r < 0x1A){	/* control key */
-				keyevent(v, Xctl, 1);
-				keyevent(v, r+0x60, 1);	/* 0x60: make capital letter */
-				keyevent(v, r+0x60, 0);
-				keyevent(v, Xctl, 0);
-			}else{
-				/*
-				 * to send an upper case letter or shifted
-				 * punctuation, mac os x vnc server,
-				 * at least, needs a `shift' sent first.
-				 */
-				if(!shift && r == ks && r < sizeof shiftkey && shiftkey[r]){
-					shift = 1;
-					keyevent(v, Xshift, 1);
-				}
-				/*
-				 * map an xkeysym onto a utf-8 char.
-				 * allows Xvnc to read us, see utf2ksym.h
-				 */
-				if((ks & 0xff00) && ks < nelem(utf2ksym) && utf2ksym[ks] != 0)
-					ks = utf2ksym[ks];
-				keyevent(v, ks, 1);
-				/*
-				 * up event needed by vmware inside linux vnc server,
-				 * perhaps others.
-				 */
-				keyevent(v, ks, 0);
-			}
-
-			if(alt){
-				keyevent(v, Xalt, 0);
-				alt = 0;
-			}
-			if(ctl){
-				keyevent(v, Xctl, 0);
-				ctl = 0;
-			}
-			if(shift){
-				keyevent(v, Xshift, 0);
-				shift = 0;
-			}
-			if(super){
-				keyevent(v, Xsuper, 0);
-				super = 0;
-			}
-			break;
-		}
-	}
-}
-
-ulong
-runetovnc(Rune r)
-{
-	ulong k;
-
-	k = runetoksym(r);
-	if((k & 0xff00) && k < nelem(utf2ksym) && utf2ksym[k] != 0)
-		k = utf2ksym[k];
-	return k;
-}
-
-void
-readkbd(Vnc *v)
-{
-	char buf[128], buf2[128], *s;
-	int fd, n;
-	Rune r;
-
-	if((fd = open("/dev/kbd", OREAD)) < 0){
-		readcons(v);
-		return;
-	}
-
-	buf2[0] = 0;
-	buf2[1] = 0;
-	buf[0] = 0;
-	for(;;){
-		if(buf[0] != 0){
-			n = strlen(buf)+1;
-			memmove(buf, buf+n, sizeof(buf)-n);
-		}
-		if(buf[0] == 0){
-			n = read(fd, buf, sizeof(buf)-1);
-			if(n <= 0)
-				break;
-			buf[n-1] = 0;
-			buf[n] = 0;
-		}
-		switch(buf[0]){
-		case 'k':
-			s = buf+1;
-			while(*s){
-				s += chartorune(&r, s);
-				if(utfrune(buf2+1, r) == nil)
-					if((r == Kshift) ||
-					   utfrune(buf+1, Kctl) || 
-					   utfrune(buf+1, Kalt) ||
-					   utfrune(buf+1, Kmod4) ||
-					   utfrune(buf+1, Kaltgr))
-						keyevent(v, runetovnc(r), 1);
-			}
-			break;
-		case 'K':
-			s = buf2+1;
-			while(*s){
-				s += chartorune(&r, s);
-				if(utfrune(buf+1, r) == nil)
-					keyevent(v, runetovnc(r), 0);
-			}
-			break;
-		case 'c':
-			if(utfrune(buf2+1, Kctl) ||
-			   utfrune(buf2+1, Kalt) ||
-			   utfrune(buf2+1, Kmod4) ||
-			   utfrune(buf2+1, Kaltgr))
-				continue;
-			chartorune(&r, buf+1);
-			keyevent(v, runetovnc(r), 1);
-			if(utfrune(buf2+1, r) == nil)
-				keyevent(v, runetovnc(r), 0);
-		default:
-			continue;
-		}
-		strcpy(buf2, buf);
-	}
-}
-
--- a/sys/src/cmd/vnc/ksym2utf.h
+++ /dev/null
@@ -1,1097 +1,0 @@
-/*
- * VNC uses X11's keysyms defined in X11/keysym.h, this is a converter
- * to unicode characters
- */
-static ulong
-ksym2utf [] = {
-	[0x1a1]	L'Ą',
-	[0x1a2]	L'˘',
-	[0x1a3]	L'Ł',
-	[0x1a5]	L'Ľ',
-	[0x1a6]	L'Ś',
-	[0x1a9]	L'Š',
-	[0x1aa]	L'Ş',
-	[0x1ab]	L'Ť',
-	[0x1ac]	L'Ź',
-	[0x1ae]	L'Ž',
-	[0x1af]	L'Ż',
-	[0x1b1]	L'ą',
-	[0x1b2]	L'˛',
-	[0x1b3]	L'ł',
-	[0x1b5]	L'ľ',
-	[0x1b6]	L'ś',
-	[0x1b7]	L'ˇ',
-	[0x1b9]	L'š',
-	[0x1ba]	L'ş',
-	[0x1bb]	L'ť',
-	[0x1bc]	L'ź',
-	[0x1bd]	L'˝',
-	[0x1be]	L'ž',
-	[0x1bf]	L'ż',
-	[0x1c0]	L'Ŕ',
-	[0x1c3]	L'Ă',
-	[0x1c5]	L'Ĺ',
-	[0x1c6]	L'Ć',
-	[0x1c8]	L'Č',
-	[0x1ca]	L'Ę',
-	[0x1cc]	L'Ě',
-	[0x1cf]	L'Ď',
-	[0x1d0]	L'Đ',
-	[0x1d1]	L'Ń',
-	[0x1d2]	L'Ň',
-	[0x1d5]	L'Ő',
-	[0x1d8]	L'Ř',
-	[0x1d9]	L'Ů',
-	[0x1db]	L'Ű',
-	[0x1de]	L'Ţ',
-	[0x1e0]	L'ŕ',
-	[0x1e3]	L'ă',
-	[0x1e5]	L'ĺ',
-	[0x1e6]	L'ć',
-	[0x1e8]	L'č',
-	[0x1ea]	L'ę',
-	[0x1ec]	L'ě',
-	[0x1ef]	L'ď',
-	[0x1f0]	L'đ',
-	[0x1f1]	L'ń',
-	[0x1f2]	L'ň',
-	[0x1f5]	L'ő',
-	[0x1f8]	L'ř',
-	[0x1f9]	L'ů',
-	[0x1fb]	L'ű',
-	[0x1fe]	L'ţ',
-	[0x1ff]	L'˙',
-	[0x2a1]	L'Ħ',
-	[0x2a6]	L'Ĥ',
-	[0x2a9]	L'İ',
-	[0x2ab]	L'Ğ',
-	[0x2ac]	L'Ĵ',
-	[0x2b1]	L'ħ',
-	[0x2b6]	L'ĥ',
-	[0x2b9]	L'ı',
-	[0x2bb]	L'ğ',
-	[0x2bc]	L'ĵ',
-	[0x2c5]	L'Ċ',
-	[0x2c6]	L'Ĉ',
-	[0x2d5]	L'Ġ',
-	[0x2d8]	L'Ĝ',
-	[0x2dd]	L'Ŭ',
-	[0x2de]	L'Ŝ',
-	[0x2e5]	L'ċ',
-	[0x2e6]	L'ĉ',
-	[0x2f5]	L'ġ',
-	[0x2f8]	L'ĝ',
-	[0x2fd]	L'ŭ',
-	[0x2fe]	L'ŝ',
-	[0x3a2]	L'ĸ',
-	[0x3a3]	L'Ŗ',
-	[0x3a5]	L'Ĩ',
-	[0x3a6]	L'Ļ',
-	[0x3aa]	L'Ē',
-	[0x3ab]	L'Ģ',
-	[0x3ac]	L'Ŧ',
-	[0x3b3]	L'ŗ',
-	[0x3b5]	L'ĩ',
-	[0x3b6]	L'ļ',
-	[0x3ba]	L'ē',
-	[0x3bb]	L'ģ',
-	[0x3bc]	L'ŧ',
-	[0x3bd]	L'Ŋ',
-	[0x3bf]	L'ŋ',
-	[0x3c0]	L'Ā',
-	[0x3c7]	L'Į',
-	[0x3cc]	L'Ė',
-	[0x3cf]	L'Ī',
-	[0x3d1]	L'Ņ',
-	[0x3d2]	L'Ō',
-	[0x3d3]	L'Ķ',
-	[0x3d9]	L'Ų',
-	[0x3dd]	L'Ũ',
-	[0x3de]	L'Ū',
-	[0x3e0]	L'ā',
-	[0x3e7]	L'į',
-	[0x3ec]	L'ė',
-	[0x3ef]	L'ī',
-	[0x3f1]	L'ņ',
-	[0x3f2]	L'ō',
-	[0x3f3]	L'ķ',
-	[0x3f9]	L'ų',
-	[0x3fd]	L'ũ',
-	[0x3fe]	L'ū',
-	[0x4a1]	L'。',
-	[0x4a2]	L'〈',
-	[0x4a3]	L'〉',
-	[0x4a4]	L'、',
-	[0x4a5]	L'・',
-	[0x4a6]	L'ヲ',
-	[0x4a7]	L'ァ',
-	[0x4a8]	L'ィ',
-	[0x4a9]	L'ゥ',
-	[0x4aa]	L'ェ',
-	[0x4ab]	L'ォ',
-	[0x4ac]	L'ャ',
-	[0x4ad]	L'ュ',
-	[0x4ae]	L'ョ',
-	[0x4af]	L'ッ',
-	[0x4b0]	L'ー',
-	[0x4b1]	L'ア',
-	[0x4b2]	L'イ',
-	[0x4b3]	L'ウ',
-	[0x4b4]	L'エ',
-	[0x4b5]	L'オ',
-	[0x4b6]	L'カ',
-	[0x4b7]	L'キ',
-	[0x4b8]	L'ク',
-	[0x4b9]	L'ケ',
-	[0x4ba]	L'コ',
-	[0x4bb]	L'サ',
-	[0x4bc]	L'シ',
-	[0x4bd]	L'ス',
-	[0x4be]	L'セ',
-	[0x4bf]	L'ソ',
-	[0x4c0]	L'タ',
-	[0x4c1]	L'チ',
-	[0x4c2]	L'ツ',
-	[0x4c3]	L'テ',
-	[0x4c4]	L'ト',
-	[0x4c5]	L'ナ',
-	[0x4c6]	L'ニ',
-	[0x4c7]	L'ヌ',
-	[0x4c8]	L'ネ',
-	[0x4c9]	L'ノ',
-	[0x4ca]	L'ハ',
-	[0x4cb]	L'ヒ',
-	[0x4cc]	L'フ',
-	[0x4cd]	L'ヘ',
-	[0x4ce]	L'ホ',
-	[0x4cf]	L'マ',
-	[0x4d0]	L'ミ',
-	[0x4d1]	L'ム',
-	[0x4d2]	L'メ',
-	[0x4d3]	L'モ',
-	[0x4d4]	L'ヤ',
-	[0x4d5]	L'ユ',
-	[0x4d6]	L'ヨ',
-	[0x4d7]	L'ラ',
-	[0x4d8]	L'リ',
-	[0x4d9]	L'ル',
-	[0x4da]	L'レ',
-	[0x4db]	L'ロ',
-	[0x4dc]	L'ワ',
-	[0x4dd]	L'ン',
-	[0x4de]	L'゛',
-	[0x4df]	L'゜',
-	[0x58a]	L'ロ',
-	[0x58b]	L'ワ',
-	[0x58c]	L'ン',
-	[0x58d]	L'゛',
-	[0x58e]	L'゜',
-	[0x590]	L'۰',
-	[0x591]	L'۱',
-	[0x592]	L'۲',
-	[0x593]	L'۳',
-	[0x594]	L'۴',
-	[0x595]	L'۵',
-	[0x596]	L'۶',
-	[0x597]	L'۷',
-	[0x598]	L'۸',
-	[0x599]	L'۹',
-	[0x5a5]	L'٪',
-	[0x5a6]	L'ٰ',
-	[0x5a7]	L'ٹ',
-	[0x5a8]	L'پ',
-	[0x5a9]	L'چ',
-	[0x5aa]	L'ڈ',
-	[0x5ab]	L'ڑ',
-	[0x5ac]	L'،',
-	[0x5ae]	L'۔',
-	[0x5b0]	L'٠',
-	[0x5b1]	L'١',
-	[0x5b2]	L'٢',
-	[0x5b3]	L'٣',
-	[0x5b4]	L'٤',
-	[0x5b5]	L'٥',
-	[0x5b6]	L'٦',
-	[0x5b7]	L'٧',
-	[0x5b8]	L'٨',
-	[0x5b9]	L'٩',
-	[0x5bb]	L'؛',
-	[0x5bf]	L'؟',
-	[0x5c1]	L'ء',
-	[0x5c2]	L'آ',
-	[0x5c3]	L'أ',
-	[0x5c4]	L'ؤ',
-	[0x5c5]	L'إ',
-	[0x5c6]	L'ئ',
-	[0x5c7]	L'ا',
-	[0x5c8]	L'ب',
-	[0x5c9]	L'ة',
-	[0x5ca]	L'ت',
-	[0x5cb]	L'ث',
-	[0x5cc]	L'ج',
-	[0x5cd]	L'ح',
-	[0x5ce]	L'خ',
-	[0x5cf]	L'د',
-	[0x5d0]	L'ذ',
-	[0x5d1]	L'ر',
-	[0x5d2]	L'ز',
-	[0x5d3]	L'س',
-	[0x5d4]	L'ش',
-	[0x5d5]	L'ص',
-	[0x5d6]	L'ض',
-	[0x5d7]	L'ط',
-	[0x5d8]	L'ظ',
-	[0x5d9]	L'ع',
-	[0x5da]	L'غ',
-	[0x5e0]	L'ـ',
-	[0x5e1]	L'ف',
-	[0x5e2]	L'ق',
-	[0x5e3]	L'ك',
-	[0x5e4]	L'ل',
-	[0x5e5]	L'م',
-	[0x5e6]	L'ن',
-	[0x5e7]	L'ه',
-	[0x5e8]	L'و',
-	[0x5e9]	L'ى',
-	[0x5ea]	L'ي',
-	[0x5eb]	L'ً',
-	[0x5ec]	L'ٌ',
-	[0x5ed]	L'ٍ',
-	[0x5ee]	L'َ',
-	[0x5ef]	L'ُ',
-	[0x5f0]	L'ِ',
-	[0x5f1]	L'ّ',
-	[0x5f2]	L'ْ',
-	[0x5f3]	L'ٓ',
-	[0x5f4]	L'ٔ',
-	[0x5f5]	L'ٕ',
-	[0x5f6]	L'ژ',
-	[0x5f7]	L'ڤ',
-	[0x5f8]	L'ک',
-	[0x5f9]	L'گ',
-	[0x5fa]	L'ں',
-	[0x5fb]	L'ھ',
-	[0x5fc]	L'ی',
-	[0x5fd]	L'ے',
-	[0x5fe]	L'ہ',
-	[0x680]	L'Ғ',
-	[0x681]	L'Җ',
-	[0x682]	L'Қ',
-	[0x683]	L'Ҝ',
-	[0x684]	L'Ң',
-	[0x685]	L'Ү',
-	[0x686]	L'Ұ',
-	[0x687]	L'Ҳ',
-	[0x688]	L'Ҷ',
-	[0x689]	L'Ҹ',
-	[0x68a]	L'Һ',
-	[0x68c]	L'Ә',
-	[0x68d]	L'Ӣ',
-	[0x68e]	L'Ө',
-	[0x68f]	L'Ӯ',
-	[0x690]	L'ғ',
-	[0x691]	L'җ',
-	[0x692]	L'қ',
-	[0x693]	L'ҝ',
-	[0x694]	L'ң',
-	[0x695]	L'ү',
-	[0x696]	L'ұ',
-	[0x697]	L'ҳ',
-	[0x698]	L'ҷ',
-	[0x699]	L'ҹ',
-	[0x69a]	L'һ',
-	[0x69c]	L'ә',
-	[0x69d]	L'ӣ',
-	[0x69e]	L'ө',
-	[0x69f]	L'ӯ',
-	[0x6a1]	L'ђ',
-	[0x6a2]	L'ѓ',
-	[0x6a3]	L'ё',
-	[0x6a4]	L'є',
-	[0x6a5]	L'ѕ',
-	[0x6a6]	L'і',
-	[0x6a7]	L'ї',
-	[0x6a8]	L'ј',
-	[0x6a9]	L'љ',
-	[0x6aa]	L'њ',
-	[0x6ab]	L'ћ',
-	[0x6ac]	L'ќ',
-	[0x6ad]	L'ґ',
-	[0x6ae]	L'ў',
-	[0x6af]	L'џ',
-	[0x6b0]	L'№',
-	[0x6b1]	L'Ђ',
-	[0x6b2]	L'Ѓ',
-	[0x6b3]	L'Ё',
-	[0x6b4]	L'Є',
-	[0x6b5]	L'Ѕ',
-	[0x6b6]	L'І',
-	[0x6b7]	L'Ї',
-	[0x6b8]	L'Ј',
-	[0x6b9]	L'Љ',
-	[0x6ba]	L'Њ',
-	[0x6bb]	L'Ћ',
-	[0x6bc]	L'Ќ',
-	[0x6bd]	L'Ґ',
-	[0x6be]	L'Ў',
-	[0x6bf]	L'Џ',
-	[0x6c0]	L'ю',
-	[0x6c1]	L'а',
-	[0x6c2]	L'б',
-	[0x6c3]	L'ц',
-	[0x6c4]	L'д',
-	[0x6c5]	L'е',
-	[0x6c6]	L'ф',
-	[0x6c7]	L'г',
-	[0x6c8]	L'х',
-	[0x6c9]	L'и',
-	[0x6ca]	L'й',
-	[0x6cb]	L'к',
-	[0x6cc]	L'л',
-	[0x6cd]	L'м',
-	[0x6ce]	L'н',
-	[0x6cf]	L'о',
-	[0x6d0]	L'п',
-	[0x6d1]	L'я',
-	[0x6d2]	L'р',
-	[0x6d3]	L'с',
-	[0x6d4]	L'т',
-	[0x6d5]	L'у',
-	[0x6d6]	L'ж',
-	[0x6d7]	L'в',
-	[0x6d8]	L'ь',
-	[0x6d9]	L'ы',
-	[0x6da]	L'з',
-	[0x6db]	L'ш',
-	[0x6dc]	L'э',
-	[0x6dd]	L'щ',
-	[0x6de]	L'ч',
-	[0x6df]	L'ъ',
-	[0x6e0]	L'Ю',
-	[0x6e1]	L'А',
-	[0x6e2]	L'Б',
-	[0x6e3]	L'Ц',
-	[0x6e4]	L'Д',
-	[0x6e5]	L'Е',
-	[0x6e6]	L'Ф',
-	[0x6e7]	L'Г',
-	[0x6e8]	L'Х',
-	[0x6e9]	L'И',
-	[0x6ea]	L'Й',
-	[0x6eb]	L'К',
-	[0x6ec]	L'Л',
-	[0x6ed]	L'М',
-	[0x6ee]	L'Н',
-	[0x6ef]	L'О',
-	[0x6f0]	L'П',
-	[0x6f1]	L'Я',
-	[0x6f2]	L'Р',
-	[0x6f3]	L'С',
-	[0x6f4]	L'Т',
-	[0x6f5]	L'У',
-	[0x6f6]	L'Ж',
-	[0x6f7]	L'В',
-	[0x6f8]	L'Ь',
-	[0x6f9]	L'Ы',
-	[0x6fa]	L'З',
-	[0x6fb]	L'Ш',
-	[0x6fc]	L'Э',
-	[0x6fd]	L'Щ',
-	[0x6fe]	L'Ч',
-	[0x6ff]	L'Ъ',
-	[0x7a1]	L'Ά',
-	[0x7a2]	L'Έ',
-	[0x7a3]	L'Ή',
-	[0x7a4]	L'Ί',
-	[0x7a5]	L'Ϊ',
-	[0x7a7]	L'Ό',
-	[0x7a8]	L'Ύ',
-	[0x7a9]	L'Ϋ',
-	[0x7ab]	L'Ώ',
-	[0x7ae]	L'΅',
-	[0x7af]	L'―',
-	[0x7b1]	L'ά',
-	[0x7b2]	L'έ',
-	[0x7b3]	L'ή',
-	[0x7b4]	L'ί',
-	[0x7b5]	L'ϊ',
-	[0x7b6]	L'ΐ',
-	[0x7b7]	L'ό',
-	[0x7b8]	L'ύ',
-	[0x7b9]	L'ϋ',
-	[0x7ba]	L'ΰ',
-	[0x7bb]	L'ώ',
-	[0x7c1]	L'Α',
-	[0x7c2]	L'Β',
-	[0x7c3]	L'Γ',
-	[0x7c4]	L'Δ',
-	[0x7c5]	L'Ε',
-	[0x7c6]	L'Ζ',
-	[0x7c7]	L'Η',
-	[0x7c8]	L'Θ',
-	[0x7c9]	L'Ι',
-	[0x7ca]	L'Κ',
-	[0x7cb]	L'Λ',
-	[0x7cc]	L'Μ',
-	[0x7cd]	L'Ν',
-	[0x7ce]	L'Ξ',
-	[0x7cf]	L'Ο',
-	[0x7d0]	L'Π',
-	[0x7d1]	L'Ρ',
-	[0x7d2]	L'Σ',
-	[0x7d4]	L'Τ',
-	[0x7d5]	L'Υ',
-	[0x7d6]	L'Φ',
-	[0x7d7]	L'Χ',
-	[0x7d8]	L'Ψ',
-	[0x7d9]	L'Ω',
-	[0x7e1]	L'α',
-	[0x7e2]	L'β',
-	[0x7e3]	L'γ',
-	[0x7e4]	L'δ',
-	[0x7e5]	L'ε',
-	[0x7e6]	L'ζ',
-	[0x7e7]	L'η',
-	[0x7e8]	L'θ',
-	[0x7e9]	L'ι',
-	[0x7ea]	L'κ',
-	[0x7eb]	L'λ',
-	[0x7ec]	L'μ',
-	[0x7ed]	L'ν',
-	[0x7ee]	L'ξ',
-	[0x7ef]	L'ο',
-	[0x7f0]	L'π',
-	[0x7f1]	L'ρ',
-	[0x7f2]	L'σ',
-	[0x7f3]	L'ς',
-	[0x7f4]	L'τ',
-	[0x7f5]	L'υ',
-	[0x7f6]	L'φ',
-	[0x7f7]	L'χ',
-	[0x7f8]	L'ψ',
-	[0x7f9]	L'ω',
-	[0x8a4]	L'⌠',
-	[0x8a5]	L'⌡',
-	[0x8a7]	L'⌜',
-	[0x8a8]	L'⌝',
-	[0x8a9]	L'⌞',
-	[0x8aa]	L'⌟',
-	[0x8bc]	L'≤',
-	[0x8bd]	L'≠',
-	[0x8be]	L'≥',
-	[0x8bf]	L'∫',
-	[0x8c0]	L'∴',
-	[0x8c2]	L'∞',
-	[0x8c5]	L'∇',
-	[0x8c8]	L'≅',
-	[0x8c9]	L'≆',
-	[0x8ce]	L'⊢',
-	[0x8d6]	L'√',
-	[0x8da]	L'⊂',
-	[0x8db]	L'⊃',
-	[0x8dc]	L'∩',
-	[0x8dd]	L'∪',
-	[0x8de]	L'∧',
-	[0x8df]	L'∨',
-	[0x8f6]	L'ƒ',
-	[0x8fb]	L'←',
-	[0x8fc]	L'↑',
-	[0x8fd]	L'→',
-	[0x8fe]	L'↓',
-	[0x9df]	L'␢',
-	[0x9e0]	L'♦',
-	[0x9e1]	L'▦',
-	[0x9e2]	L'␉',
-	[0x9e3]	L'␌',
-	[0x9e4]	L'␍',
-	[0x9e5]	L'␊',
-	[0x9e8]	L'␊',
-	[0x9e9]	L'␋',
-	[0x9ea]	L'┘',
-	[0x9eb]	L'┐',
-	[0x9ec]	L'┌',
-	[0x9ed]	L'└',
-	[0x9ee]	L'┼',
-	[0x9ef]	L'─',
-	[0x9f4]	L'├',
-	[0x9f5]	L'┤',
-	[0x9f6]	L'┴',
-	[0x9f7]	L'┬',
-	[0x9f8]	L'│',
-	[0xaa1]	L' ',
-	[0xaa2]	L' ',
-	[0xaa3]	L' ',
-	[0xaa4]	L' ',
-	[0xaa5]	L' ',
-	[0xaa6]	L' ',
-	[0xaa7]	L' ',
-	[0xaa8]	L' ',
-	[0xaa9]	L'—',
-	[0xaaa]	L'–',
-	[0xaae]	L'…',
-	[0xaaf]	L'‥',
-	[0xab0]	L'⅓',
-	[0xab1]	L'⅔',
-	[0xab2]	L'⅕',
-	[0xab3]	L'⅖',
-	[0xab4]	L'⅗',
-	[0xab5]	L'⅘',
-	[0xab6]	L'⅙',
-	[0xab7]	L'⅚',
-	[0xab8]	L'℅',
-	[0xabb]	L'‒',
-	[0xabc]	L'‹',
-	[0xabd]	L'․',
-	[0xabe]	L'›',
-	[0xac3]	L'⅛',
-	[0xac4]	L'⅜',
-	[0xac5]	L'⅝',
-	[0xac6]	L'⅞',
-	[0xac9]	L'™',
-	[0xaca]	L'℠',
-	[0xacc]	L'◁',
-	[0xacd]	L'▷',
-	[0xace]	L'○',
-	[0xacf]	L'▭',
-	[0xad0]	L'‘',
-	[0xad1]	L'’',
-	[0xad2]	L'“',
-	[0xad3]	L'”',
-	[0xad4]	L'℞',
-	[0xad6]	L'′',
-	[0xad7]	L'″',
-	[0xad9]	L'✝',
-	[0xadb]	L'∎',
-	[0xadc]	L'◂',
-	[0xadd]	L'‣',
-	[0xade]	L'●',
-	[0xadf]	L'▬',
-	[0xae0]	L'◦',
-	[0xae1]	L'▫',
-	[0xae2]	L'▮',
-	[0xae3]	L'▵',
-	[0xae4]	L'▿',
-	[0xae5]	L'☆',
-	[0xae6]	L'•',
-	[0xae7]	L'▪',
-	[0xae8]	L'▴',
-	[0xae9]	L'▾',
-	[0xaea]	L'☚',
-	[0xaeb]	L'☛',
-	[0xaec]	L'♣',
-	[0xaed]	L'♦',
-	[0xaee]	L'♥',
-	[0xaf0]	L'✠',
-	[0xaf1]	L'†',
-	[0xaf2]	L'‡',
-	[0xaf3]	L'✓',
-	[0xaf4]	L'☒',
-	[0xaf5]	L'♯',
-	[0xaf6]	L'♭',
-	[0xaf7]	L'♂',
-	[0xaf8]	L'♀',
-	[0xaf9]	L'℡',
-	[0xafa]	L'⌕',
-	[0xafb]	L'℗',
-	[0xafc]	L'‸',
-	[0xafd]	L'‚',
-	[0xafe]	L'„',
-	[0xcdf]	L'‗',
-	[0xce0]	L'א',
-	[0xce1]	L'ב',
-	[0xce2]	L'ג',
-	[0xce3]	L'ד',
-	[0xce4]	L'ה',
-	[0xce5]	L'ו',
-	[0xce6]	L'ז',
-	[0xce7]	L'ח',
-	[0xce8]	L'ט',
-	[0xce9]	L'י',
-	[0xcea]	L'ך',
-	[0xceb]	L'כ',
-	[0xcec]	L'ל',
-	[0xced]	L'ם',
-	[0xcee]	L'מ',
-	[0xcef]	L'ן',
-	[0xcf0]	L'נ',
-	[0xcf1]	L'ס',
-	[0xcf2]	L'ע',
-	[0xcf3]	L'ף',
-	[0xcf4]	L'פ',
-	[0xcf5]	L'ץ',
-	[0xcf6]	L'צ',
-	[0xcf7]	L'ק',
-	[0xcf8]	L'ר',
-	[0xcf9]	L'ש',
-	[0xcfa]	L'ת',
-	[0xda1]	L'ก',
-	[0xda2]	L'ข',
-	[0xda3]	L'ฃ',
-	[0xda4]	L'ค',
-	[0xda5]	L'ฅ',
-	[0xda6]	L'ฆ',
-	[0xda7]	L'ง',
-	[0xda8]	L'จ',
-	[0xda9]	L'ฉ',
-	[0xdaa]	L'ช',
-	[0xdab]	L'ซ',
-	[0xdac]	L'ฌ',
-	[0xdad]	L'ญ',
-	[0xdae]	L'ฎ',
-	[0xdaf]	L'ฏ',
-	[0xdb0]	L'ฐ',
-	[0xdb1]	L'ฑ',
-	[0xdb2]	L'ฒ',
-	[0xdb3]	L'ณ',
-	[0xdb4]	L'ด',
-	[0xdb5]	L'ต',
-	[0xdb6]	L'ถ',
-	[0xdb7]	L'ท',
-	[0xdb8]	L'ธ',
-	[0xdb9]	L'น',
-	[0xdba]	L'บ',
-	[0xdbb]	L'ป',
-	[0xdbc]	L'ผ',
-	[0xdbd]	L'ฝ',
-	[0xdbe]	L'พ',
-	[0xdbf]	L'ฟ',
-	[0xdc0]	L'ภ',
-	[0xdc1]	L'ม',
-	[0xdc2]	L'ย',
-	[0xdc3]	L'ร',
-	[0xdc4]	L'ฤ',
-	[0xdc5]	L'ล',
-	[0xdc6]	L'ฦ',
-	[0xdc7]	L'ว',
-	[0xdc8]	L'ศ',
-	[0xdc9]	L'ษ',
-	[0xdca]	L'ส',
-	[0xdcb]	L'ห',
-	[0xdcc]	L'ฬ',
-	[0xdcd]	L'อ',
-	[0xdce]	L'ฮ',
-	[0xdcf]	L'ฯ',
-	[0xdd0]	L'ะ',
-	[0xdd1]	L'ั',
-	[0xdd2]	L'า',
-	[0xdd3]	L'ำ',
-	[0xdd4]	L'ิ',
-	[0xdd5]	L'ี',
-	[0xdd6]	L'ึ',
-	[0xdd7]	L'ื',
-	[0xdd8]	L'ุ',
-	[0xdd9]	L'ู',
-	[0xdda]	L'ฺ',
-	[0xdde]	L'฾',
-	[0xddf]	L'฿',
-	[0xde0]	L'เ',
-	[0xde1]	L'แ',
-	[0xde2]	L'โ',
-	[0xde3]	L'ใ',
-	[0xde4]	L'ไ',
-	[0xde5]	L'ๅ',
-	[0xde6]	L'ๆ',
-	[0xde7]	L'็',
-	[0xde8]	L'่',
-	[0xde9]	L'้',
-	[0xdea]	L'๊',
-	[0xdeb]	L'๋',
-	[0xdec]	L'์',
-	[0xded]	L'ํ',
-	[0xdf0]	L'๐',
-	[0xdf1]	L'๑',
-	[0xdf2]	L'๒',
-	[0xdf3]	L'๓',
-	[0xdf4]	L'๔',
-	[0xdf5]	L'๕',
-	[0xdf6]	L'๖',
-	[0xdf7]	L'๗',
-	[0xdf8]	L'๘',
-	[0xdf9]	L'๙',
-	[0xea1]	L'ᄁ',
-	[0xea2]	L'ᄁ',
-	[0xea3]	L'ᆪ',
-	[0xea4]	L'ᄂ',
-	[0xea5]	L'ᆬ',
-	[0xea6]	L'ᆭ',
-	[0xea7]	L'ᄃ',
-	[0xea8]	L'ᄄ',
-	[0xea9]	L'ᄅ',
-	[0xeaa]	L'ᆰ',
-	[0xeab]	L'ᆱ',
-	[0xeac]	L'ᆲ',
-	[0xead]	L'ᆳ',
-	[0xeae]	L'ᆴ',
-	[0xeaf]	L'ᆵ',
-	[0xeb0]	L'ᆶ',
-	[0xeb1]	L'ᄆ',
-	[0xeb2]	L'ᄇ',
-	[0xeb3]	L'ᄈ',
-	[0xeb4]	L'ᆹ',
-	[0xeb5]	L'ᄉ',
-	[0xeb6]	L'ᄊ',
-	[0xeb7]	L'ᄋ',
-	[0xeb8]	L'ᄌ',
-	[0xeb9]	L'ᄍ',
-	[0xeba]	L'ᄎ',
-	[0xebb]	L'ᄏ',
-	[0xebc]	L'ᄐ',
-	[0xebd]	L'ᄑ',
-	[0xebe]	L'ᄒ',
-	[0xebf]	L'ᅡ',
-	[0xec0]	L'ᅢ',
-	[0xec1]	L'ᅣ',
-	[0xec2]	L'ᅤ',
-	[0xec3]	L'ᅥ',
-	[0xec4]	L'ᅦ',
-	[0xec5]	L'ᅧ',
-	[0xec6]	L'ᅨ',
-	[0xec7]	L'ᅩ',
-	[0xec8]	L'ᅪ',
-	[0xec9]	L'ᅫ',
-	[0xeca]	L'ᅬ',
-	[0xecb]	L'ᅭ',
-	[0xecc]	L'ᅮ',
-	[0xecd]	L'ᅯ',
-	[0xece]	L'ᅰ',
-	[0xecf]	L'ᅱ',
-	[0xed0]	L'ᅲ',
-	[0xed1]	L'ᅳ',
-	[0xed2]	L'ᅴ',
-	[0xed3]	L'ᅵ',
-	[0xed4]	L'ᆨ',
-	[0xed5]	L'ᆩ',
-	[0xed6]	L'ᆪ',
-	[0xed7]	L'ᆫ',
-	[0xed8]	L'ᆬ',
-	[0xed9]	L'ᆭ',
-	[0xeda]	L'ᆮ',
-	[0xedb]	L'ᆯ',
-	[0xedc]	L'ᆰ',
-	[0xedd]	L'ᆱ',
-	[0xede]	L'ᆲ',
-	[0xedf]	L'ᆳ',
-	[0xee0]	L'ᆴ',
-	[0xee1]	L'ᆵ',
-	[0xee2]	L'ᆶ',
-	[0xee3]	L'ᆷ',
-	[0xee4]	L'ᆸ',
-	[0xee5]	L'ᆹ',
-	[0xee6]	L'ᆺ',
-	[0xee7]	L'ᆻ',
-	[0xee8]	L'ᆼ',
-	[0xee9]	L'ᆽ',
-	[0xeea]	L'ᆾ',
-	[0xeeb]	L'ᆿ',
-	[0xeec]	L'ᇀ',
-	[0xeed]	L'ᇁ',
-	[0xeee]	L'ᇂ',
-	[0xef2]	L'ᅀ',
-	[0xef5]	L'ᅙ',
-	[0xef6]	L'ᆞ',
-	[0xef8]	L'ᇫ',
-	[0xefa]	L'ᇹ',
-	[0xeff]	L'₩',
-	[0x12a1]	L'Ḃ',
-	[0x12a2]	L'ḃ',
-	[0x12a6]	L'Ḋ',
-	[0x12a8]	L'Ẁ',
-	[0x12aa]	L'Ẃ',
-	[0x12ab]	L'ḋ',
-	[0x12ac]	L'Ỳ',
-	[0x12b0]	L'Ḟ',
-	[0x12b1]	L'ḟ',
-	[0x12b4]	L'Ṁ',
-	[0x12b5]	L'ṁ',
-	[0x12b7]	L'Ṗ',
-	[0x12b8]	L'ẁ',
-	[0x12b9]	L'ṗ',
-	[0x12ba]	L'ẃ',
-	[0x12bb]	L'Ṡ',
-	[0x12bc]	L'ỳ',
-	[0x12bd]	L'Ẅ',
-	[0x12be]	L'ẅ',
-	[0x12bf]	L'ṡ',
-	[0x12d0]	L'Ŵ',
-	[0x12d7]	L'Ṫ',
-	[0x12de]	L'Ŷ',
-	[0x12f0]	L'ŵ',
-	[0x12f7]	L'ṫ',
-	[0x12fe]	L'ŷ',
-	[0x13bc]	L'Œ',
-	[0x13bd]	L'œ',
-	[0x13be]	L'Ÿ',
-	[0x14a1]	L'❁',
-	[0x14a2]	L'§',
-	[0x14a3]	L'։',
-	[0x14a4]	L')',
-	[0x14a5]	L'(',
-	[0x14a6]	L'»',
-	[0x14a7]	L'«',
-	[0x14a8]	L'—',
-	[0x14a9]	L'.',
-	[0x14aa]	L'՝',
-	[0x14ab]	L',',
-	[0x14ac]	L'–',
-	[0x14ad]	L'֊',
-	[0x14ae]	L'…',
-	[0x14af]	L'՜',
-	[0x14b0]	L'՛',
-	[0x14b1]	L'՞',
-	[0x14b2]	L'Ա',
-	[0x14b3]	L'ա',
-	[0x14b4]	L'Բ',
-	[0x14b5]	L'բ',
-	[0x14b6]	L'Գ',
-	[0x14b7]	L'գ',
-	[0x14b8]	L'Դ',
-	[0x14b9]	L'դ',
-	[0x14ba]	L'Ե',
-	[0x14bb]	L'ե',
-	[0x14bc]	L'Զ',
-	[0x14bd]	L'զ',
-	[0x14be]	L'Է',
-	[0x14bf]	L'է',
-	[0x14c0]	L'Ը',
-	[0x14c1]	L'ը',
-	[0x14c2]	L'Թ',
-	[0x14c3]	L'թ',
-	[0x14c4]	L'Ժ',
-	[0x14c5]	L'ժ',
-	[0x14c6]	L'Ի',
-	[0x14c7]	L'ի',
-	[0x14c8]	L'Լ',
-	[0x14c9]	L'լ',
-	[0x14ca]	L'Խ',
-	[0x14cb]	L'խ',
-	[0x14cc]	L'Ծ',
-	[0x14cd]	L'ծ',
-	[0x14ce]	L'Կ',
-	[0x14cf]	L'կ',
-	[0x14d0]	L'Հ',
-	[0x14d1]	L'հ',
-	[0x14d2]	L'Ձ',
-	[0x14d3]	L'ձ',
-	[0x14d4]	L'Ղ',
-	[0x14d5]	L'ղ',
-	[0x14d6]	L'Ճ',
-	[0x14d7]	L'ճ',
-	[0x14d8]	L'Մ',
-	[0x14d9]	L'մ',
-	[0x14da]	L'Յ',
-	[0x14db]	L'յ',
-	[0x14dc]	L'Ն',
-	[0x14dd]	L'ն',
-	[0x14de]	L'Շ',
-	[0x14df]	L'շ',
-	[0x14e0]	L'Ո',
-	[0x14e1]	L'ո',
-	[0x14e2]	L'Չ',
-	[0x14e3]	L'չ',
-	[0x14e4]	L'Պ',
-	[0x14e5]	L'պ',
-	[0x14e6]	L'Ջ',
-	[0x14e7]	L'ջ',
-	[0x14e8]	L'Ռ',
-	[0x14e9]	L'ռ',
-	[0x14ea]	L'Ս',
-	[0x14eb]	L'ս',
-	[0x14ec]	L'Վ',
-	[0x14ed]	L'վ',
-	[0x14ee]	L'Տ',
-	[0x14ef]	L'տ',
-	[0x14f0]	L'Ր',
-	[0x14f1]	L'ր',
-	[0x14f2]	L'Ց',
-	[0x14f3]	L'ց',
-	[0x14f4]	L'Ւ',
-	[0x14f5]	L'ւ',
-	[0x14f6]	L'Փ',
-	[0x14f7]	L'փ',
-	[0x14f8]	L'Ք',
-	[0x14f9]	L'ք',
-	[0x14fa]	L'Օ',
-	[0x14fb]	L'օ',
-	[0x14fc]	L'Ֆ',
-	[0x14fd]	L'ֆ',
-	[0x14fe]	L'’',
-	[0x14ff]	L''',
-	[0x15d0]	L'ა',
-	[0x15d1]	L'ბ',
-	[0x15d2]	L'გ',
-	[0x15d3]	L'დ',
-	[0x15d4]	L'ე',
-	[0x15d5]	L'ვ',
-	[0x15d6]	L'ზ',
-	[0x15d7]	L'თ',
-	[0x15d8]	L'ი',
-	[0x15d9]	L'კ',
-	[0x15da]	L'ლ',
-	[0x15db]	L'მ',
-	[0x15dc]	L'ნ',
-	[0x15dd]	L'ო',
-	[0x15de]	L'პ',
-	[0x15df]	L'ჟ',
-	[0x15e0]	L'რ',
-	[0x15e1]	L'ს',
-	[0x15e2]	L'ტ',
-	[0x15e3]	L'უ',
-	[0x15e4]	L'ფ',
-	[0x15e5]	L'ქ',
-	[0x15e6]	L'ღ',
-	[0x15e7]	L'ყ',
-	[0x15e8]	L'შ',
-	[0x15e9]	L'ჩ',
-	[0x15ea]	L'ც',
-	[0x15eb]	L'ძ',
-	[0x15ec]	L'წ',
-	[0x15ed]	L'ჭ',
-	[0x15ee]	L'ხ',
-	[0x15ef]	L'ჯ',
-	[0x15f0]	L'ჰ',
-	[0x15f1]	L'ჱ',
-	[0x15f2]	L'ჲ',
-	[0x15f3]	L'ჳ',
-	[0x15f4]	L'ჴ',
-	[0x15f5]	L'ჵ',
-	[0x15f6]	L'ჶ',
-	[0x16a2]	L'',
-	[0x16a3]	L'Ẋ',
-	[0x16a5]	L'',
-	[0x16a6]	L'Ĭ',
-	[0x16a7]	L'',
-	[0x16a8]	L'',
-	[0x16a9]	L'Ƶ',
-	[0x16aa]	L'Ǧ',
-	[0x16af]	L'Ɵ',
-	[0x16b2]	L'',
-	[0x16b3]	L'ẋ',
-	[0x16b4]	L'Ǒ',
-	[0x16b5]	L'',
-	[0x16b6]	L'ĭ',
-	[0x16b7]	L'',
-	[0x16b8]	L'',
-	[0x16b9]	L'ƶ',
-	[0x16ba]	L'ǧ',
-	[0x16bd]	L'ǒ',
-	[0x16bf]	L'ɵ',
-	[0x16c6]	L'Ə',
-	[0x16d1]	L'Ḷ',
-	[0x16d2]	L'',
-	[0x16d3]	L'',
-	[0x16e1]	L'ḷ',
-	[0x16e2]	L'',
-	[0x16e3]	L'',
-	[0x16f6]	L'ə',
-	[0x1e9f]	L'̃',
-	[0x1ea0]	L'Ạ',
-	[0x1ea1]	L'ạ',
-	[0x1ea2]	L'Ả',
-	[0x1ea3]	L'ả',
-	[0x1ea4]	L'Ấ',
-	[0x1ea5]	L'ấ',
-	[0x1ea6]	L'Ầ',
-	[0x1ea7]	L'ầ',
-	[0x1ea8]	L'Ẩ',
-	[0x1ea9]	L'ẩ',
-	[0x1eaa]	L'Ẫ',
-	[0x1eab]	L'ẫ',
-	[0x1eac]	L'Ậ',
-	[0x1ead]	L'ậ',
-	[0x1eae]	L'Ắ',
-	[0x1eaf]	L'ắ',
-	[0x1eb0]	L'Ằ',
-	[0x1eb1]	L'ằ',
-	[0x1eb2]	L'Ẳ',
-	[0x1eb3]	L'ẳ',
-	[0x1eb4]	L'Ẵ',
-	[0x1eb5]	L'ẵ',
-	[0x1eb6]	L'Ặ',
-	[0x1eb7]	L'ặ',
-	[0x1eb8]	L'Ẹ',
-	[0x1eb9]	L'ẹ',
-	[0x1eba]	L'Ẻ',
-	[0x1ebb]	L'ẻ',
-	[0x1ebc]	L'Ẽ',
-	[0x1ebd]	L'ẽ',
-	[0x1ebe]	L'Ế',
-	[0x1ebf]	L'ế',
-	[0x1ec0]	L'Ề',
-	[0x1ec1]	L'ề',
-	[0x1ec2]	L'Ể',
-	[0x1ec3]	L'ể',
-	[0x1ec4]	L'Ễ',
-	[0x1ec5]	L'ễ',
-	[0x1ec6]	L'Ệ',
-	[0x1ec7]	L'ệ',
-	[0x1ec8]	L'Ỉ',
-	[0x1ec9]	L'ỉ',
-	[0x1eca]	L'Ị',
-	[0x1ecb]	L'ị',
-	[0x1ecc]	L'Ọ',
-	[0x1ecd]	L'ọ',
-	[0x1ece]	L'Ỏ',
-	[0x1ecf]	L'ỏ',
-	[0x1ed0]	L'Ố',
-	[0x1ed1]	L'ố',
-	[0x1ed2]	L'Ồ',
-	[0x1ed3]	L'ồ',
-	[0x1ed4]	L'Ổ',
-	[0x1ed5]	L'ổ',
-	[0x1ed6]	L'Ỗ',
-	[0x1ed7]	L'ỗ',
-	[0x1ed8]	L'Ộ',
-	[0x1ed9]	L'ộ',
-	[0x1eda]	L'Ớ',
-	[0x1edb]	L'ớ',
-	[0x1edc]	L'Ờ',
-	[0x1edd]	L'ờ',
-	[0x1ede]	L'Ở',
-	[0x1edf]	L'ở',
-	[0x1ee0]	L'Ỡ',
-	[0x1ee1]	L'ỡ',
-	[0x1ee2]	L'Ợ',
-	[0x1ee3]	L'ợ',
-	[0x1ee4]	L'Ụ',
-	[0x1ee5]	L'ụ',
-	[0x1ee6]	L'Ủ',
-	[0x1ee7]	L'ủ',
-	[0x1ee8]	L'Ứ',
-	[0x1ee9]	L'ứ',
-	[0x1eea]	L'Ừ',
-	[0x1eeb]	L'ừ',
-	[0x1eec]	L'Ử',
-	[0x1eed]	L'ử',
-	[0x1eee]	L'Ữ',
-	[0x1eef]	L'ữ',
-	[0x1ef0]	L'Ự',
-	[0x1ef1]	L'ự',
-	[0x1ef2]	L'̀',
-	[0x1ef3]	L'́',
-	[0x1ef4]	L'Ỵ',
-	[0x1ef5]	L'ỵ',
-	[0x1ef6]	L'Ỷ',
-	[0x1ef7]	L'ỷ',
-	[0x1ef8]	L'Ỹ',
-	[0x1ef9]	L'ỹ',
-	[0x1efa]	L'Ơ',
-	[0x1efb]	L'ơ',
-	[0x1efc]	L'Ư',
-	[0x1efd]	L'ư',
-	[0x1efe]	L'̉',
-	[0x1eff]	L'̣',
-	[0x20a0]	L'₠',
-	[0x20a1]	L'₡',
-	[0x20a2]	L'₢',
-	[0x20a3]	L'₣',
-	[0x20a4]	L'₤',
-	[0x20a5]	L'₥',
-	[0x20a6]	L'₦',
-	[0x20a7]	L'₧',
-	[0x20a8]	L'₨',
-	[0x20a9]	L'₩',
-	[0x20aa]	L'₪',
-	[0x20ab]	L'₫',
-	[0x20ac]	L'€',
-
-};
\ No newline at end of file
--- a/sys/src/cmd/vnc/mkfile
+++ /dev/null
@@ -1,60 +1,0 @@
-</$objtype/mkfile
-
-TARG=vncs vncv
-BIN=/$objtype/bin
-
-OFILES=\
-	proto.$O\
-	auth.$O\
-
-SOFILES=\
-	devdraw.$O\
-	devmouse.$O\
-	devcons.$O\
-	screen.$O\
-	exporter.$O\
-	dev.$O\
-	chan.$O\
-	compat.$O\
-	exportfs.$O\
-	kbds.$O\
-	rre.$O\
-	rlist.$O\
-
-COFILES=\
-	draw.$O\
-	kbdv.$O\
-	color.$O\
-	wsys.$O\
-
-HFILES=\
-	vnc.h\
-	screen.h\
-	compat.h\
-	errstr.h\
-	kbd.h\
-	vncv.h\
-	vncs.h\
-
-UPDATE=\
-	mkfile\
-	$HFILES\
-	${OFILES:%.$O=%.c}\
-	${SOFILES:%.$O=%.c}\
-	${COFILES:%.$O=%.c}\
-	${TARG:%=%.c}\
-
-
-default:V:	all
-
-</sys/src/cmd/mkmany
-
-$O.vncs:	$SOFILES
-
-$O.vncv:	$COFILES
-
-errstr.h:	error.h
-	sed 's/extern //;s,;.*/\* (.*) \*/, = "\1";,' < error.h > errstr.h
-
-kbds.$O:	ksym2utf.h
-kbdv.$O:	utf2ksym.h
--- a/sys/src/cmd/vnc/proto.c
+++ /dev/null
@@ -1,294 +1,0 @@
-#include "vnc.h"
-
-#define SHORT(p) (((p)[0]<<8)|((p)[1]))
-#define LONG(p) ((SHORT(p)<<16)|SHORT(p+2))
-
-uchar zero[64];
-
-Vnc*
-vncinit(int fd, int cfd, Vnc *v)
-{
-        if(v == nil)
-		v = mallocz(sizeof(*v), 1);
-	Binit(&v->in, fd, OREAD);
-	Binit(&v->out, fd, OWRITE);
-	v->datafd = fd;
-	v->ctlfd = cfd;
-	return v;
-}
-
-void
-vncterm(Vnc *v)
-{
-	Bterm(&v->out);
-	Bterm(&v->in);
-}
-
-void
-vncflush(Vnc *v)
-{
-	if(Bflush(&v->out) < 0){
-		if(verbose > 1)
-			fprint(2, "hungup while sending flush: %r\n");
-		vnchungup(v);
-	}
-}
-
-uchar
-vncrdchar(Vnc *v)
-{
-	uchar buf[1];
-
-	vncrdbytes(v, buf, 1);
-	return buf[0];
-}
-
-ushort
-vncrdshort(Vnc *v)
-{
-	uchar buf[2];
-
-	vncrdbytes(v, buf, 2);
-	return SHORT(buf);
-}
-
-ulong
-vncrdlong(Vnc *v)
-{
-	uchar buf[4];
-
-	vncrdbytes(v, buf, 4);
-	return LONG(buf);
-}
-
-Point
-vncrdpoint(Vnc *v)
-{
-	Point p;
-
-	p.x = vncrdshort(v);
-	p.y = vncrdshort(v);
-	return p;
-}
-
-Rectangle
-vncrdrect(Vnc *v)
-{
-	Rectangle r;
-
-	r.min.x = vncrdshort(v);
-	r.min.y = vncrdshort(v);
-	r.max.x = r.min.x + vncrdshort(v);
-	r.max.y = r.min.y + vncrdshort(v);
-	return r;
-}
-
-Rectangle
-vncrdcorect(Vnc *v)
-{
-	Rectangle r;
-
-	r.min.x = vncrdchar(v);
-	r.min.y = vncrdchar(v);
-	r.max.x = r.min.x + vncrdchar(v);
-	r.max.y = r.min.y + vncrdchar(v);
-	return r;
-}
-
-void
-vncrdbytes(Vnc *v, void *a, int n)
-{
-	if(Bread(&v->in, a, n) != n){
-		if(verbose > 1)
-			fprint(2, "hungup while reading\n");
-		vnchungup(v);
-	}
-}
-
-Pixfmt
-vncrdpixfmt(Vnc *v)
-{
-	Pixfmt fmt;
-	uchar pad[3];
-
-	fmt.bpp = vncrdchar(v);
-	fmt.depth = vncrdchar(v);
-	fmt.bigendian = vncrdchar(v);
-	fmt.truecolor = vncrdchar(v);
-	fmt.red.max = vncrdshort(v);
-	fmt.green.max = vncrdshort(v);
-	fmt.blue.max = vncrdshort(v);
-	fmt.red.shift = vncrdchar(v);
-	fmt.green.shift = vncrdchar(v);
-	fmt.blue.shift = vncrdchar(v);
-	vncrdbytes(v, pad, 3);
-	return fmt;
-}
-
-char*
-vncrdstring(Vnc *v)
-{
-	ulong len;
-	char *s;
-
-	len = vncrdlong(v);
-	s = malloc(len+1);
-	assert(s != nil);
-
-	vncrdbytes(v, s, len);
-	s[len] = '\0';
-	return s;
-}
-
-/*
- * on the server side of the negotiation protocol, we read
- * the client response and then run the negotiated function.
- * in some cases (e.g., TLS) the negotiated function needs to
- * use v->datafd directly and be sure that no data has been
- * buffered away in the Bio.  since we know the client is waiting
- * for our response, it won't have sent any until we respond.
- * thus we read the response with vncrdstringx, which goes
- * behind bio's back.
- */
-char*
-vncrdstringx(Vnc *v)
-{
-	char tmp[4];
-	char *s;
-	ulong len;
-
-	assert(Bbuffered(&v->in) == 0);
-	if(readn(v->datafd, tmp, 4) != 4){
-		fprint(2, "cannot rdstringx: %r");
-		vnchungup(v);
-	}
-	len = LONG(tmp);
-	s = malloc(len+1);
-	assert(s != nil);
-	if(readn(v->datafd, s, len) != len){
-		fprint(2, "cannot rdstringx len %lud: %r", len);
-		vnchungup(v);
-	}
-	s[len] = '\0';
-	return s;
-}
-
-void
-vncwrstring(Vnc *v, char *s)
-{
-	ulong len;
-
-	len = strlen(s);
-	vncwrlong(v, len);
-	vncwrbytes(v, s, len);
-}
-
-void
-vncwrbytes(Vnc *v, void *a, int n)
-{
-	if(Bwrite(&v->out, a, n) < 0){
-		if(verbose > 1) 
-			fprint(2, "hungup while writing bytes\n");
-		vnchungup(v);
-	}
-}
-
-void
-vncwrlong(Vnc *v, ulong u)
-{
-	uchar buf[4];
-
-	buf[0] = u>>24;
-	buf[1] = u>>16;
-	buf[2] = u>>8;
-	buf[3] = u;
-	vncwrbytes(v, buf, 4);
-}
-
-void
-vncwrshort(Vnc *v, ushort u)
-{
-	uchar buf[2];
-
-	buf[0] = u>>8;
-	buf[1] = u;
-	vncwrbytes(v, buf, 2);
-}
-
-void
-vncwrchar(Vnc *v, uchar c)
-{
-	vncwrbytes(v, &c, 1);
-}
-
-void
-vncwrpixfmt(Vnc *v, Pixfmt *fmt)
-{
-	vncwrchar(v, fmt->bpp);
-	vncwrchar(v, fmt->depth);
-	vncwrchar(v, fmt->bigendian);
-	vncwrchar(v, fmt->truecolor);
-	vncwrshort(v, fmt->red.max);
-	vncwrshort(v, fmt->green.max);
-	vncwrshort(v, fmt->blue.max);
-	vncwrchar(v, fmt->red.shift);
-	vncwrchar(v, fmt->green.shift);
-	vncwrchar(v, fmt->blue.shift);
-	vncwrbytes(v, zero, 3);
-}
-
-void
-vncwrrect(Vnc *v, Rectangle r)
-{
-	vncwrshort(v, r.min.x);
-	vncwrshort(v, r.min.y);
-	vncwrshort(v, r.max.x-r.min.x);
-	vncwrshort(v, r.max.y-r.min.y);
-}
-
-void
-vncwrpoint(Vnc *v, Point p)
-{
-	vncwrshort(v, p.x);
-	vncwrshort(v, p.y);
-}
-
-void
-vnclock(Vnc *v)
-{
-	qlock(v);
-}
-
-void
-vncunlock(Vnc *v)
-{
-	qunlock(v);
-}
-
-void
-hexdump(void *a, int n)
-{
-	uchar *p, *ep;
-
-	p = a;
-	ep = p+n;
-
-	for(; p<ep; p++) 
-		print("%.2ux ", *p);
-	print("\n");
-}
-
-void
-vncgobble(Vnc *v, long n)
-{
-	uchar buf[8192];
-	long m;
-
-	while(n > 0){
-		m = n;
-		if(m > sizeof(buf))
-			m = sizeof(buf);
-		vncrdbytes(v, buf, m);
-		n -= m;
-	}
-}
--- a/sys/src/cmd/vnc/rlist.c
+++ /dev/null
@@ -1,286 +1,0 @@
-#include "vnc.h"
-#include "vncs.h"
-
-static int tot;
-static void rprint(Rlist*);
-
-static void
-growrlist(Rlist *rlist, int n)
-{
-	int old;
-
-	if(rlist->nrect+n <= rlist->maxrect)
-		return;
-
-	old = rlist->maxrect;
-	while(rlist->nrect+n > rlist->maxrect){
-		if(rlist->maxrect == 0)
-			rlist->maxrect = 16;
-		else
-			rlist->maxrect *= 2;
-	}
-
-	tot += rlist->maxrect - old;
-	if(tot > 10000)
-		sysfatal("too many rectangles");
-
-	rlist->rect = realloc(rlist->rect, rlist->maxrect*sizeof(rlist->rect[0]));
-	if(rlist->rect == nil)
-		sysfatal("realloc failed in growrlist");
-}
-
-static void
-rappend(Rlist *rl, Rectangle r)
-{
-	growrlist(rl, 1);
-	rl->rect[rl->nrect++] = r;
-}
-
-/* remove rectangle i from the list */
-static int
-rtrim(Rlist *r, int i)
-{
-	if(i < 0 || i >= r->nrect)
-		return 0;
-	if(i == r->nrect-1){
-		r->nrect--;
-		return 1;
-	}
-	r->rect[i] = r->rect[--r->nrect];
-	return 1;
-}
-
-static int
-rectadjacent(Rectangle r, Rectangle s)
-{
-	return r.min.x<=s.max.x && s.min.x<=r.max.x &&
-	       r.min.y<=s.max.y && s.min.y<=r.max.y;
-}
-
-/*
- * If s shares three edges with r, compute the
- * rectangle r - s and return 1.
- * Else return 0.
- */
-static int
-rectubr(Rectangle *r, Rectangle s)
-{
-	if(r->min.y==s.min.y && r->max.y==s.max.y){
-		if(r->min.x == s.min.x){
-			r->min.x = s.max.x;
-			assert(r->max.x > r->min.x);
-			return 1;
-		}
-		if(r->max.x == s.max.x){
-			r->max.x = s.min.x;
-			assert(r->max.x > r->min.x);
-			return 1;
-		}
-	}
-	if(r->min.x==s.min.x && r->max.x==s.max.x){
-		if(r->min.y == s.min.y){
-			r->min.y = s.max.y;
-			assert(r->max.y > r->min.y);
-			return 1;
-		}
-		if(r->max.y == s.max.y){
-			r->max.y = s.min.y;
-			assert(r->max.y > r->min.y);
-			return 1;
-		}
-	}
-	return 0;
-}
-
-/*
- * If s is a corner of r, remove s from r, yielding
- * two rectangles r and rr.  R holds the part with
- * smaller coordinates.
- */
-static int
-rectcornersubr(Rectangle *r, Rectangle s, Rectangle *rr)
-{
-#	define UPRIGHT(r) Pt((r).max.x, (r).min.y)
-#	define LOWLEFT(r) Pt((r).min.x, (r).max.y)
-
-	*rr = *r;
-
-	if(s.min.x == r->min.x){  
-		if(s.min.y == r->min.y){  // upper left
-			*rr = Rpt(UPRIGHT(s), r->max);
-			*r = Rpt(LOWLEFT(s), LOWLEFT(*rr));
-			return 1;
-		}
-		if(s.max.y == r->max.y){ // lower left
-			*rr = Rpt(Pt(s.max.x, r->min.y), r->max);
-			*r = Rpt(r->min, UPRIGHT(s));
-			return 1;
-		}
-	}
-	if(s.max.x == r->max.x){
-		if(s.max.y == r->max.y){ // lower right
-			*rr = Rpt(Pt(s.min.x, r->min.y), UPRIGHT(s));
-			*r = Rpt(r->min, LOWLEFT(s));
-			return 1;
-		}
-		if(s.min.y == r->min.y){ // upper right
-			*rr = Rpt(LOWLEFT(s), r->max);
-			*r = Rpt(r->min, LOWLEFT(*rr));
-			return 1;
-		}
-	}
-	return 0;
-}
-
-/*
- * If s is a band cutting r into two pieces, set r to one piece
- * and rr to the other.
- */
-static int
-recttridesubr(Rectangle *nr, Rectangle s, Rectangle *rr)
-{
-	*rr = *nr;
-	if((nr->min.x == s.min.x && nr->max.x == s.max.x) &&
-	    (nr->min.y < s.min.y && s.max.y < nr->max.y)){
-		nr->max.y = s.min.y;
-		rr->min.y = s.max.y;
-		return 1;
-	}
-
-	if((nr->min.y == s.min.y && nr->max.y == s.max.y) &&
-	    (nr->min.x < s.min.x && s.max.x < nr->max.x)){
-		nr->max.x = s.min.x;
-		rr->min.x = s.max.x;
-		return 1;
-	}
-	return 0;
-}
-
-void
-addtorlist(Rlist *rlist, Rectangle r)
-{
-	int i, j;
-	Rectangle ir, cr, rr;
-	Rlist tmp;
-
-	if(r.min.x >= r.max.x || r.min.y >= r.max.y)
-		return;
-
-	memset(&tmp, 0, sizeof tmp);
-	rappend(&tmp, r);
-	
-	if(verbose > 5)
-		fprint(2, "region union add %R:\n", r);
-
-	combinerect(&rlist->bbox, r); // must do this first
-	for(j = 0; j < tmp.nrect; j++){
-		r = tmp.rect[j];
-
-		for(i=0; i < rlist->nrect; i++){
-			ir = rlist->rect[i];
-
-			if(verbose > 5)
-				fprint(2, "checking %R against %R\n", r, ir);
-			if(!rectadjacent(ir, r))
-				continue;
-
-			/* r is covered by ir? */
-			if(rectinrect(r, ir))
-				break;
-
-			/* r covers ir? */
- 			if(rectinrect(ir, r)){
-				rtrim(rlist, i);
-				i--;
-				continue;
-			}
-
-			/* aligned and overlapping? */
-			if((ir.min.y == r.min.y && ir.max.y == r.max.y) ||
-		    	(ir.min.x == r.min.x && ir.max.x == r.max.x)){
-				combinerect(&r, ir);
-				rtrim(rlist, i);
-				i--;
-				continue;
-			}
-
-			/* not aligned */ 
-			if(verbose > 5)
-				fprint(2, "break up rect %R and %R\n", ir, r);
-			/* 2->2 breakup */
-			cr = ir;
-			if (!rectclip(&cr, r))	/* share only one point */
-				continue;
-
-			if(rectubr(&r, cr))
-				continue;
-
-			if(rectubr(&rlist->rect[i], cr))
-				continue;
-
-			/* 2 -> 3 breakup */
-			/* stride across */
-			if(recttridesubr(&r, cr, &rr)){
-				rappend(&tmp, rr);
-				continue;
-			}
-
-			/* corner overlap */
-			if(rectcornersubr(&r, cr, &rr)){
-				rappend(&tmp, rr);
-				continue;
-			}
-			abort();
-		}
-		if(i == rlist->nrect)
-			rappend(rlist, r);
-	}
-	freerlist(&tmp);
-	if(verbose > 5)
-		rprint(rlist);
-}
-
-void
-freerlist(Rlist *r)
-{
-	free(r->rect);
-	tot -= r->maxrect;
-	r->nrect = 0;
-	r->maxrect = 0;
-	r->rect = nil;
-}
-
-static void
-rprint(Rlist *r)
-{
-	int i;
-
-	fprint(2, "rlist %p:", r);
-	for(i=0; i<r->nrect; i++)
-		fprint(2, " %R", r->rect[i]);
-	fprint(2, "\n");
-}
-
-
-#ifdef REGION_DEBUG
-
-int verbose = 10;
-
-void main(int argc, char * argv[])
-{
-	Rectangle r1 = Rect(0, 0, 300, 200);
-	Rectangle r2 = Rect(100, 100, 400, 300);
-	Rectangle r3 = Rect(200, 100, 500, 300);
-	Region reg;
-
-	if(initdraw(0, 0, "vncviewer") < 0){
-		fprint(2, "%s: initdraw failed: %r\n", argv[0]);
-		exits("initdraw");
-	}
-	region_init(&reg);
-	region_union(&reg, r1, r1);
-	region_union(&reg, r2, r2);
-	region_union(&reg, r3, r3);
-}
-
-#endif
--- a/sys/src/cmd/vnc/rre.c
+++ /dev/null
@@ -1,549 +1,0 @@
-#include "vnc.h"
-#include "vncs.h"
-
-/*
- * rise and run length encoding, aka rre.
- *
- * the pixel contained in r are subdivided into
- * rectangles of uniform color, each of which
- * is encoded by <color, x, y, w, h>.
- *
- * use raw encoding if it's shorter.
- *
- * for compact rre, use limited size rectangles,
- * which are shorter to encode and therefor give better compression.
- *
- * hextile encoding uses rre encoding on at most 16x16 rectangles tiled
- * across and then down the screen.
- */
-static int	encrre(uchar *raw, int stride, int w, int h, int back, int pixb, uchar *buf, int maxr, uchar *done, int (*eqpix)(uchar*, int, int), uchar *(putr)(uchar*, uchar*, int, int, int, int, int, int));
-static int	eqpix16(uchar *raw, int p1, int p2);
-static int	eqpix32(uchar *raw, int p1, int p2);
-static int	eqpix8(uchar *raw, int p1, int p2);
-static int	findback(uchar *raw, int stride, int w, int h, int (*eqpix)(uchar*, int, int));
-static uchar*	putcorre(uchar *buf, uchar *raw, int p, int pixb, int x, int y, int w, int h);
-static uchar*	putrre(uchar *buf, uchar *raw, int p, int pixb, int x, int y, int w, int h);
-static void	putpix(Vnc *v, uchar *raw, int p, int pixb);
-static int	hexcolors(uchar *raw, int stride, int w, int h, int (*eqpix)(uchar*, int, int), int back, int *fore);
-static uchar	*puthexfore(uchar *buf, uchar*, int, int, int x, int y, int w, int h);
-static uchar	*puthexcol(uchar *buf, uchar*, int, int, int x, int y, int w, int h);
-static void	sendtraw(Vnc *v, uchar *raw, int pixb, int stride, int w, int h);
-
-/*
- * default routine, no compression, just the pixels
- */
-int
-sendraw(Vncs *v, Rectangle r)
-{
-	int pixb, stride;
-	uchar *raw;
-
-	if(!rectinrect(r, v->image->r))
-		sysfatal("sending bad rectangle");
-
-	pixb = v->bpp >> 3;
-	if((pixb << 3) != v->bpp)
-		sysfatal("bad pixel math in sendraw");
-	stride = v->image->width*sizeof(ulong);
-	if(((stride / pixb) * pixb) != stride)
-		sysfatal("bad pixel math in sendraw");
-	stride /= pixb;
-
-	raw = byteaddr(v->image, r.min);
-
-	vncwrrect(v, r);
-	vncwrlong(v, EncRaw);
-	sendtraw(v, raw, pixb, stride, Dx(r), Dy(r));
-	return 1;
-}
-
-int
-countraw(Vncs*, Rectangle)
-{
-	return 1;
-}
-
-/*
- * grab the image for the entire rectangle,
- * then encode each tile
- */
-int
-sendhextile(Vncs *v, Rectangle r)
-{
-	uchar *(*putr)(uchar*, uchar*, int, int, int, int, int, int);
-	int (*eq)(uchar*, int, int);
-	uchar *raw, *buf, *done, *traw;
-	int w, h, stride, pixb, pixlg, nr, bpr, back, fore;
-	int sy, sx, th, tw, oback, ofore, k, nc;
-
-	h = Dy(r);
-	w = Dx(r);
-	if(h == 0 || w == 0 || !rectinrect(r, v->image->r))
-		sysfatal("bad rectangle %R in sendhextile %R", r, v->image->r);
-
-	switch(v->bpp){
-	case  8:	pixlg = 0;	eq = eqpix8;	break;
-	case 16:	pixlg = 1;	eq = eqpix16;	break;
-	case 32:	pixlg = 2;	eq = eqpix32;	break;
-	default:
-		sendraw(v, r);
-		return 1;
-	}
-	pixb = 1 << pixlg;
-	stride = v->image->width*sizeof(ulong);
-	if(((stride >> pixlg) << pixlg) != stride){
-		sendraw(v, r);
-		return 1;
-	}
-	stride >>= pixlg;
-
-	buf = malloc(HextileDim * HextileDim * pixb);
-	done = malloc(HextileDim * HextileDim);
-	if(buf == nil || done == nil){
-		free(buf);
-		free(done);
-		sendraw(v, r);
-		return 1;
-	}
-	raw = byteaddr(v->image, r.min);
-
-	vncwrrect(v, r);
-	vncwrlong(v, EncHextile);
-	oback = -1;
-	ofore = -1;
-	for(sy = 0; sy < h; sy += HextileDim){
-		th = h - sy;
-		if(th > HextileDim)
-			th = HextileDim;
-		for(sx = 0; sx < w; sx += HextileDim){
-			tw = w - sx;
-			if(tw > HextileDim)
-				tw = HextileDim;
-
-			traw = raw + ((sy * stride + sx) << pixlg);
-
-			back = findback(traw, stride, tw, th, eq);
-			nc = hexcolors(traw, stride, tw, th, eq, back, &fore);
-			k = 0;
-			if(oback < 0 || !(*eq)(raw, back + ((traw - raw) >> pixlg), oback))
-				k |= HextileBack;
-			if(nc == 1){
-				vncwrchar(v, k);
-				if(k & HextileBack){
-					oback = back + ((traw - raw) >> pixlg);
-					putpix(v, raw, oback, pixb);
-				}
-				continue;
-			}
-			k |= HextileRects;
-			if(nc == 2){
-				putr = puthexfore;
-				bpr = 2;
-				if(ofore < 0 || !(*eq)(raw, fore + ((traw - raw) >> pixlg), ofore))
-					k |= HextileFore;
-			}else{
-				putr = puthexcol;
-				bpr = 2 + pixb;
-				k |= HextileCols;
-				/* stupid vnc clients smash foreground in this case */
-				ofore = -1;
-			}
-
-			nr = th * tw << pixlg;
-			if(k & HextileBack)
-				nr -= pixb;
-			if(k & HextileFore)
-				nr -= pixb;
-			nr /= bpr;
-			memset(done, 0, HextileDim * HextileDim);
-			nr = encrre(traw, stride, tw, th, back, pixb, buf, nr, done, eq, putr);
-			if(nr < 0){
-				vncwrchar(v, HextileRaw);
-				sendtraw(v, traw, pixb, stride, tw, th);
-				/* stupid vnc clients smash colors in this case */
-				ofore = -1;
-				oback = -1;
-			}else{
-				vncwrchar(v, k);
-				if(k & HextileBack){
-					oback = back + ((traw - raw) >> pixlg);
-					putpix(v, raw, oback, pixb);
-				}
-				if(k & HextileFore){
-					ofore = fore + ((traw - raw) >> pixlg);
-					putpix(v, raw, ofore, pixb);
-				}
-				vncwrchar(v, nr);
-				vncwrbytes(v, buf, nr * bpr);
-			}
-		}
-	}
-	free(buf);
-	free(done);
-	return 1;
-}
-
-int
-counthextile(Vncs*, Rectangle)
-{
-	return 1;
-}
-
-static int
-hexcolors(uchar *raw, int stride, int w, int h, int (*eqpix)(uchar*, int, int), int back, int *rfore)
-{
-	int s, es, sx, esx, fore;
-
-	*rfore = -1;
-	fore = -1;
-	es = stride * h;
-	for(s = 0; s < es; s += stride){
-		esx = s + w;
-		for(sx = s; sx < esx; sx++){
-			if((*eqpix)(raw, back, sx))
-				continue;
-			if(fore < 0){
-				fore = sx;
-				*rfore = fore;
-			}else if(!(*eqpix)(raw, fore, sx))
-				return 3;
-		}
-	}
-
-	if(fore < 0)
-		return 1;
-	return 2;
-}
-
-static uchar*
-puthexcol(uchar *buf, uchar *raw, int p, int pixb, int x, int y, int w, int h)
-{
-	raw += p * pixb;
-	while(pixb--)
-		*buf++ = *raw++;
-	*buf++ = (x << 4) | y;
-	*buf++ = (w - 1) << 4 | (h - 1);
-	return buf;
-}
-
-static uchar*
-puthexfore(uchar *buf, uchar*, int, int, int x, int y, int w, int h)
-{
-	*buf++ = (x << 4) | y;
-	*buf++ = (w - 1) << 4 | (h - 1);
-	return buf;
-}
-
-static void
-sendtraw(Vnc *v, uchar *raw, int pixb, int stride, int w, int h)
-{
-	int y;
-
-	for(y = 0; y < h; y++)
-		vncwrbytes(v, &raw[y * stride * pixb], w * pixb);
-}
-
-static int
-rrerects(Rectangle r, int split)
-{
-	return ((Dy(r) + split - 1) / split) * ((Dx(r) + split - 1) / split);
-}
-
-enum
-{
-	MaxCorreDim	= 48,
-	MaxRreDim	= 64,
-};
-
-int
-countrre(Vncs*, Rectangle r)
-{
-	return rrerects(r, MaxRreDim);
-}
-
-int
-countcorre(Vncs*, Rectangle r)
-{
-	return rrerects(r, MaxCorreDim);
-}
-
-static int
-_sendrre(Vncs *v, Rectangle r, int split, int compact)
-{
-	uchar *raw, *buf, *done;
-	int w, h, stride, pixb, pixlg, nraw, nr, bpr, back, totr;
-	int (*eq)(uchar*, int, int);
-
-	totr = 0;
-	h = Dy(r);
-	while(h > split){
-		h = r.max.y;
-		r.max.y = r.min.y + split;
-		totr += _sendrre(v, r, split, compact);
-		r.min.y = r.max.y;
-		r.max.y = h;
-		h = Dy(r);
-	}
-	w = Dx(r);
-	while(w > split){
-		w = r.max.x;
-		r.max.x = r.min.x + split;
-		totr += _sendrre(v, r, split, compact);
-		r.min.x = r.max.x;
-		r.max.x = w;
-		w = Dx(r);
-	}
-	if(h == 0 || w == 0 || !rectinrect(r, v->image->r))
-		sysfatal("bad rectangle in sendrre");
-
-	switch(v->bpp){
-	case  8:	pixlg = 0;	eq = eqpix8;	break;
-	case 16:	pixlg = 1;	eq = eqpix16;	break;
-	case 32:	pixlg = 2;	eq = eqpix32;	break;
-	default:
-		sendraw(v, r);
-		return totr + 1;
-	}
-	pixb = 1 << pixlg;
-	stride = v->image->width*sizeof(ulong);
-	if(((stride >> pixlg) << pixlg) != stride){
-		sendraw(v, r);
-		return totr + 1;
-	}
-	stride >>= pixlg;
-
-	nraw = w * pixb * h;
-	buf = malloc(nraw);
-	done = malloc(w * h);
-	if(buf == nil || done == nil){
-		free(buf);
-		free(done);
-		sendraw(v, r);
-		return totr + 1;
-	}
-	memset(done, 0, w * h);
-
-	raw = byteaddr(v->image, r.min);
-
-	if(compact)
-		bpr = 4 * 1 + pixb;
-	else
-		bpr = 4 * 2 + pixb;
-	nr = (nraw - 4 - pixb) / bpr;
-	back = findback(raw, stride, w, h, eq);
-	if(compact)
-		nr = encrre(raw, stride, w, h, back, pixb, buf, nr, done, eq, putcorre);
-	else
-		nr = encrre(raw, stride, w, h, back, pixb, buf, nr, done, eq, putrre);
-	if(nr < 0){
-		vncwrrect(v, r);
-		vncwrlong(v, EncRaw);
-		sendtraw(v, raw, pixb, stride, w, h);
-	}else{
-		vncwrrect(v, r);
-		if(compact)
-			vncwrlong(v, EncCorre);
-		else
-			vncwrlong(v, EncRre);
-		vncwrlong(v, nr);
-		putpix(v, raw, back, pixb);
-		vncwrbytes(v, buf, nr * bpr);
-	}
-	free(buf);
-	free(done);
-
-	return totr + 1;
-}
-
-int
-sendrre(Vncs *v, Rectangle r)
-{
-	return _sendrre(v, r, MaxRreDim, 0);
-}
-
-int
-sendcorre(Vncs *v, Rectangle r)
-{
-	return _sendrre(v, r, MaxCorreDim, 1);
-}
-
-static int
-encrre(uchar *raw, int stride, int w, int h, int back, int pixb, uchar *buf,
-	int maxr, uchar *done, int (*eqpix)(uchar*, int, int),
-	uchar *(*putr)(uchar*, uchar*, int, int, int, int, int, int))
-{
-	int s, es, sx, esx, sy, syx, esyx, rh, rw, y, nr, dsy, dp;
-
-	es = stride * h;
-	y = 0;
-	nr = 0;
-	dp = 0;
-	for(s = 0; s < es; s += stride){
-		esx = s + w;
-		for(sx = s; sx < esx; ){
-			rw = done[dp];
-			if(rw){
-				sx += rw;
-				dp += rw;
-				continue;
-			}
-			if((*eqpix)(raw, back, sx)){
-				sx++;
-				dp++;
-				continue;
-			}
-
-			if(nr >= maxr)
-				return -1;
-
-			/*
-			 * find the tallest maximally wide uniform colored rectangle
-			 * with p at the upper left.
-			 * this isn't an optimal parse, but it's pretty good for text
-			 */
-			rw = esx - sx;
-			rh = 0;
-			for(sy = sx; sy < es; sy += stride){
-				if(!(*eqpix)(raw, sx, sy))
-					break;
-				esyx = sy + rw;
-				for(syx = sy + 1; syx < esyx; syx++){
-					if(!(*eqpix)(raw, sx, syx)){
-						if(sy == sx)
-							break;
-						goto breakout;
-					}
-				}
-				if(sy == sx)
-					rw = syx - sy;
-				rh++;
-			}
-		breakout:;
-
-			nr++;
-			buf = (*putr)(buf, raw, sx, pixb, sx - s, y, rw, rh);
-
-			/*
-			 * mark all pixels done
-			 */
-			dsy = dp;
-			while(rh--){
-				esyx = dsy + rw;
-				for(syx = dsy; syx < esyx; syx++)
-					done[syx] = esyx - syx;
-				dsy += w;
-			}
-
-			sx += rw;
-			dp += rw;
-		}
-		y++;
-	}
-	return nr;
-}
-
-/*
- * estimate the background color
- * by finding the most frequent character in a small sample
- */
-static int
-findback(uchar *raw, int stride, int w, int h, int (*eqpix)(uchar*, int, int))
-{
-	enum{
-		NCol = 6,
-		NExamine = 4
-	};
-	int ccount[NCol], col[NCol], i, wstep, hstep, x, y, pix, c, max, maxc;
-
-	wstep = w / NExamine;
-	if(wstep < 1)
-		wstep = 1;
-	hstep = h / NExamine;
-	if(hstep < 1)
-		hstep = 1;
-
-	for(i = 0; i< NCol; i++)
-		ccount[i] = 0;
-	for(y = 0; y < h; y += hstep){
-		for(x = 0; x < w; x += wstep){
-			pix = y * stride + x;
-			for(i = 0; i < NCol; i++){
-				if(ccount[i] == 0){
-					ccount[i] = 1;
-					col[i] = pix;
-					break;
-				}
-				if((*eqpix)(raw, pix, col[i])){
-					ccount[i]++;
-					break;
-				}
-			}
-		}
-	}
-	maxc = ccount[0];
-	max = 0;
-	for(i = 1; i < NCol; i++){
-		c = ccount[i];
-		if(!c)
-			break;
-		if(c > maxc){
-			max = i;
-			maxc = c;
-		}
-	}
-	return col[max];
-}
-
-static uchar*
-putrre(uchar *buf, uchar *raw, int p, int pixb, int x, int y, int w, int h)
-{
-	raw += p * pixb;
-	while(pixb--)
-		*buf++ = *raw++;
-	*buf++ = x >> 8;
-	*buf++ = x;
-	*buf++ = y >> 8;
-	*buf++ = y;
-	*buf++ = w >> 8;
-	*buf++ = w;
-	*buf++ = h >> 8;
-	*buf++ = h;
-	return buf;
-}
-
-static uchar*
-putcorre(uchar *buf, uchar *raw, int p, int pixb, int x, int y, int w, int h)
-{
-	raw += p * pixb;
-	while(pixb--)
-		*buf++ = *raw++;
-	*buf++ = x;
-	*buf++ = y;
-	*buf++ = w;
-	*buf++ = h;
-	return buf;
-}
-
-static int
-eqpix8(uchar *raw, int p1, int p2)
-{
-	return raw[p1] == raw[p2];
-}
-
-static int
-eqpix16(uchar *raw, int p1, int p2)
-{
-	return ((ushort*)raw)[p1] == ((ushort*)raw)[p2];
-}
-
-static int
-eqpix32(uchar *raw, int p1, int p2)
-{
-	return ((ulong*)raw)[p1] == ((ulong*)raw)[p2];
-}
-
-static void
-putpix(Vnc *v, uchar *raw, int p, int pixb)
-{
-	vncwrbytes(v, raw + p * pixb, pixb);
-}
--- a/sys/src/cmd/vnc/screen.c
+++ /dev/null
@@ -1,347 +1,0 @@
-#include	<u.h>
-#include	<libc.h>
-#include	"compat.h"
-#include	"kbd.h"
-#include	"error.h"
-
-#define	Image	IMAGE
-#include	<draw.h>
-#include	<memdraw.h>
-#include	<cursor.h>
-#include	"screen.h"
-
-enum
-{
-	CURSORDIM = 16
-};
-
-Memimage	*gscreen;
-Point		ZP;
-int		cursorver;
-Point		cursorpos;
-
-static Memimage		*back;
-static Memimage		*conscol;
-static Memimage		*curscol;
-static Point		curpos;
-static Memsubfont	*memdefont;
-static Rectangle	flushr;
-static Rectangle	window;
-static int		h;
-static int		w;
-
-static Rectangle	cursorr;
-static Point		offscreen;
-static uchar		cursset[CURSORDIM*CURSORDIM/8];
-static uchar		cursclr[CURSORDIM*CURSORDIM/8];
-static int		cursdrawvers = -1;
-static Memimage		*cursorset;
-static Memimage		*cursorclear;
-static Cursor		screencursor;
-
-void
-screeninit(int x, int y, char *chanstr)
-{
-	char buf[128];
-	Rectangle r;
-	int chan;
-
-	cursorver = 0;
-
-	memimageinit();
-	chan = strtochan(chanstr);
-	if(chan == 0)
-		error("bad screen channel string");
-
-	r = Rect(0, 0, x, y);
-	gscreen = allocmemimage(r, chan);
-	if(gscreen == nil){
-		snprint(buf, sizeof buf, "can't allocate screen image: %r");
-		error(buf);
-	}
-
-	offscreen = Pt(x + 100, y + 100);
-	cursorr = Rect(0, 0, CURSORDIM, CURSORDIM);
-	cursorset = allocmemimage(cursorr, GREY8);
-	cursorclear = allocmemimage(cursorr, GREY1);
-	if(cursorset == nil || cursorclear == nil){
-		freememimage(gscreen);
-		freememimage(cursorset);
-		freememimage(cursorclear);
-		gscreen = nil;
-		cursorset = nil;
-		cursorclear = nil;
-		snprint(buf, sizeof buf, "can't allocate cursor images: %r");
-		error(buf);
-	}
-
-	/* a lot of work to get a grey color */
-	curscol = allocmemimage(Rect(0,0,1,1), RGBA32);
-	curscol->flags |= Frepl;
-	curscol->clipr = gscreen->r;
-	memfillcolor(curscol, 0xff0000ff);
-
-	screenwin();
-
-	setcursor(&arrow);
-}
-
-void
-screenwin(void)
-{
-	Point p;
-	char *greet;
-	Memimage *grey;
-
-	qlock(&drawlock);
-	back = memwhite;
-	conscol = memblack;
-	memfillcolor(gscreen, 0x888844FF);
-	
-	memdefont = getmemdefont();
-	h = memdefont->height;
-
-	window = insetrect(gscreen->clipr, 20);
-	memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP, S);
-	window = insetrect(window, 4);
-	memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
-
-	/* a lot of work to get a grey color */
-	grey = allocmemimage(Rect(0,0,1,1), CMAP8);
-	grey->flags |= Frepl;
-	grey->clipr = gscreen->r;
-	memfillcolor(grey, 0xAAAAAAFF);
-	memimagedraw(gscreen, Rect(window.min.x, window.min.y,
-			window.max.x, window.min.y+h+5+6), grey, ZP, nil, ZP, S);
-	freememimage(grey);
-	window = insetrect(window, 5);
-
-	greet = " Plan 9 Console ";
-	p = addpt(window.min, Pt(10, 0));
-	memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
-	window.min.y += h+6;
-	curpos = window.min;
-	window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
-	flushmemscreen(gscreen->r);
-	qunlock(&drawlock);
-}
-
-Memdata*
-attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen)
-{
-	*r = gscreen->clipr;
-	*d = gscreen->depth;
-	*chan = gscreen->chan;
-	*width = gscreen->width;
-	*softscreen = 1;
-
-	gscreen->data->ref++;
-	return gscreen->data;
-}
-
-void
-getcolor(ulong , ulong* pr, ulong* pg, ulong* pb)
-{
-	*pr = 0;
-	*pg = 0;
-	*pb = 0;
-}
-
-int
-setcolor(ulong , ulong , ulong , ulong )
-{
-	return 0;
-}
-
-/*
- * called with cursor unlocked, drawlock locked
- */
-void
-cursordraw(Memimage *dst, Rectangle r)
-{
-	static uchar set[CURSORDIM*CURSORDIM], clr[CURSORDIM*CURSORDIM/8];
-	static int ver = -1;
-	int i, j, n;
-
-	lock(&cursor);
-	if(ver != cursorver){
-		n = 0;
-		for(i = 0; i < CURSORDIM*CURSORDIM/8; i += CURSORDIM/8){
-			for(j = 0; j < CURSORDIM; j++){
-				if(cursset[i + (j >> 3)] & (1 << (7 - (j & 7))))
-					set[n] = 0xaa;
-				else
-					set[n] = 0;
-				n++;
-			}
-		}
-		memmove(clr, cursclr, CURSORDIM*CURSORDIM/8);
-		ver = cursorver;
-		unlock(&cursor);
-		loadmemimage(cursorset, cursorr, set, CURSORDIM*CURSORDIM);
-		loadmemimage(cursorclear, cursorr, clr, CURSORDIM*CURSORDIM/8);
-	}else
-		unlock(&cursor);
-	memimagedraw(dst, r, memwhite, ZP, cursorclear, ZP, SoverD);
-	memimagedraw(dst, r, curscol, ZP, cursorset, ZP, SoverD);
-}
-
-/*
- * called with cursor locked, drawlock possibly unlocked
- */
-Rectangle
-cursorrect(void)
-{
-	Rectangle r;
-
-	r.min.x = cursorpos.x + cursor.offset.x;
-	r.min.y = cursorpos.y + cursor.offset.y;
-	r.max.x = r.min.x + CURSORDIM;
-	r.max.y = r.min.y + CURSORDIM;
-	return r;
-}
-
-/*
- * called with cursor locked, drawlock possibly unlocked
- */
-void
-setcursor(Cursor* curs)
-{
-	cursorver++;
-	memmove(cursset, curs->set, CURSORDIM*CURSORDIM/8);
-	memmove(cursclr, curs->clr, CURSORDIM*CURSORDIM/8);
-}
-
-void
-cursoron(void)
-{
-	cursorpos = mousexy();
-}
-
-void
-cursoroff(void)
-{
-	cursorpos = offscreen;
-}
-
-void
-blankscreen(int blank)
-{
-	USED(blank);
-}
-
-static void
-screenflush(void)
-{
-	flushmemscreen(flushr);
-	flushr = Rect(10000, 10000, -10000, -10000);
-}
-
-static void
-addflush(Rectangle r)
-{
-	if(flushr.min.x >= flushr.max.x)
-		flushr = r;
-	else
-		combinerect(&flushr, r);
-}
-
-static void
-scroll(void)
-{
-	int o;
-	Point p;
-	Rectangle r;
-
-	o = 8*h;
-	r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
-	p = Pt(window.min.x, window.min.y+o);
-	memimagedraw(gscreen, r, gscreen, p, nil, p, S);
-	r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
-	memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
-	flushmemscreen(gscreen->clipr);
-
-	curpos.y -= o;
-}
-
-static void
-screenputc(char *buf)
-{
-	Point p;
-	int w, pos;
-	Rectangle r;
-	static int *xp;
-	static int xbuf[256];
-
-	if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
-		xp = xbuf;
-
-	switch(buf[0]){
-	case '\n':
-		if(curpos.y+h >= window.max.y)
-			scroll();
-		curpos.y += h;
-		screenputc("\r");
-		break;
-	case '\r':
-		xp = xbuf;
-		curpos.x = window.min.x;
-		break;
-	case '\t':
-		p = memsubfontwidth(memdefont, " ");
-		w = p.x;
-		*xp++ = curpos.x;
-		pos = (curpos.x-window.min.x)/w;
-		pos = 8-(pos%8);
-		r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
-		memimagedraw(gscreen, r, back, back->r.min, memopaque, ZP, S);
-		addflush(r);
-		curpos.x += pos*w;
-		break;
-	case '\b':
-		if(xp <= xbuf)
-			break;
-		xp--;
-		r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
-		memimagedraw(gscreen, r, back, back->r.min, memopaque, ZP, S);
-		addflush(r);
-		curpos.x = *xp;
-		break;
-	case '\0':
-		break;
-	default:
-		p = memsubfontwidth(memdefont, buf);
-		w = p.x;
-
-		if(curpos.x >= window.max.x-w)
-			screenputc("\n");
-
-		*xp++ = curpos.x;
-		r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y + h);
-		memimagedraw(gscreen, r, back, back->r.min, memopaque, ZP, S);
-		memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
-		addflush(r);
-		curpos.x += w;
-	}
-}
-
-void
-screenputs(char *s, int n)
-{
-	static char rb[UTFmax+1];
-	static int nrb;
-	char *e;
-
-	qlock(&drawlock);
-	e = s + n;
-	while(s < e){
-		rb[nrb++] = *s++;
-		if(nrb >= UTFmax || fullrune(rb, nrb)){
-			rb[nrb] = 0;
-			screenputc(rb);
-			nrb = 0;
-		}
-	}
-	screenflush();
-	qunlock(&drawlock);
-}
--- a/sys/src/cmd/vnc/screen.h
+++ /dev/null
@@ -1,37 +1,0 @@
-typedef struct Cursor Cursor;
-typedef struct Cursorinfo Cursorinfo;
-struct Cursorinfo {
-	Cursor;
-	Lock;
-};
-
-extern Cursorinfo	cursor;
-extern Cursor		arrow;
-extern Memimage		*gscreen;
-extern int		cursorver;
-extern Point		cursorpos;
-
-void		mouseresize(void);
-Point 		mousexy(void);
-void		cursoron(void);
-void		cursoroff(void);
-void		setcursor(Cursor*);
-void		flushmemscreen(Rectangle r);
-Rectangle	cursorrect(void);
-void		cursordraw(Memimage *dst, Rectangle r);
-
-extern QLock	drawlock;
-void		drawactive(int);
-void		getcolor(ulong, ulong*, ulong*, ulong*);
-int		setcolor(ulong, ulong, ulong, ulong);
-#define		TK2SEC(x)	0
-extern void	blankscreen(int);
-void		screeninit(int x, int y, char *chanstr);
-void		screenwin(void);
-void		absmousetrack(int x, int y, int b, ulong msec);
-Memdata*	attachscreen(Rectangle*, ulong*, int*, int*, int*);
-void		deletescreenimage(void);
-void		resetscreenimage(void);
-
-void		fsinit(char *mntpt, int x, int y, char *chanstr);
-#define		ishwimage(i)	0
--- a/sys/src/cmd/vnc/utf2ksym.h
+++ /dev/null
@@ -1,1073 +1,0 @@
-/*
- * VNC uses X11's keysyms defined in X11/keysym.h, this is a converter
- * from unicode characters to ksyms that other servers use.
- */
-static ulong
-utf2ksym [] = {
-	[L'Ą']	0x1a1,
-	[L'˘']	0x1a2,
-	[L'Ł']	0x1a3,
-	[L'Ľ']	0x1a5,
-	[L'Ś']	0x1a6,
-	[L'Š']	0x1a9,
-	[L'Ş']	0x1aa,
-	[L'Ť']	0x1ab,
-	[L'Ź']	0x1ac,
-	[L'Ž']	0x1ae,
-	[L'Ż']	0x1af,
-	[L'ą']	0x1b1,
-	[L'˛']	0x1b2,
-	[L'ł']	0x1b3,
-	[L'ľ']	0x1b5,
-	[L'ś']	0x1b6,
-	[L'ˇ']	0x1b7,
-	[L'š']	0x1b9,
-	[L'ş']	0x1ba,
-	[L'ť']	0x1bb,
-	[L'ź']	0x1bc,
-	[L'˝']	0x1bd,
-	[L'ž']	0x1be,
-	[L'ż']	0x1bf,
-	[L'Ŕ']	0x1c0,
-	[L'Ă']	0x1c3,
-	[L'Ĺ']	0x1c5,
-	[L'Ć']	0x1c6,
-	[L'Č']	0x1c8,
-	[L'Ę']	0x1ca,
-	[L'Ě']	0x1cc,
-	[L'Ď']	0x1cf,
-	[L'Đ']	0x1d0,
-	[L'Ń']	0x1d1,
-	[L'Ň']	0x1d2,
-	[L'Ő']	0x1d5,
-	[L'Ř']	0x1d8,
-	[L'Ů']	0x1d9,
-	[L'Ű']	0x1db,
-	[L'Ţ']	0x1de,
-	[L'ŕ']	0x1e0,
-	[L'ă']	0x1e3,
-	[L'ĺ']	0x1e5,
-	[L'ć']	0x1e6,
-	[L'č']	0x1e8,
-	[L'ę']	0x1ea,
-	[L'ě']	0x1ec,
-	[L'ď']	0x1ef,
-	[L'đ']	0x1f0,
-	[L'ń']	0x1f1,
-	[L'ň']	0x1f2,
-	[L'ő']	0x1f5,
-	[L'ř']	0x1f8,
-	[L'ů']	0x1f9,
-	[L'ű']	0x1fb,
-	[L'ţ']	0x1fe,
-	[L'˙']	0x1ff,
-	[L'Ħ']	0x2a1,
-	[L'Ĥ']	0x2a6,
-	[L'İ']	0x2a9,
-	[L'Ğ']	0x2ab,
-	[L'Ĵ']	0x2ac,
-	[L'ħ']	0x2b1,
-	[L'ĥ']	0x2b6,
-	[L'ı']	0x2b9,
-	[L'ğ']	0x2bb,
-	[L'ĵ']	0x2bc,
-	[L'Ċ']	0x2c5,
-	[L'Ĉ']	0x2c6,
-	[L'Ġ']	0x2d5,
-	[L'Ĝ']	0x2d8,
-	[L'Ŭ']	0x2dd,
-	[L'Ŝ']	0x2de,
-	[L'ċ']	0x2e5,
-	[L'ĉ']	0x2e6,
-	[L'ġ']	0x2f5,
-	[L'ĝ']	0x2f8,
-	[L'ŭ']	0x2fd,
-	[L'ŝ']	0x2fe,
-	[L'ĸ']	0x3a2,
-	[L'Ŗ']	0x3a3,
-	[L'Ĩ']	0x3a5,
-	[L'Ļ']	0x3a6,
-	[L'Ē']	0x3aa,
-	[L'Ģ']	0x3ab,
-	[L'Ŧ']	0x3ac,
-	[L'ŗ']	0x3b3,
-	[L'ĩ']	0x3b5,
-	[L'ļ']	0x3b6,
-	[L'ē']	0x3ba,
-	[L'ģ']	0x3bb,
-	[L'ŧ']	0x3bc,
-	[L'Ŋ']	0x3bd,
-	[L'ŋ']	0x3bf,
-	[L'Ā']	0x3c0,
-	[L'Į']	0x3c7,
-	[L'Ė']	0x3cc,
-	[L'Ī']	0x3cf,
-	[L'Ņ']	0x3d1,
-	[L'Ō']	0x3d2,
-	[L'Ķ']	0x3d3,
-	[L'Ų']	0x3d9,
-	[L'Ũ']	0x3dd,
-	[L'Ū']	0x3de,
-	[L'ā']	0x3e0,
-	[L'į']	0x3e7,
-	[L'ė']	0x3ec,
-	[L'ī']	0x3ef,
-	[L'ņ']	0x3f1,
-	[L'ō']	0x3f2,
-	[L'ķ']	0x3f3,
-	[L'ų']	0x3f9,
-	[L'ũ']	0x3fd,
-	[L'ū']	0x3fe,
-	[L'。']	0x4a1,
-	[L'〈']	0x4a2,
-	[L'〉']	0x4a3,
-	[L'、']	0x4a4,
-	[L'・']	0x4a5,
-	[L'ヲ']	0x4a6,
-	[L'ァ']	0x4a7,
-	[L'ィ']	0x4a8,
-	[L'ゥ']	0x4a9,
-	[L'ェ']	0x4aa,
-	[L'ォ']	0x4ab,
-	[L'ャ']	0x4ac,
-	[L'ュ']	0x4ad,
-	[L'ョ']	0x4ae,
-	[L'ッ']	0x4af,
-	[L'ー']	0x4b0,
-	[L'ア']	0x4b1,
-	[L'イ']	0x4b2,
-	[L'ウ']	0x4b3,
-	[L'エ']	0x4b4,
-	[L'オ']	0x4b5,
-	[L'カ']	0x4b6,
-	[L'キ']	0x4b7,
-	[L'ク']	0x4b8,
-	[L'ケ']	0x4b9,
-	[L'コ']	0x4ba,
-	[L'サ']	0x4bb,
-	[L'シ']	0x4bc,
-	[L'ス']	0x4bd,
-	[L'セ']	0x4be,
-	[L'ソ']	0x4bf,
-	[L'タ']	0x4c0,
-	[L'チ']	0x4c1,
-	[L'ツ']	0x4c2,
-	[L'テ']	0x4c3,
-	[L'ト']	0x4c4,
-	[L'ナ']	0x4c5,
-	[L'ニ']	0x4c6,
-	[L'ヌ']	0x4c7,
-	[L'ネ']	0x4c8,
-	[L'ノ']	0x4c9,
-	[L'ハ']	0x4ca,
-	[L'ヒ']	0x4cb,
-	[L'フ']	0x4cc,
-	[L'ヘ']	0x4cd,
-	[L'ホ']	0x4ce,
-	[L'マ']	0x4cf,
-	[L'ミ']	0x4d0,
-	[L'ム']	0x4d1,
-	[L'メ']	0x4d2,
-	[L'モ']	0x4d3,
-	[L'ヤ']	0x4d4,
-	[L'ユ']	0x4d5,
-	[L'ヨ']	0x4d6,
-	[L'ラ']	0x4d7,
-	[L'リ']	0x4d8,
-	[L'ル']	0x4d9,
-	[L'レ']	0x4da,
-	[L'ロ']	0x4db,
-	[L'ワ']	0x4dc,
-	[L'ン']	0x4dd,
-	[L'゛']	0x4de,
-	[L'゜']	0x4df,
-	[L'۰']	0x10006f0,
-	[L'۱']	0x10006f1,
-	[L'۲']	0x10006f2,
-	[L'۳']	0x10006f3,
-	[L'۴']	0x10006f4,
-	[L'۵']	0x10006f5,
-	[L'۶']	0x10006f6,
-	[L'۷']	0x10006f7,
-	[L'۸']	0x10006f8,
-	[L'۹']	0x10006f9,
-	[L'٪']	0x5a5,
-	[L'ٰ']	0x5a6,
-	[L'ٹ']	0x5a7,
-	[L'پ']	0x100067e,
-	[L'چ']	0x1000686,
-	[L'ڈ']	0x5aa,
-	[L'ڑ']	0x5ab,
-	[L'،']	0x5ac,
-	[L'۔']	0x5ae,
-	[L'٠']	0x5b0,
-	[L'١']	0x5b1,
-	[L'٢']	0x5b2,
-	[L'٣']	0x5b3,
-	[L'٤']	0x5b4,
-	[L'٥']	0x5b5,
-	[L'٦']	0x5b6,
-	[L'٧']	0x5b7,
-	[L'٨']	0x5b8,
-	[L'٩']	0x5b9,
-	[L'؛']	0x5bb,
-	[L'؟']	0x5bf,
-	[L'ء']	0x5c1,
-	[L'آ']	0x5c2,
-	[L'أ']	0x5c3,
-	[L'ؤ']	0x5c4,
-	[L'إ']	0x5c5,
-	[L'ئ']	0x5c6,
-	[L'ا']	0x5c7,
-	[L'ب']	0x5c8,
-	[L'ة']	0x5c9,
-	[L'ت']	0x5ca,
-	[L'ث']	0x5cb,
-	[L'ج']	0x5cc,
-	[L'ح']	0x5cd,
-	[L'خ']	0x5ce,
-	[L'د']	0x5cf,
-	[L'ذ']	0x5d0,
-	[L'ر']	0x5d1,
-	[L'ز']	0x5d2,
-	[L'س']	0x5d3,
-	[L'ش']	0x5d4,
-	[L'ص']	0x5d5,
-	[L'ض']	0x5d6,
-	[L'ط']	0x5d7,
-	[L'ظ']	0x5d8,
-	[L'ع']	0x5d9,
-	[L'غ']	0x5da,
-	[L'ـ']	0x5e0,
-	[L'ف']	0x5e1,
-	[L'ق']	0x5e2,
-	[L'ك']	0x5e3,
-	[L'ل']	0x5e4,
-	[L'م']	0x5e5,
-	[L'ن']	0x5e6,
-	[L'ه']	0x5e7,
-	[L'و']	0x5e8,
-	[L'ى']	0x5e9,
-	[L'ي']	0x5ea,
-	[L'ً']	0x5eb,
-	[L'ٌ']	0x5ec,
-	[L'ٍ']	0x5ed,
-	[L'َ']	0x5ee,
-	[L'ُ']	0x5ef,
-	[L'ِ']	0x5f0,
-	[L'ّ']	0x5f1,
-	[L'ْ']	0x5f2,
-	[L'ٓ']	0x5f3,
-	[L'ٔ']	0x5f4,
-	[L'ٕ']	0x5f5,
-	[L'ژ']	0x1000698,
-	[L'ڤ']	0x5f7,
-	[L'ک']	0x10006a9,
-	[L'گ']	0x10006af,
-	[L'ں']	0x5fa,
-	[L'ھ']	0x5fb,
-	[L'ی']	0x10006cc,
-	[L'ے']	0x5fd,
-	[L'ہ']	0x5fe,
-	[L'Ғ']	0x680,
-	[L'Җ']	0x681,
-	[L'Қ']	0x682,
-	[L'Ҝ']	0x683,
-	[L'Ң']	0x684,
-	[L'Ү']	0x685,
-	[L'Ұ']	0x686,
-	[L'Ҳ']	0x687,
-	[L'Ҷ']	0x688,
-	[L'Ҹ']	0x689,
-	[L'Һ']	0x68a,
-	[L'Ә']	0x68c,
-	[L'Ӣ']	0x68d,
-	[L'Ө']	0x68e,
-	[L'Ӯ']	0x68f,
-	[L'ғ']	0x690,
-	[L'җ']	0x691,
-	[L'қ']	0x692,
-	[L'ҝ']	0x693,
-	[L'ң']	0x694,
-	[L'ү']	0x695,
-	[L'ұ']	0x696,
-	[L'ҳ']	0x697,
-	[L'ҷ']	0x698,
-	[L'ҹ']	0x699,
-	[L'һ']	0x69a,
-	[L'ә']	0x69c,
-	[L'ӣ']	0x69d,
-	[L'ө']	0x69e,
-	[L'ӯ']	0x69f,
-	[L'ђ']	0x6a1,
-	[L'ѓ']	0x6a2,
-	[L'ё']	0x6a3,
-	[L'є']	0x6a4,
-	[L'ѕ']	0x6a5,
-	[L'і']	0x6a6,
-	[L'ї']	0x6a7,
-	[L'ј']	0x6a8,
-	[L'љ']	0x6a9,
-	[L'њ']	0x6aa,
-	[L'ћ']	0x6ab,
-	[L'ќ']	0x6ac,
-	[L'ґ']	0x6ad,
-	[L'ў']	0x6ae,
-	[L'џ']	0x6af,
-	[L'№']	0x6b0,
-	[L'Ђ']	0x6b1,
-	[L'Ѓ']	0x6b2,
-	[L'Ё']	0x6b3,
-	[L'Є']	0x6b4,
-	[L'Ѕ']	0x6b5,
-	[L'І']	0x6b6,
-	[L'Ї']	0x6b7,
-	[L'Ј']	0x6b8,
-	[L'Љ']	0x6b9,
-	[L'Њ']	0x6ba,
-	[L'Ћ']	0x6bb,
-	[L'Ќ']	0x6bc,
-	[L'Ґ']	0x6bd,
-	[L'Ў']	0x6be,
-	[L'Џ']	0x6bf,
-	[L'ю']	0x6c0,
-	[L'а']	0x6c1,
-	[L'б']	0x6c2,
-	[L'ц']	0x6c3,
-	[L'д']	0x6c4,
-	[L'е']	0x6c5,
-	[L'ф']	0x6c6,
-	[L'г']	0x6c7,
-	[L'х']	0x6c8,
-	[L'и']	0x6c9,
-	[L'й']	0x6ca,
-	[L'к']	0x6cb,
-	[L'л']	0x6cc,
-	[L'м']	0x6cd,
-	[L'н']	0x6ce,
-	[L'о']	0x6cf,
-	[L'п']	0x6d0,
-	[L'я']	0x6d1,
-	[L'р']	0x6d2,
-	[L'с']	0x6d3,
-	[L'т']	0x6d4,
-	[L'у']	0x6d5,
-	[L'ж']	0x6d6,
-	[L'в']	0x6d7,
-	[L'ь']	0x6d8,
-	[L'ы']	0x6d9,
-	[L'з']	0x6da,
-	[L'ш']	0x6db,
-	[L'э']	0x6dc,
-	[L'щ']	0x6dd,
-	[L'ч']	0x6de,
-	[L'ъ']	0x6df,
-	[L'Ю']	0x6e0,
-	[L'А']	0x6e1,
-	[L'Б']	0x6e2,
-	[L'Ц']	0x6e3,
-	[L'Д']	0x6e4,
-	[L'Е']	0x6e5,
-	[L'Ф']	0x6e6,
-	[L'Г']	0x6e7,
-	[L'Х']	0x6e8,
-	[L'И']	0x6e9,
-	[L'Й']	0x6ea,
-	[L'К']	0x6eb,
-	[L'Л']	0x6ec,
-	[L'М']	0x6ed,
-	[L'Н']	0x6ee,
-	[L'О']	0x6ef,
-	[L'П']	0x6f0,
-	[L'Я']	0x6f1,
-	[L'Р']	0x6f2,
-	[L'С']	0x6f3,
-	[L'Т']	0x6f4,
-	[L'У']	0x6f5,
-	[L'Ж']	0x6f6,
-	[L'В']	0x6f7,
-	[L'Ь']	0x6f8,
-	[L'Ы']	0x6f9,
-	[L'З']	0x6fa,
-	[L'Ш']	0x6fb,
-	[L'Э']	0x6fc,
-	[L'Щ']	0x6fd,
-	[L'Ч']	0x6fe,
-	[L'Ъ']	0x6ff,
-	[L'Ά']	0x7a1,
-	[L'Έ']	0x7a2,
-	[L'Ή']	0x7a3,
-	[L'Ί']	0x7a4,
-	[L'Ϊ']	0x7a5,
-	[L'Ό']	0x7a7,
-	[L'Ύ']	0x7a8,
-	[L'Ϋ']	0x7a9,
-	[L'Ώ']	0x7ab,
-	[L'΅']	0x7ae,
-	[L'―']	0x7af,
-	[L'ά']	0x7b1,
-	[L'έ']	0x7b2,
-	[L'ή']	0x7b3,
-	[L'ί']	0x7b4,
-	[L'ϊ']	0x7b5,
-	[L'ΐ']	0x7b6,
-	[L'ό']	0x7b7,
-	[L'ύ']	0x7b8,
-	[L'ϋ']	0x7b9,
-	[L'ΰ']	0x7ba,
-	[L'ώ']	0x7bb,
-	[L'Α']	0x7c1,
-	[L'Β']	0x7c2,
-	[L'Γ']	0x7c3,
-	[L'Δ']	0x7c4,
-	[L'Ε']	0x7c5,
-	[L'Ζ']	0x7c6,
-	[L'Η']	0x7c7,
-	[L'Θ']	0x7c8,
-	[L'Ι']	0x7c9,
-	[L'Κ']	0x7ca,
-	[L'Λ']	0x7cb,
-	[L'Μ']	0x7cc,
-	[L'Ν']	0x7cd,
-	[L'Ξ']	0x7ce,
-	[L'Ο']	0x7cf,
-	[L'Π']	0x7d0,
-	[L'Ρ']	0x7d1,
-	[L'Σ']	0x7d2,
-	[L'Τ']	0x7d4,
-	[L'Υ']	0x7d5,
-	[L'Φ']	0x7d6,
-	[L'Χ']	0x7d7,
-	[L'Ψ']	0x7d8,
-	[L'Ω']	0x7d9,
-	[L'α']	0x7e1,
-	[L'β']	0x7e2,
-	[L'γ']	0x7e3,
-	[L'δ']	0x7e4,
-	[L'ε']	0x7e5,
-	[L'ζ']	0x7e6,
-	[L'η']	0x7e7,
-	[L'θ']	0x7e8,
-	[L'ι']	0x7e9,
-	[L'κ']	0x7ea,
-	[L'λ']	0x7eb,
-	[L'μ']	0x7ec,
-	[L'ν']	0x7ed,
-	[L'ξ']	0x7ee,
-	[L'ο']	0x7ef,
-	[L'π']	0x7f0,
-	[L'ρ']	0x7f1,
-	[L'σ']	0x7f2,
-	[L'ς']	0x7f3,
-	[L'τ']	0x7f4,
-	[L'υ']	0x7f5,
-	[L'φ']	0x7f6,
-	[L'χ']	0x7f7,
-	[L'ψ']	0x7f8,
-	[L'ω']	0x7f9,
-	[L'⌠']	0x8a4,
-	[L'⌡']	0x8a5,
-	[L'⌜']	0x8a7,
-	[L'⌝']	0x8a8,
-	[L'⌞']	0x8a9,
-	[L'⌟']	0x8aa,
-	[L'≤']	0x8bc,
-	[L'≠']	0x8bd,
-	[L'≥']	0x8be,
-	[L'∫']	0x8bf,
-	[L'∴']	0x8c0,
-	[L'∞']	0x8c2,
-	[L'∇']	0x8c5,
-	[L'≅']	0x8c8,
-	[L'≆']	0x8c9,
-	[L'⊢']	0x8ce,
-	[L'√']	0x8d6,
-	[L'⊂']	0x8da,
-	[L'⊃']	0x8db,
-	[L'∩']	0x8dc,
-	[L'∪']	0x8dd,
-	[L'∧']	0x8de,
-	[L'∨']	0x8df,
-	[L'ƒ']	0x8f6,
-	[L'←']	0x8fb,
-	[L'↑']	0x8fc,
-	[L'→']	0x8fd,
-	[L'↓']	0x8fe,
-	[L'␢']	0x9df,
-	[L'♦']	0x9e0,
-	[L'▦']	0x9e1,
-	[L'␉']	0x9e2,
-	[L'␌']	0x9e3,
-	[L'␍']	0x9e4,
-	[L'␊']	0x9e5,
-	[L'␋']	0x9e9,
-	[L'┘']	0x9ea,
-	[L'┐']	0x9eb,
-	[L'┌']	0x9ec,
-	[L'└']	0x9ed,
-	[L'┼']	0x9ee,
-	[L'─']	0x9ef,
-	[L'├']	0x9f4,
-	[L'┤']	0x9f5,
-	[L'┴']	0x9f6,
-	[L'┬']	0x9f7,
-	[L'│']	0x9f8,
-	[L' ']	0xaa1,
-	[L' ']	0xaa2,
-	[L' ']	0xaa3,
-	[L' ']	0xaa4,
-	[L' ']	0xaa5,
-	[L' ']	0xaa6,
-	[L' ']	0xaa7,
-	[L' ']	0xaa8,
-	[L'—']	0xaa9,
-	[L'–']	0xaaa,
-	[L'…']	0xaae,
-	[L'‥']	0xaaf,
-	[L'⅓']	0xab0,
-	[L'⅔']	0xab1,
-	[L'⅕']	0xab2,
-	[L'⅖']	0xab3,
-	[L'⅗']	0xab4,
-	[L'⅘']	0xab5,
-	[L'⅙']	0xab6,
-	[L'⅚']	0xab7,
-	[L'℅']	0xab8,
-	[L'‒']	0xabb,
-	[L'‹']	0xabc,
-	[L'․']	0xabd,
-	[L'›']	0xabe,
-	[L'⅛']	0xac3,
-	[L'⅜']	0xac4,
-	[L'⅝']	0xac5,
-	[L'⅞']	0xac6,
-	[L'™']	0xac9,
-	[L'℠']	0xaca,
-	[L'◁']	0xacc,
-	[L'▷']	0xacd,
-	[L'○']	0xace,
-	[L'▭']	0xacf,
-	[L'‘']	0xad0,
-	[L'’']	0xad1,
-	[L'“']	0xad2,
-	[L'”']	0xad3,
-	[L'℞']	0xad4,
-	[L'′']	0xad6,
-	[L'″']	0xad7,
-	[L'✝']	0xad9,
-	[L'∎']	0xadb,
-	[L'◂']	0xadc,
-	[L'‣']	0xadd,
-	[L'●']	0xade,
-	[L'▬']	0xadf,
-	[L'◦']	0xae0,
-	[L'▫']	0xae1,
-	[L'▮']	0xae2,
-	[L'▵']	0xae3,
-	[L'▿']	0xae4,
-	[L'☆']	0xae5,
-	[L'•']	0xae6,
-	[L'▪']	0xae7,
-	[L'▴']	0xae8,
-	[L'▾']	0xae9,
-	[L'☚']	0xaea,
-	[L'☛']	0xaeb,
-	[L'♣']	0xaec,
-	[L'♥']	0xaee,
-	[L'✠']	0xaf0,
-	[L'†']	0xaf1,
-	[L'‡']	0xaf2,
-	[L'✓']	0xaf3,
-	[L'☒']	0xaf4,
-	[L'♯']	0xaf5,
-	[L'♭']	0xaf6,
-	[L'♂']	0xaf7,
-	[L'♀']	0xaf8,
-	[L'℡']	0xaf9,
-	[L'⌕']	0xafa,
-	[L'℗']	0xafb,
-	[L'‸']	0xafc,
-	[L'‚']	0xafd,
-	[L'„']	0xafe,
-	[L'‗']	0xcdf,
-	[L'א']	0xce0,
-	[L'ב']	0xce1,
-	[L'ג']	0xce2,
-	[L'ד']	0xce3,
-	[L'ה']	0xce4,
-	[L'ו']	0xce5,
-	[L'ז']	0xce6,
-	[L'ח']	0xce7,
-	[L'ט']	0xce8,
-	[L'י']	0xce9,
-	[L'ך']	0xcea,
-	[L'כ']	0xceb,
-	[L'ל']	0xcec,
-	[L'ם']	0xced,
-	[L'מ']	0xcee,
-	[L'ן']	0xcef,
-	[L'נ']	0xcf0,
-	[L'ס']	0xcf1,
-	[L'ע']	0xcf2,
-	[L'ף']	0xcf3,
-	[L'פ']	0xcf4,
-	[L'ץ']	0xcf5,
-	[L'צ']	0xcf6,
-	[L'ק']	0xcf7,
-	[L'ר']	0xcf8,
-	[L'ש']	0xcf9,
-	[L'ת']	0xcfa,
-	[L'ก']	0xda1,
-	[L'ข']	0xda2,
-	[L'ฃ']	0xda3,
-	[L'ค']	0xda4,
-	[L'ฅ']	0xda5,
-	[L'ฆ']	0xda6,
-	[L'ง']	0xda7,
-	[L'จ']	0xda8,
-	[L'ฉ']	0xda9,
-	[L'ช']	0xdaa,
-	[L'ซ']	0xdab,
-	[L'ฌ']	0xdac,
-	[L'ญ']	0xdad,
-	[L'ฎ']	0xdae,
-	[L'ฏ']	0xdaf,
-	[L'ฐ']	0xdb0,
-	[L'ฑ']	0xdb1,
-	[L'ฒ']	0xdb2,
-	[L'ณ']	0xdb3,
-	[L'ด']	0xdb4,
-	[L'ต']	0xdb5,
-	[L'ถ']	0xdb6,
-	[L'ท']	0xdb7,
-	[L'ธ']	0xdb8,
-	[L'น']	0xdb9,
-	[L'บ']	0xdba,
-	[L'ป']	0xdbb,
-	[L'ผ']	0xdbc,
-	[L'ฝ']	0xdbd,
-	[L'พ']	0xdbe,
-	[L'ฟ']	0xdbf,
-	[L'ภ']	0xdc0,
-	[L'ม']	0xdc1,
-	[L'ย']	0xdc2,
-	[L'ร']	0xdc3,
-	[L'ฤ']	0xdc4,
-	[L'ล']	0xdc5,
-	[L'ฦ']	0xdc6,
-	[L'ว']	0xdc7,
-	[L'ศ']	0xdc8,
-	[L'ษ']	0xdc9,
-	[L'ส']	0xdca,
-	[L'ห']	0xdcb,
-	[L'ฬ']	0xdcc,
-	[L'อ']	0xdcd,
-	[L'ฮ']	0xdce,
-	[L'ฯ']	0xdcf,
-	[L'ะ']	0xdd0,
-	[L'ั']	0xdd1,
-	[L'า']	0xdd2,
-	[L'ำ']	0xdd3,
-	[L'ิ']	0xdd4,
-	[L'ี']	0xdd5,
-	[L'ึ']	0xdd6,
-	[L'ื']	0xdd7,
-	[L'ุ']	0xdd8,
-	[L'ู']	0xdd9,
-	[L'ฺ']	0xdda,
-	[L'฾']	0xdde,
-	[L'฿']	0xddf,
-	[L'เ']	0xde0,
-	[L'แ']	0xde1,
-	[L'โ']	0xde2,
-	[L'ใ']	0xde3,
-	[L'ไ']	0xde4,
-	[L'ๅ']	0xde5,
-	[L'ๆ']	0xde6,
-	[L'็']	0xde7,
-	[L'่']	0xde8,
-	[L'้']	0xde9,
-	[L'๊']	0xdea,
-	[L'๋']	0xdeb,
-	[L'์']	0xdec,
-	[L'ํ']	0xded,
-	[L'๐']	0xdf0,
-	[L'๑']	0xdf1,
-	[L'๒']	0xdf2,
-	[L'๓']	0xdf3,
-	[L'๔']	0xdf4,
-	[L'๕']	0xdf5,
-	[L'๖']	0xdf6,
-	[L'๗']	0xdf7,
-	[L'๘']	0xdf8,
-	[L'๙']	0xdf9,
-	[L'ᄁ']	0xea2,
-	[L'ᄂ']	0xea4,
-	[L'ᄃ']	0xea7,
-	[L'ᄄ']	0xea8,
-	[L'ᄅ']	0xea9,
-	[L'ᄆ']	0xeb1,
-	[L'ᄇ']	0xeb2,
-	[L'ᄈ']	0xeb3,
-	[L'ᄉ']	0xeb5,
-	[L'ᄊ']	0xeb6,
-	[L'ᄋ']	0xeb7,
-	[L'ᄌ']	0xeb8,
-	[L'ᄍ']	0xeb9,
-	[L'ᄎ']	0xeba,
-	[L'ᄏ']	0xebb,
-	[L'ᄐ']	0xebc,
-	[L'ᄑ']	0xebd,
-	[L'ᄒ']	0xebe,
-	[L'ᅡ']	0xebf,
-	[L'ᅢ']	0xec0,
-	[L'ᅣ']	0xec1,
-	[L'ᅤ']	0xec2,
-	[L'ᅥ']	0xec3,
-	[L'ᅦ']	0xec4,
-	[L'ᅧ']	0xec5,
-	[L'ᅨ']	0xec6,
-	[L'ᅩ']	0xec7,
-	[L'ᅪ']	0xec8,
-	[L'ᅫ']	0xec9,
-	[L'ᅬ']	0xeca,
-	[L'ᅭ']	0xecb,
-	[L'ᅮ']	0xecc,
-	[L'ᅯ']	0xecd,
-	[L'ᅰ']	0xece,
-	[L'ᅱ']	0xecf,
-	[L'ᅲ']	0xed0,
-	[L'ᅳ']	0xed1,
-	[L'ᅴ']	0xed2,
-	[L'ᅵ']	0xed3,
-	[L'ᆨ']	0xed4,
-	[L'ᆩ']	0xed5,
-	[L'ᆪ']	0xed6,
-	[L'ᆫ']	0xed7,
-	[L'ᆬ']	0xed8,
-	[L'ᆭ']	0xed9,
-	[L'ᆮ']	0xeda,
-	[L'ᆯ']	0xedb,
-	[L'ᆰ']	0xedc,
-	[L'ᆱ']	0xedd,
-	[L'ᆲ']	0xede,
-	[L'ᆳ']	0xedf,
-	[L'ᆴ']	0xee0,
-	[L'ᆵ']	0xee1,
-	[L'ᆶ']	0xee2,
-	[L'ᆷ']	0xee3,
-	[L'ᆸ']	0xee4,
-	[L'ᆹ']	0xee5,
-	[L'ᆺ']	0xee6,
-	[L'ᆻ']	0xee7,
-	[L'ᆼ']	0xee8,
-	[L'ᆽ']	0xee9,
-	[L'ᆾ']	0xeea,
-	[L'ᆿ']	0xeeb,
-	[L'ᇀ']	0xeec,
-	[L'ᇁ']	0xeed,
-	[L'ᇂ']	0xeee,
-	[L'ᅀ']	0xef2,
-	[L'ᅙ']	0xef5,
-	[L'ᆞ']	0xef6,
-	[L'ᇫ']	0xef8,
-	[L'ᇹ']	0xefa,
-	[L'₩']	0xeff,
-	[L'Ḃ']	0x12a1,
-	[L'ḃ']	0x12a2,
-	[L'Ḋ']	0x12a6,
-	[L'Ẁ']	0x12a8,
-	[L'Ẃ']	0x12aa,
-	[L'ḋ']	0x12ab,
-	[L'Ỳ']	0x12ac,
-	[L'Ḟ']	0x12b0,
-	[L'ḟ']	0x12b1,
-	[L'Ṁ']	0x12b4,
-	[L'ṁ']	0x12b5,
-	[L'Ṗ']	0x12b7,
-	[L'ẁ']	0x12b8,
-	[L'ṗ']	0x12b9,
-	[L'ẃ']	0x12ba,
-	[L'Ṡ']	0x12bb,
-	[L'ỳ']	0x12bc,
-	[L'Ẅ']	0x12bd,
-	[L'ẅ']	0x12be,
-	[L'ṡ']	0x12bf,
-	[L'Ŵ']	0x12d0,
-	[L'Ṫ']	0x12d7,
-	[L'Ŷ']	0x12de,
-	[L'ŵ']	0x12f0,
-	[L'ṫ']	0x12f7,
-	[L'ŷ']	0x12fe,
-	[L'Œ']	0x13bc,
-	[L'œ']	0x13bd,
-	[L'Ÿ']	0x13be,
-	[L'❁']	0x14a1,
-	[L'§']	0x14a2,
-	[L'։']	0x14a3,
-	[L')']	0x14a4,
-	[L'(']	0x14a5,
-	[L'»']	0x14a6,
-	[L'«']	0x14a7,
-	[L'.']	0x14a9,
-	[L'՝']	0x14aa,
-	[L',']	0x14ab,
-	[L'֊']	0x14ad,
-	[L'՜']	0x14af,
-	[L'՛']	0x14b0,
-	[L'՞']	0x14b1,
-	[L'Ա']	0x14b2,
-	[L'ա']	0x14b3,
-	[L'Բ']	0x14b4,
-	[L'բ']	0x14b5,
-	[L'Գ']	0x14b6,
-	[L'գ']	0x14b7,
-	[L'Դ']	0x14b8,
-	[L'դ']	0x14b9,
-	[L'Ե']	0x14ba,
-	[L'ե']	0x14bb,
-	[L'Զ']	0x14bc,
-	[L'զ']	0x14bd,
-	[L'Է']	0x14be,
-	[L'է']	0x14bf,
-	[L'Ը']	0x14c0,
-	[L'ը']	0x14c1,
-	[L'Թ']	0x14c2,
-	[L'թ']	0x14c3,
-	[L'Ժ']	0x14c4,
-	[L'ժ']	0x14c5,
-	[L'Ի']	0x14c6,
-	[L'ի']	0x14c7,
-	[L'Լ']	0x14c8,
-	[L'լ']	0x14c9,
-	[L'Խ']	0x14ca,
-	[L'խ']	0x14cb,
-	[L'Ծ']	0x14cc,
-	[L'ծ']	0x14cd,
-	[L'Կ']	0x14ce,
-	[L'կ']	0x14cf,
-	[L'Հ']	0x14d0,
-	[L'հ']	0x14d1,
-	[L'Ձ']	0x14d2,
-	[L'ձ']	0x14d3,
-	[L'Ղ']	0x14d4,
-	[L'ղ']	0x14d5,
-	[L'Ճ']	0x14d6,
-	[L'ճ']	0x14d7,
-	[L'Մ']	0x14d8,
-	[L'մ']	0x14d9,
-	[L'Յ']	0x14da,
-	[L'յ']	0x14db,
-	[L'Ն']	0x14dc,
-	[L'ն']	0x14dd,
-	[L'Շ']	0x14de,
-	[L'շ']	0x14df,
-	[L'Ո']	0x14e0,
-	[L'ո']	0x14e1,
-	[L'Չ']	0x14e2,
-	[L'չ']	0x14e3,
-	[L'Պ']	0x14e4,
-	[L'պ']	0x14e5,
-	[L'Ջ']	0x14e6,
-	[L'ջ']	0x14e7,
-	[L'Ռ']	0x14e8,
-	[L'ռ']	0x14e9,
-	[L'Ս']	0x14ea,
-	[L'ս']	0x14eb,
-	[L'Վ']	0x14ec,
-	[L'վ']	0x14ed,
-	[L'Տ']	0x14ee,
-	[L'տ']	0x14ef,
-	[L'Ր']	0x14f0,
-	[L'ր']	0x14f1,
-	[L'Ց']	0x14f2,
-	[L'ց']	0x14f3,
-	[L'Ւ']	0x14f4,
-	[L'ւ']	0x14f5,
-	[L'Փ']	0x14f6,
-	[L'փ']	0x14f7,
-	[L'Ք']	0x14f8,
-	[L'ք']	0x14f9,
-	[L'Օ']	0x14fa,
-	[L'օ']	0x14fb,
-	[L'Ֆ']	0x14fc,
-	[L'ֆ']	0x14fd,
-	[L''']	0x14ff,
-	[L'ა']	0x15d0,
-	[L'ბ']	0x15d1,
-	[L'გ']	0x15d2,
-	[L'დ']	0x15d3,
-	[L'ე']	0x15d4,
-	[L'ვ']	0x15d5,
-	[L'ზ']	0x15d6,
-	[L'თ']	0x15d7,
-	[L'ი']	0x15d8,
-	[L'კ']	0x15d9,
-	[L'ლ']	0x15da,
-	[L'მ']	0x15db,
-	[L'ნ']	0x15dc,
-	[L'ო']	0x15dd,
-	[L'პ']	0x15de,
-	[L'ჟ']	0x15df,
-	[L'რ']	0x15e0,
-	[L'ს']	0x15e1,
-	[L'ტ']	0x15e2,
-	[L'უ']	0x15e3,
-	[L'ფ']	0x15e4,
-	[L'ქ']	0x15e5,
-	[L'ღ']	0x15e6,
-	[L'ყ']	0x15e7,
-	[L'შ']	0x15e8,
-	[L'ჩ']	0x15e9,
-	[L'ც']	0x15ea,
-	[L'ძ']	0x15eb,
-	[L'წ']	0x15ec,
-	[L'ჭ']	0x15ed,
-	[L'ხ']	0x15ee,
-	[L'ჯ']	0x15ef,
-	[L'ჰ']	0x15f0,
-	[L'ჱ']	0x15f1,
-	[L'ჲ']	0x15f2,
-	[L'ჳ']	0x15f3,
-	[L'ჴ']	0x15f4,
-	[L'ჵ']	0x15f5,
-	[L'ჶ']	0x15f6,
-	[L'']	0x16a2,
-	[L'Ẋ']	0x16a3,
-	[L'']	0x16a5,
-	[L'Ĭ']	0x16a6,
-	[L'']	0x16a7,
-	[L'']	0x16a8,
-	[L'Ƶ']	0x16a9,
-	[L'Ǧ']	0x16aa,
-	[L'Ɵ']	0x16af,
-	[L'']	0x16b2,
-	[L'ẋ']	0x16b3,
-	[L'Ǒ']	0x16b4,
-	[L'']	0x16b5,
-	[L'ĭ']	0x16b6,
-	[L'']	0x16b7,
-	[L'']	0x16b8,
-	[L'ƶ']	0x16b9,
-	[L'ǧ']	0x16ba,
-	[L'ǒ']	0x16bd,
-	[L'ɵ']	0x16bf,
-	[L'Ə']	0x16c6,
-	[L'Ḷ']	0x16d1,
-	[L'']	0x16d2,
-	[L'']	0x16d3,
-	[L'ḷ']	0x16e1,
-	[L'']	0x16e2,
-	[L'']	0x16e3,
-	[L'ə']	0x16f6,
-	[L'̃']	0x1e9f,
-	[L'Ạ']	0x1ea0,
-	[L'ạ']	0x1ea1,
-	[L'Ả']	0x1ea2,
-	[L'ả']	0x1ea3,
-	[L'Ấ']	0x1ea4,
-	[L'ấ']	0x1ea5,
-	[L'Ầ']	0x1ea6,
-	[L'ầ']	0x1ea7,
-	[L'Ẩ']	0x1ea8,
-	[L'ẩ']	0x1ea9,
-	[L'Ẫ']	0x1eaa,
-	[L'ẫ']	0x1eab,
-	[L'Ậ']	0x1eac,
-	[L'ậ']	0x1ead,
-	[L'Ắ']	0x1eae,
-	[L'ắ']	0x1eaf,
-	[L'Ằ']	0x1eb0,
-	[L'ằ']	0x1eb1,
-	[L'Ẳ']	0x1eb2,
-	[L'ẳ']	0x1eb3,
-	[L'Ẵ']	0x1eb4,
-	[L'ẵ']	0x1eb5,
-	[L'Ặ']	0x1eb6,
-	[L'ặ']	0x1eb7,
-	[L'Ẹ']	0x1eb8,
-	[L'ẹ']	0x1eb9,
-	[L'Ẻ']	0x1eba,
-	[L'ẻ']	0x1ebb,
-	[L'Ẽ']	0x1ebc,
-	[L'ẽ']	0x1ebd,
-	[L'Ế']	0x1ebe,
-	[L'ế']	0x1ebf,
-	[L'Ề']	0x1ec0,
-	[L'ề']	0x1ec1,
-	[L'Ể']	0x1ec2,
-	[L'ể']	0x1ec3,
-	[L'Ễ']	0x1ec4,
-	[L'ễ']	0x1ec5,
-	[L'Ệ']	0x1ec6,
-	[L'ệ']	0x1ec7,
-	[L'Ỉ']	0x1ec8,
-	[L'ỉ']	0x1ec9,
-	[L'Ị']	0x1eca,
-	[L'ị']	0x1ecb,
-	[L'Ọ']	0x1ecc,
-	[L'ọ']	0x1ecd,
-	[L'Ỏ']	0x1ece,
-	[L'ỏ']	0x1ecf,
-	[L'Ố']	0x1ed0,
-	[L'ố']	0x1ed1,
-	[L'Ồ']	0x1ed2,
-	[L'ồ']	0x1ed3,
-	[L'Ổ']	0x1ed4,
-	[L'ổ']	0x1ed5,
-	[L'Ỗ']	0x1ed6,
-	[L'ỗ']	0x1ed7,
-	[L'Ộ']	0x1ed8,
-	[L'ộ']	0x1ed9,
-	[L'Ớ']	0x1eda,
-	[L'ớ']	0x1edb,
-	[L'Ờ']	0x1edc,
-	[L'ờ']	0x1edd,
-	[L'Ở']	0x1ede,
-	[L'ở']	0x1edf,
-	[L'Ỡ']	0x1ee0,
-	[L'ỡ']	0x1ee1,
-	[L'Ợ']	0x1ee2,
-	[L'ợ']	0x1ee3,
-	[L'Ụ']	0x1ee4,
-	[L'ụ']	0x1ee5,
-	[L'Ủ']	0x1ee6,
-	[L'ủ']	0x1ee7,
-	[L'Ứ']	0x1ee8,
-	[L'ứ']	0x1ee9,
-	[L'Ừ']	0x1eea,
-	[L'ừ']	0x1eeb,
-	[L'Ử']	0x1eec,
-	[L'ử']	0x1eed,
-	[L'Ữ']	0x1eee,
-	[L'ữ']	0x1eef,
-	[L'Ự']	0x1ef0,
-	[L'ự']	0x1ef1,
-	[L'̀']	0x1ef2,
-	[L'́']	0x1ef3,
-	[L'Ỵ']	0x1ef4,
-	[L'ỵ']	0x1ef5,
-	[L'Ỷ']	0x1ef6,
-	[L'ỷ']	0x1ef7,
-	[L'Ỹ']	0x1ef8,
-	[L'ỹ']	0x1ef9,
-	[L'Ơ']	0x1efa,
-	[L'ơ']	0x1efb,
-	[L'Ư']	0x1efc,
-	[L'ư']	0x1efd,
-	[L'̉']	0x1efe,
-	[L'̣']	0x1eff,
-	[L'₠']	0x20a0,
-	[L'₡']	0x20a1,
-	[L'₢']	0x20a2,
-	[L'₣']	0x20a3,
-	[L'₤']	0x20a4,
-	[L'₥']	0x20a5,
-	[L'₦']	0x20a6,
-	[L'₧']	0x20a7,
-	[L'₨']	0x20a8,
-	[L'₪']	0x20aa,
-	[L'₫']	0x20ab,
-	[L'€']	0x20ac,
-
-};
\ No newline at end of file
--- a/sys/src/cmd/vnc/vnc.h
+++ /dev/null
@@ -1,149 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <draw.h>
-#include <memdraw.h>
-
-typedef struct Pixfmt	Pixfmt;
-typedef struct Colorfmt	Colorfmt;
-typedef struct Vnc	Vnc;
-
-struct Colorfmt {
-	int		max;
-	int		shift;
-};
-
-struct Pixfmt {
-	int		bpp;
-	int		depth;
-	int		bigendian;
-	int		truecolor;
-	Colorfmt	red;
-	Colorfmt	green;
-	Colorfmt	blue;
-};
-
-struct Vnc {
-	QLock;
-	int		datafd;			/* for network connection */
-	int		ctlfd;			/* control for network connection */
-
-	Biobuf		in;
-	Biobuf		out;
-
-	Rectangle	dim;
-	Pixfmt;
-
-	/* client only */
-	char		*name;
-	char		*srvaddr;
-	int		vers;
-
-	int		canresize;
-	struct {
-		ulong		id;
-		Rectangle	rect;
-		ulong		flags;
-	}		screen[1];
-};
-
-enum {
-	VerLen		= 12,
-	/* authentication negotiation */
-	AFailed		= 0,
-	ANoAuth,
-	AVncAuth,
-
-	/* vnc auth negotiation */
-	VncAuthOK	= 0,
-	VncAuthFailed,
-	VncAuthTooMany,
-	VncChalLen	= 16,
-
-	/* server to client */
-	MFrameUpdate	= 0,
-	MSetCmap,
-	MBell,
-	MSCut,
-	MSAck,
-
-	/* client to server */
-	MPixFmt		= 0,
-	MFixCmap,
-	MSetEnc,
-	MFrameReq,
-	MKey,
-	MMouse,
-	MCCut,
-	MSetDesktopSize = 251,
-
-	/* image encoding methods */
-	EncRaw		= 0,
-	EncCopyRect	= 1,
-	EncRre		= 2,
-	EncCorre	= 4,
-	EncHextile	= 5,
-	EncZlib		= 6,  /* 6,7,8 have been used by others */
-	EncTight	= 7,
-	EncZHextile	= 8,
-	EncMouseWarp	= 9,
-
-	EncDesktopSize	= -223,
-	EncXDesktopSize	= -308,
-
-	/* paramaters for hextile encoding */
-	HextileDim	= 16,
-	HextileRaw	= 1,
-	HextileBack	= 2,
-	HextileFore	= 4,
-	HextileRects	= 8,
-	HextileCols	= 16
-};
-
-/*
- * we're only using the ulong as a place to store bytes,
- * and as something to compare against.
- * the bytes are stored in little-endian format.
- */
-typedef ulong Color;
-
-/* auth.c */
-extern	int		vncauth(Vnc*, char*);
-extern	int		vnchandshake(Vnc*);
-extern	int		vncsrvauth(Vnc*);
-extern	int		vncsrvhandshake(Vnc*);
-
-/* proto.c */
-extern	Vnc*		vncinit(int, int, Vnc*);
-extern	uchar		vncrdchar(Vnc*);
-extern	ushort		vncrdshort(Vnc*);
-extern	ulong		vncrdlong(Vnc*);
-extern	Point		vncrdpoint(Vnc*);
-extern	Rectangle	vncrdrect(Vnc*);
-extern	Rectangle	vncrdcorect(Vnc*);
-extern	Pixfmt		vncrdpixfmt(Vnc*);
-extern	void		vncrdbytes(Vnc*, void*, int);
-extern	char*		vncrdstring(Vnc*);
-extern	char*	vncrdstringx(Vnc*);
-extern	void		vncwrstring(Vnc*, char*);
-extern  void    	vncgobble(Vnc*, long);
-
-extern	void		vncflush(Vnc*);
-extern	void		vncterm(Vnc*);
-extern	void		vncwrbytes(Vnc*, void*, int);
-extern	void		vncwrlong(Vnc*, ulong);
-extern	void		vncwrshort(Vnc*, ushort);
-extern	void		vncwrchar(Vnc*, uchar);
-extern	void		vncwrpixfmt(Vnc*, Pixfmt*);
-extern	void		vncwrrect(Vnc*, Rectangle);
-extern	void		vncwrpoint(Vnc*, Point);
-
-extern	void		vnclock(Vnc*);		/* for writing */
-extern	void		vncunlock(Vnc*);
-
-extern	void		hexdump(void*, int);
-
-/* implemented by clients of the io library */
-extern	void		vnchungup(Vnc*);
-
-extern	int		verbose;
--- a/sys/src/cmd/vnc/vncs.c
+++ /dev/null
@@ -1,1143 +1,0 @@
-#define	Image	IMAGE
-#include "vnc.h"
-#include "vncs.h"
-#include "compat.h"
-#include <cursor.h>
-#include "screen.h"
-#include "kbd.h"
-
-#include <mp.h>
-#include <libsec.h>
-
-extern	Dev	drawdevtab;
-extern	Dev	mousedevtab;
-extern	Dev	consdevtab;
-
-Dev	*devtab[] =
-{
-	&drawdevtab,
-	&mousedevtab,
-	&consdevtab,
-	nil
-};
-
-/* 
- * list head. used to hold the list, the lock, dim, and pixelfmt
- */
-struct {
-	QLock;
-	Vncs *head;
-} clients;
-
-int	shared;
-int	sleeptime = 5;
-int	verbose = 0;
-int	noauth = 0;
-int	kbdin = -1;
-
-char *cert;
-char *pixchan = "r5g6b5";
-static int	cmdpid;
-static int	srvfd;
-static int	exportfd;
-static Vncs	**vncpriv;
-
-static int parsedisplay(char*);
-static void vnckill(char*, int, int);
-static int vncannounce(char *net, int display, char *adir, int base);
-static void noteshutdown(void*, char*);
-static void vncaccept(Vncs*);
-static int vncsfmt(Fmt*);
-static void getremote(char*, char*);
-#pragma varargck type "V" Vncs*
-
-void
-usage(void)
-{
-	fprint(2, "usage: vncs [-v] [-c cert] [-d :display] [-g widthXheight] [-p pixelfmt] [-A] [cmd [args]...]\n");
-	fprint(2, "\tto kill a server: vncs [-v] -k :display\n");
-	exits("usage");
-}
-
-void
-main(int argc, char **argv)
-{
-	int baseport, cfd, display, exnum, fd, pid, h, killing, w;
-	char adir[NETPATHLEN], ldir[NETPATHLEN];
-	char net[NETPATHLEN], *p;
-	char *kbdfs[] = { "/bin/aux/kbdfs", "-dq", nil };
-	char *rc[] = { "/bin/rc", "-i", nil };
-	Vncs *v;
-
-	fmtinstall('V', vncsfmt);
-	display = -1;
-	killing = 0;
-	w = 1024;
-	h = 768;
-	baseport = 5900;
-	setnetmtpt(net, sizeof net, nil);
-	ARGBEGIN{
-	default:
-		usage();
-	case 'c':
-		cert = EARGF(usage());
-		baseport = 35729;
-		break;
-	case 'd':
-		if(display != -1)
-			usage();
-		display = parsedisplay(EARGF(usage()));
-		break;
-	case 'g':
-		p = EARGF(usage());
-		w = strtol(p, &p, 10);
-		if(*p != 'x' && *p != 'X' && *p != ' ' && *p != '	')
-			usage();
-		h = strtol(p+1, &p, 10);
-		if(*p != 0)
-			usage();
-		break;
-	case 'k':
-		if(display != -1)
-			usage();
-		display = parsedisplay(EARGF(usage()));
-		killing = 1;
-		break;
-	case 'p':
-		pixchan = EARGF(usage());
-		break;
-/* DEBUGGING
-	case 's':
-		sleeptime = atoi(EARGF(usage()));
-		break;
-*/
-	case 'v':
-		verbose++;
-		break;
-	case 'x':
-		p = EARGF(usage());
-		setnetmtpt(net, sizeof net, p);
-		break;
-	case 'A':
-		noauth = 1;
-		break;
-	}ARGEND
-
-	if(killing){
-		vnckill(net, display, baseport);
-		exits(nil);
-	}
-
-	if(argc == 0)
-		argv = rc;
-
-	/* easy exit */
-	if(access(argv[0], AEXEC) < 0)
-		sysfatal("access %s for exec: %r", argv[0]);
-
-	/* background ourselves */
-	switch(rfork(RFPROC|RFNAMEG|RFFDG|RFNOTEG)){
-	case -1:
-		sysfatal("rfork: %r");
-	default:
-		exits(nil);
-	case 0:
-		break;
-	}
-
-	vncpriv = privalloc();
-	if(vncpriv == nil)
-		sysfatal("privalloc: %r");
-
-	/* start screen */
-	initcompat();
-	if(waserror())
-		sysfatal("screeninit %dx%d %s: %s", w, h, pixchan, up->error);
-	if(verbose)
-		fprint(2, "geometry is %dx%d\n", w, h);
-	screeninit(w, h, pixchan);
-	poperror();
-
-	/* start file system device slaves */
-	exnum = exporter(devtab, &fd, &exportfd);
-
-	/* rebuild /dev because the underlying connection might go away (ick) */
-	unmount(nil, "/dev");
-	bind("#c", "/dev", MREPL);
-
-	/* mount exporter */
-	if(mounter("/dev", MBEFORE, fd, exnum) < 0)
-		sysfatal("mounter: %r");
-	close(fd);
-
-	pid = rfork(RFPROC|RFMEM|RFFDG|RFNOTEG);
-	switch(pid){
-	case -1:
-		sysfatal("rfork: %r");
-		break;
-	case 0:
-		close(exportfd);
-
-		close(1);
-		open("/dev/cons", OWRITE);
-		close(2);
-		open("/dev/cons", OWRITE);
-
-		/* start and mount kbdfs */
-		pid = rfork(RFPROC|RFMEM|RFFDG|RFREND);
-		switch(pid){
-		case -1:
-			sysfatal("rfork: %r");
-			break;
-		case 0:
-			exec(kbdfs[0], kbdfs);
-			fprint(2, "exec %s: %r\n", kbdfs[0]);
-			_exits("kbdfs");
-		}
-		if(waitpid() != pid){
-			rendezvous(&kbdin, nil);
-			sysfatal("waitpid: %s: %r", kbdfs[0]);
-		}
-		rendezvous(&kbdin, nil);
-
-		rfork(RFNAMEG|RFREND);
-
-		close(0);
-		open("/dev/cons", OREAD);
-		close(1);
-		open("/dev/cons", OWRITE);
-		close(2);
-		open("/dev/cons", OWRITE);
-
-		exec(argv[0], argv);
-		fprint(2, "exec %s: %r\n", argv[0]);
-		_exits(nil);
-	}
-	cmdpid = pid;
-
-	/* wait for kbdfs to get mounted */
-	rendezvous(&kbdin, nil);
-	if((kbdin = open("/dev/kbdin", OWRITE)) < 0)
-		sysfatal("open /dev/kbdin: %r");
-
-	/* run the service */
-	srvfd = vncannounce(net, display, adir, baseport);
-	if(srvfd < 0)
-		sysfatal("announce failed");
-	if(verbose)
-		fprint(2, "announced in %s\n", adir);
-
-	atexit(shutdown);
-	notify(noteshutdown);
-	for(;;){
-		procsetname("listener");
-		cfd = listen(adir, ldir);
-		if(cfd < 0)
-			break;
-		if(verbose)
-			fprint(2, "call in %s\n", ldir);
-		fd = accept(cfd, ldir);
-		if(fd < 0){
-			close(cfd);
-			continue;
-		}
-		v = mallocz(sizeof(Vncs), 1);
-		if(v == nil){
-			close(cfd);
-			close(fd);
-			continue;
-		}
-		v->ctlfd = cfd;
-		v->datafd = fd;
-		v->nproc = 1;
-		v->ndead = 0;
-		getremote(ldir, v->remote);
-		strcpy(v->netpath, ldir);
-		qlock(&clients);
-		v->next = clients.head;
-		clients.head = v;
-		qunlock(&clients);
-		vncaccept(v);
-	}
-	exits(0);
-}
-
-static int
-parsedisplay(char *p)
-{
-	int n;
-
-	if(*p != ':')
-		usage();
-	if(*p == 0)
-		usage();
-	n = strtol(p+1, &p, 10);
-	if(*p != 0)
-		usage();
-	return n;
-}
-
-static void
-getremote(char *ldir, char *remote)
-{
-	char buf[NETPATHLEN];
-	int fd, n;
-
-	snprint(buf, sizeof buf, "%s/remote", ldir);
-	strcpy(remote, "<none>");
-	if((fd = open(buf, OREAD)) < 0)
-		return;
-	n = readn(fd, remote, NETPATHLEN-1);
-	close(fd);
-	if(n < 0)
-		return;
-	remote[n] = 0;
-	if(n>0 && remote[n-1] == '\n')
-		remote[n-1] = 0;
-}
-
-static int
-vncsfmt(Fmt *fmt)
-{
-	Vncs *v;
-
-	v = va_arg(fmt->args, Vncs*);
-	return fmtprint(fmt, "[%d] %s %s", getpid(), v->remote, v->netpath);
-}
-
-/*
- * We register exiting as an atexit handler in each proc, so that 
- * client procs need merely exit when something goes wrong.
- */
-static void
-vncclose(Vncs *v)
-{
-	Vncs **l;
-
-	/* remove self from client list if there */
-	qlock(&clients);
-	for(l=&clients.head; *l; l=&(*l)->next)
-		if(*l == v){
-			*l = v->next;
-			break;
-		}
-	qunlock(&clients);
-
-	/* if last proc, free v */
-	vnclock(v);
-	if(++v->ndead < v->nproc){
-		vncunlock(v);
-		return;
-	}
-
-	freerlist(&v->rlist);
-	vncterm(v);
-	if(v->ctlfd >= 0)
-		close(v->ctlfd);
-	if(v->datafd >= 0)
-		close(v->datafd);
-	if(v->image)
-		freememimage(v->image);
-	free(v);
-}
-
-static void
-exiting(void)
-{
-	vncclose(*vncpriv);
-}
-
-void
-vnchungup(Vnc *v)
-{
-	if(verbose)
-		fprint(2, "%V: hangup\n", (Vncs*)v);
-	exits(0);	/* atexit and exiting() will take care of everything */
-}
-
-/*
- * Kill all clients except safe.
- * Used to start a non-shared client and at shutdown. 
- */
-static void
-killclients(Vncs *safe)
-{
-	Vncs *v;
-
-	qlock(&clients);
-	for(v=clients.head; v; v=v->next){
-		if(v == safe)
-			continue;
-		if(v->ctlfd >= 0){
-			hangup(v->ctlfd);
-			close(v->ctlfd);
-			v->ctlfd = -1;
-			close(v->datafd);
-			v->datafd = -1;
-		}
-	}
-	qunlock(&clients);
-}
-
-/*
- * Kill the executing command and then kill everyone else.
- * Called to close up shop at the end of the day
- * and also if we get an unexpected note.
- */
-static char killkin[] = "die vnc kin";
-static void
-killall(void)
-{
-	postnote(PNGROUP, cmdpid, "hangup");
-	close(srvfd);
-	srvfd = -1;
-	close(exportfd);
-	exportfd = -1;
-	close(kbdin);
-	kbdin = -1;
-	postnote(PNGROUP, getpid(), killkin);
-}
-
-void
-shutdown(void)
-{
-	if(verbose)
-		fprint(2, "vnc server shutdown\n");
-	killall();
-}
-
-static void
-noteshutdown(void*, char *msg)
-{
-	if(strcmp(msg, killkin) == 0)	/* already shutting down */
-		noted(NDFLT);
-	killall();
-	noted(NDFLT);
-}
-
-/*
- * Kill a specific instance of a server.
- */
-static void
-vnckill(char *net, int display, int baseport)
-{
-	int fd, i, n, port;
-	char buf[NETPATHLEN], *p;
-
-	for(i=0;; i++){
-		snprint(buf, sizeof buf, "%s/tcp/%d/local", net, i);
-		if((fd = open(buf, OREAD)) < 0)
-			sysfatal("did not find display");
-		n = read(fd, buf, sizeof buf-1);
-		close(fd);
-		if(n <= 0)
-			continue;
-		buf[n] = 0;
-		p = strchr(buf, '!');
-		if(p == 0)
-			continue;
-		port = atoi(p+1);
-		if(port != display+baseport)
-			continue;
-		snprint(buf, sizeof buf, "%s/tcp/%d/ctl", net, i);
-		fd = open(buf, OWRITE);
-		if(fd < 0)
-			sysfatal("cannot open %s: %r", buf);
-		if(write(fd, "hangup", 6) != 6)
-			sysfatal("cannot hangup %s: %r", buf);
-		close(fd);
-		break;
-	}
-}
-
-/*
- * Look for a port on which to announce.
- * If display != -1, we only try that one.
- * Otherwise we hunt.
- *
- * Returns the announce fd.
- */
-static int
-vncannounce(char *net, int display, char *adir, int base)
-{
-	int port, eport, fd;
-	char addr[NETPATHLEN];
-
-	if(display == -1){
-		port = base;
-		eport = base+50;
-	}else{
-		port = base+display;
-		eport = port;
-	}
-
-	for(; port<=eport; port++){
-		snprint(addr, sizeof addr, "%s/tcp!*!%d", net, port);
-		if((fd = announce(addr, adir)) >= 0){
-			fprint(2, "server started on display :%d\n", port-base);
-			return fd;
-		}
-	}
-	if(display == -1)
-		fprint(2, "could not find any ports to announce\n");
-	else
-		fprint(2, "announce: %r\n");
-	return -1;
-}
-
-/*
- * Handle a new connection.
- */
-static void clientreadproc(Vncs*);
-static void clientwriteproc(Vncs*);
-static void chan2fmt(Pixfmt*, ulong);
-static ulong fmt2chan(Pixfmt*);
-
-static void
-vncaccept(Vncs *v)
-{
-	char buf[32];
-	int fd;
-
-	/* caller returns to listen */
-	switch(rfork(RFPROC|RFMEM|RFNAMEG)){
-	case -1:
-		fprint(2, "%V: fork failed: %r\n", v);
-		vncclose(v);
-		return;
-	default:
-		return;
-	case 0:
-		break;
-	}
-	*vncpriv = v;
-
-	if(!atexit(exiting)){
-		fprint(2, "%V: could not register atexit handler: %r; hanging up\n", v);
-		exiting();
-		exits(nil);
-	}
-
-	if(cert != nil){
-		TLSconn conn;
-
-		memset(&conn, 0, sizeof conn);
-		conn.cert = readcert(cert, &conn.certlen);
-		if(conn.cert == nil){
-			fprint(2, "%V: could not read cert %s: %r; hanging up\n", v, cert);
-			exits(nil);
-		}
-		fd = tlsServer(v->datafd, &conn);
-		if(fd < 0){
-			fprint(2, "%V: tlsServer: %r; hanging up\n", v);
-			free(conn.cert);
-			free(conn.sessionID);
-			exits(nil);
-		}
-		v->datafd = fd;
-		free(conn.cert);
-		free(conn.sessionID);
-	}
-	vncinit(v->datafd, v->ctlfd, v);
-
-	if(verbose)
-		fprint(2, "%V: handshake\n", v);
-	if(vncsrvhandshake(v) < 0){
-		fprint(2, "%V: handshake failed; hanging up\n", v);
-		exits(0);
-	}
-
-	if(noauth){
-		if(verbose)
-			fprint(2, "%V: noauth\n", v);
-		vncwrlong(v, ANoAuth);
-		vncflush(v);
-	} else {
-		if(verbose)
-			fprint(2, "%V: auth\n", v);
-		if(vncsrvauth(v) < 0){
-			fprint(2, "%V: auth failed; hanging up\n", v);
-			exits(0);
-		}
-	}
-
-	shared = vncrdchar(v);
-
-	if(verbose)
-		fprint(2, "%V: %sshared\n", v, shared ? "" : "not ");
-	if(!shared)
-		killclients(v);
-
-	v->dim = rectsubpt(gscreen->clipr, gscreen->clipr.min);
-	vncwrpoint(v, v->dim.max);
-	if(verbose)
-		fprint(2, "%V: send screen size %R\n", v, v->dim);
-
-	v->bpp = gscreen->depth;
-	v->depth = gscreen->depth;
-	v->truecolor = 1;
-	v->bigendian = 0;
-	chan2fmt(v, gscreen->chan);
-	if(verbose)
-		fprint(2, "%V: bpp=%d, depth=%d, chan=%s\n", v,
-			v->bpp, v->depth, chantostr(buf, gscreen->chan));
-	vncwrpixfmt(v, v);
-	vncwrlong(v, 14);
-	vncwrbytes(v, "Plan9 Desktop", 14);
-	vncflush(v);
-
-	if(verbose)
-		fprint(2, "%V: handshaking done\n", v);
-
-	v->updatereq = 0;
-
-	switch(rfork(RFPROC|RFMEM)){
-	case -1:
-		fprint(2, "%V: cannot fork: %r; hanging up\n", v);
-		vnchungup(v);
-	default:
-		clientreadproc(v);
-		exits(nil);
-	case 0:
-		*vncpriv = v;
-		v->nproc++;
-		if(atexit(exiting) == 0){
-			exiting();
-			fprint(2, "%V: could not register atexit handler: %r; hanging up\n", v);
-			exits(nil);
-		}
-		clientwriteproc(v);
-		exits(nil);
-	}
-}
-
-
-/*
- * Set the pixel format being sent.  Can only happen once.
- * (Maybe a client would send this again if the screen changed
- * underneath it?  If we want to support this we need a way to
- * make sure the current image is no longer in use, so we can free it. 
- */
-static void
-setpixelfmt(Vncs *v)
-{
-	ulong chan;
-
-	vncgobble(v, 3);
-	v->Pixfmt = vncrdpixfmt(v);
-	chan = fmt2chan(v);
-	if(chan == 0){
-		fprint(2, "%V: bad pixel format; hanging up\n", v);
-		vnchungup(v);
-	}
-	v->imagechan = chan;
-}
-
-/*
- * Set the preferred encoding list.  Can only happen once.
- * If we want to support changing this more than once then
- * we need to put a lock around the encoding functions
- * so as not to conflict with updateimage.
- */
-static void
-setencoding(Vncs *v)
-{
-	int n, x;
-
-	vncrdchar(v);
-	n = vncrdshort(v);
-	while(n-- > 0){
-		x = vncrdlong(v);
-		switch(x){
-		case EncCopyRect:
-			v->copyrect = 1;
-			continue;
-		case EncMouseWarp:
-			v->canwarp = 1;
-			continue;
-		case EncDesktopSize:
-			v->canresize |= 1;
-			continue;
-		case EncXDesktopSize:
-			v->canresize |= 2;
-			continue;
-		}
-		if(v->countrect != nil)
-			continue;
-		switch(x){
-		case EncRaw:
-			v->encname = "raw";
-			v->countrect = countraw;
-			v->sendrect = sendraw;
-			break;
-		case EncRre:
-			v->encname = "rre";
-			v->countrect = countrre;
-			v->sendrect = sendrre;
-			break;
-		case EncCorre:
-			v->encname = "corre";
-			v->countrect = countcorre;
-			v->sendrect = sendcorre;
-			break;
-		case EncHextile:
-			v->encname = "hextile";
-			v->countrect = counthextile;
-			v->sendrect = sendhextile;
-			break;
-		}
-	}
-
-	if(v->countrect == nil){
-		v->encname = "raw";
-		v->countrect = countraw;
-		v->sendrect = sendraw;
-	}
-
-	if(verbose)
-		fprint(2, "Encoding with %s%s%s%s\n", v->encname,
-			v->copyrect ? ", copyrect" : "",
-			v->canwarp ? ", canwarp" : "",
-			v->canresize ? ", resize" : "");
-}
-
-/*
- * Continually read updates from one client.
- */
-static void
-clientreadproc(Vncs *v)
-{
-	int incremental, key, keydown, buttons, type, x, y, n;
-	char *buf;
-	Rectangle r;
-
-	procsetname("read %V", v);
-
-	for(;;){
-		type = vncrdchar(v);
-		switch(type){
-		default:
-			fprint(2, "%V: unknown vnc message type %d; hanging up\n", v, type);
-			vnchungup(v);
-
-		/* set pixel format */
-		case MPixFmt:
-			setpixelfmt(v);
-			break;
-
-		/* ignore color map changes */
-		case MFixCmap:
-			vncgobble(v, 3);
-			n = vncrdshort(v);
-			vncgobble(v, n*6);
-			break;
-
-		/* set encoding list */
-		case MSetEnc:
-			setencoding(v);
-			break;
-
-		/* request image update in rectangle */
-		case MFrameReq:
-			incremental = vncrdchar(v);
-			r = vncrdrect(v);
-			if(!incremental){
-				qlock(&drawlock);	/* protects rlist */
-				addtorlist(&v->rlist, r);
-				qunlock(&drawlock);
-			}
-			v->updatereq++;
-			break;
-
-		case MSetDesktopSize:
-			vncrdchar(v);
-			vncrdpoint(v);	// desktop size
-			n = vncrdchar(v);
-			vncrdchar(v);
-			if(n == 0)
-				break;
-			vncrdlong(v);	// id
-			r = vncrdrect(v);
-			vncrdlong(v);	// flags
-			while(--n > 0){
-				vncrdlong(v);
-				vncrdrect(v);
-				vncrdlong(v);
-			}
-			qlock(&drawlock);
-			if(!rectclip(&r, gscreen->r)){
-				qunlock(&drawlock);
-				break;
-			}
-			gscreen->clipr = r;
-			qunlock(&drawlock);
-
-			screenwin();
-			deletescreenimage();
-			resetscreenimage();
-			break;
-
-		/* send keystroke */
-		case MKey:
-			keydown = vncrdchar(v);
-			vncgobble(v, 2);
-			key = vncrdlong(v);
-			vncputc(!keydown, key);
-			break;
-
-		/* send mouse event */
-		case MMouse:
-			buttons = vncrdchar(v);
-			x = vncrdshort(v);
-			y = vncrdshort(v);
-			absmousetrack(x, y, buttons, nsec()/(1000*1000LL));
-			break;
-
-		/* send cut text */
-		case MCCut:
-			vncgobble(v, 3);
-			n = vncrdlong(v);
-			buf = malloc(n+1);
-			if(buf){
-				vncrdbytes(v, buf, n);
-				buf[n] = 0;
-				vnclock(v);	/* for snarfvers */
-				setsnarf(buf, n, &v->snarfvers);
-				vncunlock(v);
-			}else
-				vncgobble(v, n);
-			break;
-		}
-	}
-}
-
-static int
-nbits(ulong mask)
-{
-	int n;
-
-	n = 0;
-	for(; mask; mask>>=1)
-		n += mask&1;
-	return n;
-}
-
-typedef struct Col Col;
-struct Col {
-	int type;
-	int nbits;
-	int shift;
-};
-
-static ulong
-fmt2chan(Pixfmt *fmt)
-{
-	Col c[4], t;
-	int i, j, depth, n, nc;
-	ulong mask, u;
-
-	/* unpack the Pixfmt channels */
-	c[0] = (Col){CRed, nbits(fmt->red.max), fmt->red.shift};
-	c[1] = (Col){CGreen, nbits(fmt->green.max), fmt->green.shift};
-	c[2] = (Col){CBlue, nbits(fmt->blue.max), fmt->blue.shift};
-	nc = 3;
-
-	/* add an ignore channel if necessary */
-	depth = c[0].nbits+c[1].nbits+c[2].nbits;
-	if(fmt->bpp != depth){
-		/* BUG: assumes only one run of ignored bits */
-		if(fmt->bpp == 32)
-			mask = ~0;
-		else
-			mask = (1<<fmt->bpp)-1;
-		mask ^= fmt->red.max << fmt->red.shift;
-		mask ^= fmt->green.max << fmt->green.shift;
-		mask ^= fmt->blue.max << fmt->blue.shift;
-		if(mask == 0)
-			abort();
-		n = 0;
-		for(; !(mask&1); mask>>=1)
-			n++;
-		c[3] = (Col){CIgnore, nbits(mask), n};
-		nc++;
-	}
-
-	/* sort the channels, largest shift (leftmost bits) first */
-	for(i=1; i<nc; i++)
-		for(j=i; j>0; j--)
-			if(c[j].shift > c[j-1].shift){
-				t = c[j];
-				c[j] = c[j-1];
-				c[j-1] = t;
-			}
-
-	/* build the channel descriptor */
-	u = 0;
-	for(i=0; i<nc; i++){
-		u <<= 8;
-		u |= CHAN1(c[i].type, c[i].nbits);
-	}
-
-	return u;
-}
-
-static void
-chan2fmt(Pixfmt *fmt, ulong chan)
-{
-	ulong c, rc, shift;
-
-	shift = 0;
-	for(rc = chan; rc; rc >>=8){
-		c = rc & 0xFF;
-		switch(TYPE(c)){
-		case CRed:
-			fmt->red = (Colorfmt){(1<<NBITS(c))-1, shift};
-			break;
-		case CBlue:
-			fmt->blue = (Colorfmt){(1<<NBITS(c))-1, shift};
-			break;
-		case CGreen:
-			fmt->green = (Colorfmt){(1<<NBITS(c))-1, shift};
-			break;
-		}
-		shift += NBITS(c);
-	}
-}
-
-/*
- * Note that r has changed on the screen.
- * Updating the rlists is okay because they are protected by drawlock.
- */
-void
-flushmemscreen(Rectangle r)
-{
-	Vncs *v;
-
-	if(!rectclip(&r, gscreen->clipr))
-		return;
-	qlock(&clients);
-	for(v=clients.head; v; v=v->next)
-		addtorlist(&v->rlist, r);
-	qunlock(&clients);
-}
-
-/*
- * Queue a mouse warp note for the next update to each client.
- */
-void
-mousewarpnote(Point p)
-{
-	Vncs *v;
-
-	qlock(&clients);
-	for(v=clients.head; v; v=v->next){
-		if(v->canwarp){
-			vnclock(v);
-			v->dowarp = 1;
-			v->warppt = p;
-			vncunlock(v);
-		}
-	}
-	qunlock(&clients);
-}
-
-/*
- * Send a client his changed screen image.
- * v is locked on entrance, locked on exit, but released during.
- */
-static int
-updateimage(Vncs *v)
-{
-	int i, j, ncount, nsend, docursor, dowarp, doresize;
-	vlong ooffset = 0, t1 = 0;
-	Point warppt;
-	Rectangle cr;
-	Rlist rlist;
-	int (*count)(Vncs*, Rectangle);
-	int (*send)(Vncs*, Rectangle);
-
-	vnclock(v);
-	dowarp = v->canwarp && v->dowarp;
-	warppt = v->warppt;
-	v->dowarp = 0;
-	vncunlock(v);
-
-	/* copy the screen bits and then unlock the screen so updates can proceed */
-	qlock(&drawlock);
-	rlist = v->rlist;
-	memset(&v->rlist, 0, sizeof v->rlist);
-
-	if(v->canresize && !eqrect(v->screen[0].rect, gscreen->clipr)){
-		v->screen[0].rect = gscreen->clipr;
-		v->dim = rectsubpt(gscreen->clipr, gscreen->clipr.min);
-		doresize = 1;
-	} else
-		doresize = 0;
-
-	if(doresize
-	|| (v->image == nil && v->imagechan != 0)
-	|| (v->image != nil && v->image->chan != v->imagechan)){
-		if(v->image)
-			freememimage(v->image);
-		v->image = allocmemimage(v->dim, v->imagechan);
-		if(v->image == nil){
-			fprint(2, "%V: allocmemimage: %r; hanging up\n", v);
-			qlock(&drawlock);
-			vnchungup(v);
-		}
-	}
-
-	/* if the cursor has moved or changed shape, we need to redraw its square */
-	lock(&cursor);
-	if(v->cursorver != cursorver || !eqpt(v->cursorpos, cursorpos)){
-		docursor = 1;
-		v->cursorver = cursorver;
-		v->cursorpos = cursorpos;
-		cr = cursorrect();
-	}else{
-		docursor = 0;
-		cr = v->cursorr;
-	}
-	unlock(&cursor);
-
-	if(docursor){
-		addtorlist(&rlist, v->cursorr);
-		if(!rectclip(&cr, gscreen->clipr))
-			cr.max = cr.min;
-		addtorlist(&rlist, cr);
-	}
-
-	/* copy changed screen parts, also check for parts overlapping cursor location */
-	for(i=0; i<rlist.nrect; i++){
-		if(!docursor)
-			docursor = rectXrect(v->cursorr, rlist.rect[i]);
-		memimagedraw(v->image, rlist.rect[i], gscreen, rlist.rect[i].min, memopaque, ZP, S);
-	}
-
-	if(docursor){
-		cursordraw(v->image, cr);
-		addtorlist(&rlist, v->cursorr);
-		v->cursorr = cr;
-	}
-
-	qunlock(&drawlock);
-
-	count = v->countrect;
-	send = v->sendrect;
-	if(count == nil || send == nil){
-		count = countraw;
-		send = sendraw;
-	}
-
-	ncount = 0;
-	for(i=j=0; i<rlist.nrect; i++){
-		if(j < i)
-			rlist.rect[j] = rlist.rect[i];
-		if(rectclip(&rlist.rect[j], v->dim))
-			ncount += (*count)(v, rlist.rect[j++]);
-	}
-	rlist.nrect = j;
-
-	if(doresize == 0 && ncount == 0 && dowarp == 0)
-		return 0;
-
-	if(verbose > 1){
-		fprint(2, "sendupdate: rlist.nrect=%d, ncount=%d\n", rlist.nrect, ncount);
-		t1 = nsec();
-		ooffset = Boffset(&v->out);
-	}
-
-	if(doresize && v->canresize == 1){
-		doresize = 0;
-
-		vncwrchar(v, MFrameUpdate);
-		vncwrchar(v, 0);
-		vncwrshort(v, 1);
-		vncwrrect(v, v->dim);
-		vncwrlong(v, EncDesktopSize);
-	}
-
-	vncwrchar(v, MFrameUpdate);
-	vncwrchar(v, 0);
-	vncwrshort(v, doresize+ncount+dowarp);
-
-	if(doresize){
-		vncwrrect(v, gscreen->r);
-		vncwrlong(v, EncXDesktopSize);
-		vncwrlong(v, 1<<24);
-		vncwrlong(v, v->screen[0].id);
-		vncwrrect(v, v->screen[0].rect);
-		vncwrlong(v, v->screen[0].flags);
-	}
-
-	nsend = 0;
-	for(i=0; i<rlist.nrect; i++)
-		nsend += (*send)(v, rlist.rect[i]);
-
-	if(ncount != nsend){
-		fprint(2, "%V: ncount=%d, nsend=%d; hanging up\n", v, ncount, nsend);
-		vnchungup(v);
-	}
-
-	if(dowarp){
-		vncwrrect(v, Rect(warppt.x, warppt.y, warppt.x+1, warppt.y+1));
-		vncwrlong(v, EncMouseWarp);
-	}
-
-	if(verbose > 1){
-		t1 = nsec() - t1;
-		fprint(2, " in %lldms, %lld bytes\n", t1/1000000, Boffset(&v->out) - ooffset);
-	}
-
-	freerlist(&rlist);
-	return 1;
-}
-
-/*
- * Update the snarf buffer if it has changed.
- */
-static void
-updatesnarf(Vncs *v)
-{
-	char *buf;
-	int len;
-
-	if(v->snarfvers == snarf.vers)
-		return;
-	qlock(&snarf);
-	len = snarf.n;
-	buf = malloc(len);
-	if(buf == nil){
-		qunlock(&snarf);
-		return;
-	}
-	memmove(buf, snarf.buf, len);
-	v->snarfvers = snarf.vers;
-	qunlock(&snarf);
-
-	vncwrchar(v, MSCut);
-	vncwrbytes(v, "pad", 3);
-	vncwrlong(v, len);
-	vncwrbytes(v, buf, len);
-	free(buf);
-}
-
-/*
- * Continually update one client.
- */
-static void
-clientwriteproc(Vncs *v)
-{
-	ulong last = 0;
-
-	procsetname("write %V", v);
-	while(!v->ndead){
-		sleep(sleeptime);
-		updatesnarf(v);
-		if(v->updatereq != last && updateimage(v))
-			last++;
-		vncflush(v);
-	}
-	vnchungup(v);
-}
-
--- a/sys/src/cmd/vnc/vncs.h
+++ /dev/null
@@ -1,54 +1,0 @@
-typedef struct	Rlist Rlist;
-typedef struct	Vncs	Vncs;
-
-struct Rlist
-{
-	Rectangle	bbox;
-	int	maxrect;
-	int	nrect;
-	Rectangle *rect;
-};
-
-struct Vncs
-{
-	Vnc;
-
-	Vncs	*next;
-	char		remote[NETPATHLEN];
-	char		netpath[NETPATHLEN];
-
-	char		*encname;
-	int		(*countrect)(Vncs*, Rectangle);
-	int		(*sendrect)(Vncs*, Rectangle);
-	int		copyrect;
-	int		canwarp;
-	int		dowarp;
-	Point		warppt;
-
-	ulong		updatereq;
-
-	Rlist		rlist;
-	int		ndead;
-	int		nproc;
-	int		cursorver;
-	Point		cursorpos;
-	Rectangle	cursorr;
-	int		snarfvers;
-
-	Memimage	*image;
-	ulong	imagechan;
-};
-
-/* rre.c */
-int	countcorre(Vncs*, Rectangle);
-int	counthextile(Vncs*, Rectangle);
-int	countraw(Vncs*, Rectangle);
-int	countrre(Vncs*, Rectangle);
-int	sendcorre(Vncs*, Rectangle);
-int	sendhextile(Vncs*, Rectangle);
-int	sendraw(Vncs*, Rectangle);
-int	sendrre(Vncs*, Rectangle);
-
-/* rlist.c */
-void addtorlist(Rlist*, Rectangle);
-void freerlist(Rlist*);
--- a/sys/src/cmd/vnc/vncv.c
+++ /dev/null
@@ -1,205 +1,0 @@
-#include "vnc.h"
-#include "vncv.h"
-#include <libsec.h>
-
-char*		charset = "utf-8";
-char*		encodings = "copyrect hextile corre rre raw mousewarp desktopsize xdesktopsize";
-int		bpp12;
-int		shared;
-int		verbose;
-Vnc*		vnc;
-int		mousefd;
-int		tls;
-
-
-static int	vncstart(Vnc*, int);
-
-enum
-{
-	NProcs	= 4
-};
-
-static int pids[NProcs];
-static char killkin[] = "die vnc kin";
-
-/*
- * called by any proc when exiting to tear everything down.
- */
-static void
-shutdown(void)
-{
-	int i, pid;
-
-	hangup(vnc->ctlfd);
-	close(vnc->ctlfd);
-	vnc->ctlfd = -1;
-	close(vnc->datafd);
-	vnc->datafd = -1;
-
-	pid = getpid();
-	for(i = 0; i < NProcs; i++)
-		if(pids[i] != 0 && pids[i] != pid)
-			postnote(PNPROC, pids[i], killkin);
-}
-
-char*
-netmkvncaddr(char *server)
-{
-	char *p, portstr[NETPATHLEN];
-	int port;
-
-	/* leave execnet dial strings alone */
-	if(strncmp(server, "exec!", 5) == 0)
-		return server;
-
-	port = 5900;
-	if(tls)
-		port = 35729;
-	if((p = strchr(server, ']')) == nil)
-		p = server;
-	if((p = strchr(p, ':')) != nil) {
-		*p++ = '\0';
-		port += atoi(p);
-	}
-	snprint(portstr, sizeof portstr, "%d", port);
-	return netmkaddr(server, "tcp", portstr);
-}
-
-void
-vnchungup(Vnc*)
-{
-	sysfatal("connection closed");
-}
-
-void
-usage(void)
-{
-	fprint(2, "usage: vncv [-e encodings] [-k keypattern] [-l charset] [-csv] host[:n]\n");
-	exits("usage");
-}
-
-void
-main(int argc, char **argv)
-{
-	int p, dfd, cfd, shared;
-	char *keypattern, *label;
-
-	keypattern = nil;
-	shared = 0;
-	ARGBEGIN{
-	case 'c':
-		bpp12 = 1;
-		break;
-	case 'e':
-		encodings = EARGF(usage());
-		break;
-	case 's':
-		shared = 1;
-		break;
-	case 't':
-		tls = 1;
-		break;
-	case 'v':
-		verbose++;
-		break;
-	case 'k':
-		keypattern = EARGF(usage());
-		break;
-	case 'l':
-		charset = EARGF(usage());
-		break;
-	default:
-		usage();
-	}ARGEND;
-
-	if(argc != 1)
-		usage();
-
-	dfd = dial(netmkvncaddr(argv[0]), nil, nil, &cfd);
-	if(dfd < 0)
-		sysfatal("cannot dial %s: %r", argv[0]);
-	if(tls){
-		TLSconn conn;
-
-		memset(&conn, 0, sizeof(conn));
-		if((dfd = tlsClient(dfd, &conn)) < 0)
-			sysfatal("tlsClient: %r");
-		/* XXX check thumbprint */
-		free(conn.cert);
-		free(conn.sessionID);
-	}
-	vnc = vncinit(dfd, cfd, nil);
-	vnc->srvaddr = strdup(argv[0]);
-
-	if(vnchandshake(vnc) < 0)
-		sysfatal("handshake failure: %r");
-	if(vncauth(vnc, keypattern) < 0)
-		sysfatal("authentication failure: %r");
-	if(vncstart(vnc, shared) < 0)
-		sysfatal("init failure: %r");
-
-	label = smprint("vnc %s", argv[0]);
-	if(initdraw(0, 0, label) < 0)
-		sysfatal("initdraw: %r");
-	free(label);
-	display->locking = 1;
-	unlockdisplay(display);
-
-	choosecolor(vnc);
-	sendencodings(vnc);
-	initmouse();
-
-	rfork(RFREND);
-	atexit(shutdown);
-	pids[0] = getpid();
-
-	switch(p = rfork(RFPROC|RFMEM)){
-	case -1:
-		sysfatal("rfork: %r");
-	default:
-		break;
-	case 0:
-		atexit(shutdown);
-		readfromserver(vnc);
-		exits(nil);
-	}
-	pids[1] = p;
-
-	switch(p = rfork(RFPROC|RFMEM)){
-	case -1:
-		sysfatal("rfork: %r");
-	default:
-		break;
-	case 0:
-		atexit(shutdown);
-		checksnarf(vnc);
-		exits(nil);
-	}
-	pids[2] = p;
-
-	switch(p = rfork(RFPROC|RFMEM)){
-	case -1:
-		sysfatal("rfork: %r");
-	default:
-		break;
-	case 0:
-		atexit(shutdown);
-		readkbd(vnc);
-		exits(nil);
-	}
-	pids[3] = p;
-
-	readmouse(vnc);
-	exits(nil);
-}
-
-static int
-vncstart(Vnc *v, int shared)
-{
-	vncwrchar(v, shared);
-	vncflush(v);
-	v->dim = Rpt(ZP, vncrdpoint(v));
-	v->Pixfmt = vncrdpixfmt(v);
-	v->name = vncrdstring(v);
-	return 0;
-}
--- a/sys/src/cmd/vnc/vncv.h
+++ /dev/null
@@ -1,28 +1,0 @@
-/* color.c */
-extern	void		choosecolor(Vnc*);
-extern	void		(*cvtpixels)(uchar*, uchar*, int);
-extern  void            settranslation(Vnc*);
-
-/* draw.c */
-extern	void		sendencodings(Vnc*);
-extern	void		requestupdate(Vnc*, int);
-extern	void		readfromserver(Vnc*);
-
-extern	uchar	zero[];
-
-/* vncv.c */
-extern	char		*charset;
-extern	char		*encodings;
-extern	int		bpp12;
-extern	Vnc*		vnc;
-extern	int		mousefd;
-
-/* wsys.c */
-extern	void		adjustwin(Vnc*, int);
-extern	void		readkbd(Vnc*);
-extern	void		initmouse(void);
-extern	void		mousewarp(Point);
-extern	void		readmouse(Vnc*);
-extern  void            senddim(Vnc*);
-extern  void            writesnarf(Vnc*, long);
-extern  void            checksnarf(Vnc*);
--- a/sys/src/cmd/vnc/wsys.c
+++ /dev/null
@@ -1,323 +1,0 @@
-#include "vnc.h"
-#include "vncv.h"
-#include <cursor.h>
-
-typedef struct Cursor Cursor;
-
-typedef struct Mouse Mouse;
-struct Mouse {
-	int buttons;
-	Point xy;
-};
-
-void
-adjustwin(Vnc *v, int force)
-{
-	int fd;
-	Point d;
-
-	if(force)
-		d = v->dim.max;
-	else {
-		/*
-		 * limit the window to at most the vnc server's size
-		 */
-		d = subpt(screen->r.max, screen->r.min);
-		if(d.x > v->dim.max.x){
-			d.x = v->dim.max.x;
-			force = 1;
-		}
-		if(d.y > v->dim.max.y){
-			d.y = v->dim.max.y;
-			force = 1;
-		}
-	}
-	if(force) {
-		fd = open("/dev/wctl", OWRITE);
-		if(fd >= 0){
-			fprint(fd, "resize -dx %d -dy %d", d.x+2*Borderwidth, d.y+2*Borderwidth);
-			close(fd);
-		}
-	}
-}
-
-static void
-resized(int first)
-{
-	lockdisplay(display);
-	if(getwindow(display, Refnone) < 0)
-		sysfatal("internal error: can't get the window image");
-	if((vnc->canresize&2) == 0)
-		adjustwin(vnc, first);
-	unlockdisplay(display);
-	requestupdate(vnc, 0);
-}
-
-static Cursor dotcursor = {
-	{-7, -7},
-	{0x00, 0x00,
-	 0x00, 0x00,
-	 0x00, 0x00,
-	 0x00, 0x00, 
-	 0x03, 0xc0,
-	 0x07, 0xe0,
-	 0x0f, 0xf0, 
-	 0x0f, 0xf0,
-	 0x0f, 0xf0,
-	 0x07, 0xe0,
-	 0x03, 0xc0,
-	 0x00, 0x00, 
-	 0x00, 0x00,
-	 0x00, 0x00,
-	 0x00, 0x00,
-	 0x00, 0x00, },
-	{0x00, 0x00,
-	 0x00, 0x00,
-	 0x00, 0x00,
-	 0x00, 0x00, 
-	 0x00, 0x00,
-	 0x03, 0xc0,
-	 0x07, 0xe0, 
-	 0x07, 0xe0,
-	 0x07, 0xe0,
-	 0x03, 0xc0,
-	 0x00, 0x00,
-	 0x00, 0x00, 
-	 0x00, 0x00,
-	 0x00, 0x00,
-	 0x00, 0x00,
-	 0x00, 0x00, }
-};
-
-static void
-mouseevent(Vnc *v, Mouse m)
-{
-	vnclock(v);
-	vncwrchar(v, MMouse);
-	vncwrchar(v, m.buttons);
-	vncwrpoint(v, m.xy);
-	vncflush(v);
-	vncunlock(v);
-}
-
-void
-mousewarp(Point pt)
-{
-	pt = addpt(pt, screen->r.min);
-	if(fprint(mousefd, "m%d %d", pt.x, pt.y) < 0)
-		fprint(2, "mousefd write: %r\n");
-}
-
-void
-initmouse(void)
-{
-	char buf[1024];
-
-	snprint(buf, sizeof buf, "%s/mouse", display->devdir);
-	if((mousefd = open(buf, ORDWR)) < 0)
-		sysfatal("open %s: %r", buf);
-}
-
-enum {
-	EventSize = 1+4*12
-};
-void
-readmouse(Vnc *v)
-{
-	int cursorfd, len, n;
-	char buf[10*EventSize], *start, *end;
-	uchar curs[2*4+2*2*16];
-	Cursor *cs;
-	Mouse m;
-
-	cs = &dotcursor;
-
-	snprint(buf, sizeof buf, "%s/cursor", display->devdir);
-	if((cursorfd = open(buf, OWRITE)) < 0)
-		sysfatal("open %s: %r", buf);
-
-	BPLONG(curs+0*4, cs->offset.x);
-	BPLONG(curs+1*4, cs->offset.y);
-	memmove(curs+2*4, cs->clr, 2*2*16);
-	write(cursorfd, curs, sizeof curs);
-
-	resized(1);
-	start = end = buf;
-	len = 0;
-	for(;;){
-		if((n = read(mousefd, end, sizeof(buf) - (end - buf))) < 0)
-			sysfatal("read mouse failed");
-
-		len += n;
-		end += n;
-		while(len >= EventSize){
-			if(*start == 'm'){
-				m.xy.x = atoi(start+1);
-				m.xy.y = atoi(start+1+12);
-				m.buttons = atoi(start+1+2*12) & 0x1F;
-				m.xy = subpt(m.xy, screen->r.min);
-				if(ptinrect(m.xy, v->dim)){
-					mouseevent(v, m);
-					/* send wheel button *release* */ 
-					if ((m.buttons & 0x7) != m.buttons) {
-						m.buttons &= 0x7;
-						mouseevent(v, m);
-					}
-				}
-			} else
-				resized(0);
-			start += EventSize;
-			len -= EventSize;
-		}
-		if(start - buf > sizeof(buf) - EventSize){
-			memmove(buf, start, len);
-			start = buf;
-			end = start+len;
-		}
-	}
-}
-
-static int
-tcs(int fd0, int fd1)
-{
-	int pfd[2];
-
-	if(strcmp(charset, "utf-8") == 0)
-		goto Dup;
-	if(pipe(pfd) < 0)
-		goto Dup;
-	switch(rfork(RFPROC|RFFDG|RFMEM)){
-	case -1:
-		close(pfd[0]);
-		close(pfd[1]);
-		goto Dup;
-	case 0:
-		if(fd0 < 0){
-			dup(pfd[0], 0);
-			dup(fd1, 1);
-			close(fd1);	
-		} else {
-			dup(pfd[0], 1);
-			dup(fd0, 0);
-			close(fd0);	
-		}
-		close(pfd[0]);
-		close(pfd[1]);
-		execl("/bin/tcs", "tcs", fd0 < 0 ? "-f" : "-t", charset, nil);
-		execl("/bin/cat", "cat", nil);
-		_exits(0);
-	}
-	close(pfd[0]);
-	return pfd[1];
-Dup:
-	return dup(fd0 < 0 ? fd1 : fd0, -1);
-}
-
-static int snarffd = -1;
-static ulong snarfvers;
-
-static int
-gotsnarf(void)
-{
-	Dir *dir;
-	int ret;
-
-	if(snarffd < 0 || (dir = dirfstat(snarffd)) == nil)
-		return 0;
-
-	ret = dir->qid.vers != snarfvers;
-	snarfvers = dir->qid.vers;
-	free(dir);
-
-	return ret;
-}
-
-void 
-writesnarf(Vnc *v, long n)
-{
-	uchar buf[8192];
-	int fd, sfd;
-	long m;
-
-	vnclock(v);
-	fd = -1;
-	if((sfd = create("/dev/snarf", OWRITE, 0666)) >= 0){
-		fd = tcs(-1, sfd);
-		close(sfd);
-	}
-	if(fd < 0)
-		vncgobble(v, n);
-	else {
-		while(n > 0){
-			m = n;
-			if(m > sizeof(buf))
-				m = sizeof(buf);
-			vncrdbytes(v, buf, m);
-			n -= m;
-			write(fd, buf, m);
-		}
-		close(fd);
-		waitpid();
-	}
-	gotsnarf();
-	vncunlock(v);
-}
-
-char *
-getsnarf(int *sz)
-{
-	char *snarf, *p;
-	int fd, n, c;
-
-	*sz =0;
-	n = 8192;
-	p = snarf = malloc(n);
-
-	seek(snarffd, 0, 0);
-	if((fd = tcs(snarffd, -1)) >= 0){
-		while((c = read(fd, p, n)) > 0){
-			p += c;
-			n -= c;
-			*sz += c;
-			if (n == 0){
-				snarf = realloc(snarf, *sz + 8192);
-				p = snarf + *sz;
-				n = 8192;
-			}
-		}
-		close(fd);
-		waitpid();
-	}
-	return snarf;
-}
-
-void
-checksnarf(Vnc *v)
-{
-	char *snarf;
-	int len;
-
-	if(snarffd < 0){
-		snarffd = open("/dev/snarf", OREAD);
-		if(snarffd < 0)
-			sysfatal("can't open /dev/snarf: %r");
-	}
-
-	for(;;){
-		sleep(1000);
-
-		vnclock(v);
-		if(gotsnarf()){
-			snarf = getsnarf(&len);
-
-			vncwrchar(v, MCCut);
-			vncwrbytes(v, "pad", 3);
-			vncwrlong(v, len);
-			vncwrbytes(v, snarf, len);
-			vncflush(v);
-
-			free(snarf);
-		}
-		vncunlock(v);
-	}
-}