Browse Source

Plan 9 from Bell Labs 2014-03-18

David du Colombier 10 years ago
parent
commit
c550f72506
44 changed files with 2018 additions and 1762 deletions
  1. 1 1
      sys/src/9/ip/icmp.c
  2. 1 0
      sys/src/9/ip/icmp6.c
  3. 69 14
      sys/src/9/omap/kbd.c
  4. 1 1
      sys/src/9/pc/ahci.h
  5. 17 17
      sys/src/9/pc/sdiahci.c
  6. 1 0
      sys/src/ape/lib/draw/libc.h
  7. 0 2
      sys/src/cmd/aan.c
  8. 23 0
      sys/src/cmd/dict/mkroget
  9. 3 2
      sys/src/cmd/ip/imap4d/imap4d.c
  10. 2 2
      sys/src/cmd/mkfile
  11. 2 1
      sys/src/cmd/ssh1/ssh1.c
  12. 4 0
      sys/src/cmd/unix/drawterm/Makefile
  13. 12 11
      sys/src/cmd/unix/drawterm/cpu.c
  14. 1 1
      sys/src/cmd/unix/drawterm/exportfs/exportfs.c
  15. 1 1
      sys/src/cmd/unix/drawterm/exportfs/exportsrv.c
  16. 0 204
      sys/src/cmd/unix/drawterm/gui-x11/alloc.c
  17. 0 16
      sys/src/cmd/unix/drawterm/gui-x11/cload.c
  18. 0 186
      sys/src/cmd/unix/drawterm/gui-x11/draw.c
  19. 0 754
      sys/src/cmd/unix/drawterm/gui-x11/ksym2utf.h
  20. 0 16
      sys/src/cmd/unix/drawterm/gui-x11/load.c
  21. 572 113
      sys/src/cmd/unix/drawterm/gui-x11/x11.c
  22. 0 60
      sys/src/cmd/unix/drawterm/gui-x11/xmem.h
  23. 1 1
      sys/src/cmd/unix/drawterm/include/fcall.h
  24. 38 0
      sys/src/cmd/unix/drawterm/include/ip.h
  25. 3 0
      sys/src/cmd/unix/drawterm/include/lib.h
  26. 0 0
      sys/src/cmd/unix/drawterm/include/x
  27. 268 0
      sys/src/cmd/unix/drawterm/kern/devaudio-sun.c
  28. 8 7
      sys/src/cmd/unix/drawterm/kern/devfs-posix.c
  29. 114 41
      sys/src/cmd/unix/drawterm/kern/devip-posix.c
  30. 104 41
      sys/src/cmd/unix/drawterm/kern/devip-win32.c
  31. 37 182
      sys/src/cmd/unix/drawterm/kern/devip.c
  32. 5 5
      sys/src/cmd/unix/drawterm/kern/devip.h
  33. 0 6
      sys/src/cmd/unix/drawterm/kern/fns.h
  34. 19 0
      sys/src/cmd/unix/drawterm/libip/Makefile
  35. 77 0
      sys/src/cmd/unix/drawterm/libip/bo.c
  36. 86 0
      sys/src/cmd/unix/drawterm/libip/classmask.c
  37. 109 0
      sys/src/cmd/unix/drawterm/libip/eipfmt.c
  38. 102 0
      sys/src/cmd/unix/drawterm/libip/ipaux.c
  39. 185 0
      sys/src/cmd/unix/drawterm/libip/parseip.c
  40. 136 72
      sys/src/cmd/unix/drawterm/libmemdraw/draw.c
  41. 1 1
      sys/src/cmd/unix/drawterm/posix-arm/Makefile
  42. 1 1
      sys/src/cmd/unix/drawterm/posix-arm/getcallerpc.c
  43. 13 2
      sys/src/cmd/unix/drawterm/posix-arm/tas.c
  44. 1 1
      sys/src/cmd/usb/kb/kb.c

+ 1 - 1
sys/src/9/ip/icmp.c

@@ -366,7 +366,7 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp)
 	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;

+ 1 - 0
sys/src/9/ip/icmp6.c

@@ -718,6 +718,7 @@ icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp)
 	ipriv->in[type]++;
 	switch(type) {
 	case EchoRequestV6:
+		bp = concatblock(bp);
 		r = mkechoreply6(bp, ipifc);
 		if(r == nil)
 			goto raise;

+ 69 - 14
sys/src/9/omap/kbd.c

@@ -51,7 +51,7 @@ enum {
  * 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 @@ Rune kbtabesc1[Nscan] =
 [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 kbtabaltgr[Nscan] =
 
 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 @@ kbdputsc(int c, int external)
 		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 @@ kbdputsc(int c, int external)
 			 * 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 @@ kbdputmap(ushort m, ushort scanc, Rune r)
 	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;
 	}
 }
 
@@ -406,5 +455,11 @@ kbdgetmap(uint offset, int *t, int *sc, Rune *r)
 	case 4:
 		*r = kbtabctrl[*sc];
 		return 1;
+	case 5:
+		*r = kbtabctrlesc1[*sc];
+		return 1;
+	case 6:
+		*r = kbtabshiftesc1[*sc];
+		return 1;
 	}
 }

+ 1 - 1
sys/src/9/pc/ahci.h

