--- /sys/src/9/ip/icmp.c Thu Jun 13 23:28:45 2013 +++ /sys/src/9/ip/icmp.c Mon Mar 17 23:23:13 2014 @@ -366,7 +366,7 @@ case EchoRequest: if (iplen < n) bp = trimblock(bp, 0, iplen); - r = mkechoreply(bp); + r = mkechoreply(concatblock(bp)); ipriv->out[EchoReply]++; ipoput4(icmp->f, r, 0, MAXTTL, DFLTTOS, nil); break; --- /sys/src/9/ip/icmp6.c Wed Feb 5 22:32:14 2014 +++ /sys/src/9/ip/icmp6.c Mon Mar 17 23:23:13 2014 @@ -718,6 +718,7 @@ ipriv->in[type]++; switch(type) { case EchoRequestV6: + bp = concatblock(bp); r = mkechoreply6(bp, ipifc); if(r == nil) goto raise; --- /sys/src/9/omap/kbd.c Thu Apr 26 04:56:30 2012 +++ /sys/src/9/omap/kbd.c Mon Mar 17 21:50:34 2014 @@ -51,7 +51,7 @@ * The codes at 0x79 and 0x7b are produced by the PFU Happy Hacking keyboard. * A 'standard' keyboard doesn't produce anything above 0x58. */ -Rune kbtab[Nscan] = +Rune kbtab[Nscan] = { [0x00] No, 0x1b, '1', '2', '3', '4', '5', '6', [0x08] '7', '8', '9', '0', '-', '=', '\b', '\t', @@ -111,6 +111,46 @@ [0x78] No, Up, No, No, No, No, No, No, }; +Rune kbtabshiftesc1[Nscan] = +{ +[0x00] No, No, No, No, No, No, No, No, +[0x08] No, No, No, No, No, No, No, No, +[0x10] No, No, No, No, No, No, No, No, +[0x18] No, No, No, No, No, No, No, No, +[0x20] No, No, No, No, No, No, No, No, +[0x28] No, No, No, No, No, No, No, No, +[0x30] No, No, No, No, No, No, No, No, +[0x38] No, No, No, No, No, No, No, No, +[0x40] No, No, No, No, No, No, No, No, +[0x48] Up, No, No, No, No, No, No, No, +[0x50] No, No, No, No, No, No, No, No, +[0x58] No, No, No, No, No, No, No, No, +[0x60] No, No, No, No, No, No, No, No, +[0x68] No, No, No, No, No, No, No, No, +[0x70] No, No, No, No, No, No, No, No, +[0x78] No, Up, No, No, No, No, No, No, +}; + +Rune kbtabctrlesc1[Nscan] = +{ +[0x00] No, No, No, No, No, No, No, No, +[0x08] No, No, No, No, No, No, No, No, +[0x10] No, No, No, No, No, No, No, No, +[0x18] No, No, No, No, No, No, No, No, +[0x20] No, No, No, No, No, No, No, No, +[0x28] No, No, No, No, No, No, No, No, +[0x30] No, No, No, No, No, No, No, No, +[0x38] No, No, No, No, No, No, No, No, +[0x40] No, No, No, No, No, No, No, No, +[0x48] Up, No, No, No, No, No, No, No, +[0x50] No, No, No, No, No, No, No, No, +[0x58] No, No, No, No, No, No, No, No, +[0x60] No, No, No, No, No, No, No, No, +[0x68] No, No, No, No, No, No, No, No, +[0x70] No, No, No, No, No, No, No, No, +[0x78] No, Up, No, No, No, No, No, No, +}; + Rune kbtabaltgr[Nscan] = { [0x00] No, No, No, No, No, No, No, No, @@ -133,17 +173,17 @@ Rune kbtabctrl[Nscan] = { -[0x00] No, '', '', '', '', '', '', '', +[0x00] No, '', '', '', '', '', '', '', [0x08] '', '', '', '', ' ', '', '\b', '\t', [0x10] '', '', '', '', '', '', '', '\t', -[0x18] '', '', '', '', '\n', Ctrl, '', '', -[0x20] '', '', '', '\b', '\n', ' ', ' ', '', -[0x28] '', No, Shift, '', '', '', '', '', +[0x18] '', '', '', '', '\n', Ctrl, '', '', +[0x20] '', '', '', '\b', '\n', ' ', ' ', '', +[0x28] '', No, Shift, '', '', '', '', '', [0x30] '', '', ' ', ' ', '', '', Shift, '\n', -[0x38] Latin, No, Ctrl, '', '', '', '', '', -[0x40] '', '', ' ', ' ', '', '', '', '', -[0x48] '', '', ' ', '', '', '', ' ', '', -[0x50] '', '', '', '', No, No, No, '', +[0x38] Latin, No, Ctrl, '', '', '', '', '', +[0x40] '', '', ' ', ' ', '', '', '', '', +[0x48] '', '', ' ', '', '', '', ' ', '', +[0x50] '', '', '', '', No, No, No, '', [0x58] ' ', No, No, No, No, No, No, No, [0x60] No, No, No, No, No, No, No, No, [0x68] No, No, No, No, No, No, No, No, @@ -211,7 +251,10 @@ return; } - if(kbscan->esc1){ + if(kbscan->esc1 && kbscan->shift){ + c = kbtabshiftesc1[c]; + kbscan->esc1 = 0; + } else if(kbscan->esc1){ c = kbtabesc1[c]; kbscan->esc1 = 0; } else if(kbscan->esc2){ @@ -306,10 +349,10 @@ * to make the VM give up keyboard and mouse focus. * This has the unfortunate side effect that when you * come back into focus, Plan 9 thinks you want to type - * a compose sequence (you just typed alt). + * a compose sequence (you just typed alt). * - * As a clumsy hack around this, we look for ctl-alt - * and don't treat it as the start of a compose sequence. + * As a clumsy hack around this, we look for ctl-alt and + * don't treat it as the start of a compose sequence. */ if(!kbscan->ctl){ kbscan->collecting = 1; @@ -375,9 +418,15 @@ case 3: kbtabaltgr[scanc] = r; break; - case 4: + case 4: kbtabctrl[scanc] = r; break; + case 5: + kbtabctrlesc1[scanc] = r; + break; + case 6: + kbtabshiftesc1[scanc] = r; + break; } } @@ -405,6 +454,12 @@ return 1; case 4: *r = kbtabctrl[*sc]; + return 1; + case 5: + *r = kbtabctrlesc1[*sc]; + return 1; + case 6: + *r = kbtabshiftesc1[*sc]; return 1; } } --- /sys/src/9/pc/ahci.h Mon Nov 5 03:28:32 2012 +++ /sys/src/9/pc/ahci.h Mon Mar 17 23:11:51 2014 @@ -289,5 +289,5 @@ typedef struct { Aport *p; - Aportm *m; + Aportm *pm; } Aportc; --- /sys/src/9/pc/sdiahci.c Thu Mar 13 23:45:35 2014 +++ /sys/src/9/pc/sdiahci.c Mon Mar 17 23:11:51 2014 @@ -285,7 +285,7 @@ p->ci = 1; as.p = p; as.i = 1; - aesleep(c->m, &as, ms); + aesleep(c->pm, &as, ms); if((p->task&1) == 0 && p->ci == 0) return 0; dreg("ahciwait timeout ", c->p); @@ -298,7 +298,7 @@ { uchar *cfis; - cfis = pc->m->ctab->cfis; + cfis = pc->pm->ctab->cfis; memset(cfis, 0, 0x20); cfis[0] = 0x27; cfis[1] = 0x80; @@ -312,10 +312,10 @@ { Alist *list; - list = pc->m->list; + list = pc->pm->list; list->flags = flags | 5; list->len = 0; - list->ctab = PCIWADDR(pc->m->ctab); + list->ctab = PCIWADDR(pc->pm->ctab); list->ctabhi = 0; } @@ -324,7 +324,7 @@ { uchar *c; - if((pc->m->feat & Dnop) == 0) + if((pc->pm->feat & Dnop) == 0) return -1; c = cfissetup(pc); c[2] = 0; @@ -394,7 +394,7 @@ { uchar *c; - if((pc->m->feat&Dsmart) == 0) + if((pc->pm->feat&Dsmart) == 0) return -1; c = cfissetup(pc); c[2] = 0xb0; @@ -424,7 +424,7 @@ c[6] = 0xc2; listsetup(pc, Lwrite); - c = pc->m->fis.r; + c = pc->pm->fis.r; if(ahciwait(pc, 1000) == -1 || pc->p->task & (1|32)){ dprint("ahci: smart fail %#lux\n", pc->p->task); preg(c, 20); @@ -441,7 +441,7 @@ uchar *c; c = cfissetup(pc); - c[2] = pc->m->feat & Dllba? 0xea: 0xe7; + c[2] = pc->pm->feat & Dllba? 0xea: 0xe7; listsetup(pc, Lwrite); if(ahciwait(pc, 60000) == -1 || pc->p->task & (1|32)){ dprint("ahciflushcache: fail %#lux\n", pc->p->task); @@ -495,7 +495,7 @@ listsetup(pc, 1<<16); memset(id, 0, 0x100); /* magic */ - p = &pc->m->ctab->prdt; + p = &pc->pm->ctab->prdt; p->dba = PCIWADDR(id); p->dbahi = 0; p->count = 1<<31 | (0x200-2) | 1; @@ -509,7 +509,7 @@ vlong s; Aportm *pm; - pm = pc->m; + pm = pc->pm; pm->feat = 0; pm->smart = 0; i = 0; @@ -723,7 +723,7 @@ h = d->ctlr->hba; p = d->portc.p; - pm = d->portc.m; + pm = d->portc.pm; if(pm->list == 0){ setupfis(&pm->fis); pm->list = malign(sizeof *pm->list, 1024); @@ -953,7 +953,7 @@ case Devpresent: /* device but no phy comm. */ if((p->sstatus & Intpm) == Intslumber || (p->sstatus & Intpm) == Intpartpwr) - d->state = Dnew; /* slumbering */ + d->state = Dnew; /* slumbering */ else d->state = Derror; break; @@ -970,7 +970,7 @@ diskstates[s0], diskstates[d->state], p->sstatus); /* print pulled message here. */ if(s0 == Dready && d->state != Dready) - idprint("%s: pulled\n", name); + idprint("%s: pulled\n", name); /* wtf? */ if(d->state != Dready) d->portm.flag |= Ferror; ewake = 1; @@ -1088,7 +1088,7 @@ if(d->port->task == 0x80) return -1; - qlock(c->m); + qlock(c->pm); if(setudmamode(c, 5) == -1){ dprint("%s: can't set udma mode\n", name); goto lose; @@ -1103,7 +1103,7 @@ goto lose; } setstate(d, Dready); - qunlock(c->m); + qunlock(c->pm); idprint("%s: %sLBA %,llud sectors: %s %s %s %s\n", d->unit->name, (pm->feat & Dllba? "L": ""), d->sectors, d->model, d->firmware, @@ -1113,7 +1113,7 @@ lose: idprint("%s: can't be initialized\n", d->unit->name); setstate(d, Dnull); - qunlock(c->m); + qunlock(c->pm); return -1; } @@ -2023,7 +2023,7 @@ continue; drive->port = (Aport*)(ctlr->mmio + 0x80*i + 0x100); drive->portc.p = drive->port; - drive->portc.m = &drive->portm; + drive->portc.pm = &drive->portm; drive->driveno = n++; ctlr->drive[drive->driveno] = drive; iadrive[niadrive + drive->driveno] = drive; --- /sys/src/ape/lib/draw/libc.h Sun Dec 25 22:58:41 2005 +++ /sys/src/ape/lib/draw/libc.h Mon Mar 17 22:06:52 2014 @@ -126,6 +126,7 @@ #define readn _READN #define mallocz _MALLOCZ #define iounit _IOUNIT +#define bind _BIND /* assume being called as in event.c */ #define postnote(x, pid, msg) kill(pid, SIGTERM) --- /sys/src/cmd/aan.c Tue Mar 5 22:45:29 2013 +++ /sys/src/cmd/aan.c Mon Mar 17 22:18:19 2014 @@ -68,10 +68,8 @@ static void fromclient(void*); static void fromnet(void*); static Endpoints *getendpoints(char *); -static int getport(char *); static void packhdr(Hdr *, uchar *); static void reconnect(void); -static int sendcommand(ulong, ulong); static void showmsg(int, char *, Buf *); static void synchronize(void); static void timerproc(void *); --- /sys/src/cmd/dict/mkroget Thu Jan 1 01:00:00 1970 +++ /sys/src/cmd/dict/mkroget Mon Mar 17 23:27:31 2014 @@ -0,0 +1,23 @@ +#!/bin/rc + +rtf2txt roget-body.rtf | + sed ' + 1,12d + /^100. /{ + N + s/\n// + p + } + /^388a. /{ + N + s/\n// + p + } + ' > /lib/dict/roget + +mkindex -d roget | + sort -u -t' ' +0f -1 +0 -1 +1n -2 | + sed ' + s/[ ]+$//g + s/ / /g + ' > /lib/dict/rogetindex --- /sys/src/cmd/ip/imap4d/imap4d.c Mon Jul 30 20:21:07 2012 +++ /sys/src/cmd/ip/imap4d/imap4d.c Mon Mar 17 23:41:48 2014 @@ -1074,9 +1074,10 @@ if(uids) uid = "uid "; if(rock.next != nil && rock.next->key == SKCharset){ - if(cistrstr(rock.next->s, "utf-8") != 0 + if(cistrcmp(rock.next->s, "utf-8") != 0 && cistrcmp(rock.next->s, "us-ascii") != 0){ - Bprint(&bout, "%s NO [BADCHARSET] (\"US-ASCII\" \"UTF-8\") %s%s failed\r\n", tg, uid, cmd); + Bprint(&bout, "%s NO [BADCHARSET] (\"US-ASCII\" \"UTF-8\") %s%s failed\r\n", + tg, uid, cmd); checkBox(selected, 0); status(uids, uids); return; --- /sys/src/cmd/mkfile Sun May 6 23:38:02 2007 +++ /sys/src/cmd/mkfile Mon Mar 17 22:11:55 2014 @@ -8,14 +8,14 @@ YFLAGS=-d NOTSYS=sml|dup|.+\..+ -BUGGERED=unix|postscript +BUGGERED=unix OUTOFDATE=old NOMK=$NOTSYS|$BUGGERED|$OUTOFDATE cpuobjtype=`{sed -n 's/^O=//p' /$cputype/mkfile} DIRS=`{ls -l | sed '/^d/!d; s/.* //; /^('$NOMK')$/d'} -APEDIRS=awk bzip2 compress cvs eqn grap gs links-ape lp pic postscript spin \ +APEDIRS=awk bzip2 compress cvs eqn grap gs lp pic postscript spin \ tex troff none:VQ: --- /sys/src/cmd/ssh1/ssh1.c Wed Apr 18 21:37:51 2012 +++ /sys/src/cmd/ssh1/ssh1.c Mon Mar 17 23:34:11 2014 @@ -563,7 +563,8 @@ sendwritemsg(c, buf, n); } sendwritemsg(c, "", 0); - atexitdont(atexitkiller); + if(n >= 0) /* weren't hung up upon? */ + atexitdont(atexitkiller); exits(nil); } --- /sys/src/cmd/unix/drawterm/Makefile Fri Dec 30 00:55:34 2005 +++ /sys/src/cmd/unix/drawterm/Makefile Tue Mar 18 00:38:18 2014 @@ -23,6 +23,7 @@ libdraw/libdraw.a\ gui-$(GUI)/libgui.a\ libc/libc.a\ + libip/libip.a\ # stupid gcc LIBS=$(LIBS1) $(LIBS1) $(LIBS1) libmachdep.a @@ -66,6 +67,9 @@ libc/libc.a: (cd libc; $(MAKE)) + +libip/libip.a: + (cd libip; $(MAKE)) gui-$(GUI)/libgui.a: (cd gui-$(GUI); $(MAKE)) --- /sys/src/cmd/unix/drawterm/cpu.c Thu Aug 27 14:19:25 2009 +++ /sys/src/cmd/unix/drawterm/cpu.c Tue Mar 18 05:28:50 2014 @@ -29,7 +29,7 @@ static char *system; static int cflag; extern int dbg; -extern char* base; // fs base for devroot +extern char* base; // fs base for devroot static char *srvname = "ncpu"; static char *ealgs = "rc4_256 sha1"; @@ -169,14 +169,14 @@ if(mountfactotum() < 0){ if(secstoreserver == nil) secstoreserver = authserver; - if(havesecstore(secstoreserver, user)){ - s = secstorefetch(secstoreserver, user, nil); - if(s){ - if(strlen(s) >= sizeof secstorebuf) - sysfatal("secstore data too big"); - strcpy(secstorebuf, s); - } - } + if(havesecstore(secstoreserver, user)){ + s = secstorefetch(secstoreserver, user, nil); + if(s){ + if(strlen(s) >= sizeof secstorebuf) + sysfatal("secstore data too big"); + strcpy(secstorebuf, s); + } + } } if((err = rexcall(&data, system, srvname))) @@ -560,6 +560,7 @@ if((afd = open("/mnt/factotum/ctl", ORDWR)) >= 0) return p9anyfactotum(fd, afd); + werrstr(""); if(readstr(fd, buf, sizeof buf) < 0) fatal(1, "cannot read p9any negotiation"); @@ -582,8 +583,8 @@ if(write(fd, buf2, strlen(buf2)+1) != strlen(buf2)+1) fatal(1, "cannot write user/domain choice in p9any"); if(v2){ - if(readstr(fd, buf, sizeof buf) != 3) - fatal(1, "cannot read OK in p9any"); + if(readstr(fd, buf, sizeof buf) < 0) + fatal(1, "cannot read OK in p9any: got %d %s", n, buf); if(memcmp(buf, "OK\0", 3) != 0) fatal(1, "did not get OK in p9any"); } --- /sys/src/cmd/unix/drawterm/exportfs/exportfs.c Fri Dec 30 00:55:52 2005 +++ /sys/src/cmd/unix/drawterm/exportfs/exportfs.c Tue Mar 18 05:40:00 2014 @@ -58,7 +58,7 @@ if(messagesize == 0){ messagesize = iounit(netfd); if(messagesize == 0) - messagesize = 8192+IOHDRSZ; + messagesize = 8*8192+IOHDRSZ; } Workq = emallocz(sizeof(Fsrpc)*Nr_workbufs); --- /sys/src/cmd/unix/drawterm/exportfs/exportsrv.c Sun May 21 19:49:49 2006 +++ /sys/src/cmd/unix/drawterm/exportfs/exportsrv.c Tue Mar 18 05:40:00 2014 @@ -16,7 +16,7 @@ int iounit(int x) { - return 8192+IOHDRSZ; + return 8*8192+IOHDRSZ; } void* --- /sys/src/cmd/unix/drawterm/gui-x11/alloc.c Fri Dec 30 00:55:47 2005 +++ /sys/src/cmd/unix/drawterm/gui-x11/alloc.c Thu Jan 1 01:00:00 1970 @@ -1,204 +0,0 @@ -#include -#include -#include -#include -#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(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; ydirty = 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; ypmid, g, xi, xdelta.x, xdelta.y, delta.x, delta.y, Dx(r), Dy(r)); - - if(xtblbit && m->chan == CMAP8) - for(y=r.min.y; yX) != nil){ - xm->dirty = 1; - addrect(&xm->dirtyr, r); - } -} --- /sys/src/cmd/unix/drawterm/gui-x11/cload.c Fri Dec 30 00:55:47 2005 +++ /sys/src/cmd/unix/drawterm/gui-x11/cload.c Thu Jan 1 01:00:00 1970 @@ -1,16 +0,0 @@ -#include -#include -#include -#include -#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; -} --- /sys/src/cmd/unix/drawterm/gui-x11/draw.c Fri Dec 30 00:55:47 2005 +++ /sys/src/cmd/unix/drawterm/gui-x11/draw.c Thu Jan 1 01:00:00 1970 @@ -1,186 +0,0 @@ -#include -#include -#include -#include -#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); -} --- /sys/src/cmd/unix/drawterm/gui-x11/ksym2utf.h Fri Dec 30 00:55:48 2005 +++ /sys/src/cmd/unix/drawterm/gui-x11/ksym2utf.h Thu Jan 1 01:00:00 1970 @@ -1,754 +0,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, -}; --- /sys/src/cmd/unix/drawterm/gui-x11/load.c Fri Dec 30 00:55:48 2005 +++ /sys/src/cmd/unix/drawterm/gui-x11/load.c Thu Jan 1 01:00:00 1970 @@ -1,16 +0,0 @@ -#include -#include -#include -#include -#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; -} --- /sys/src/cmd/unix/drawterm/gui-x11/screen.c Sun May 21 19:49:53 2006 +++ /sys/src/cmd/unix/drawterm/gui-x11/screen.c Thu Jan 1 01:00:00 1970 @@ -1,1168 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "keysym2ucs.h" - -/* - * 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; - - 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; iclass != 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); - - /* - * 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 = InputHint|StateHint; - hints.input = 1; - hints.initial_state = NormalState; - 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){ - /* 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); - 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; -} - --- /sys/src/cmd/unix/drawterm/gui-x11/x11.c Thu Jan 1 01:00:00 1970 +++ /sys/src/cmd/unix/drawterm/gui-x11/x11.c Tue Mar 18 05:39:16 2014 @@ -0,0 +1,1627 @@ +#include "u.h" +#include "lib.h" +#include "dat.h" +#include "fns.h" +#include "error.h" + +#include +#include +#include +#include +#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 +#include +#include +#include +#include +#include +#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 */ +}; + +/* + * 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; ydirty = 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; ypmid, g, xi, xdelta.x, xdelta.y, delta.x, delta.y, Dx(r), Dy(r)); + + if(xtblbit && m->chan == CMAP8) + for(y=r.min.y; yX) != 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; iclass != 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_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: + 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 != Kalt) + 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; + unsigned long 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, 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{ + 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; +} + --- /sys/src/cmd/unix/drawterm/gui-x11/xmem.h Sun May 21 19:49:53 2006 +++ /sys/src/cmd/unix/drawterm/gui-x11/xmem.h Thu Jan 1 01:00:00 1970 @@ -1,60 +0,0 @@ -#define Font XXFont -#define Screen XXScreen -#define Display XXDisplay - -#include -/* #include */ -#include -#include -#include -#include - -#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); --- /sys/src/cmd/unix/drawterm/include/fcall.h Mon Mar 21 19:10:47 2011 +++ /sys/src/cmd/unix/drawterm/include/fcall.h Wed Aug 26 07:44:41 2009 @@ -37,7 +37,7 @@ #define GBIT8(p) ((p)[0]) #define GBIT16(p) ((p)[0]|((p)[1]<<8)) #define GBIT32(p) ((p)[0]|((p)[1]<<8)|((p)[2]<<16)|((p)[3]<<24)) -#define GBIT64(p) ((ulong)((p)[0]|((p)[1]<<8)|((p)[2]<<16)|((p)[3]<<24)) |\ +#define GBIT64(p) ((vlong)((p)[0]|((p)[1]<<8)|((p)[2]<<16)|((p)[3]<<24)) |\ ((vlong)((p)[4]|((p)[5]<<8)|((p)[6]<<16)|((p)[7]<<24)) << 32)) #define PBIT8(p,v) (p)[0]=(v) --- /sys/src/cmd/unix/drawterm/include/ip.h Thu Jan 1 01:00:00 1970 +++ /sys/src/cmd/unix/drawterm/include/ip.h Tue Mar 18 00:37:13 2014 @@ -0,0 +1,38 @@ +enum +{ + IPaddrlen= 16, + IPv4addrlen= 4, + IPv4off= 12, +}; + +uchar* defmask(uchar*); +void maskip(uchar*, uchar*, uchar*); +int eipfmt(Fmt*); +int isv4(uchar*); +vlong parseip(uchar*, char*); +vlong parseipmask(uchar*, char*); +char* v4parseip(uchar*, char*); +char* v4parsecidr(uchar*, uchar*, char*); + +void hnputv(void*, uvlong); +void hnputl(void*, uint); +void hnputs(void*, ushort); +uvlong nhgetv(void*); +uint nhgetl(void*); +ushort nhgets(void*); + +int v6tov4(uchar*, uchar*); +void v4tov6(uchar*, uchar*); + +#define ipcmp(x, y) memcmp(x, y, IPaddrlen) +#define ipmove(x, y) memmove(x, y, IPaddrlen) + +extern uchar IPv4bcast[IPaddrlen]; +extern uchar IPv4bcastobs[IPaddrlen]; +extern uchar IPv4allsys[IPaddrlen]; +extern uchar IPv4allrouter[IPaddrlen]; +extern uchar IPnoaddr[IPaddrlen]; +extern uchar v4prefix[IPaddrlen]; +extern uchar IPallbits[IPaddrlen]; + +#define CLASS(p) ((*(uchar*)(p))>>6) --- /sys/src/cmd/unix/drawterm/include/lib.h Mon Apr 29 23:45:21 2013 +++ /sys/src/cmd/unix/drawterm/include/lib.h Tue Jul 2 06:10:02 2013 @@ -3,6 +3,9 @@ #define listen pm_listen #define sleep ksleep #define wakeup kwakeup +#ifdef strtod +#undef strtod +#endif #define strtod fmtstrtod /* conflicts on some os's */ --- /sys/src/cmd/unix/drawterm/kern/devaudio-sun.c Thu Jan 1 01:00:00 1970 +++ /sys/src/cmd/unix/drawterm/kern/devaudio-sun.c Wed Aug 26 20:01:43 2009 @@ -0,0 +1,268 @@ +/* + * Sun + */ +#include +#include +#include "u.h" +#include "lib.h" +#include "dat.h" +#include "fns.h" +#include "error.h" +#include "devaudio.h" + +enum +{ + Channels = 2, + Rate = 44100, + Bits = 16, +}; + +static char* afn = 0; +static char* cfn = 0; +static int afd = -1; +static int cfd = -1; +static int speed = Rate; +static int needswap = -1; + +static void +audiodevinit(void) +{ + uchar *p; + ushort leorder; + + if ((afn = getenv("AUDIODEV")) == nil) + afn = "/dev/audio"; + cfn = (char*)malloc(strlen(afn) + 3 + 1); + if(cfn == nil) + panic("out of memory"); + strcpy(cfn, afn); + strcat(cfn, "ctl"); + + /* + * Plan 9 /dev/audio is always little endian; + * solaris /dev/audio seems to expect native byte order, + * so on big endian machine (like sparc) we have to swap. + */ + leorder = (ushort) 0x0100; + p = (uchar*)&leorder; + if (p[0] == 0 && p[1] == 1) { + /* little-endian: nothing to do */ + needswap = 0; + } else { + /* big-endian: translate Plan 9 little-endian */ + needswap = 1; + } +} + +/* maybe this should return -1 instead of sysfatal */ +void +audiodevopen(void) +{ + audio_info_t info; + struct audio_device ad; + + if (afn == nil || cfn == nil) + audiodevinit(); + if((afd = open(afn, O_WRONLY)) < 0) + goto err; + if(cfd < 0 && (cfd = open(cfn, O_RDWR)) < 0) + goto err; + + AUDIO_INITINFO(&info); + info.play.precision = Bits; + info.play.channels = Channels; + info.play.sample_rate = speed; + info.play.encoding = AUDIO_ENCODING_LINEAR; + if(ioctl(afd, AUDIO_SETINFO, &info) < 0) + goto err; + + return; + +err: + if(afd >= 0) + close(afd); + afd = -1; + if(cfd >= 0) + close(cfd); + cfd = -1; + oserror(); +} + +void +audiodevclose(void) +{ + if(afd >= 0) + close(afd); + if(cfd >= 0) + close(cfd); + afd = -1; + cfd = -1; +} + +static double +fromsun(double val, double min, double max) +{ + return (val-min) / (max-min); +} + +static double +tosun(double val, double min, double max) +{ + return val*(max-min) + min; +} + +static void +setvolbal(double left, double right) +{ + audio_info_t info; + double vol, bal; + + if (left < 0 || right < 0) { + /* should not happen */ + return; + } else if (left == right) { + vol = tosun(left/100.0, AUDIO_MIN_GAIN, AUDIO_MAX_GAIN); + bal = AUDIO_MID_BALANCE; + } else if (left < right) { + vol = tosun(right/100.0, AUDIO_MIN_GAIN, AUDIO_MAX_GAIN); + bal = tosun(1.0 - left/right, AUDIO_MID_BALANCE, AUDIO_RIGHT_BALANCE); + } else if (right < left) { + vol = tosun(left/100.0, AUDIO_MIN_GAIN, AUDIO_MAX_GAIN); + bal = tosun(1.0 - right/left, AUDIO_MID_BALANCE, AUDIO_LEFT_BALANCE); + } + AUDIO_INITINFO(&info); + info.play.gain = (long)(vol+0.5); + info.play.balance = (long)(bal+0.5); + if(ioctl(cfd, AUDIO_SETINFO, &info) < 0) + oserror(); +} + +static void +getvolbal(int *left, int *right) +{ + audio_info_t info; + double gain, bal, vol, l, r; + + AUDIO_INITINFO(&info); + if (ioctl(cfd, AUDIO_GETINFO, &info) < 0) + oserror(); + + gain = info.play.gain; + bal = info.play.balance; + vol = fromsun(gain, AUDIO_MIN_GAIN, AUDIO_MAX_GAIN) * 100.0; + + if (bal == AUDIO_MID_BALANCE) { + l = r = vol; + } else if (bal < AUDIO_MID_BALANCE) { + l = vol; + r = vol * (1.0 - fromsun(bal, AUDIO_MID_BALANCE, AUDIO_LEFT_BALANCE)); + } else { + r = vol; + l = vol * (1.0 - fromsun(bal, AUDIO_MID_BALANCE, AUDIO_RIGHT_BALANCE)); + } + *left = (long)(l+0.5); + *right = (long)(r+0.5); + return; +} + +void +audiodevsetvol(int what, int left, int right) +{ + audio_info_t info; + ulong x; + int l, r; + + if (afn == nil || cfn == nil) + audiodevinit(); + if(cfd < 0 && (cfd = open(cfn, O_RDWR)) < 0) { + cfd = -1; + oserror(); + } + + if(what == Vspeed){ + x = left; + AUDIO_INITINFO(&info); + info.play.sample_rate = x; + if(ioctl(cfd, AUDIO_SETINFO, &info) < 0) + oserror(); + speed = x; + return; + } + if(what == Vaudio){ + getvolbal(&l, &r); + if (left < 0) + setvolbal(l, right); + else if (right < 0) + setvolbal(left, r); + else + setvolbal(left, right); + return; + } +} + +void +audiodevgetvol(int what, int *left, int *right) +{ + audio_info_t info; + + if (afn == nil || cfn == nil) + audiodevinit(); + if(cfd < 0 && (cfd = open(cfn, O_RDWR)) < 0) { + cfd = -1; + oserror(); + } + switch(what) { + case Vspeed: + *left = *right = speed; + break; + case Vaudio: + getvolbal(left, right); + break; + case Vtreb: + case Vbass: + *left = *right = 50; + break; + default: + *left = *right = 0; + } +} + + +static uchar *buf = 0; +static int nbuf = 0; + +int +audiodevwrite(void *v, int n) +{ + int i, m, tot; + uchar *p; + + if (needswap) { + if (nbuf < n) { + buf = (uchar*)erealloc(buf, n); + if(buf == nil) + panic("out of memory"); + nbuf = n; + } + + p = (uchar*)v; + for(i=0; i+1aux; + fspath(c, 0, old); + if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) { + if(chmod(old, d.mode&0777) < 0) + error(strerror(errno)); + uif->mode &= ~0777; + uif->mode |= d.mode&0777; + } + if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) { fspath(c, 0, old); strcpy(new, old); @@ -434,13 +442,6 @@ error(strerror(errno)); } - fspath(c, 0, old); - if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) { - if(chmod(old, d.mode&0777) < 0) - error(strerror(errno)); - uif->mode &= ~0777; - uif->mode |= d.mode&0777; - } /* p = name2pass(gid, d.gid); if(p == 0) --- /sys/src/cmd/unix/drawterm/kern/devip-posix.c Fri Dec 30 00:59:26 2005 +++ /sys/src/cmd/unix/drawterm/kern/devip-posix.c Tue Jul 2 06:10:02 2013 @@ -3,12 +3,14 @@ #include #include #include +#include #include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" +#include "ip.h" #include "devip.h" @@ -16,6 +18,26 @@ #undef accept #undef bind +static int +family(unsigned char *addr) +{ + if(isv4(addr)) + return AF_INET; + return AF_INET6; +} + +static int +addrlen(struct sockaddr_storage *ss) +{ + switch(ss->ss_family){ + case AF_INET: + return sizeof(struct sockaddr_in); + case AF_INET6: + return sizeof(struct sockaddr_in6); + } + return 0; +} + void osipinit(void) { @@ -26,7 +48,7 @@ } int -so_socket(int type) +so_socket(int type, unsigned char *addr) { int fd, one; @@ -41,7 +63,7 @@ break; } - fd = socket(AF_INET, type, 0); + fd = socket(family(addr), type, 0); if(fd < 0) oserror(); @@ -54,36 +76,52 @@ return fd; } - void -so_connect(int fd, unsigned long raddr, unsigned short rport) +so_connect(int fd, unsigned char *raddr, unsigned short rport) { - struct sockaddr_in sin; + struct sockaddr_storage ss; + + memset(&ss, 0, sizeof(ss)); + + ss.ss_family = family(raddr); - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - hnputs(&sin.sin_port, rport); - hnputl(&sin.sin_addr.s_addr, raddr); + switch(ss.ss_family){ + case AF_INET: + hnputs(&((struct sockaddr_in*)&ss)->sin_port, rport); + v6tov4((unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr, raddr); + break; + case AF_INET6: + hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, rport); + memcpy(&((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, raddr, sizeof(struct in6_addr)); + break; + } - if(connect(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) + if(connect(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0) oserror(); } void -so_getsockname(int fd, unsigned long *laddr, unsigned short *lport) +so_getsockname(int fd, unsigned char *laddr, unsigned short *lport) { socklen_t len; - struct sockaddr_in sin; + struct sockaddr_storage ss; - len = sizeof(sin); - if(getsockname(fd, (struct sockaddr*)&sin, &len) < 0) + len = sizeof(ss); + if(getsockname(fd, (struct sockaddr*)&ss, &len) < 0) oserror(); - if(sin.sin_family != AF_INET || len != sizeof(sin)) - error("not AF_INET"); - - *laddr = nhgetl(&sin.sin_addr.s_addr); - *lport = nhgets(&sin.sin_port); + switch(ss.ss_family){ + case AF_INET: + v4tov6(laddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr); + *lport = nhgets(&((struct sockaddr_in*)&ss)->sin_port); + break; + case AF_INET6: + memcpy(laddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr)); + *lport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port); + break; + default: + error("not AF_INET or AF_INET6"); + } } void @@ -94,30 +132,37 @@ } int -so_accept(int fd, unsigned long *raddr, unsigned short *rport) +so_accept(int fd, unsigned char *raddr, unsigned short *rport) { int nfd; socklen_t len; - struct sockaddr_in sin; + struct sockaddr_storage ss; - len = sizeof(sin); - nfd = accept(fd, (struct sockaddr*)&sin, &len); + len = sizeof(ss); + nfd = accept(fd, (struct sockaddr*)&ss, &len); if(nfd < 0) oserror(); - if(sin.sin_family != AF_INET || len != sizeof(sin)) - error("not AF_INET"); - - *raddr = nhgetl(&sin.sin_addr.s_addr); - *rport = nhgets(&sin.sin_port); + switch(ss.ss_family){ + case AF_INET: + v4tov6(raddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr); + *rport = nhgets(&((struct sockaddr_in*)&ss)->sin_port); + break; + case AF_INET6: + memcpy(raddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr)); + *rport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port); + break; + default: + error("not AF_INET or AF_INET6"); + } return nfd; } void -so_bind(int fd, int su, unsigned short port) +so_bind(int fd, int su, unsigned short port, unsigned char *addr) { int i, one; - struct sockaddr_in sin; + struct sockaddr_storage ss; one = 1; if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0){ @@ -127,21 +172,37 @@ if(su) { for(i = 600; i < 1024; i++) { - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = i; + memset(&ss, 0, sizeof(ss)); + ss.ss_family = family(addr); + + switch(ss.ss_family){ + case AF_INET: + ((struct sockaddr_in*)&ss)->sin_port = i; + break; + case AF_INET6: + ((struct sockaddr_in6*)&ss)->sin6_port = i; + break; + } - if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) >= 0) + if(bind(fd, (struct sockaddr*)&ss, addrlen(&ss)) >= 0) return; } oserror(); } - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - hnputs(&sin.sin_port, port); + memset(&ss, 0, sizeof(ss)); + ss.ss_family = family(addr); - if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) + switch(ss.ss_family){ + case AF_INET: + hnputs(&((struct sockaddr_in*)&ss)->sin_port, port); + break; + case AF_INET6: + hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, port); + break; + } + + if(bind(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0) oserror(); } @@ -170,16 +231,28 @@ char* hostlookup(char *host) { - char buf[100]; + char buf[INET6_ADDRSTRLEN]; uchar *p; struct hostent *he; + struct addrinfo *result; he = gethostbyname(host); if(he != 0 && he->h_addr_list[0]) { p = (uchar*)he->h_addr_list[0]; sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]); + } else if(getaddrinfo(host, NULL, NULL, &result) == 0) { + switch (result->ai_family) { + case AF_INET: + inet_ntop(AF_INET, &((struct sockaddr_in*)result->ai_addr)->sin_addr, buf, sizeof(buf)); + break; + case AF_INET6: + inet_ntop(AF_INET6, &((struct sockaddr_in6*)result->ai_addr)->sin6_addr, buf, sizeof(buf)); + break; + default: + return nil; + } } else - strcpy(buf, host); + return nil; return strdup(buf); } --- /sys/src/cmd/unix/drawterm/kern/devip-win32.c Wed Aug 26 20:39:33 2009 +++ /sys/src/cmd/unix/drawterm/kern/devip-win32.c Tue Jul 2 06:10:02 2013 @@ -1,9 +1,11 @@ #include +#include #include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" +#include "ip.h" #include "devip.h" @@ -15,6 +17,26 @@ #undef accept #undef bind +static int +family(unsigned char *addr) +{ + if(isv4(addr)) + return AF_INET; + return AF_INET6; +} + +static int +addrlen(struct sockaddr_storage *ss) +{ + switch(ss->ss_family){ + case AF_INET: + return sizeof(struct sockaddr_in); + case AF_INET6: + return sizeof(struct sockaddr_in6); + } + return 0; +} + void osipinit(void) { @@ -29,7 +51,7 @@ } int -so_socket(int type) +so_socket(int type, unsigned char *addr) { int fd, one; @@ -44,7 +66,7 @@ break; } - fd = socket(AF_INET, type, 0); + fd = socket(family(addr), type, 0); if(fd < 0) oserror(); @@ -59,34 +81,51 @@ void -so_connect(int fd, unsigned long raddr, unsigned short rport) +so_connect(int fd, unsigned char *raddr, unsigned short rport) { - struct sockaddr_in sin; + struct sockaddr_storage ss; - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - hnputs(&sin.sin_port, rport); - hnputl(&sin.sin_addr.s_addr, raddr); + memset(&ss, 0, sizeof(ss)); - if(connect(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) + ss.ss_family = family(raddr); + + switch(ss.ss_family){ + case AF_INET: + hnputs(&((struct sockaddr_in*)&ss)->sin_port, rport); + v6tov4((unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr, raddr); + break; + case AF_INET6: + hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, rport); + memcpy(&((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, raddr, sizeof(struct in6_addr)); + break; + } + + if(connect(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0) oserror(); } void -so_getsockname(int fd, unsigned long *laddr, unsigned short *lport) +so_getsockname(int fd, unsigned char *laddr, unsigned short *lport) { int len; - struct sockaddr_in sin; + struct sockaddr_storage ss; - len = sizeof(sin); - if(getsockname(fd, (struct sockaddr*)&sin, &len) < 0) + len = sizeof(ss); + if(getsockname(fd, (struct sockaddr*)&ss, &len) < 0) oserror(); - if(sin.sin_family != AF_INET || len != sizeof(sin)) - error("not AF_INET"); - - *laddr = nhgetl(&sin.sin_addr.s_addr); - *lport = nhgets(&sin.sin_port); + switch(ss.ss_family){ + case AF_INET: + v4tov6(laddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr); + *lport = nhgets(&((struct sockaddr_in*)&ss)->sin_port); + break; + case AF_INET6: + memcpy(laddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr)); + *lport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port); + break; + default: + error("not AF_INET or AF_INET6"); + } } void @@ -97,53 +136,77 @@ } int -so_accept(int fd, unsigned long *raddr, unsigned short *rport) +so_accept(int fd, unsigned char *raddr, unsigned short *rport) { - int nfd, len; - struct sockaddr_in sin; + int nfd; + int len; + struct sockaddr_storage ss; - len = sizeof(sin); - nfd = accept(fd, (struct sockaddr*)&sin, &len); + len = sizeof(ss); + nfd = accept(fd, (struct sockaddr*)&ss, &len); if(nfd < 0) oserror(); - if(sin.sin_family != AF_INET || len != sizeof(sin)) - error("not AF_INET"); - - *raddr = nhgetl(&sin.sin_addr.s_addr); - *rport = nhgets(&sin.sin_port); + switch(ss.ss_family){ + case AF_INET: + v4tov6(raddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr); + *rport = nhgets(&((struct sockaddr_in*)&ss)->sin_port); + break; + case AF_INET6: + memcpy(raddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr)); + *rport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port); + break; + default: + error("not AF_INET or AF_INET6"); + } return nfd; } void -so_bind(int fd, int su, unsigned short port) +so_bind(int fd, int su, unsigned short port, unsigned char *addr) { int i, one; - struct sockaddr_in sin; + struct sockaddr_storage ss; one = 1; if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0){ oserrstr(); - print("setsockopt: %s", up->errstr); + print("setsockopt: %r"); } if(su) { for(i = 600; i < 1024; i++) { - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = i; + memset(&ss, 0, sizeof(ss)); + ss.ss_family = family(addr); + + switch(ss.ss_family){ + case AF_INET: + ((struct sockaddr_in*)&ss)->sin_port = i; + break; + case AF_INET6: + ((struct sockaddr_in6*)&ss)->sin6_port = i; + break; + } - if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) >= 0) + if(bind(fd, (struct sockaddr*)&ss, addrlen(&ss)) >= 0) return; } oserror(); } - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - hnputs(&sin.sin_port, port); + memset(&ss, 0, sizeof(ss)); + ss.ss_family = family(addr); + + switch(ss.ss_family){ + case AF_INET: + hnputs(&((struct sockaddr_in*)&ss)->sin_port, port); + break; + case AF_INET6: + hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, port); + break; + } - if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) + if(bind(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0) oserror(); } @@ -174,7 +237,7 @@ { char buf[100]; uchar *p; - HOSTENT *he; + struct hostent *he; he = gethostbyname(host); if(he != 0 && he->h_addr_list[0]) { --- /sys/src/cmd/unix/drawterm/kern/devip.c Sun May 21 19:50:04 2006 +++ /sys/src/cmd/unix/drawterm/kern/devip.c Tue Mar 18 00:38:35 2014 @@ -3,14 +3,10 @@ #include "dat.h" #include "fns.h" #include "error.h" +#include "ip.h" #include "devip.h" -void hnputl(void *p, unsigned long v); -void hnputs(void *p, unsigned short v); -unsigned long nhgetl(void *p); -unsigned short nhgets(void *p); -unsigned long parseip(char *to, char *from); void csclose(Chan*); long csread(Chan*, void*, long, vlong); long cswrite(Chan*, void*, long, vlong); @@ -37,6 +33,7 @@ #define CONV(x) ((int)(((x).path >> 4)&0xfff)) #define PROTO(x) ((int)(((x).path >> 16)&0xff)) #define QID(p, c, y) (((p)<<16) | ((c)<<4) | (y)) +#define ipzero(x) memset(x, 0, IPaddrlen) typedef struct Proto Proto; typedef struct Conv Conv; @@ -48,9 +45,9 @@ int perm; char owner[KNAMELEN]; char* state; - ulong laddr; + uchar laddr[IPaddrlen]; ushort lport; - ulong raddr; + uchar raddr[IPaddrlen]; ushort rport; int restricted; char cerr[KNAMELEN]; @@ -71,7 +68,6 @@ static int np; static Proto proto[MAXPROTO]; -int eipfmt(Fmt*); static Conv* protoclone(Proto*, char*, int); static void setladdr(Conv*); @@ -222,7 +218,7 @@ ipopen(Chan *c, int omode) { Proto *p; - ulong raddr; + uchar raddr[IPaddrlen]; ushort rport; int perm, sfd; Conv *cv, *lcv; @@ -286,13 +282,13 @@ case Qlisten: p = &proto[PROTO(c->qid)]; lcv = p->conv[CONV(c->qid)]; - sfd = so_accept(lcv->sfd, &raddr, &rport); + sfd = so_accept(lcv->sfd, raddr, &rport); cv = protoclone(p, up->user, sfd); if(cv == 0) { close(sfd); error(Enodev); } - cv->raddr = raddr; + ipmove(cv->raddr, raddr); cv->rport = rport; setladdr(cv); cv->state = "Established"; @@ -324,8 +320,8 @@ strcpy(cc->owner, "network"); cc->perm = 0666; cc->state = "Closed"; - cc->laddr = 0; - cc->raddr = 0; + ipzero(cc->laddr); + ipzero(cc->raddr); cc->lport = 0; cc->rport = 0; close(cc->sfd); @@ -339,7 +335,7 @@ int r; Conv *c; Proto *x; - uchar ip[4]; + uchar ip[IPaddrlen]; char buf[128], *p; /*print("ipread %s %lux\n", c2name(ch), (long)ch->qid.path);*/ @@ -358,12 +354,12 @@ return readstr(offset, p, n, buf); case Qremote: c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)]; - hnputl(ip, c->raddr); + ipmove(ip, c->raddr); sprint(buf, "%I!%d\n", ip, c->rport); return readstr(offset, p, n, buf); case Qlocal: c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)]; - hnputl(ip, c->laddr); + ipmove(ip, c->laddr); sprint(buf, "%I!%d\n", ip, c->lport); return readstr(offset, p, n, buf); case Qstatus: @@ -386,7 +382,7 @@ static void setladdr(Conv *c) { - so_getsockname(c->sfd, &c->laddr, &c->lport); + so_getsockname(c->sfd, c->laddr, &c->lport); } static void @@ -395,23 +391,27 @@ if(c->restricted == 0 && c->lport == 0) return; - so_bind(c->sfd, c->restricted, c->lport); + if(c->sfd == -1) + c->sfd = so_socket(c->p->stype, c->laddr); + + so_bind(c->sfd, c->restricted, c->lport, c->laddr); } static void setladdrport(Conv *c, char *str) { - char *p, addr[4]; + char *p; + uchar addr[IPaddrlen]; p = strchr(str, '!'); if(p == 0) { p = str; - c->laddr = 0; + ipzero(c->laddr); } else { *p++ = 0; parseip(addr, str); - c->laddr = nhgetl((uchar*)addr); + ipmove(c->laddr, addr); } if(*p == '*') c->lport = 0; @@ -424,14 +424,15 @@ static char* setraddrport(Conv *c, char *str) { - char *p, addr[4]; + char *p; + uchar addr[IPaddrlen]; p = strchr(str, '!'); if(p == 0) return "malformed address"; *p++ = 0; parseip(addr, str); - c->raddr = nhgetl((uchar*)addr); + ipmove(c->raddr, addr); c->rport = atoi(p); p = strchr(p, '!'); if(p) { @@ -480,6 +481,8 @@ setlport(c); break; } + if(c->sfd == -1) + c->sfd = so_socket(c->p->stype, c->raddr); so_connect(c->sfd, c->raddr, c->rport); setladdr(c); c->state = "Established"; @@ -565,13 +568,11 @@ c->perm = 0660; c->state = "Closed"; c->restricted = 0; - c->laddr = 0; - c->raddr = 0; + ipzero(c->laddr); + ipzero(c->raddr); c->lport = 0; c->rport = 0; c->sfd = nfd; - if(nfd == -1) - c->sfd = so_socket(p->stype); unlock(&c->r.lk); unlock(&p->l); @@ -579,145 +580,6 @@ return c; } -enum -{ - Isprefix= 16, -}; - -uchar prefixvals[256] = -{ -/*0x00*/ 0 | Isprefix, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x80*/ 1 | Isprefix, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0xA0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0xB0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0xC0*/ 2 | Isprefix, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0xD0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0xE0*/ 3 | Isprefix, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0xF0*/ 4 | Isprefix, - 0, 0, 0, 0, 0, 0, 0, -/*0xF8*/ 5 | Isprefix, - 0, 0, 0, -/*0xFC*/ 6 | Isprefix, - 0, -/*0xFE*/ 7 | Isprefix, -/*0xFF*/ 8 | Isprefix, -}; - -int -eipfmt(Fmt *f) -{ - char buf[5*8]; - static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux"; - static char *ifmt = "%d.%d.%d.%d"; - uchar *p, ip[16]; - ulong ul; - - switch(f->r) { - case 'E': /* Ethernet address */ - p = va_arg(f->args, uchar*); - snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]); - return fmtstrcpy(f, buf); - - case 'I': - ul = va_arg(f->args, ulong); - hnputl(ip, ul); - snprint(buf, sizeof buf, ifmt, ip[0], ip[1], ip[2], ip[3]); - return fmtstrcpy(f, buf); - } - return fmtstrcpy(f, "(eipfmt)"); -} - -void -hnputl(void *p, unsigned long v) -{ - unsigned char *a; - - a = p; - a[0] = v>>24; - a[1] = v>>16; - a[2] = v>>8; - a[3] = v; -} - -void -hnputs(void *p, unsigned short v) -{ - unsigned char *a; - - a = p; - a[0] = v>>8; - a[1] = v; -} - -unsigned long -nhgetl(void *p) -{ - unsigned char *a; - a = p; - return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|(a[3]<<0); -} - -unsigned short -nhgets(void *p) -{ - unsigned char *a; - a = p; - return (a[0]<<8)|(a[1]<<0); -} - -#define CLASS(p) ((*(unsigned char*)(p))>>6) - -unsigned long -parseip(char *to, char *from) -{ - int i; - char *p; - - p = from; - memset(to, 0, 4); - for(i = 0; i < 4 && *p; i++){ - to[i] = strtoul(p, &p, 10); - if(*p != '.' && *p != 0){ - memset(to, 0, 4); - return 0; - } - if(*p == '.') - p++; - } - switch(CLASS(to)){ - case 0: /* class A - 1 byte net */ - case 1: - if(i == 3){ - to[3] = to[2]; - to[2] = to[1]; - to[1] = 0; - } else if (i == 2){ - to[3] = to[1]; - to[1] = 0; - } - break; - case 2: /* class B - 2 byte net */ - if(i == 3){ - to[3] = to[2]; - to[2] = 0; - } - break; - } - return nhgetl(to); -} - void csclose(Chan *c) { @@ -856,23 +718,17 @@ return 0; } -static ulong -lookuphost(char *s) +static int +lookuphost(char *s, uchar *to) { - char to[4]; - ulong ip; - - memset(to, 0, sizeof to); - parseip(to, s); - ip = nhgetl(to); - if(ip != 0) - return ip; - if((s = hostlookup(s)) == nil) + ipzero(to); + if(parseip(to, s) != -1) return 0; + if((s = hostlookup(s)) == nil) + return -1; parseip(to, s); - ip = nhgetl(to); free(s); - return ip; + return 0; } long @@ -880,7 +736,7 @@ { char *f[4]; char *s, *ns; - ulong ip; + uchar ip[IPaddrlen]; int nf, port; s = malloc(n+1); @@ -900,8 +756,7 @@ if(port <= 0) error("no translation for port found"); - ip = lookuphost(f[1]); - if(ip == 0) + if(lookuphost(f[1], ip) < 0) error("no translation for host found"); ns = smprint("/net/%s/clone %I!%d", f[0], ip, port); --- /sys/src/cmd/unix/drawterm/kern/devip.h Fri Dec 30 00:59:26 2005 +++ /sys/src/cmd/unix/drawterm/kern/devip.h Tue Mar 18 00:38:35 2014 @@ -4,14 +4,14 @@ S_UDP }; -int so_socket(int type); -void so_connect(int, unsigned long, unsigned short); -void so_getsockname(int, unsigned long*, unsigned short*); -void so_bind(int, int, unsigned short); +int so_socket(int, unsigned char*); +void so_connect(int, unsigned char*, unsigned short); +void so_getsockname(int, unsigned char*, unsigned short*); +void so_bind(int, int, unsigned short, unsigned char*); void so_listen(int); int so_send(int, void*, int, int); int so_recv(int, void*, int, int); -int so_accept(int, unsigned long*, unsigned short*); +int so_accept(int, unsigned char*, unsigned short*); int so_getservbyname(char*, char*, char*); int so_gethostbyname(char*, char**, int); --- /sys/src/cmd/unix/drawterm/kern/fns.h Mon May 22 01:33:37 2006 +++ /sys/src/cmd/unix/drawterm/kern/fns.h Tue Mar 18 00:38:35 2014 @@ -375,12 +375,6 @@ Segment* dupseg(Segment**, int, int); Segment* newseg(int, ulong, ulong); Segment* seg(Proc*, ulong, int); -void hnputv(void*, vlong); -void hnputl(void*, ulong); -void hnputs(void*, ushort); -vlong nhgetv(void*); -ulong nhgetl(void*); -ushort nhgets(void*); ulong ticks(void); void osproc(Proc*); void osnewproc(Proc*); --- /sys/src/cmd/unix/drawterm/libip/Makefile Thu Jan 1 01:00:00 1970 +++ /sys/src/cmd/unix/drawterm/libip/Makefile Tue Mar 18 00:37:26 2014 @@ -0,0 +1,19 @@ +ROOT=.. +include ../Make.config +LIB=libip.a + +OFILES=\ + eipfmt.$O\ + parseip.$O\ + classmask.$O\ + bo.$O\ + ipaux.$O\ + +default: $(LIB) +$(LIB): $(OFILES) + $(AR) r $(LIB) $(OFILES) + $(RANLIB) $(LIB) + +%.$O: %.c + $(CC) $(CFLAGS) $*.c + --- /sys/src/cmd/unix/drawterm/libip/bo.c Thu Jan 1 01:00:00 1970 +++ /sys/src/cmd/unix/drawterm/libip/bo.c Tue Mar 18 00:37:26 2014 @@ -0,0 +1,77 @@ +#include +#include +#include + +void +hnputv(void *p, uvlong v) +{ + uchar *a; + + a = p; + a[0] = v>>56; + a[1] = v>>48; + a[2] = v>>40; + a[3] = v>>32; + a[4] = v>>24; + a[5] = v>>16; + a[6] = v>>8; + a[7] = v; +} + +void +hnputl(void *p, uint v) +{ + uchar *a; + + a = p; + a[0] = v>>24; + a[1] = v>>16; + a[2] = v>>8; + a[3] = v; +} + +void +hnputs(void *p, ushort v) +{ + uchar *a; + + a = p; + a[0] = v>>8; + a[1] = v; +} + +uvlong +nhgetv(void *p) +{ + uchar *a; + uvlong v; + + a = p; + v = (uvlong)a[0]<<56; + v |= (uvlong)a[1]<<48; + v |= (uvlong)a[2]<<40; + v |= (uvlong)a[3]<<32; + v |= a[4]<<24; + v |= a[5]<<16; + v |= a[6]<<8; + v |= a[7]<<0; + return v; +} + +uint +nhgetl(void *p) +{ + uchar *a; + + a = p; + return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|(a[3]<<0); +} + +ushort +nhgets(void *p) +{ + uchar *a; + + a = p; + return (a[0]<<8)|(a[1]<<0); +} --- /sys/src/cmd/unix/drawterm/libip/classmask.c Thu Jan 1 01:00:00 1970 +++ /sys/src/cmd/unix/drawterm/libip/classmask.c Tue Mar 18 00:37:26 2014 @@ -0,0 +1,86 @@ +#include +#include +#include + +static uchar classmask[4][16] = { + 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0x00,0x00,0x00, + 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0x00,0x00,0x00, + 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0x00,0x00, + 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0x00, +}; + +static uchar v6loopback[IPaddrlen] = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0x01 +}; + +static uchar v6linklocal[IPaddrlen] = { + 0xfe, 0x80, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; +static uchar v6linklocalmask[IPaddrlen] = { + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; +static int v6llpreflen = 8; /* link-local prefix length in bytes */ + +static uchar v6multicast[IPaddrlen] = { + 0xff, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; +static uchar v6multicastmask[IPaddrlen] = { + 0xff, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; +static int v6mcpreflen = 1; /* multicast prefix length */ + +static uchar v6solicitednode[IPaddrlen] = { + 0xff, 0x02, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0x01, + 0xff, 0, 0, 0 +}; +static uchar v6solicitednodemask[IPaddrlen] = { + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0x0, 0x0, 0x0 +}; +static int v6snpreflen = 13; + +uchar* +defmask(uchar *ip) +{ + if(isv4(ip)) + return classmask[ip[IPv4off]>>6]; + else { + if(ipcmp(ip, v6loopback) == 0) + return IPallbits; + else if(memcmp(ip, v6linklocal, v6llpreflen) == 0) + return v6linklocalmask; + else if(memcmp(ip, v6solicitednode, v6snpreflen) == 0) + return v6solicitednodemask; + else if(memcmp(ip, v6multicast, v6mcpreflen) == 0) + return v6multicastmask; + return IPallbits; + } +} + +void +maskip(uchar *from, uchar *mask, uchar *to) +{ + int i; + + for(i = 0; i < IPaddrlen; i++) + to[i] = from[i] & mask[i]; +} --- /sys/src/cmd/unix/drawterm/libip/eipfmt.c Thu Jan 1 01:00:00 1970 +++ /sys/src/cmd/unix/drawterm/libip/eipfmt.c Tue Mar 18 00:37:26 2014 @@ -0,0 +1,109 @@ +#include +#include +#include + +enum +{ + Isprefix= 16, +}; + +uchar prefixvals[256] = +{ +[0x00] 0 | Isprefix, +[0x80] 1 | Isprefix, +[0xC0] 2 | Isprefix, +[0xE0] 3 | Isprefix, +[0xF0] 4 | Isprefix, +[0xF8] 5 | Isprefix, +[0xFC] 6 | Isprefix, +[0xFE] 7 | Isprefix, +[0xFF] 8 | Isprefix, +}; + +int +eipfmt(Fmt *f) +{ + char buf[5*8]; + static char *efmt = "%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux"; + static char *ifmt = "%d.%d.%d.%d"; + uchar *p, ip[16]; + ulong *lp; + ushort s; + int i, j, n, eln, eli; + + switch(f->r) { + case 'E': /* Ethernet address */ + p = va_arg(f->args, uchar*); + snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]); + return fmtstrcpy(f, buf); + + case 'I': /* Ip address */ + p = va_arg(f->args, uchar*); +common: + if(memcmp(p, v4prefix, 12) == 0){ + snprint(buf, sizeof buf, ifmt, p[12], p[13], p[14], p[15]); + return fmtstrcpy(f, buf); + } + + /* find longest elision */ + eln = eli = -1; + for(i = 0; i < 16; i += 2){ + for(j = i; j < 16; j += 2) + if(p[j] != 0 || p[j+1] != 0) + break; + if(j > i && j - i > eln){ + eli = i; + eln = j - i; + } + } + + /* print with possible elision */ + n = 0; + for(i = 0; i < 16; i += 2){ + if(i == eli){ + n += sprint(buf+n, "::"); + i += eln; + if(i >= 16) + break; + } else if(i != 0) + n += sprint(buf+n, ":"); + s = (p[i]<<8) + p[i+1]; + n += sprint(buf+n, "%ux", s); + } + return fmtstrcpy(f, buf); + + case 'i': /* v6 address as 4 longs */ + lp = va_arg(f->args, ulong*); + for(i = 0; i < 4; i++) + hnputl(ip+4*i, *lp++); + p = ip; + goto common; + + case 'V': /* v4 ip address */ + p = va_arg(f->args, uchar*); + snprint(buf, sizeof buf, ifmt, p[0], p[1], p[2], p[3]); + return fmtstrcpy(f, buf); + + case 'M': /* ip mask */ + p = va_arg(f->args, uchar*); + + /* look for a prefix mask */ + for(i = 0; i < 16; i++) + if(p[i] != 0xff) + break; + if(i < 16){ + if((prefixvals[p[i]] & Isprefix) == 0) + goto common; + for(j = i+1; j < 16; j++) + if(p[j] != 0) + goto common; + n = 8*i + (prefixvals[p[i]] & ~Isprefix); + } else + n = 8*16; + + /* got one, use /xx format */ + snprint(buf, sizeof buf, "/%d", n); + return fmtstrcpy(f, buf); + } + return fmtstrcpy(f, "(eipfmt)"); +} --- /sys/src/cmd/unix/drawterm/libip/ipaux.c Thu Jan 1 01:00:00 1970 +++ /sys/src/cmd/unix/drawterm/libip/ipaux.c Tue Mar 18 00:37:26 2014 @@ -0,0 +1,102 @@ +#include +#include +#include + +/* + * well known IP addresses + */ +uchar IPv4bcast[IPaddrlen] = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff +}; +uchar IPv4allsys[IPaddrlen] = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0xff, 0xff, + 0xe0, 0, 0, 0x01 +}; +uchar IPv4allrouter[IPaddrlen] = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0xff, 0xff, + 0xe0, 0, 0, 0x02 +}; +uchar IPallbits[IPaddrlen] = { + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff +}; +uchar IPnoaddr[IPaddrlen]; + +/* + * prefix of all v4 addresses + */ +uchar v4prefix[IPaddrlen] = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0xff, 0xff, + 0, 0, 0, 0 +}; + +int +isv4(uchar *ip) +{ + return memcmp(ip, v4prefix, IPv4off) == 0; +} + +/* + * the following routines are unrolled with no memset's to speed + * up the usual case + */ +void +v4tov6(uchar *v6, uchar *v4) +{ + v6[0] = 0; + v6[1] = 0; + v6[2] = 0; + v6[3] = 0; + v6[4] = 0; + v6[5] = 0; + v6[6] = 0; + v6[7] = 0; + v6[8] = 0; + v6[9] = 0; + v6[10] = 0xff; + v6[11] = 0xff; + v6[12] = v4[0]; + v6[13] = v4[1]; + v6[14] = v4[2]; + v6[15] = v4[3]; +} + +int +v6tov4(uchar *v4, uchar *v6) +{ + if(v6[0] == 0 + && v6[1] == 0 + && v6[2] == 0 + && v6[3] == 0 + && v6[4] == 0 + && v6[5] == 0 + && v6[6] == 0 + && v6[7] == 0 + && v6[8] == 0 + && v6[9] == 0 + && v6[10] == 0xff + && v6[11] == 0xff) + { + v4[0] = v6[12]; + v4[1] = v6[13]; + v4[2] = v6[14]; + v4[3] = v6[15]; + return 0; + } else { + memset(v4, 0, 4); + if(memcmp(v6, IPnoaddr, IPaddrlen) == 0) + return 0; + return -1; + } +} --- /sys/src/cmd/unix/drawterm/libip/parseip.c Thu Jan 1 01:00:00 1970 +++ /sys/src/cmd/unix/drawterm/libip/parseip.c Tue Mar 18 00:37:26 2014 @@ -0,0 +1,185 @@ +#include +#include +#include +#include + +char* +v4parseip(uchar *to, char *from) +{ + int i; + char *p; + + p = from; + for(i = 0; i < 4 && *p; i++){ + to[i] = strtoul(p, &p, 0); + if(*p == '.') + p++; + } + switch(CLASS(to)){ + case 0: /* class A - 1 uchar net */ + case 1: + if(i == 3){ + to[3] = to[2]; + to[2] = to[1]; + to[1] = 0; + } else if (i == 2){ + to[3] = to[1]; + to[1] = 0; + } + break; + case 2: /* class B - 2 uchar net */ + if(i == 3){ + to[3] = to[2]; + to[2] = 0; + } + break; + } + return p; +} + +static int +ipcharok(int c) +{ + return c == '.' || c == ':' || (isascii(c) && isxdigit(c)); +} + +static int +delimchar(int c) +{ + if(c == '\0') + return 1; + if(c == '.' || c == ':' || (isascii(c) && isalnum(c))) + return 0; + return 1; +} + +/* + * `from' may contain an address followed by other characters, + * at least in /boot, so we permit whitespace (and more) after the address. + * we do ensure that "delete" cannot be parsed as "de::". + * + * some callers don't check the return value for errors, so + * set `to' to something distinctive in the case of a parse error. + */ +vlong +parseip(uchar *to, char *from) +{ + int i, elipsis = 0, v4 = 1; + ulong x; + char *p, *op; + + memset(to, 0, IPaddrlen); + p = from; + for(i = 0; i < IPaddrlen && ipcharok(*p); i+=2){ + op = p; + x = strtoul(p, &p, 16); + if((*p == '.' && i <= IPaddrlen-4) || (*p == 0 && i == 0)){ + /* ends with v4 */ + p = v4parseip(to+i, op); + i += 4; + break; + } + /* v6: at most 4 hex digits, followed by colon or delim */ + if(x != (ushort)x || (*p != ':' && !delimchar(*p))) { + memset(to, 0, IPaddrlen); + return -1; /* parse error */ + } + to[i] = x>>8; + to[i+1] = x; + if(*p == ':'){ + v4 = 0; + if(*++p == ':'){ /* :: is elided zero short(s) */ + if (elipsis) { + memset(to, 0, IPaddrlen); + return -1; /* second :: */ + } + elipsis = i+2; + p++; + } + } else if (p == op) /* strtoul made no progress? */ + break; + } + if (p == from || !delimchar(*p)) { + memset(to, 0, IPaddrlen); + return -1; /* parse error */ + } + if(i < IPaddrlen){ + memmove(&to[elipsis+IPaddrlen-i], &to[elipsis], i-elipsis); + memset(&to[elipsis], 0, IPaddrlen-i); + } + if(v4){ + to[10] = to[11] = 0xff; + return nhgetl(to + IPv4off); + } else + return 6; +} + +/* + * hack to allow ip v4 masks to be entered in the old + * style + */ +vlong +parseipmask(uchar *to, char *from) +{ + int i, w; + vlong x; + uchar *p; + + if(*from == '/'){ + /* as a number of prefix bits */ + i = atoi(from+1); + if(i < 0) + i = 0; + if(i > 128) + i = 128; + w = i; + memset(to, 0, IPaddrlen); + for(p = to; i >= 8; i -= 8) + *p++ = 0xff; + if(i > 0) + *p = ~((1<<(8-i))-1); + x = nhgetl(to+IPv4off); + /* + * identify as ipv6 if the mask is inexpressible as a v4 mask + * (because it has too few mask bits). Arguably, we could + * always return 6 here. + */ + if (w < 8*(IPaddrlen-IPv4addrlen)) + return 6; + } else { + /* as a straight v4 bit mask */ + x = parseip(to, from); + if (x != -1) + x = (ulong)nhgetl(to + IPv4off); + if(memcmp(to, v4prefix, IPv4off) == 0) + memset(to, 0xff, IPv4off); + } + return x; +} + +/* + * parse a v4 ip address/mask in cidr format + */ +char* +v4parsecidr(uchar *addr, uchar *mask, char *from) +{ + int i; + char *p; + uchar *a; + + p = v4parseip(addr, from); + + if(*p == '/'){ + /* as a number of prefix bits */ + i = strtoul(p+1, &p, 0); + if(i > 32) + i = 32; + memset(mask, 0, IPv4addrlen); + for(a = mask; i >= 8; i -= 8) + *a++ = 0xff; + if(i > 0) + *a = ~((1<<(8-i))-1); + } else + memcpy(mask, defmask(addr), IPv4addrlen); + return p; +} --- /sys/src/cmd/unix/drawterm/libmemdraw/draw.c Sun May 21 19:50:27 2006 +++ /sys/src/cmd/unix/drawterm/libmemdraw/draw.c Tue Mar 18 05:36:36 2014 @@ -10,22 +10,34 @@ #define RGB2K(r,g,b) ((156763*(r)+307758*(g)+59769*(b))>>19) /* - * for 0 ≤ x ≤ 255*255, (x*0x0101+0x100)>>16 is a perfect approximation. - * for 0 ≤ x < (1<<16), x/255 = ((x+1)*0x0101)>>16 is a perfect approximation. - * the last one is perfect for all up to 1<<16, avoids a multiply, but requires a rathole. + * For 16-bit values, x / 255 == (t = x+1, (t+(t>>8)) >> 8). + * We add another 127 to round to the nearest value rather + * than truncate. + * + * CALCxy does x bytewise calculations on y input images (x=1,4; y=1,2). + * CALC2x does two parallel 16-bit calculations on y input images (y=1,2). */ -/* #define DIV255(x) (((x)*257+256)>>16) */ -#define DIV255(x) ((((x)+1)*257)>>16) -/* #define DIV255(x) (tmp=(x)+1, (tmp+(tmp>>8))>>8) */ - -#define MUL(x, y, t) (t = (x)*(y)+128, (t+(t>>8))>>8) -#define MASK13 0xFF00FF00 -#define MASK02 0x00FF00FF -#define MUL13(a, x, t) (t = (a)*(((x)&MASK13)>>8)+128, ((t+((t>>8)&MASK02))>>8)&MASK02) -#define MUL02(a, x, t) (t = (a)*(((x)&MASK02)>>0)+128, ((t+((t>>8)&MASK02))>>8)&MASK02) -#define MUL0123(a, x, s, t) ((MUL13(a, x, s)<<8)|MUL02(a, x, t)) +#define CALC11(a, v, tmp) \ + (tmp=(a)*(v)+128, (tmp+(tmp>>8))>>8) + +#define CALC12(a1, v1, a2, v2, tmp) \ + (tmp=(a1)*(v1)+(a2)*(v2)+128, (tmp+(tmp>>8))>>8) + +#define MASK 0xFF00FF + +#define CALC21(a, vvuu, tmp) \ + (tmp=(a)*(vvuu)+0x00800080, ((tmp+((tmp>>8)&MASK))>>8)&MASK) + +#define CALC41(a, rgba, tmp1, tmp2) \ + (CALC21(a, rgba & MASK, tmp1) | \ + (CALC21(a, (rgba>>8)&MASK, tmp2)<<8)) -#define MUL2(u, v, x, y) (t = (u)*(v)+(x)*(y)+256, (t+(t>>8))>>8) +#define CALC22(a1, vvuu1, a2, vvuu2, tmp) \ + (tmp=(a1)*(vvuu1)+(a2)*(vvuu2)+0x00800080, ((tmp+((tmp>>8)&MASK))>>8)&MASK) + +#define CALC42(a1, rgba1, a2, rgba2, tmp1, tmp2) \ + (CALC22(a1, rgba1 & MASK, a2, rgba2 & MASK, tmp1) | \ + (CALC22(a1, (rgba1>>8) & MASK, a2, (rgba2>>8) & MASK, tmp2)<<8)) static void mktables(void); typedef int Subdraw(Memdrawparam*); @@ -307,6 +319,9 @@ * Conversion tables. */ static uchar replbit[1+8][256]; /* replbit[x][y] is the replication of the x-bit quantity y to 8-bit depth */ +static uchar conv18[256][8]; /* conv18[x][y] is the yth pixel in the depth-1 pixel x */ +static uchar conv28[256][4]; /* ... */ +static uchar conv48[256][2]; /* * bitmap of how to replicate n bits to fill 8, for 1 ≤ n ≤ 8. @@ -340,7 +355,7 @@ static void mktables(void) { - int i, j, small; + int i, j, mask, sh, small; if(tablesbuilt) return; @@ -357,6 +372,17 @@ } } + /* bit unpacking up to 8 bits, only powers of 2 */ + for(i=0; i<256; i++){ + for(j=0, sh=7, mask=1; j<8; j++, sh--) + conv18[i][j] = replbit[1][(i>>sh)&mask]; + + for(j=0, sh=6, mask=3; j<4; j++, sh-=2) + conv28[i][j] = replbit[2][(i>>sh)&mask]; + + for(j=0, sh=4, mask=15; j<2; j++, sh-=4) + conv48[i][j] = replbit[4][(i>>sh)&mask]; + } } static uchar ones = 0xff; @@ -770,41 +796,85 @@ return bdst; } +/* + * Do the channels in the buffers match enough + * that we can do word-at-a-time operations + * on the pixels? + */ +static int +chanmatch(Buffer *bdst, Buffer *bsrc) +{ + uchar *drgb, *srgb; + + /* + * first, r, g, b must be in the same place + * in the rgba word. + */ + drgb = (uchar*)bdst->rgba; + srgb = (uchar*)bsrc->rgba; + if(bdst->red - drgb != bsrc->red - srgb + || bdst->blu - drgb != bsrc->blu - srgb + || bdst->grn - drgb != bsrc->grn - srgb) + return 0; + + /* + * that implies alpha is in the same place, + * if it is there at all (it might be == &ones). + * if the destination is &ones, we can scribble + * over the rgba slot just fine. + */ + if(bdst->alpha == &ones) + return 1; + + /* + * if the destination is not ones but the src is, + * then the simultaneous calculation will use + * bogus bytes from the src's rgba. no good. + */ + if(bsrc->alpha == &ones) + return 0; + + /* + * otherwise, alphas are in the same place. + */ + return 1; +} + static Buffer alphacalc14(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op) { Buffer obdst; int fd, sadelta; int i, sa, ma, q; - ulong s, t; + ulong t, t1; obdst = bdst; sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta; - q = bsrc.delta == 4 && bdst.delta == 4; + q = bsrc.delta == 4 && bdst.delta == 4 && chanmatch(&bdst, &bsrc); for(i=0; isdval; /* make little endian */ @@ -2457,7 +2527,6 @@ { ulong bits; int d, y; - uchar p[4]; if(val == DNofill) return; @@ -2471,11 +2540,6 @@ default: /* 1, 2, 4, 8, 16, 32 */ for(d=i->depth; d<32; d*=2) bits = (bits << d) | bits; - p[0] = bits; /* make little endian */ - p[1] = bits>>8; - p[2] = bits>>16; - p[3] = bits>>24; - bits = *(ulong*)p; memsetl(wordaddr(i, i->r.min), bits, i->width*Dy(i->r)); break; } --- /sys/src/cmd/unix/drawterm/posix-arm/Makefile Sun Jul 8 07:48:13 2012 +++ /sys/src/cmd/unix/drawterm/posix-arm/Makefile Tue Mar 18 05:36:05 2014 @@ -6,7 +6,7 @@ getcallerpc.$O\ md5block.$O\ sha1block.$O\ - tas.$O\ + tas.$O default: $(LIB) $(LIB): $(OFILES) --- /sys/src/cmd/unix/drawterm/posix-arm/getcallerpc.c Sun Jul 8 07:48:13 2012 +++ /sys/src/cmd/unix/drawterm/posix-arm/getcallerpc.c Tue Mar 18 05:36:20 2014 @@ -4,5 +4,5 @@ uintptr getcallerpc(void *a) { - return 0; + return ((uintptr*)a)[-1]; } --- /sys/src/cmd/unix/drawterm/posix-arm/tas.c Sun Jul 8 07:49:47 2012 +++ /sys/src/cmd/unix/drawterm/posix-arm/tas.c Tue Mar 18 05:36:23 2014 @@ -1,18 +1,28 @@ -/* arm pre-v7 architecture */ #include "u.h" #include "libc.h" int tas(long *x) { - int v; + int v, t, i = 1; +#if ARMv5 __asm__( "swp %0, %1, [%2]" : "=&r" (v) : "r" (1), "r" (x) : "memory" ); +#else + __asm__ ( + "1: ldrex %0, [%2]\n" + " strex %1, %3, [%2]\n" + " teq %1, #0\n" + " bne 1b" + : "=&r" (v), "=&r" (t) + : "r" (x), "r" (i) + : "cc"); +#endif switch(v) { case 0: case 1: @@ -22,3 +32,4 @@ return 1; } } + --- /sys/src/cmd/usb/kb/kb.c Fri Mar 29 20:00:59 2013 +++ /sys/src/cmd/usb/kb/kb.c Mon Mar 17 23:46:34 2014 @@ -473,7 +473,7 @@ } -#define hasesc1(sc) (((sc) > 0x47) || ((sc) == 0x38)) +#define hasesc1(sc) ((sc) >= 0x47 || (sc) == 0x38) static void putmod(KDev *f, uchar mods, uchar omods, uchar mask, uchar esc, uchar sc)