|
@@ -1,109 +1,549 @@
|
|
|
-#include <sys/types.h>
|
|
|
-#include <sys/stat.h>
|
|
|
-#include <fcntl.h>
|
|
|
-#include <termios.h>
|
|
|
-#include <stdio.h>
|
|
|
+#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;
|
|
|
+
|
|
|
+#undef long
|
|
|
+#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
|
|
|
+#define long int
|
|
|
+
|
|
|
+/* 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 */
|
|
|
+};
|
|
|
+
|
|
|
/*
|
|
|
- * alias defs for image types to overcome name conflicts
|
|
|
+ * Structure pointed to by X field of Memimage
|
|
|
*/
|
|
|
-#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
|
|
|
+typedef struct Xmem Xmem;
|
|
|
+struct Xmem
|
|
|
{
|
|
|
- int w;
|
|
|
- int h;
|
|
|
- int hotx;
|
|
|
- int hoty;
|
|
|
- char *src;
|
|
|
- char *mask;
|
|
|
+ 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
|
|
|
+};
|
|
|
|
|
|
-#define ABS(x) ((x) < 0 ? -(x) : (x))
|
|
|
+/*
|
|
|
+ * 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);
|
|
|
+}
|
|
|
|
|
|
-enum
|
|
|
+static XImage*
|
|
|
+getXdata(Memimage *m, Rectangle r)
|
|
|
{
|
|
|
- DblTime = 300 /* double click time in msec */
|
|
|
-};
|
|
|
+ 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 */
|
|
|
|
|
|
-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 Atom clipboard;
|
|
|
+static Atom utf8string;
|
|
|
+static Atom targets;
|
|
|
+static Atom text;
|
|
|
+static 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 xselect(XEvent*, XDisplay*);
|
|
|
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;
|
|
|
+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)
|
|
@@ -121,7 +561,7 @@ screeninit(void)
|
|
|
}
|
|
|
|
|
|
uchar*
|
|
|
-attachscreen(IRectangle *r, ulong *chan, int *depth,
|
|
|
+attachscreen(Rectangle *r, ulong *chan, int *depth,
|
|
|
int *width, int *softscreen, void **X)
|
|
|
{
|
|
|
*r = gscreen->r;
|
|
@@ -134,16 +574,6 @@ attachscreen(IRectangle *r, ulong *chan, int *depth,
|
|
|
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)
|
|
|
{
|
|
@@ -162,7 +592,7 @@ revbyte(int b)
|
|
|
}
|
|
|
|
|
|
void
|
|
|
-mouseset(IPoint xy)
|
|
|
+mouseset(Point xy)
|
|
|
{
|
|
|
drawqlock();
|
|
|
XWarpPointer(xdisplay, None, xdrawable, 0, 0, 0, 0, xy.x, xy.y);
|
|
@@ -170,12 +600,12 @@ mouseset(IPoint xy)
|
|
|
drawqunlock();
|
|
|
}
|
|
|
|
|
|
-static Cursor xcursor;
|
|
|
+static XCursor xcursor;
|
|
|
|
|
|
void
|
|
|
setcursor(void)
|
|
|
{
|
|
|
- Cursor xc;
|
|
|
+ XCursor xc;
|
|
|
XColor fg, bg;
|
|
|
Pixmap xsrc, xmask;
|
|
|
int i;
|
|
@@ -249,7 +679,7 @@ xproc(void *arg)
|
|
|
}
|
|
|
|
|
|
static int
|
|
|
-shutup(Display *d, XErrorEvent *e)
|
|
|
+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);
|
|
@@ -261,7 +691,7 @@ shutup(Display *d, XErrorEvent *e)
|
|
|
}
|
|
|
|
|
|
static int
|
|
|
-panicshutup(Display *d)
|
|
|
+panicshutup(XDisplay *d)
|
|
|
{
|
|
|
panic("x error");
|
|
|
return -1;
|
|
@@ -275,9 +705,9 @@ xinitscreen(void)
|
|
|
char *argv[2];
|
|
|
char *disp_val;
|
|
|
Window rootwin;
|
|
|
- IRectangle r;
|
|
|
+ Rectangle r;
|
|
|
XWMHints hints;
|
|
|
- Screen *screen;
|
|
|
+ XScreen *screen;
|
|
|
XVisualInfo xvi;
|
|
|
int rootscreennum;
|
|
|
XTextProperty name;
|
|
@@ -286,16 +716,15 @@ xinitscreen(void)
|
|
|
XSetWindowAttributes attrs;
|
|
|
XPixmapFormatValues *pfmt;
|
|
|
int n;
|
|
|
-
|
|
|
+ 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);
|
|
|
+ iprint("xinitscreen: XOpenDisplay: %r [DISPLAY=%s]\n",
|
|
|
+ getenv("DISPLAY"));
|
|
|
exit(0);
|
|
|
}
|
|
|
|
|
@@ -375,12 +804,10 @@ xinitscreen(void)
|
|
|
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;
|
|
|
|
|
@@ -391,6 +818,11 @@ xinitscreen(void)
|
|
|
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
|
|
|
*/
|
|
@@ -403,9 +835,11 @@ xinitscreen(void)
|
|
|
normalhints.max_height = Dy(r);
|
|
|
normalhints.width = xsize;
|
|
|
normalhints.height = ysize;
|
|
|
- hints.flags = InputHint|StateHint;
|
|
|
+ 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";
|
|
@@ -660,7 +1094,7 @@ creategc(Drawable d)
|
|
|
static void
|
|
|
xexpose(XEvent *e)
|
|
|
{
|
|
|
- IRectangle r;
|
|
|
+ Rectangle r;
|
|
|
XExposeEvent *xe;
|
|
|
|
|
|
if(e->type != Expose)
|
|
@@ -764,6 +1198,20 @@ xkeyboard(XEvent *e)
|
|
|
case XK_Alt_R:
|
|
|
k = Kalt;
|
|
|
break;
|
|
|
+ case XK_F1:
|
|
|
+ case XK_F2:
|
|
|
+ case XK_F3:
|
|
|
+ case XK_F4:
|
|
|
+ case XK_F5:
|
|
|
+ case XK_F6:
|
|
|
+ case XK_F7:
|
|
|
+ case XK_F8:
|
|
|
+ case XK_F9:
|
|
|
+ case XK_F10:
|
|
|
+ case XK_F11:
|
|
|
+ case XK_F12:
|
|
|
+ k = KF|(k - XK_F1 + 1);
|
|
|
+ break;
|
|
|
case XK_Shift_L:
|
|
|
case XK_Shift_R:
|
|
|
case XK_Control_L:
|
|
@@ -792,7 +1240,7 @@ xkeyboard(XEvent *e)
|
|
|
if(k == XK_hyphen)
|
|
|
k = XK_minus;
|
|
|
/* Do control mapping ourselves if translator doesn't */
|
|
|
- if(e->xkey.state&ControlMask)
|
|
|
+ if(e->xkey.state&ControlMask && k != Kalt)
|
|
|
k &= 0x9f;
|
|
|
if(k == NoSymbol) {
|
|
|
return;
|
|
@@ -987,11 +1435,12 @@ Clip clip;
|
|
|
#undef ulong
|
|
|
|
|
|
static char*
|
|
|
-_xgetsnarf(Display *xd)
|
|
|
+_xgetsnarf(XDisplay *xd)
|
|
|
{
|
|
|
uchar *data, *xdata;
|
|
|
Atom clipboard, type, prop;
|
|
|
- unsigned long len, lastlen, dummy;
|
|
|
+ unsigned long lastlen;
|
|
|
+ unsigned long dummy, len;
|
|
|
int fmt, i;
|
|
|
Window w;
|
|
|
|
|
@@ -1078,7 +1527,7 @@ out:
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
-_xputsnarf(Display *xd, char *data)
|
|
|
+_xputsnarf(XDisplay *xd, char *data)
|
|
|
{
|
|
|
XButtonEvent e;
|
|
|
|
|
@@ -1102,7 +1551,7 @@ _xputsnarf(Display *xd, char *data)
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
-xselect(XEvent *e, Display *xd)
|
|
|
+xselect(XEvent *e, XDisplay *xd)
|
|
|
{
|
|
|
char *name;
|
|
|
XEvent r;
|
|
@@ -1123,21 +1572,31 @@ if(0) iprint("xselect target=%d requestor=%d property=%d selection=%d\n",
|
|
|
a[2] = text;
|
|
|
a[3] = compoundtext;
|
|
|
|
|
|
- XChangeProperty(xd, xe->requestor, xe->property, xe->target,
|
|
|
- 8, PropModeReplace, (uchar*)a, sizeof a);
|
|
|
+ XChangeProperty(xd, xe->requestor, xe->property, XA_ATOM,
|
|
|
+ 32, 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{
|
|
|
- iprint("get %d\n", xe->target);
|
|
|
name = XGetAtomName(xd, xe->target);
|
|
|
if(name == nil)
|
|
|
- iprint("XGetAtomName failed\n");
|
|
|
- else if(strcmp(name, "TIMESTAMP") != 0)
|
|
|
- iprint("%s: cannot handle selection request for '%s' (%d)\n", argv0, name, (int)xe->target);
|
|
|
+ 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;
|
|
|
}
|
|
|
|