@@ -289,5 +289,5 @@ typedef struct {
 
 typedef struct {
 	Aport	*p;
-	Aportm	*m;
+	Aportm	*pm;
 } Aportc;

+ 17 - 17
sys/src/9/pc/sdiahci.c

@@ -285,7 +285,7 @@ ahciwait(Aportc *c, int ms)
 	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 @@ cfissetup(Aportc *pc)
 {
 	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 @@ listsetup(Aportc *pc, int flags)
 {
 	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 @@ nop(Aportc *pc)
 {
 	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 @@ smart(Aportc *pc, int n)
 {
 	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 @@ smartrs(Aportc *pc)
 	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 @@ ahciflushcache(Aportc *pc)
 	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 @@ ahciidentify0(Aportc *pc, void *id, int atapi)
 	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 @@ ahciidentify(Aportc *pc, ushort *id)
 	vlong s;
 	Aportm *pm;
 
-	pm = pc->m;
+	pm = pc->pm;
 	pm->feat = 0;
 	pm->smart = 0;
 	i = 0;
@@ -723,7 +723,7 @@ ahciconfigdrive(Drive *d)
 
 	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 @@ updatedrive(Drive *d)
 		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 @@ updatedrive(Drive *d)
 			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 @@ newdrive(Drive *d)
 
 	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 @@ newdrive(Drive *d)
 			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 @@ newdrive(Drive *d)
 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 @@ newctlr(Ctlr *ctlr, SDev *sdev, int nunit)
 			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;

+ 1 - 0
sys/src/ape/lib/draw/libc.h

@@ -126,6 +126,7 @@ extern	int	_IOUNIT(int);
 #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)

+ 0 - 2
sys/src/cmd/aan.c

@@ -68,10 +68,8 @@ static void	freeendpoints(Endpoints *);
 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 *);

+ 23 - 0
sys/src/cmd/dict/mkroget

@@ -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

+ 3 - 2
sys/src/cmd/ip/imap4d/imap4d.c

@@ -1074,9 +1074,10 @@ searchUCmd(char *tg, char *cmd, int uids)
 	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;

+ 2 - 2
sys/src/cmd/mkfile

@@ -8,14 +8,14 @@ LDFLAGS=
 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:

+ 2 - 1
sys/src/cmd/ssh1/ssh1.c

@@ -563,7 +563,8 @@ fromstdin(Conn *c)
 		sendwritemsg(c, buf, n);
 	}
 	sendwritemsg(c, "", 0);
-	atexitdont(atexitkiller);
+	if(n >= 0)				/* weren't hung up upon? */
+		atexitdont(atexitkiller);
 	exits(nil);
 }
 

+ 4 - 0
sys/src/cmd/unix/drawterm/Makefile

@@ -23,6 +23,7 @@ LIBS1=\
 	libdraw/libdraw.a\
 	gui-$(GUI)/libgui.a\
 	libc/libc.a\
+	libip/libip.a\
 
 # stupid gcc
 LIBS=$(LIBS1) $(LIBS1) $(LIBS1) libmachdep.a
@@ -67,5 +68,8 @@ libdraw/libdraw.a:
 libc/libc.a:
 	(cd libc; $(MAKE))
 
+libip/libip.a:
+	(cd libip; $(MAKE))
+
 gui-$(GUI)/libgui.a:
 	(cd gui-$(GUI); $(MAKE))

+ 12 - 11
sys/src/cmd/unix/drawterm/cpu.c

@@ -29,7 +29,7 @@ static AuthInfo *p9any(int);
 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 @@ cpumain(int argc, char **argv)
 	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 @@ p9any(int fd)
 
 	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 @@ p9any(int fd)
 	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");
 	}

+ 1 - 1
sys/src/cmd/unix/drawterm/exportfs/exportfs.c

@@ -58,7 +58,7 @@ exportfs(int fd, int msgsz)
 	if(messagesize == 0){
 		messagesize = iounit(netfd);
 		if(messagesize == 0)
-			messagesize = 8192+IOHDRSZ;
+			messagesize = 8*8192+IOHDRSZ;
 	}
 
 	Workq = emallocz(sizeof(Fsrpc)*Nr_workbufs);

+ 1 - 1
sys/src/cmd/unix/drawterm/exportfs/exportsrv.c

@@ -16,7 +16,7 @@ char Eversion[] = "Bad 9P2000 version";
 
 int iounit(int x)
 {
-	return 8192+IOHDRSZ;
+	return 8*8192+IOHDRSZ;
 }
 
 void*

+ 0 - 204
sys/src/cmd/unix/drawterm/gui-x11/alloc.c

@@ -1,204 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include "xmem.h"
-
-/* perfect approximation to NTSC = .299r+.587g+.114b when 0 ≤ r,g,b < 256 */
-#define RGB2K(r,g,b)	((156763*(r)+307758*(g)+59769*(b))>>19)
-
-Memimage*
-xallocmemimage(Rectangle r, ulong chan, int pmid)
-{
-	Memimage *m;
-	Xmem *xm;
-	XImage *xi;
-	int offset;
-	int d;
-	
-	m = _allocmemimage(r, chan);
-	if(chan != GREY1 && chan != xscreenchan)
-		return m;
-
-	d = m->depth;
-	xm = mallocz(sizeof(Xmem), 1);
-	if(pmid != PMundef)
-		xm->pmid = pmid;
-	else
-		xm->pmid = XCreatePixmap(xdisplay, xscreenid, Dx(r), Dy(r), (d==32) ? 24 : d);
-		
-	if(m->depth == 24)
-		offset = r.min.x&(4-1);
-	else
-		offset = r.min.x&(31/m->depth);
-	r.min.x -= offset;
-	
-	assert(wordsperline(r, m->depth) <= m->width);
-
-	xi = XCreateImage(xdisplay, xvis, m->depth==32?24:m->depth, ZPixmap, 0,
-		(char*)m->data->bdata, Dx(r), Dy(r), 32, m->width*sizeof(ulong));
-	
-	if(xi == nil){
-		_freememimage(m);
-		return nil;
-	}
-
-	xm->xi = xi;
-	xm->pc = getcallerpc(&r);
-	xm->r = r;
-	
-	/*
-	 * Set the parameters of the XImage so its memory looks exactly like a
-	 * Memimage, so we can call _memimagedraw on the same data.  All frame
-	 * buffers we've seen, and Plan 9's graphics code, require big-endian
-	 * bits within bytes, but little endian byte order within pixels.
-	 */
-	xi->bitmap_unit = m->depth < 8 || m->depth == 24 ? 8 : m->depth;
-	xi->byte_order = LSBFirst;
-	xi->bitmap_bit_order = MSBFirst;
-	xi->bitmap_pad = 32;
-	xm->r = Rect(0,0,0,0);
-	XInitImage(xi);
-	XFlush(xdisplay);
-
-	m->X = xm;
-	return m;
-}
-
-Memimage*
-allocmemimage(Rectangle r, ulong chan)
-{
-	return xallocmemimage(r, chan, PMundef);
-}
-
-void
-freememimage(Memimage *m)
-{
-	Xmem *xm;
-	
-	if(m == nil)
-		return;
-		
-	if(m->data->ref == 1){
-		if((xm = m->X) != nil){
-			if(xm->xi){
-				xm->xi->data = nil;
-				XFree(xm->xi);
-			}
-			XFreePixmap(xdisplay, xm->pmid);
-			free(xm);
-			m->X = nil;
-		}
-	}
-	_freememimage(m);
-}
-
-void
-memfillcolor(Memimage *m, ulong val)
-{
-	_memfillcolor(m, val);
-	if(m->X){
-		if((val & 0xFF) == 0xFF)
-			xfillcolor(m, m->r, _rgbatoimg(m, val));
-		else
-			putXdata(m, m->r);
-	}
-}
-
-static void
-addrect(Rectangle *rp, Rectangle r)
-{
-	if(rp->min.x >= rp->max.x)
-		*rp = r;
-	else
-		combinerect(rp, r);
-}
-
-XImage*
-getXdata(Memimage *m, Rectangle r)
-{
-	uchar *p;
-	int x, y;
-	Xmem *xm;
-	Point xdelta, delta;
-	Point tp;
-
- 	xm = m->X;
- 	if(xm == nil)
- 		return nil;
- 
-	assert(xm != nil && xm->xi != nil);
-	
- 	if(xm->dirty == 0)
- 		return xm->xi;
- 		
- 	r = xm->dirtyr;
-	if(Dx(r)==0 || Dy(r)==0)
-		return xm->xi;
-
-	delta = subpt(r.min, m->r.min);
-	tp = xm->r.min;	/* avoid unaligned access on digital unix */
-	xdelta = subpt(r.min, tp);
-	
-	XGetSubImage(xdisplay, xm->pmid, delta.x, delta.y, Dx(r), Dy(r),
-		AllPlanes, ZPixmap, xm->xi, xdelta.x, xdelta.y);
-		
-	if(xtblbit && m->chan == CMAP8)
-		for(y=r.min.y; y<r.max.y; y++)
-			for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
-				*p = x11toplan9[*p];
-				
-	xm->dirty = 0;
-	xm->dirtyr = Rect(0,0,0,0);
-	return xm->xi;
-}
-
-void
-putXdata(Memimage *m, Rectangle r)
-{
-	Xmem *xm;
-	XImage *xi;
-	GC g;
-	Point xdelta, delta;
-	Point tp;
-	int x, y;
-	uchar *p;
-
-	xm = m->X;
-	if(xm == nil)
-		return;
-		
-	assert(xm != nil);
-	assert(xm->xi != nil);
-
-	xi = xm->xi;
-
-	g = (m->chan == GREY1) ? xgccopy0 : xgccopy;
-
-	delta = subpt(r.min, m->r.min);
-	tp = xm->r.min;	/* avoid unaligned access on digital unix */
-	xdelta = subpt(r.min, tp);
-	
-	if(xtblbit && m->chan == CMAP8)
-		for(y=r.min.y; y<r.max.y; y++)
-			for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
-				*p = plan9tox11[*p];
-	
-	XPutImage(xdisplay, xm->pmid, g, xi, xdelta.x, xdelta.y, delta.x, delta.y, Dx(r), Dy(r));
-
-	if(xtblbit && m->chan == CMAP8)
-		for(y=r.min.y; y<r.max.y; y++)
-			for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
-				*p = x11toplan9[*p];
-}
-
-void
-dirtyXdata(Memimage *m, Rectangle r)
-{
-	Xmem *xm;
-	
-	if((xm = m->X) != nil){
-		xm->dirty = 1;
-		addrect(&xm->dirtyr, r);
-	}
-}

+ 0 - 16
sys/src/cmd/unix/drawterm/gui-x11/cload.c

@@ -1,16 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include "xmem.h"
-
-int
-cloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
-{
-	int n;
-
-	n = _cloadmemimage(i, r, data, ndata);
-	if(n > 0 && i->X)
-		putXdata(i, r);
-	return n;
-}

+ 0 - 186
sys/src/cmd/unix/drawterm/gui-x11/draw.c

@@ -1,186 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include "xmem.h"
-
-void xfillcolor(Memimage*, Rectangle, ulong);
-static int xdraw(Memdrawparam*);
-
-int	xgcfillcolor = 0;
-int	xgcfillcolor0 = 0;
-int	xgczeropm = 0;
-int	xgczeropm0 = 0;
-int	xgcsimplecolor = 0;
-int	xgcsimplecolor0 = 0;
-int	xgcsimplepm = 0; 
-int	xgcsimplepm0 = 0;
-int	xgcreplsrctile = 0;
-int	xgcreplsrctile0 = 0;
-
-void
-memimageinit(void)
-{
-	static int didinit = 0;
-	
-	if(didinit)
-		return;
-
-	didinit = 1;
-	_memimageinit();
-	
-	xfillcolor(memblack, memblack->r, 0);
-	xfillcolor(memwhite, memwhite->r, 1);
-}
-
-void
-memimagedraw(Memimage *dst, Rectangle r, Memimage *src, Point sp, Memimage *mask, Point mp, int op)
-{
-	Memdrawparam *par;
-	
-	if((par = _memimagedrawsetup(dst, r, src, sp, mask, mp, op)) == nil)
-		return;
-	_memimagedraw(par);
-	if(!xdraw(par))
-		putXdata(dst, par->r);
-}
-
-void
-xfillcolor(Memimage *m, Rectangle r, ulong v)
-{
-	GC gc;
-	Xmem *dxm;
-
-	dxm = m->X;
-	assert(dxm != nil);
-	r = rectsubpt(r, m->r.min);
-		
-	if(m->chan == GREY1){
-		gc = xgcfill0;
-		if(xgcfillcolor0 != v){
-			XSetForeground(xdisplay, gc, v);
-			xgcfillcolor0 = v;
-		}
-	}else{
-		if(m->chan == CMAP8 && xtblbit)
-			v = plan9tox11[v];
-				
-		gc = xgcfill;
-		if(xgcfillcolor != v){
-			XSetForeground(xdisplay, gc, v);
-			xgcfillcolor = v;
-		}
-	}
-	XFillRectangle(xdisplay, dxm->pmid, gc, r.min.x, r.min.y, Dx(r), Dy(r));
-}
-
-static int
-xdraw(Memdrawparam *par)
-{
-	int dy, dx;
-	unsigned m;
-	Memimage *src, *dst, *mask;
-	Xmem *dxm, *sxm, *mxm;
-	GC gc;
-	Rectangle r, sr, mr;
-	ulong sdval;
-
-	dx = Dx(par->r);
-	dy = Dy(par->r);
-	src = par->src;
-	dst = par->dst;
-	mask = par->mask;
-	r = par->r;
-	sr = par->sr;
-	mr = par->mr;
-	sdval = par->sdval;
-
-return 0;
-	if((dxm = dst->X) == nil)
-		return 0;
-
-	/*
-	 * If we have an opaque mask and source is one opaque pixel we can convert to the
-	 * destination format and just XFillRectangle.
-	 */
-	m = Simplesrc|Simplemask|Fullmask;
-	if((par->state&m)==m){
-		xfillcolor(dst, r, sdval);
-		dirtyXdata(dst, par->r);
-		return 1;
-	}
-
-	/*
-	 * If no source alpha, an opaque mask, we can just copy the
-	 * source onto the destination.  If the channels are the same and
-	 * the source is not replicated, XCopyArea suffices.
-	 */
-	m = Simplemask|Fullmask;
-	if((par->state&(m|Replsrc))==m && src->chan == dst->chan && src->X){
-		sxm = src->X;
-		r = rectsubpt(r, dst->r.min);		
-		sr = rectsubpt(sr, src->r.min);
-		if(dst->chan == GREY1)
-			gc = xgccopy0;
-		else
-			gc = xgccopy;
-		XCopyArea(xdisplay, sxm->pmid, dxm->pmid, gc, 
-			sr.min.x, sr.min.y, dx, dy, r.min.x, r.min.y);
-		dirtyXdata(dst, par->r);
-		return 1;
-	}
-	
-	/*
-	 * If no source alpha, a 1-bit mask, and a simple source
-	 * we can just copy through the mask onto the destination.
-	 */
-	if(dst->X && mask->X && !(mask->flags&Frepl)
-	&& mask->chan == GREY1 && (par->state&Simplesrc)){
-		Point p;
-
-		mxm = mask->X;
-		r = rectsubpt(r, dst->r.min);		
-		mr = rectsubpt(mr, mask->r.min);
-		p = subpt(r.min, mr.min);
-		if(dst->chan == GREY1){
-			gc = xgcsimplesrc0;
-			if(xgcsimplecolor0 != sdval){
-				XSetForeground(xdisplay, gc, sdval);
-				xgcsimplecolor0 = sdval;
-			}
-			if(xgcsimplepm0 != mxm->pmid){
-				XSetStipple(xdisplay, gc, mxm->pmid);
-				xgcsimplepm0 = mxm->pmid;
-			}
-		}else{
-		/* somehow this doesn't work on rob's mac 
-			gc = xgcsimplesrc;
-			if(dst->chan == CMAP8 && xtblbit)
-				sdval = plan9tox11[sdval];
-				
-			if(xgcsimplecolor != sdval){
-				XSetForeground(xdisplay, gc, sdval);
-				xgcsimplecolor = sdval;
-			}
-			if(xgcsimplepm != mxm->pmid){
-				XSetStipple(xdisplay, gc, mxm->pmid);
-				xgcsimplepm = mxm->pmid;
-			}
-		*/
-			return 0;
-		}
-		XSetTSOrigin(xdisplay, gc, p.x, p.y);
-		XFillRectangle(xdisplay, dxm->pmid, gc, r.min.x, r.min.y, dx, dy);
-		dirtyXdata(dst, par->r);
-		return 1;
-	}
-	return 0;
-}
-
-ulong
-pixelbits(Memimage *m, Point p)
-{
-	if(m->X)
-		getXdata(m, Rect(p.x, p.y, p.x+1, p.y+1));
-	return _pixelbits(m, p);
-}

+ 0 - 754
sys/src/cmd/unix/drawterm/gui-x11/ksym2utf.h

@@ -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,
-};

