tInitial import. - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit ed7c8e8d02c02bdbff1e88a6d8d1419f39af48ad
 (DIR) parent b2cfc4e2e71d0f0a5113ddfbd93c8285cc4d74e4
 (HTM) Author: rsc <devnull@localhost>
       Date:   Tue, 30 Sep 2003 17:47:42 +0000
       
       Initial import.
       
       Diffstat:
         A src/cmd/mk/NOTICE                   |      27 +++++++++++++++++++++++++++
         A src/cmd/mk/README                   |       7 +++++++
         A src/cmd/mk/bufblock.c               |      88 +++++++++++++++++++++++++++++++
         A src/cmd/mk/job.c                    |      33 +++++++++++++++++++++++++++++++
         A src/cmd/mk/mk.pdf                   |       0 
         A src/cmd/sam/README                  |      29 +++++++++++++++++++++++++++++
         A src/cmd/sam/_libc.h                 |      40 +++++++++++++++++++++++++++++++
         A src/cmd/sam/err                     |      39 +++++++++++++++++++++++++++++++
         A src/cmd/sam/plumb.h                 |      17 +++++++++++++++++
         A src/cmd/sam/string.c                |     193 +++++++++++++++++++++++++++++++
         A src/cmd/sam/sys.c                   |      60 +++++++++++++++++++++++++++++++
         A src/cmd/sam/util.c                  |      54 +++++++++++++++++++++++++++++++
         A src/libdraw/allocimagemix.c         |      43 ++++++++++++++++++++++++++++++
         A src/libdraw/bezier.c                |     244 +++++++++++++++++++++++++++++++
         A src/libdraw/border.c                |      21 +++++++++++++++++++++
         A src/libdraw/cloadimage.c            |      49 +++++++++++++++++++++++++++++++
         A src/libdraw/computil.c              |      38 +++++++++++++++++++++++++++++++
         A src/libdraw/debug.c                 |      16 ++++++++++++++++
         A src/libdraw/defont.c                |     402 ++++++++++++++++++++++++++++++
         A src/libdraw/draw.c                  |      69 ++++++++++++++++++++++++++++++
         A src/libdraw/drawrepl.c              |      23 +++++++++++++++++++++++
         A src/libdraw/egetrect.c              |     116 ++++++++++++++++++++++++++++++
         A src/libdraw/freesubfont.c           |      17 +++++++++++++++++
         A src/libdraw/getdefont.c             |      60 +++++++++++++++++++++++++++++++
         A src/libdraw/getrect.c               |     133 +++++++++++++++++++++++++++++++
         A src/libdraw/icossin.c               |     140 +++++++++++++++++++++++++++++++
         A src/libdraw/icossin2.c              |     261 +++++++++++++++++++++++++++++++
         A src/libdraw/line.c                  |      35 +++++++++++++++++++++++++++++++
         A src/libdraw/loadimage.c             |      54 +++++++++++++++++++++++++++++++
         A src/libdraw/mkfont.c                |      55 +++++++++++++++++++++++++++++++
         A src/libdraw/newwindow.c             |      27 +++++++++++++++++++++++++++
         A src/libdraw/poly.c                  |      87 +++++++++++++++++++++++++++++++
         A src/libdraw/rectclip.c              |      25 +++++++++++++++++++++++++
         A src/libdraw/replclipr.c             |      21 +++++++++++++++++++++
         A src/libdraw/rgb.c                   |      99 +++++++++++++++++++++++++++++++
         A src/libdraw/stringbg.c              |      51 +++++++++++++++++++++++++++++++
         A src/libdraw/stringsubfont.c         |      65 +++++++++++++++++++++++++++++++
         A src/libdraw/test.c                  |      44 +++++++++++++++++++++++++++++++
         A src/libdraw/window.c                |     214 +++++++++++++++++++++++++++++++
         A src/libdraw/writeimage.c            |     185 ++++++++++++++++++++++++++++++
         A src/libdraw/writesubfont.c          |      45 +++++++++++++++++++++++++++++++
       
       41 files changed, 3226 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/mk/NOTICE b/src/cmd/mk/NOTICE
       t@@ -0,0 +1,27 @@
       +Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
       +Portions Copyright © 1995-1997 C H Forsyth (forsyth@caldo.demon.co.uk).  All rights reserved.
       +Portions Copyright © 1997-1999 Vita Nuova Limited.  All rights reserved.
       +Portions Copyright © 2000-2002 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
       +
       +Under a licence agreement with Lucent Technologies Inc. effective 1st March 2000,
       +Vita Nuova Holdings Limited has the right to determine (within a specified scope)
       +the form and content of sublicences for this software.
       +
       +Vita Nuova Holdings Limited now makes this software available as Free
       +Software under the terms of the `GNU General Public LIcense, Version 2'
       +(see the file LICENCE or http://www.fsf.org/copyleft/gpl.html for
       +the full terms and conditions).  One of the conditions of that licence
       +is that you must keep intact all notices that refer to that licence and to the absence of
       +of any warranty: for this software, note that includes this NOTICE file in particular.
       +  
       +This suite of programs is distributed in the hope that it will be useful,
       +but WITHOUT ANY WARRANTY; without even the implied warranty of
       +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       +`GNU General Public License' for more details.
       +
       +This copyright NOTICE applies to all files in this directory and
       +subdirectories, unless another copyright notice appears in a given
       +file or subdirectory.  If you take code from this software to use in
       +other programs, you must somehow include with it an appropriate
       +copyright notice that includes the copyright notice and the other
       +notices above.
 (DIR) diff --git a/src/cmd/mk/README b/src/cmd/mk/README
       t@@ -0,0 +1,7 @@
       +This is a Unix port of mk,
       +originally done for the Inferno operating system.
       +
       +Russ Cox repackaged this to build as a standalone
       +Unix program.  Send comments about packaging to
       +Russ Cox <rsc@post.harvard.edu>
       +
 (DIR) diff --git a/src/cmd/mk/bufblock.c b/src/cmd/mk/bufblock.c
       t@@ -0,0 +1,88 @@
       +#include        "mk.h"
       +
       +static Bufblock *freelist;
       +#define        QUANTA        4096
       +
       +Bufblock *
       +newbuf(void)
       +{
       +        Bufblock *p;
       +
       +        if (freelist) {
       +                p = freelist;
       +                freelist = freelist->next;
       +        } else {
       +                p = (Bufblock *) Malloc(sizeof(Bufblock));
       +                p->start = Malloc(QUANTA*sizeof(*p->start));
       +                p->end = p->start+QUANTA;
       +        }
       +        p->current = p->start;
       +        *p->start = 0;
       +        p->next = 0;
       +        return p;
       +}
       +
       +void
       +freebuf(Bufblock *p)
       +{
       +        p->next = freelist;
       +        freelist = p;
       +}
       +
       +void
       +growbuf(Bufblock *p)
       +{
       +        int n;
       +        Bufblock *f;
       +        char *cp;
       +
       +        n = p->end-p->start+QUANTA;
       +                /* search the free list for a big buffer */
       +        for (f = freelist; f; f = f->next) {
       +                if (f->end-f->start >= n) {
       +                        memcpy(f->start, p->start, p->end-p->start);
       +                        cp = f->start;
       +                        f->start = p->start;
       +                        p->start = cp;
       +                        cp = f->end;
       +                        f->end = p->end;
       +                        p->end = cp;
       +                        f->current = f->start;
       +                        break;
       +                }
       +        }
       +        if (!f) {                /* not found - grow it */
       +                p->start = Realloc(p->start, n);
       +                p->end = p->start+n;
       +        }
       +        p->current = p->start+n-QUANTA;
       +}
       +
       +void
       +bufcpy(Bufblock *buf, char *cp, int n)
       +{
       +
       +        while (n--)
       +                insert(buf, *cp++);
       +}
       +
       +void
       +insert(Bufblock *buf, int c)
       +{
       +
       +        if (buf->current >= buf->end)
       +                growbuf(buf);
       +        *buf->current++ = c;
       +}
       +
       +void
       +rinsert(Bufblock *buf, Rune r)
       +{
       +        int n;
       +
       +        n = runelen(r);
       +        if (buf->current+n > buf->end)
       +                growbuf(buf);
       +        runetochar(buf->current, &r);
       +        buf->current += n;
       +}
 (DIR) diff --git a/src/cmd/mk/job.c b/src/cmd/mk/job.c
       t@@ -0,0 +1,33 @@
       +#include        "mk.h"
       +
       +Job *
       +newjob(Rule *r, Node *nlist, char *stem, char **match, Word *pre, Word *npre, Word *tar, Word *atar)
       +{
       +        register Job *j;
       +
       +        j = (Job *)Malloc(sizeof(Job));
       +        j->r = r;
       +        j->n = nlist;
       +        j->stem = stem;
       +        j->match = match;
       +        j->p = pre;
       +        j->np = npre;
       +        j->t = tar;
       +        j->at = atar;
       +        j->nproc = -1;
       +        j->next = 0;
       +        return(j);
       +}
       +
       +void
       +dumpj(char *s, Job *j, int all)
       +{
       +        Bprint(&bout, "%s\n", s);
       +        while(j){
       +                Bprint(&bout, "job@%ld: r=%ld n=%ld stem='%s' nproc=%d\n",
       +                        j, j->r, j->n, j->stem, j->nproc);
       +                Bprint(&bout, "\ttarget='%s' alltarget='%s' prereq='%s' nprereq='%s'\n",
       +                        wtos(j->t, ' '), wtos(j->at, ' '), wtos(j->p, ' '), wtos(j->np, ' '));
       +                j = all? j->next : 0;
       +        }
       +}
 (DIR) diff --git a/src/cmd/mk/mk.pdf b/src/cmd/mk/mk.pdf
       Binary files differ.
 (DIR) diff --git a/src/cmd/sam/README b/src/cmd/sam/README
       t@@ -0,0 +1,29 @@
       +This is sam (not including samterm) from the 4th edition of Plan 9,
       +with changes so that it can be compiled under unix.
       +(Tested on Solaris 7 and Debian 3.0r1.)
       +
       +Some extra libraries are needed.  First, fetch libutf-2.0 and libfmt-2.0
       +from
       +        http://pdos.lcs.mit.edu/~rsc/software/
       +
       +(Beware that in libfmt/fmt.c there is a line that says:
       +        'u',    __ifmt,         /* in Plan 9, __flagfmt */
       +Thus, sam will have to fmtinstall the other thing.  Other ported programs
       +may have to do the same.  The fmt library should probably print messages
       +about bad format characters to stderr, since no one seems to check the
       +return codes.)
       +
       +Compile and install those two libraries.  
       +Set PREFIX in the Makefile to match, then compile sam.
       +
       +Your C compiler will emit many complaints of the form:
       +  sam.c:496: warning: passing arg 1 of `bufread' from incompatible pointer type
       +
       +This is because the Plan 9 compiler has a slightly different (better,
       +ala Oberon) type system than ISO C.  Popular compilers generate the right
       +code, so in an act of civil disobediance I changed just enough to get
       +it to compile, but left the type errors in.  Now the next C standard can
       +adopt this extension, because at least one important C program uses it!
       +
       +-- Scott Schwartz,  4 July 2003
       +
 (DIR) diff --git a/src/cmd/sam/_libc.h b/src/cmd/sam/_libc.h
       t@@ -0,0 +1,40 @@
       +#define __USE_UNIX98  // for pread/pwrite, supposedly
       +#include <unistd.h>
       +#include <stdlib.h>
       +#include <stdarg.h>
       +#include <setjmp.h>
       +#include <string.h>
       +#include <sys/types.h>
       +#include <sys/stat.h>
       +#include <fcntl.h>
       +#include <errno.h>
       +#include <stdio.h>
       +
       +#include "utf.h"
       +#include "fmt.h"
       +
       +#define nil 0
       +#define dup dup2
       +#define exec execv
       +#define seek lseek
       +#define getwd getcwd
       +#define USED(a)
       +#define SET(a)
       +
       +enum {
       +        OREAD = 0,
       +        OWRITE = 1,
       +        ORDWR = 2,
       +        OCEXEC = 4,
       +        ORCLOSE = 8
       +};
       +
       +enum {
       +        ERRMAX = 255
       +};
       +
       +void exits(const char *);
       +void _exits(const char *);
       +int notify (void(*f)(void *, char *));
       +int create(char *, int, int);
       +int errstr(char *, int);
 (DIR) diff --git a/src/cmd/sam/err b/src/cmd/sam/err
       t@@ -0,0 +1,39 @@
       +address.c: In function `filematch':
       +address.c:159: warning: passing arg 1 of `bufreset' from incompatible pointer type
       +address.c:160: warning: passing arg 1 of `bufinsert' from incompatible pointer type
       +file.c: In function `mergeextend':
       +file.c:117: warning: passing arg 1 of `bufread' from incompatible pointer type
       +file.c: In function `fileinsert':
       +file.c:275: warning: passing arg 1 of `bufinsert' from incompatible pointer type
       +file.c: In function `filedelete':
       +file.c:301: warning: passing arg 1 of `bufdelete' from incompatible pointer type
       +file.c: In function `fileundelete':
       +file.c:324: warning: passing arg 1 of `bufread' from incompatible pointer type
       +file.c: In function `filereadc':
       +file.c:339: warning: passing arg 1 of `bufread' from incompatible pointer type
       +file.c: In function `fileload':
       +file.c:405: warning: passing arg 1 of `bufload' from incompatible pointer type
       +file.c: In function `fileundo':
       +file.c:528: warning: passing arg 1 of `bufdelete' from incompatible pointer type
       +file.c:546: warning: passing arg 1 of `bufinsert' from incompatible pointer type
       +file.c: In function `fileclose':
       +file.c:604: warning: passing arg 1 of `bufclose' from incompatible pointer type
       +io.c: In function `readio':
       +io.c:90: warning: passing arg 1 of `bufload' from incompatible pointer type
       +io.c: In function `writeio':
       +io.c:152: warning: passing arg 1 of `bufread' from incompatible pointer type
       +mesg.c: In function `inmesg':
       +mesg.c:248: warning: passing arg 1 of `bufread' from incompatible pointer type
       +mesg.c: In function `snarf':
       +mesg.c:568: warning: passing arg 1 of `bufread' from incompatible pointer type
       +mesg.c: In function `setgenstr':
       +mesg.c:612: warning: passing arg 1 of `bufread' from incompatible pointer type
       +sam.c: In function `readcmd':
       +sam.c:496: warning: passing arg 1 of `bufread' from incompatible pointer type
       +sam.c: In function `copy':
       +sam.c:676: warning: passing arg 1 of `bufread' from incompatible pointer type
       +xec.c: In function `s_cmd':
       +xec.c:234: warning: passing arg 1 of `bufread' from incompatible pointer type
       +xec.c:243: warning: passing arg 1 of `bufread' from incompatible pointer type
       +xec.c: In function `display':
       +xec.c:401: warning: passing arg 1 of `bufread' from incompatible pointer type
 (DIR) diff --git a/src/cmd/sam/plumb.h b/src/cmd/sam/plumb.h
       t@@ -0,0 +1,17 @@
       +typedef struct Plumbmsg Plumbmsg;
       +
       +struct Plumbmsg {
       +        char *src;
       +        char *dst;
       +        char *wdir;
       +        char *type;
       +        char *attr;
       +        char *data;
       +        int ndata;
       +};
       +
       +char *plumbunpackattr(char*);
       +char *plumbpack(Plumbmsg *, int *);
       +int plumbfree(Plumbmsg *);
       +char *cleanname(char*);
       +
 (DIR) diff --git a/src/cmd/sam/string.c b/src/cmd/sam/string.c
       t@@ -0,0 +1,193 @@
       +#include "sam.h"
       +
       +#define        MINSIZE        16                /* minimum number of chars allocated */
       +#define        MAXSIZE        256                /* maximum number of chars for an empty string */
       +
       +
       +void
       +Strinit(String *p)
       +{
       +        p->s = emalloc(MINSIZE*RUNESIZE);
       +        p->n = 0;
       +        p->size = MINSIZE;
       +}
       +
       +void
       +Strinit0(String *p)
       +{
       +        p->s = emalloc(MINSIZE*RUNESIZE);
       +        p->s[0] = 0;
       +        p->n = 1;
       +        p->size = MINSIZE;
       +}
       +
       +void
       +Strclose(String *p)
       +{
       +        free(p->s);
       +}
       +
       +void
       +Strzero(String *p)
       +{
       +        if(p->size > MAXSIZE){
       +                p->s = erealloc(p->s, RUNESIZE*MAXSIZE); /* throw away the garbage */
       +                p->size = MAXSIZE;
       +        }
       +        p->n = 0;
       +}
       +
       +int
       +Strlen(Rune *r)
       +{
       +        Rune *s;
       +
       +        for(s=r; *s; s++)
       +                ;
       +        return s-r;
       +}
       +
       +void
       +Strdupl(String *p, Rune *s)        /* copies the null */
       +{
       +        p->n = Strlen(s)+1;
       +        Strinsure(p, p->n);
       +        memmove(p->s, s, p->n*RUNESIZE);
       +}
       +
       +void
       +Strduplstr(String *p, String *q)        /* will copy the null if there's one there */
       +{
       +        Strinsure(p, q->n);
       +        p->n = q->n;
       +        memmove(p->s, q->s, q->n*RUNESIZE);
       +}
       +
       +void
       +Straddc(String *p, int c)
       +{
       +        Strinsure(p, p->n+1);
       +        p->s[p->n++] = c;
       +}
       +
       +void
       +Strinsure(String *p, ulong n)
       +{
       +        if(n > STRSIZE)
       +                error(Etoolong);
       +        if(p->size < n){        /* p needs to grow */
       +                n += 100;
       +                p->s = erealloc(p->s, n*RUNESIZE);
       +                p->size = n;
       +        }
       +}
       +
       +void
       +Strinsert(String *p, String *q, Posn p0)
       +{
       +        Strinsure(p, p->n+q->n);
       +        memmove(p->s+p0+q->n, p->s+p0, (p->n-p0)*RUNESIZE);
       +        memmove(p->s+p0, q->s, q->n*RUNESIZE);
       +        p->n += q->n;
       +}
       +
       +void
       +Strdelete(String *p, Posn p1, Posn p2)
       +{
       +        memmove(p->s+p1, p->s+p2, (p->n-p2)*RUNESIZE);
       +        p->n -= p2-p1;
       +}
       +
       +int
       +Strcmp(String *a, String *b)
       +{
       +        int i, c;
       +
       +        for(i=0; i<a->n && i<b->n; i++)
       +                if(c = (a->s[i] - b->s[i]))        /* assign = */
       +                        return c;
       +        /* damn NULs confuse everything */
       +        i = a->n - b->n;
       +        if(i == 1){
       +                if(a->s[a->n-1] == 0)
       +                        return 0;
       +        }else if(i == -1){
       +                if(b->s[b->n-1] == 0)
       +                        return 0;
       +        }
       +        return i;
       +}
       +
       +int
       +Strispre(String *a, String *b)
       +{
       +        int i;
       +
       +        for(i=0; i<a->n && i<b->n; i++){
       +                if(a->s[i] - b->s[i]){        /* assign = */
       +                        if(a->s[i] == 0)
       +                                return 1;
       +                        return 0;
       +                }
       +        }
       +        return i == a->n;
       +}
       +
       +char*
       +Strtoc(String *s)
       +{
       +        int i;
       +        char *c, *d;
       +        Rune *r;
       +        c = emalloc(s->n*UTFmax + 1);  /* worst case UTFmax bytes per rune, plus NUL */
       +        d = c;
       +        r = s->s;
       +        for(i=0; i<s->n; i++)
       +                d += runetochar(d, r++);
       +        if(d==c || d[-1]!=0)
       +                *d = 0;
       +        return c;
       +
       +}
       +
       +/*
       + * Build very temporary String from Rune*
       + */
       +String*
       +tmprstr(Rune *r, int n)
       +{
       +        static String p;
       +
       +        p.s = r;
       +        p.n = n;
       +        p.size = n;
       +        return &p;
       +}
       +
       +/*
       + * Convert null-terminated char* into String
       + */
       +String*
       +tmpcstr(char *s)
       +{
       +        String *p;
       +        Rune *r;
       +        int i, n;
       +
       +        n = utflen(s);        /* don't include NUL */
       +        p = emalloc(sizeof(String));
       +        r = emalloc(n*RUNESIZE);
       +        p->s = r;
       +        for(i=0; i<n; i++,r++)
       +                s += chartorune(r, s);
       +        p->n = n;
       +        p->size = n;
       +        return p;
       +}
       +
       +void
       +freetmpstr(String *s)
       +{
       +        free(s->s);
       +        free(s);
       +}
 (DIR) diff --git a/src/cmd/sam/sys.c b/src/cmd/sam/sys.c
       t@@ -0,0 +1,60 @@
       +#include "sam.h"
       +
       +static int inerror=FALSE;
       +
       +/*
       + * A reasonable interface to the system calls
       + */
       +
       +void
       +resetsys(void)
       +{
       +        inerror = FALSE;
       +}
       +
       +void
       +syserror(char *a)
       +{
       +        char buf[ERRMAX];
       +
       +        if(!inerror){
       +                inerror=TRUE;
       +                errstr(buf, sizeof buf);
       +                dprint("%s: ", a);
       +                error_s(Eio, buf);
       +        }
       +}
       +
       +int
       +Read(int f, void *a, int n)
       +{
       +        char buf[ERRMAX];
       +
       +        if(read(f, (char *)a, n)!=n) {
       +                if (lastfile)
       +                        lastfile->rescuing = 1;
       +                errstr(buf, sizeof buf);
       +                if (downloaded)
       +                        fprint(2, "read error: %s\n", buf);
       +                rescue();
       +                exits("read");
       +        }
       +        return n;
       +}
       +
       +int
       +Write(int f, void *a, int n)
       +{
       +        int m;
       +
       +        if((m=write(f, (char *)a, n))!=n)
       +                syserror("write");
       +        return m;
       +}
       +
       +void
       +Seek(int f, long n, int w)
       +{
       +        if(seek(f, n, w)==-1)
       +                syserror("seek");
       +}
 (DIR) diff --git a/src/cmd/sam/util.c b/src/cmd/sam/util.c
       t@@ -0,0 +1,54 @@
       +#include "sam.h"
       +
       +void
       +cvttorunes(char *p, int n, Rune *r, int *nb, int *nr, int *nulls)
       +{
       +        uchar *q;
       +        Rune *s;
       +        int j, w;
       +
       +        /*
       +         * Always guaranteed that n bytes may be interpreted
       +         * without worrying about partial runes.  This may mean
       +         * reading up to UTFmax-1 more bytes than n; the caller
       +         * knows this.  If n is a firm limit, the caller should
       +         * set p[n] = 0.
       +         */
       +        q = (uchar*)p;
       +        s = r;
       +        for(j=0; j<n; j+=w){
       +                if(*q < Runeself){
       +                        w = 1;
       +                        *s = *q++;
       +                }else{
       +                        w = chartorune(s, (char*)q);
       +                        q += w;
       +                }
       +                if(*s)
       +                        s++;
       +                else if(nulls)
       +                        *nulls = TRUE;
       +        }
       +        *nb = (char*)q-p;
       +        *nr = s-r;
       +}
       +
       +void*
       +fbufalloc(void)
       +{
       +        return emalloc(BUFSIZE);
       +}
       +
       +void
       +fbuffree(void *f)
       +{
       +        free(f);
       +}
       +
       +uint
       +min(uint a, uint b)
       +{
       +        if(a < b)
       +                return a;
       +        return b;
       +}
 (DIR) diff --git a/src/libdraw/allocimagemix.c b/src/libdraw/allocimagemix.c
       t@@ -0,0 +1,43 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +Image*
       +allocimagemix(Display *d, u32int color1, u32int color3)
       +{
       +        Image *t, *b;
       +        static Image *qmask;
       +
       +        if(qmask == nil)
       +                qmask = allocimage(d, Rect(0,0,1,1), GREY8, 1, 0x3F3F3FFF);
       +                
       +        if(d->screenimage->depth <= 8){        /* create a 2×2 texture */
       +                t = allocimage(d, Rect(0,0,1,1), d->screenimage->chan, 0, color1);
       +                if(t == nil)
       +                        return nil;
       +
       +                b = allocimage(d, Rect(0,0,2,2), d->screenimage->chan, 1, color3);
       +                if(b == nil){
       +                        freeimage(t);
       +                        return nil;
       +                }
       +
       +                draw(b, Rect(0,0,1,1), t, nil, ZP);
       +                freeimage(t);
       +                return b;
       +        }else{        /* use a solid color, blended using alpha */
       +                t = allocimage(d, Rect(0,0,1,1), d->screenimage->chan, 1, color1);
       +                if(t == nil)
       +                        return nil;
       +
       +                b = allocimage(d, Rect(0,0,1,1), d->screenimage->chan, 1, color3);
       +                if(b == nil){
       +                        freeimage(t);
       +                        return nil;
       +                }
       +
       +                draw(b, b->r, t, qmask, ZP);
       +                freeimage(t);
       +                return b;
       +        }
       +}
 (DIR) diff --git a/src/libdraw/bezier.c b/src/libdraw/bezier.c
       t@@ -0,0 +1,244 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +#define        PINC        32                /* realloc granularity */
       +
       +typedef struct Plist Plist;
       +struct Plist
       +{
       +        Point *p;
       +        int np;                        /* -1 if malloc/realloc failed */
       +};
       +
       +static void
       +appendpt(Plist *l, Point p)
       +{
       +        if(l->np == -1)
       +                return;
       +        if(l->np == 0)
       +                l->p = malloc(PINC*sizeof(Point));
       +        else if(l->np%PINC == 0)
       +                l->p = realloc(l->p, (l->np+PINC)*sizeof(Point));
       +        if(l->p == 0){
       +                l->np = -1;
       +                return;
       +        }
       +        l->p[l->np++] = p;
       +}
       +
       +static int
       +normsq(Point p)
       +{
       +        return p.x*p.x+p.y*p.y;
       +}
       +
       +static int
       +psdist(Point p, Point a, Point b)
       +{
       +        int num, den;
       +
       +        p = subpt(p, a);
       +        b = subpt(b, a);
       +        num = p.x*b.x + p.y*b.y;
       +        if(num <= 0)
       +                return normsq(p);
       +        den = normsq(b);
       +        if(num >= den)
       +                return normsq(subpt(b, p));
       +        return normsq(subpt(divpt(mulpt(b, num), den), p));
       +}
       +
       +/*
       + * Convert cubic Bezier curve control points to polyline
       + * vertices.  Leaves the last vertex off, so you can continue
       + * with another curve.
       + */
       +static void
       +bpts1(Plist *l, Point p0, Point p1, Point p2, Point p3, int scale)
       +{
       +        Point p01, p12, p23, p012, p123, p0123;
       +        Point tp0, tp1, tp2, tp3;
       +        tp0=divpt(p0, scale);
       +        tp1=divpt(p1, scale);
       +        tp2=divpt(p2, scale);
       +        tp3=divpt(p3, scale);
       +        if(psdist(tp1, tp0, tp3)<=1 && psdist(tp2, tp0, tp3)<=1){
       +                appendpt(l, tp0);
       +                appendpt(l, tp1);
       +                appendpt(l, tp2);
       +        }
       +        else{
       +                /*
       +                 * if scale factor is getting too big for comfort,
       +                 * rescale now & concede the rounding error
       +                 */
       +                if(scale>(1<<12)){
       +                        p0=tp0;
       +                        p1=tp1;
       +                        p2=tp2;
       +                        p3=tp3;
       +                        scale=1;
       +                }
       +                p01=addpt(p0, p1);
       +                p12=addpt(p1, p2);
       +                p23=addpt(p2, p3);
       +                p012=addpt(p01, p12);
       +                p123=addpt(p12, p23);
       +                p0123=addpt(p012, p123);
       +                bpts1(l, mulpt(p0, 8), mulpt(p01, 4), mulpt(p012, 2), p0123, scale*8);
       +                bpts1(l, p0123, mulpt(p123, 2), mulpt(p23, 4), mulpt(p3, 8), scale*8);
       +        }
       +}
       +
       +static void
       +bpts(Plist *l, Point p0, Point p1, Point p2, Point p3)
       +{
       +        bpts1(l, p0, p1, p2, p3, 1);
       +}
       +
       +static void
       +bezierpts(Plist *l, Point p0, Point p1, Point p2, Point p3)
       +{
       +        bpts(l, p0, p1, p2, p3);
       +        appendpt(l, p3);
       +}
       +
       +static void
       +_bezsplinepts(Plist *l, Point *pt, int npt)
       +{
       +        Point *p, *ep;
       +        Point a, b, c, d;
       +        int periodic;
       +
       +        if(npt<3)
       +                return;
       +        ep = &pt[npt-3];
       +        periodic = eqpt(pt[0], ep[2]);
       +        if(periodic){
       +                a = divpt(addpt(ep[1], pt[0]), 2);
       +                b = divpt(addpt(ep[1], mulpt(pt[0], 5)), 6);
       +                c = divpt(addpt(mulpt(pt[0], 5), pt[1]), 6);
       +                d = divpt(addpt(pt[0], pt[1]), 2);
       +                bpts(l, a, b, c, d);
       +        }
       +        for(p=pt; p<=ep; p++){
       +                if(p==pt && !periodic){
       +                        a = p[0];
       +                        b = divpt(addpt(p[0], mulpt(p[1], 2)), 3);
       +                }
       +                else{
       +                        a = divpt(addpt(p[0], p[1]), 2);
       +                        b = divpt(addpt(p[0], mulpt(p[1], 5)), 6);
       +                }
       +                if(p==ep && !periodic){
       +                        c = divpt(addpt(mulpt(p[1], 2), p[2]), 3);
       +                        d = p[2];
       +                }
       +                else{
       +                        c = divpt(addpt(mulpt(p[1], 5), p[2]), 6);
       +                        d = divpt(addpt(p[1], p[2]), 2);
       +                }
       +                bpts(l, a, b, c, d);
       +        }
       +        appendpt(l, d);
       +}
       +
       +int
       +bezsplinepts(Point *pt, int npt, Point **pp)
       +{
       +        Plist l;
       +        l.np = 0;
       +        l.p = nil;
       +        _bezsplinepts(&l, pt, npt);
       +        *pp  = l.p;
       +        return l.np;
       +}
       +
       +int
       +bezier(Image *dst, Point p0, Point p1, Point p2, Point p3, int end0, int end1, int radius, Image *src, Point sp)
       +{
       +        return bezierop(dst, p0, p1, p2, p3, end0, end1, radius, src, sp, SoverD);
       +}
       +
       +int
       +bezierop(Image *dst, Point p0, Point p1, Point p2, Point p3, int end0, int end1, int radius, Image *src, Point sp, Drawop op)
       +{
       +        Plist l;
       +
       +        l.np = 0;
       +        bezierpts(&l, p0, p1, p2, p3);
       +        if(l.np == -1)
       +                return 0;
       +        if(l.np != 0){
       +                polyop(dst, l.p, l.np, end0, end1, radius, src, addpt(subpt(sp, p0), l.p[0]), op);
       +                free(l.p);
       +        }
       +        return 1;
       +}
       +
       +int
       +bezspline(Image *dst, Point *pt, int npt, int end0, int end1, int radius, Image *src, Point sp)
       +{
       +        return bezsplineop(dst, pt, npt, end0, end1, radius, src, sp, SoverD);
       +}
       +
       +int
       +bezsplineop(Image *dst, Point *pt, int npt, int end0, int end1, int radius, Image *src, Point sp, Drawop op)
       +{
       +        Plist l;
       +
       +        l.np = 0;
       +        _bezsplinepts(&l, pt, npt);
       +        if(l.np==-1)
       +                return 0;
       +        if(l.np != 0){
       +                polyop(dst, l.p, l.np, end0, end1, radius, src, addpt(subpt(sp, pt[0]), l.p[0]), op);
       +                free(l.p);
       +        }
       +        return 1;
       +}
       +
       +int
       +fillbezier(Image *dst, Point p0, Point p1, Point p2, Point p3, int w, Image *src, Point sp)
       +{
       +        return fillbezierop(dst, p0, p1, p2, p3, w, src, sp, SoverD);
       +}
       +
       +int
       +fillbezierop(Image *dst, Point p0, Point p1, Point p2, Point p3, int w, Image *src, Point sp, Drawop op)
       +{
       +        Plist l;
       +
       +        l.np = 0;
       +        bezierpts(&l, p0, p1, p2, p3);
       +        if(l.np == -1)
       +                return 0;
       +        if(l.np != 0){
       +                fillpolyop(dst, l.p, l.np, w, src, addpt(subpt(sp, p0), l.p[0]), op);
       +                free(l.p);
       +        }
       +        return 1;
       +}
       +
       +int
       +fillbezspline(Image *dst, Point *pt, int npt, int w, Image *src, Point sp)
       +{
       +        return fillbezsplineop(dst, pt, npt, w, src, sp, SoverD);
       +}
       +
       +int
       +fillbezsplineop(Image *dst, Point *pt, int npt, int w, Image *src, Point sp, Drawop op)
       +{
       +        Plist l;
       +
       +        l.np = 0;
       +        _bezsplinepts(&l, pt, npt);
       +        if(l.np == -1)
       +                return 0;
       +        if(l.np > 0){
       +                fillpolyop(dst, l.p, l.np, w, src, addpt(subpt(sp, pt[0]), l.p[0]), op);
       +                free(l.p);
       +        }
       +        return 1;
       +}
 (DIR) diff --git a/src/libdraw/border.c b/src/libdraw/border.c
       t@@ -0,0 +1,21 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +void
       +border(Image *im, Rectangle r, int i, Image *color, Point sp)
       +{
       +        if(i < 0){
       +                r = insetrect(r, i);
       +                sp = addpt(sp, Pt(i,i));
       +                i = -i;
       +        }
       +        draw(im, Rect(r.min.x, r.min.y, r.max.x, r.min.y+i),
       +                color, nil, sp);
       +        draw(im, Rect(r.min.x, r.max.y-i, r.max.x, r.max.y),
       +                color, nil, Pt(sp.x, sp.y+Dy(r)-i));
       +        draw(im, Rect(r.min.x, r.min.y+i, r.min.x+i, r.max.y-i),
       +                color, nil, Pt(sp.x, sp.y+i));
       +        draw(im, Rect(r.max.x-i, r.min.y+i, r.max.x, r.max.y-i),
       +                color, nil, Pt(sp.x+Dx(r)-i, sp.y+i));
       +}
 (DIR) diff --git a/src/libdraw/cloadimage.c b/src/libdraw/cloadimage.c
       t@@ -0,0 +1,49 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +int
       +cloadimage(Image *i, Rectangle r, uchar *data, int ndata)
       +{
       +        int m, nb, miny, maxy, ncblock;
       +        uchar *a;
       +
       +        if(!rectinrect(r, i->r)){
       +                werrstr("cloadimage: bad rectangle");
       +                return -1;
       +        }
       +
       +        miny = r.min.y;
       +        m = 0;
       +        ncblock = _compblocksize(r, i->depth);
       +        while(miny != r.max.y){
       +                maxy = atoi((char*)data+0*12);
       +                nb = atoi((char*)data+1*12);
       +                if(maxy<=miny || r.max.y<maxy){
       +                        werrstr("creadimage: bad maxy %d", maxy);
       +                        return -1;
       +                }
       +                data += 2*12;
       +                ndata -= 2*12;
       +                m += 2*12;
       +                if(nb<=0 || ncblock<nb || nb>ndata){
       +                        werrstr("creadimage: bad count %d", nb);
       +                        return -1;
       +                }
       +                a = bufimage(i->display, 21+nb);
       +                if(a == nil)
       +                        return -1;
       +                a[0] = 'Y';
       +                BPLONG(a+1, i->id);
       +                BPLONG(a+5, r.min.x);
       +                BPLONG(a+9, miny);
       +                BPLONG(a+13, r.max.x);
       +                BPLONG(a+17, maxy);
       +                memmove(a+21, data, nb);
       +                miny = maxy;
       +                data += nb;
       +                ndata += nb;
       +                m += nb;
       +        }
       +        return m;
       +}
 (DIR) diff --git a/src/libdraw/computil.c b/src/libdraw/computil.c
       t@@ -0,0 +1,38 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +/*
       + * compressed data are seuences of byte codes.  
       + * if the first byte b has the 0x80 bit set, the next (b^0x80)+1 bytes
       + * are data.  otherwise, it's two bytes specifying a previous string to repeat.
       + */
       +void
       +_twiddlecompressed(uchar *buf, int n)
       +{
       +        uchar *ebuf;
       +        int j, k, c;
       +
       +        ebuf = buf+n;
       +        while(buf < ebuf){
       +                c = *buf++;
       +                if(c >= 128){
       +                        k = c-128+1;
       +                        for(j=0; j<k; j++, buf++)
       +                                *buf ^= 0xFF;
       +                }else
       +                        buf++;
       +        }
       +}
       +
       +int
       +_compblocksize(Rectangle r, int depth)
       +{
       +        int bpl;
       +
       +        bpl = bytesperline(r, depth);
       +        bpl = 2*bpl;        /* add plenty extra for blocking, etc. */
       +        if(bpl < NCBLOCK)
       +                return NCBLOCK;
       +        return bpl;
       +}
 (DIR) diff --git a/src/libdraw/debug.c b/src/libdraw/debug.c
       t@@ -0,0 +1,16 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +void
       +drawsetdebug(int v)
       +{
       +        uchar *a;
       +        a = bufimage(display, 1+1);
       +        if(a == 0){
       +                fprint(2, "drawsetdebug: %r\n");
       +                return;
       +        }
       +        a[0] = 'D';
       +        a[1] = v;
       +}
 (DIR) diff --git a/src/libdraw/defont.c b/src/libdraw/defont.c
       t@@ -0,0 +1,402 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +/*
       + * lucm/latin1.9, in uncompressed form
       + */
       +uchar
       +defontdata[] =
       +{
       +0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x30,0x20,0x20,0x20,0x20,0x20,
       +0x20,0x20,0x20,0x20,0x20,0x20,0x30,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
       +0x20,0x20,0x30,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x32,0x33,0x30,0x34,0x20,
       +0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x31,0x35,0x20,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
       +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
       +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
       +0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x30,0x06,0x06,0x03,0x42,0x40,0x00,0x00,0x00,0x18,0x03,0x03,
       +0x02,0x43,0x00,0x60,0x60,0x48,0x00,0x0d,0x0c,0x01,0x81,0x80,0xd0,0x90,0x00,0x00,
       +0x18,0x01,0x81,0x81,0x40,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x7f,0x9c,0x1c,
       +0x0e,0x07,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x70,
       +0x38,0x1c,0x0e,0x04,0x81,0xc1,0xc0,0x70,0x00,0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaa,0x80,0xc0,0x63,0xe3,
       +0xf1,0xf8,0xfe,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x7f,0xff,0xff,0x1f,0x8f,
       +0xc7,0xe3,0xf1,0xfb,0x7e,0x3e,0x3f,0x8f,0xff,0xe3,0xe3,0xff,0xff,0xff,0xff,0xff,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x0c,0x18,0x09,0x05,0x82,0x40,0xc0,0x00,0x00,0x06,0x0c,0x04,
       +0x82,0x40,0xc1,0x80,0x90,0x48,0x00,0x16,0x03,0x06,0x02,0x41,0x60,0x90,0x00,0x00,
       +0x06,0x06,0x02,0x41,0x41,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x7f,0xa0,0x10,
       +0x08,0x04,0x02,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x48,
       +0x24,0x12,0x09,0x06,0x82,0x01,0x00,0x90,0x00,0x20,0x10,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x04,0x80,0x00,0x40,0x00,0x00,0x38,0x06,0x18,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x07,0xc6,0x01,0xf0,0x00,0x00,0x0c,0x00,0x18,0x00,0x00,0x30,0x00,0x3c,
       +0x00,0x60,0x06,0x01,0x8c,0x07,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xe0,0xc3,0xc0,0x01,0x54,0x9c,0xc0,0x5f,0xef,
       +0xf7,0xfb,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0x7f,0xff,0xff,0x6f,0xb7,
       +0xdb,0xed,0xf6,0xf9,0x7d,0xfe,0xff,0x6f,0xff,0xdf,0xef,0xff,0xff,0xff,0xff,0xff,
       +0xff,0x00,0x01,0x00,0x00,0x00,0x00,0x30,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x30,0x06,0x06,0x06,0x82,0x80,0xc0,0x00,
       +0x00,0x18,0x03,0x03,0x02,0x41,0x80,0x30,0x30,0x24,0x76,0x0d,0x0c,0x00,0xc0,0xc0,
       +0xd0,0x50,0x00,0x00,0x18,0x01,0x81,0x81,0x40,0x30,0x00,0x28,0x0f,0x7f,0xbc,0x1c,
       +0x0e,0x07,0x03,0xc0,0x10,0x70,0x24,0x10,0x09,0x07,0x03,0x80,0xe0,0x70,0x90,0x48,
       +0x24,0x12,0x09,0x05,0x81,0x81,0xc0,0x80,0x70,0x18,0x1c,0x07,0x01,0xc1,0xc0,0x90,
       +0x00,0x0c,0x04,0x84,0x83,0xe1,0xc0,0xe0,0x38,0x0c,0x0c,0x02,0x00,0x00,0x00,0x00,
       +0x00,0x06,0x1c,0x06,0x0f,0x87,0xc0,0x63,0xf8,0x78,0xfe,0x3e,0x0e,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x7c,0x1c,0x0c,0x1f,0x03,0xc7,0xc3,0xf1,0xf8,0x3c,0x63,0x3f,0x0f,
       +0x8c,0x66,0x06,0x19,0x84,0x78,0x7e,0x1e,0x1f,0x07,0xcf,0xf3,0x1b,0x0d,0x86,0x63,
       +0x61,0x9f,0xc6,0x06,0x00,0x30,0x00,0x00,0x10,0x00,0x18,0x00,0x00,0x30,0x00,0x60,
       +0x00,0x60,0x06,0x01,0x8c,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0xc0,0x60,0x00,0xaa,0xb6,0xc0,0x43,0xe3,
       +0xf1,0xf8,0xfc,0x3f,0xef,0x8f,0xdb,0xef,0xf6,0xf8,0xfb,0xff,0x1f,0x8f,0x6f,0xb7,
       +0xdb,0xed,0xf6,0xfa,0x7e,0x7e,0x3f,0x7f,0x8f,0xe7,0xe3,0xf8,0xfe,0x3e,0x3f,0x6f,
       +0x00,0x00,0x01,0x01,0xc8,0x0b,0x0c,0x30,0x7c,0x14,0x0f,0x0f,0x00,0x00,0x00,0x00,
       +0x78,0x00,0x1c,0x00,0x0f,0x07,0x81,0x80,0x00,0x7c,0x00,0x00,0x1c,0x0f,0x80,0x04,
       +0x42,0x23,0x90,0x00,0x18,0x0c,0x06,0x03,0x01,0x80,0xc0,0x3c,0x3c,0x3f,0x1f,0x8f,
       +0xc7,0xe7,0xe3,0xf1,0xf8,0xfc,0x7c,0x30,0x8f,0x07,0x83,0xc1,0xe0,0xf0,0x00,0x3d,
       +0x31,0x98,0xcc,0x66,0x36,0x19,0x80,0xcc,0x0c,0x18,0x09,0x0b,0x02,0x81,0x20,0x00,
       +0x00,0x06,0x0c,0x04,0x82,0x40,0x60,0xc0,0x48,0x24,0x18,0x16,0x03,0x03,0x01,0x21,
       +0x60,0x50,0x00,0x00,0x06,0x06,0x02,0x41,0x40,0xc1,0x80,0x28,0x87,0x7f,0x84,0x10,
       +0x08,0x04,0x02,0x40,0x38,0x48,0x24,0x10,0x09,0x04,0x04,0x81,0x00,0x80,0x90,0x48,
       +0x24,0x12,0x09,0x04,0x80,0x41,0x00,0x80,0x40,0x04,0x10,0x04,0x02,0x01,0x20,0x90,
       +0x00,0x0c,0x04,0x84,0x86,0x53,0x65,0xb0,0x08,0x18,0x06,0x0a,0x80,0x00,0x00,0x00,
       +0x00,0x0c,0x36,0x0e,0x19,0xcc,0xe0,0xe3,0xf8,0xcc,0xfe,0x63,0x1b,0x00,0x00,0x00,
       +0x00,0x00,0x00,0xc6,0x62,0x0c,0x19,0x86,0x66,0x63,0x01,0x80,0x66,0x63,0x0c,0x01,
       +0x8c,0xc6,0x06,0x19,0xc4,0xcc,0x63,0x33,0x19,0x8c,0x61,0x83,0x1b,0x0d,0x86,0x63,
       +0x61,0x80,0xc6,0x03,0x00,0x30,0x30,0x00,0x1c,0x00,0x18,0x00,0x00,0x30,0x00,0x60,
       +0x00,0x60,0x00,0x00,0x0c,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0xc0,0x60,0x01,0x54,0x86,0xc0,0x7b,0xef,
       +0xf7,0xfb,0xfd,0xbf,0xc7,0xb7,0xdb,0xef,0xf6,0xfb,0xfb,0x7e,0xff,0x7f,0x6f,0xb7,
       +0xdb,0xed,0xf6,0xfb,0x7f,0xbe,0xff,0x7f,0xbf,0xfb,0xef,0xfb,0xfd,0xfe,0xdf,0x6f,
       +0xff,0x00,0x07,0x83,0x24,0x13,0x0c,0x30,0xc6,0x00,0x10,0x81,0x80,0x00,0x00,0x00,
       +0x84,0x00,0x22,0x00,0x01,0x80,0xc0,0x00,0x00,0xf4,0x00,0x00,0x2c,0x18,0xc0,0x0c,
       +0x46,0x20,0x90,0x00,0x18,0x0c,0x06,0x03,0x01,0x80,0xc0,0x70,0x66,0x30,0x18,0x0c,
       +0x06,0x01,0x80,0xc0,0x60,0x30,0x66,0x38,0x99,0x8c,0xc6,0x63,0x31,0x98,0x00,0x66,
       +0x31,0x98,0xcc,0x66,0x36,0x19,0x80,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,0xff,0x7f,0xb8,0x1c,
       +0x0e,0x07,0x02,0x40,0x7c,0x70,0x3c,0x10,0x09,0x07,0x04,0x00,0xc0,0x60,0xe0,0x70,
       +0x38,0x1c,0x0e,0x04,0x83,0x81,0xc0,0x70,0x70,0x38,0x1c,0x07,0x02,0xc1,0xc0,0x90,
       +0x00,0x0c,0x00,0x04,0x86,0x43,0x69,0xb0,0x30,0x18,0x06,0x07,0x01,0x00,0x00,0x00,
       +0x00,0x0c,0x63,0x16,0x00,0xc0,0x61,0x62,0x01,0x80,0x06,0x63,0x31,0x80,0x00,0x00,
       +0x60,0x00,0xc0,0x06,0x43,0x16,0x19,0x8c,0x06,0x33,0x01,0x80,0xc0,0x63,0x0c,0x01,
       +0x8c,0x86,0x07,0x39,0xc5,0x86,0x63,0x61,0x99,0x8c,0x01,0x83,0x1b,0x0d,0xb6,0x63,
       +0x31,0x01,0x86,0x03,0x00,0x30,0x30,0x00,0x1c,0x3e,0x1b,0x03,0xc1,0xf0,0xf0,0x60,
       +0x3e,0x6e,0x3e,0x0f,0x8c,0x60,0xc5,0xb1,0xb8,0x38,0x6c,0x0f,0x8c,0xc7,0xc1,0x83,
       +0x19,0x8d,0x82,0x63,0x31,0x9f,0xc1,0x80,0xc0,0xc0,0x00,0xaa,0x86,0xc0,0x47,0xe3,
       +0xf1,0xf8,0xfd,0xbf,0x83,0x8f,0xc3,0xef,0xf6,0xf8,0xfc,0xff,0x3f,0x9f,0x1f,0x8f,
       +0xc7,0xe3,0xf1,0xfb,0x7c,0x7e,0x3f,0x8f,0x8f,0xc7,0xe3,0xf8,0xfd,0x3e,0x3f,0x6f,
       +0x00,0x0c,0x0d,0x43,0x03,0xe1,0x88,0x30,0xc0,0x00,0x27,0x41,0x80,0x00,0x00,0x01,
       +0x72,0x00,0x22,0x04,0x01,0x80,0xc0,0x03,0x18,0xf4,0x00,0x00,0x0c,0x18,0xc0,0x04,
       +0x82,0x43,0x20,0x18,0x2c,0x16,0x0b,0x05,0x82,0xc1,0x60,0xb0,0xc0,0x30,0x18,0x0c,
       +0x06,0x01,0x80,0xc0,0x60,0x30,0x63,0x38,0xb0,0xd8,0x6c,0x36,0x1b,0x0c,0x00,0xc7,
       +0x31,0x98,0xcc,0x66,0x33,0x11,0xf8,0xc8,0x7c,0x3e,0x1f,0x0f,0x87,0xc3,0xe1,0xd8,
       +0x3c,0x1e,0x0f,0x07,0x83,0xc7,0xc3,0xe1,0xf0,0xf8,0x06,0x37,0x07,0x03,0x81,0xc0,
       +0xe0,0x70,0x10,0x1d,0x31,0x98,0xcc,0x66,0x33,0x19,0xb0,0xc6,0x8f,0x7f,0x87,0x03,
       +0x81,0x80,0x90,0x30,0x6c,0x48,0x24,0x10,0x06,0x04,0x04,0x80,0x20,0x10,0x10,0x0e,
       +0x07,0x03,0x81,0xc0,0x60,0x88,0x38,0x0c,0x40,0x09,0x03,0x84,0x02,0x41,0x40,0x90,
       +0x00,0x0c,0x00,0x1f,0xe7,0x41,0xd1,0xa0,0x00,0x30,0x03,0x0a,0x81,0x00,0x00,0x00,
       +0x00,0x18,0x63,0x06,0x00,0xc0,0xc2,0x62,0x01,0xb0,0x0c,0x72,0x31,0x86,0x03,0x00,
       +0xc0,0x00,0x60,0x06,0x8f,0x16,0x19,0x0c,0x06,0x33,0x01,0x80,0xc0,0x63,0x0c,0x01,
       +0x8d,0x06,0x07,0x39,0x65,0x86,0x63,0x61,0x99,0x0e,0x01,0x83,0x19,0x89,0xb6,0x32,
       +0x33,0x03,0x06,0x01,0x80,0x30,0x78,0x00,0x00,0x03,0x1d,0x86,0x23,0x31,0x99,0xfc,
       +0x66,0x77,0x06,0x01,0x8c,0x40,0xc6,0xd9,0xdc,0x6c,0x76,0x19,0x8d,0xcc,0x27,0xf3,
       +0x19,0x8d,0x82,0x63,0x31,0x80,0xc0,0x80,0xc0,0x80,0x01,0x54,0x8c,0xc0,0x78,0xfc,
       +0x7e,0x7f,0x6f,0xcf,0x93,0xb7,0xdb,0xef,0xf9,0xfb,0xff,0xff,0xdf,0xef,0xef,0xf1,
       +0xf8,0xfc,0x7e,0x3f,0x9f,0x77,0xc7,0xf3,0xbf,0xf6,0xfc,0x7b,0xfd,0xbe,0xbf,0x6f,
       +0xff,0x0c,0x19,0x03,0x03,0x61,0x98,0x30,0x78,0x00,0x28,0x4f,0x83,0x30,0x00,0x01,
       +0x4a,0x00,0x1c,0x04,0x03,0x03,0x80,0x03,0x18,0xf4,0x00,0x00,0x0c,0x18,0xd9,0x84,
       +0x82,0x40,0xa0,0x18,0x2c,0x16,0x0b,0x05,0x82,0xc1,0x60,0xb0,0xc0,0x30,0x18,0x0c,
       +0x06,0x01,0x80,0xc0,0x60,0x30,0x63,0x2c,0xb0,0xd8,0x6c,0x36,0x1b,0x0c,0x64,0xcb,
       +0x31,0x98,0xcc,0x66,0x33,0x31,0x8c,0xd8,0x06,0x03,0x01,0x80,0xc0,0x60,0x30,0x6c,
       +0x62,0x33,0x19,0x8c,0xc6,0x60,0xc0,0x60,0x30,0x18,0x1e,0x3b,0x8d,0x86,0xc3,0x61,
       +0xb0,0xd8,0x10,0x36,0x31,0x98,0xcc,0x66,0x33,0x19,0xd8,0xc6,0x0f,0x7f,0x82,0x01,
       +0x02,0x40,0xd0,0x40,0x6c,0x70,0x24,0x1c,0x06,0x04,0x03,0x01,0xc0,0xe0,0x10,0x12,
       +0x09,0x04,0x82,0x40,0x90,0x50,0x10,0x12,0x70,0x09,0x04,0x04,0x01,0xc1,0x20,0x60,
       +0x00,0x0c,0x00,0x04,0x83,0xc0,0x20,0xcc,0x00,0x30,0x03,0x02,0x01,0x00,0x00,0x00,
       +0x00,0x18,0x63,0x06,0x01,0x83,0x84,0x63,0xf1,0xd8,0x18,0x3c,0x31,0x86,0x03,0x01,
       +0x83,0xf8,0x30,0x1c,0x9b,0x33,0x1e,0x0c,0x06,0x33,0xe1,0x80,0xc0,0x7f,0x0c,0x01,
       +0x8f,0x06,0x07,0x79,0x65,0x86,0x66,0x61,0x9e,0x07,0x81,0x83,0x19,0x89,0xb6,0x1c,
       +0x1a,0x03,0x06,0x01,0x80,0x30,0x48,0x00,0x00,0x03,0x18,0xcc,0x06,0x33,0x18,0x60,
       +0xc6,0x63,0x06,0x01,0x8c,0x80,0xc6,0xd9,0x8c,0xc6,0x63,0x31,0x8e,0x4c,0x01,0x83,
       +0x19,0x8d,0x92,0x32,0x31,0x81,0x87,0x00,0xc0,0x70,0xe4,0xaa,0x98,0xc0,0x7d,0xfe,
       +0xfd,0xbf,0x2f,0xbf,0x93,0x8f,0xdb,0xe3,0xf9,0xfb,0xff,0x1e,0x3f,0x1f,0xef,0xed,
       +0xf6,0xfb,0x7d,0xbf,0x6f,0xaf,0xef,0xed,0x8f,0xf6,0xfb,0xfb,0xfe,0x3e,0xdf,0x9f,
       +0x00,0x00,0x19,0x0f,0xc6,0x30,0xd0,0x00,0xcc,0x00,0x28,0x59,0x86,0x67,0xf0,0x01,
       +0x72,0x00,0x00,0x3f,0x86,0x00,0xc0,0x03,0x18,0xf4,0x00,0x00,0x0c,0x18,0xcc,0xc5,
       +0x32,0x83,0x4c,0x00,0x66,0x33,0x19,0x8c,0xc6,0x63,0x31,0xbc,0xc0,0x3e,0x1f,0x0f,
       +0x87,0xc1,0x80,0xc0,0x60,0x30,0xfb,0x2c,0xb0,0xd8,0x6c,0x36,0x1b,0x0c,0x38,0xcb,
       +0x31,0x98,0xcc,0x66,0x31,0xa1,0x8c,0xcc,0x06,0x03,0x01,0x80,0xc0,0x60,0x30,0x6c,
       +0xc0,0x63,0x31,0x98,0xcc,0x60,0xc0,0x60,0x30,0x18,0x37,0x31,0x98,0xcc,0x66,0x33,
       +0x19,0x8c,0x00,0x67,0x31,0x98,0xcc,0x66,0x33,0x19,0x8c,0xc6,0x1f,0x7f,0x82,0x01,
       +0x02,0x40,0xb0,0x40,0x6c,0x07,0x03,0x83,0x80,0xe0,0xe0,0x00,0x18,0x0e,0x10,0x10,
       +0x08,0x04,0x02,0x00,0xf0,0x20,0x10,0x1e,0x08,0x89,0x03,0x00,0xe0,0x38,0x1c,0x0e,
       +0x00,0x0c,0x00,0x04,0x81,0xe0,0x41,0x6c,0x00,0x30,0x03,0x00,0x0f,0xe0,0x03,0xf8,
       +0x00,0x30,0x63,0x06,0x03,0x00,0xc7,0xf0,0x39,0x8c,0x30,0x3e,0x1b,0x80,0x00,0x03,
       +0x00,0x00,0x18,0x30,0x9b,0x23,0x19,0x0c,0x06,0x33,0x01,0xf8,0xc6,0x63,0x0c,0x01,
       +0x8d,0x86,0x05,0xd9,0x35,0x86,0x7c,0x61,0x9b,0x01,0xc1,0x83,0x19,0x99,0xb4,0x1c,
       +0x0c,0x06,0x06,0x00,0xc0,0x30,0xcc,0x00,0x00,0x3f,0x18,0xcc,0x06,0x33,0xf8,0x60,
       +0xc6,0x63,0x06,0x01,0x8f,0x00,0xc6,0xd9,0x8c,0xc6,0x63,0x31,0x8c,0x0f,0x81,0x83,
       +0x18,0xd9,0xba,0x1c,0x1b,0x03,0x00,0x80,0xc0,0x81,0x75,0x54,0x98,0xc0,0x7d,0xfe,
       +0xfd,0xbf,0x4f,0xbf,0x93,0xf8,0xfc,0x7c,0x7f,0x1f,0x1f,0x6f,0xe7,0xf1,0xef,0xef,
       +0xf7,0xfb,0xfd,0xff,0x0f,0xdf,0xef,0xe1,0xf7,0x76,0xfc,0xff,0x1f,0xc7,0xe3,0xf1,
       +0xff,0x08,0x19,0x03,0x06,0x31,0xf8,0x00,0xc6,0x00,0x28,0x5b,0x8c,0xc0,0x11,0xf1,
       +0x4a,0x00,0x00,0x04,0x0c,0x00,0xc0,0x03,0x18,0x74,0x38,0x00,0x0c,0x18,0xc6,0x65,
       +0x52,0xb8,0x54,0x18,0x46,0x23,0x11,0x88,0xc4,0x62,0x31,0x30,0xc0,0x30,0x18,0x0c,
       +0x06,0x01,0x80,0xc0,0x60,0x30,0x63,0x26,0xb0,0xd8,0x6c,0x36,0x1b,0x0c,0x10,0xd3,
       +0x31,0x98,0xcc,0x66,0x30,0xc1,0x8c,0xc6,0x7e,0x3f,0x1f,0x8f,0xc7,0xe3,0xf1,0xfc,
       +0xc0,0x7f,0x3f,0x9f,0xcf,0xe0,0xc0,0x60,0x30,0x18,0x63,0x31,0x98,0xcc,0x66,0x33,
       +0x19,0x8c,0xfe,0x6b,0x31,0x98,0xcc,0x66,0x31,0xb1,0x8c,0x6c,0x0e,0x7f,0x82,0x01,
       +0x01,0x80,0x90,0x30,0xc6,0x08,0x01,0x02,0x00,0x40,0x80,0xe0,0x24,0x04,0x1c,0x10,
       +0x08,0x04,0x02,0x00,0x90,0x20,0x10,0x12,0x0d,0x86,0x00,0x81,0x00,0x40,0x20,0x10,
       +0x00,0x04,0x00,0x1f,0xe1,0x70,0xbb,0x28,0x00,0x30,0x03,0x00,0x01,0x00,0x00,0x00,
       +0x00,0x30,0x63,0x06,0x06,0x00,0x67,0xf0,0x19,0x8c,0x30,0x67,0x0d,0x80,0x00,0x01,
       +0x83,0xf8,0x30,0x30,0x9b,0x7f,0x19,0x8c,0x06,0x33,0x01,0x80,0xc6,0x63,0x0c,0x01,
       +0x8c,0xc6,0x05,0xd9,0x35,0x86,0x60,0x61,0x99,0x80,0xe1,0x83,0x18,0xd0,0xdc,0x26,
       +0x0c,0x0c,0x06,0x00,0xc0,0x30,0x84,0x00,0x00,0x63,0x18,0xcc,0x06,0x33,0x00,0x60,
       +0xc6,0x63,0x06,0x01,0x8d,0x80,0xc6,0xd9,0x8c,0xc6,0x63,0x31,0x8c,0x03,0xe1,0x83,
       +0x18,0xd9,0xba,0x1c,0x1b,0x06,0x01,0x80,0xc0,0xc1,0x38,0xaa,0x80,0xc0,0x7d,0xfe,
       +0xfe,0x7f,0x6f,0xcf,0x39,0xf7,0xfe,0xfd,0xff,0xbf,0x7f,0x0f,0xdb,0xfb,0xe3,0xef,
       +0xf7,0xfb,0xfd,0xff,0x6f,0xdf,0xef,0xed,0xf2,0x79,0xff,0x7e,0xff,0xbf,0xdf,0xef,
       +0x00,0x0c,0x19,0x03,0x03,0x60,0x60,0x30,0x66,0x00,0x28,0x4d,0xc6,0x60,0x10,0x00,
       +0x84,0x00,0x00,0x04,0x0f,0x87,0x80,0x03,0x18,0x14,0x38,0x00,0x3f,0x0f,0x8c,0xc2,
       +0x90,0x84,0xa4,0x18,0xfe,0x7f,0x3f,0x9f,0xcf,0xe7,0xf1,0xf0,0xc0,0x30,0x18,0x0c,
       +0x06,0x01,0x80,0xc0,0x60,0x30,0x63,0x26,0xb0,0xd8,0x6c,0x36,0x1b,0x0c,0x38,0xd3,
       +0x31,0x98,0xcc,0x66,0x30,0xc1,0x98,0xc6,0xc6,0x63,0x31,0x98,0xcc,0x66,0x33,0x60,
       +0xc0,0x60,0x30,0x18,0x0c,0x00,0xc0,0x60,0x30,0x18,0x63,0x31,0x98,0xcc,0x66,0x33,
       +0x19,0x8c,0x00,0x6b,0x31,0x98,0xcc,0x66,0x31,0xb1,0x8c,0x6c,0x1c,0x7f,0x81,0x20,
       +0x90,0x38,0x18,0x0b,0x83,0x06,0x01,0x03,0x80,0x40,0xe0,0x90,0x24,0x04,0x03,0x8e,
       +0x86,0xc3,0x61,0x90,0x24,0x12,0x0e,0x04,0x8a,0x81,0xc7,0x70,0xc0,0x30,0x18,0x0c,
       +0x00,0x00,0x00,0x04,0x81,0x31,0x6f,0x30,0x00,0x18,0x06,0x00,0x01,0x00,0x00,0x00,
       +0x00,0x60,0x63,0x06,0x0c,0x00,0x60,0x60,0x19,0x8c,0x60,0x63,0x01,0x80,0x00,0x00,
       +0xc0,0x00,0x60,0x00,0x4d,0xe1,0x99,0x8c,0x06,0x33,0x01,0x80,0xc6,0x63,0x0c,0x01,
       +0x8c,0xc6,0x04,0x99,0x1d,0x86,0x60,0x61,0x99,0x80,0x61,0x83,0x18,0xd0,0xdc,0x63,
       +0x0c,0x0c,0x06,0x00,0x60,0x30,0x84,0x00,0x00,0x63,0x18,0xcc,0x06,0x33,0x00,0x60,
       +0x6e,0x63,0x06,0x01,0x8c,0xc0,0xc6,0xd9,0x8c,0xc6,0x63,0x31,0x8c,0x00,0x61,0x83,
       +0x18,0xd0,0xcc,0x26,0x0e,0x0c,0x03,0x00,0xc0,0x60,0x01,0x54,0x98,0xc0,0x7e,0xdf,
       +0x6f,0xc7,0xe7,0xf4,0x7c,0xf9,0xfe,0xfc,0x7f,0xbf,0x1f,0x5f,0xdb,0xfb,0xfc,0x71,
       +0x79,0x3c,0x9e,0x6f,0xdb,0xed,0xf1,0xfb,0x75,0x7e,0x38,0x8f,0x3f,0xcf,0xe7,0xf3,
       +0xff,0x0c,0x0d,0x03,0x03,0xe1,0xf8,0x30,0x3c,0x00,0x27,0x40,0x03,0x30,0x00,0x00,
       +0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x18,0x14,0x00,0x00,0x00,0x00,0x19,0x82,
       +0xf8,0x98,0xbe,0x70,0xc3,0x61,0xb0,0xd8,0x6c,0x36,0x1b,0x30,0xc0,0x30,0x18,0x0c,
       +0x06,0x01,0x80,0xc0,0x60,0x30,0x63,0x23,0xb0,0xd8,0x6c,0x36,0x1b,0x0c,0x4c,0xe3,
       +0x31,0x98,0xcc,0x66,0x30,0xc1,0xf0,0xc6,0xc6,0x63,0x31,0x98,0xcc,0x66,0x33,0x60,
       +0xc0,0x60,0x30,0x18,0x0c,0x00,0xc0,0x60,0x30,0x18,0x63,0x31,0x98,0xcc,0x66,0x33,
       +0x19,0x8c,0x10,0x73,0x31,0x98,0xcc,0x66,0x30,0xe1,0x8c,0x38,0x1c,0x7f,0x80,0xa0,
       +0x50,0x10,0x24,0x0d,0xff,0x01,0x01,0x02,0x00,0x40,0x80,0xf0,0x24,0x04,0x02,0x01,
       +0x81,0x20,0x10,0x30,0x28,0x1a,0x09,0x06,0x8a,0x81,0x20,0x90,0x20,0x08,0x04,0x02,
       +0x00,0x0c,0x00,0x04,0x85,0x32,0x6f,0xb8,0x00,0x18,0x06,0x00,0x01,0x01,0xc0,0x00,
       +0x70,0x60,0x36,0x06,0x1f,0xcc,0xe0,0x63,0x30,0xd8,0x60,0x63,0x33,0x06,0x03,0x00,
       +0x60,0x00,0xc0,0x30,0x60,0x61,0x99,0x86,0x66,0x63,0x01,0x80,0x66,0x63,0x0c,0x03,
       +0x0c,0x66,0x04,0x19,0x1c,0xcc,0x60,0x33,0x18,0xcc,0x61,0x81,0xb0,0x60,0xcc,0x63,
       +0x0c,0x18,0x06,0x00,0x60,0x30,0x00,0x00,0x00,0x67,0x19,0x86,0x23,0x71,0x88,0x60,
       +0x36,0x63,0x06,0x01,0x8c,0x60,0xc6,0xd9,0x8c,0x6c,0x66,0x1b,0x8c,0x08,0x61,0x83,
       +0xb8,0x70,0xcc,0x63,0x0c,0x18,0x03,0x00,0xc0,0x60,0x00,0xaa,0x98,0xc0,0x7f,0x5f,
       +0xaf,0xef,0xdb,0xf2,0x00,0xfe,0xfe,0xfd,0xff,0xbf,0x7f,0x6f,0xdb,0xfb,0xfd,0xfe,
       +0x7e,0xdf,0xef,0xcf,0xd7,0xe5,0xf6,0xf9,0x75,0x7e,0xdf,0x6f,0xdf,0xf7,0xfb,0xfd,
       +0x00,0x0c,0x07,0xc6,0x04,0x10,0x60,0x30,0x06,0x00,0x10,0x80,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x3f,0x80,0x00,0x00,0x03,0xb8,0x14,0x00,0x00,0x00,0x00,0x00,0x04,
       +0x11,0x21,0x04,0xc0,0xc3,0x61,0xb0,0xd8,0x6c,0x36,0x1b,0x30,0x66,0x30,0x18,0x0c,
       +0x06,0x01,0x80,0xc0,0x60,0x30,0x66,0x23,0x99,0x8c,0xc6,0x63,0x31,0x98,0x00,0x66,
       +0x1b,0x0d,0x86,0xc3,0x60,0xc1,0x80,0xc6,0xce,0x67,0x33,0x99,0xcc,0xe6,0x73,0x74,
       +0x62,0x31,0x18,0x8c,0x46,0x20,0xc0,0x60,0x30,0x18,0x36,0x31,0x8d,0x86,0xc3,0x61,
       +0xb0,0xd8,0x10,0x36,0x3b,0x9d,0xce,0xe7,0x70,0xc1,0x98,0x30,0x00,0x7f,0x80,0xc0,
       +0x60,0x10,0x24,0x0c,0x38,0x0e,0x01,0x02,0x00,0x40,0x80,0xa0,0x18,0x0e,0x03,0x00,
       +0x80,0x40,0x60,0x50,0x30,0x16,0x0e,0x05,0x88,0x81,0xc0,0x81,0xc0,0x70,0x38,0x1c,
       +0x00,0x0c,0x00,0x04,0x83,0xe0,0x39,0xcc,0x00,0x0c,0x0c,0x00,0x00,0x01,0xc0,0x00,
       +0x70,0xc0,0x1c,0x06,0x1f,0xc7,0xc0,0x61,0xe0,0x70,0x60,0x3e,0x1e,0x06,0x03,0x00,
       +0x00,0x00,0x00,0x30,0x1e,0x61,0x9f,0x03,0xc7,0xc3,0xf1,0x80,0x3e,0x63,0x3f,0x1e,
       +0x0c,0x67,0xe4,0x19,0x0c,0x78,0x60,0x1e,0x18,0xc7,0xc1,0x80,0xe0,0x60,0xcc,0x63,
       +0x0c,0x1f,0xc6,0x00,0x30,0x30,0x00,0x00,0x00,0x3b,0x9f,0x03,0xc1,0xb0,0xf0,0x60,
       +0x06,0x63,0x06,0x01,0x8c,0x70,0xc6,0xd9,0x8c,0x38,0x7c,0x0d,0x8c,0x07,0xc0,0xf1,
       +0xd8,0x60,0xcc,0x63,0x0c,0x1f,0xc3,0x00,0xc0,0x60,0x01,0x54,0x80,0xc0,0x7f,0x3f,
       +0x9f,0xef,0xdb,0xf3,0xc7,0xf1,0xfe,0xfd,0xff,0xbf,0x7f,0xff,0xe7,0xf1,0xfc,0xff,
       +0x7f,0xbf,0x9f,0xaf,0xcf,0xe9,0xf1,0xfa,0x77,0x7e,0x3f,0x7e,0x3f,0x8f,0xc7,0xe3,
       +0xff,0x0c,0x01,0x0f,0xe8,0x08,0x60,0x30,0xc6,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xd8,0x14,0x00,0x00,0x00,0x00,0x00,0x04,
       +0x11,0x3d,0x04,0xc0,0xc3,0x61,0xb0,0xd8,0x6c,0x36,0x1b,0x3c,0x3c,0x3f,0x1f,0x8f,
       +0xc7,0xe7,0xe3,0xf1,0xf8,0xfc,0x7c,0x21,0x8f,0x07,0x83,0xc1,0xe0,0xf0,0x00,0xbc,
       +0x0e,0x07,0x03,0x81,0xc0,0xc1,0x80,0xcc,0x77,0x3b,0x9d,0xce,0xe7,0x73,0xb9,0x98,
       +0x3c,0x1e,0x0f,0x07,0x83,0xc0,0xc0,0x60,0x30,0x18,0x1c,0x31,0x87,0x03,0x81,0xc0,
       +0xe0,0x70,0x00,0x5c,0x1d,0x8e,0xc7,0x63,0xb0,0xc1,0xf0,0x30,0x00,0x7f,0x81,0x40,
       +0xa0,0x10,0x28,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x02,0x00,
       +0x80,0x80,0x10,0xf8,0x28,0x12,0x09,0x04,0x80,0x01,0x20,0x80,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x06,0x18,0x00,0x00,0x00,0x40,0x00,
       +0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x07,0xc0,0x31,0xf0,0x01,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0xcc,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x80,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x18,0x00,0x01,0xe0,0xc3,0xc0,0x00,0x00,0xff,0xc0,0x7e,0xbf,
       +0x5f,0xef,0xd7,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,
       +0x7f,0x7f,0xef,0x07,0xd7,0xed,0xf6,0xfb,0x7f,0xfe,0xdf,0x7f,0xff,0xff,0xff,0xff,
       +0x00,0x0c,0x01,0x00,0x00,0x00,0x00,0x30,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x14,0x00,0x08,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x81,0x80,0x60,0x00,0x7f,0x81,0x20,
       +0x90,0x10,0x1c,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,
       +0x81,0xe0,0x60,0x10,0x24,0x12,0x0e,0x04,0x80,0x01,0xc0,0x70,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x78,0x00,0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x80,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0xfe,0xdf,
       +0x6f,0xef,0xe3,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x7f,
       +0x7e,0x1f,0x9f,0xef,0xdb,0xed,0xf1,0xfb,0x7f,0xfe,0x3f,0x8f,0xff,0xff,0xff,0xff,
       +0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x81,0x80,0x60,0x20,0x20,0x20,0x20,
       +0x20,0x20,0x20,0x20,0x32,0x35,0x36,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
       +0x20,0x31,0x35,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x31,0x33,0x20,
       +0x00,0x00,0x01,0x0c,0x00,0x09,0x09,0x00,0x01,0x0f,0x00,0x09,0x12,0x00,0x01,0x0f,
       +0x00,0x09,0x1b,0x00,0x01,0x0f,0x00,0x09,0x24,0x00,0x01,0x0f,0x00,0x09,0x2d,0x00,
       +0x01,0x0f,0x00,0x09,0x36,0x00,0x01,0x0f,0x00,0x09,0x3f,0x00,0x03,0x0d,0x00,0x09,
       +0x48,0x00,0x03,0x0d,0x00,0x09,0x51,0x00,0x03,0x0d,0x00,0x09,0x5a,0x00,0x03,0x0d,
       +0x00,0x09,0x63,0x00,0x03,0x0d,0x00,0x09,0x6c,0x00,0x03,0x0d,0x00,0x09,0x75,0x00,
       +0x03,0x0e,0x00,0x09,0x7e,0x00,0x03,0x0d,0x00,0x09,0x87,0x00,0x03,0x0d,0x00,0x09,
       +0x90,0x00,0x01,0x0f,0x00,0x09,0x99,0x00,0x01,0x0f,0x00,0x09,0xa2,0x00,0x01,0x0f,
       +0x00,0x09,0xab,0x00,0x01,0x0f,0x00,0x09,0xb4,0x00,0x01,0x0f,0x00,0x09,0xbd,0x00,
       +0x01,0x0f,0x00,0x09,0xc6,0x00,0x01,0x0f,0x00,0x09,0xcf,0x00,0x01,0x0f,0x00,0x09,
       +0xd8,0x00,0x01,0x0f,0x00,0x09,0xe1,0x00,0x03,0x0d,0x00,0x09,0xea,0x00,0x01,0x0f,
       +0x00,0x09,0xf3,0x00,0x01,0x0f,0x00,0x09,0xfc,0x00,0x03,0x0d,0x00,0x09,0x05,0x01,
       +0x03,0x0d,0x00,0x09,0x0e,0x01,0x03,0x0d,0x00,0x09,0x17,0x01,0x03,0x0d,0x00,0x09,
       +0x20,0x01,0x00,0x00,0x00,0x09,0x29,0x01,0x03,0x0d,0x00,0x09,0x32,0x01,0x02,0x05,
       +0x00,0x09,0x3b,0x01,0x03,0x0d,0x00,0x09,0x44,0x01,0x02,0x0e,0x00,0x09,0x4d,0x01,
       +0x03,0x0d,0x00,0x09,0x56,0x01,0x03,0x0d,0x00,0x09,0x5f,0x01,0x02,0x06,0x00,0x09,
       +0x68,0x01,0x02,0x0e,0x00,0x09,0x71,0x01,0x02,0x0e,0x00,0x09,0x7a,0x01,0x03,0x08,
       +0x00,0x09,0x83,0x01,0x05,0x0c,0x00,0x09,0x8c,0x01,0x0b,0x0f,0x00,0x09,0x95,0x01,
       +0x08,0x09,0x00,0x09,0x9e,0x01,0x0b,0x0d,0x00,0x09,0xa7,0x01,0x02,0x0e,0x00,0x09,
       +0xb0,0x01,0x03,0x0d,0x00,0x09,0xb9,0x01,0x03,0x0d,0x00,0x09,0xc2,0x01,0x03,0x0d,
       +0x00,0x09,0xcb,0x01,0x03,0x0d,0x00,0x09,0xd4,0x01,0x03,0x0d,0x00,0x09,0xdd,0x01,
       +0x03,0x0d,0x00,0x09,0xe6,0x01,0x03,0x0d,0x00,0x09,0xef,0x01,0x03,0x0d,0x00,0x09,
       +0xf8,0x01,0x03,0x0d,0x00,0x09,0x01,0x02,0x03,0x0d,0x00,0x09,0x0a,0x02,0x06,0x0d,
       +0x00,0x09,0x13,0x02,0x06,0x0f,0x00,0x09,0x1c,0x02,0x05,0x0c,0x00,0x09,0x25,0x02,
       +0x07,0x0a,0x00,0x09,0x2e,0x02,0x05,0x0c,0x00,0x09,0x37,0x02,0x03,0x0d,0x00,0x09,
       +0x40,0x02,0x03,0x0d,0x00,0x09,0x49,0x02,0x03,0x0d,0x00,0x09,0x52,0x02,0x03,0x0d,
       +0x00,0x09,0x5b,0x02,0x03,0x0d,0x00,0x09,0x64,0x02,0x03,0x0d,0x00,0x09,0x6d,0x02,
       +0x03,0x0d,0x00,0x09,0x76,0x02,0x03,0x0d,0x00,0x09,0x7f,0x02,0x03,0x0d,0x00,0x09,
       +0x88,0x02,0x03,0x0d,0x00,0x09,0x91,0x02,0x03,0x0d,0x00,0x09,0x9a,0x02,0x03,0x0d,
       +0x00,0x09,0xa3,0x02,0x03,0x0d,0x00,0x09,0xac,0x02,0x03,0x0d,0x00,0x09,0xb5,0x02,
       +0x03,0x0d,0x00,0x09,0xbe,0x02,0x03,0x0d,0x00,0x09,0xc7,0x02,0x03,0x0d,0x00,0x09,
       +0xd0,0x02,0x03,0x0d,0x00,0x09,0xd9,0x02,0x03,0x0f,0x00,0x09,0xe2,0x02,0x03,0x0d,
       +0x00,0x09,0xeb,0x02,0x03,0x0d,0x00,0x09,0xf4,0x02,0x03,0x0d,0x00,0x09,0xfd,0x02,
       +0x03,0x0d,0x00,0x09,0x06,0x03,0x03,0x0d,0x00,0x09,0x0f,0x03,0x03,0x0d,0x00,0x09,
       +0x18,0x03,0x03,0x0d,0x00,0x09,0x21,0x03,0x03,0x0d,0x00,0x09,0x2a,0x03,0x03,0x0d,
       +0x00,0x09,0x33,0x03,0x02,0x0e,0x00,0x09,0x3c,0x03,0x02,0x0e,0x00,0x09,0x45,0x03,
       +0x02,0x0e,0x00,0x09,0x4e,0x03,0x04,0x0b,0x00,0x09,0x57,0x03,0x0d,0x0e,0x00,0x09,
       +0x60,0x03,0x02,0x06,0x00,0x09,0x69,0x03,0x05,0x0d,0x00,0x09,0x72,0x03,0x02,0x0d,
       +0x00,0x09,0x7b,0x03,0x05,0x0d,0x00,0x09,0x84,0x03,0x02,0x0d,0x00,0x09,0x8d,0x03,
       +0x05,0x0d,0x00,0x09,0x96,0x03,0x02,0x0d,0x00,0x09,0x9f,0x03,0x05,0x0f,0x00,0x09,
       +0xa8,0x03,0x02,0x0d,0x00,0x09,0xb1,0x03,0x02,0x0d,0x00,0x09,0xba,0x03,0x02,0x0f,
       +0x00,0x09,0xc3,0x03,0x02,0x0d,0x00,0x09,0xcc,0x03,0x02,0x0d,0x00,0x09,0xd5,0x03,
       +0x05,0x0d,0x00,0x09,0xde,0x03,0x05,0x0d,0x00,0x09,0xe7,0x03,0x05,0x0d,0x00,0x09,
       +0xf0,0x03,0x05,0x0f,0x00,0x09,0xf9,0x03,0x05,0x0f,0x00,0x09,0x02,0x04,0x05,0x0d,
       +0x00,0x09,0x0b,0x04,0x05,0x0d,0x00,0x09,0x14,0x04,0x03,0x0d,0x00,0x09,0x1d,0x04,
       +0x05,0x0d,0x00,0x09,0x26,0x04,0x05,0x0d,0x00,0x09,0x2f,0x04,0x05,0x0d,0x00,0x09,
       +0x38,0x04,0x05,0x0d,0x00,0x09,0x41,0x04,0x05,0x0f,0x00,0x09,0x4a,0x04,0x05,0x0d,
       +0x00,0x09,0x53,0x04,0x02,0x0e,0x00,0x09,0x5c,0x04,0x02,0x0e,0x00,0x09,0x65,0x04,
       +0x02,0x0e,0x00,0x09,0x6e,0x04,0x07,0x0a,0x00,0x09,0x77,0x04,0x01,0x0d,0x00,0x09,
       +0x80,0x04,0x00,0x0e,0x00,0x09,0x89,0x04,0x00,0x0f,0x00,0x09,0x92,0x04,0x00,0x0f,
       +0x00,0x09,0x9b,0x04,0x00,0x0f,0x00,0x09,0xa4,0x04,0x00,0x0f,0x00,0x09,0xad,0x04,
       +0x00,0x0f,0x00,0x09,0xb6,0x04,0x00,0x0f,0x00,0x09,0xbf,0x04,0x00,0x0f,0x00,0x09,
       +0xc8,0x04,0x00,0x0f,0x00,0x09,0xd1,0x04,0x00,0x0f,0x00,0x09,0xda,0x04,0x00,0x0f,
       +0x00,0x09,0xe3,0x04,0x00,0x0f,0x00,0x09,0xec,0x04,0x00,0x0f,0x00,0x09,0xf5,0x04,
       +0x00,0x0f,0x00,0x09,0xfe,0x04,0x00,0x0f,0x00,0x09,0x07,0x05,0x00,0x0f,0x00,0x09,
       +0x10,0x05,0x00,0x0f,0x00,0x09,0x19,0x05,0x00,0x0f,0x00,0x09,0x22,0x05,0x00,0x0f,
       +0x00,0x09,0x2b,0x05,0x00,0x0f,0x00,0x09,0x34,0x05,0x00,0x0f,0x00,0x09,0x3d,0x05,
       +0x00,0x0f,0x00,0x09,0x46,0x05,0x00,0x0f,0x00,0x09,0x4f,0x05,0x00,0x0f,0x00,0x09,
       +0x58,0x05,0x00,0x0f,0x00,0x09,0x61,0x05,0x00,0x0f,0x00,0x09,0x6a,0x05,0x00,0x0f,
       +0x00,0x09,0x73,0x05,0x00,0x0f,0x00,0x09,0x7c,0x05,0x00,0x0f,0x00,0x09,0x85,0x05,
       +0x00,0x0f,0x00,0x09,0x8e,0x05,0x00,0x0f,0x00,0x09,0x97,0x05,0x00,0x0f,0x00,0x09,
       +0xa0,0x05,0x00,0x0d,0x00,0x09,0xa9,0x05,0x05,0x0f,0x00,0x09,0xb2,0x05,0x02,0x0e,
       +0x00,0x09,0xbb,0x05,0x03,0x0d,0x00,0x09,0xc4,0x05,0x03,0x0d,0x00,0x09,0xcd,0x05,
       +0x03,0x0d,0x00,0x09,0xd6,0x05,0x02,0x0e,0x00,0x09,0xdf,0x05,0x03,0x0e,0x00,0x09,
       +0xe8,0x05,0x02,0x04,0x00,0x09,0xf1,0x05,0x03,0x0d,0x00,0x09,0xfa,0x05,0x03,0x0a,
       +0x00,0x09,0x03,0x06,0x06,0x0b,0x00,0x09,0x0c,0x06,0x07,0x0a,0x00,0x09,0x15,0x06,
       +0x08,0x09,0x00,0x09,0x1e,0x06,0x03,0x0b,0x00,0x09,0x27,0x06,0x02,0x03,0x00,0x09,
       +0x30,0x06,0x03,0x07,0x00,0x09,0x39,0x06,0x05,0x0c,0x00,0x09,0x42,0x06,0x03,0x0a,
       +0x00,0x09,0x4b,0x06,0x03,0x0a,0x00,0x09,0x54,0x06,0x02,0x04,0x00,0x09,0x5d,0x06,
       +0x05,0x0f,0x00,0x09,0x66,0x06,0x03,0x0e,0x00,0x09,0x6f,0x06,0x08,0x0a,0x00,0x09,
       +0x78,0x06,0x0d,0x0f,0x00,0x09,0x81,0x06,0x03,0x0a,0x00,0x09,0x8a,0x06,0x03,0x0a,
       +0x00,0x09,0x93,0x06,0x06,0x0b,0x00,0x09,0x9c,0x06,0x03,0x0d,0x00,0x09,0xa5,0x06,
       +0x03,0x0d,0x00,0x09,0xae,0x06,0x03,0x0d,0x00,0x09,0xb7,0x06,0x05,0x0f,0x00,0x09,
       +0xc0,0x06,0x00,0x0d,0x00,0x09,0xc9,0x06,0x00,0x0d,0x00,0x09,0xd2,0x06,0x00,0x0d,
       +0x00,0x09,0xdb,0x06,0x00,0x0d,0x00,0x09,0xe4,0x06,0x00,0x0d,0x00,0x09,0xed,0x06,
       +0x01,0x0d,0x00,0x09,0xf6,0x06,0x03,0x0d,0x00,0x09,0xff,0x06,0x03,0x0f,0x00,0x09,
       +0x08,0x07,0x00,0x0d,0x00,0x09,0x11,0x07,0x00,0x0d,0x00,0x09,0x1a,0x07,0x00,0x0d,
       +0x00,0x09,0x23,0x07,0x00,0x0d,0x00,0x09,0x2c,0x07,0x00,0x0d,0x00,0x09,0x35,0x07,
       +0x00,0x0d,0x00,0x09,0x3e,0x07,0x00,0x0d,0x00,0x09,0x47,0x07,0x00,0x0d,0x00,0x09,
       +0x50,0x07,0x03,0x0d,0x00,0x09,0x59,0x07,0x00,0x0d,0x00,0x09,0x62,0x07,0x00,0x0d,
       +0x00,0x09,0x6b,0x07,0x00,0x0d,0x00,0x09,0x74,0x07,0x00,0x0d,0x00,0x09,0x7d,0x07,
       +0x00,0x0d,0x00,0x09,0x86,0x07,0x00,0x0d,0x00,0x09,0x8f,0x07,0x06,0x0b,0x00,0x09,
       +0x98,0x07,0x03,0x0d,0x00,0x09,0xa1,0x07,0x00,0x0d,0x00,0x09,0xaa,0x07,0x00,0x0d,
       +0x00,0x09,0xb3,0x07,0x00,0x0d,0x00,0x09,0xbc,0x07,0x00,0x0d,0x00,0x09,0xc5,0x07,
       +0x00,0x0d,0x00,0x09,0xce,0x07,0x03,0x0d,0x00,0x09,0xd7,0x07,0x02,0x0d,0x00,0x09,
       +0xe0,0x07,0x02,0x0d,0x00,0x09,0xe9,0x07,0x02,0x0d,0x00,0x09,0xf2,0x07,0x02,0x0d,
       +0x00,0x09,0xfb,0x07,0x02,0x0d,0x00,0x09,0x04,0x08,0x02,0x0d,0x00,0x09,0x0d,0x08,
       +0x02,0x0d,0x00,0x09,0x16,0x08,0x05,0x0d,0x00,0x09,0x1f,0x08,0x05,0x0f,0x00,0x09,
       +0x28,0x08,0x02,0x0d,0x00,0x09,0x31,0x08,0x02,0x0d,0x00,0x09,0x3a,0x08,0x02,0x0d,
       +0x00,0x09,0x43,0x08,0x02,0x0d,0x00,0x09,0x4c,0x08,0x02,0x0d,0x00,0x09,0x55,0x08,
       +0x02,0x0d,0x00,0x09,0x5e,0x08,0x02,0x0d,0x00,0x09,0x67,0x08,0x02,0x0d,0x00,0x09,
       +0x70,0x08,0x02,0x0d,0x00,0x09,0x79,0x08,0x02,0x0d,0x00,0x09,0x82,0x08,0x02,0x0d,
       +0x00,0x09,0x8b,0x08,0x02,0x0d,0x00,0x09,0x94,0x08,0x02,0x0d,0x00,0x09,0x9d,0x08,
       +0x02,0x0d,0x00,0x09,0xa6,0x08,0x02,0x0d,0x00,0x09,0xaf,0x08,0x05,0x0c,0x00,0x09,
       +0xb8,0x08,0x05,0x0d,0x00,0x09,0xc1,0x08,0x02,0x0d,0x00,0x09,0xca,0x08,0x02,0x0d,
       +0x00,0x09,0xd3,0x08,0x02,0x0d,0x00,0x09,0xdc,0x08,0x02,0x0d,0x00,0x09,0xe5,0x08,
       +0x02,0x0f,0x00,0x09,0xee,0x08,0x03,0x0f,0x00,0x09,0xf7,0x08,0x02,0x0f,0x00,0x09,
       +0x00,0x09,0x00,0x00,0x00,0x00,
       +};
       +
       +int        sizeofdefont = sizeof defontdata;
       +
       +void
       +_unpackinfo(Fontchar *fc, uchar *p, int n)
       +{
       +        int j;
       +
       +        for(j=0;  j<=n;  j++){
       +                fc->x = p[0]|(p[1]<<8);
       +                fc->top = p[2];
       +                fc->bottom = p[3];
       +                fc->left = p[4];
       +                fc->width = p[5];
       +                fc++;
       +                p += 6;
       +        }
       +}
 (DIR) diff --git a/src/libdraw/draw.c b/src/libdraw/draw.c
       t@@ -0,0 +1,69 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +void
       +_setdrawop(Display *d, Drawop op)
       +{
       +        uchar *a;
       +
       +        if(op != SoverD){
       +                a = bufimage(d, 1+1);
       +                if(a == 0)
       +                        return;
       +                a[0] = 'O';
       +                a[1] = op;
       +        }
       +}
       +                
       +static void
       +draw1(Image *dst, Rectangle *r, Image *src, Point *p0, Image *mask, Point *p1, Drawop op)
       +{
       +        uchar *a;
       +
       +        _setdrawop(dst->display, op);
       +
       +        a = bufimage(dst->display, 1+4+4+4+4*4+2*4+2*4);
       +        if(a == 0)
       +                return;
       +        if(src == nil)
       +                src = dst->display->black;
       +        if(mask == nil)
       +                mask = dst->display->opaque;
       +        a[0] = 'd';
       +        BPLONG(a+1, dst->id);
       +        BPLONG(a+5, src->id);
       +        BPLONG(a+9, mask->id);
       +        BPLONG(a+13, r->min.x);
       +        BPLONG(a+17, r->min.y);
       +        BPLONG(a+21, r->max.x);
       +        BPLONG(a+25, r->max.y);
       +        BPLONG(a+29, p0->x);
       +        BPLONG(a+33, p0->y);
       +        BPLONG(a+37, p1->x);
       +        BPLONG(a+41, p1->y);
       +}
       +
       +void
       +draw(Image *dst, Rectangle r, Image *src, Image *mask, Point p1)
       +{
       +        draw1(dst, &r, src, &p1, mask, &p1, SoverD);
       +}
       +
       +void
       +drawop(Image *dst, Rectangle r, Image *src, Image *mask, Point p1, Drawop op)
       +{
       +        draw1(dst, &r, src, &p1, mask, &p1, op);
       +}
       +
       +void
       +gendraw(Image *dst, Rectangle r, Image *src, Point p0, Image *mask, Point p1)
       +{
       +        draw1(dst, &r, src, &p0, mask, &p1, SoverD);
       +}
       +
       +void
       +gendrawop(Image *dst, Rectangle r, Image *src, Point p0, Image *mask, Point p1, Drawop op)
       +{
       +        draw1(dst, &r, src, &p0, mask, &p1, op);
       +}
 (DIR) diff --git a/src/libdraw/drawrepl.c b/src/libdraw/drawrepl.c
       t@@ -0,0 +1,23 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +int
       +drawreplxy(int min, int max, int x)
       +{
       +        int sx;
       +
       +        sx = (x-min)%(max-min);
       +        if(sx < 0)
       +                sx += max-min;
       +        return sx+min;
       +}
       +
       +Point
       +drawrepl(Rectangle r, Point p)
       +{
       +        p.x = drawreplxy(r.min.x, r.max.x, p.x);
       +        p.y = drawreplxy(r.min.y, r.max.y, p.y);
       +        return p;
       +}
       +
 (DIR) diff --git a/src/libdraw/egetrect.c b/src/libdraw/egetrect.c
       t@@ -0,0 +1,116 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +#include <cursor.h>
       +#include <event.h>
       +
       +#define        W        Borderwidth
       +
       +static Image *tmp[4];
       +static Image *red;
       +
       +static Cursor sweep={
       +        {-7, -7},
       +        {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07,
       +         0xE0, 0x07, 0xE0, 0x07, 0xE3, 0xF7, 0xE3, 0xF7,
       +         0xE3, 0xE7, 0xE3, 0xF7, 0xE3, 0xFF, 0xE3, 0x7F,
       +         0xE0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,},
       +        {0x00, 0x00, 0x7F, 0xFE, 0x40, 0x02, 0x40, 0x02,
       +         0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x41, 0xE2,
       +         0x41, 0xC2, 0x41, 0xE2, 0x41, 0x72, 0x40, 0x38,
       +         0x40, 0x1C, 0x40, 0x0E, 0x7F, 0xE6, 0x00, 0x00,}
       +};
       +
       +static
       +void
       +brects(Rectangle r, Rectangle rp[4])
       +{
       +        if(Dx(r) < 2*W)
       +                r.max.x = r.min.x+2*W;
       +        if(Dy(r) < 2*W)
       +                r.max.y = r.min.y+2*W;
       +        rp[0] = Rect(r.min.x, r.min.y, r.max.x, r.min.y+W);
       +        rp[1] = Rect(r.min.x, r.max.y-W, r.max.x, r.max.y);
       +        rp[2] = Rect(r.min.x, r.min.y+W, r.min.x+W, r.max.y-W);
       +        rp[3] = Rect(r.max.x-W, r.min.y+W, r.max.x, r.max.y-W);
       +}
       +
       +Rectangle
       +egetrect(int but, Mouse *m)
       +{
       +        Rectangle r, rc;
       +
       +        but = 1<<(but-1);
       +        esetcursor(&sweep);
       +        while(m->buttons)
       +                *m = emouse();
       +        while(!(m->buttons & but)){
       +                *m = emouse();
       +                if(m->buttons & (7^but))
       +                        goto Return;
       +        }
       +        r.min = m->xy;
       +        r.max = m->xy;
       +        do{
       +                rc = canonrect(r);
       +                edrawgetrect(rc, 1);
       +                *m = emouse();
       +                edrawgetrect(rc, 0);
       +                r.max = m->xy;
       +        }while(m->buttons == but);
       +
       +    Return:
       +        esetcursor(0);
       +        if(m->buttons & (7^but)){
       +                rc.min.x = rc.max.x = 0;
       +                rc.min.y = rc.max.y = 0;
       +                while(m->buttons)
       +                        *m = emouse();
       +        }
       +        return rc;
       +}
       +
       +static
       +void
       +freetmp(void)
       +{
       +        freeimage(tmp[0]);
       +        freeimage(tmp[1]);
       +        freeimage(tmp[2]);
       +        freeimage(tmp[3]);
       +        freeimage(red);
       +        tmp[0] = tmp[1] = tmp[2] = tmp[3] = red = nil;
       +}
       +
       +void
       +edrawgetrect(Rectangle rc, int up)
       +{
       +        int i;
       +        Rectangle r, rects[4];
       +
       +        if(up && tmp[0]!=nil)
       +                if(Dx(tmp[0]->r)<Dx(rc) || Dy(tmp[2]->r)<Dy(rc))
       +                        freetmp();
       +
       +        if(tmp[0] == 0){
       +                r = Rect(0, 0, Dx(screen->r), W);
       +                tmp[0] = allocimage(display, r, screen->chan, 0, -1);
       +                tmp[1] = allocimage(display, r, screen->chan, 0, -1);
       +                r = Rect(0, 0, W, Dy(screen->r));
       +                tmp[2] = allocimage(display, r, screen->chan, 0, -1);
       +                tmp[3] = allocimage(display, r, screen->chan, 0, -1);
       +                red = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DRed);
       +                if(tmp[0]==0 || tmp[1]==0 || tmp[2]==0 || tmp[3]==0 || red==0)
       +                        drawerror(display, "getrect: allocimage failed");
       +        }
       +        brects(rc, rects);
       +        if(!up){
       +                for(i=0; i<4; i++)
       +                        draw(screen, rects[i], tmp[i], nil, ZP);
       +                return;
       +        }
       +        for(i=0; i<4; i++){
       +                draw(tmp[i], Rect(0, 0, Dx(rects[i]), Dy(rects[i])), screen, nil, rects[i].min);
       +                draw(screen, rects[i], red, nil, ZP);
       +        }
       +}
 (DIR) diff --git a/src/libdraw/freesubfont.c b/src/libdraw/freesubfont.c
       t@@ -0,0 +1,17 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +void
       +freesubfont(Subfont *f)
       +{
       +        if(f == 0)
       +                return;
       +        f->ref--;
       +        if(f->ref > 0)
       +                return;
       +        uninstallsubfont(f);
       +        free(f->info);        /* note: f->info must have been malloc'ed! */
       +        freeimage(f->bits);
       +        free(f);
       +}
 (DIR) diff --git a/src/libdraw/getdefont.c b/src/libdraw/getdefont.c
       t@@ -0,0 +1,60 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +Subfont*
       +getdefont(Display *d)
       +{
       +        char *hdr, *p;
       +        int n;
       +        Fontchar *fc;
       +        Subfont *f;
       +        int ld;
       +        Rectangle r;
       +        Image *i;
       +
       +        /*
       +         * make sure data is word-aligned.  this is true with Plan 9 compilers
       +         * but not in general.  the byte order is right because the data is
       +         * declared as char*, not ulong*.
       +         */
       +        p = (char*)defontdata;
       +        n = (ulong)p & 3;
       +        if(n != 0){
       +                memmove(p+(4-n), p, sizeofdefont-n);
       +                p += 4-n;
       +        }
       +        ld = atoi(p+0*12);
       +        r.min.x = atoi(p+1*12);
       +        r.min.y = atoi(p+2*12);
       +        r.max.x = atoi(p+3*12);
       +        r.max.y = atoi(p+4*12);
       +
       +        i = allocimage(d, r, drawld2chan[ld], 0, 0);
       +        if(i == 0)
       +                return 0;
       +
       +        p += 5*12;
       +        n = loadimage(i, r, (uchar*)p, (defontdata+sizeofdefont)-(uchar*)p);
       +        if(n < 0){
       +                freeimage(i);
       +                return 0;
       +        }
       +
       +        hdr = p+n;
       +        n = atoi(hdr);
       +        p = hdr+3*12;
       +        fc = malloc(sizeof(Fontchar)*(n+1));
       +        if(fc == 0){
       +                freeimage(i);
       +                return 0;
       +        }
       +        _unpackinfo(fc, (uchar*)p, n);
       +        f = allocsubfont("*default*", n, atoi(hdr+12), atoi(hdr+24), fc, i);
       +        if(f == 0){
       +                freeimage(i);
       +                free(fc);
       +                return 0;
       +        }
       +        return f;
       +}
 (DIR) diff --git a/src/libdraw/getrect.c b/src/libdraw/getrect.c
       t@@ -0,0 +1,133 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +#include <thread.h>
       +#include <cursor.h>
       +#include <mouse.h>
       +
       +#define        W        Borderwidth
       +
       +static Image *tmp[4];
       +static Image *red;
       +
       +static Cursor sweep={
       +        {-7, -7},
       +        {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07,
       +         0xE0, 0x07, 0xE0, 0x07, 0xE3, 0xF7, 0xE3, 0xF7,
       +         0xE3, 0xE7, 0xE3, 0xF7, 0xE3, 0xFF, 0xE3, 0x7F,
       +         0xE0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,},
       +        {0x00, 0x00, 0x7F, 0xFE, 0x40, 0x02, 0x40, 0x02,
       +         0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x41, 0xE2,
       +         0x41, 0xC2, 0x41, 0xE2, 0x41, 0x72, 0x40, 0x38,
       +         0x40, 0x1C, 0x40, 0x0E, 0x7F, 0xE6, 0x00, 0x00,}
       +};
       +
       +static
       +void
       +brects(Rectangle r, Rectangle rp[4])
       +{
       +        if(Dx(r) < 2*W)
       +                r.max.x = r.min.x+2*W;
       +        if(Dy(r) < 2*W)
       +                r.max.y = r.min.y+2*W;
       +        rp[0] = Rect(r.min.x, r.min.y, r.max.x, r.min.y+W);
       +        rp[1] = Rect(r.min.x, r.max.y-W, r.max.x, r.max.y);
       +        rp[2] = Rect(r.min.x, r.min.y+W, r.min.x+W, r.max.y-W);
       +        rp[3] = Rect(r.max.x-W, r.min.y+W, r.max.x, r.max.y-W);
       +}
       +
       +Rectangle
       +getrect(int but, Mousectl *mc)
       +{
       +        Rectangle r, rc;
       +
       +        but = 1<<(but-1);
       +        setcursor(mc, &sweep);
       +        while(mc->m.buttons)
       +                readmouse(mc);
       +        while(!(mc->m.buttons & but)){
       +                readmouse(mc);
       +                if(mc->m.buttons & (7^but))
       +                        goto Return;
       +        }
       +        r.min = mc->m.xy;
       +        r.max = mc->m.xy;
       +        do{
       +                rc = canonrect(r);
       +                drawgetrect(rc, 1);
       +                readmouse(mc);
       +                drawgetrect(rc, 0);
       +                r.max = mc->m.xy;
       +        }while(mc->m.buttons == but);
       +
       +    Return:
       +        setcursor(mc, nil);
       +        if(mc->m.buttons & (7^but)){
       +                rc.min.x = rc.max.x = 0;
       +                rc.min.y = rc.max.y = 0;
       +                while(mc->m.buttons)
       +                        readmouse(mc);
       +        }
       +        return rc;
       +}
       +
       +static
       +void
       +freetmp(void)
       +{
       +        freeimage(tmp[0]);
       +        freeimage(tmp[1]);
       +        freeimage(tmp[2]);
       +        freeimage(tmp[3]);
       +        freeimage(red);
       +        tmp[0] = tmp[1] = tmp[2] = tmp[3] = red = nil;
       +}
       +
       +static
       +int
       +max(int a, int b)
       +{
       +        if(a > b)
       +                return a;
       +        return b;
       +}
       +
       +void
       +drawgetrect(Rectangle rc, int up)
       +{
       +        int i;
       +        Rectangle r, rects[4];
       +
       +        /*
       +         * BUG: if for some reason we have two of these going on at once
       +         * when we must grow the tmp buffers, we lose data.  Also if tmp
       +         * is unallocated and we ask to restore the screen, it would be nice
       +         * to complain, but we silently make a mess.
       +         */
       +        if(up && tmp[0]!=nil)
       +                if(Dx(tmp[0]->r)<Dx(rc) || Dy(tmp[2]->r)<Dy(rc))
       +                        freetmp();
       +        if(tmp[0] == 0){
       +                r = Rect(0, 0, max(Dx(display->screenimage->r), Dx(rc)), W);
       +                tmp[0] = allocimage(display, r, screen->chan, 0, -1);
       +                tmp[1] = allocimage(display, r, screen->chan, 0, -1);
       +                r = Rect(0, 0, W, max(Dy(display->screenimage->r), Dy(rc)));
       +                tmp[2] = allocimage(display, r, screen->chan, 0, -1);
       +                tmp[3] = allocimage(display, r, screen->chan, 0, -1);
       +                red = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DRed);
       +                if(tmp[0]==0 || tmp[1]==0 || tmp[2]==0 || tmp[3]==0 || red==0){
       +                        freetmp();
       +                        drawerror(display, "getrect: allocimage failed");
       +                }
       +        }
       +        brects(rc, rects);
       +        if(!up){
       +                for(i=0; i<4; i++)
       +                        draw(screen, rects[i], tmp[i], nil, ZP);
       +                return;
       +        }
       +        for(i=0; i<4; i++){
       +                draw(tmp[i], Rect(0, 0, Dx(rects[i]), Dy(rects[i])), screen, nil, rects[i].min);
       +                draw(screen, rects[i], red, nil, ZP);
       +        }
       +}
 (DIR) diff --git a/src/libdraw/icossin.c b/src/libdraw/icossin.c
       t@@ -0,0 +1,140 @@
       +#include        <u.h>
       +#include        <libc.h>
       +#include        <draw.h>
       +
       +/*
       + * Integer sine and cosine for integral degree argument.
       + * Tables computed by (sin,cos)(PI*d/180).
       + */
       +static short sinus[91] = {
       +        0,        /* 0 */
       +        18,        /* 1 */
       +        36,        /* 2 */
       +        54,        /* 3 */
       +        71,        /* 4 */
       +        89,        /* 5 */
       +        107,        /* 6 */
       +        125,        /* 7 */
       +        143,        /* 8 */
       +        160,        /* 9 */
       +        178,        /* 10 */
       +        195,        /* 11 */
       +        213,        /* 12 */
       +        230,        /* 13 */
       +        248,        /* 14 */
       +        265,        /* 15 */
       +        282,        /* 16 */
       +        299,        /* 17 */
       +        316,        /* 18 */
       +        333,        /* 19 */
       +        350,        /* 20 */
       +        367,        /* 21 */
       +        384,        /* 22 */
       +        400,        /* 23 */
       +        416,        /* 24 */
       +        433,        /* 25 */
       +        449,        /* 26 */
       +        465,        /* 27 */
       +        481,        /* 28 */
       +        496,        /* 29 */
       +        512,        /* 30 */
       +        527,        /* 31 */
       +        543,        /* 32 */
       +        558,        /* 33 */
       +        573,        /* 34 */
       +        587,        /* 35 */
       +        602,        /* 36 */
       +        616,        /* 37 */
       +        630,        /* 38 */
       +        644,        /* 39 */
       +        658,        /* 40 */
       +        672,        /* 41 */
       +        685,        /* 42 */
       +        698,        /* 43 */
       +        711,        /* 44 */
       +        724,        /* 45 */
       +        737,        /* 46 */
       +        749,        /* 47 */
       +        761,        /* 48 */
       +        773,        /* 49 */
       +        784,        /* 50 */
       +        796,        /* 51 */
       +        807,        /* 52 */
       +        818,        /* 53 */
       +        828,        /* 54 */
       +        839,        /* 55 */
       +        849,        /* 56 */
       +        859,        /* 57 */
       +        868,        /* 58 */
       +        878,        /* 59 */
       +        887,        /* 60 */
       +        896,        /* 61 */
       +        904,        /* 62 */
       +        912,        /* 63 */
       +        920,        /* 64 */
       +        928,        /* 65 */
       +        935,        /* 66 */
       +        943,        /* 67 */
       +        949,        /* 68 */
       +        956,        /* 69 */
       +        962,        /* 70 */
       +        968,        /* 71 */
       +        974,        /* 72 */
       +        979,        /* 73 */
       +        984,        /* 74 */
       +        989,        /* 75 */
       +        994,        /* 76 */
       +        998,        /* 77 */
       +        1002,        /* 78 */
       +        1005,        /* 79 */
       +        1008,        /* 80 */
       +        1011,        /* 81 */
       +        1014,        /* 82 */
       +        1016,        /* 83 */
       +        1018,        /* 84 */
       +        1020,        /* 85 */
       +        1022,        /* 86 */
       +        1023,        /* 87 */
       +        1023,        /* 88 */
       +        1024,        /* 89 */
       +        1024,        /* 90 */
       +};
       +
       +void
       +icossin(int deg, int *cosp, int *sinp)
       +{
       +        int sinsign, cossign;
       +        short *stp, *ctp;
       +
       +        deg %= 360;
       +        if(deg < 0)
       +                deg += 360;
       +        sinsign = 1;
       +        cossign = 1;
       +        stp = 0;
       +        ctp = 0;
       +        switch(deg/90){
       +        case 2:
       +                sinsign = -1;
       +                cossign = -1;
       +                deg -= 180;
       +                /* fall through */
       +        case 0:
       +                stp = &sinus[deg];
       +                ctp = &sinus[90-deg];
       +                break;
       +        case 3:
       +                sinsign = -1;
       +                cossign = -1;
       +                deg -= 180;
       +                /* fall through */
       +        case 1:
       +                deg = 180-deg;
       +                cossign = -cossign;
       +                stp = &sinus[deg];
       +                ctp = &sinus[90-deg];
       +                break;
       +        }
       +        *sinp = sinsign*stp[0];
       +        *cosp = cossign*ctp[0];
       +}
 (DIR) diff --git a/src/libdraw/icossin2.c b/src/libdraw/icossin2.c
       t@@ -0,0 +1,261 @@
       +#include        <u.h>
       +#include        <libc.h>
       +#include        <draw.h>
       +
       +/*
       + * Sine and Cosine of arctangents, calculated by 
       + *   (sin(atan(index/100.0))*1024.+0.5)
       + *   (cos(atan(index/100.0))*1024.+0.5)
       + * To use, get rational tangent between 0<=tan<=1, scale by 100,
       + * and look up sin and cos, and use linear interpolation.  divide by 1024.
       + * Maximum error is 0.0020.  Without linear interpolation, it's 0.010.
       + */
       +static
       +short sinus[] = {
       +        0,        /* 0.00 */
       +        10,        /* 0.01 */
       +        20,        /* 0.02 */
       +        31,        /* 0.03 */
       +        41,        /* 0.04 */
       +        51,        /* 0.05 */
       +        61,        /* 0.06 */
       +        72,        /* 0.07 */
       +        82,        /* 0.08 */
       +        92,        /* 0.09 */
       +        102,        /* 0.10 */
       +        112,        /* 0.11 */
       +        122,        /* 0.12 */
       +        132,        /* 0.13 */
       +        142,        /* 0.14 */
       +        152,        /* 0.15 */
       +        162,        /* 0.16 */
       +        172,        /* 0.17 */
       +        181,        /* 0.18 */
       +        191,        /* 0.19 */
       +        201,        /* 0.20 */
       +        210,        /* 0.21 */
       +        220,        /* 0.22 */
       +        230,        /* 0.23 */
       +        239,        /* 0.24 */
       +        248,        /* 0.25 */
       +        258,        /* 0.26 */
       +        267,        /* 0.27 */
       +        276,        /* 0.28 */
       +        285,        /* 0.29 */
       +        294,        /* 0.30 */
       +        303,        /* 0.31 */
       +        312,        /* 0.32 */
       +        321,        /* 0.33 */
       +        330,        /* 0.34 */
       +        338,        /* 0.35 */
       +        347,        /* 0.36 */
       +        355,        /* 0.37 */
       +        364,        /* 0.38 */
       +        372,        /* 0.39 */
       +        380,        /* 0.40 */
       +        388,        /* 0.41 */
       +        397,        /* 0.42 */
       +        405,        /* 0.43 */
       +        412,        /* 0.44 */
       +        420,        /* 0.45 */
       +        428,        /* 0.46 */
       +        436,        /* 0.47 */
       +        443,        /* 0.48 */
       +        451,        /* 0.49 */
       +        458,        /* 0.50 */
       +        465,        /* 0.51 */
       +        472,        /* 0.52 */
       +        480,        /* 0.53 */
       +        487,        /* 0.54 */
       +        493,        /* 0.55 */
       +        500,        /* 0.56 */
       +        507,        /* 0.57 */
       +        514,        /* 0.58 */
       +        520,        /* 0.59 */
       +        527,        /* 0.60 */
       +        533,        /* 0.61 */
       +        540,        /* 0.62 */
       +        546,        /* 0.63 */
       +        552,        /* 0.64 */
       +        558,        /* 0.65 */
       +        564,        /* 0.66 */
       +        570,        /* 0.67 */
       +        576,        /* 0.68 */
       +        582,        /* 0.69 */
       +        587,        /* 0.70 */
       +        593,        /* 0.71 */
       +        598,        /* 0.72 */
       +        604,        /* 0.73 */
       +        609,        /* 0.74 */
       +        614,        /* 0.75 */
       +        620,        /* 0.76 */
       +        625,        /* 0.77 */
       +        630,        /* 0.78 */
       +        635,        /* 0.79 */
       +        640,        /* 0.80 */
       +        645,        /* 0.81 */
       +        649,        /* 0.82 */
       +        654,        /* 0.83 */
       +        659,        /* 0.84 */
       +        663,        /* 0.85 */
       +        668,        /* 0.86 */
       +        672,        /* 0.87 */
       +        676,        /* 0.88 */
       +        681,        /* 0.89 */
       +        685,        /* 0.90 */
       +        689,        /* 0.91 */
       +        693,        /* 0.92 */
       +        697,        /* 0.93 */
       +        701,        /* 0.94 */
       +        705,        /* 0.95 */
       +        709,        /* 0.96 */
       +        713,        /* 0.97 */
       +        717,        /* 0.98 */
       +        720,        /* 0.99 */
       +        724,        /* 1.00 */
       +        728,        /* 1.01 */
       +};
       +
       +static
       +short cosinus[] = {
       +        1024,        /* 0.00 */
       +        1024,        /* 0.01 */
       +        1024,        /* 0.02 */
       +        1024,        /* 0.03 */
       +        1023,        /* 0.04 */
       +        1023,        /* 0.05 */
       +        1022,        /* 0.06 */
       +        1022,        /* 0.07 */
       +        1021,        /* 0.08 */
       +        1020,        /* 0.09 */
       +        1019,        /* 0.10 */
       +        1018,        /* 0.11 */
       +        1017,        /* 0.12 */
       +        1015,        /* 0.13 */
       +        1014,        /* 0.14 */
       +        1013,        /* 0.15 */
       +        1011,        /* 0.16 */
       +        1010,        /* 0.17 */
       +        1008,        /* 0.18 */
       +        1006,        /* 0.19 */
       +        1004,        /* 0.20 */
       +        1002,        /* 0.21 */
       +        1000,        /* 0.22 */
       +        998,        /* 0.23 */
       +        996,        /* 0.24 */
       +        993,        /* 0.25 */
       +        991,        /* 0.26 */
       +        989,        /* 0.27 */
       +        986,        /* 0.28 */
       +        983,        /* 0.29 */
       +        981,        /* 0.30 */
       +        978,        /* 0.31 */
       +        975,        /* 0.32 */
       +        972,        /* 0.33 */
       +        969,        /* 0.34 */
       +        967,        /* 0.35 */
       +        963,        /* 0.36 */
       +        960,        /* 0.37 */
       +        957,        /* 0.38 */
       +        954,        /* 0.39 */
       +        951,        /* 0.40 */
       +        947,        /* 0.41 */
       +        944,        /* 0.42 */
       +        941,        /* 0.43 */
       +        937,        /* 0.44 */
       +        934,        /* 0.45 */
       +        930,        /* 0.46 */
       +        927,        /* 0.47 */
       +        923,        /* 0.48 */
       +        920,        /* 0.49 */
       +        916,        /* 0.50 */
       +        912,        /* 0.51 */
       +        909,        /* 0.52 */
       +        905,        /* 0.53 */
       +        901,        /* 0.54 */
       +        897,        /* 0.55 */
       +        893,        /* 0.56 */
       +        890,        /* 0.57 */
       +        886,        /* 0.58 */
       +        882,        /* 0.59 */
       +        878,        /* 0.60 */
       +        874,        /* 0.61 */
       +        870,        /* 0.62 */
       +        866,        /* 0.63 */
       +        862,        /* 0.64 */
       +        859,        /* 0.65 */
       +        855,        /* 0.66 */
       +        851,        /* 0.67 */
       +        847,        /* 0.68 */
       +        843,        /* 0.69 */
       +        839,        /* 0.70 */
       +        835,        /* 0.71 */
       +        831,        /* 0.72 */
       +        827,        /* 0.73 */
       +        823,        /* 0.74 */
       +        819,        /* 0.75 */
       +        815,        /* 0.76 */
       +        811,        /* 0.77 */
       +        807,        /* 0.78 */
       +        804,        /* 0.79 */
       +        800,        /* 0.80 */
       +        796,        /* 0.81 */
       +        792,        /* 0.82 */
       +        788,        /* 0.83 */
       +        784,        /* 0.84 */
       +        780,        /* 0.85 */
       +        776,        /* 0.86 */
       +        773,        /* 0.87 */
       +        769,        /* 0.88 */
       +        765,        /* 0.89 */
       +        761,        /* 0.90 */
       +        757,        /* 0.91 */
       +        754,        /* 0.92 */
       +        750,        /* 0.93 */
       +        746,        /* 0.94 */
       +        742,        /* 0.95 */
       +        739,        /* 0.96 */
       +        735,        /* 0.97 */
       +        731,        /* 0.98 */
       +        728,        /* 0.99 */
       +        724,        /* 1.00 */
       +        720,        /* 1.01 */
       +};
       +
       +void
       +icossin2(int x, int y, int *cosp, int *sinp)
       +{
       +        int sinsign, cossign, tan, tan10, rem;
       +        short *stp, *ctp;
       +
       +        if(x == 0){
       +                if(y >= 0)
       +                        *sinp = ICOSSCALE, *cosp = 0;
       +                else
       +                        *sinp = -ICOSSCALE, *cosp = 0;
       +                return;
       +        }
       +        sinsign = cossign = 1;
       +        if(x < 0){
       +                cossign = -1;
       +                x = -x;
       +        }
       +        if(y < 0){
       +                sinsign = -1;
       +                y = -y;
       +        }
       +        if(y > x){
       +                tan = 1000*x/y;
       +                tan10 = tan/10;
       +                stp = &cosinus[tan10];
       +                ctp = &sinus[tan10];
       +        }else{
       +                tan = 1000*y/x;
       +                tan10 = tan/10;
       +                stp = &sinus[tan10];
       +                ctp = &cosinus[tan10];
       +        }
       +        rem = tan-(tan10*10);
       +        *sinp = sinsign*(stp[0]+(stp[1]-stp[0])*rem/10);
       +        *cosp = cossign*(ctp[0]+(ctp[1]-ctp[0])*rem/10);
       +}
 (DIR) diff --git a/src/libdraw/line.c b/src/libdraw/line.c
       t@@ -0,0 +1,35 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +void
       +line(Image *dst, Point p0, Point p1, int end0, int end1, int radius, Image *src, Point sp)
       +{
       +        lineop(dst, p0, p1, end0, end1, radius, src, sp, SoverD);
       +}
       +
       +void
       +lineop(Image *dst, Point p0, Point p1, int end0, int end1, int radius, Image *src, Point sp, Drawop op)
       +{
       +        uchar *a;
       +
       +        _setdrawop(dst->display, op);
       +
       +        a = bufimage(dst->display, 1+4+2*4+2*4+4+4+4+4+2*4);
       +        if(a == 0){
       +                fprint(2, "image line: %r\n");
       +                return;
       +        }
       +        a[0] = 'L';
       +        BPLONG(a+1, dst->id);
       +        BPLONG(a+5, p0.x);
       +        BPLONG(a+9, p0.y);
       +        BPLONG(a+13, p1.x);
       +        BPLONG(a+17, p1.y);
       +        BPLONG(a+21, end0);
       +        BPLONG(a+25, end1);
       +        BPLONG(a+29, radius);
       +        BPLONG(a+33, src->id);
       +        BPLONG(a+37, sp.x);
       +        BPLONG(a+41, sp.y);
       +}
 (DIR) diff --git a/src/libdraw/loadimage.c b/src/libdraw/loadimage.c
       t@@ -0,0 +1,54 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +int
       +loadimage(Image *i, Rectangle r, uchar *data, int ndata)
       +{
       +        long dy;
       +        int n, bpl;
       +        uchar *a;
       +        int chunk;
       +
       +        chunk = i->display->bufsize - 64;
       +
       +        if(!rectinrect(r, i->r)){
       +                werrstr("loadimage: bad rectangle");
       +                return -1;
       +        }
       +        bpl = bytesperline(r, i->depth);
       +        n = bpl*Dy(r);
       +        if(n > ndata){
       +                werrstr("loadimage: insufficient data");
       +                return -1;
       +        }
       +        ndata = 0;
       +        while(r.max.y > r.min.y){
       +                dy = r.max.y - r.min.y;
       +                if(dy*bpl > chunk)
       +                        dy = chunk/bpl;
       +                if(dy <= 0){
       +                        werrstr("loadimage: image too wide for buffer");
       +                        return -1;
       +                }
       +                n = dy*bpl;
       +                a = bufimage(i->display, 21+n);
       +                if(a == nil){
       +                        werrstr("bufimage failed");
       +                        return -1;
       +                }
       +                a[0] = 'y';
       +                BPLONG(a+1, i->id);
       +                BPLONG(a+5, r.min.x);
       +                BPLONG(a+9, r.min.y);
       +                BPLONG(a+13, r.max.x);
       +                BPLONG(a+17, r.min.y+dy);
       +                memmove(a+21, data, n);
       +                ndata += n;
       +                data += n;
       +                r.min.y += dy;
       +        }
       +        if(flushimage(i->display, 0) < 0)
       +                return -1;
       +        return ndata;
       +}
 (DIR) diff --git a/src/libdraw/mkfont.c b/src/libdraw/mkfont.c
       t@@ -0,0 +1,55 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +/*
       + * Cobble fake font using existing subfont
       + */
       +Font*
       +mkfont(Subfont *subfont, Rune min)
       +{
       +        Font *font;
       +        Cachefont *c;
       +
       +        font = malloc(sizeof(Font));
       +        if(font == 0)
       +                return 0;
       +        memset(font, 0, sizeof(Font));
       +        font->display = subfont->bits->display;
       +        font->name = strdup("<synthetic>");
       +        font->ncache = NFCACHE+NFLOOK;
       +        font->nsubf = NFSUBF;
       +        font->cache = malloc(font->ncache * sizeof(font->cache[0]));
       +        font->subf = malloc(font->nsubf * sizeof(font->subf[0]));
       +        if(font->name==0 || font->cache==0 || font->subf==0){
       +    Err:
       +                free(font->name);
       +                free(font->cache);
       +                free(font->subf);
       +                free(font->sub);
       +                free(font);
       +                return 0;
       +        }
       +        memset(font->cache, 0, font->ncache*sizeof(font->cache[0]));
       +        memset(font->subf, 0, font->nsubf*sizeof(font->subf[0]));
       +        font->height = subfont->height;
       +        font->ascent = subfont->ascent;
       +        font->age = 1;
       +        font->sub = malloc(sizeof(Cachefont*));
       +        if(font->sub == 0)
       +                goto Err;
       +        c = malloc(sizeof(Cachefont));
       +        if(c == 0)
       +                goto Err;
       +        font->nsub = 1;
       +        font->sub[0] = c;
       +        c->min = min;
       +        c->max = min+subfont->n-1;
       +        c->offset = 0;
       +        c->name = 0;        /* noticed by freeup() and agefont() */
       +        c->subfontname = 0;
       +        font->subf[0].age = 0;
       +        font->subf[0].cf = c;
       +        font->subf[0].f = subfont;
       +        return font;
       +}
 (DIR) diff --git a/src/libdraw/newwindow.c b/src/libdraw/newwindow.c
       t@@ -0,0 +1,27 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +/* Connect us to new window, if possible */
       +int
       +newwindow(char *str)
       +{
       +        int fd;
       +        char *wsys;
       +        char buf[256];
       +
       +        wsys = getenv("wsys");
       +        if(wsys == nil)
       +                return -1;
       +        fd = open(wsys, ORDWR);
       +        free(wsys);
       +        if(fd < 0)
       +                return -1;
       +        rfork(RFNAMEG);
       +        if(str)
       +                snprint(buf, sizeof buf, "new %s", str);
       +        else
       +                strcpy(buf, "new");
       +        return mount(fd, -1, "/dev", MBEFORE, buf);
       +}
       +
 (DIR) diff --git a/src/libdraw/poly.c b/src/libdraw/poly.c
       t@@ -0,0 +1,87 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +static
       +uchar*
       +addcoord(uchar *p, int oldx, int newx)
       +{
       +        int dx;
       +
       +        dx = newx-oldx;
       +        /* does dx fit in 7 signed bits? */
       +        if((unsigned)(dx - -0x40) <= 0x7F)
       +                *p++ = dx&0x7F;
       +        else{
       +                *p++ = 0x80 | (newx&0x7F);
       +                *p++ = newx>>7;
       +                *p++ = newx>>15;
       +        }
       +        return p;
       +}
       +
       +static
       +void
       +dopoly(int cmd, Image *dst, Point *pp, int np, int end0, int end1, int radius, Image *src, Point *sp, Drawop op)
       +{
       +        uchar *a, *t, *u;
       +        int i, ox, oy;
       +
       +        if(np == 0)
       +                return;
       +        t = malloc(np*2*3);
       +        if(t == nil)
       +                return;
       +        u = t;
       +        ox = oy = 0;
       +        for(i=0; i<np; i++){
       +                u = addcoord(u, ox, pp[i].x);
       +                ox = pp[i].x;
       +                u = addcoord(u, oy, pp[i].y);
       +                oy = pp[i].y;
       +        }
       +
       +        _setdrawop(dst->display, op);
       +
       +        a = bufimage(dst->display, 1+4+2+4+4+4+4+2*4+(u-t));
       +        if(a == 0){
       +                free(t);
       +                fprint(2, "image poly: %r\n");
       +                return;
       +        }
       +        a[0] = cmd;
       +        BPLONG(a+1, dst->id);
       +        BPSHORT(a+5, np-1);
       +        BPLONG(a+7, end0);
       +        BPLONG(a+11, end1);
       +        BPLONG(a+15, radius);
       +        BPLONG(a+19, src->id);
       +        BPLONG(a+23, sp->x);
       +        BPLONG(a+27, sp->y);
       +        memmove(a+31, t, u-t);
       +        free(t);
       +}
       +
       +void
       +poly(Image *dst, Point *p, int np, int end0, int end1, int radius, Image *src, Point sp)
       +{
       +        dopoly('p', dst, p, np, end0, end1, radius, src, &sp, SoverD);
       +}
       +
       +void
       +polyop(Image *dst, Point *p, int np, int end0, int end1, int radius, Image *src, Point sp, Drawop op)
       +{
       +        dopoly('p', dst, p, np, end0, end1, radius, src, &sp, op);
       +}
       +
       +void
       +fillpoly(Image *dst, Point *p, int np, int wind, Image *src, Point sp)
       +{
       +        dopoly('P', dst, p, np, wind, 0, 0, src, &sp, SoverD);
       +}
       +
       +void
       +fillpolyop(Image *dst, Point *p, int np, int wind, Image *src, Point sp, Drawop op)
       +{
       +        dopoly('P', dst, p, np, wind, 0, 0, src, &sp, op);
       +}
 (DIR) diff --git a/src/libdraw/rectclip.c b/src/libdraw/rectclip.c
       t@@ -0,0 +1,25 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +int
       +rectclip(Rectangle *rp, Rectangle b)                /* first by reference, second by value */
       +{
       +        Rectangle *bp = &b;
       +        /*
       +         * Expand rectXrect() in line for speed
       +         */
       +        if((rp->min.x<bp->max.x && bp->min.x<rp->max.x &&
       +            rp->min.y<bp->max.y && bp->min.y<rp->max.y)==0)
       +                return 0;
       +        /* They must overlap */
       +        if(rp->min.x < bp->min.x)
       +                rp->min.x = bp->min.x;
       +        if(rp->min.y < bp->min.y)
       +                rp->min.y = bp->min.y;
       +        if(rp->max.x > bp->max.x)
       +                rp->max.x = bp->max.x;
       +        if(rp->max.y > bp->max.y)
       +                rp->max.y = bp->max.y;
       +        return 1;
       +}
 (DIR) diff --git a/src/libdraw/replclipr.c b/src/libdraw/replclipr.c
       t@@ -0,0 +1,21 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +void
       +replclipr(Image *i, int repl, Rectangle clipr)
       +{
       +        uchar *b;
       +
       +        b = bufimage(i->display, 22);
       +        b[0] = 'c';
       +        BPLONG(b+1, i->id);
       +        repl = repl!=0;
       +        b[5] = repl;
       +        BPLONG(b+6, clipr.min.x);
       +        BPLONG(b+10, clipr.min.y);
       +        BPLONG(b+14, clipr.max.x);
       +        BPLONG(b+18, clipr.max.y);
       +        i->repl = repl;
       +        i->clipr = clipr;
       +}
 (DIR) diff --git a/src/libdraw/rgb.c b/src/libdraw/rgb.c
       t@@ -0,0 +1,99 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +/*
       + * This original version, although fast and a true inverse of
       + * cmap2rgb, in the sense that rgb2cmap(cmap2rgb(c))
       + * returned the original color, does a terrible job for RGB
       + * triples that do not appear in the color map, so it has been
       + * replaced by the much slower version below, that loops
       + * over the color map looking for the nearest point in RGB
       + * space.  There is no visual psychology reason for that
       + * criterion, but it's easy to implement and the results are
       + * far more pleasing. 
       + *
       +int
       +rgb2cmap(int cr, int cg, int cb)
       +{
       +        int r, g, b, v, cv;
       +
       +        if(cr < 0)
       +                cr = 0;
       +        else if(cr > 255)
       +                cr = 255;
       +        if(cg < 0)
       +                cg = 0;
       +        else if(cg > 255)
       +                cg = 255;
       +        if(cb < 0)
       +                cb = 0;
       +        else if(cb > 255)
       +                cb = 255;
       +        r = cr>>6;
       +        g = cg>>6;
       +        b = cb>>6;
       +        cv = cr;
       +        if(cg > cv)
       +                cv = cg;
       +        if(cb > cv)
       +                cv = cb;
       +        v = (cv>>4)&3;
       +        return ((((r<<2)+v)<<4)+(((g<<2)+b+v-r)&15));
       +}
       +*/
       +
       +int
       +rgb2cmap(int cr, int cg, int cb)
       +{
       +        int i, r, g, b, sq;
       +        u32int rgb;
       +        int best, bestsq;
       +
       +        best = 0;
       +        bestsq = 0x7FFFFFFF;
       +        for(i=0; i<256; i++){
       +                rgb = cmap2rgb(i);
       +                r = (rgb>>16) & 0xFF;
       +                g = (rgb>>8) & 0xFF;
       +                b = (rgb>>0) & 0xFF;
       +                sq = (r-cr)*(r-cr)+(g-cg)*(g-cg)+(b-cb)*(b-cb);
       +                if(sq < bestsq){
       +                        bestsq = sq;
       +                        best = i;
       +                }
       +        }
       +        return best;
       +}
       +
       +int
       +cmap2rgb(int c)
       +{
       +        int j, num, den, r, g, b, v, rgb;
       +
       +        r = c>>6;
       +        v = (c>>4)&3;
       +        j = (c-v+r)&15;
       +        g = j>>2;
       +        b = j&3;
       +        den=r;
       +        if(g>den)
       +                den=g;
       +        if(b>den)
       +                den=b;
       +        if(den==0) {
       +                v *= 17;
       +                rgb = (v<<16)|(v<<8)|v;
       +        }
       +        else{
       +                num=17*(4*den+v);
       +                rgb = ((r*num/den)<<16)|((g*num/den)<<8)|(b*num/den);
       +        }
       +        return rgb;
       +}
       +
       +int
       +cmap2rgba(int c)
       +{
       +        return (cmap2rgb(c)<<8)|0xFF;
       +}
 (DIR) diff --git a/src/libdraw/stringbg.c b/src/libdraw/stringbg.c
       t@@ -0,0 +1,51 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +Point
       +stringbg(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Image *bg, Point bgp)
       +{
       +        return _string(dst, pt, src, sp, f, s, nil, 1<<24, dst->clipr, bg, bgp, SoverD);
       +}
       +
       +Point
       +stringbgop(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Image *bg, Point bgp, Drawop op)
       +{
       +        return _string(dst, pt, src, sp, f, s, nil, 1<<24, dst->clipr, bg, bgp, op);
       +}
       +
       +Point
       +stringnbg(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, int len, Image *bg, Point bgp)
       +{
       +        return _string(dst, pt, src, sp, f, s, nil, len, dst->clipr, bg, bgp, SoverD);
       +}
       +
       +Point
       +stringnbgop(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, int len, Image *bg, Point bgp, Drawop op)
       +{
       +        return _string(dst, pt, src, sp, f, s, nil, len, dst->clipr, bg, bgp, op);
       +}
       +
       +Point
       +runestringbg(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, Image *bg, Point bgp)
       +{
       +        return _string(dst, pt, src, sp, f, nil, r, 1<<24, dst->clipr, bg, bgp, SoverD);
       +}
       +
       +Point
       +runestringbgop(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, Image *bg, Point bgp, Drawop op)
       +{
       +        return _string(dst, pt, src, sp, f, nil, r, 1<<24, dst->clipr, bg, bgp, op);
       +}
       +
       +Point
       +runestringnbg(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, int len, Image *bg, Point bgp)
       +{
       +        return _string(dst, pt, src, sp, f, nil, r, len, dst->clipr, bg, bgp, SoverD);
       +}
       +
       +Point
       +runestringnbgop(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, int len, Image *bg, Point bgp, Drawop op)
       +{
       +        return _string(dst, pt, src, sp, f, nil, r, len, dst->clipr, bg, bgp, op);
       +}
 (DIR) diff --git a/src/libdraw/stringsubfont.c b/src/libdraw/stringsubfont.c
       t@@ -0,0 +1,65 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +Point
       +stringsubfont(Image *b, Point p, Image *color, Subfont *f, char *cs)
       +{
       +        int w, width;
       +        uchar *s;
       +        Rune c;
       +        Fontchar *i;
       +
       +        s = (uchar*)cs;
       +        for(; c=*s; p.x+=width){
       +                width = 0;
       +                if(c < Runeself)
       +                        s++;
       +                else{
       +                        w = chartorune(&c, (char*)s);
       +                        if(w == 0){
       +                                s++;
       +                                continue;
       +                        }
       +                        s += w;
       +                }
       +                if(c >= f->n)
       +                        continue;
       +                i = f->info+c;
       +                width = i->width;
       +                draw(b, Rect(p.x+i->left, p.y+i->top, p.x+i->left+(i[1].x-i[0].x), p.y+i->bottom),
       +                        color, f->bits, Pt(i->x, i->top));
       +        }
       +        return p;
       +}
       +
       +Point
       +strsubfontwidth(Subfont *f, char *cs)
       +{
       +        Rune c;
       +        Point p;
       +        uchar *s;
       +        Fontchar *i;
       +        int w, width;
       +
       +        p = Pt(0, f->height);
       +        s = (uchar*)cs;
       +        for(; c=*s; p.x+=width){
       +                width = 0;
       +                if(c < Runeself)
       +                        s++;
       +                else{
       +                        w = chartorune(&c, (char*)s);
       +                        if(w == 0){
       +                                s++;
       +                                continue;
       +                        }
       +                        s += w;
       +                }
       +                if(c >= f->n)
       +                        continue;
       +                i = f->info+c;
       +                width = i->width;
       +        }
       +        return p;
       +}
 (DIR) diff --git a/src/libdraw/test.c b/src/libdraw/test.c
       t@@ -0,0 +1,44 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +#include <event.h>
       +
       +void
       +eresized(int new)
       +{
       +        if(new && getwindow(display, Refnone) < 0){
       +                fprint(2, "colors: can't reattach to window: %r\n");
       +                exits("resized");
       +        }
       +        draw(screen, screen->r, display->white, nil, ZP);
       +        flushimage(display, 1);
       +}
       +
       +char *buttons[] =
       +{
       +        "exit",
       +        0
       +};
       +
       +Menu menu =
       +{
       +        buttons
       +};
       +
       +void
       +main(int argc, char *argv[])
       +{
       +        Mouse m;
       +
       +        initdraw(0,0,0);
       +        eresized(0);
       +        einit(Emouse);
       +        for(;;){
       +                m = emouse();
       +                if(m.buttons == 4)
       +                        switch(emenuhit(3, &m, &menu)){
       +                        case 0:
       +                                exits(0);
       +                        }
       +        }
       +}
 (DIR) diff --git a/src/libdraw/window.c b/src/libdraw/window.c
       t@@ -0,0 +1,214 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +typedef struct Memimage Memimage;
       +
       +static int        screenid;
       +
       +Screen*
       +allocscreen(Image *image, Image *fill, int public)
       +{
       +        uchar *a;
       +        Screen *s;
       +        int id, try;
       +        Display *d;
       +
       +        d = image->display;
       +        if(d != fill->display){
       +                werrstr("allocscreen: image and fill on different displays");
       +                return 0;
       +        }
       +        s = malloc(sizeof(Screen));
       +        if(s == 0)
       +                return 0;
       +        SET(id);
       +        for(try=0; try<25; try++){
       +                /* loop until find a free id */
       +                a = bufimage(d, 1+4+4+4+1);
       +                if(a == 0){
       +                        free(s);
       +                        return 0;
       +                }
       +                id = ++screenid;
       +                a[0] = 'A';
       +                BPLONG(a+1, id);
       +                BPLONG(a+5, image->id);
       +                BPLONG(a+9, fill->id);
       +                a[13] = public;
       +                if(flushimage(d, 0) != -1)
       +                        break;
       +        }
       +        s->display = d;
       +        s->id = id;
       +        s->image = image;
       +        assert(s->image && s->image->chan != 0);
       +
       +        s->fill = fill;
       +        return s;
       +}
       +
       +Screen*
       +publicscreen(Display *d, int id, u32int chan)
       +{
       +        uchar *a;
       +        Screen *s;
       +
       +        s = malloc(sizeof(Screen));
       +        if(s == 0)
       +                return 0;
       +        a = bufimage(d, 1+4+4);
       +        if(a == 0){
       +    Error:
       +                free(s);
       +                return 0;
       +        }
       +        a[0] = 'S';
       +        BPLONG(a+1, id);
       +        BPLONG(a+5, chan);
       +        if(flushimage(d, 0) < 0)
       +                goto Error;
       +
       +        s->display = d;
       +        s->id = id;
       +        s->image = 0;
       +        s->fill = 0;
       +        return s;
       +}
       +
       +int
       +freescreen(Screen *s)
       +{
       +        uchar *a;
       +        Display *d;
       +
       +        if(s == 0)
       +                return 0;
       +        d = s->display;
       +        a = bufimage(d, 1+4);
       +        if(a == 0)
       +                return -1;
       +        a[0] = 'F';
       +        BPLONG(a+1, s->id);
       +        /*
       +         * flush(1) because screen is likely holding last reference to
       +         * window, and want it to disappear visually.
       +         */
       +        if(flushimage(d, 1) < 0)
       +                return -1;
       +        free(s);
       +        return 1;
       +}
       +
       +Image*
       +allocwindow(Screen *s, Rectangle r, int ref, u32int val)
       +{
       +        return _allocwindow(nil, s, r, ref, val);
       +}
       +
       +Image*
       +_allocwindow(Image *i, Screen *s, Rectangle r, int ref, u32int val)
       +{
       +        Display *d;
       +
       +        d = s->display;
       +        i = _allocimage(i, d, r, d->screenimage->chan, 0, val, s->id, ref);
       +        if(i == 0)
       +                return 0;
       +        i->screen = s;
       +        i->next = s->display->windows;
       +        s->display->windows = i;
       +        return i;
       +}
       +
       +static
       +void
       +topbottom(Image **w, int n, int top)
       +{
       +        int i;
       +        uchar *b;
       +        Display *d;
       +
       +        if(n < 0){
       +    Ridiculous:
       +                fprint(2, "top/bottom: ridiculous number of windows\n");
       +                return;
       +        }
       +        if(n == 0)
       +                return;
       +        if(n > (w[0]->display->bufsize-100)/4)
       +                goto Ridiculous;
       +        /*
       +         * this used to check that all images were on the same screen.
       +         * we don't know the screen associated with images we acquired
       +         * by name.  instead, check that all images are on the same display.
       +         * the display will check that they are all on the same screen.
       +         */
       +        d = w[0]->display;
       +        for(i=1; i<n; i++)
       +                if(w[i]->display != d){
       +                        fprint(2, "top/bottom: windows not on same screen\n");
       +                        return;
       +                }
       +
       +        if(n==0)
       +                return;
       +        b = bufimage(d, 1+1+2+4*n);
       +        b[0] = 't';
       +        b[1] = top;
       +        BPSHORT(b+2, n);
       +        for(i=0; i<n; i++)
       +                BPLONG(b+4+4*i, w[i]->id);
       +}
       +
       +void
       +bottomwindow(Image *w)
       +{
       +        if(w->screen == 0)
       +                return;
       +        topbottom(&w, 1, 0);
       +}
       +
       +void
       +topwindow(Image *w)
       +{
       +        if(w->screen == 0)
       +                return;
       +        topbottom(&w, 1, 1);
       +}
       +
       +void
       +bottomnwindows(Image **w, int n)
       +{
       +        topbottom(w, n, 0);
       +}
       +
       +void
       +topnwindows(Image **w, int n)
       +{
       +        topbottom(w, n, 1);
       +}
       +
       +int
       +originwindow(Image *w, Point log, Point scr)
       +{
       +        uchar *b;
       +        Point delta;
       +
       +        flushimage(w->display, 0);
       +        b = bufimage(w->display, 1+4+2*4+2*4);
       +        if(b == nil)
       +                return 0;
       +        b[0] = 'o';
       +        BPLONG(b+1, w->id);
       +        BPLONG(b+5, log.x);
       +        BPLONG(b+9, log.y);
       +        BPLONG(b+13, scr.x);
       +        BPLONG(b+17, scr.y);
       +        if(flushimage(w->display, 1) < 0)
       +                return -1;
       +        delta = subpt(log, w->r.min);
       +        w->r = rectaddpt(w->r, delta);
       +        w->clipr = rectaddpt(w->clipr, delta);
       +        return 1;
       +}
 (DIR) diff --git a/src/libdraw/writeimage.c b/src/libdraw/writeimage.c
       t@@ -0,0 +1,185 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +#define        HSHIFT        3        /* HSHIFT==5 runs slightly faster, but hash table is 64x bigger */
       +#define        NHASH        (1<<(HSHIFT*NMATCH))
       +#define        HMASK        (NHASH-1)
       +#define        hupdate(h, c)        ((((h)<<HSHIFT)^(c))&HMASK)
       +typedef struct Hlist Hlist;
       +struct Hlist{
       +        uchar *s;
       +        Hlist *next, *prev;
       +};
       +
       +int
       +writeimage(int fd, Image *i, int dolock)
       +{
       +        uchar *outbuf, *outp, *eout;                /* encoded data, pointer, end */
       +        uchar *loutp;                                /* start of encoded line */
       +        Hlist *hash;                                /* heads of hash chains of past strings */
       +        Hlist *chain, *hp;                        /* hash chain members, pointer */
       +        Hlist *cp;                                /* next Hlist to fall out of window */
       +        int h;                                        /* hash value */
       +        uchar *line, *eline;                        /* input line, end pointer */
       +        uchar *data, *edata;                        /* input buffer, end pointer */
       +        ulong n;                                /* length of input buffer */
       +        ulong nb;                                /* # of bytes returned by unloadimage */
       +        int bpl;                                /* input line length */
       +        int offs, runlen;                        /* offset, length of consumed data */
       +        uchar dumpbuf[NDUMP];                        /* dump accumulator */
       +        int ndump;                                /* length of dump accumulator */
       +        int miny, dy;                                /* y values while unloading input */
       +        int chunk, ncblock;
       +        Rectangle r;
       +        uchar *p, *q, *s, *es, *t;
       +        char hdr[11+5*12+1];
       +        char cbuf[20];
       +
       +        chunk = i->display->bufsize - 32;        /* a little room for header */
       +        r = i->r;
       +        bpl = bytesperline(r, i->depth);
       +        n = Dy(r)*bpl;
       +        data = malloc(n);
       +        ncblock = _compblocksize(r, i->depth);
       +        outbuf = malloc(ncblock);
       +        hash = malloc(NHASH*sizeof(Hlist));
       +        chain = malloc(NMEM*sizeof(Hlist));
       +        if(data == 0 || outbuf == 0 || hash == 0 || chain == 0){
       +        ErrOut:
       +                free(data);
       +                free(outbuf);
       +                free(hash);
       +                free(chain);
       +                return -1;
       +        }
       +        for(miny = r.min.y; miny != r.max.y; miny += dy){
       +                dy = r.max.y-miny;
       +                if(dy*bpl > chunk)
       +                        dy = chunk/bpl;
       +                if(dolock)
       +                        lockdisplay(i->display);
       +                nb = unloadimage(i, Rect(r.min.x, miny, r.max.x, miny+dy),
       +                        data+(miny-r.min.y)*bpl, dy*bpl);
       +                if(dolock)
       +                        unlockdisplay(i->display);
       +                if(nb != dy*bpl)
       +                        goto ErrOut;
       +        }
       +        sprint(hdr, "compressed\n%11s %11d %11d %11d %11d ",
       +                chantostr(cbuf, i->chan), r.min.x, r.min.y, r.max.x, r.max.y);
       +        if(write(fd, hdr, 11+5*12) != 11+5*12)
       +                goto ErrOut;
       +        edata = data+n;
       +        eout = outbuf+ncblock;
       +        line = data;
       +        r.max.y = r.min.y;
       +        while(line != edata){
       +                memset(hash, 0, NHASH*sizeof(Hlist));
       +                memset(chain, 0, NMEM*sizeof(Hlist));
       +                cp = chain;
       +                h = 0;
       +                outp = outbuf;
       +                for(n = 0; n != NMATCH; n++)
       +                        h = hupdate(h, line[n]);
       +                loutp = outbuf;
       +                while(line != edata){
       +                        ndump = 0;
       +                        eline = line+bpl;
       +                        for(p = line; p != eline; ){
       +                                if(eline-p < NRUN)
       +                                        es = eline;
       +                                else
       +                                        es = p+NRUN;
       +                                q = 0;
       +                                runlen = 0;
       +                                for(hp = hash[h].next; hp; hp = hp->next){
       +                                        s = p + runlen;
       +                                        if(s >= es)
       +                                                continue;
       +                                        t = hp->s + runlen;
       +                                        for(; s >= p; s--)
       +                                                if(*s != *t--)
       +                                                        goto matchloop;
       +                                        t += runlen+2;
       +                                        s += runlen+2;
       +                                        for(; s < es; s++)
       +                                                if(*s != *t++)
       +                                                        break;
       +                                        n = s-p;
       +                                        if(n > runlen){
       +                                                runlen = n;
       +                                                q = hp->s;
       +                                                if(n == NRUN)
       +                                                        break;
       +                                        }
       +                        matchloop: ;
       +                                }
       +                                if(runlen < NMATCH){
       +                                        if(ndump == NDUMP){
       +                                                if(eout-outp < ndump+1)
       +                                                        goto Bfull;
       +                                                *outp++ = ndump-1+128;
       +                                                memmove(outp, dumpbuf, ndump);
       +                                                outp += ndump;
       +                                                ndump = 0;
       +                                        }
       +                                        dumpbuf[ndump++] = *p;
       +                                        runlen = 1;
       +                                }
       +                                else{
       +                                        if(ndump != 0){
       +                                                if(eout-outp < ndump+1)
       +                                                        goto Bfull;
       +                                                *outp++ = ndump-1+128;
       +                                                memmove(outp, dumpbuf, ndump);
       +                                                outp += ndump;
       +                                                ndump = 0;
       +                                        }
       +                                        offs = p-q-1;
       +                                        if(eout-outp < 2)
       +                                                goto Bfull;
       +                                        *outp++ = ((runlen-NMATCH)<<2) + (offs>>8);
       +                                        *outp++ = offs&255;
       +                                }
       +                                for(q = p+runlen; p != q; p++){
       +                                        if(cp->prev)
       +                                                cp->prev->next = 0;
       +                                        cp->next = hash[h].next;
       +                                        cp->prev = &hash[h];
       +                                        if(cp->next)
       +                                                cp->next->prev = cp;
       +                                        cp->prev->next = cp;
       +                                        cp->s = p;
       +                                        if(++cp == &chain[NMEM])
       +                                                cp = chain;
       +                                        if(edata-p > NMATCH)
       +                                                h = hupdate(h, p[NMATCH]);
       +                                }
       +                        }
       +                        if(ndump != 0){
       +                                if(eout-outp < ndump+1)
       +                                        goto Bfull;
       +                                *outp++ = ndump-1+128;
       +                                memmove(outp, dumpbuf, ndump);
       +                                outp += ndump;
       +                        }
       +                        line = eline;
       +                        loutp = outp;
       +                        r.max.y++;
       +                }
       +        Bfull:
       +                if(loutp == outbuf)
       +                        goto ErrOut;
       +                n = loutp-outbuf;
       +                sprint(hdr, "%11d %11ld ", r.max.y, n);
       +                write(fd, hdr, 2*12);
       +                write(fd, outbuf, n);
       +                r.min.y = r.max.y;
       +        }
       +        free(data);
       +        free(outbuf);
       +        free(hash);
       +        free(chain);
       +        return 0;
       +}
 (DIR) diff --git a/src/libdraw/writesubfont.c b/src/libdraw/writesubfont.c
       t@@ -0,0 +1,45 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +static
       +void
       +packinfo(Fontchar *fc, uchar *p, int n)
       +{
       +        int j;
       +
       +        for(j=0;  j<=n;  j++){
       +                p[0] = fc->x;
       +                p[1] = fc->x>>8;
       +                p[2] = fc->top;
       +                p[3] = fc->bottom;
       +                p[4] = fc->left;
       +                p[5] = fc->width;
       +                fc++;
       +                p += 6;
       +        }
       +}
       +
       +int
       +writesubfont(int fd, Subfont *f)
       +{
       +        char hdr[3*12+1];
       +        uchar *data;
       +        int nb;
       +
       +        sprint(hdr, "%11d %11d %11d ", f->n, f->height, f->ascent);
       +        if(write(fd, hdr, 3*12) != 3*12){
       +   Err:
       +                werrstr("writesubfont: bad write: %r");
       +                return -1;
       +        }
       +        nb = 6*(f->n+1);
       +        data = malloc(nb);
       +        if(data == nil)
       +                return -1;
       +        packinfo(f->info, data, f->n);
       +        if(write(fd, data, nb) != nb)
       +                goto Err;
       +        free(data);
       +        return 0;
       +}