tnew - 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 257fb6261eba6026e127e1a42e06b8b2d9c3b722
 (DIR) parent 74dc60da74c62e07f0d63179da9724d705794a6d
 (HTM) Author: rsc <devnull@localhost>
       Date:   Sun, 25 Jun 2006 19:00:14 +0000
       
       new
       
       Diffstat:
         A src/libdraw/drawclient.c            |     336 +++++++++++++++++++++++++++++++
         A src/libdraw/drawfcall.c             |     367 ++++++++++++++++++++++++++++++
         A src/libdraw/snarf.c                 |      15 +++++++++++++++
         A src/libdraw/wsys.c                  |      24 ++++++++++++++++++++++++
       
       4 files changed, 742 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/src/libdraw/drawclient.c b/src/libdraw/drawclient.c
       t@@ -0,0 +1,336 @@
       +/* Copyright (c) 2006 Russ Cox */
       +
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +#include <mouse.h>
       +#include <cursor.h>
       +#include <drawfcall.h>
       +#include <mux.h>
       +
       +int chattydrawclient;
       +
       +static int        drawgettag(Mux *mux, void *vmsg);
       +static void*        drawrecv(Mux *mux);
       +static int        drawsend(Mux *mux, void *vmsg);
       +static int        drawsettag(Mux *mux, void *vmsg, uint tag);
       +
       +int
       +_displayconnect(Display *d)
       +{
       +        int pid, p[2];
       +        
       +        fmtinstall('W', drawfcallfmt);
       +        fmtinstall('H', encodefmt);
       +        
       +        if(pipe(p) < 0)
       +                return -1;
       +        if((pid=fork()) < 0){
       +                close(p[0]);
       +                close(p[1]);
       +                return -1;
       +        }
       +        if(pid == 0){
       +                close(p[0]);
       +                dup(p[1], 0);
       +                dup(p[1], 1);
       +                /* execl("strace", "strace", "-o", "drawsrv.out", "drawsrv", nil); */
       +                execl("drawsrv", "drawsrv", nil);
       +                sysfatal("exec drawsrv: %r");
       +        }
       +        close(p[1]);
       +        d->srvfd = p[0];
       +        return 0;
       +}
       +
       +int
       +_displaymux(Display *d)
       +{
       +        if((d->mux = mallocz(sizeof(*d->mux), 1)) == nil)
       +                return -1;
       +
       +        d->mux->mintag = 1;
       +        d->mux->maxtag = 255;
       +        d->mux->send = drawsend;
       +        d->mux->recv = drawrecv;
       +        d->mux->gettag = drawgettag;
       +        d->mux->settag = drawsettag;
       +        d->mux->aux = d;
       +        muxinit(d->mux);
       +        
       +        return 0;
       +}
       +
       +#define GET(p, x) \
       +        ((x) = (((p)[0] << 24) | ((p)[1] << 16) | ((p)[2] << 8) | ((p)[3])))
       +
       +static int
       +drawsend(Mux *mux, void *vmsg)
       +{
       +        int n;
       +        uchar *msg;
       +        Display *d;
       +        
       +        msg = vmsg;
       +        GET(msg, n);
       +        d = mux->aux;
       +        return write(d->srvfd, msg, n);
       +}
       +
       +static void*
       +drawrecv(Mux *mux)
       +{
       +        int n;
       +        uchar buf[4], *p;
       +        Display *d;
       +        
       +        d = mux->aux;
       +        if((n=readn(d->srvfd, buf, 4)) != 4){
       +fprint(2, "readn 4 got %d: %r\n", n);
       +                return nil;
       +        }
       +        GET(buf, n);
       +        p = malloc(n);
       +        if(p == nil){
       +                fprint(2, "out of memory allocating %d in drawrecv\n", n);
       +                return nil;
       +        }
       +        memmove(p, buf, 4);
       +        if(readn(d->srvfd, p+4, n-4) != n-4){
       +fprint(2, "short readn\n");
       +                return nil;
       +        }
       +        return p;
       +}
       +
       +static int
       +drawgettag(Mux *mux, void *vmsg)
       +{
       +        USED(mux);
       +        uchar *msg;
       +        
       +        msg = vmsg;
       +        return msg[4];
       +}
       +
       +static int
       +drawsettag(Mux *mux, void *vmsg, uint tag)
       +{
       +        USED(mux);
       +        uchar *msg;
       +        
       +        msg = vmsg;
       +        msg[4] = tag;
       +        return 0;
       +}
       +
       +static int
       +displayrpc(Display *d, Wsysmsg *tx, Wsysmsg *rx, void **freep)
       +{
       +        int n, nn;
       +        void *tpkt, *rpkt;
       +        
       +        n = sizeW2M(tx);
       +        tpkt = malloc(n);
       +        if(freep)
       +                *freep = nil;
       +        if(tpkt == nil)
       +                return -1;
       +        tx->tag = 0;
       +        if(chattydrawclient)
       +                fprint(2, "<- %W\n", tx);
       +        nn = convW2M(tx, tpkt, n);
       +        if(nn != n){
       +                free(tpkt);
       +                werrstr("drawclient: sizeW2M convW2M mismatch");
       +                fprint(2, "%r\n");
       +                return -1;
       +        }
       +        rpkt = muxrpc(d->mux, tpkt);
       +        free(tpkt);
       +        if(rpkt == nil){
       +                werrstr("muxrpc: %r");
       +                return -1;
       +        }
       +        GET((uchar*)rpkt, n);
       +        nn = convM2W(rpkt, n, rx);
       +        if(nn != n){
       +                free(rpkt);
       +                werrstr("drawclient: convM2W packet size mismatch %d %d %.*H", n, nn, n, rpkt);
       +                fprint(2, "%r\n");
       +                return -1;
       +        }
       +        if(chattydrawclient)
       +                fprint(2, "-> %W\n", rx);
       +        if(rx->type == Rerror){
       +                werrstr("%s", rx->error);
       +                free(rpkt);
       +                return -1;
       +        }
       +        if(rx->type != tx->type+1){
       +                werrstr("packet type mismatch -- tx %d rx %d",
       +                        tx->type, rx->type);
       +                free(rpkt);
       +                return -1;
       +        }
       +        if(freep)
       +                *freep = rpkt;
       +        else
       +                free(rpkt);
       +        return 0;
       +}
       +
       +int
       +_displayinit(Display *d, char *label, char *winsize)
       +{
       +        Wsysmsg tx, rx;
       +
       +        tx.type = Tinit;
       +        tx.label = "";
       +        tx.winsize = "";
       +        return displayrpc(d, &tx, &rx, nil);
       +}
       +
       +int
       +_displayrdmouse(Display *d, Mouse *m, int *resized)
       +{
       +        Wsysmsg tx, rx;
       +
       +        tx.type = Trdmouse;
       +        if(displayrpc(d, &tx, &rx, nil) < 0)
       +                return -1;
       +        *m = rx.mouse;
       +        *resized = rx.resized;
       +        return 0;
       +}
       +
       +int
       +_displayrdkbd(Display *d, Rune *r)
       +{
       +        Wsysmsg tx, rx;
       +
       +        tx.type = Trdkbd;
       +        if(displayrpc(d, &tx, &rx, nil) < 0)
       +                return -1;
       +        *r = rx.rune;
       +        return 0;
       +}
       +
       +int
       +_displaymoveto(Display *d, Point p)
       +{
       +        Wsysmsg tx, rx;
       +
       +        tx.type = Tmoveto;
       +        tx.mouse.xy = p;
       +        return displayrpc(d, &tx, &rx, nil);
       +}
       +
       +int
       +_displaycursor(Display *d, Cursor *c)
       +{
       +        Wsysmsg tx, rx;
       +        
       +        tx.type = Tcursor;
       +        if(c == nil){
       +                memset(&tx.cursor, 0, sizeof tx.cursor);
       +                tx.arrowcursor = 1;
       +        }else{
       +                tx.arrowcursor = 0;
       +                tx.cursor = *c;
       +        }
       +        return displayrpc(d, &tx, &rx, nil);
       +}
       +
       +int
       +_displaybouncemouse(Display *d, Mouse *m)
       +{
       +        Wsysmsg tx, rx;
       +        
       +        tx.type = Tbouncemouse;
       +        tx.mouse = *m;
       +        return displayrpc(d, &tx, &rx, nil);
       +}
       +
       +int
       +_displaylabel(Display *d, char *label)
       +{
       +        Wsysmsg tx, rx;
       +        
       +        tx.type = Tlabel;
       +        tx.label = label;
       +        return displayrpc(d, &tx, &rx, nil);
       +}
       +
       +char*
       +_displayrdsnarf(Display *d)
       +{
       +        void *p;
       +        char *s;
       +        Wsysmsg tx, rx;
       +        
       +        tx.type = Trdsnarf;
       +        if(displayrpc(d, &tx, &rx, &p) < 0)
       +                return nil;
       +        s = strdup(rx.snarf);
       +        free(p);
       +        return s;
       +}
       +
       +int
       +_displaywrsnarf(Display *d, char *snarf)
       +{
       +        Wsysmsg tx, rx;
       +        
       +        tx.type = Twrsnarf;
       +        tx.snarf = snarf;
       +        return displayrpc(d, &tx, &rx, nil);
       +}
       +
       +int
       +_displayrddraw(Display *d, void *v, int n)
       +{
       +        void *p;
       +        Wsysmsg tx, rx;
       +        
       +        tx.type = Trddraw;
       +        tx.count = n;
       +        if(displayrpc(d, &tx, &rx, &p) < 0)
       +                return -1;
       +        memmove(v, rx.data, rx.count);
       +        free(p);
       +        return rx.count;
       +}
       +
       +int
       +_displaywrdraw(Display *d, void *v, int n)
       +{
       +        Wsysmsg tx, rx;
       +        
       +        tx.type = Twrdraw;
       +        tx.count = n;
       +        tx.data = v;
       +        if(displayrpc(d, &tx, &rx, nil) < 0)
       +                return -1;
       +        return rx.count;
       +}
       +
       +int
       +_displaytop(Display *d)
       +{
       +        Wsysmsg tx, rx;
       +
       +        tx.type = Ttop;
       +        return displayrpc(d, &tx, &rx, nil);
       +}
       +
       +int
       +_displayresize(Display *d, Rectangle r)
       +{
       +        Wsysmsg tx, rx;
       +        
       +        tx.type = Tresize;
       +        tx.rect = r;
       +        return displayrpc(d, &tx, &rx, nil);
       +}
       +
 (DIR) diff --git a/src/libdraw/drawfcall.c b/src/libdraw/drawfcall.c
       t@@ -0,0 +1,367 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +#include <mouse.h>
       +#include <cursor.h>
       +#include <drawfcall.h>
       +
       +#define PUT(p, x) \
       +        (p)[0] = ((x) >> 24)&0xFF, \
       +        (p)[1] = ((x) >> 16)&0xFF, \
       +        (p)[2] = ((x) >> 8)&0xFF, \
       +        (p)[3] = (x)&0xFF
       +
       +#define GET(p, x) \
       +        ((x) = (((p)[0] << 24) | ((p)[1] << 16) | ((p)[2] << 8) | ((p)[3])))
       +
       +#define PUT2(p, x) \
       +        (p)[0] = ((x) >> 8)&0xFF, \
       +        (p)[1] = (x)&0xFF
       +
       +#define GET2(p, x) \
       +        ((x) = (((p)[0] << 8) | ((p)[1])))
       +
       +static int
       +_stringsize(char *s)
       +{
       +        return 4+strlen(s);
       +}
       +
       +static int
       +PUTSTRING(uchar *p, char *s)
       +{
       +        int n;
       +        
       +        if(s == nil)
       +                s = "";
       +        n = strlen(s);
       +        PUT(p, n);
       +        memmove(p+4, s, n);
       +        return n+4;
       +}
       +
       +static int
       +GETSTRING(uchar *p, char **s)
       +{
       +        int n;
       +        
       +        GET(p, n);
       +        memmove(p, p+4, n);
       +        *s = (char*)p;
       +        p[n] = 0;
       +        return n+4;
       +}
       +        
       +uint
       +sizeW2M(Wsysmsg *m)
       +{
       +        switch(m->type){
       +        default:
       +                return 0;
       +        case Trdmouse:
       +        case Rbouncemouse:
       +        case Rmoveto:
       +        case Rcursor:
       +        case Trdkbd:
       +        case Rlabel:
       +        case Rinit:
       +        case Trdsnarf:
       +        case Rwrsnarf:
       +        case Ttop:
       +        case Rtop:
       +        case Rresize:
       +                return 4+1+1;
       +        case Rrdmouse:
       +                return 4+1+1+4+4+4+4+1;
       +        case Tbouncemouse:
       +                return 4+1+1+4+4+4;
       +        case Tmoveto:
       +                return 4+1+1+4+4;
       +        case Tcursor:
       +                return 4+1+1+4+4+2*16+2*16+1;
       +        case Rerror:
       +                return 4+1+1+_stringsize(m->error);
       +        case Rrdkbd:
       +                return 4+1+1+2;
       +        case Tlabel:
       +                return 4+1+1+_stringsize(m->label);
       +        case Tinit:
       +                return 4+1+1
       +                        +_stringsize(m->winsize)
       +                        +_stringsize(m->label);
       +        case Rrdsnarf:
       +        case Twrsnarf:
       +                return 4+1+1+_stringsize(m->snarf);
       +        case Rrddraw:
       +        case Twrdraw:
       +                return 4+1+1+4+m->count;
       +        case Trddraw:
       +        case Rwrdraw:
       +                return 4+1+1+4;
       +        case Tresize:
       +                return 4+1+1+4*4;
       +        }
       +}
       +
       +uint
       +convW2M(Wsysmsg *m, uchar *p, uint n)
       +{
       +        int nn;
       +        
       +        nn = sizeW2M(m);
       +        if(n < nn || nn == 0 || n < 6)
       +                return 0;
       +        PUT(p, nn);
       +        p[4] = m->tag;
       +        p[5] = m->type;
       +
       +        switch(m->type){
       +        default:
       +                return 0;
       +        case Trdmouse:
       +        case Rbouncemouse:
       +        case Rmoveto:
       +        case Rcursor:
       +        case Trdkbd:
       +        case Rlabel:
       +        case Rinit:
       +        case Trdsnarf:
       +        case Rwrsnarf:
       +        case Ttop:
       +        case Rtop:
       +        case Rresize:
       +                break;
       +        case Rerror:
       +                PUTSTRING(p+6, m->error);
       +                break;
       +        case Rrdmouse:
       +                PUT(p+6, m->mouse.xy.x);
       +                PUT(p+10, m->mouse.xy.y);
       +                PUT(p+14, m->mouse.buttons);
       +                PUT(p+18, m->mouse.msec);
       +                p[19] = m->resized;
       +                break;
       +        case Tbouncemouse:
       +                PUT(p+6, m->mouse.xy.x);
       +                PUT(p+10, m->mouse.xy.y);
       +                PUT(p+14, m->mouse.buttons);
       +                break;
       +        case Tmoveto:
       +                PUT(p+6, m->mouse.xy.x);
       +                PUT(p+10, m->mouse.xy.y);
       +                break;
       +        case Tcursor:
       +                PUT(p+6, m->cursor.offset.x);
       +                PUT(p+10, m->cursor.offset.y);
       +                memmove(p+14, m->cursor.clr, sizeof m->cursor.clr);
       +                memmove(p+46, m->cursor.set, sizeof m->cursor.set);
       +                p[78] = m->arrowcursor;
       +                break;
       +        case Rrdkbd:
       +                PUT2(p+6, m->rune);
       +                break;
       +        case Tlabel:
       +                PUTSTRING(p+6, m->label);
       +                break;
       +        case Tinit:
       +                p += 6;
       +                p += PUTSTRING(p, m->winsize);
       +                p += PUTSTRING(p, m->label);
       +                break;
       +        case Rrdsnarf:
       +        case Twrsnarf:
       +                PUTSTRING(p+6, m->snarf);
       +                break;
       +        case Rrddraw:
       +        case Twrdraw:
       +                PUT(p+6, m->count);
       +                memmove(p+10, m->data, m->count);
       +                break;
       +        case Trddraw:
       +        case Rwrdraw:
       +                PUT(p+6, m->count);
       +                break;
       +        case Tresize:
       +                PUT(p+6, m->rect.min.x);
       +                PUT(p+10, m->rect.min.y);
       +                PUT(p+14, m->rect.max.x);
       +                PUT(p+18, m->rect.max.y);
       +                break;
       +        }                
       +        return nn;
       +}
       +
       +uint
       +convM2W(uchar *p, uint n, Wsysmsg *m)
       +{
       +        int nn;
       +        
       +        if(n < 6)
       +                return 0;
       +        GET(p, nn);
       +        if(nn > n)
       +                return 0;
       +        m->tag = p[4];
       +        m->type = p[5];
       +        switch(m->type){
       +        default:
       +                return 0;
       +        case Trdmouse:
       +        case Rbouncemouse:
       +        case Rmoveto:
       +        case Rcursor:
       +        case Trdkbd:
       +        case Rlabel:
       +        case Rinit:
       +        case Trdsnarf:
       +        case Rwrsnarf:
       +        case Ttop:
       +        case Rtop:
       +        case Rresize:
       +                break;
       +        case Rerror:
       +                GETSTRING(p+6, &m->error);
       +                break;
       +        case Rrdmouse:
       +                GET(p+6, m->mouse.xy.x);
       +                GET(p+10, m->mouse.xy.y);
       +                GET(p+14, m->mouse.buttons);
       +                GET(p+18, m->mouse.msec);
       +                m->resized = p[19];
       +                break;
       +        case Tbouncemouse:
       +                GET(p+6, m->mouse.xy.x);
       +                GET(p+10, m->mouse.xy.y);
       +                GET(p+14, m->mouse.buttons);
       +                break;
       +        case Tmoveto:
       +                GET(p+6, m->mouse.xy.x);
       +                GET(p+10, m->mouse.xy.y);
       +                break;
       +        case Tcursor:
       +                GET(p+6, m->cursor.offset.x);
       +                GET(p+10, m->cursor.offset.y);
       +                memmove(m->cursor.clr, p+14, sizeof m->cursor.clr);
       +                memmove(m->cursor.set, p+46, sizeof m->cursor.set);
       +                m->arrowcursor = p[78];
       +                break;
       +        case Rrdkbd:
       +                GET2(p+6, m->rune);
       +                break;
       +        case Tlabel:
       +                GETSTRING(p+6, &m->label);
       +                break;
       +        case Tinit:
       +                p += 6;
       +                p += GETSTRING(p, &m->winsize);
       +                p += GETSTRING(p, &m->label);
       +                break;
       +        case Rrdsnarf:
       +        case Twrsnarf:
       +                GETSTRING(p+6, &m->snarf);
       +                break;
       +        case Rrddraw:
       +        case Twrdraw:
       +                GET(p+6, m->count);
       +                m->data = p+10;
       +                break;
       +        case Trddraw:
       +        case Rwrdraw:
       +                GET(p+6, m->count);
       +                break;
       +        case Tresize:
       +                GET(p+6, m->rect.min.x);
       +                GET(p+10, m->rect.min.y);
       +                GET(p+14, m->rect.max.x);
       +                GET(p+18, m->rect.max.y);
       +                break;
       +        }        
       +        return nn;
       +}
       +
       +int
       +readwsysmsg(int fd, uchar *buf, uint nbuf)
       +{
       +        int n;
       +
       +        if(nbuf < 6)
       +                return -1;
       +        if(readn(fd, buf, 4) != 4)
       +                return -1;
       +        GET(buf, n);
       +        if(n > nbuf)
       +                return -1;
       +        if(readn(fd, buf+4, n-4) != n-4)
       +                return -1;
       +        return n;
       +}
       +
       +int
       +drawfcallfmt(Fmt *fmt)
       +{
       +        Wsysmsg *m;
       +        
       +        m = va_arg(fmt->args, Wsysmsg*);
       +        fmtprint(fmt, "tag=%d ", m->tag);
       +        switch(m->type){
       +        default:
       +                return fmtprint(fmt, "unknown msg %d", m->type);
       +        case Rerror:
       +                return fmtprint(fmt, "Rerror error='%s'", m->error);
       +        case Trdmouse:
       +                return fmtprint(fmt, "Trdmouse");
       +        case Rrdmouse:
       +                return fmtprint(fmt, "Rrdmouse x=%d y=%d buttons=%d msec=%d resized=%d",
       +                        m->mouse.xy.x, m->mouse.xy.y, 
       +                        m->mouse.buttons, m->mouse.msec, m->resized);
       +        case Tbouncemouse:
       +                return fmtprint(fmt, "Tbouncemouse x=%d y=%d buttons=%d",
       +                        m->mouse.xy.x, m->mouse.xy.y, m->mouse.buttons);
       +        case Rbouncemouse:
       +                return fmtprint(fmt, "Rbouncemouse");
       +        case Tmoveto:
       +                return fmtprint(fmt, "Tmoveto x=%d y=%d", m->mouse.xy.x, m->mouse.xy.y);
       +        case Rmoveto:
       +                return fmtprint(fmt, "Rmoveto");
       +        case Tcursor:
       +                return fmtprint(fmt, "Tcursor arrow=%d", m->arrowcursor);
       +        case Rcursor:
       +                return fmtprint(fmt, "Rcursor");
       +        case Trdkbd:
       +                return fmtprint(fmt, "Trdkbd");
       +        case Rrdkbd:
       +                return fmtprint(fmt, "Rrdkbd rune=%C", m->rune);
       +        case Tlabel:
       +                return fmtprint(fmt, "Tlabel label='%s'", m->label);
       +        case Rlabel:
       +                return fmtprint(fmt, "Rlabel");
       +        case Tinit:
       +                return fmtprint(fmt, "Tinit label='%s' winsize='%s'", m->label, m->winsize);
       +        case Rinit:
       +                return fmtprint(fmt, "Rinit");
       +        case Trdsnarf:
       +                return fmtprint(fmt, "Trdsnarf");
       +        case Rrdsnarf:
       +                return fmtprint(fmt, "Rrdsnarf snarf='%s'", m->snarf);
       +        case Twrsnarf:
       +                return fmtprint(fmt, "Twrsnarf snarf='%s'", m->snarf);
       +        case Rwrsnarf:
       +                return fmtprint(fmt, "Rwrsnarf");
       +        case Trddraw:
       +                return fmtprint(fmt, "Trddraw %d", m->count);
       +        case Rrddraw:
       +                return fmtprint(fmt, "Rrddraw %d %.*H", m->count, m->count, m->data);
       +        case Twrdraw:
       +                return fmtprint(fmt, "Twrdraw %d %.*H", m->count, m->count, m->data);
       +        case Rwrdraw:
       +                return fmtprint(fmt, "Rwrdraw %d", m->count);
       +        case Ttop:
       +                return fmtprint(fmt, "Ttop");
       +        case Rtop:
       +                return fmtprint(fmt, "Rtop");
       +        case Tresize:
       +                return fmtprint(fmt, "Tresize %R", m->rect);
       +        case Rresize:
       +                return fmtprint(fmt, "Rresize");
       +        }
       +}
 (DIR) diff --git a/src/libdraw/snarf.c b/src/libdraw/snarf.c
       t@@ -0,0 +1,15 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +void
       +putsnarf(char *snarf)
       +{
       +        _displaywrsnarf(display, snarf);
       +}
       +
       +char*
       +getsnarf(void)
       +{
       +        return _displayrdsnarf(display);
       +}
 (DIR) diff --git a/src/libdraw/wsys.c b/src/libdraw/wsys.c
       t@@ -0,0 +1,24 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <draw.h>
       +
       +int _wantfocuschanges;
       +
       +void
       +drawtopwindow(void)
       +{
       +        _displaytop(display);
       +}
       +
       +int
       +drawsetlabel(char *label)
       +{
       +        return _displaylabel(display, label);
       +}
       +
       +void
       +bouncemouse(Mouse *m)
       +{
       +        _displaybouncemouse(display, m);
       +}
       +