+ 0 - 16
sys/src/cmd/unix/drawterm/gui-x11/load.c

@@ -1,16 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <memdraw.h>
-#include "xmem.h"
-
-int
-loadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
-{
-	int n;
-
-	n = _loadmemimage(i, r, data, ndata);
-	if(n > 0 && i->X)
-		putXdata(i, r);
-	return n;
-}

+ 572 - 113
sys/src/cmd/unix/drawterm/gui-x11/screen.c → sys/src/cmd/unix/drawterm/gui-x11/x11.c

@@ -1,109 +1,549 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <stdio.h>
+#include "u.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+
+#include <draw.h>
+#include <memdraw.h>
+#include <keyboard.h>
+#include <cursor.h>
+#include "screen.h"
+
+#define argv0 "drawterm"
+
+typedef struct Cursor Cursor;
+
+#undef	long
+#define	Font		XFont
+#define	Screen	XScreen
+#define	Display	XDisplay
+#define	Cursor	XCursor
 
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
 #include <X11/Xutil.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
 #include <X11/keysym.h>
-
 #include "keysym2ucs.h"
 
+#undef	Font
+#undef	Screen
+#undef	Display
+#undef	Cursor
+#define	long	int
+
+/* perfect approximation to NTSC = .299r+.587g+.114b when 0 ≤ r,g,b < 256 */
+#define RGB2K(r,g,b)	((156763*(r)+307758*(g)+59769*(b))>>19)
+
+enum
+{
+	PMundef	= ~0		/* undefined pixmap id */
+};
+
 /*
- * alias defs for image types to overcome name conflicts
+ * Structure pointed to by X field of Memimage
  */
-#define	Point	IPoint
-#define	Rectangle	IRectangle
-#define	Display	IDisplay
-#define	Font	IFont
-#define	Screen	IScreen
-
-#include	"u.h"
-#include	"lib.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"user.h"
-#include	"draw.h"
-#include	"memdraw.h"
-#include	"keyboard.h"
-#include	"screen.h"
-
-#undef time
-#undef Point
-#undef Rectangle
-#undef Display
-#undef Font
-#undef Screen
-
-typedef struct ICursor ICursor;
-struct ICursor
+typedef struct Xmem Xmem;
+struct Xmem
 {
-	int	w;
-	int	h;
-	int	hotx;
-	int	hoty;
-	char	*src;
-	char	*mask;
+	int	pmid;	/* pixmap id for screen ldepth instance */
+	XImage *xi;	/* local image if we currenty have the data */
+	int	dirty;
+	Rectangle dirtyr;
+	Rectangle r;
+	uintptr pc;	/* who wrote into xi */
 };
 
+static int	xgcfillcolor;
+static int	xgcfillcolor0;
+static int	xgcsimplecolor0;
+static int	xgcsimplepm0;
+
+static	XDisplay*	xdisplay;	/* used holding draw lock */
+static int				xtblbit;
+static int 			plan9tox11[256]; /* Values for mapping between */
+static int 			x11toplan9[256]; /* X11 and Plan 9 */
+static	GC		xgcfill, xgccopy, xgcsimplesrc, xgczero, xgcreplsrc;
+static	GC		xgcfill0, xgccopy0, xgcsimplesrc0, xgczero0, xgcreplsrc0;
+static	ulong	xscreenchan;
+static	Drawable	xscreenid;
+static	Visual		*xvis;
+
+static int xdraw(Memdrawparam*);
+
+#define glenda_width 48
+#define glenda_height 48
+static unsigned short glenda_bits[] = {
+   0xffff, 0xffff, 0xffff, 0xffff, 0xffe9, 0xffff, 0x7fff, 0xffae, 0xffff,
+   0xffff, 0xffbe, 0xffff, 0x1fff, 0xff3f, 0xffff, 0xbfff, 0xfe6e, 0xffff,
+   0xbbff, 0xfcce, 0xffff, 0xffff, 0xf98c, 0xffff, 0xe5ff, 0xf31b, 0xffff,
+   0x87ff, 0xe617, 0xffff, 0x05ff, 0xdf37, 0xffff, 0x0fff, 0x7ffe, 0xffff,
+   0x1bff, 0xfffc, 0xfffa, 0x37ff, 0xfffc, 0xfffb, 0xd7ff, 0xfffc, 0xfff7,
+   0xcfff, 0xffff, 0xfff7, 0xcfff, 0xffff, 0xffef, 0xdfff, 0xffff, 0xffef,
+   0xafff, 0xffff, 0xffdf, 0xefff, 0xffff, 0xfff3, 0xdfff, 0xefff, 0xffd3,
+   0xdfff, 0xc7ff, 0xffdf, 0xefff, 0xefff, 0xffef, 0xcfff, 0xffff, 0xffcf,
+   0xdfff, 0xffff, 0xffd9, 0x9fff, 0x7fff, 0xffd0, 0xbfff, 0xffff, 0xffd7,
+   0x7fff, 0xbfff, 0xffd0, 0x3fff, 0x3fff, 0xffd9, 0x7fff, 0x3fff, 0xffcb,
+   0x3fff, 0xffff, 0xffdc, 0x3fff, 0xffff, 0xffdf, 0x3fff, 0xffff, 0xff9f,
+   0x3fff, 0xffff, 0xffdf, 0x8fff, 0xffff, 0xff9f, 0xa7ff, 0xffff, 0xffdf,
+   0xe3ff, 0xffff, 0xffcf, 0xe9ff, 0xffff, 0xffcf, 0xf1ff, 0xffff, 0xffef,
+   0xf3ff, 0xffff, 0xffe7, 0xf9ff, 0xffff, 0xffe7, 0x53ff, 0xffff, 0xffe1,
+   0x07ff, 0x7ffc, 0xffc6, 0x17ff, 0xeff0, 0xffee, 0xffff, 0xc781, 0xffe5,
+   0xffff, 0x8807, 0xffe0, 0xffff, 0x003f, 0xfff0, 0xffff, 0x1fff, 0xfffe
+};
 
-#define ABS(x) ((x) < 0 ? -(x) : (x))
+/*
+ * Synchronize images between X bitmaps and in-memory bitmaps.
+ */
+static void
+addrect(Rectangle *rp, Rectangle r)
+{
+	if(rp->min.x >= rp->max.x)
+		*rp = r;
+	else
+		combinerect(rp, r);
+}
 
