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);