code: drawterm

Download patch

ref: 6c519f33091bdee3a5c2f65e89510239825f76a8
parent: 972518cb05abadad60bd61a454f743ca72042c47
author: Russ Cox <rsc@swtch.com>
date: Sat Jun 21 23:10:12 EDT 2008

consolidate

--- a/gui-x11/Makefile
+++ b/gui-x11/Makefile
@@ -3,11 +3,7 @@
 LIB=libgui.a
 
 OFILES=\
-	alloc.$O\
-	cload.$O\
-	draw.$O\
-	load.$O\
-	screen.$O\
+	x11.$O\
 	keysym2ucs-x11.$O
 
 default: $(LIB)
--- a/gui-x11/alloc.c
+++ /dev/null
@@ -1,206 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include "xmem.h"
-
-/* perfect approximation to NTSC = .299r+.587g+.114b when 0 ≤ r,g,b < 256 */
-#define RGB2K(r,g,b)	((156763*(r)+307758*(g)+59769*(b))>>19)
-
-Memimage*
-xallocmemimage(Rectangle r, ulong chan, int pmid)
-{
-	Memimage *m;
-	Xmem *xm;
-	XImage *xi;
-	int offset;
-	int d;
-	
-	m = _allocmemimage(r, chan);
-	if(m == nil)
-		return nil;
-	if(chan != GREY1 && chan != xscreenchan)
-		return m;
-
-	d = m->depth;
-	xm = mallocz(sizeof(Xmem), 1);
-	if(pmid != PMundef)
-		xm->pmid = pmid;
-	else
-		xm->pmid = XCreatePixmap(xdisplay, xscreenid, Dx(r), Dy(r), (d==32) ? 24 : d);
-		
-	if(m->depth == 24)
-		offset = r.min.x&(4-1);
-	else
-		offset = r.min.x&(31/m->depth);
-	r.min.x -= offset;
-	
-	assert(wordsperline(r, m->depth) <= m->width);
-
-	xi = XCreateImage(xdisplay, xvis, m->depth==32?24:m->depth, ZPixmap, 0,
-		(char*)m->data->bdata, Dx(r), Dy(r), 32, m->width*sizeof(ulong));
-	
-	if(xi == nil){
-		_freememimage(m);
-		return nil;
-	}
-
-	xm->xi = xi;
-	xm->pc = getcallerpc(&r);
-	xm->r = r;
-	
-	/*
-	 * Set the parameters of the XImage so its memory looks exactly like a
-	 * Memimage, so we can call _memimagedraw on the same data.  All frame
-	 * buffers we've seen, and Plan 9's graphics code, require big-endian
-	 * bits within bytes, but little endian byte order within pixels.
-	 */
-	xi->bitmap_unit = m->depth < 8 || m->depth == 24 ? 8 : m->depth;
-	xi->byte_order = LSBFirst;
-	xi->bitmap_bit_order = MSBFirst;
-	xi->bitmap_pad = 32;
-	xm->r = Rect(0,0,0,0);
-	XInitImage(xi);
-	XFlush(xdisplay);
-
-	m->X = xm;
-	return m;
-}
-
-Memimage*
-allocmemimage(Rectangle r, ulong chan)
-{
-	return xallocmemimage(r, chan, PMundef);
-}
-
-void
-freememimage(Memimage *m)
-{
-	Xmem *xm;
-	
-	if(m == nil)
-		return;
-		
-	if(m->data->ref == 1){
-		if((xm = m->X) != nil){
-			if(xm->xi){
-				xm->xi->data = nil;
-				XFree(xm->xi);
-			}
-			XFreePixmap(xdisplay, xm->pmid);
-			free(xm);
-			m->X = nil;
-		}
-	}
-	_freememimage(m);
-}
-
-void
-memfillcolor(Memimage *m, ulong val)
-{
-	_memfillcolor(m, val);
-	if(m->X){
-		if((val & 0xFF) == 0xFF)
-			xfillcolor(m, m->r, _rgbatoimg(m, val));
-		else
-			putXdata(m, m->r);
-	}
-}
-
-static void
-addrect(Rectangle *rp, Rectangle r)
-{
-	if(rp->min.x >= rp->max.x)
-		*rp = r;
-	else
-		combinerect(rp, r);
-}
-
-XImage*
-getXdata(Memimage *m, Rectangle r)
-{
-	uchar *p;
-	int x, y;
-	Xmem *xm;
-	Point xdelta, delta;
-	Point tp;
-
- 	xm = m->X;
- 	if(xm == nil)
- 		return nil;
- 
-	assert(xm != nil && xm->xi != nil);
-	
- 	if(xm->dirty == 0)
- 		return xm->xi;
- 		
- 	r = xm->dirtyr;
-	if(Dx(r)==0 || Dy(r)==0)
-		return xm->xi;
-
-	delta = subpt(r.min, m->r.min);
-	tp = xm->r.min;	/* avoid unaligned access on digital unix */
-	xdelta = subpt(r.min, tp);
-	
-	XGetSubImage(xdisplay, xm->pmid, delta.x, delta.y, Dx(r), Dy(r),
-		AllPlanes, ZPixmap, xm->xi, xdelta.x, xdelta.y);
-		
-	if(xtblbit && m->chan == CMAP8)
-		for(y=r.min.y; y<r.max.y; y++)
-			for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
-				*p = x11toplan9[*p];
-				
-	xm->dirty = 0;
-	xm->dirtyr = Rect(0,0,0,0);
-	return xm->xi;
-}
-
-void
-putXdata(Memimage *m, Rectangle r)
-{
-	Xmem *xm;
-	XImage *xi;
-	GC g;
-	Point xdelta, delta;
-	Point tp;
-	int x, y;
-	uchar *p;
-
-	xm = m->X;
-	if(xm == nil)
-		return;
-		
-	assert(xm != nil);
-	assert(xm->xi != nil);
-
-	xi = xm->xi;
-
-	g = (m->chan == GREY1) ? xgccopy0 : xgccopy;
-
-	delta = subpt(r.min, m->r.min);
-	tp = xm->r.min;	/* avoid unaligned access on digital unix */
-	xdelta = subpt(r.min, tp);
-	
-	if(xtblbit && m->chan == CMAP8)
-		for(y=r.min.y; y<r.max.y; y++)
-			for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
-				*p = plan9tox11[*p];
-	
-	XPutImage(xdisplay, xm->pmid, g, xi, xdelta.x, xdelta.y, delta.x, delta.y, Dx(r), Dy(r));
-
-	if(xtblbit && m->chan == CMAP8)
-		for(y=r.min.y; y<r.max.y; y++)
-			for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
-				*p = x11toplan9[*p];
-}
-
-void
-dirtyXdata(Memimage *m, Rectangle r)
-{
-	Xmem *xm;
-	
-	if((xm = m->X) != nil){
-		xm->dirty = 1;
-		addrect(&xm->dirtyr, r);
-	}
-}
--- a/gui-x11/cload.c
+++ /dev/null
@@ -1,16 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include "xmem.h"
-
-int
-cloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
-{
-	int n;
-
-	n = _cloadmemimage(i, r, data, ndata);
-	if(n > 0 && i->X)
-		putXdata(i, r);
-	return n;
-}
--- a/gui-x11/draw.c
+++ /dev/null
@@ -1,186 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include "xmem.h"
-
-void xfillcolor(Memimage*, Rectangle, ulong);
-static int xdraw(Memdrawparam*);
-
-int	xgcfillcolor = 0;
-int	xgcfillcolor0 = 0;
-int	xgczeropm = 0;
-int	xgczeropm0 = 0;
-int	xgcsimplecolor = 0;
-int	xgcsimplecolor0 = 0;
-int	xgcsimplepm = 0; 
-int	xgcsimplepm0 = 0;
-int	xgcreplsrctile = 0;
-int	xgcreplsrctile0 = 0;
-
-void
-memimageinit(void)
-{
-	static int didinit = 0;
-	
-	if(didinit)
-		return;
-
-	didinit = 1;
-	_memimageinit();
-	
-	xfillcolor(memblack, memblack->r, 0);
-	xfillcolor(memwhite, memwhite->r, 1);
-}
-
-void
-memimagedraw(Memimage *dst, Rectangle r, Memimage *src, Point sp, Memimage *mask, Point mp, int op)
-{
-	Memdrawparam *par;
-	
-	if((par = _memimagedrawsetup(dst, r, src, sp, mask, mp, op)) == nil)
-		return;
-	_memimagedraw(par);
-	if(!xdraw(par))
-		putXdata(dst, par->r);
-}
-
-void
-xfillcolor(Memimage *m, Rectangle r, ulong v)
-{
-	GC gc;
-	Xmem *dxm;
-
-	dxm = m->X;
-	assert(dxm != nil);
-	r = rectsubpt(r, m->r.min);
-		
-	if(m->chan == GREY1){
-		gc = xgcfill0;
-		if(xgcfillcolor0 != v){
-			XSetForeground(xdisplay, gc, v);
-			xgcfillcolor0 = v;
-		}
-	}else{
-		if(m->chan == CMAP8 && xtblbit)
-			v = plan9tox11[v];
-				
-		gc = xgcfill;
-		if(xgcfillcolor != v){
-			XSetForeground(xdisplay, gc, v);
-			xgcfillcolor = v;
-		}
-	}
-	XFillRectangle(xdisplay, dxm->pmid, gc, r.min.x, r.min.y, Dx(r), Dy(r));
-}
-
-static int
-xdraw(Memdrawparam *par)
-{
-	int dy, dx;
-	unsigned m;
-	Memimage *src, *dst, *mask;
-	Xmem *dxm, *sxm, *mxm;
-	GC gc;
-	Rectangle r, sr, mr;
-	ulong sdval;
-
-	dx = Dx(par->r);
-	dy = Dy(par->r);
-	src = par->src;
-	dst = par->dst;
-	mask = par->mask;
-	r = par->r;
-	sr = par->sr;
-	mr = par->mr;
-	sdval = par->sdval;
-
-return 0;
-	if((dxm = dst->X) == nil)
-		return 0;
-
-	/*
-	 * If we have an opaque mask and source is one opaque pixel we can convert to the
-	 * destination format and just XFillRectangle.
-	 */
-	m = Simplesrc|Simplemask|Fullmask;
-	if((par->state&m)==m){
-		xfillcolor(dst, r, sdval);
-		dirtyXdata(dst, par->r);
-		return 1;
-	}
-
-	/*
-	 * If no source alpha, an opaque mask, we can just copy the
-	 * source onto the destination.  If the channels are the same and
-	 * the source is not replicated, XCopyArea suffices.
-	 */
-	m = Simplemask|Fullmask;
-	if((par->state&(m|Replsrc))==m && src->chan == dst->chan && src->X){
-		sxm = src->X;
-		r = rectsubpt(r, dst->r.min);		
-		sr = rectsubpt(sr, src->r.min);
-		if(dst->chan == GREY1)
-			gc = xgccopy0;
-		else
-			gc = xgccopy;
-		XCopyArea(xdisplay, sxm->pmid, dxm->pmid, gc, 
-			sr.min.x, sr.min.y, dx, dy, r.min.x, r.min.y);
-		dirtyXdata(dst, par->r);
-		return 1;
-	}
-	
-	/*
-	 * If no source alpha, a 1-bit mask, and a simple source
-	 * we can just copy through the mask onto the destination.
-	 */
-	if(dst->X && mask->X && !(mask->flags&Frepl)
-	&& mask->chan == GREY1 && (par->state&Simplesrc)){
-		Point p;
-
-		mxm = mask->X;
-		r = rectsubpt(r, dst->r.min);		
-		mr = rectsubpt(mr, mask->r.min);
-		p = subpt(r.min, mr.min);
-		if(dst->chan == GREY1){
-			gc = xgcsimplesrc0;
-			if(xgcsimplecolor0 != sdval){
-				XSetForeground(xdisplay, gc, sdval);
-				xgcsimplecolor0 = sdval;
-			}
-			if(xgcsimplepm0 != mxm->pmid){
-				XSetStipple(xdisplay, gc, mxm->pmid);
-				xgcsimplepm0 = mxm->pmid;
-			}
-		}else{
-		/* somehow this doesn't work on rob's mac 
-			gc = xgcsimplesrc;
-			if(dst->chan == CMAP8 && xtblbit)
-				sdval = plan9tox11[sdval];
-				
-			if(xgcsimplecolor != sdval){
-				XSetForeground(xdisplay, gc, sdval);
-				xgcsimplecolor = sdval;
-			}
-			if(xgcsimplepm != mxm->pmid){
-				XSetStipple(xdisplay, gc, mxm->pmid);
-				xgcsimplepm = mxm->pmid;
-			}
-		*/
-			return 0;
-		}
-		XSetTSOrigin(xdisplay, gc, p.x, p.y);
-		XFillRectangle(xdisplay, dxm->pmid, gc, r.min.x, r.min.y, dx, dy);
-		dirtyXdata(dst, par->r);
-		return 1;
-	}
-	return 0;
-}
-
-ulong
-pixelbits(Memimage *m, Point p)
-{
-	if(m->X)
-		getXdata(m, Rect(p.x, p.y, p.x+1, p.y+1));
-	return _pixelbits(m, p);
-}
--- a/gui-x11/glenda.xbm
+++ /dev/null
@@ -1,19 +1,0 @@
-#define icon_bitmap_width 48
-#define icon_bitmap_height 48
-static unsigned short icon_bitmap_bits[] = {
-   0xffff, 0xffff, 0xffff, 0xffff, 0xffe9, 0xffff, 0x7fff, 0xffae, 0xffff,
-   0xffff, 0xffbe, 0xffff, 0x1fff, 0xff3f, 0xffff, 0xbfff, 0xfe6e, 0xffff,
-   0xbbff, 0xfcce, 0xffff, 0xffff, 0xf98c, 0xffff, 0xe5ff, 0xf31b, 0xffff,
-   0x87ff, 0xe617, 0xffff, 0x05ff, 0xdf37, 0xffff, 0x0fff, 0x7ffe, 0xffff,
-   0x1bff, 0xfffc, 0xfffa, 0x37ff, 0xfffc, 0xfffb, 0xd7ff, 0xfffc, 0xfff7,
-   0xcfff, 0xffff, 0xfff7, 0xcfff, 0xffff, 0xffef, 0xdfff, 0xffff, 0xffef,
-   0xafff, 0xffff, 0xffdf, 0xefff, 0xffff, 0xfff3, 0xdfff, 0xefff, 0xffd3,
-   0xdfff, 0xc7ff, 0xffdf, 0xefff, 0xefff, 0xffef, 0xcfff, 0xffff, 0xffcf,
-   0xdfff, 0xffff, 0xffd9, 0x9fff, 0x7fff, 0xffd0, 0xbfff, 0xffff, 0xffd7,
-   0x7fff, 0xbfff, 0xffd0, 0x3fff, 0x3fff, 0xffd9, 0x7fff, 0x3fff, 0xffcb,
-   0x3fff, 0xffff, 0xffdc, 0x3fff, 0xffff, 0xffdf, 0x3fff, 0xffff, 0xff9f,
-   0x3fff, 0xffff, 0xffdf, 0x8fff, 0xffff, 0xff9f, 0xa7ff, 0xffff, 0xffdf,
-   0xe3ff, 0xffff, 0xffcf, 0xe9ff, 0xffff, 0xffcf, 0xf1ff, 0xffff, 0xffef,
-   0xf3ff, 0xffff, 0xffe7, 0xf9ff, 0xffff, 0xffe7, 0x53ff, 0xffff, 0xffe1,
-   0x07ff, 0x7ffc, 0xffc6, 0x17ff, 0xeff0, 0xffee, 0xffff, 0xc781, 0xffe5,
-   0xffff, 0x8807, 0xffe0, 0xffff, 0x003f, 0xfff0, 0xffff, 0x1fff, 0xfffe };
--- a/gui-x11/ksym2utf.h
+++ /dev/null
@@ -1,754 +1,0 @@
-static ulong
-ksym2utf[] = {
-	[0x01a1]	0x0104,
-	[0x01a2]	0x02d8,
-	[0x01a3]	0x0141,
-	[0x01a5]	0x013d,
-	[0x01a6]	0x015a,
-	[0x01a9]	0x0160,
-	[0x01aa]	0x015e,
-	[0x01ab]	0x0164,
-	[0x01ac]	0x0179,
-	[0x01ae]	0x017d,
-	[0x01af]	0x017b,
-	[0x01b1]	0x0105,
-	[0x01b2]	0x02db,
-	[0x01b3]	0x0142,
-	[0x01b5]	0x013e,
-	[0x01b6]	0x015b,
-	[0x01b7]	0x02c7,
-	[0x01b9]	0x0161,
-	[0x01ba]	0x015f,
-	[0x01bb]	0x0165,
-	[0x01bc]	0x017a,
-	[0x01bd]	0x02dd,
-	[0x01be]	0x017e,
-	[0x01bf]	0x017c,
-	[0x01c0]	0x0154,
-	[0x01c3]	0x0102,
-	[0x01c5]	0x0139,
-	[0x01c6]	0x0106,
-	[0x01c8]	0x010c,
-	[0x01ca]	0x0118,
-	[0x01cc]	0x011a,
-	[0x01cf]	0x010e,
-	[0x01d0]	0x0110,
-	[0x01d1]	0x0143,
-	[0x01d2]	0x0147,
-	[0x01d5]	0x0150,
-	[0x01d8]	0x0158,
-	[0x01d9]	0x016e,
-	[0x01db]	0x0170,
-	[0x01de]	0x0162,
-	[0x01e0]	0x0155,
-	[0x01e3]	0x0103,
-	[0x01e5]	0x013a,
-	[0x01e6]	0x0107,
-	[0x01e8]	0x010d,
-	[0x01ea]	0x0119,
-	[0x01ec]	0x011b,
-	[0x01ef]	0x010f,
-	[0x01f0]	0x0111,
-	[0x01f1]	0x0144,
-	[0x01f2]	0x0148,
-	[0x01f5]	0x0151,
-	[0x01f8]	0x0159,
-	[0x01f9]	0x016f,
-	[0x01fb]	0x0171,
-	[0x01fe]	0x0163,
-	[0x01ff]	0x02d9,
-	[0x02a1]	0x0126,
-	[0x02a6]	0x0124,
-	[0x02a9]	0x0130,
-	[0x02ab]	0x011e,
-	[0x02ac]	0x0134,
-	[0x02b1]	0x0127,
-	[0x02b6]	0x0125,
-	[0x02b9]	0x0131,
-	[0x02bb]	0x011f,
-	[0x02bc]	0x0135,
-	[0x02c5]	0x010a,
-	[0x02c6]	0x0108,
-	[0x02d5]	0x0120,
-	[0x02d8]	0x011c,
-	[0x02dd]	0x016c,
-	[0x02de]	0x015c,
-	[0x02e5]	0x010b,
-	[0x02e6]	0x0109,
-	[0x02f5]	0x0121,
-	[0x02f8]	0x011d,
-	[0x02fd]	0x016d,
-	[0x02fe]	0x015d,
-	[0x03a2]	0x0138,
-	[0x03a3]	0x0156,
-	[0x03a5]	0x0128,
-	[0x03a6]	0x013b,
-	[0x03aa]	0x0112,
-	[0x03ab]	0x0122,
-	[0x03ac]	0x0166,
-	[0x03b3]	0x0157,
-	[0x03b5]	0x0129,
-	[0x03b6]	0x013c,
-	[0x03ba]	0x0113,
-	[0x03bb]	0x0123,
-	[0x03bc]	0x0167,
-	[0x03bd]	0x014a,
-	[0x03bf]	0x014b,
-	[0x03c0]	0x0100,
-	[0x03c7]	0x012e,
-	[0x03cc]	0x0116,
-	[0x03cf]	0x012a,
-	[0x03d1]	0x0145,
-	[0x03d2]	0x014c,
-	[0x03d3]	0x0136,
-	[0x03d9]	0x0172,
-	[0x03dd]	0x0168,
-	[0x03de]	0x016a,
-	[0x03e0]	0x0101,
-	[0x03e7]	0x012f,
-	[0x03ec]	0x0117,
-	[0x03ef]	0x012b,
-	[0x03f1]	0x0146,
-	[0x03f2]	0x014d,
-	[0x03f3]	0x0137,
-	[0x03f9]	0x0173,
-	[0x03fd]	0x0169,
-	[0x03fe]	0x016b,
-	[0x047e]	0x203e,
-	[0x04a1]	0x3002,
-	[0x04a2]	0x300c,
-	[0x04a3]	0x300d,
-	[0x04a4]	0x3001,
-	[0x04a5]	0x30fb,
-	[0x04a6]	0x30f2,
-	[0x04a7]	0x30a1,
-	[0x04a8]	0x30a3,
-	[0x04a9]	0x30a5,
-	[0x04aa]	0x30a7,
-	[0x04ab]	0x30a9,
-	[0x04ac]	0x30e3,
-	[0x04ad]	0x30e5,
-	[0x04ae]	0x30e7,
-	[0x04af]	0x30c3,
-	[0x04b0]	0x30fc,
-	[0x04b1]	0x30a2,
-	[0x04b2]	0x30a4,
-	[0x04b3]	0x30a6,
-	[0x04b4]	0x30a8,
-	[0x04b5]	0x30aa,
-	[0x04b6]	0x30ab,
-	[0x04b7]	0x30ad,
-	[0x04b8]	0x30af,
-	[0x04b9]	0x30b1,
-	[0x04ba]	0x30b3,
-	[0x04bb]	0x30b5,
-	[0x04bc]	0x30b7,
-	[0x04bd]	0x30b9,
-	[0x04be]	0x30bb,
-	[0x04bf]	0x30bd,
-	[0x04c0]	0x30bf,
-	[0x04c1]	0x30c1,
-	[0x04c2]	0x30c4,
-	[0x04c3]	0x30c6,
-	[0x04c4]	0x30c8,
-	[0x04c5]	0x30ca,
-	[0x04c6]	0x30cb,
-	[0x04c7]	0x30cc,
-	[0x04c8]	0x30cd,
-	[0x04c9]	0x30ce,
-	[0x04ca]	0x30cf,
-	[0x04cb]	0x30d2,
-	[0x04cc]	0x30d5,
-	[0x04cd]	0x30d8,
-	[0x04ce]	0x30db,
-	[0x04cf]	0x30de,
-	[0x04d0]	0x30df,
-	[0x04d1]	0x30e0,
-	[0x04d2]	0x30e1,
-	[0x04d3]	0x30e2,
-	[0x04d4]	0x30e4,
-	[0x04d5]	0x30e6,
-	[0x04d6]	0x30e8,
-	[0x04d7]	0x30e9,
-	[0x04d8]	0x30ea,
-	[0x04d9]	0x30eb,
-	[0x04da]	0x30ec,
-	[0x04db]	0x30ed,
-	[0x04dc]	0x30ef,
-	[0x04dd]	0x30f3,
-	[0x04de]	0x309b,
-	[0x04df]	0x309c,
-	[0x05ac]	0x060c,
-	[0x05bb]	0x061b,
-	[0x05bf]	0x061f,
-	[0x05c1]	0x0621,
-	[0x05c2]	0x0622,
-	[0x05c3]	0x0623,
-	[0x05c4]	0x0624,
-	[0x05c5]	0x0625,
-	[0x05c6]	0x0626,
-	[0x05c7]	0x0627,
-	[0x05c8]	0x0628,
-	[0x05c9]	0x0629,
-	[0x05ca]	0x062a,
-	[0x05cb]	0x062b,
-	[0x05cc]	0x062c,
-	[0x05cd]	0x062d,
-	[0x05ce]	0x062e,
-	[0x05cf]	0x062f,
-	[0x05d0]	0x0630,
-	[0x05d1]	0x0631,
-	[0x05d2]	0x0632,
-	[0x05d3]	0x0633,
-	[0x05d4]	0x0634,
-	[0x05d5]	0x0635,
-	[0x05d6]	0x0636,
-	[0x05d7]	0x0637,
-	[0x05d8]	0x0638,
-	[0x05d9]	0x0639,
-	[0x05da]	0x063a,
-	[0x05e0]	0x0640,
-	[0x05e1]	0x0641,
-	[0x05e2]	0x0642,
-	[0x05e3]	0x0643,
-	[0x05e4]	0x0644,
-	[0x05e5]	0x0645,
-	[0x05e6]	0x0646,
-	[0x05e7]	0x0647,
-	[0x05e8]	0x0648,
-	[0x05e9]	0x0649,
-	[0x05ea]	0x064a,
-	[0x05eb]	0x064b,
-	[0x05ec]	0x064c,
-	[0x05ed]	0x064d,
-	[0x05ee]	0x064e,
-	[0x05ef]	0x064f,
-	[0x05f0]	0x0650,
-	[0x05f1]	0x0651,
-	[0x05f2]	0x0652,
-	[0x06a1]	0x0452,
-	[0x06a2]	0x0453,
-	[0x06a3]	0x0451,
-	[0x06a4]	0x0454,
-	[0x06a5]	0x0455,
-	[0x06a6]	0x0456,
-	[0x06a7]	0x0457,
-	[0x06a8]	0x0458,
-	[0x06a9]	0x0459,
-	[0x06aa]	0x045a,
-	[0x06ab]	0x045b,
-	[0x06ac]	0x045c,
-	[0x06ae]	0x045e,
-	[0x06af]	0x045f,
-	[0x06b0]	0x2116,
-	[0x06b1]	0x0402,
-	[0x06b2]	0x0403,
-	[0x06b3]	0x0401,
-	[0x06b4]	0x0404,
-	[0x06b5]	0x0405,
-	[0x06b6]	0x0406,
-	[0x06b7]	0x0407,
-	[0x06b8]	0x0408,
-	[0x06b9]	0x0409,
-	[0x06ba]	0x040a,
-	[0x06bb]	0x040b,
-	[0x06bc]	0x040c,
-	[0x06be]	0x040e,
-	[0x06bf]	0x040f,
-	[0x06c0]	0x044e,
-	[0x06c1]	0x0430,
-	[0x06c2]	0x0431,
-	[0x06c3]	0x0446,
-	[0x06c4]	0x0434,
-	[0x06c5]	0x0435,
-	[0x06c6]	0x0444,
-	[0x06c7]	0x0433,
-	[0x06c8]	0x0445,
-	[0x06c9]	0x0438,
-	[0x06ca]	0x0439,
-	[0x06cb]	0x043a,
-	[0x06cc]	0x043b,
-	[0x06cd]	0x043c,
-	[0x06ce]	0x043d,
-	[0x06cf]	0x043e,
-	[0x06d0]	0x043f,
-	[0x06d1]	0x044f,
-	[0x06d2]	0x0440,
-	[0x06d3]	0x0441,
-	[0x06d4]	0x0442,
-	[0x06d5]	0x0443,
-	[0x06d6]	0x0436,
-	[0x06d7]	0x0432,
-	[0x06d8]	0x044c,
-	[0x06d9]	0x044b,
-	[0x06da]	0x0437,
-	[0x06db]	0x0448,
-	[0x06dc]	0x044d,
-	[0x06dd]	0x0449,
-	[0x06de]	0x0447,
-	[0x06df]	0x044a,
-	[0x06e0]	0x042e,
-	[0x06e1]	0x0410,
-	[0x06e2]	0x0411,
-	[0x06e3]	0x0426,
-	[0x06e4]	0x0414,
-	[0x06e5]	0x0415,
-	[0x06e6]	0x0424,
-	[0x06e7]	0x0413,
-	[0x06e8]	0x0425,
-	[0x06e9]	0x0418,
-	[0x06ea]	0x0419,
-	[0x06eb]	0x041a,
-	[0x06ec]	0x041b,
-	[0x06ed]	0x041c,
-	[0x06ee]	0x041d,
-	[0x06ef]	0x041e,
-	[0x06f0]	0x041f,
-	[0x06f1]	0x042f,
-	[0x06f2]	0x0420,
-	[0x06f3]	0x0421,
-	[0x06f4]	0x0422,
-	[0x06f5]	0x0423,
-	[0x06f6]	0x0416,
-	[0x06f7]	0x0412,
-	[0x06f8]	0x042c,
-	[0x06f9]	0x042b,
-	[0x06fa]	0x0417,
-	[0x06fb]	0x0428,
-	[0x06fc]	0x042d,
-	[0x06fd]	0x0429,
-	[0x06fe]	0x0427,
-	[0x06ff]	0x042a,
-	[0x07a1]	0x0386,
-	[0x07a2]	0x0388,
-	[0x07a3]	0x0389,
-	[0x07a4]	0x038a,
-	[0x07a5]	0x03aa,
-	[0x07a7]	0x038c,
-	[0x07a8]	0x038e,
-	[0x07a9]	0x03ab,
-	[0x07ab]	0x038f,
-	[0x07ae]	0x0385,
-	[0x07af]	0x2015,
-	[0x07b1]	0x03ac,
-	[0x07b2]	0x03ad,
-	[0x07b3]	0x03ae,
-	[0x07b4]	0x03af,
-	[0x07b5]	0x03ca,
-	[0x07b6]	0x0390,
-	[0x07b7]	0x03cc,
-	[0x07b8]	0x03cd,
-	[0x07b9]	0x03cb,
-	[0x07ba]	0x03b0,
-	[0x07bb]	0x03ce,
-	[0x07c1]	0x0391,
-	[0x07c2]	0x0392,
-	[0x07c3]	0x0393,
-	[0x07c4]	0x0394,
-	[0x07c5]	0x0395,
-	[0x07c6]	0x0396,
-	[0x07c7]	0x0397,
-	[0x07c8]	0x0398,
-	[0x07c9]	0x0399,
-	[0x07ca]	0x039a,
-	[0x07cb]	0x039b,
-	[0x07cc]	0x039c,
-	[0x07cd]	0x039d,
-	[0x07ce]	0x039e,
-	[0x07cf]	0x039f,
-	[0x07d0]	0x03a0,
-	[0x07d1]	0x03a1,
-	[0x07d2]	0x03a3,
-	[0x07d4]	0x03a4,
-	[0x07d5]	0x03a5,
-	[0x07d6]	0x03a6,
-	[0x07d7]	0x03a7,
-	[0x07d8]	0x03a8,
-	[0x07d9]	0x03a9,
-	[0x07e1]	0x03b1,
-	[0x07e2]	0x03b2,
-	[0x07e3]	0x03b3,
-	[0x07e4]	0x03b4,
-	[0x07e5]	0x03b5,
-	[0x07e6]	0x03b6,
-	[0x07e7]	0x03b7,
-	[0x07e8]	0x03b8,
-	[0x07e9]	0x03b9,
-	[0x07ea]	0x03ba,
-	[0x07eb]	0x03bb,
-	[0x07ec]	0x03bc,
-	[0x07ed]	0x03bd,
-	[0x07ee]	0x03be,
-	[0x07ef]	0x03bf,
-	[0x07f0]	0x03c0,
-	[0x07f1]	0x03c1,
-	[0x07f2]	0x03c3,
-	[0x07f3]	0x03c2,
-	[0x07f4]	0x03c4,
-	[0x07f5]	0x03c5,
-	[0x07f6]	0x03c6,
-	[0x07f7]	0x03c7,
-	[0x07f8]	0x03c8,
-	[0x07f9]	0x03c9,
-	[0x08a4]	0x2320,
-	[0x08a5]	0x2321,
-	[0x08a6]	0x2502,
-	[0x08bc]	0x2264,
-	[0x08bd]	0x2260,
-	[0x08be]	0x2265,
-	[0x08bf]	0x222b,
-	[0x08c0]	0x2234,
-	[0x08c1]	0x221d,
-	[0x08c2]	0x221e,
-	[0x08c5]	0x2207,
-	[0x08c8]	0x2245,
-	[0x08cd]	0x21d4,
-	[0x08ce]	0x21d2,
-	[0x08cf]	0x2261,
-	[0x08d6]	0x221a,
-	[0x08da]	0x2282,
-	[0x08db]	0x2283,
-	[0x08dc]	0x2229,
-	[0x08dd]	0x222a,
-	[0x08de]	0x2227,
-	[0x08df]	0x2228,
-	[0x08ef]	0x2202,
-	[0x08f6]	0x0192,
-	[0x08fb]	0x2190,
-	[0x08fc]	0x2191,
-	[0x08fd]	0x2192,
-	[0x08fe]	0x2193,
-	[0x09df]	0x2422,
-	[0x09e0]	0x25c6,
-	[0x09e1]	0x2592,
-	[0x09e2]	0x2409,
-	[0x09e3]	0x240c,
-	[0x09e4]	0x240d,
-	[0x09e5]	0x240a,
-	[0x09e8]	0x2424,
-	[0x09e9]	0x240b,
-	[0x09ea]	0x2518,
-	[0x09eb]	0x2510,
-	[0x09ec]	0x250c,
-	[0x09ed]	0x2514,
-	[0x09ee]	0x253c,
-	[0x09f1]	0x2500,
-	[0x09f4]	0x251c,
-	[0x09f5]	0x2524,
-	[0x09f6]	0x2534,
-	[0x09f7]	0x252c,
-	[0x09f8]	0x2502,
-	[0x0aa1]	0x2003,
-	[0x0aa2]	0x2002,
-	[0x0aa3]	0x2004,
-	[0x0aa4]	0x2005,
-	[0x0aa5]	0x2007,
-	[0x0aa6]	0x2008,
-	[0x0aa7]	0x2009,
-	[0x0aa8]	0x200a,
-	[0x0aa9]	0x2014,
-	[0x0aaa]	0x2013,
-	[0x0aae]	0x2026,
-	[0x0ab0]	0x2153,
-	[0x0ab1]	0x2154,
-	[0x0ab2]	0x2155,
-	[0x0ab3]	0x2156,
-	[0x0ab4]	0x2157,
-	[0x0ab5]	0x2158,
-	[0x0ab6]	0x2159,
-	[0x0ab7]	0x215a,
-	[0x0ab8]	0x2105,
-	[0x0abb]	0x2012,
-	[0x0abc]	0x2329,
-	[0x0abd]	0x002e,
-	[0x0abe]	0x232a,
-	[0x0ac3]	0x215b,
-	[0x0ac4]	0x215c,
-	[0x0ac5]	0x215d,
-	[0x0ac6]	0x215e,
-	[0x0ac9]	0x2122,
-	[0x0aca]	0x2613,
-	[0x0acc]	0x25c1,
-	[0x0acd]	0x25b7,
-	[0x0ace]	0x25cb,
-	[0x0acf]	0x25a1,
-	[0x0ad0]	0x2018,
-	[0x0ad1]	0x2019,
-	[0x0ad2]	0x201c,
-	[0x0ad3]	0x201d,
-	[0x0ad4]	0x211e,
-	[0x0ad6]	0x2032,
-	[0x0ad7]	0x2033,
-	[0x0ad9]	0x271d,
-	[0x0adb]	0x25ac,
-	[0x0adc]	0x25c0,
-	[0x0add]	0x25b6,
-	[0x0ade]	0x25cf,
-	[0x0adf]	0x25a0,
-	[0x0ae0]	0x25e6,
-	[0x0ae1]	0x25ab,
-	[0x0ae2]	0x25ad,
-	[0x0ae3]	0x25b3,
-	[0x0ae4]	0x25bd,
-	[0x0ae5]	0x2606,
-	[0x0ae6]	0x2022,
-	[0x0ae7]	0x25aa,
-	[0x0ae8]	0x25b2,
-	[0x0ae9]	0x25bc,
-	[0x0aea]	0x261c,
-	[0x0aeb]	0x261e,
-	[0x0aec]	0x2663,
-	[0x0aed]	0x2666,
-	[0x0aee]	0x2665,
-	[0x0af0]	0x2720,
-	[0x0af1]	0x2020,
-	[0x0af2]	0x2021,
-	[0x0af3]	0x2713,
-	[0x0af4]	0x2717,
-	[0x0af5]	0x266f,
-	[0x0af6]	0x266d,
-	[0x0af7]	0x2642,
-	[0x0af8]	0x2640,
-	[0x0af9]	0x260e,
-	[0x0afa]	0x2315,
-	[0x0afb]	0x2117,
-	[0x0afc]	0x2038,
-	[0x0afd]	0x201a,
-	[0x0afe]	0x201e,
-	[0x0ba3]	0x003c,
-	[0x0ba6]	0x003e,
-	[0x0ba8]	0x2228,
-	[0x0ba9]	0x2227,
-	[0x0bc0]	0x00af,
-	[0x0bc2]	0x22a4,
-	[0x0bc3]	0x2229,
-	[0x0bc4]	0x230a,
-	[0x0bc6]	0x005f,
-	[0x0bca]	0x2218,
-	[0x0bcc]	0x2395,
-	[0x0bce]	0x22a5,
-	[0x0bcf]	0x25cb,
-	[0x0bd3]	0x2308,
-	[0x0bd6]	0x222a,
-	[0x0bd8]	0x2283,
-	[0x0bda]	0x2282,
-	[0x0bdc]	0x22a3,
-	[0x0bfc]	0x22a2,
-	[0x0cdf]	0x2017,
-	[0x0ce0]	0x05d0,
-	[0x0ce1]	0x05d1,
-	[0x0ce2]	0x05d2,
-	[0x0ce3]	0x05d3,
-	[0x0ce4]	0x05d4,
-	[0x0ce5]	0x05d5,
-	[0x0ce6]	0x05d6,
-	[0x0ce7]	0x05d7,
-	[0x0ce8]	0x05d8,
-	[0x0ce9]	0x05d9,
-	[0x0cea]	0x05da,
-	[0x0ceb]	0x05db,
-	[0x0cec]	0x05dc,
-	[0x0ced]	0x05dd,
-	[0x0cee]	0x05de,
-	[0x0cef]	0x05df,
-	[0x0cf0]	0x05e0,
-	[0x0cf1]	0x05e1,
-	[0x0cf2]	0x05e2,
-	[0x0cf3]	0x05e3,
-	[0x0cf4]	0x05e4,
-	[0x0cf5]	0x05e5,
-	[0x0cf6]	0x05e6,
-	[0x0cf7]	0x05e7,
-	[0x0cf8]	0x05e8,
-	[0x0cf9]	0x05e9,
-	[0x0cfa]	0x05ea,
-	[0x0da1]	0x0e01,
-	[0x0da2]	0x0e02,
-	[0x0da3]	0x0e03,
-	[0x0da4]	0x0e04,
-	[0x0da5]	0x0e05,
-	[0x0da6]	0x0e06,
-	[0x0da7]	0x0e07,
-	[0x0da8]	0x0e08,
-	[0x0da9]	0x0e09,
-	[0x0daa]	0x0e0a,
-	[0x0dab]	0x0e0b,
-	[0x0dac]	0x0e0c,
-	[0x0dad]	0x0e0d,
-	[0x0dae]	0x0e0e,
-	[0x0daf]	0x0e0f,
-	[0x0db0]	0x0e10,
-	[0x0db1]	0x0e11,
-	[0x0db2]	0x0e12,
-	[0x0db3]	0x0e13,
-	[0x0db4]	0x0e14,
-	[0x0db5]	0x0e15,
-	[0x0db6]	0x0e16,
-	[0x0db7]	0x0e17,
-	[0x0db8]	0x0e18,
-	[0x0db9]	0x0e19,
-	[0x0dba]	0x0e1a,
-	[0x0dbb]	0x0e1b,
-	[0x0dbc]	0x0e1c,
-	[0x0dbd]	0x0e1d,
-	[0x0dbe]	0x0e1e,
-	[0x0dbf]	0x0e1f,
-	[0x0dc0]	0x0e20,
-	[0x0dc1]	0x0e21,
-	[0x0dc2]	0x0e22,
-	[0x0dc3]	0x0e23,
-	[0x0dc4]	0x0e24,
-	[0x0dc5]	0x0e25,
-	[0x0dc6]	0x0e26,
-	[0x0dc7]	0x0e27,
-	[0x0dc8]	0x0e28,
-	[0x0dc9]	0x0e29,
-	[0x0dca]	0x0e2a,
-	[0x0dcb]	0x0e2b,
-	[0x0dcc]	0x0e2c,
-	[0x0dcd]	0x0e2d,
-	[0x0dce]	0x0e2e,
-	[0x0dcf]	0x0e2f,
-	[0x0dd0]	0x0e30,
-	[0x0dd1]	0x0e31,
-	[0x0dd2]	0x0e32,
-	[0x0dd3]	0x0e33,
-	[0x0dd4]	0x0e34,
-	[0x0dd5]	0x0e35,
-	[0x0dd6]	0x0e36,
-	[0x0dd7]	0x0e37,
-	[0x0dd8]	0x0e38,
-	[0x0dd9]	0x0e39,
-	[0x0dda]	0x0e3a,
-	[0x0dde]	0x0e3e,
-	[0x0ddf]	0x0e3f,
-	[0x0de0]	0x0e40,
-	[0x0de1]	0x0e41,
-	[0x0de2]	0x0e42,
-	[0x0de3]	0x0e43,
-	[0x0de4]	0x0e44,
-	[0x0de5]	0x0e45,
-	[0x0de6]	0x0e46,
-	[0x0de7]	0x0e47,
-	[0x0de8]	0x0e48,
-	[0x0de9]	0x0e49,
-	[0x0dea]	0x0e4a,
-	[0x0deb]	0x0e4b,
-	[0x0dec]	0x0e4c,
-	[0x0ded]	0x0e4d,
-	[0x0df0]	0x0e50,
-	[0x0df1]	0x0e51,
-	[0x0df2]	0x0e52,
-	[0x0df3]	0x0e53,
-	[0x0df4]	0x0e54,
-	[0x0df5]	0x0e55,
-	[0x0df6]	0x0e56,
-	[0x0df7]	0x0e57,
-	[0x0df8]	0x0e58,
-	[0x0df9]	0x0e59,
-	[0x0ea1]	0x3131,
-	[0x0ea2]	0x3132,
-	[0x0ea3]	0x3133,
-	[0x0ea4]	0x3134,
-	[0x0ea5]	0x3135,
-	[0x0ea6]	0x3136,
-	[0x0ea7]	0x3137,
-	[0x0ea8]	0x3138,
-	[0x0ea9]	0x3139,
-	[0x0eaa]	0x313a,
-	[0x0eab]	0x313b,
-	[0x0eac]	0x313c,
-	[0x0ead]	0x313d,
-	[0x0eae]	0x313e,
-	[0x0eaf]	0x313f,
-	[0x0eb0]	0x3140,
-	[0x0eb1]	0x3141,
-	[0x0eb2]	0x3142,
-	[0x0eb3]	0x3143,
-	[0x0eb4]	0x3144,
-	[0x0eb5]	0x3145,
-	[0x0eb6]	0x3146,
-	[0x0eb7]	0x3147,
-	[0x0eb8]	0x3148,
-	[0x0eb9]	0x3149,
-	[0x0eba]	0x314a,
-	[0x0ebb]	0x314b,
-	[0x0ebc]	0x314c,
-	[0x0ebd]	0x314d,
-	[0x0ebe]	0x314e,
-	[0x0ebf]	0x314f,
-	[0x0ec0]	0x3150,
-	[0x0ec1]	0x3151,
-	[0x0ec2]	0x3152,
-	[0x0ec3]	0x3153,
-	[0x0ec4]	0x3154,
-	[0x0ec5]	0x3155,
-	[0x0ec6]	0x3156,
-	[0x0ec7]	0x3157,
-	[0x0ec8]	0x3158,
-	[0x0ec9]	0x3159,
-	[0x0eca]	0x315a,
-	[0x0ecb]	0x315b,
-	[0x0ecc]	0x315c,
-	[0x0ecd]	0x315d,
-	[0x0ece]	0x315e,
-	[0x0ecf]	0x315f,
-	[0x0ed0]	0x3160,
-	[0x0ed1]	0x3161,
-	[0x0ed2]	0x3162,
-	[0x0ed3]	0x3163,
-	[0x0ed4]	0x11a8,
-	[0x0ed5]	0x11a9,
-	[0x0ed6]	0x11aa,
-	[0x0ed7]	0x11ab,
-	[0x0ed8]	0x11ac,
-	[0x0ed9]	0x11ad,
-	[0x0eda]	0x11ae,
-	[0x0edb]	0x11af,
-	[0x0edc]	0x11b0,
-	[0x0edd]	0x11b1,
-	[0x0ede]	0x11b2,
-	[0x0edf]	0x11b3,
-	[0x0ee0]	0x11b4,
-	[0x0ee1]	0x11b5,
-	[0x0ee2]	0x11b6,
-	[0x0ee3]	0x11b7,
-	[0x0ee4]	0x11b8,
-	[0x0ee5]	0x11b9,
-	[0x0ee6]	0x11ba,
-	[0x0ee7]	0x11bb,
-	[0x0ee8]	0x11bc,
-	[0x0ee9]	0x11bd,
-	[0x0eea]	0x11be,
-	[0x0eeb]	0x11bf,
-	[0x0eec]	0x11c0,
-	[0x0eed]	0x11c1,
-	[0x0eee]	0x11c2,
-	[0x0eef]	0x316d,
-	[0x0ef0]	0x3171,
-	[0x0ef1]	0x3178,
-	[0x0ef2]	0x317f,
-	[0x0ef4]	0x3184,
-	[0x0ef5]	0x3186,
-	[0x0ef6]	0x318d,
-	[0x0ef7]	0x318e,
-	[0x0ef8]	0x11eb,
-	[0x0efa]	0x11f9,
-	[0x0eff]	0x20a9,
-	[0x13bc]	0x0152,
-	[0x13bd]	0x0153,
-	[0x13be]	0x0178,
-	[0x20a0]	0x20a0,
-	[0x20a1]	0x20a1,
-	[0x20a2]	0x20a2,
-	[0x20a3]	0x20a3,
-	[0x20a4]	0x20a4,
-	[0x20a5]	0x20a5,
-	[0x20a6]	0x20a6,
-	[0x20a7]	0x20a7,
-	[0x20a8]	0x20a8,
-	[0x20a9]	0x20a9,
-	[0x20aa]	0x20aa,
-	[0x20ab]	0x20ab,
-	[0x20ac]	0x20ac,
-};
--- a/gui-x11/load.c
+++ /dev/null
@@ -1,16 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include "xmem.h"
-
-int
-loadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
-{
-	int n;
-
-	n = _loadmemimage(i, r, data, ndata);
-	if(n > 0 && i->X)
-		putXdata(i, r);
-	return n;
-}
--- a/gui-x11/screen.c
+++ /dev/null
@@ -1,1190 +1,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <stdio.h>
-
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#include <X11/Xutil.h>
-#include <X11/keysym.h>
-
-#include "keysym2ucs.h"
-#include "glenda.xbm"
-
-/*
- * alias defs for image types to overcome name conflicts
- */
-#define	Point	IPoint
-#define	Rectangle	IRectangle
-#define	Display	IDisplay
-#define	Font	IFont
-#define	Screen	IScreen
-
-#include	"u.h"
-#include	"lib.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"user.h"
-#include	"draw.h"
-#include	"memdraw.h"
-#include	"keyboard.h"
-#include	"screen.h"
-
-#undef time
-#undef Point
-#undef Rectangle
-#undef Display
-#undef Font
-#undef Screen
-
-typedef struct ICursor ICursor;
-struct ICursor
-{
-	int	w;
-	int	h;
-	int	hotx;
-	int	hoty;
-	char	*src;
-	char	*mask;
-};
-
-
-#define ABS(x) ((x) < 0 ? -(x) : (x))
-
-enum
-{
-	DblTime	= 300		/* double click time in msec */
-};
-
-XColor			map[256];	/* Plan 9 colormap array */
-XColor			map7[128];	/* Plan 9 colormap array */
-uchar			map7to8[128][2];
-Colormap		xcmap;		/* Default shared colormap  */
-int 			plan9tox11[256]; /* Values for mapping between */
-int 			x11toplan9[256]; /* X11 and Plan 9 */
-int				x24bitswap = 0;	/* swap endian for 24bit RGB */
-int				xtblbit;
-extern int mousequeue;
-
-/* for copy/paste, lifted from plan9ports */
-Atom clipboard; 
-Atom utf8string;
-Atom targets;
-Atom text;
-Atom compoundtext;
-
-static	Drawable	xdrawable;
-/* static	Atom		wm_take_focus; */
-static	void		xexpose(XEvent*);
-static	void		xmouse(XEvent*);
-static	void		xkeyboard(XEvent*);
-static	void		xmapping(XEvent*);
-static	void		xdestroy(XEvent*);
-static	void		xselect(XEvent*, Display*);
-static	void		xproc(void*);
-static	Memimage*		xinitscreen(void);
-static	void		initmap(Window);
-static	GC		creategc(Drawable);
-static	void		graphicscmap(XColor*);
-	int		xscreendepth;
-	Drawable	xscreenid;
-	Display*	xdisplay;	/* used holding draw lock */
-	Display*	xkmcon;	/* used only in xproc */
-	Display*	xsnarfcon;	/* used holding clip.lk */
-	Visual		*xvis;
-	GC		xgcfill, xgccopy, xgcsimplesrc, xgczero, xgcreplsrc;
-	GC		xgcfill0, xgccopy0, xgcsimplesrc0, xgczero0, xgcreplsrc0;
-	ulong		xblack;
-	ulong		xwhite;
-	ulong	xscreenchan;
-
-static int putsnarf, assertsnarf;
-
-extern Memimage* xallocmemimage(IRectangle, ulong, int);
-Memimage *gscreen;
-Screeninfo screen;
-XImage *ximage;
-
-void
-screeninit(void)
-{
-	_memmkcmap();
-
-	gscreen = xinitscreen();
-	kproc("xscreen", xproc, nil);
-
-	memimageinit();
-	terminit();
-	drawqlock();
-	flushmemscreen(gscreen->r);
-	drawqunlock();
-}
-
-uchar*
-attachscreen(IRectangle *r, ulong *chan, int *depth,
-	int *width, int *softscreen, void **X)
-{
-	*r = gscreen->r;
-	*chan = gscreen->chan;
-	*depth = gscreen->depth;
-	*width = gscreen->width;
-	*X = gscreen->X;
-	*softscreen = 1;
-
-	return gscreen->data->bdata;
-}
-
-void
-flushmemscreen(IRectangle r)
-{
-	assert(!drawcanqlock());
-	if(r.min.x >= r.max.x || r.min.y >= r.max.y)
-		return;
-	XCopyArea(xdisplay, xscreenid, xdrawable, xgccopy, r.min.x, r.min.y, Dx(r), Dy(r), r.min.x, r.min.y);
-	XFlush(xdisplay);
-}
-
-static int
-revbyte(int b)
-{
-	int r;
-
-	r = 0;
-	r |= (b&0x01) << 7;
-	r |= (b&0x02) << 5;
-	r |= (b&0x04) << 3;
-	r |= (b&0x08) << 1;
-	r |= (b&0x10) >> 1;
-	r |= (b&0x20) >> 3;
-	r |= (b&0x40) >> 5;
-	r |= (b&0x80) >> 7;
-	return r;
-}
-
-void
-mouseset(IPoint xy)
-{
-	drawqlock();
-	XWarpPointer(xdisplay, None, xdrawable, 0, 0, 0, 0, xy.x, xy.y);
-	XFlush(xdisplay);
-	drawqunlock();
-}
-
-static Cursor xcursor;
-
-void
-setcursor(void)
-{
-	Cursor xc;
-	XColor fg, bg;
-	Pixmap xsrc, xmask;
-	int i;
-	uchar src[2*16], mask[2*16];
-
-	for(i=0; i<2*16; i++){
-		src[i] = revbyte(cursor.set[i]);
-		mask[i] = revbyte(cursor.set[i] | cursor.clr[i]);
-	}
-
-	drawqlock();
-	fg = map[0];
-	bg = map[255];
-	xsrc = XCreateBitmapFromData(xdisplay, xdrawable, (char*)src, 16, 16);
-	xmask = XCreateBitmapFromData(xdisplay, xdrawable, (char*)mask, 16, 16);
-	xc = XCreatePixmapCursor(xdisplay, xsrc, xmask, &fg, &bg, -cursor.offset.x, -cursor.offset.y);
-	if(xc != 0) {
-		XDefineCursor(xdisplay, xdrawable, xc);
-		if(xcursor != 0)
-			XFreeCursor(xdisplay, xcursor);
-		xcursor = xc;
-	}
-	XFreePixmap(xdisplay, xsrc);
-	XFreePixmap(xdisplay, xmask);
-	XFlush(xdisplay);
-	drawqunlock();
-}
-
-void
-cursorarrow(void)
-{
-	drawqlock();
-	if(xcursor != 0){
-		XFreeCursor(xdisplay, xcursor);
-		xcursor = 0;
-	}
-	XUndefineCursor(xdisplay, xdrawable);
-	XFlush(xdisplay);
-	drawqunlock();
-}
-
-static void
-xproc(void *arg)
-{
-	ulong mask;
-	XEvent event;
-
-	mask = 	KeyPressMask|
-		ButtonPressMask|
-		ButtonReleaseMask|
-		PointerMotionMask|
-		Button1MotionMask|
-		Button2MotionMask|
-		Button3MotionMask|
-		Button4MotionMask|
-		Button5MotionMask|
-		ExposureMask|
-		StructureNotifyMask;
-
-	XSelectInput(xkmcon, xdrawable, mask);
-	for(;;) {
-		//XWindowEvent(xkmcon, xdrawable, mask, &event);
-		XNextEvent(xkmcon, &event);
-		xselect(&event, xkmcon);
-		xkeyboard(&event);
-		xmouse(&event);
-		xexpose(&event);
-		xmapping(&event);
-		xdestroy(&event);
-	}
-}
-
-static int
-shutup(Display *d, XErrorEvent *e)
-{
-	char buf[200];
-	iprint("X error: error code=%d, request_code=%d, minor=%d\n", e->error_code, e->request_code, e->minor_code);
-	XGetErrorText(d, e->error_code, buf, sizeof(buf));
-	iprint("%s\n", buf);
-	USED(d);
-	USED(e);
-	return 0;
-}
-
-static int
-panicshutup(Display *d)
-{
-	panic("x error");
-	return -1;
-}
-
-static Memimage*
-xinitscreen(void)
-{
-	Memimage *gscreen;
-	int i, xsize, ysize, pmid;
-	char *argv[2];
-	char *disp_val;
-	Window rootwin;
-	IRectangle r;
-	XWMHints hints;
-	Screen *screen;
-	XVisualInfo xvi;
-	int rootscreennum;
-	XTextProperty name;
-	XClassHint classhints;
-	XSizeHints normalhints;
-	XSetWindowAttributes attrs;
-	XPixmapFormatValues *pfmt;
-	int n;
- 
-	/* pixmap used to store the icon's image. */
-	Pixmap icon_pixmap;
-
-
-	xscreenid = 0;
-	xdrawable = 0;
-
-	xdisplay = XOpenDisplay(NULL);
-	if(xdisplay == 0){
-		disp_val = getenv("DISPLAY");
-		if(disp_val == 0)
-			disp_val = "not set";
-		iprint("drawterm: open %r, DISPLAY is %s\n", disp_val);
-		exit(0);
-	}
-
-	XSetErrorHandler(shutup);
-	XSetIOErrorHandler(panicshutup);
-	rootscreennum = DefaultScreen(xdisplay);
-	rootwin = DefaultRootWindow(xdisplay);
-	
-	xscreendepth = DefaultDepth(xdisplay, rootscreennum);
-	if(XMatchVisualInfo(xdisplay, rootscreennum, 16, TrueColor, &xvi)
-	|| XMatchVisualInfo(xdisplay, rootscreennum, 16, DirectColor, &xvi)){
-		xvis = xvi.visual;
-		xscreendepth = 16;
-		xtblbit = 1;
-	}
-	else if(XMatchVisualInfo(xdisplay, rootscreennum, 24, TrueColor, &xvi)
-	|| XMatchVisualInfo(xdisplay, rootscreennum, 24, DirectColor, &xvi)){
-		xvis = xvi.visual;
-		xscreendepth = 24;
-		xtblbit = 1;
-	}
-	else if(XMatchVisualInfo(xdisplay, rootscreennum, 8, PseudoColor, &xvi)
-	|| XMatchVisualInfo(xdisplay, rootscreennum, 8, StaticColor, &xvi)){
-		if(xscreendepth > 8)
-			panic("drawterm: can't deal with colormapped depth %d screens\n", xscreendepth);
-		xvis = xvi.visual;
-		xscreendepth = 8;
-	}
-	else{
-		if(xscreendepth != 8)
-			panic("drawterm: can't deal with depth %d screens\n", xscreendepth);
-		xvis = DefaultVisual(xdisplay, rootscreennum);
-	}
-
-	/*
-	 * xscreendepth is only the number of significant pixel bits,
-	 * not the total.  We need to walk the display list to find
-	 * how many actual bits are being used per pixel.
-	 */
-	xscreenchan = 0; /* not a valid channel */
-	pfmt = XListPixmapFormats(xdisplay, &n);
-	for(i=0; i<n; i++){
-		if(pfmt[i].depth == xscreendepth){
-			switch(pfmt[i].bits_per_pixel){
-			case 1:	/* untested */
-				xscreenchan = GREY1;
-				break;
-			case 2:	/* untested */
-				xscreenchan = GREY2;
-				break;
-			case 4:	/* untested */
-				xscreenchan = GREY4;
-				break;
-			case 8:
-				xscreenchan = CMAP8;
-				break;
-			case 16: /* uses 16 rather than 15, empirically. */
-				xscreenchan = RGB16;
-				break;
-			case 24: /* untested (impossible?) */
-				xscreenchan = RGB24;
-				break;
-			case 32:
-				xscreenchan = CHAN4(CIgnore, 8, CRed, 8, CGreen, 8, CBlue, 8);
-				break;
-			}
-		}
-	}
-	if(xscreenchan == 0)
-		panic("drawterm: unknown screen pixel format\n");
-		
-	screen = DefaultScreenOfDisplay(xdisplay);
-	xcmap = DefaultColormapOfScreen(screen);
-
-	if(xvis->class != StaticColor){
-		graphicscmap(map);
-		initmap(rootwin);
-	}
-
-
-	r.min = ZP;
-	r.max.x = WidthOfScreen(screen);
-	r.max.y = HeightOfScreen(screen);
-
-	
-	xsize = Dx(r)*3/4;
-	ysize = Dy(r)*3/4;
-	
-	attrs.colormap = xcmap;
-	attrs.background_pixel = 0;
-	attrs.border_pixel = 0;
-	/* attrs.override_redirect = 1;*/ /* WM leave me alone! |CWOverrideRedirect */
-	xdrawable = XCreateWindow(xdisplay, rootwin, 0, 0, xsize, ysize, 0, 
-		xscreendepth, InputOutput, xvis, CWBackPixel|CWBorderPixel|CWColormap, &attrs);
-
-	/* load the given bitmap data and create an X pixmap containing it. */
-	icon_pixmap = XCreateBitmapFromData(xdisplay,
-		rootwin, (char *)icon_bitmap_bits,
-		icon_bitmap_width, icon_bitmap_height);
-
-	/*
-	 * set up property as required by ICCCM
-	 */
-	name.value = (uchar*)"drawterm";
-	name.encoding = XA_STRING;
-	name.format = 8;
-	name.nitems = strlen((char*)name.value);
-	normalhints.flags = USSize|PMaxSize;
-	normalhints.max_width = Dx(r);
-	normalhints.max_height = Dy(r);
-	normalhints.width = xsize;
-	normalhints.height = ysize;
-	hints.flags = IconPixmapHint |InputHint|StateHint;
-	hints.input = 1;
-	hints.initial_state = NormalState;
-	hints.icon_pixmap = icon_pixmap;
-
-	classhints.res_name = "drawterm";
-	classhints.res_class = "Drawterm";
-	argv[0] = "drawterm";
-	argv[1] = nil;
-	XSetWMProperties(xdisplay, xdrawable,
-		&name,			/* XA_WM_NAME property for ICCCM */
-		&name,			/* XA_WM_ICON_NAME */
-		argv,			/* XA_WM_COMMAND */
-		1,			/* argc */
-		&normalhints,		/* XA_WM_NORMAL_HINTS */
-		&hints,			/* XA_WM_HINTS */
-		&classhints);		/* XA_WM_CLASS */
-	XFlush(xdisplay);
-	
-	/*
-	 * put the window on the screen
-	 */
-	XMapWindow(xdisplay, xdrawable);
-	XFlush(xdisplay);
-
-	xscreenid = XCreatePixmap(xdisplay, xdrawable, Dx(r), Dy(r), xscreendepth);
-	gscreen = xallocmemimage(r, xscreenchan, xscreenid);
-	
-	xgcfill = creategc(xscreenid);
-	XSetFillStyle(xdisplay, xgcfill, FillSolid);
-	xgccopy = creategc(xscreenid);
-	xgcsimplesrc = creategc(xscreenid);
-	XSetFillStyle(xdisplay, xgcsimplesrc, FillStippled);
-	xgczero = creategc(xscreenid);
-	xgcreplsrc = creategc(xscreenid);
-	XSetFillStyle(xdisplay, xgcreplsrc, FillTiled);
-
-	pmid = XCreatePixmap(xdisplay, xdrawable, 1, 1, 1);
-	xgcfill0 = creategc(pmid);
-	XSetForeground(xdisplay, xgcfill0, 0);
-	XSetFillStyle(xdisplay, xgcfill0, FillSolid);
-	xgccopy0 = creategc(pmid);
-	xgcsimplesrc0 = creategc(pmid);
-	XSetFillStyle(xdisplay, xgcsimplesrc0, FillStippled);
-	xgczero0 = creategc(pmid);
-	xgcreplsrc0 = creategc(pmid);
-	XSetFillStyle(xdisplay, xgcreplsrc0, FillTiled);
-	XFreePixmap(xdisplay, pmid);
-
-	XSetForeground(xdisplay, xgccopy, plan9tox11[0]);
-	XFillRectangle(xdisplay, xscreenid, xgccopy, 0, 0, xsize, ysize);
-
-	xkmcon = XOpenDisplay(NULL);
-	if(xkmcon == 0){
-		disp_val = getenv("DISPLAY");
-		if(disp_val == 0)
-			disp_val = "not set";
-		iprint("drawterm: open %r, DISPLAY is %s\n", disp_val);
-		exit(0);
-	}
-	xsnarfcon = XOpenDisplay(NULL);
-	if(xsnarfcon == 0){
-		disp_val = getenv("DISPLAY");
-		if(disp_val == 0)
-			disp_val = "not set";
-		iprint("drawterm: open %r, DISPLAY is %s\n", disp_val);
-		exit(0);
-	}
-
-	clipboard = XInternAtom(xkmcon, "CLIPBOARD", False);
-	utf8string = XInternAtom(xkmcon, "UTF8_STRING", False);
-	targets = XInternAtom(xkmcon, "TARGETS", False);
-	text = XInternAtom(xkmcon, "TEXT", False);
-	compoundtext = XInternAtom(xkmcon, "COMPOUND_TEXT", False);
-
-	xblack = screen->black_pixel;
-	xwhite = screen->white_pixel;
-	return gscreen;
-}
-
-static void
-graphicscmap(XColor *map)
-{
-	int r, g, b, cr, cg, cb, v, num, den, idx, v7, idx7;
-
-	for(r=0; r!=4; r++) {
-		for(g = 0; g != 4; g++) {
-			for(b = 0; b!=4; b++) {
-				for(v = 0; v!=4; v++) {
-					den=r;
-					if(g > den)
-						den=g;
-					if(b > den)
-						den=b;
-					/* divide check -- pick grey shades */
-					if(den==0)
-						cr=cg=cb=v*17;
-					else {
-						num=17*(4*den+v);
-						cr=r*num/den;
-						cg=g*num/den;
-						cb=b*num/den;
-					}
-					idx = r*64 + v*16 + ((g*4 + b + v - r) & 15);
-					map[idx].red = cr*0x0101;
-					map[idx].green = cg*0x0101;
-					map[idx].blue = cb*0x0101;
-					map[idx].pixel = idx;
-					map[idx].flags = DoRed|DoGreen|DoBlue;
-
-					v7 = v >> 1;
-					idx7 = r*32 + v7*16 + g*4 + b;
-					if((v & 1) == v7){
-						map7to8[idx7][0] = idx;
-						if(den == 0) { 		/* divide check -- pick grey shades */
-							cr = ((255.0/7.0)*v7)+0.5;
-							cg = cr;
-							cb = cr;
-						}
-						else {
-							num=17*15*(4*den+v7*2)/14;
-							cr=r*num/den;
-							cg=g*num/den;
-							cb=b*num/den;
-						}
-						map7[idx7].red = cr*0x0101;
-						map7[idx7].green = cg*0x0101;
-						map7[idx7].blue = cb*0x0101;
-						map7[idx7].pixel = idx7;
-						map7[idx7].flags = DoRed|DoGreen|DoBlue;
-					}
-					else
-						map7to8[idx7][1] = idx;
-				}
-			}
-		}
-	}
-}
-
-/*
- * Initialize and install the drawterm colormap as a private colormap for this
- * application.  Drawterm gets the best colors here when it has the cursor focus.
- */  
-static void 
-initmap(Window w)
-{
-	XColor c;
-	int i;
-	ulong p, pp;
-	char buf[30];
-
-	if(xscreendepth <= 1)
-		return;
-
-	if(xscreendepth >= 24) {
-		/* The pixel value returned from XGetPixel needs to
-		 * be converted to RGB so we can call rgb2cmap()
-		 * to translate between 24 bit X and our color. Unfortunately,
-		 * the return value appears to be display server endian 
-		 * dependant. Therefore, we run some heuristics to later
-		 * determine how to mask the int value correctly.
-		 * Yeah, I know we can look at xvis->byte_order but 
-		 * some displays say MSB even though they run on LSB.
-		 * Besides, this is more anal.
-		 */
-		if(xscreendepth != DefaultDepth(xdisplay, DefaultScreen(xdisplay)))
-			xcmap = XCreateColormap(xdisplay, w, xvis, AllocNone);
-
-		c = map[19];
-		/* find out index into colormap for our RGB */
-		if(!XAllocColor(xdisplay, xcmap, &c))
-			panic("drawterm: screen-x11 can't alloc color");
-
-		p  = c.pixel;
-		pp = rgb2cmap((p>>16)&0xff,(p>>8)&0xff,p&0xff);
-		if(pp!=map[19].pixel) {
-			/* check if endian is other way */
-			pp = rgb2cmap(p&0xff,(p>>8)&0xff,(p>>16)&0xff);
-			if(pp!=map[19].pixel)
-				panic("cannot detect x server byte order");
-			switch(xscreenchan){
-			case RGB24:
-				xscreenchan = BGR24;
-				break;
-			case XRGB32:
-				xscreenchan = XBGR32;
-				break;
-			default:
-				panic("don't know how to byteswap channel %s", 
-					chantostr(buf, xscreenchan));
-				break;
-			}
-		}
-	} else if(xvis->class == TrueColor || xvis->class == DirectColor) {
-	} else if(xvis->class == PseudoColor) {
-		if(xtblbit == 0){
-			xcmap = XCreateColormap(xdisplay, w, xvis, AllocAll); 
-			XStoreColors(xdisplay, xcmap, map, 256);
-			for(i = 0; i < 256; i++) {
-				plan9tox11[i] = i;
-				x11toplan9[i] = i;
-			}
-		}
-		else {
-			for(i = 0; i < 128; i++) {
-				c = map7[i];
-				if(!XAllocColor(xdisplay, xcmap, &c)) {
-					iprint("drawterm: can't alloc colors in default map, don't use -7\n");
-					exit(0);
-				}
-				plan9tox11[map7to8[i][0]] = c.pixel;
-				plan9tox11[map7to8[i][1]] = c.pixel;
-				x11toplan9[c.pixel] = map7to8[i][0];
-			}
-		}
-	}
-	else
-		panic("drawterm: unsupported visual class %d\n", xvis->class);
-}
-
-static void
-xdestroy(XEvent *e)
-{
-	XDestroyWindowEvent *xe;
-	if(e->type != DestroyNotify)
-		return;
-	xe = (XDestroyWindowEvent*)e;
-	if(xe->window == xdrawable)
-		exit(0);
-}
-
-static void
-xmapping(XEvent *e)
-{
-	XMappingEvent *xe;
-
-	if(e->type != MappingNotify)
-		return;
-	xe = (XMappingEvent*)e;
-	USED(xe);
-}
-
-
-/*
- * Disable generation of GraphicsExpose/NoExpose events in the GC.
- */
-static GC
-creategc(Drawable d)
-{
-	XGCValues gcv;
-
-	gcv.function = GXcopy;
-	gcv.graphics_exposures = False;
-	return XCreateGC(xdisplay, d, GCFunction|GCGraphicsExposures, &gcv);
-}
-
-static void
-xexpose(XEvent *e)
-{
-	IRectangle r;
-	XExposeEvent *xe;
-
-	if(e->type != Expose)
-		return;
-	xe = (XExposeEvent*)e;
-	r.min.x = xe->x;
-	r.min.y = xe->y;
-	r.max.x = xe->x + xe->width;
-	r.max.y = xe->y + xe->height;
-	drawflushr(r);
-}
-
-static void
-xkeyboard(XEvent *e)
-{
-	KeySym k;
-
-	/*
-	 * I tried using XtGetActionKeysym, but it didn't seem to
-	 * do case conversion properly
-	 * (at least, with Xterminal servers and R4 intrinsics)
-	 */
-	if(e->xany.type != KeyPress)
-		return;
-
-
-	XLookupString((XKeyEvent*)e, NULL, 0, &k, NULL);
-
-	if(k == XK_Multi_key || k == NoSymbol)
-		return;
-	if(k&0xFF00){
-		switch(k){
-		case XK_BackSpace:
-		case XK_Tab:
-		case XK_Escape:
-		case XK_Delete:
-		case XK_KP_0:
-		case XK_KP_1:
-		case XK_KP_2:
-		case XK_KP_3:
-		case XK_KP_4:
-		case XK_KP_5:
-		case XK_KP_6:
-		case XK_KP_7:
-		case XK_KP_8:
-		case XK_KP_9:
-		case XK_KP_Divide:
-		case XK_KP_Multiply:
-		case XK_KP_Subtract:
-		case XK_KP_Add:
-		case XK_KP_Decimal:
-			k &= 0x7F;
-			break;
-		case XK_Linefeed:
-			k = '\r';
-			break;
-		case XK_KP_Space:
-			k = ' ';
-			break;
-		case XK_Home:
-		case XK_KP_Home:
-			k = Khome;
-			break;
-		case XK_Left:
-		case XK_KP_Left:
-			k = Kleft;
-			break;
-		case XK_Up:
-		case XK_KP_Up:
-			k = Kup;
-			break;
-		case XK_Down:
-		case XK_KP_Down:
-			k = Kdown;
-			break;
-		case XK_Right:
-		case XK_KP_Right:
-			k = Kright;
-			break;
-		case XK_Page_Down:
-		case XK_KP_Page_Down:
-			k = Kpgdown;
-			break;
-		case XK_End:
-		case XK_KP_End:
-			k = Kend;
-			break;
-		case XK_Page_Up:	
-		case XK_KP_Page_Up:
-			k = Kpgup;
-			break;
-		case XK_Insert:
-		case XK_KP_Insert:
-			k = Kins;
-			break;
-		case XK_KP_Enter:
-		case XK_Return:
-			k = '\n';
-			break;
-		case XK_Alt_L:
-		case XK_Alt_R:
-			k = Kalt;
-			break;
-		case XK_Shift_L:
-		case XK_Shift_R:
-		case XK_Control_L:
-		case XK_Control_R:
-		case XK_Caps_Lock:
-		case XK_Shift_Lock:
-
-		case XK_Meta_L:
-		case XK_Meta_R:
-		case XK_Super_L:
-		case XK_Super_R:
-		case XK_Hyper_L:
-		case XK_Hyper_R:
-			return;
-		default:		/* not ISO-1 or tty control */
-  			if(k>0xff){
-				k = keysym2ucs(k); /* supplied by X */
-				if(k == -1)
-					return;
-			}
-			break;
-		}
-	}
-
-	/* Compensate for servers that call a minus a hyphen */
-	if(k == XK_hyphen)
-		k = XK_minus;
-	/* Do control mapping ourselves if translator doesn't */
-	if(e->xkey.state&ControlMask)
-		k &= 0x9f;
-	if(k == NoSymbol) {
-		return;
-	}
-
-	kbdputc(kbdq, k);
-}
-
-static void
-xmouse(XEvent *e)
-{
-	Mousestate ms;
-	int i, s;
-	XButtonEvent *be;
-	XMotionEvent *me;
-
-	if(putsnarf != assertsnarf){
-		assertsnarf = putsnarf;
-		XSetSelectionOwner(xkmcon, XA_PRIMARY, xdrawable, CurrentTime);
-		if(clipboard != None)
-			XSetSelectionOwner(xkmcon, clipboard, xdrawable, CurrentTime);
-		XFlush(xkmcon);
-	}
-
-	switch(e->type){
-	case ButtonPress:
-		be = (XButtonEvent *)e;
-		/* 
-		 * Fake message, just sent to make us announce snarf.
-		 * Apparently state and button are 16 and 8 bits on
-		 * the wire, since they are truncated by the time they
-		 * get to us.
-		 */
-		if(be->send_event
-		&& (~be->state&0xFFFF)==0
-		&& (~be->button&0xFF)==0)
-			return;
-		ms.xy.x = be->x;
-		ms.xy.y = be->y;
-		s = be->state;
-		ms.msec = be->time;
-		switch(be->button){
-		case 1:
-			s |= Button1Mask;
-			break;
-		case 2:
-			s |= Button2Mask;
-			break;
-		case 3:
-			s |= Button3Mask;
-			break;
-		case 4:
-			s |= Button4Mask;
-			break;
-		case 5:
-			s |= Button5Mask;
-			break;
-		}
-		break;
-	case ButtonRelease:
-		be = (XButtonEvent *)e;
-		ms.xy.x = be->x;
-		ms.xy.y = be->y;
-		ms.msec = be->time;
-		s = be->state;
-		switch(be->button){
-		case 1:
-			s &= ~Button1Mask;
-			break;
-		case 2:
-			s &= ~Button2Mask;
-			break;
-		case 3:
-			s &= ~Button3Mask;
-			break;
-		case 4:
-			s &= ~Button4Mask;
-			break;
-		case 5:
-			s &= ~Button5Mask;
-			break;
-		}
-		break;
-	case MotionNotify:
-		me = (XMotionEvent *)e;
-		s = me->state;
-		ms.xy.x = me->x;
-		ms.xy.y = me->y;
-		ms.msec = me->time;
-		break;
-	default:
-		return;
-	}
-
-	ms.buttons = 0;
-	if(s & Button1Mask)
-		ms.buttons |= 1;
-	if(s & Button2Mask)
-		ms.buttons |= 2;
-	if(s & Button3Mask)
-		ms.buttons |= 4;
-	if(s & Button4Mask)
-		ms.buttons |= 8;
-	if(s & Button5Mask)
-		ms.buttons |= 16;
-
-	lock(&mouse.lk);
-	i = mouse.wi;
-	if(mousequeue) {
-		if(i == mouse.ri || mouse.lastb != ms.buttons || mouse.trans) {
-			mouse.wi = (i+1)%Mousequeue;
-			if(mouse.wi == mouse.ri)
-				mouse.ri = (mouse.ri+1)%Mousequeue;
-			mouse.trans = mouse.lastb != ms.buttons;
-		} else {
-			i = (i-1+Mousequeue)%Mousequeue;
-		}
-	} else {
-		mouse.wi = (i+1)%Mousequeue;
-		mouse.ri = i;
-	}
-	mouse.queue[i] = ms;
-	mouse.lastb = ms.buttons;
-	unlock(&mouse.lk);
-	wakeup(&mouse.r);
-}
-
-void
-getcolor(ulong i, ulong *r, ulong *g, ulong *b)
-{
-	ulong v;
-	
-	v = cmap2rgb(i);
-	*r = (v>>16)&0xFF;
-	*g = (v>>8)&0xFF;
-	*b = v&0xFF;
-}
-
-void
-setcolor(ulong i, ulong r, ulong g, ulong b)
-{
-	/* no-op */
-}
-
-int
-atlocalconsole(void)
-{
-	char *p, *q;
-	char buf[128];
-
-	p = getenv("DRAWTERM_ATLOCALCONSOLE");
-	if(p && atoi(p) == 1)
-		return 1;
-
-	p = getenv("DISPLAY");
-	if(p == nil)
-		return 0;
-
-	/* extract host part */
-	q = strchr(p, ':');
-	if(q == nil)
-		return 0;
-	*q = 0;
-
-	if(strcmp(p, "") == 0)
-		return 1;
-
-	/* try to match against system name (i.e. for ssh) */
-	if(gethostname(buf, sizeof buf) == 0){
-		if(strcmp(p, buf) == 0)
-			return 1;
-		if(strncmp(p, buf, strlen(p)) == 0 && buf[strlen(p)]=='.')
-			return 1;
-	}
-
-	return 0;
-}
-
-/*
- * Cut and paste.  Just couldn't stand to make this simple...
- */
-
-typedef struct Clip Clip;
-struct Clip
-{
-	char buf[SnarfSize];
-	QLock lk;
-};
-Clip clip;
-
-#undef long	/* sic */
-#undef ulong
-
-static char*
-_xgetsnarf(Display *xd)
-{
-	uchar *data, *xdata;
-	Atom clipboard, type, prop;
-	unsigned long len, lastlen, dummy;
-	int fmt, i;
-	Window w;
-
-	qlock(&clip.lk);
-	/*
-	 * Have we snarfed recently and the X server hasn't caught up?
-	 */
-	if(putsnarf != assertsnarf)
-		goto mine;
-
-	/*
-	 * Is there a primary selection (highlighted text in an xterm)?
-	 */
-	clipboard = XA_PRIMARY;
-	w = XGetSelectionOwner(xd, XA_PRIMARY);
-	if(w == xdrawable){
-	mine:
-		data = (uchar*)strdup(clip.buf);
-		goto out;
-	}
-
-	/*
-	 * If not, is there a clipboard selection?
-	 */
-	if(w == None && clipboard != None){
-		clipboard = clipboard;
-		w = XGetSelectionOwner(xd, clipboard);
-		if(w == xdrawable)
-			goto mine;
-	}
-
-	/*
-	 * If not, give up.
-	 */
-	if(w == None){
-		data = nil;
-		goto out;
-	}
-		
-	/*
-	 * We should be waiting for SelectionNotify here, but it might never
-	 * come, and we have no way to time out.  Instead, we will clear
-	 * local property #1, request our buddy to fill it in for us, and poll
-	 * until he's done or we get tired of waiting.
-	 *
-	 * We should try to go for utf8string instead of XA_STRING,
-	 * but that would add to the polling.
-	 */
-	prop = 1;
-	XChangeProperty(xd, xdrawable, prop, XA_STRING, 8, PropModeReplace, (uchar*)"", 0);
-	XConvertSelection(xd, clipboard, XA_STRING, prop, xdrawable, CurrentTime);
-	XFlush(xd);
-	lastlen = 0;
-	for(i=0; i<10 || (lastlen!=0 && i<30); i++){
-		usleep(100*1000);
-		XGetWindowProperty(xd, xdrawable, prop, 0, 0, 0, AnyPropertyType,
-			&type, &fmt, &dummy, &len, &data);
-		if(lastlen == len && len > 0)
-			break;
-		lastlen = len;
-	}
-	if(i == 10){
-		data = nil;
-		goto out;
-	}
-	/* get the property */
-	data = nil;
-	XGetWindowProperty(xd, xdrawable, prop, 0, SnarfSize/sizeof(unsigned long), 0, 
-		AnyPropertyType, &type, &fmt, &len, &dummy, &xdata);
-	if((type != XA_STRING && type != utf8string) || len == 0){
-		if(xdata)
-			XFree(xdata);
-		data = nil;
-	}else{
-		if(xdata){
-			data = (uchar*)strdup((char*)xdata);
-			XFree(xdata);
-		}else
-			data = nil;
-	}
-out:
-	qunlock(&clip.lk);
-	return (char*)data;
-}
-
-static void
-_xputsnarf(Display *xd, char *data)
-{
-	XButtonEvent e;
-
-	if(strlen(data) >= SnarfSize)
-		return;
-	qlock(&clip.lk);
-	strcpy(clip.buf, data);
-
-	/* leave note for mouse proc to assert selection ownership */
-	putsnarf++;
-
-	/* send mouse a fake event so snarf is announced */
-	memset(&e, 0, sizeof e);
-	e.type = ButtonPress;
-	e.window = xdrawable;
-	e.state = ~0;
-	e.button = ~0;
-	XSendEvent(xd, xdrawable, True, ButtonPressMask, (XEvent*)&e);
-	XFlush(xd);
-	qunlock(&clip.lk);
-}
-
-static void
-xselect(XEvent *e, Display *xd)
-{
-	char *name;
-	XEvent r;
-	XSelectionRequestEvent *xe;
-	Atom a[4];
-
-	if(e->xany.type != SelectionRequest)
-		return;
-
-	memset(&r, 0, sizeof r);
-	xe = (XSelectionRequestEvent*)e;
-if(0) iprint("xselect target=%d requestor=%d property=%d selection=%d\n",
-	xe->target, xe->requestor, xe->property, xe->selection);
-	r.xselection.property = xe->property;
-	if(xe->target == targets){
-		a[0] = XA_STRING;
-		a[1] = utf8string;
-		a[2] = text;
-		a[3] = compoundtext;
-
-		XChangeProperty(xd, xe->requestor, xe->property, xe->target,
-			8, PropModeReplace, (uchar*)a, sizeof a);
-	}else if(xe->target == XA_STRING || xe->target == utf8string || xe->target == text || xe->target == compoundtext){
-	text:
-		/* if the target is STRING we're supposed to reply with Latin1 XXX */
-		qlock(&clip.lk);
-		XChangeProperty(xd, xe->requestor, xe->property, xe->target,
-			8, PropModeReplace, (uchar*)clip.buf, strlen(clip.buf));
-		qunlock(&clip.lk);
-	}else{
-		name = XGetAtomName(xd, xe->target);
-		if(name == nil)
-			iprint("XGetAtomName %d failed\n", xe->target);
-		if(name){
-			if(strcmp(name, "TIMESTAMP") == 0){
-				/* nothing */
-			}else if(strncmp(name, "image/", 6) == 0){
-				/* nothing */
-			}else if(strcmp(name, "text/html") == 0){
-				/* nothing */
-			}else if(strcmp(name, "text/plain") == 0 || strcmp(name, "text/plain;charset=UTF-8") == 0){
-				goto text;
-			}else
-				iprint("%s: cannot handle selection request for '%s' (%d)\n", argv0, name, (int)xe->target);
-		}
-		r.xselection.property = None;
-	}
-
-	r.xselection.display = xe->display;
-	/* r.xselection.property filled above */
-	r.xselection.target = xe->target;
-	r.xselection.type = SelectionNotify;
-	r.xselection.requestor = xe->requestor;
-	r.xselection.time = xe->time;
-	r.xselection.send_event = True;
-	r.xselection.selection = xe->selection;
-	XSendEvent(xd, xe->requestor, False, 0, &r);
-	XFlush(xd);
-}
-
-char*
-clipread(void)
-{
-	return _xgetsnarf(xsnarfcon);
-}
-
-int
-clipwrite(char *buf)
-{
-	_xputsnarf(xsnarfcon, buf);
-	return 0;
-}
-
--- /dev/null
+++ b/gui-x11/x11.c
@@ -1,0 +1,1611 @@
+#include "u.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+
+#include <draw.h>
+#include <memdraw.h>
+#include <keyboard.h>
+#include <cursor.h>
+#include "screen.h"
+
+#define argv0 "drawterm"
+
+typedef struct Cursor Cursor;
+
+#define	Font		XFont
+#define	Screen	XScreen
+#define	Display	XDisplay
+#define	Cursor	XCursor
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/keysym.h>
+#include "keysym2ucs.h"
+
+#undef	Font
+#undef	Screen
+#undef	Display
+#undef	Cursor
+
+/* perfect approximation to NTSC = .299r+.587g+.114b when 0 ≤ r,g,b < 256 */
+#define RGB2K(r,g,b)	((156763*(r)+307758*(g)+59769*(b))>>19)
+
+enum
+{
+	PMundef	= ~0		/* undefined pixmap id */
+};
+
+/*
+ * Structure pointed to by X field of Memimage
+ */
+typedef struct Xmem Xmem;
+struct Xmem
+{
+	int	pmid;	/* pixmap id for screen ldepth instance */
+	XImage *xi;	/* local image if we currenty have the data */
+	int	dirty;
+	Rectangle dirtyr;
+	Rectangle r;
+	uintptr pc;	/* who wrote into xi */
+};
+
+static int	xgcfillcolor;
+static int	xgcfillcolor0;
+static int	xgcsimplecolor0;
+static int	xgcsimplepm0;
+
+static	XDisplay*	xdisplay;	/* used holding draw lock */
+static int				xtblbit;
+static int 			plan9tox11[256]; /* Values for mapping between */
+static int 			x11toplan9[256]; /* X11 and Plan 9 */
+static	GC		xgcfill, xgccopy, xgcsimplesrc, xgczero, xgcreplsrc;
+static	GC		xgcfill0, xgccopy0, xgcsimplesrc0, xgczero0, xgcreplsrc0;
+static	ulong	xscreenchan;
+static	Drawable	xscreenid;
+static	Visual		*xvis;
+
+static int xdraw(Memdrawparam*);
+
+#define glenda_width 48
+#define glenda_height 48
+static unsigned short glenda_bits[] = {
+   0xffff, 0xffff, 0xffff, 0xffff, 0xffe9, 0xffff, 0x7fff, 0xffae, 0xffff,
+   0xffff, 0xffbe, 0xffff, 0x1fff, 0xff3f, 0xffff, 0xbfff, 0xfe6e, 0xffff,
+   0xbbff, 0xfcce, 0xffff, 0xffff, 0xf98c, 0xffff, 0xe5ff, 0xf31b, 0xffff,
+   0x87ff, 0xe617, 0xffff, 0x05ff, 0xdf37, 0xffff, 0x0fff, 0x7ffe, 0xffff,
+   0x1bff, 0xfffc, 0xfffa, 0x37ff, 0xfffc, 0xfffb, 0xd7ff, 0xfffc, 0xfff7,
+   0xcfff, 0xffff, 0xfff7, 0xcfff, 0xffff, 0xffef, 0xdfff, 0xffff, 0xffef,
+   0xafff, 0xffff, 0xffdf, 0xefff, 0xffff, 0xfff3, 0xdfff, 0xefff, 0xffd3,
+   0xdfff, 0xc7ff, 0xffdf, 0xefff, 0xefff, 0xffef, 0xcfff, 0xffff, 0xffcf,
+   0xdfff, 0xffff, 0xffd9, 0x9fff, 0x7fff, 0xffd0, 0xbfff, 0xffff, 0xffd7,
+   0x7fff, 0xbfff, 0xffd0, 0x3fff, 0x3fff, 0xffd9, 0x7fff, 0x3fff, 0xffcb,
+   0x3fff, 0xffff, 0xffdc, 0x3fff, 0xffff, 0xffdf, 0x3fff, 0xffff, 0xff9f,
+   0x3fff, 0xffff, 0xffdf, 0x8fff, 0xffff, 0xff9f, 0xa7ff, 0xffff, 0xffdf,
+   0xe3ff, 0xffff, 0xffcf, 0xe9ff, 0xffff, 0xffcf, 0xf1ff, 0xffff, 0xffef,
+   0xf3ff, 0xffff, 0xffe7, 0xf9ff, 0xffff, 0xffe7, 0x53ff, 0xffff, 0xffe1,
+   0x07ff, 0x7ffc, 0xffc6, 0x17ff, 0xeff0, 0xffee, 0xffff, 0xc781, 0xffe5,
+   0xffff, 0x8807, 0xffe0, 0xffff, 0x003f, 0xfff0, 0xffff, 0x1fff, 0xfffe
+};
+
+/*
+ * Synchronize images between X bitmaps and in-memory bitmaps.
+ */
+static void
+addrect(Rectangle *rp, Rectangle r)
+{
+	if(rp->min.x >= rp->max.x)
+		*rp = r;
+	else
+		combinerect(rp, r);
+}
+
+static XImage*
+getXdata(Memimage *m, Rectangle r)
+{
+	uchar *p;
+	int x, y;
+	Xmem *xm;
+	Point xdelta, delta;
+	Point tp;
+
+ 	xm = m->X;
+ 	if(xm == nil)
+ 		return nil;
+ 
+	assert(xm != nil && xm->xi != nil);
+	
+ 	if(xm->dirty == 0)
+ 		return xm->xi;
+ 		
+ 	r = xm->dirtyr;
+	if(Dx(r)==0 || Dy(r)==0)
+		return xm->xi;
+
+	delta = subpt(r.min, m->r.min);
+	tp = xm->r.min;	/* avoid unaligned access on digital unix */
+	xdelta = subpt(r.min, tp);
+	
+	XGetSubImage(xdisplay, xm->pmid, delta.x, delta.y, Dx(r), Dy(r),
+		AllPlanes, ZPixmap, xm->xi, xdelta.x, xdelta.y);
+		
+	if(xtblbit && m->chan == CMAP8)
+		for(y=r.min.y; y<r.max.y; y++)
+			for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
+				*p = x11toplan9[*p];
+				
+	xm->dirty = 0;
+	xm->dirtyr = Rect(0,0,0,0);
+	return xm->xi;
+}
+
+static void
+putXdata(Memimage *m, Rectangle r)
+{
+	Xmem *xm;
+	XImage *xi;
+	GC g;
+	Point xdelta, delta;
+	Point tp;
+	int x, y;
+	uchar *p;
+
+	xm = m->X;
+	if(xm == nil)
+		return;
+		
+	assert(xm != nil);
+	assert(xm->xi != nil);
+
+	xi = xm->xi;
+
+	g = (m->chan == GREY1) ? xgccopy0 : xgccopy;
+
+	delta = subpt(r.min, m->r.min);
+	tp = xm->r.min;	/* avoid unaligned access on digital unix */
+	xdelta = subpt(r.min, tp);
+	
+	if(xtblbit && m->chan == CMAP8)
+		for(y=r.min.y; y<r.max.y; y++)
+			for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
+				*p = plan9tox11[*p];
+	
+	XPutImage(xdisplay, xm->pmid, g, xi, xdelta.x, xdelta.y, delta.x, delta.y, Dx(r), Dy(r));
+
+	if(xtblbit && m->chan == CMAP8)
+		for(y=r.min.y; y<r.max.y; y++)
+			for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
+				*p = x11toplan9[*p];
+}
+
+static void
+dirtyXdata(Memimage *m, Rectangle r)
+{
+	Xmem *xm;
+	
+	if((xm = m->X) != nil){
+		xm->dirty = 1;
+		addrect(&xm->dirtyr, r);
+	}
+}
+
+Memimage*
+xallocmemimage(Rectangle r, ulong chan, int pmid)
+{
+	Memimage *m;
+	Xmem *xm;
+	XImage *xi;
+	int offset;
+	int d;
+	
+	m = _allocmemimage(r, chan);
+	if(m == nil)
+		return nil;
+	if(chan != GREY1 && chan != xscreenchan)
+		return m;
+
+	d = m->depth;
+	xm = mallocz(sizeof(Xmem), 1);
+	if(pmid != PMundef)
+		xm->pmid = pmid;
+	else
+		xm->pmid = XCreatePixmap(xdisplay, xscreenid, Dx(r), Dy(r), (d==32) ? 24 : d);
+		
+	if(m->depth == 24)
+		offset = r.min.x&(4-1);
+	else
+		offset = r.min.x&(31/m->depth);
+	r.min.x -= offset;
+	
+	assert(wordsperline(r, m->depth) <= m->width);
+
+	xi = XCreateImage(xdisplay, xvis, m->depth==32?24:m->depth, ZPixmap, 0,
+		(char*)m->data->bdata, Dx(r), Dy(r), 32, m->width*sizeof(ulong));
+	
+	if(xi == nil){
+		_freememimage(m);
+		return nil;
+	}
+
+	xm->xi = xi;
+	xm->pc = getcallerpc(&r);
+	xm->r = r;
+	
+	/*
+	 * Set the parameters of the XImage so its memory looks exactly like a
+	 * Memimage, so we can call _memimagedraw on the same data.  All frame
+	 * buffers we've seen, and Plan 9's graphics code, require big-endian
+	 * bits within bytes, but little endian byte order within pixels.
+	 */
+	xi->bitmap_unit = m->depth < 8 || m->depth == 24 ? 8 : m->depth;
+	xi->byte_order = LSBFirst;
+	xi->bitmap_bit_order = MSBFirst;
+	xi->bitmap_pad = 32;
+	xm->r = Rect(0,0,0,0);
+	XInitImage(xi);
+	XFlush(xdisplay);
+
+	m->X = xm;
+	return m;
+}
+
+void
+xfillcolor(Memimage *m, Rectangle r, ulong v)
+{
+	GC gc;
+	Xmem *dxm;
+
+	dxm = m->X;
+	assert(dxm != nil);
+	r = rectsubpt(r, m->r.min);
+		
+	if(m->chan == GREY1){
+		gc = xgcfill0;
+		if(xgcfillcolor0 != v){
+			XSetForeground(xdisplay, gc, v);
+			xgcfillcolor0 = v;
+		}
+	}else{
+		if(m->chan == CMAP8 && xtblbit)
+			v = plan9tox11[v];
+				
+		gc = xgcfill;
+		if(xgcfillcolor != v){
+			XSetForeground(xdisplay, gc, v);
+			xgcfillcolor = v;
+		}
+	}
+	XFillRectangle(xdisplay, dxm->pmid, gc, r.min.x, r.min.y, Dx(r), Dy(r));
+}
+
+/*
+ * Replacements for libmemdraw routines.
+ * (They've been underscored.)
+ */
+Memimage*
+allocmemimage(Rectangle r, ulong chan)
+{
+	return xallocmemimage(r, chan, PMundef);
+}
+
+void
+freememimage(Memimage *m)
+{
+	Xmem *xm;
+	
+	if(m == nil)
+		return;
+		
+	if(m->data->ref == 1){
+		if((xm = m->X) != nil){
+			if(xm->xi){
+				xm->xi->data = nil;
+				XFree(xm->xi);
+			}
+			XFreePixmap(xdisplay, xm->pmid);
+			free(xm);
+			m->X = nil;
+		}
+	}
+	_freememimage(m);
+}
+
+void
+memfillcolor(Memimage *m, ulong val)
+{
+	_memfillcolor(m, val);
+	if(m->X){
+		if((val & 0xFF) == 0xFF)
+			xfillcolor(m, m->r, _rgbatoimg(m, val));
+		else
+			putXdata(m, m->r);
+	}
+}
+
+int
+loadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
+{
+	int n;
+
+	n = _loadmemimage(i, r, data, ndata);
+	if(n > 0 && i->X)
+		putXdata(i, r);
+	return n;
+}
+
+int
+cloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
+{
+	int n;
+
+	n = _cloadmemimage(i, r, data, ndata);
+	if(n > 0 && i->X)
+		putXdata(i, r);
+	return n;
+}
+
+ulong
+pixelbits(Memimage *m, Point p)
+{
+	if(m->X)
+		getXdata(m, Rect(p.x, p.y, p.x+1, p.y+1));
+	return _pixelbits(m, p);
+}
+
+void
+memimageinit(void)
+{
+	static int didinit = 0;
+	
+	if(didinit)
+		return;
+
+	didinit = 1;
+	_memimageinit();
+	
+	xfillcolor(memblack, memblack->r, 0);
+	xfillcolor(memwhite, memwhite->r, 1);
+}
+
+void
+memimagedraw(Memimage *dst, Rectangle r, Memimage *src, Point sp, Memimage *mask, Point mp, int op)
+{
+	Memdrawparam *par;
+	
+	if((par = _memimagedrawsetup(dst, r, src, sp, mask, mp, op)) == nil)
+		return;
+	_memimagedraw(par);
+	if(!xdraw(par))
+		putXdata(dst, par->r);
+}
+
+static int
+xdraw(Memdrawparam *par)
+{
+	int dy, dx;
+	unsigned m;
+	Memimage *src, *dst, *mask;
+	Xmem *dxm, *sxm, *mxm;
+	GC gc;
+	Rectangle r, sr, mr;
+	ulong sdval;
+
+	dx = Dx(par->r);
+	dy = Dy(par->r);
+	src = par->src;
+	dst = par->dst;
+	mask = par->mask;
+	r = par->r;
+	sr = par->sr;
+	mr = par->mr;
+	sdval = par->sdval;
+
+	/*
+	 * drawterm was distributed for years with
+	 * "return 0;" right here.
+	 * maybe we should give up on all this?
+	 */
+
+	if((dxm = dst->X) == nil)
+		return 0;
+
+	/*
+	 * If we have an opaque mask and source is one opaque pixel we can convert to the
+	 * destination format and just XFillRectangle.
+	 */
+	m = Simplesrc|Simplemask|Fullmask;
+	if((par->state&m)==m){
+		xfillcolor(dst, r, sdval);
+		dirtyXdata(dst, par->r);
+		return 1;
+	}
+
+	/*
+	 * If no source alpha, an opaque mask, we can just copy the
+	 * source onto the destination.  If the channels are the same and
+	 * the source is not replicated, XCopyArea suffices.
+	 */
+	m = Simplemask|Fullmask;
+	if((par->state&(m|Replsrc))==m && src->chan == dst->chan && src->X){
+		sxm = src->X;
+		r = rectsubpt(r, dst->r.min);		
+		sr = rectsubpt(sr, src->r.min);
+		if(dst->chan == GREY1)
+			gc = xgccopy0;
+		else
+			gc = xgccopy;
+		XCopyArea(xdisplay, sxm->pmid, dxm->pmid, gc, 
+			sr.min.x, sr.min.y, dx, dy, r.min.x, r.min.y);
+		dirtyXdata(dst, par->r);
+		return 1;
+	}
+	
+	/*
+	 * If no source alpha, a 1-bit mask, and a simple source
+	 * we can just copy through the mask onto the destination.
+	 */
+	if(dst->X && mask->X && !(mask->flags&Frepl)
+	&& mask->chan == GREY1 && (par->state&Simplesrc)){
+		Point p;
+
+		mxm = mask->X;
+		r = rectsubpt(r, dst->r.min);		
+		mr = rectsubpt(mr, mask->r.min);
+		p = subpt(r.min, mr.min);
+		if(dst->chan == GREY1){
+			gc = xgcsimplesrc0;
+			if(xgcsimplecolor0 != sdval){
+				XSetForeground(xdisplay, gc, sdval);
+				xgcsimplecolor0 = sdval;
+			}
+			if(xgcsimplepm0 != mxm->pmid){
+				XSetStipple(xdisplay, gc, mxm->pmid);
+				xgcsimplepm0 = mxm->pmid;
+			}
+		}else{
+		/* somehow this doesn't work on rob's mac 
+			gc = xgcsimplesrc;
+			if(dst->chan == CMAP8 && xtblbit)
+				sdval = plan9tox11[sdval];
+				
+			if(xgcsimplecolor != sdval){
+				XSetForeground(xdisplay, gc, sdval);
+				xgcsimplecolor = sdval;
+			}
+			if(xgcsimplepm != mxm->pmid){
+				XSetStipple(xdisplay, gc, mxm->pmid);
+				xgcsimplepm = mxm->pmid;
+			}
+		*/
+			return 0;
+		}
+		XSetTSOrigin(xdisplay, gc, p.x, p.y);
+		XFillRectangle(xdisplay, dxm->pmid, gc, r.min.x, r.min.y, dx, dy);
+		dirtyXdata(dst, par->r);
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * X11 window management and kernel hooks.
+ * Oh, how I loathe this code!
+ */
+
+static XColor			map[256];	/* Plan 9 colormap array */
+static XColor			map7[128];	/* Plan 9 colormap array */
+static uchar			map7to8[128][2];
+static Colormap		xcmap;		/* Default shared colormap  */
+
+extern int mousequeue;
+
+/* for copy/paste, lifted from plan9ports */
+static Atom clipboard; 
+static Atom utf8string;
+static Atom targets;
+static Atom text;
+static Atom compoundtext;
+
+static	Drawable	xdrawable;
+static	void		xexpose(XEvent*);
+static	void		xmouse(XEvent*);
+static	void		xkeyboard(XEvent*);
+static	void		xmapping(XEvent*);
+static	void		xdestroy(XEvent*);
+static	void		xselect(XEvent*, XDisplay*);
+static	void		xproc(void*);
+static	Memimage*		xinitscreen(void);
+static	void		initmap(Window);
+static	GC		creategc(Drawable);
+static	void		graphicscmap(XColor*);
+static	int		xscreendepth;
+static	XDisplay*	xkmcon;	/* used only in xproc */
+static	XDisplay*	xsnarfcon;	/* used holding clip.lk */
+static	ulong		xblack;
+static	ulong		xwhite;
+
+static	int	putsnarf, assertsnarf;
+
+	Memimage *gscreen;
+	Screeninfo screen;
+
+void
+flushmemscreen(Rectangle r)
+{
+	assert(!drawcanqlock());
+	if(r.min.x >= r.max.x || r.min.y >= r.max.y)
+		return;
+	XCopyArea(xdisplay, xscreenid, xdrawable, xgccopy, r.min.x, r.min.y, Dx(r), Dy(r), r.min.x, r.min.y);
+	XFlush(xdisplay);
+}
+
+void
+screeninit(void)
+{
+	_memmkcmap();
+
+	gscreen = xinitscreen();
+	kproc("xscreen", xproc, nil);
+
+	memimageinit();
+	terminit();
+	drawqlock();
+	flushmemscreen(gscreen->r);
+	drawqunlock();
+}
+
+uchar*
+attachscreen(Rectangle *r, ulong *chan, int *depth,
+	int *width, int *softscreen, void **X)
+{
+	*r = gscreen->r;
+	*chan = gscreen->chan;
+	*depth = gscreen->depth;
+	*width = gscreen->width;
+	*X = gscreen->X;
+	*softscreen = 1;
+
+	return gscreen->data->bdata;
+}
+
+static int
+revbyte(int b)
+{
+	int r;
+
+	r = 0;
+	r |= (b&0x01) << 7;
+	r |= (b&0x02) << 5;
+	r |= (b&0x04) << 3;
+	r |= (b&0x08) << 1;
+	r |= (b&0x10) >> 1;
+	r |= (b&0x20) >> 3;
+	r |= (b&0x40) >> 5;
+	r |= (b&0x80) >> 7;
+	return r;
+}
+
+void
+mouseset(Point xy)
+{
+	drawqlock();
+	XWarpPointer(xdisplay, None, xdrawable, 0, 0, 0, 0, xy.x, xy.y);
+	XFlush(xdisplay);
+	drawqunlock();
+}
+
+static XCursor xcursor;
+
+void
+setcursor(void)
+{
+	XCursor xc;
+	XColor fg, bg;
+	Pixmap xsrc, xmask;
+	int i;
+	uchar src[2*16], mask[2*16];
+
+	for(i=0; i<2*16; i++){
+		src[i] = revbyte(cursor.set[i]);
+		mask[i] = revbyte(cursor.set[i] | cursor.clr[i]);
+	}
+
+	drawqlock();
+	fg = map[0];
+	bg = map[255];
+	xsrc = XCreateBitmapFromData(xdisplay, xdrawable, (char*)src, 16, 16);
+	xmask = XCreateBitmapFromData(xdisplay, xdrawable, (char*)mask, 16, 16);
+	xc = XCreatePixmapCursor(xdisplay, xsrc, xmask, &fg, &bg, -cursor.offset.x, -cursor.offset.y);
+	if(xc != 0) {
+		XDefineCursor(xdisplay, xdrawable, xc);
+		if(xcursor != 0)
+			XFreeCursor(xdisplay, xcursor);
+		xcursor = xc;
+	}
+	XFreePixmap(xdisplay, xsrc);
+	XFreePixmap(xdisplay, xmask);
+	XFlush(xdisplay);
+	drawqunlock();
+}
+
+void
+cursorarrow(void)
+{
+	drawqlock();
+	if(xcursor != 0){
+		XFreeCursor(xdisplay, xcursor);
+		xcursor = 0;
+	}
+	XUndefineCursor(xdisplay, xdrawable);
+	XFlush(xdisplay);
+	drawqunlock();
+}
+
+static void
+xproc(void *arg)
+{
+	ulong mask;
+	XEvent event;
+
+	mask = 	KeyPressMask|
+		ButtonPressMask|
+		ButtonReleaseMask|
+		PointerMotionMask|
+		Button1MotionMask|
+		Button2MotionMask|
+		Button3MotionMask|
+		Button4MotionMask|
+		Button5MotionMask|
+		ExposureMask|
+		StructureNotifyMask;
+
+	XSelectInput(xkmcon, xdrawable, mask);
+	for(;;) {
+		//XWindowEvent(xkmcon, xdrawable, mask, &event);
+		XNextEvent(xkmcon, &event);
+		xselect(&event, xkmcon);
+		xkeyboard(&event);
+		xmouse(&event);
+		xexpose(&event);
+		xmapping(&event);
+		xdestroy(&event);
+	}
+}
+
+static int
+shutup(XDisplay *d, XErrorEvent *e)
+{
+	char buf[200];
+	iprint("X error: error code=%d, request_code=%d, minor=%d\n", e->error_code, e->request_code, e->minor_code);
+	XGetErrorText(d, e->error_code, buf, sizeof(buf));
+	iprint("%s\n", buf);
+	USED(d);
+	USED(e);
+	return 0;
+}
+
+static int
+panicshutup(XDisplay *d)
+{
+	panic("x error");
+	return -1;
+}
+
+static Memimage*
+xinitscreen(void)
+{
+	Memimage *gscreen;
+	int i, xsize, ysize, pmid;
+	char *argv[2];
+	char *disp_val;
+	Window rootwin;
+	Rectangle r;
+	XWMHints hints;
+	XScreen *screen;
+	XVisualInfo xvi;
+	int rootscreennum;
+	XTextProperty name;
+	XClassHint classhints;
+	XSizeHints normalhints;
+	XSetWindowAttributes attrs;
+	XPixmapFormatValues *pfmt;
+	int n;
+	Pixmap icon_pixmap;
+
+	xscreenid = 0;
+	xdrawable = 0;
+
+	xdisplay = XOpenDisplay(NULL);
+	if(xdisplay == 0){
+		iprint("xinitscreen: XOpenDisplay: %r [DISPLAY=%s]\n",
+			getenv("DISPLAY"));
+		exit(0);
+	}
+
+	XSetErrorHandler(shutup);
+	XSetIOErrorHandler(panicshutup);
+	rootscreennum = DefaultScreen(xdisplay);
+	rootwin = DefaultRootWindow(xdisplay);
+	
+	xscreendepth = DefaultDepth(xdisplay, rootscreennum);
+	if(XMatchVisualInfo(xdisplay, rootscreennum, 16, TrueColor, &xvi)
+	|| XMatchVisualInfo(xdisplay, rootscreennum, 16, DirectColor, &xvi)){
+		xvis = xvi.visual;
+		xscreendepth = 16;
+		xtblbit = 1;
+	}
+	else if(XMatchVisualInfo(xdisplay, rootscreennum, 24, TrueColor, &xvi)
+	|| XMatchVisualInfo(xdisplay, rootscreennum, 24, DirectColor, &xvi)){
+		xvis = xvi.visual;
+		xscreendepth = 24;
+		xtblbit = 1;
+	}
+	else if(XMatchVisualInfo(xdisplay, rootscreennum, 8, PseudoColor, &xvi)
+	|| XMatchVisualInfo(xdisplay, rootscreennum, 8, StaticColor, &xvi)){
+		if(xscreendepth > 8)
+			panic("drawterm: can't deal with colormapped depth %d screens\n", xscreendepth);
+		xvis = xvi.visual;
+		xscreendepth = 8;
+	}
+	else{
+		if(xscreendepth != 8)
+			panic("drawterm: can't deal with depth %d screens\n", xscreendepth);
+		xvis = DefaultVisual(xdisplay, rootscreennum);
+	}
+
+	/*
+	 * xscreendepth is only the number of significant pixel bits,
+	 * not the total.  We need to walk the display list to find
+	 * how many actual bits are being used per pixel.
+	 */
+	xscreenchan = 0; /* not a valid channel */
+	pfmt = XListPixmapFormats(xdisplay, &n);
+	for(i=0; i<n; i++){
+		if(pfmt[i].depth == xscreendepth){
+			switch(pfmt[i].bits_per_pixel){
+			case 1:	/* untested */
+				xscreenchan = GREY1;
+				break;
+			case 2:	/* untested */
+				xscreenchan = GREY2;
+				break;
+			case 4:	/* untested */
+				xscreenchan = GREY4;
+				break;
+			case 8:
+				xscreenchan = CMAP8;
+				break;
+			case 16: /* uses 16 rather than 15, empirically. */
+				xscreenchan = RGB16;
+				break;
+			case 24: /* untested (impossible?) */
+				xscreenchan = RGB24;
+				break;
+			case 32:
+				xscreenchan = CHAN4(CIgnore, 8, CRed, 8, CGreen, 8, CBlue, 8);
+				break;
+			}
+		}
+	}
+	if(xscreenchan == 0)
+		panic("drawterm: unknown screen pixel format\n");
+		
+	screen = DefaultScreenOfDisplay(xdisplay);
+	xcmap = DefaultColormapOfScreen(screen);
+
+	if(xvis->class != StaticColor){
+		graphicscmap(map);
+		initmap(rootwin);
+	}
+
+	r.min = ZP;
+	r.max.x = WidthOfScreen(screen);
+	r.max.y = HeightOfScreen(screen);
+
+	xsize = Dx(r)*3/4;
+	ysize = Dy(r)*3/4;
+	
+	attrs.colormap = xcmap;
+	attrs.background_pixel = 0;
+	attrs.border_pixel = 0;
+	/* attrs.override_redirect = 1;*/ /* WM leave me alone! |CWOverrideRedirect */
+	xdrawable = XCreateWindow(xdisplay, rootwin, 0, 0, xsize, ysize, 0, 
+		xscreendepth, InputOutput, xvis, CWBackPixel|CWBorderPixel|CWColormap, &attrs);
+
+	/* load the given bitmap data and create an X pixmap containing it. */
+	icon_pixmap = XCreateBitmapFromData(xdisplay,
+		rootwin, (char *)glenda_bits,
+		glenda_width, glenda_height);
+
+	/*
+	 * set up property as required by ICCCM
+	 */
+	name.value = (uchar*)"drawterm";
+	name.encoding = XA_STRING;
+	name.format = 8;
+	name.nitems = strlen((char*)name.value);
+	normalhints.flags = USSize|PMaxSize;
+	normalhints.max_width = Dx(r);
+	normalhints.max_height = Dy(r);
+	normalhints.width = xsize;
+	normalhints.height = ysize;
+	hints.flags = IconPixmapHint |InputHint|StateHint;
+	hints.input = 1;
+	hints.initial_state = NormalState;
+	hints.icon_pixmap = icon_pixmap;
+
+	classhints.res_name = "drawterm";
+	classhints.res_class = "Drawterm";
+	argv[0] = "drawterm";
+	argv[1] = nil;
+	XSetWMProperties(xdisplay, xdrawable,
+		&name,			/* XA_WM_NAME property for ICCCM */
+		&name,			/* XA_WM_ICON_NAME */
+		argv,			/* XA_WM_COMMAND */
+		1,			/* argc */
+		&normalhints,		/* XA_WM_NORMAL_HINTS */
+		&hints,			/* XA_WM_HINTS */
+		&classhints);		/* XA_WM_CLASS */
+	XFlush(xdisplay);
+	
+	/*
+	 * put the window on the screen
+	 */
+	XMapWindow(xdisplay, xdrawable);
+	XFlush(xdisplay);
+
+	xscreenid = XCreatePixmap(xdisplay, xdrawable, Dx(r), Dy(r), xscreendepth);
+	gscreen = xallocmemimage(r, xscreenchan, xscreenid);
+	
+	xgcfill = creategc(xscreenid);
+	XSetFillStyle(xdisplay, xgcfill, FillSolid);
+	xgccopy = creategc(xscreenid);
+	xgcsimplesrc = creategc(xscreenid);
+	XSetFillStyle(xdisplay, xgcsimplesrc, FillStippled);
+	xgczero = creategc(xscreenid);
+	xgcreplsrc = creategc(xscreenid);
+	XSetFillStyle(xdisplay, xgcreplsrc, FillTiled);
+
+	pmid = XCreatePixmap(xdisplay, xdrawable, 1, 1, 1);
+	xgcfill0 = creategc(pmid);
+	XSetForeground(xdisplay, xgcfill0, 0);
+	XSetFillStyle(xdisplay, xgcfill0, FillSolid);
+	xgccopy0 = creategc(pmid);
+	xgcsimplesrc0 = creategc(pmid);
+	XSetFillStyle(xdisplay, xgcsimplesrc0, FillStippled);
+	xgczero0 = creategc(pmid);
+	xgcreplsrc0 = creategc(pmid);
+	XSetFillStyle(xdisplay, xgcreplsrc0, FillTiled);
+	XFreePixmap(xdisplay, pmid);
+
+	XSetForeground(xdisplay, xgccopy, plan9tox11[0]);
+	XFillRectangle(xdisplay, xscreenid, xgccopy, 0, 0, xsize, ysize);
+
+	xkmcon = XOpenDisplay(NULL);
+	if(xkmcon == 0){
+		disp_val = getenv("DISPLAY");
+		if(disp_val == 0)
+			disp_val = "not set";
+		iprint("drawterm: open %r, DISPLAY is %s\n", disp_val);
+		exit(0);
+	}
+	xsnarfcon = XOpenDisplay(NULL);
+	if(xsnarfcon == 0){
+		disp_val = getenv("DISPLAY");
+		if(disp_val == 0)
+			disp_val = "not set";
+		iprint("drawterm: open %r, DISPLAY is %s\n", disp_val);
+		exit(0);
+	}
+
+	clipboard = XInternAtom(xkmcon, "CLIPBOARD", False);
+	utf8string = XInternAtom(xkmcon, "UTF8_STRING", False);
+	targets = XInternAtom(xkmcon, "TARGETS", False);
+	text = XInternAtom(xkmcon, "TEXT", False);
+	compoundtext = XInternAtom(xkmcon, "COMPOUND_TEXT", False);
+
+	xblack = screen->black_pixel;
+	xwhite = screen->white_pixel;
+	return gscreen;
+}
+
+static void
+graphicscmap(XColor *map)
+{
+	int r, g, b, cr, cg, cb, v, num, den, idx, v7, idx7;
+
+	for(r=0; r!=4; r++) {
+		for(g = 0; g != 4; g++) {
+			for(b = 0; b!=4; b++) {
+				for(v = 0; v!=4; v++) {
+					den=r;
+					if(g > den)
+						den=g;
+					if(b > den)
+						den=b;
+					/* divide check -- pick grey shades */
+					if(den==0)
+						cr=cg=cb=v*17;
+					else {
+						num=17*(4*den+v);
+						cr=r*num/den;
+						cg=g*num/den;
+						cb=b*num/den;
+					}
+					idx = r*64 + v*16 + ((g*4 + b + v - r) & 15);
+					map[idx].red = cr*0x0101;
+					map[idx].green = cg*0x0101;
+					map[idx].blue = cb*0x0101;
+					map[idx].pixel = idx;
+					map[idx].flags = DoRed|DoGreen|DoBlue;
+
+					v7 = v >> 1;
+					idx7 = r*32 + v7*16 + g*4 + b;
+					if((v & 1) == v7){
+						map7to8[idx7][0] = idx;
+						if(den == 0) { 		/* divide check -- pick grey shades */
+							cr = ((255.0/7.0)*v7)+0.5;
+							cg = cr;
+							cb = cr;
+						}
+						else {
+							num=17*15*(4*den+v7*2)/14;
+							cr=r*num/den;
+							cg=g*num/den;
+							cb=b*num/den;
+						}
+						map7[idx7].red = cr*0x0101;
+						map7[idx7].green = cg*0x0101;
+						map7[idx7].blue = cb*0x0101;
+						map7[idx7].pixel = idx7;
+						map7[idx7].flags = DoRed|DoGreen|DoBlue;
+					}
+					else
+						map7to8[idx7][1] = idx;
+				}
+			}
+		}
+	}
+}
+
+/*
+ * Initialize and install the drawterm colormap as a private colormap for this
+ * application.  Drawterm gets the best colors here when it has the cursor focus.
+ */  
+static void 
+initmap(Window w)
+{
+	XColor c;
+	int i;
+	ulong p, pp;
+	char buf[30];
+
+	if(xscreendepth <= 1)
+		return;
+
+	if(xscreendepth >= 24) {
+		/* The pixel value returned from XGetPixel needs to
+		 * be converted to RGB so we can call rgb2cmap()
+		 * to translate between 24 bit X and our color. Unfortunately,
+		 * the return value appears to be display server endian 
+		 * dependant. Therefore, we run some heuristics to later
+		 * determine how to mask the int value correctly.
+		 * Yeah, I know we can look at xvis->byte_order but 
+		 * some displays say MSB even though they run on LSB.
+		 * Besides, this is more anal.
+		 */
+		if(xscreendepth != DefaultDepth(xdisplay, DefaultScreen(xdisplay)))
+			xcmap = XCreateColormap(xdisplay, w, xvis, AllocNone);
+
+		c = map[19];
+		/* find out index into colormap for our RGB */
+		if(!XAllocColor(xdisplay, xcmap, &c))
+			panic("drawterm: screen-x11 can't alloc color");
+
+		p  = c.pixel;
+		pp = rgb2cmap((p>>16)&0xff,(p>>8)&0xff,p&0xff);
+		if(pp!=map[19].pixel) {
+			/* check if endian is other way */
+			pp = rgb2cmap(p&0xff,(p>>8)&0xff,(p>>16)&0xff);
+			if(pp!=map[19].pixel)
+				panic("cannot detect x server byte order");
+			switch(xscreenchan){
+			case RGB24:
+				xscreenchan = BGR24;
+				break;
+			case XRGB32:
+				xscreenchan = XBGR32;
+				break;
+			default:
+				panic("don't know how to byteswap channel %s", 
+					chantostr(buf, xscreenchan));
+				break;
+			}
+		}
+	} else if(xvis->class == TrueColor || xvis->class == DirectColor) {
+	} else if(xvis->class == PseudoColor) {
+		if(xtblbit == 0){
+			xcmap = XCreateColormap(xdisplay, w, xvis, AllocAll); 
+			XStoreColors(xdisplay, xcmap, map, 256);
+			for(i = 0; i < 256; i++) {
+				plan9tox11[i] = i;
+				x11toplan9[i] = i;
+			}
+		}
+		else {
+			for(i = 0; i < 128; i++) {
+				c = map7[i];
+				if(!XAllocColor(xdisplay, xcmap, &c)) {
+					iprint("drawterm: can't alloc colors in default map, don't use -7\n");
+					exit(0);
+				}
+				plan9tox11[map7to8[i][0]] = c.pixel;
+				plan9tox11[map7to8[i][1]] = c.pixel;
+				x11toplan9[c.pixel] = map7to8[i][0];
+			}
+		}
+	}
+	else
+		panic("drawterm: unsupported visual class %d\n", xvis->class);
+}
+
+static void
+xdestroy(XEvent *e)
+{
+	XDestroyWindowEvent *xe;
+	if(e->type != DestroyNotify)
+		return;
+	xe = (XDestroyWindowEvent*)e;
+	if(xe->window == xdrawable)
+		exit(0);
+}
+
+static void
+xmapping(XEvent *e)
+{
+	XMappingEvent *xe;
+
+	if(e->type != MappingNotify)
+		return;
+	xe = (XMappingEvent*)e;
+	USED(xe);
+}
+
+
+/*
+ * Disable generation of GraphicsExpose/NoExpose events in the GC.
+ */
+static GC
+creategc(Drawable d)
+{
+	XGCValues gcv;
+
+	gcv.function = GXcopy;
+	gcv.graphics_exposures = False;
+	return XCreateGC(xdisplay, d, GCFunction|GCGraphicsExposures, &gcv);
+}
+
+static void
+xexpose(XEvent *e)
+{
+	Rectangle r;
+	XExposeEvent *xe;
+
+	if(e->type != Expose)
+		return;
+	xe = (XExposeEvent*)e;
+	r.min.x = xe->x;
+	r.min.y = xe->y;
+	r.max.x = xe->x + xe->width;
+	r.max.y = xe->y + xe->height;
+	drawflushr(r);
+}
+
+static void
+xkeyboard(XEvent *e)
+{
+	KeySym k;
+
+	/*
+	 * I tried using XtGetActionKeysym, but it didn't seem to
+	 * do case conversion properly
+	 * (at least, with Xterminal servers and R4 intrinsics)
+	 */
+	if(e->xany.type != KeyPress)
+		return;
+
+
+	XLookupString((XKeyEvent*)e, NULL, 0, &k, NULL);
+
+	if(k == XK_Multi_key || k == NoSymbol)
+		return;
+	if(k&0xFF00){
+		switch(k){
+		case XK_BackSpace:
+		case XK_Tab:
+		case XK_Escape:
+		case XK_Delete:
+		case XK_KP_0:
+		case XK_KP_1:
+		case XK_KP_2:
+		case XK_KP_3:
+		case XK_KP_4:
+		case XK_KP_5:
+		case XK_KP_6:
+		case XK_KP_7:
+		case XK_KP_8:
+		case XK_KP_9:
+		case XK_KP_Divide:
+		case XK_KP_Multiply:
+		case XK_KP_Subtract:
+		case XK_KP_Add:
+		case XK_KP_Decimal:
+			k &= 0x7F;
+			break;
+		case XK_Linefeed:
+			k = '\r';
+			break;
+		case XK_KP_Space:
+			k = ' ';
+			break;
+		case XK_Home:
+		case XK_KP_Home:
+			k = Khome;
+			break;
+		case XK_Left:
+		case XK_KP_Left:
+			k = Kleft;
+			break;
+		case XK_Up:
+		case XK_KP_Up:
+			k = Kup;
+			break;
+		case XK_Down:
+		case XK_KP_Down:
+			k = Kdown;
+			break;
+		case XK_Right:
+		case XK_KP_Right:
+			k = Kright;
+			break;
+		case XK_Page_Down:
+		case XK_KP_Page_Down:
+			k = Kpgdown;
+			break;
+		case XK_End:
+		case XK_KP_End:
+			k = Kend;
+			break;
+		case XK_Page_Up:	
+		case XK_KP_Page_Up:
+			k = Kpgup;
+			break;
+		case XK_Insert:
+		case XK_KP_Insert:
+			k = Kins;
+			break;
+		case XK_KP_Enter:
+		case XK_Return:
+			k = '\n';
+			break;
+		case XK_Alt_L:
+		case XK_Alt_R:
+			k = Kalt;
+			break;
+		case XK_Shift_L:
+		case XK_Shift_R:
+		case XK_Control_L:
+		case XK_Control_R:
+		case XK_Caps_Lock:
+		case XK_Shift_Lock:
+
+		case XK_Meta_L:
+		case XK_Meta_R:
+		case XK_Super_L:
+		case XK_Super_R:
+		case XK_Hyper_L:
+		case XK_Hyper_R:
+			return;
+		default:		/* not ISO-1 or tty control */
+  			if(k>0xff){
+				k = keysym2ucs(k); /* supplied by X */
+				if(k == -1)
+					return;
+			}
+			break;
+		}
+	}
+
+	/* Compensate for servers that call a minus a hyphen */
+	if(k == XK_hyphen)
+		k = XK_minus;
+	/* Do control mapping ourselves if translator doesn't */
+	if(e->xkey.state&ControlMask)
+		k &= 0x9f;
+	if(k == NoSymbol) {
+		return;
+	}
+
+	kbdputc(kbdq, k);
+}
+
+static void
+xmouse(XEvent *e)
+{
+	Mousestate ms;
+	int i, s;
+	XButtonEvent *be;
+	XMotionEvent *me;
+
+	if(putsnarf != assertsnarf){
+		assertsnarf = putsnarf;
+		XSetSelectionOwner(xkmcon, XA_PRIMARY, xdrawable, CurrentTime);
+		if(clipboard != None)
+			XSetSelectionOwner(xkmcon, clipboard, xdrawable, CurrentTime);
+		XFlush(xkmcon);
+	}
+
+	switch(e->type){
+	case ButtonPress:
+		be = (XButtonEvent *)e;
+		/* 
+		 * Fake message, just sent to make us announce snarf.
+		 * Apparently state and button are 16 and 8 bits on
+		 * the wire, since they are truncated by the time they
+		 * get to us.
+		 */
+		if(be->send_event
+		&& (~be->state&0xFFFF)==0
+		&& (~be->button&0xFF)==0)
+			return;
+		ms.xy.x = be->x;
+		ms.xy.y = be->y;
+		s = be->state;
+		ms.msec = be->time;
+		switch(be->button){
+		case 1:
+			s |= Button1Mask;
+			break;
+		case 2:
+			s |= Button2Mask;
+			break;
+		case 3:
+			s |= Button3Mask;
+			break;
+		case 4:
+			s |= Button4Mask;
+			break;
+		case 5:
+			s |= Button5Mask;
+			break;
+		}
+		break;
+	case ButtonRelease:
+		be = (XButtonEvent *)e;
+		ms.xy.x = be->x;
+		ms.xy.y = be->y;
+		ms.msec = be->time;
+		s = be->state;
+		switch(be->button){
+		case 1:
+			s &= ~Button1Mask;
+			break;
+		case 2:
+			s &= ~Button2Mask;
+			break;
+		case 3:
+			s &= ~Button3Mask;
+			break;
+		case 4:
+			s &= ~Button4Mask;
+			break;
+		case 5:
+			s &= ~Button5Mask;
+			break;
+		}
+		break;
+	case MotionNotify:
+		me = (XMotionEvent *)e;
+		s = me->state;
+		ms.xy.x = me->x;
+		ms.xy.y = me->y;
+		ms.msec = me->time;
+		break;
+	default:
+		return;
+	}
+
+	ms.buttons = 0;
+	if(s & Button1Mask)
+		ms.buttons |= 1;
+	if(s & Button2Mask)
+		ms.buttons |= 2;
+	if(s & Button3Mask)
+		ms.buttons |= 4;
+	if(s & Button4Mask)
+		ms.buttons |= 8;
+	if(s & Button5Mask)
+		ms.buttons |= 16;
+
+	lock(&mouse.lk);
+	i = mouse.wi;
+	if(mousequeue) {
+		if(i == mouse.ri || mouse.lastb != ms.buttons || mouse.trans) {
+			mouse.wi = (i+1)%Mousequeue;
+			if(mouse.wi == mouse.ri)
+				mouse.ri = (mouse.ri+1)%Mousequeue;
+			mouse.trans = mouse.lastb != ms.buttons;
+		} else {
+			i = (i-1+Mousequeue)%Mousequeue;
+		}
+	} else {
+		mouse.wi = (i+1)%Mousequeue;
+		mouse.ri = i;
+	}
+	mouse.queue[i] = ms;
+	mouse.lastb = ms.buttons;
+	unlock(&mouse.lk);
+	wakeup(&mouse.r);
+}
+
+void
+getcolor(ulong i, ulong *r, ulong *g, ulong *b)
+{
+	ulong v;
+	
+	v = cmap2rgb(i);
+	*r = (v>>16)&0xFF;
+	*g = (v>>8)&0xFF;
+	*b = v&0xFF;
+}
+
+void
+setcolor(ulong i, ulong r, ulong g, ulong b)
+{
+	/* no-op */
+}
+
+int
+atlocalconsole(void)
+{
+	char *p, *q;
+	char buf[128];
+
+	p = getenv("DRAWTERM_ATLOCALCONSOLE");
+	if(p && atoi(p) == 1)
+		return 1;
+
+	p = getenv("DISPLAY");
+	if(p == nil)
+		return 0;
+
+	/* extract host part */
+	q = strchr(p, ':');
+	if(q == nil)
+		return 0;
+	*q = 0;
+
+	if(strcmp(p, "") == 0)
+		return 1;
+
+	/* try to match against system name (i.e. for ssh) */
+	if(gethostname(buf, sizeof buf) == 0){
+		if(strcmp(p, buf) == 0)
+			return 1;
+		if(strncmp(p, buf, strlen(p)) == 0 && buf[strlen(p)]=='.')
+			return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * Cut and paste.  Just couldn't stand to make this simple...
+ */
+
+typedef struct Clip Clip;
+struct Clip
+{
+	char buf[SnarfSize];
+	QLock lk;
+};
+Clip clip;
+
+#undef long	/* sic */
+#undef ulong
+
+static char*
+_xgetsnarf(XDisplay *xd)
+{
+	uchar *data, *xdata;
+	Atom clipboard, type, prop;
+	unsigned long lastlen;
+	uint dummy, len;
+	int fmt, i;
+	Window w;
+
+	qlock(&clip.lk);
+	/*
+	 * Have we snarfed recently and the X server hasn't caught up?
+	 */
+	if(putsnarf != assertsnarf)
+		goto mine;
+
+	/*
+	 * Is there a primary selection (highlighted text in an xterm)?
+	 */
+	clipboard = XA_PRIMARY;
+	w = XGetSelectionOwner(xd, XA_PRIMARY);
+	if(w == xdrawable){
+	mine:
+		data = (uchar*)strdup(clip.buf);
+		goto out;
+	}
+
+	/*
+	 * If not, is there a clipboard selection?
+	 */
+	if(w == None && clipboard != None){
+		clipboard = clipboard;
+		w = XGetSelectionOwner(xd, clipboard);
+		if(w == xdrawable)
+			goto mine;
+	}
+
+	/*
+	 * If not, give up.
+	 */
+	if(w == None){
+		data = nil;
+		goto out;
+	}
+		
+	/*
+	 * We should be waiting for SelectionNotify here, but it might never
+	 * come, and we have no way to time out.  Instead, we will clear
+	 * local property #1, request our buddy to fill it in for us, and poll
+	 * until he's done or we get tired of waiting.
+	 *
+	 * We should try to go for utf8string instead of XA_STRING,
+	 * but that would add to the polling.
+	 */
+	prop = 1;
+	XChangeProperty(xd, xdrawable, prop, XA_STRING, 8, PropModeReplace, (uchar*)"", 0);
+	XConvertSelection(xd, clipboard, XA_STRING, prop, xdrawable, CurrentTime);
+	XFlush(xd);
+	lastlen = 0;
+	for(i=0; i<10 || (lastlen!=0 && i<30); i++){
+		usleep(100*1000);
+		XGetWindowProperty(xd, xdrawable, prop, 0, 0, 0, AnyPropertyType,
+			&type, &fmt, &dummy, &len, &data);
+		if(lastlen == len && len > 0)
+			break;
+		lastlen = len;
+	}
+	if(i == 10){
+		data = nil;
+		goto out;
+	}
+	/* get the property */
+	data = nil;
+	XGetWindowProperty(xd, xdrawable, prop, 0, SnarfSize/sizeof(unsigned long), 0, 
+		AnyPropertyType, &type, &fmt, &len, &dummy, &xdata);
+	if((type != XA_STRING && type != utf8string) || len == 0){
+		if(xdata)
+			XFree(xdata);
+		data = nil;
+	}else{
+		if(xdata){
+			data = (uchar*)strdup((char*)xdata);
+			XFree(xdata);
+		}else
+			data = nil;
+	}
+out:
+	qunlock(&clip.lk);
+	return (char*)data;
+}
+
+static void
+_xputsnarf(XDisplay *xd, char *data)
+{
+	XButtonEvent e;
+
+	if(strlen(data) >= SnarfSize)
+		return;
+	qlock(&clip.lk);
+	strcpy(clip.buf, data);
+
+	/* leave note for mouse proc to assert selection ownership */
+	putsnarf++;
+
+	/* send mouse a fake event so snarf is announced */
+	memset(&e, 0, sizeof e);
+	e.type = ButtonPress;
+	e.window = xdrawable;
+	e.state = ~0;
+	e.button = ~0;
+	XSendEvent(xd, xdrawable, True, ButtonPressMask, (XEvent*)&e);
+	XFlush(xd);
+	qunlock(&clip.lk);
+}
+
+static void
+xselect(XEvent *e, XDisplay *xd)
+{
+	char *name;
+	XEvent r;
+	XSelectionRequestEvent *xe;
+	Atom a[4];
+
+	if(e->xany.type != SelectionRequest)
+		return;
+
+	memset(&r, 0, sizeof r);
+	xe = (XSelectionRequestEvent*)e;
+if(0) iprint("xselect target=%d requestor=%d property=%d selection=%d\n",
+	xe->target, xe->requestor, xe->property, xe->selection);
+	r.xselection.property = xe->property;
+	if(xe->target == targets){
+		a[0] = XA_STRING;
+		a[1] = utf8string;
+		a[2] = text;
+		a[3] = compoundtext;
+
+		XChangeProperty(xd, xe->requestor, xe->property, xe->target,
+			8, PropModeReplace, (uchar*)a, sizeof a);
+	}else if(xe->target == XA_STRING || xe->target == utf8string || xe->target == text || xe->target == compoundtext){
+	text:
+		/* if the target is STRING we're supposed to reply with Latin1 XXX */
+		qlock(&clip.lk);
+		XChangeProperty(xd, xe->requestor, xe->property, xe->target,
+			8, PropModeReplace, (uchar*)clip.buf, strlen(clip.buf));
+		qunlock(&clip.lk);
+	}else{
+		name = XGetAtomName(xd, xe->target);
+		if(name == nil)
+			iprint("XGetAtomName %d failed\n", xe->target);
+		if(name){
+			if(strcmp(name, "TIMESTAMP") == 0){
+				/* nothing */
+			}else if(strncmp(name, "image/", 6) == 0){
+				/* nothing */
+			}else if(strcmp(name, "text/html") == 0){
+				/* nothing */
+			}else if(strcmp(name, "text/plain") == 0 || strcmp(name, "text/plain;charset=UTF-8") == 0){
+				goto text;
+			}else
+				iprint("%s: cannot handle selection request for '%s' (%d)\n", argv0, name, (int)xe->target);
+		}
+		r.xselection.property = None;
+	}
+
+	r.xselection.display = xe->display;
+	/* r.xselection.property filled above */
+	r.xselection.target = xe->target;
+	r.xselection.type = SelectionNotify;
+	r.xselection.requestor = xe->requestor;
+	r.xselection.time = xe->time;
+	r.xselection.send_event = True;
+	r.xselection.selection = xe->selection;
+	XSendEvent(xd, xe->requestor, False, 0, &r);
+	XFlush(xd);
+}
+
+char*
+clipread(void)
+{
+	return _xgetsnarf(xsnarfcon);
+}
+
+int
+clipwrite(char *buf)
+{
+	_xputsnarf(xsnarfcon, buf);
+	return 0;
+}
+
--- a/gui-x11/xmem.h
+++ /dev/null
@@ -1,60 +1,0 @@
-#define	Font	XXFont
-#define	Screen	XXScreen
-#define	Display	XXDisplay
-
-#include <X11/Xlib.h>
-/* #include <X11/Xlibint.h> */
-#include <X11/Xatom.h>
-#include <X11/Xutil.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-
-#undef	Font
-#undef	Screen
-#undef	Display
-
-/*
- * Structure pointed to by X field of Memimage
- */
-typedef struct Xmem Xmem;
-
-enum
-{
-	PMundef	= ~0		/* undefined pixmap id */
-};
-
-
-struct Xmem
-{
-	int	pmid;	/* pixmap id for screen ldepth instance */
-	XImage *xi;	/* local image if we currenty have the data */
-	int	dirty;
-	Rectangle dirtyr;
-	Rectangle r;
-	uintptr pc;	/* who wrote into xi */
-};
-
-extern	int		xtblbit;
-extern	int		x24bitswap;
-extern	int		plan9tox11[];
-extern  int		x11toplan9[];
-extern	int		xscreendepth;
-extern	XXDisplay	*xdisplay;
-extern	Drawable	xscreenid;
-extern	Visual		*xvis;
-extern	GC		xgcfill, xgcfill0;
-extern	int		xgcfillcolor, xgcfillcolor0;
-extern	GC		xgccopy, xgccopy0;
-extern	GC		xgczero, xgczero0;
-extern	int		xgczeropm, xgczeropm0;
-extern	GC		xgcsimplesrc, xgcsimplesrc0;
-extern	int		xgcsimplecolor, xgcsimplecolor0, xgcsimplepm, xgcsimplepm0;
-extern	GC		xgcreplsrc, xgcreplsrc0;
-extern	int		xgcreplsrcpm, xgcreplsrcpm0, xgcreplsrctile, xgcreplsrctile0;
-extern	XImage*		allocXdata(Memimage*, Rectangle);
-extern	void 		putXdata(Memimage*, Rectangle);
-extern	XImage*		getXdata(Memimage*, Rectangle);
-extern	void		freeXdata(Memimage*);
-extern	void	dirtyXdata(Memimage*, Rectangle);
-extern	ulong	xscreenchan;
-extern	void	xfillcolor(Memimage*, Rectangle, ulong);