-enum
+static XImage*
+getXdata(Memimage *m, Rectangle r)
 {
-	DblTime	= 300		/* double click time in msec */
-};
+	uchar *p;
+	int x, y;
+	Xmem *xm;
+	Point xdelta, delta;
+	Point tp;
+
+ 	xm = m->X;
+ 	if(xm == nil)
+ 		return nil;
+ 
+	assert(xm != nil && xm->xi != nil);
+	
+ 	if(xm->dirty == 0)
+ 		return xm->xi;
+ 		
+ 	r = xm->dirtyr;
+	if(Dx(r)==0 || Dy(r)==0)
+		return xm->xi;
+
+	delta = subpt(r.min, m->r.min);
+	tp = xm->r.min;	/* avoid unaligned access on digital unix */
+	xdelta = subpt(r.min, tp);
+	
+	XGetSubImage(xdisplay, xm->pmid, delta.x, delta.y, Dx(r), Dy(r),
+		AllPlanes, ZPixmap, xm->xi, xdelta.x, xdelta.y);
+		
+	if(xtblbit && m->chan == CMAP8)
+		for(y=r.min.y; y<r.max.y; y++)
+			for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
+				*p = x11toplan9[*p];
+				
+	xm->dirty = 0;
+	xm->dirtyr = Rect(0,0,0,0);
+	return xm->xi;
+}
+
+static void
+putXdata(Memimage *m, Rectangle r)
+{
+	Xmem *xm;
+	XImage *xi;
+	GC g;
+	Point xdelta, delta;
+	Point tp;
+	int x, y;
+	uchar *p;
+
+	xm = m->X;
+	if(xm == nil)
+		return;
+		
+	assert(xm != nil);
+	assert(xm->xi != nil);
+
+	xi = xm->xi;
+
+	g = (m->chan == GREY1) ? xgccopy0 : xgccopy;
+
+	delta = subpt(r.min, m->r.min);
+	tp = xm->r.min;	/* avoid unaligned access on digital unix */
+	xdelta = subpt(r.min, tp);
+	
+	if(xtblbit && m->chan == CMAP8)
+		for(y=r.min.y; y<r.max.y; y++)
+			for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
+				*p = plan9tox11[*p];
+	
+	XPutImage(xdisplay, xm->pmid, g, xi, xdelta.x, xdelta.y, delta.x, delta.y, Dx(r), Dy(r));
+
+	if(xtblbit && m->chan == CMAP8)
+		for(y=r.min.y; y<r.max.y; y++)
+			for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
+				*p = x11toplan9[*p];
+}
+
+static void
+dirtyXdata(Memimage *m, Rectangle r)
+{
+	Xmem *xm;
+	
+	if((xm = m->X) != nil){
+		xm->dirty = 1;
+		addrect(&xm->dirtyr, r);
+	}
+}
+
+Memimage*
+xallocmemimage(Rectangle r, ulong chan, int pmid)
+{
+	Memimage *m;
+	Xmem *xm;
+	XImage *xi;
+	int offset;
+	int d;
+	
+	m = _allocmemimage(r, chan);
+	if(m == nil)
+		return nil;
+	if(chan != GREY1 && chan != xscreenchan)
+		return m;
+
+	d = m->depth;
+	xm = mallocz(sizeof(Xmem), 1);
+	if(pmid != PMundef)
+		xm->pmid = pmid;
+	else
+		xm->pmid = XCreatePixmap(xdisplay, xscreenid, Dx(r), Dy(r), (d==32) ? 24 : d);
+		
+	if(m->depth == 24)
+		offset = r.min.x&(4-1);
+	else
+		offset = r.min.x&(31/m->depth);
+	r.min.x -= offset;
+	
+	assert(wordsperline(r, m->depth) <= m->width);
+
+	xi = XCreateImage(xdisplay, xvis, m->depth==32?24:m->depth, ZPixmap, 0,
+		(char*)m->data->bdata, Dx(r), Dy(r), 32, m->width*sizeof(ulong));
+	
+	if(xi == nil){
+		_freememimage(m);
+		return nil;
+	}
+
+	xm->xi = xi;
+	xm->pc = getcallerpc(&r);
+	xm->r = r;
+	
+	/*
+	 * Set the parameters of the XImage so its memory looks exactly like a
+	 * Memimage, so we can call _memimagedraw on the same data.  All frame
+	 * buffers we've seen, and Plan 9's graphics code, require big-endian
+	 * bits within bytes, but little endian byte order within pixels.
+	 */
+	xi->bitmap_unit = m->depth < 8 || m->depth == 24 ? 8 : m->depth;
+	xi->byte_order = LSBFirst;
+	xi->bitmap_bit_order = MSBFirst;
+	xi->bitmap_pad = 32;
+	xm->r = Rect(0,0,0,0);
+	XInitImage(xi);
+	XFlush(xdisplay);
+
+	m->X = xm;
+	return m;
+}
+
+void
+xfillcolor(Memimage *m, Rectangle r, ulong v)
+{
+	GC gc;
+	Xmem *dxm;
+
+	dxm = m->X;
+	assert(dxm != nil);
+	r = rectsubpt(r, m->r.min);
+		
+	if(m->chan == GREY1){
+		gc = xgcfill0;
+		if(xgcfillcolor0 != v){
+			XSetForeground(xdisplay, gc, v);
+			xgcfillcolor0 = v;
+		}
+	}else{
+		if(m->chan == CMAP8 && xtblbit)
+			v = plan9tox11[v];
+				
+		gc = xgcfill;
+		if(xgcfillcolor != v){
+			XSetForeground(xdisplay, gc, v);
+			xgcfillcolor = v;
+		}
+	}
+	XFillRectangle(xdisplay, dxm->pmid, gc, r.min.x, r.min.y, Dx(r), Dy(r));
+}
+
+/*
+ * Replacements for libmemdraw routines.
+ * (They've been underscored.)
+ */
+Memimage*
+allocmemimage(Rectangle r, ulong chan)
+{
+	return xallocmemimage(r, chan, PMundef);
+}
+
+void
+freememimage(Memimage *m)
+{
+	Xmem *xm;
+	
+	if(m == nil)
+		return;
+		
+	if(m->data->ref == 1){
+		if((xm = m->X) != nil){
+			if(xm->xi){
+				xm->xi->data = nil;
+				XFree(xm->xi);
+			}
+			XFreePixmap(xdisplay, xm->pmid);
+			free(xm);
+			m->X = nil;
+		}
+	}
+	_freememimage(m);
+}
+
+void
+memfillcolor(Memimage *m, ulong val)
+{
+	_memfillcolor(m, val);
+	if(m->X){
+		if((val & 0xFF) == 0xFF)
+			xfillcolor(m, m->r, _rgbatoimg(m, val));
+		else
+			putXdata(m, m->r);
+	}
+}
+
+int
+loadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
+{
+	int n;
+
+	n = _loadmemimage(i, r, data, ndata);
+	if(n > 0 && i->X)
+		putXdata(i, r);
+	return n;
+}
+
+int
+cloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
+{
+	int n;
+
+	n = _cloadmemimage(i, r, data, ndata);
+	if(n > 0 && i->X)
+		putXdata(i, r);
+	return n;
+}
+
+ulong
+pixelbits(Memimage *m, Point p)
+{
+	if(m->X)
+		getXdata(m, Rect(p.x, p.y, p.x+1, p.y+1));
+	return _pixelbits(m, p);
+}
+
+void
+memimageinit(void)
+{
+	static int didinit = 0;
+	
+	if(didinit)
+		return;
+
+	didinit = 1;
+	_memimageinit();
+	
+	xfillcolor(memblack, memblack->r, 0);
+	xfillcolor(memwhite, memwhite->r, 1);
+}
+
+void
+memimagedraw(Memimage *dst, Rectangle r, Memimage *src, Point sp, Memimage *mask, Point mp, int op)
+{
+	Memdrawparam *par;
+	
+	if((par = _memimagedrawsetup(dst, r, src, sp, mask, mp, op)) == nil)
+		return;
+	_memimagedraw(par);
+	if(!xdraw(par))
+		putXdata(dst, par->r);
+}
+
+static int
+xdraw(Memdrawparam *par)
+{
+	int dy, dx;
+	unsigned m;
+	Memimage *src, *dst, *mask;
+	Xmem *dxm, *sxm, *mxm;
+	GC gc;
+	Rectangle r, sr, mr;
+	ulong sdval;
+
+	dx = Dx(par->r);
+	dy = Dy(par->r);
+	src = par->src;
+	dst = par->dst;
+	mask = par->mask;
+	r = par->r;
+	sr = par->sr;
+	mr = par->mr;
+	sdval = par->sdval;
+
+	/*
+	 * drawterm was distributed for years with
+	 * "return 0;" right here.
+	 * maybe we should give up on all this?
+	 */
+
+	if((dxm = dst->X) == nil)
+		return 0;
+
+	/*
+	 * If we have an opaque mask and source is one opaque pixel we can convert to the
+	 * destination format and just XFillRectangle.
+	 */
+	m = Simplesrc|Simplemask|Fullmask;
+	if((par->state&m)==m){
+		xfillcolor(dst, r, sdval);
+		dirtyXdata(dst, par->r);
+		return 1;
+	}
+
+	/*
+	 * If no source alpha, an opaque mask, we can just copy the
+	 * source onto the destination.  If the channels are the same and
+	 * the source is not replicated, XCopyArea suffices.
+	 */
+	m = Simplemask|Fullmask;
+	if((par->state&(m|Replsrc))==m && src->chan == dst->chan && src->X){
+		sxm = src->X;
+		r = rectsubpt(r, dst->r.min);		
+		sr = rectsubpt(sr, src->r.min);
+		if(dst->chan == GREY1)
+			gc = xgccopy0;
+		else
+			gc = xgccopy;
+		XCopyArea(xdisplay, sxm->pmid, dxm->pmid, gc, 
+			sr.min.x, sr.min.y, dx, dy, r.min.x, r.min.y);
+		dirtyXdata(dst, par->r);
+		return 1;
+	}
+	
+	/*
+	 * If no source alpha, a 1-bit mask, and a simple source
+	 * we can just copy through the mask onto the destination.
+	 */
+	if(dst->X && mask->X && !(mask->flags&Frepl)
+	&& mask->chan == GREY1 && (par->state&Simplesrc)){
+		Point p;
+
+		mxm = mask->X;
+		r = rectsubpt(r, dst->r.min);		
+		mr = rectsubpt(mr, mask->r.min);
+		p = subpt(r.min, mr.min);
+		if(dst->chan == GREY1){
+			gc = xgcsimplesrc0;
+			if(xgcsimplecolor0 != sdval){
+				XSetForeground(xdisplay, gc, sdval);
+				xgcsimplecolor0 = sdval;
+			}
+			if(xgcsimplepm0 != mxm->pmid){
+				XSetStipple(xdisplay, gc, mxm->pmid);
+				xgcsimplepm0 = mxm->pmid;
+			}
+		}else{
+		/* somehow this doesn't work on rob's mac 
+			gc = xgcsimplesrc;
+			if(dst->chan == CMAP8 && xtblbit)
+				sdval = plan9tox11[sdval];
+				
+			if(xgcsimplecolor != sdval){
+				XSetForeground(xdisplay, gc, sdval);
+				xgcsimplecolor = sdval;
+			}
+			if(xgcsimplepm != mxm->pmid){
+				XSetStipple(xdisplay, gc, mxm->pmid);
+				xgcsimplepm = mxm->pmid;
+			}
+		*/
+			return 0;
+		}
+		XSetTSOrigin(xdisplay, gc, p.x, p.y);
+		XFillRectangle(xdisplay, dxm->pmid, gc, r.min.x, r.min.y, dx, dy);
+		dirtyXdata(dst, par->r);
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * X11 window management and kernel hooks.
+ * Oh, how I loathe this code!
+ */
+
+static XColor			map[256];	/* Plan 9 colormap array */
+static XColor			map7[128];	/* Plan 9 colormap array */
+static uchar			map7to8[128][2];
+static Colormap		xcmap;		/* Default shared colormap  */
 
-XColor			map[256];	/* Plan 9 colormap array */
-XColor			map7[128];	/* Plan 9 colormap array */
-uchar			map7to8[128][2];
-Colormap		xcmap;		/* Default shared colormap  */
-int 			plan9tox11[256]; /* Values for mapping between */
-int 			x11toplan9[256]; /* X11 and Plan 9 */
-int				x24bitswap = 0;	/* swap endian for 24bit RGB */
-int				xtblbit;
 extern int mousequeue;
 
 /* for copy/paste, lifted from plan9ports */
-Atom clipboard; 
-Atom utf8string;
-Atom targets;
-Atom text;
-Atom compoundtext;
+static Atom clipboard; 
+static Atom utf8string;
+static Atom targets;
+static Atom text;
+static Atom compoundtext;
 
 static	Drawable	xdrawable;
-/* static	Atom		wm_take_focus; */
 static	void		xexpose(XEvent*);
 static	void		xmouse(XEvent*);
 static	void		xkeyboard(XEvent*);
 static	void		xmapping(XEvent*);
 static	void		xdestroy(XEvent*);
-static	void		xselect(XEvent*, Display*);
+static	void		xselect(XEvent*, XDisplay*);
 static	void		xproc(void*);
 static	Memimage*		xinitscreen(void);
 static	void		initmap(Window);
 static	GC		creategc(Drawable);
 static	void		graphicscmap(XColor*);
-	int		xscreendepth;
-	Drawable	xscreenid;
-	Display*	xdisplay;	/* used holding draw lock */
-	Display*	xkmcon;	/* used only in xproc */
-	Display*	xsnarfcon;	/* used holding clip.lk */
-	Visual		*xvis;
-	GC		xgcfill, xgccopy, xgcsimplesrc, xgczero, xgcreplsrc;
-	GC		xgcfill0, xgccopy0, xgcsimplesrc0, xgczero0, xgcreplsrc0;
-	ulong		xblack;
-	ulong		xwhite;
-	ulong	xscreenchan;
-
-static int putsnarf, assertsnarf;
-
-extern Memimage* xallocmemimage(IRectangle, ulong, int);
-Memimage *gscreen;
-Screeninfo screen;
-XImage *ximage;
+static	int		xscreendepth;
+static	XDisplay*	xkmcon;	/* used only in xproc */
+static	XDisplay*	xsnarfcon;	/* used holding clip.lk */
+static	ulong		xblack;
+static	ulong		xwhite;
+
+static	int	putsnarf, assertsnarf;
+
+	Memimage *gscreen;
+	Screeninfo screen;
+
+void
+flushmemscreen(Rectangle r)
+{
+	assert(!drawcanqlock());
+	if(r.min.x >= r.max.x || r.min.y >= r.max.y)
+		return;
+	XCopyArea(xdisplay, xscreenid, xdrawable, xgccopy, r.min.x, r.min.y, Dx(r), Dy(r), r.min.x, r.min.y);
+	XFlush(xdisplay);
+}
 
 void
 screeninit(void)
@@ -121,7 +561,7 @@ screeninit(void)
 }
 
 uchar*
-attachscreen(IRectangle *r, ulong *chan, int *depth,
+attachscreen(Rectangle *r, ulong *chan, int *depth,
 	int *width, int *softscreen, void **X)
 {
 	*r = gscreen->r;
@@ -134,16 +574,6 @@ attachscreen(IRectangle *r, ulong *chan, int *depth,
 	return gscreen->data->bdata;
 }
 
-void
-flushmemscreen(IRectangle r)
-{
-	assert(!drawcanqlock());
-	if(r.min.x >= r.max.x || r.min.y >= r.max.y)
-		return;
-	XCopyArea(xdisplay, xscreenid, xdrawable, xgccopy, r.min.x, r.min.y, Dx(r), Dy(r), r.min.x, r.min.y);
-	XFlush(xdisplay);
-}
-
 static int
 revbyte(int b)
 {
@@ -162,7 +592,7 @@ revbyte(int b)
 }
 
 void
-mouseset(IPoint xy)
+mouseset(Point xy)
 {
 	drawqlock();
 	XWarpPointer(xdisplay, None, xdrawable, 0, 0, 0, 0, xy.x, xy.y);
@@ -170,12 +600,12 @@ mouseset(IPoint xy)
 	drawqunlock();
 }
 
-static Cursor xcursor;
+static XCursor xcursor;
 
 void
 setcursor(void)
 {
-	Cursor xc;
+	XCursor xc;
 	XColor fg, bg;
 	Pixmap xsrc, xmask;
 	int i;
@@ -249,7 +679,7 @@ xproc(void *arg)
 }
 
 static int
-shutup(Display *d, XErrorEvent *e)
+shutup(XDisplay *d, XErrorEvent *e)
 {
 	char buf[200];
 	iprint("X error: error code=%d, request_code=%d, minor=%d\n", e->error_code, e->request_code, e->minor_code);
@@ -261,7 +691,7 @@ shutup(Display *d, XErrorEvent *e)
 }
 
 static int
-panicshutup(Display *d)
+panicshutup(XDisplay *d)
 {
 	panic("x error");
 	return -1;
@@ -275,9 +705,9 @@ xinitscreen(void)
 	char *argv[2];
 	char *disp_val;
 	Window rootwin;
-	IRectangle r;
+	Rectangle r;
 	XWMHints hints;
-	Screen *screen;
+	XScreen *screen;
 	XVisualInfo xvi;
 	int rootscreennum;
 	XTextProperty name;
@@ -286,16 +716,15 @@ xinitscreen(void)
 	XSetWindowAttributes attrs;
 	XPixmapFormatValues *pfmt;
 	int n;
- 
+	Pixmap icon_pixmap;
+
 	xscreenid = 0;
 	xdrawable = 0;
 
 	xdisplay = XOpenDisplay(NULL);
 	if(xdisplay == 0){
-		disp_val = getenv("DISPLAY");
-		if(disp_val == 0)
-			disp_val = "not set";
-		iprint("drawterm: open %r, DISPLAY is %s\n", disp_val);
+		iprint("xinitscreen: XOpenDisplay: %r [DISPLAY=%s]\n",
+			getenv("DISPLAY"));
 		exit(0);
 	}
 
@@ -375,12 +804,10 @@ xinitscreen(void)
 		initmap(rootwin);
 	}
 
-
 	r.min = ZP;
 	r.max.x = WidthOfScreen(screen);
 	r.max.y = HeightOfScreen(screen);
 
-	
 	xsize = Dx(r)*3/4;
 	ysize = Dy(r)*3/4;
 	
@@ -391,6 +818,11 @@ xinitscreen(void)
 	xdrawable = XCreateWindow(xdisplay, rootwin, 0, 0, xsize, ysize, 0, 
 		xscreendepth, InputOutput, xvis, CWBackPixel|CWBorderPixel|CWColormap, &attrs);
 
+	/* load the given bitmap data and create an X pixmap containing it. */
+	icon_pixmap = XCreateBitmapFromData(xdisplay,
+		rootwin, (char *)glenda_bits,
+		glenda_width, glenda_height);
+
 	/*
 	 * set up property as required by ICCCM
 	 */
@@ -403,9 +835,11 @@ xinitscreen(void)
 	normalhints.max_height = Dy(r);
 	normalhints.width = xsize;
 	normalhints.height = ysize;
-	hints.flags = InputHint|StateHint;
+	hints.flags = IconPixmapHint |InputHint|StateHint;
 	hints.input = 1;
 	hints.initial_state = NormalState;
+	hints.icon_pixmap = icon_pixmap;
+
 	classhints.res_name = "drawterm";
 	classhints.res_class = "Drawterm";
 	argv[0] = "drawterm";
@@ -660,7 +1094,7 @@ creategc(Drawable d)
 static void
 xexpose(XEvent *e)
 {
-	IRectangle r;
+	Rectangle r;
 	XExposeEvent *xe;
 
 	if(e->type != Expose)
@@ -764,6 +1198,20 @@ xkeyboard(XEvent *e)
 		case XK_Alt_R:
 			k = Kalt;
 			break;
+		case XK_F1:
+		case XK_F2:
+		case XK_F3:
+		case XK_F4:
+		case XK_F5:
+		case XK_F6:
+		case XK_F7:
+		case XK_F8:
+		case XK_F9:
+		case XK_F10:
+		case XK_F11:
+		case XK_F12:
+			k = KF|(k - XK_F1 + 1);
+			break;
 		case XK_Shift_L:
 		case XK_Shift_R:
 		case XK_Control_L:
@@ -792,7 +1240,7 @@ xkeyboard(XEvent *e)
 	if(k == XK_hyphen)
 		k = XK_minus;
 	/* Do control mapping ourselves if translator doesn't */
-	if(e->xkey.state&ControlMask)
+	if(e->xkey.state&ControlMask && k != Kalt)
 		k &= 0x9f;
 	if(k == NoSymbol) {
 		return;
@@ -987,11 +1435,12 @@ Clip clip;
 #undef ulong
 
 static char*
-_xgetsnarf(Display *xd)
+_xgetsnarf(XDisplay *xd)
 {
 	uchar *data, *xdata;
 	Atom clipboard, type, prop;
-	unsigned long len, lastlen, dummy;
+	unsigned long lastlen;
+	unsigned long dummy, len;
 	int fmt, i;
 	Window w;
 
@@ -1078,7 +1527,7 @@ out:
 }
 
 static void
-_xputsnarf(Display *xd, char *data)
+_xputsnarf(XDisplay *xd, char *data)
 {
 	XButtonEvent e;
 
@@ -1102,7 +1551,7 @@ _xputsnarf(Display *xd, char *data)
 }
 
 static void
-xselect(XEvent *e, Display *xd)
+xselect(XEvent *e, XDisplay *xd)
 {
 	char *name;
 	XEvent r;
@@ -1123,21 +1572,31 @@ if(0) iprint("xselect target=%d requestor=%d property=%d selection=%d\n",
 		a[2] = text;
 		a[3] = compoundtext;
 
-		XChangeProperty(xd, xe->requestor, xe->property, xe->target,
-			8, PropModeReplace, (uchar*)a, sizeof a);
+		XChangeProperty(xd, xe->requestor, xe->property, XA_ATOM,
+			32, PropModeReplace, (uchar*)a, sizeof a);
 	}else if(xe->target == XA_STRING || xe->target == utf8string || xe->target == text || xe->target == compoundtext){
+	text:
 		/* if the target is STRING we're supposed to reply with Latin1 XXX */
 		qlock(&clip.lk);
 		XChangeProperty(xd, xe->requestor, xe->property, xe->target,
 			8, PropModeReplace, (uchar*)clip.buf, strlen(clip.buf));
 		qunlock(&clip.lk);
 	}else{
-		iprint("get %d\n", xe->target);
 		name = XGetAtomName(xd, xe->target);
 		if(name == nil)
-			iprint("XGetAtomName failed\n");
-		else if(strcmp(name, "TIMESTAMP") != 0)
-			iprint("%s: cannot handle selection request for '%s' (%d)\n", argv0, name, (int)xe->target);
+			iprint("XGetAtomName %d failed\n", xe->target);
+		if(name){
+			if(strcmp(name, "TIMESTAMP") == 0){
+				/* nothing */
+			}else if(strncmp(name, "image/", 6) == 0){
+				/* nothing */
+			}else if(strcmp(name, "text/html") == 0){
+				/* nothing */
+			}else if(strcmp(name, "text/plain") == 0 || strcmp(name, "text/plain;charset=UTF-8") == 0){
+				goto text;
+			}else
+				iprint("%s: cannot handle selection request for '%s' (%d)\n", argv0, name, (int)xe->target);
+		}
 		r.xselection.property = None;
 	}
 

+ 0 - 60
sys/src/cmd/unix/drawterm/gui-x11/xmem.h

@@ -1,60 +0,0 @@
-#define	Font	XXFont
-#define	Screen	XXScreen
-#define	Display	XXDisplay
-
-#include <X11/Xlib.h>
-/* #include <X11/Xlibint.h> */
-#include <X11/Xatom.h>
-#include <X11/Xutil.h>
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-
-#undef	Font
-#undef	Screen
-#undef	Display
-
-/*
- * Structure pointed to by X field of Memimage
- */
-typedef struct Xmem Xmem;
-
-enum
-{
-	PMundef	= ~0		/* undefined pixmap id */
-};
-
-
-struct Xmem
-{
-	int	pmid;	/* pixmap id for screen ldepth instance */
-	XImage *xi;	/* local image if we currenty have the data */
-	int	dirty;
-	Rectangle dirtyr;
-	Rectangle r;
-	uintptr pc;	/* who wrote into xi */
-};
-
-extern	int		xtblbit;
-extern	int		x24bitswap;
-extern	int		plan9tox11[];
-extern  int		x11toplan9[];
-extern	int		xscreendepth;
-extern	XXDisplay	*xdisplay;
-extern	Drawable	xscreenid;
-extern	Visual		*xvis;
-extern	GC		xgcfill, xgcfill0;
-extern	int		xgcfillcolor, xgcfillcolor0;
-extern	GC		xgccopy, xgccopy0;
-extern	GC		xgczero, xgczero0;
-extern	int		xgczeropm, xgczeropm0;
-extern	GC		xgcsimplesrc, xgcsimplesrc0;
-extern	int		xgcsimplecolor, xgcsimplecolor0, xgcsimplepm, xgcsimplepm0;
-extern	GC		xgcreplsrc, xgcreplsrc0;
-extern	int		xgcreplsrcpm, xgcreplsrcpm0, xgcreplsrctile, xgcreplsrctile0;
-extern	XImage*		allocXdata(Memimage*, Rectangle);
-extern	void 		putXdata(Memimage*, Rectangle);
-extern	XImage*		getXdata(Memimage*, Rectangle);
-extern	void		freeXdata(Memimage*);
-extern	void	dirtyXdata(Memimage*, Rectangle);
-extern	ulong	xscreenchan;
-extern	void	xfillcolor(Memimage*, Rectangle, ulong);

+ 1 - 1
sys/src/cmd/unix/drawterm/include/fcall.h

@@ -37,7 +37,7 @@ struct	Fcall
 #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)

+ 38 - 0
sys/src/cmd/unix/drawterm/include/ip.h

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

+ 3 - 0
sys/src/cmd/unix/drawterm/include/lib.h

@@ -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 */

+ 0 - 0
sys/src/cmd/unix/drawterm/include/x


+ 268 - 0
sys/src/cmd/unix/drawterm/kern/devaudio-sun.c

@@ -0,0 +1,268 @@
+/*
+ * Sun
+ */
+#include <sys/ioctl.h>
+#include <sys/audio.h>
+#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+1<n; i+=2) {
+			buf[i] = p[i+1];
+			buf[i+1] = p[i];
+		}
+		p = buf;
+	} else
+		p = (uchar*)v;
+	
+	for(tot=0; tot<n; tot+=m)
+		if((m = write(afd, p+tot, n-tot)) <= 0)
+			oserror();
+	return tot;
+}
+
+int
+audiodevread(void *v, int n)
+{
+	error("no reading");
+	return -1;
+}

+ 8 - 7
sys/src/cmd/unix/drawterm/kern/devfs-posix.c

@@ -425,6 +425,14 @@ fswstat(Chan *c, uchar *buf, int n)
 
 	uif = c->aux;
 
+	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 @@ fswstat(Chan *c, uchar *buf, int n)
 			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)

+ 114 - 41
sys/src/cmd/unix/drawterm/kern/devip-posix.c

@@ -3,12 +3,14 @@
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <netdb.h>
+#include <arpa/inet.h>
 
 #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 @@ osipinit(void)
 }
 
 int
-so_socket(int type)
+so_socket(int type, unsigned char *addr)
 {
 	int fd, one;
 
@@ -41,7 +63,7 @@ so_socket(int type)
 		break;
 	}
 
-	fd = socket(AF_INET, type, 0);
+	fd = socket(family(addr), type, 0);
 	if(fd < 0)
 		oserror();
 
@@ -54,36 +76,52 @@ so_socket(int type)
 	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));
 
-	memset(&sin, 0, sizeof(sin));
-	sin.sin_family = AF_INET;
-	hnputs(&sin.sin_port, rport);
-	hnputl(&sin.sin_addr.s_addr, raddr);
+	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*)&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 @@ so_listen(int fd)
 }
 
 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 @@ so_bind(int fd, int su, unsigned short port)
 
 	if(su) {
 		for(i = 600; i < 1024; i++) {
-			memset(&sin, 0, sizeof(sin));
-			sin.sin_family = AF_INET;
-			sin.sin_port = i;
-
-			if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) >= 0)	
+			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*)&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();
 }
 
@@ -170,16 +231,28 @@ so_gethostbyname(char *host, char**hostv, int n)
 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);
 }

+ 104 - 41
sys/src/cmd/unix/drawterm/kern/devip-win32.c

@@ -1,9 +1,11 @@
 #include <windows.h>
+#include <ws2tcpip.h>
 #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 @@ osipinit(void)
 }
 
 int
-so_socket(int type)
+so_socket(int type, unsigned char *addr)
 {
 	int fd, one;
 
@@ -44,7 +66,7 @@ so_socket(int type)
 		break;
 	}
 
-	fd = socket(AF_INET, type, 0);
+	fd = socket(family(addr), type, 0);
 	if(fd < 0)
 		oserror();
 
@@ -59,34 +81,51 @@ so_socket(int type)
 
 
 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 @@ so_listen(int fd)
 }
 
 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;
-
-			if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) >= 0)	
+			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*)&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 @@ hostlookup(char *host)
 {
 	char buf[100];
 	uchar *p;
-	HOSTENT *he;
+	struct hostent *he;
 
 	he = gethostbyname(host);
 	if(he != 0 && he->h_addr_list[0]) {

+ 37 - 182
sys/src/cmd/unix/drawterm/kern/devip.c

@@ -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 @@ enum
 #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 @@ struct Conv
 	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 @@ struct Proto
 
 static	int	np;
 static	Proto	proto[MAXPROTO];
-int	eipfmt(Fmt*);
 
 static	Conv*	protoclone(Proto*, char*, int);
 static	void	setladdr(Conv*);
@@ -222,7 +218,7 @@ Chan *
 ipopen(Chan *c, int omode)
 {
 	Proto *p;
-	ulong raddr;
+	uchar raddr[IPaddrlen];
 	ushort rport;
 	int perm, sfd;
 	Conv *cv, *lcv;
@@ -286,13 +282,13 @@ ipopen(Chan *c, int omode)
 	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 @@ ipclose(Chan *c)
 		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 @@ ipread(Chan *ch, void *a, long n, vlong offset)
 	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 @@ ipread(Chan *ch, void *a, long n, vlong offset)
 		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 @@ ipread(Chan *ch, void *a, long n, vlong offset)
 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 @@ setlport(Conv *c)
 	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 @@ setladdrport(Conv *c, char *str)
 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 @@ ipwrite(Chan *ch, void *a, long n, vlong offset)
 				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 @@ protoclone(Proto *p, char *user, int nfd)
 	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 @@ protoclone(Proto *p, char *user, int nfd)
 	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 @@ lookupport(char *s)
 	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 @@ cswrite(Chan *c, void *a, long n, vlong offset)
 {
 	char *f[4];
 	char *s, *ns;
-	ulong ip;
+	uchar ip[IPaddrlen];
 	int nf, port;
 
 	s = malloc(n+1);
@@ -900,8 +756,7 @@ cswrite(Chan *c, void *a, long n, vlong offset)
 	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);

+ 5 - 5
sys/src/cmd/unix/drawterm/kern/devip.h

@@ -4,14 +4,14 @@ enum
 	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);
 

+ 0 - 6
sys/src/cmd/unix/drawterm/kern/fns.h

@@ -375,12 +375,6 @@ Segment*	data2txt(Segment*);
 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*);

+ 19 - 0
sys/src/cmd/unix/drawterm/libip/Makefile

@@ -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
+

+ 77 - 0
sys/src/cmd/unix/drawterm/libip/bo.c

@@ -0,0 +1,77 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+
+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);
+}

+ 86 - 0
sys/src/cmd/unix/drawterm/libip/classmask.c

@@ -0,0 +1,86 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+
+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];
+}

+ 109 - 0
sys/src/cmd/unix/drawterm/libip/eipfmt.c

@@ -0,0 +1,109 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+
+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)");
+}

+ 102 - 0
sys/src/cmd/unix/drawterm/libip/ipaux.c

@@ -0,0 +1,102 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+
+/*
+ *  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;
+	}
+}

+ 185 - 0
sys/src/cmd/unix/drawterm/libip/parseip.c

@@ -0,0 +1,185 @@
+#include <u.h>
+#include <libc.h>
+#include <ctype.h>
+#include <ip.h>
+
+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;
+}

+ 136 - 72
sys/src/cmd/unix/drawterm/libmemdraw/draw.c

@@ -10,22 +10,34 @@ static int	tablesbuilt;
 #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 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 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 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 @@ drawclip(Memimage *dst, Rectangle *r, Memimage *src, Point *p0, Memimage *mask,
  * 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 int replmul[1+8] = {
 static void
 mktables(void)
 {
-	int i, j, small;
+	int i, j, mask, sh, small;
 		
 	if(tablesbuilt)
 		return;
@@ -357,6 +372,17 @@ mktables(void)
 		}
 	}
 
+	/* 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 @@ alphacalc0(Buffer bdst, Buffer b1, Buffer b2, int dx, int grey, int op)
 	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; i<dx; i++){
 		sa = *bsrc.alpha;
 		ma = *bmask.alpha;
-		fd = MUL(sa, ma, t);
+		fd = CALC11(sa, ma, t);
 		if(op == DoutS)
 			fd = 255-fd;
 
 		if(grey){
-			*bdst.grey = MUL(fd, *bdst.grey, t);
+			*bdst.grey = CALC11(fd, *bdst.grey, t);
 			bsrc.grey += bsrc.delta;
 			bdst.grey += bdst.delta;
 		}else{
 			if(q){
-				*bdst.rgba = MUL0123(fd, *bdst.rgba, s, t);
+				*bdst.rgba = CALC41(fd, *bdst.rgba, t, t1);
 				bsrc.rgba++;
 				bdst.rgba++;
 				bsrc.alpha += sadelta;
 				bmask.alpha += bmask.delta;
 				continue;
 			}
-			*bdst.red = MUL(fd, *bdst.red, t);
-			*bdst.grn = MUL(fd, *bdst.grn, t);
-			*bdst.blu = MUL(fd, *bdst.blu, t);
+			*bdst.red = CALC11(fd, *bdst.red, t);
+			*bdst.grn = CALC11(fd, *bdst.grn, t);
+			*bdst.blu = CALC11(fd, *bdst.blu, t);
 			bsrc.red += bsrc.delta;
 			bsrc.blu += bsrc.delta;
 			bsrc.grn += bsrc.delta;
@@ -813,7 +883,7 @@ alphacalc14(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
 			bdst.grn += bdst.delta;
 		}
 		if(bdst.alpha != &ones){
-			*bdst.alpha = MUL(fd, *bdst.alpha, t);
+			*bdst.alpha = CALC11(fd, *bdst.alpha, t);
 			bdst.alpha += bdst.delta;
 		}
 		bmask.alpha += bmask.delta;
@@ -828,11 +898,11 @@ alphacalc2810(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
 	Buffer obdst;
 	int fs, sadelta;
 	int i, ma, da, 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; i<dx; i++){
 		ma = *bmask.alpha;
@@ -841,24 +911,24 @@ alphacalc2810(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
 			da = 255-da;
 		fs = ma;
 		if(op != S)
-			fs = MUL(fs, da, t);
+			fs = CALC11(fs, da, t);
 
 		if(grey){
-			*bdst.grey = MUL(fs, *bsrc.grey, t);
+			*bdst.grey = CALC11(fs, *bsrc.grey, t);
 			bsrc.grey += bsrc.delta;
 			bdst.grey += bdst.delta;
 		}else{
 			if(q){
-				*bdst.rgba = MUL0123(fs, *bsrc.rgba, s, t);
+				*bdst.rgba = CALC41(fs, *bsrc.rgba, t, t1);
 				bsrc.rgba++;
 				bdst.rgba++;
 				bmask.alpha += bmask.delta;
 				bdst.alpha += bdst.delta;
 				continue;
 			}
-			*bdst.red = MUL(fs, *bsrc.red, t);
-			*bdst.grn = MUL(fs, *bsrc.grn, t);
-			*bdst.blu = MUL(fs, *bsrc.blu, t);
+			*bdst.red = CALC11(fs, *bsrc.red, t);
+			*bdst.grn = CALC11(fs, *bsrc.grn, t);
+			*bdst.blu = CALC11(fs, *bsrc.blu, t);
 			bsrc.red += bsrc.delta;
 			bsrc.blu += bsrc.delta;
 			bsrc.grn += bsrc.delta;
@@ -867,7 +937,7 @@ alphacalc2810(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
 			bdst.grn += bdst.delta;
 		}
 		if(bdst.alpha != &ones){
-			*bdst.alpha = MUL(fs, *bsrc.alpha, t);
+			*bdst.alpha = CALC11(fs, *bsrc.alpha, t);
 			bdst.alpha += bdst.delta;
 		}
 		bmask.alpha += bmask.delta;
@@ -882,35 +952,35 @@ alphacalc3679(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
 	Buffer obdst;
 	int fs, fd, sadelta;
 	int i, sa, ma, da, q;
-	ulong s, t, u, v;
+	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; i<dx; i++){
 		sa = *bsrc.alpha;
 		ma = *bmask.alpha;
 		da = *bdst.alpha;
 		if(op == SatopD)
-			fs = MUL(ma, da, t);
+			fs = CALC11(ma, da, t);
 		else
-			fs = MUL(ma, 255-da, t);
+			fs = CALC11(ma, 255-da, t);
 		if(op == DoverS)
 			fd = 255;
 		else{
-			fd = MUL(sa, ma, t);
+			fd = CALC11(sa, ma, t);
 			if(op != DatopS)
 				fd = 255-fd;
 		}
 
 		if(grey){
-			*bdst.grey = MUL(fs, *bsrc.grey, s)+MUL(fd, *bdst.grey, t);
+			*bdst.grey = CALC12(fs, *bsrc.grey, fd, *bdst.grey, t);
 			bsrc.grey += bsrc.delta;
 			bdst.grey += bdst.delta;
 		}else{
 			if(q){
-				*bdst.rgba = MUL0123(fs, *bsrc.rgba, s, t)+MUL0123(fd, *bdst.rgba, u, v);
+				*bdst.rgba = CALC42(fs, *bsrc.rgba, fd, *bdst.rgba, t, t1);
 				bsrc.rgba++;
 				bdst.rgba++;
 				bsrc.alpha += sadelta;
@@ -918,9 +988,9 @@ alphacalc3679(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
 				bdst.alpha += bdst.delta;
 				continue;
 			}
-			*bdst.red = MUL(fs, *bsrc.red, s)+MUL(fd, *bdst.red, t);
-			*bdst.grn = MUL(fs, *bsrc.grn, s)+MUL(fd, *bdst.grn, t);
-			*bdst.blu = MUL(fs, *bsrc.blu, s)+MUL(fd, *bdst.blu, t);
+			*bdst.red = CALC12(fs, *bsrc.red, fd, *bdst.red, t);
+			*bdst.grn = CALC12(fs, *bsrc.grn, fd, *bdst.grn, t);
+			*bdst.blu = CALC12(fs, *bsrc.blu, fd, *bdst.blu, t);
 			bsrc.red += bsrc.delta;
 			bsrc.blu += bsrc.delta;
 			bsrc.grn += bsrc.delta;
@@ -929,7 +999,7 @@ alphacalc3679(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
 			bdst.grn += bdst.delta;
 		}
 		if(bdst.alpha != &ones){
-			*bdst.alpha = MUL(fs, sa, s)+MUL(fd, da, t);
+			*bdst.alpha = CALC12(fs, sa, fd, da, t);
 			bdst.alpha += bdst.delta;
 		}
 		bmask.alpha += bmask.delta;
@@ -953,34 +1023,34 @@ alphacalc11(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, u, v;
+	ulong t, t1;
 
 	USED(op);
 	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; i<dx; i++){
 		sa = *bsrc.alpha;
 		ma = *bmask.alpha;
-		fd = 255-MUL(sa, ma, t);
+		fd = 255-CALC11(sa, ma, t);
 
 		if(grey){
-			*bdst.grey = MUL(ma, *bsrc.grey, s)+MUL(fd, *bdst.grey, t);
+			*bdst.grey = CALC12(ma, *bsrc.grey, fd, *bdst.grey, t);
 			bsrc.grey += bsrc.delta;
 			bdst.grey += bdst.delta;
 		}else{
 			if(q){
-				*bdst.rgba = MUL0123(ma, *bsrc.rgba, s, t)+MUL0123(fd, *bdst.rgba, u, v);
+				*bdst.rgba = CALC42(ma, *bsrc.rgba, fd, *bdst.rgba, t, t1);
 				bsrc.rgba++;
 				bdst.rgba++;
 				bsrc.alpha += sadelta;
 				bmask.alpha += bmask.delta;
 				continue;
 			}
-			*bdst.red = MUL(ma, *bsrc.red, s)+MUL(fd, *bdst.red, t);
-			*bdst.grn = MUL(ma, *bsrc.grn, s)+MUL(fd, *bdst.grn, t);
-			*bdst.blu = MUL(ma, *bsrc.blu, s)+MUL(fd, *bdst.blu, t);
+			*bdst.red = CALC12(ma, *bsrc.red, fd, *bdst.red, t);
+			*bdst.grn = CALC12(ma, *bsrc.grn, fd, *bdst.grn, t);
+			*bdst.blu = CALC12(ma, *bsrc.blu, fd, *bdst.blu, t);
 			bsrc.red += bsrc.delta;
 			bsrc.blu += bsrc.delta;
 			bsrc.grn += bsrc.delta;
@@ -989,7 +1059,7 @@ alphacalc11(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
 			bdst.grn += bdst.delta;
 		}
 		if(bdst.alpha != &ones){
-			*bdst.alpha = MUL(ma, sa, s)+MUL(fd, *bdst.alpha, t);
+			*bdst.alpha = CALC12(ma, sa, fd, *bdst.alpha, t);
 			bdst.alpha += bdst.delta;
 		}
 		bmask.alpha += bmask.delta;
@@ -1045,7 +1115,7 @@ alphacalcS(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
 	Buffer obdst;
 	int fd;
 	int i, ma;
-	ulong s, t;
+	ulong t;
 
 	USED(op);
 	obdst = bdst;
@@ -1055,13 +1125,13 @@ alphacalcS(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
 		fd = 255-ma;
 
 		if(grey){
-			*bdst.grey = MUL(ma, *bsrc.grey, s)+MUL(fd, *bdst.grey, t);
+			*bdst.grey = CALC12(ma, *bsrc.grey, fd, *bdst.grey, t);
 			bsrc.grey += bsrc.delta;
 			bdst.grey += bdst.delta;
 		}else{
-			*bdst.red = MUL(ma, *bsrc.red, s)+MUL(fd, *bdst.red, t);
-			*bdst.grn = MUL(ma, *bsrc.grn, s)+MUL(fd, *bdst.grn, t);
-			*bdst.blu = MUL(ma, *bsrc.blu, s)+MUL(fd, *bdst.blu, t);
+			*bdst.red = CALC12(ma, *bsrc.red, fd, *bdst.red, t);
+			*bdst.grn = CALC12(ma, *bsrc.grn, fd, *bdst.grn, t);
+			*bdst.blu = CALC12(ma, *bsrc.blu, fd, *bdst.blu, t);
 			bsrc.red += bsrc.delta;
 			bsrc.blu += bsrc.delta;
 			bsrc.grn += bsrc.delta;
@@ -1070,7 +1140,7 @@ alphacalcS(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
 			bdst.grn += bdst.delta;
 		}
 		if(bdst.alpha != &ones){
-			*bdst.alpha = ma+MUL(fd, *bdst.alpha, t);
+			*bdst.alpha = ma+CALC11(fd, *bdst.alpha, t);
 			bdst.alpha += bdst.delta;
 		}
 		bmask.alpha += bmask.delta;
@@ -1117,7 +1187,7 @@ boolcalc236789(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
 	Buffer obdst;
 	int fs, fd;
 	int i, ma, da, zero;
-	ulong s, t;
+	ulong t;
 
 	obdst = bdst;
 	zero = !(op&1);
@@ -1134,16 +1204,16 @@ boolcalc236789(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
 
 		if(grey){
 			if(ma)
-				*bdst.grey = MUL(fs, *bsrc.grey, s)+MUL(fd, *bdst.grey, t);
+				*bdst.grey = CALC12(fs, *bsrc.grey, fd, *bdst.grey, t);
 			else if(zero)
 				*bdst.grey = 0;
 			bsrc.grey += bsrc.delta;
 			bdst.grey += bdst.delta;
 		}else{
 			if(ma){
-				*bdst.red = MUL(fs, *bsrc.red, s)+MUL(fd, *bdst.red, t);
-				*bdst.grn = MUL(fs, *bsrc.grn, s)+MUL(fd, *bdst.grn, t);
-				*bdst.blu = MUL(fs, *bsrc.blu, s)+MUL(fd, *bdst.blu, t);
+				*bdst.red = CALC12(fs, *bsrc.red, fd, *bdst.red, t);
+				*bdst.grn = CALC12(fs, *bsrc.grn, fd, *bdst.grn, t);
+				*bdst.blu = CALC12(fs, *bsrc.blu, fd, *bdst.blu, t);
 			}
 			else if(zero)
 				*bdst.red = *bdst.grn = *bdst.blu = 0;
@@ -1157,7 +1227,7 @@ boolcalc236789(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
 		bmask.alpha += bmask.delta;
 		if(bdst.alpha != &ones){
 			if(ma)
-				*bdst.alpha = fs+MUL(fd, da, t);
+				*bdst.alpha = fs+CALC11(fd, da, t);
 			else if(zero)
 				*bdst.alpha = 0;
 			bdst.alpha += bdst.delta;
@@ -1890,7 +1960,7 @@ boolcopyfn(Memimage *img, Memimage *mask)
 	default:
 		assert(0 /* boolcopyfn */);
 	}
-	return 0;
+	return nil;
 }
 
 /*
@@ -2353,7 +2423,7 @@ DBG print("bsh %d\n", bsh);
 
 	bx = -bsh-1;
 	ex = -bsh-1-dx;
-	bits = 0;
+	SET(bits);
 	v = par->sdval;
 
 	/* make little endian */
@@ -2457,7 +2527,6 @@ _memfillcolor(Memimage *i, ulong val)
 {
 	ulong bits;
 	int d, y;
-	uchar p[4];
 
 	if(val == DNofill)
 		return;
@@ -2471,11 +2540,6 @@ _memfillcolor(Memimage *i, ulong val)
 	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;
 	}

+ 1 - 1
sys/src/cmd/unix/drawterm/posix-arm/Makefile

@@ -6,7 +6,7 @@ OFILES=\
 	getcallerpc.$O\
 	md5block.$O\
 	sha1block.$O\
-	tas.$O\
+	tas.$O
 
 default: $(LIB)
 $(LIB): $(OFILES)

+ 1 - 1
sys/src/cmd/unix/drawterm/posix-arm/getcallerpc.c

@@ -4,5 +4,5 @@
 uintptr
 getcallerpc(void *a)
 {
-	return 0;
+	return ((uintptr*)a)[-1];
 }

+ 13 - 2
sys/src/cmd/unix/drawterm/posix-arm/tas.c

@@ -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 @@ tas(long *x)
 		return 1;
 	}
 }
+

+ 1 - 1
sys/src/cmd/usb/kb/kb.c

@@ -473,7 +473,7 @@ Abort:
 }
 
 
-#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)