| plan 9 kernel history: overview | file list | diff list |
1992/0605/port/devbit.c (diff list | history)
| port/devbit.c on 1990/0324 | ||
| 1990/0324 | #include "u.h" | |
| 1992/0321 | #include "../port/lib.h" | |
| 1990/0324 | #include "mem.h" #include "dat.h" #include "fns.h" | |
| 1992/0111 | #include "../port/error.h" | |
| 1990/0324 | #include "devtab.h" | |
| 1992/0211 | #include <libg.h> | |
| 1990/0902 | #include <gnot.h> | |
| 1991/0708 | #include "screen.h" | |
| 1990/0324 | ||
| 1992/0208 | extern GSubfont *defont; | |
| 1990/0329 | ||
| 1990/0327 | /* | |
| 1991/0706 | * Some monochrome screens are reversed from what we like: | |
| 1992/0209 | * We want 0's bright and 1's dark. | |
| 1991/0706 | * Indexed by an Fcode, these compensate for the source bitmap being wrong * (exchange S rows) and destination (exchange D columns and invert result) */ int flipS[] = { 0x0, 0x4, 0x8, 0xC, 0x1, 0x5, 0x9, 0xD, 0x2, 0x6, 0xA, 0xE, 0x3, 0x7, 0xB, 0xF }; int flipD[] = { 0xF, 0xD, 0xE, 0xC, 0x7, 0x5, 0x6, 0x4, 0xB, 0x9, 0xA, 0x8, 0x3, 0x1, 0x2, 0x0, }; int flipping; /* are flip tables being used to transform Fcodes? */ /* | |
| 1990/0329 | * Device (#b/bitblt) is exclusive use on open, so no locks are necessary * for i/o */ /* | |
| 1990/0902 | * Some fields in GBitmaps are overloaded: | |
| 1990/0327 | * ldepth = -1 means free. * base is next pointer when free. * Arena is a word containing N, followed by a pointer to its bitmap, * followed by N blocks. The bitmap pointer is zero if block is free. */ | |
| 1990/0324 | ||
| 1990/05313 | struct { | |
| 1990/0324 | Ref; | |
| 1990/0902 | GBitmap *map; /* arena */ GBitmap *free; /* free list */ | |
| 1990/0327 | ulong *words; /* storage */ ulong nwords; /* total in arena */ ulong *wfree; /* pointer to next free word */ | |
| 1992/0209 | GFont *font; /* arena; looked up linearly BUG */ GSubfont *subfont; /* arena; looked up linearly BUG */ | |
| 1990/0327 | int lastid; /* last allocated bitmap id */ | |
| 1992/0209 | int lastsubfid; /* last allocated subfont id */ | |
| 1990/0623 | int lastfid; /* last allocated font id */ | |
| 1990/0329 | int init; /* freshly opened; init message pending */ | |
| 1990/0613 | int rid; /* read bitmap id */ int rminy; /* read miny */ int rmaxy; /* read maxy */ | |
| 1991/0706 | int mid; /* colormap read bitmap id */ | |
| 1990/0324 | }bit; | |
| 1990/0327 | #define FREE 0x80000000 void bitcompact(void); | |
| 1992/0209 | GBitmap*bitalloc(Rectangle, int); | |
| 1990/0902 | void bitfree(GBitmap*); | |
| 1992/0209 | void bitstring(GBitmap*, Point, GFont*, uchar*, long, Fcode); void bitloadchar(GFont*, int, GSubfont*, int); | |
| 1990/0912 | extern GBitmap gscreen; | |
| 1990/0327 | ||
| 1991/0707 | Mouseinfo mouse; Cursorinfo cursor; | |
| 1990/0504 | ||
| 1990/05313 | Cursor arrow = { | |
| 1990/0730 | {-1, -1}, | |
| 1990/05313 | {0xFF, 0xE0, 0xFF, 0xE0, 0xFF, 0xC0, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x80, 0xFF, 0xC0, 0xFF, 0xE0, 0xE7, 0xF0, 0xE3, 0xF8, 0xC1, 0xFC, 0x00, 0xFE, 0x00, 0x7F, 0x00, 0x3E, 0x00, 0x1C, 0x00, 0x08, }, {0x00, 0x00, 0x7F, 0xC0, 0x7F, 0x00, 0x7C, 0x00, 0x7E, 0x00, 0x7F, 0x00, 0x6F, 0x80, 0x67, 0xC0, 0x43, 0xE0, 0x41, 0xF0, 0x00, 0xF8, 0x00, 0x7C, 0x00, 0x3E, 0x00, 0x1C, 0x00, 0x08, 0x00, 0x00, } }; | |
| 1990/0504 | ulong setbits[16]; | |
| 1990/0902 | GBitmap set = | |
| 1990/0504 | { setbits, 0, 1, 0, | |
| 1992/0604 | {0, 0, 16, 16}, | |
| 1990/0504 | {0, 0, 16, 16} }; ulong clrbits[16]; | |
| 1990/0902 | GBitmap clr = | |
| 1990/0504 | { clrbits, 0, 1, 0, | |
| 1992/0604 | {0, 0, 16, 16}, | |
| 1990/0504 | {0, 0, 16, 16} }; | |
| 1991/0706 | ulong cursorbackbits[16*4]; | |
| 1990/0902 | GBitmap cursorback = | |
| 1990/0504 | { cursorbackbits, 0, 1, 0, | |
| 1992/0604 | {0, 0, 16, 16}, | |
| 1990/0504 | {0, 0, 16, 16} }; | |
| 1990/05313 | void Cursortocursor(Cursor*); | |
| 1990/0504 | void cursoron(int); void cursoroff(int); | |
| 1990/0505 | int mousechanged(void*); | |
| 1990/0504 | ||
| 1990/0324 | enum{ Qdir, Qbitblt, | |
| 1990/0329 | Qmouse, | |
| 1990/0709 | Qscreen, | |
| 1990/0324 | }; Dirtab bitdir[]={ | |
| 1991/1112 | "bitblt", {Qbitblt}, 0, 0666, "mouse", {Qmouse}, 0, 0666, "screen", {Qscreen}, 0, 0444, | |
| 1990/0324 | }; #define NBIT (sizeof bitdir/sizeof(Dirtab)) | |
| 1990/0629 | #define NINFO 257 | |
| 1990/0324 | void bitreset(void) { | |
| 1990/0327 | int i; | |
| 1990/0902 | GBitmap *bp; | |
| 1991/0706 | ulong r; | |
| 1990/0327 | ||
| 1990/0902 | bit.map = ialloc(conf.nbitmap * sizeof(GBitmap), 0); | |
| 1990/0327 | for(i=0,bp=bit.map; i<conf.nbitmap; i++,bp++){ bp->ldepth = -1; bp->base = (ulong*)(bp+1); } bp--; bp->base = 0; | |
| 1990/0912 | bit.map[0] = gscreen; /* bitmap 0 is screen */ | |
| 1991/0706 | getcolor(0, &r, &r, &r); if(r == 0) flipping = 1; | |
| 1990/0327 | bit.free = bit.map+1; bit.lastid = -1; | |
| 1992/0209 | bit.lastsubfid = -1; | |
| 1990/0623 | bit.lastfid = -1; | |
| 1990/0327 | bit.words = ialloc(conf.nbitbyte, 0); bit.nwords = conf.nbitbyte/sizeof(ulong); bit.wfree = bit.words; | |
| 1992/0209 | bit.subfont = ialloc(conf.nsubfont * sizeof(GSubfont), 0); bit.subfont[0] = *defont; bit.font = ialloc(conf.nfont * sizeof(GFont), 0); | |
| 1992/0208 | for(i=1; i<conf.nsubfont; i++) | |
| 1992/0209 | bit.subfont[i].info = ialloc((NINFO+1)*sizeof(Fontchar), 0); for(i=0; i<conf.nfont; i++) bit.font[i].ldepth = -1; | |
| 1990/05313 | Cursortocursor(&arrow); | |
| 1990/0324 | } void bitinit(void) { lock(&bit); unlock(&bit); | |
| 1991/0706 | if(gscreen.ldepth > 3) cursorback.ldepth = 0; else { cursorback.ldepth = gscreen.ldepth; cursorback.width = ((16 << gscreen.ldepth) + 31) >> 5; } | |
| 1990/0504 | cursoron(1); | |
| 1990/0324 | } Chan* bitattach(char *spec) { | |
| 1992/0604 | bit.map[0] = gscreen; /* bitmap 0 is screen */ | |
| 1990/0324 | return devattach('b', spec); } Chan* bitclone(Chan *c, Chan *nc) { nc = devclone(c, nc); | |
| 1990/11211 | if(c->qid.path != CHDIR) | |
| 1990/0324 | incref(&bit); | |
| 1991/0706 | return nc; | |
| 1990/0324 | } int bitwalk(Chan *c, char *name) { return devwalk(c, name, bitdir, NBIT, devgen); } void bitstat(Chan *c, char *db) { devstat(c, db, bitdir, NBIT, devgen); } Chan * bitopen(Chan *c, int omode) { | |
| 1990/11211 | if(c->qid.path == CHDIR){ | |
| 1990/0324 | if(omode != OREAD) | |
| 1990/11211 | error(Eperm); }else if(c->qid.path == Qbitblt){ | |
| 1990/0324 | lock(&bit); | |
| 1990/0515 | if(bit.ref){ | |
| 1990/0324 | unlock(&bit); | |
| 1990/11211 | error(Einuse); | |
| 1990/0324 | } | |
| 1992/0604 | bit.map[0].clipr = gscreen.clipr; | |
| 1990/0327 | bit.lastid = -1; | |
| 1990/0623 | bit.lastfid = -1; | |
| 1992/0209 | bit.lastsubfid = -1; | |
| 1990/0613 | bit.rid = -1; | |
| 1991/0706 | bit.mid = -1; | |
| 1990/0604 | bit.init = 0; | |
| 1990/05151 | bit.ref = 1; | |
| 1990/05313 | Cursortocursor(&arrow); | |
| 1990/0324 | unlock(&bit); | |
| 1990/05151 | }else | |
| 1990/0324 | incref(&bit); c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } void bitcreate(Chan *c, char *name, int omode, ulong perm) { | |
| 1991/1115 | USED(c, name, omode, perm); | |
| 1990/11211 | error(Eperm); | |
| 1990/0324 | } void bitremove(Chan *c) { | |
| 1991/1115 | USED(c); | |
| 1990/11211 | error(Eperm); | |
| 1990/0324 | } void bitwstat(Chan *c, char *db) { | |
| 1991/1115 | USED(c, db); | |
| 1990/11211 | error(Eperm); | |
| 1990/0324 | } void bitclose(Chan *c) { | |
| 1990/0327 | int i; | |
| 1990/0902 | GBitmap *bp; | |
| 1992/0208 | GSubfont *fp; | |
| 1992/0209 | GFont *ffp; | |
| 1990/0327 | ||
| 1990/11211 | if(c->qid.path!=CHDIR && (c->flag&COPEN)){ | |
| 1990/0329 | lock(&bit); | |
| 1990/0327 | if(--bit.ref == 0){ for(i=1,bp=&bit.map[1]; i<conf.nbitmap; i++,bp++) if(bp->ldepth >= 0) bitfree(bp); | |
| 1992/0209 | for(i=1,fp=&bit.subfont[1]; i<conf.nsubfont; i++,fp++) | |
| 1990/0623 | fp->bits = 0; | |
| 1992/0209 | for(i=0,ffp=&bit.font[0]; i<conf.nfont; i++,ffp++){ ffp->b = 0; ffp->ldepth = -1; } bit.font[0].ldepth=0;/*BUG */ | |
| 1990/0327 | } | |
| 1990/0324 | unlock(&bit); } } | |
| 1990/0327 | #define GSHORT(p) (((p)[0]<<0) | ((p)[1]<<8)) #define GLONG(p) ((GSHORT(p)<<0) | (GSHORT(p+2)<<16)) | |
| 1990/0329 | #define PSHORT(p, v) ((p)[0]=(v), (p)[1]=((v)>>8)) #define PLONG(p, v) (PSHORT(p, (v)), PSHORT(p+2, (v)>>16)) | |
| 1990/0327 | ||
| 1990/0324 | long | |
| 1991/0411 | bitread(Chan *c, void *va, long n, ulong offset) | |
| 1990/0324 | { | |
| 1990/0613 | uchar *p, *q; long miny, maxy, t, x, y; | |
| 1991/0706 | ulong l, nw, ws, rv, gv, bv; | |
| 1992/0605 | int off, j, dn; | |
| 1990/06231 | Fontchar *i; | |
| 1990/0902 | GBitmap *src; | |
| 1990/0327 | ||
| 1990/11211 | if(c->qid.path & CHDIR) | |
| 1990/0324 | return devdirread(c, va, n, bitdir, NBIT, devgen); | |
| 1990/11211 | switch(c->qid.path){ | |
| 1990/0505 | case Qmouse: | |
| 1990/0329 | /* | |
| 1990/0505 | * mouse: * 'm' 1 * buttons 1 * point 8 | |
| 1990/0329 | */ | |
| 1990/0505 | if(n < 10) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0505 | Again: while(mouse.changed == 0) sleep(&mouse.r, mousechanged, 0); lock(&cursor); if(mouse.changed == 0){ unlock(&cursor); goto Again; } p = va; p[0] = 'm'; p[1] = mouse.buttons; PLONG(p+2, mouse.xy.x); PLONG(p+6, mouse.xy.y); mouse.changed = 0; unlock(&cursor); n = 10; break; case Qbitblt: p = va; | |
| 1990/0329 | /* | |
| 1990/0505 | * Fuss about and figure out what to say. | |
| 1990/0329 | */ | |
| 1990/0505 | if(bit.init){ /* * init: * 'I' 1 * ldepth 1 * rectangle 16 | |
| 1990/06231 | * if count great enough, also * font info 3*12 * fontchars 6*(defont->n+1) | |
| 1990/0505 | */ if(n < 18) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0505 | p[0] = 'I'; | |
| 1990/0912 | p[1] = gscreen.ldepth; PLONG(p+2, gscreen.r.min.x); PLONG(p+6, gscreen.r.min.y); PLONG(p+10, gscreen.r.max.x); PLONG(p+14, gscreen.r.max.y); | |
| 1992/0605 | dn = 18; if(bit.init=='j' && n>=18+16){ PLONG(p+18, gscreen.clipr.min.x); PLONG(p+22, gscreen.clipr.min.y); PLONG(p+26, gscreen.clipr.max.x); PLONG(p+30, gscreen.clipr.max.y); dn += 16; } if(n >= dn+3*12+6*(defont->n+1)){ p += dn; | |
| 1990/06231 | sprint((char*)p, "%11d %11d %11d ", defont->n, defont->height, defont->ascent); p += 3*12; for(i=defont->info,j=0; j<=defont->n; j++,i++,p+=6){ PSHORT(p, i->x); p[2] = i->top; p[3] = i->bottom; p[4] = i->left; p[5] = i->width; } | |
| 1992/0605 | n = dn+3*12+6*(defont->n+1); | |
| 1990/06231 | }else | |
| 1992/0605 | n = dn; | |
| 1990/0505 | bit.init = 0; break; } if(bit.lastid > 0){ /* * allocate: * 'A' 1 * bitmap id 2 */ if(n < 3) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0505 | p[0] = 'A'; PSHORT(p+1, bit.lastid); bit.lastid = -1; n = 3; break; } | |
| 1992/0209 | if(bit.lastsubfid > 0){ | |
| 1990/0623 | /* | |
| 1992/0209 | * allocate subfont: | |
| 1990/0623 | * 'K' 1 | |
| 1992/0209 | * subfont id 2 | |
| 1990/0623 | */ if(n < 3) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0623 | p[0] = 'K'; | |
| 1992/0209 | PSHORT(p+1, bit.lastsubfid); bit.lastsubfid = -1; n = 3; break; } if(bit.lastfid >= 0){ /* * allocate font: * 'N' 1 * font id 2 */ if(n < 3) error(Ebadblt); p[0] = 'N'; | |
| 1990/0623 | PSHORT(p+1, bit.lastfid); bit.lastfid = -1; n = 3; break; } | |
| 1991/0706 | if(bit.mid >= 0){ /* * read colormap: * data 12*(2**bitmapdepth) */ l = (1<<bit.map[bit.mid].ldepth); nw = 1 << l; if(n < 12*nw) error(Ebadblt); for(j = 0; j < nw; j++){ if(bit.mid == 0){ getcolor(flipping? ~j : j, &rv, &gv, &bv); }else{ rv = j; for(off = 32-l; off > 0; off -= l) rv = (rv << l) | j; gv = bv = rv; } PLONG(p, rv); PLONG(p+4, gv); PLONG(p+8, bv); p += 12; } bit.mid = -1; n = 12*nw; break; } | |
| 1990/0613 | if(bit.rid >= 0){ /* | |
| 1991/0706 | * read bitmap: | |
| 1990/0613 | * data bytewidth*(maxy-miny) */ src = &bit.map[bit.rid]; if(src->ldepth<0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1990/0613 | off = 0; if(bit.rid == 0) off = 1; miny = bit.rminy; maxy = bit.rmaxy; if(miny>maxy || miny<src->r.min.y || maxy>src->r.max.y) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0613 | ws = 1<<(3-src->ldepth); /* pixels per byte */ /* set l to number of bytes of incoming data per scan line */ if(src->r.min.x >= 0) l = (src->r.max.x+ws-1)/ws - src->r.min.x/ws; else{ /* make positive before divide */ t = (-src->r.min.x)+ws-1; t = (t/ws)*ws; l = (t+src->r.max.x+ws-1)/ws; } if(n < l*(maxy-miny)) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0613 | if(off) cursoroff(1); n = 0; p = va; for(y=miny; y<maxy; y++){ | |
| 1990/0912 | q = (uchar*)gaddr(src, Pt(src->r.min.x, y)); | |
| 1990/0911 | q += (src->r.min.x&((sizeof(ulong))*ws-1))/ws; | |
| 1991/0706 | if(bit.rid == 0 && flipping) /* flip bits */ for(x=0; x<l; x++) | |
| 1992/0209 | *p++ = ~(*q++); | |
| 1991/0706 | else for(x=0; x<l; x++) | |
| 1992/0209 | *p++ = *q++; | |
| 1990/0613 | n += l; } if(off) cursoron(1); bit.rid = -1; break; } | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0709 | case Qscreen: | |
| 1991/0411 | if(offset==0){ | |
| 1990/0709 | if(n < 5*12) | |
| 1990/11211 | error(Eio); | |
| 1990/0709 | sprint(va, "%11d %11d %11d %11d %11d ", | |
| 1990/0912 | gscreen.ldepth, gscreen.r.min.x, gscreen.r.min.y, gscreen.r.max.x, gscreen.r.max.y); | |
| 1990/0709 | n = 5*12; break; } | |
| 1990/0912 | ws = 1<<(3-gscreen.ldepth); /* pixels per byte */ l = (gscreen.r.max.x+ws-1)/ws - gscreen.r.min.x/ws; | |
| 1991/0411 | t = offset-5*12; | |
| 1991/1023 | miny = t/l; /* unsigned computation */ | |
| 1990/0709 | maxy = (t+n)/l; | |
| 1990/0912 | if(miny >= gscreen.r.max.y) | |
| 1990/0709 | return 0; | |
| 1990/0912 | if(maxy >= gscreen.r.max.y) maxy = gscreen.r.max.y; | |
| 1990/0709 | n = 0; p = va; for(y=miny; y<maxy; y++){ | |
| 1990/0912 | q = (uchar*)gaddr(&gscreen, Pt(0, y)); | |
| 1991/1105 | if(flipping) for(x=0; x<l; x++) | |
| 1992/0209 | *p++ = ~(*q++); | |
| 1991/1105 | else for(x=0; x<l; x++) | |
| 1992/0209 | *p++ = *q++; | |
| 1990/0709 | n += l; } break; | |
| 1990/0505 | default: | |
| 1990/11211 | error(Egreg); | |
| 1990/0327 | } return n; | |
| 1990/0324 | } long | |
| 1991/0411 | bitwrite(Chan *c, void *va, long n, ulong offset) | |
| 1990/0324 | { | |
| 1990/0329 | uchar *p, *q; | |
| 1991/0706 | long m, v, miny, maxy, minx, maxx, t, x, y; ulong l, nw, ws, rv; int off, isoff, i, ok; | |
| 1990/06111 | Point pt, pt1, pt2; | |
| 1990/0324 | Rectangle rect; | |
| 1990/05313 | Cursor curs; | |
| 1991/0706 | Fcode fc; | |
| 1990/0623 | Fontchar *fcp; | |
| 1990/0902 | GBitmap *bp, *src, *dst; | |
| 1992/0208 | GSubfont *f; | |
| 1992/0209 | GFont *ff; | |
| 1990/0324 | ||
| 1990/11211 | if(c->qid.path == CHDIR) error(Eisdir); | |
| 1990/0324 | ||
| 1990/11211 | if(c->qid.path != Qbitblt) error(Egreg); | |
| 1990/0327 | ||
| 1990/0721 | isoff = 0; if(waserror()){ if(isoff) cursoron(1); nexterror(); } | |
| 1990/0324 | p = va; m = n; | |
| 1990/0327 | while(m > 0) switch(*p){ | |
| 1990/0329 | default: pprint("bitblt request 0x%x\n", *p); | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0329 | ||
| 1990/0327 | case 'a': /* * allocate: * 'a' 1 * ldepth 1 * Rectangle 16 * next read returns allocated bitmap id */ if(m < 18) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0327 | v = *(p+1); | |
| 1992/0209 | if(v > 3) /* BUG */ | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0327 | rect.min.x = GLONG(p+2); rect.min.y = GLONG(p+6); rect.max.x = GLONG(p+10); rect.max.y = GLONG(p+14); | |
| 1991/0423 | if(Dx(rect) < 0 || Dy(rect) < 0) error(Ebadblt); | |
| 1992/0209 | bp = bitalloc(rect, v); | |
| 1990/0327 | bit.lastid = bp-bit.map; m -= 18; p += 18; break; | |
| 1990/0324 | ||
| 1990/0327 | case 'b': /* * bitblt * 'b' 1 * dst id 2 * dst Point 8 * src id 2 * src Rectangle 16 * code 2 */ if(m < 31) | |
| 1990/11211 | error(Ebadblt); | |
| 1991/0706 | fc = GSHORT(p+29) & 0xF; v = GSHORT(p+11); src = &bit.map[v]; if(v<0 || v>=conf.nbitmap || src->ldepth < 0) error(Ebadbitmap); off = 0; if(v == 0){ if(flipping) fc = flipS[fc]; off = 1; } | |
| 1990/0327 | v = GSHORT(p+1); dst = &bit.map[v]; if(v<0 || v>=conf.nbitmap || dst->ldepth < 0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1991/0706 | if(v == 0){ if(flipping) fc = flipD[fc]; | |
| 1990/0504 | off = 1; | |
| 1991/0706 | } | |
| 1990/0327 | pt.x = GLONG(p+3); pt.y = GLONG(p+7); rect.min.x = GLONG(p+13); rect.min.y = GLONG(p+17); rect.max.x = GLONG(p+21); rect.max.y = GLONG(p+25); | |
| 1990/0721 | if(off && !isoff){ | |
| 1990/0504 | cursoroff(1); | |
| 1990/0721 | isoff = 1; } | |
| 1991/1225 | gbitblt(dst, pt, src, rect, fc); | |
| 1990/0327 | m -= 31; p += 31; break; | |
| 1990/05313 | case 'c': /* * cursorswitch * 'c' 1 * nothing more: return to arrow; else * Point 8 * clr 32 * set 32 */ if(m == 1){ | |
| 1990/0721 | if(!isoff){ cursoroff(1); isoff = 1; } | |
| 1990/05313 | Cursortocursor(&arrow); m -= 1; p += 1; break; } if(m < 73) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/05313 | curs.offset.x = GLONG(p+1); curs.offset.y = GLONG(p+5); | |
| 1991/0318 | memmove(curs.clr, p+9, 2*16); memmove(curs.set, p+41, 2*16); | |
| 1990/0721 | if(!isoff){ cursoroff(1); isoff = 1; } | |
| 1990/05313 | Cursortocursor(&curs); m -= 73; p += 73; break; | |
| 1990/0327 | case 'f': /* * free * 'f' 1 * id 2 */ if(m < 3) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0327 | v = GSHORT(p+1); dst = &bit.map[v]; | |
| 1990/0623 | if(v<0 || v>=conf.nbitmap || dst->ldepth<0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1990/0327 | bitfree(dst); m -= 3; p += 3; | |
| 1990/0604 | break; | |
| 1990/0623 | case 'g': /* | |
| 1992/0209 | * free subfont (free bitmap separately) | |
| 1990/0623 | * 'g' 1 * id 2 */ if(m < 3) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0623 | v = GSHORT(p+1); | |
| 1992/0209 | f = &bit.subfont[v]; | |
| 1992/0208 | if(v<0 || v>=conf.nsubfont || f->bits==0) | |
| 1990/11211 | error(Ebadfont); | |
| 1990/0623 | f->bits = 0; m -= 3; p += 3; break; | |
| 1992/0209 | case 'h': /* * free font * 'h' 1 * id 2 */ if(m < 3) error(Ebadblt); v = GSHORT(p+1); ff = &bit.font[v]; if(v<0 || v>=conf.nfont || ff->ldepth<0) error(Ebadfont); if(ff->b) bitfree(ff->b); ff->b = 0; ff->ldepth = -1; m -= 3; p += 3; break; | |
| 1990/0604 | case 'i': | |
| 1992/0605 | case 'j': | |
| 1990/0604 | /* * init * | |
| 1992/0605 | * 'i','j' 1 | |
| 1990/0604 | */ | |
| 1992/0605 | bit.init = *p; | |
| 1990/0604 | m -= 1; p += 1; | |
| 1990/0327 | break; | |
| 1990/0329 | ||
| 1990/0623 | case 'k': /* | |
| 1992/0209 | * allocate subfont | |
| 1990/0623 | * 'k' 1 * n 2 * height 1 * ascent 1 * bitmap id 2 | |
| 1990/0707 | * fontchars 6*(n+1) | |
| 1990/0623 | * next read returns allocated font id */ if(m < 7) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0623 | v = GSHORT(p+1); if(v<0 || v>NINFO || m<7+6*(v+1)) /* BUG */ | |
| 1990/11211 | error(Ebadblt); | |
| 1992/0208 | for(i=1; i<conf.nsubfont; i++) | |
| 1992/0209 | if(bit.subfont[i].bits == 0) goto subfontfound; | |
| 1990/11211 | error(Enofont); | |
| 1992/0209 | subfontfound: f = &bit.subfont[i]; | |
| 1990/0623 | f->n = v; f->height = p[3]; f->ascent = p[4]; v = GSHORT(p+5); dst = &bit.map[v]; if(v<0 || v>=conf.nbitmap || dst->ldepth<0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1990/0623 | m -= 7; p += 7; fcp = f->info; for(i=0; i<=f->n; i++,fcp++){ fcp->x = GSHORT(p); fcp->top = p[2]; fcp->bottom = p[3]; fcp->left = p[4]; fcp->width = p[5]; fcp->top = p[2]; p += 6; m -= 6; } | |
| 1992/0209 | bit.lastsubfid = f - bit.subfont; | |
| 1990/0623 | f->bits = dst; break; | |
| 1990/06111 | case 'l': /* * line segment * * 'l' 1 * id 2 * pt1 8 * pt2 8 * value 1 * code 2 */ if(m < 22) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/06111 | v = GSHORT(p+1); dst = &bit.map[v]; | |
| 1990/0623 | if(v<0 || v>=conf.nbitmap || dst->ldepth<0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1990/06111 | off = 0; | |
| 1991/0706 | fc = GSHORT(p+20) & 0xF; if(v == 0){ if(flipping) fc = flipD[fc]; | |
| 1990/06111 | off = 1; | |
| 1991/0706 | } | |
| 1990/06111 | pt1.x = GLONG(p+3); pt1.y = GLONG(p+7); pt2.x = GLONG(p+11); pt2.y = GLONG(p+15); t = p[19]; | |
| 1990/0721 | if(off && !isoff){ | |
| 1990/06111 | cursoroff(1); | |
| 1990/0721 | isoff = 1; } | |
| 1991/0706 | gsegment(dst, pt1, pt2, t, fc); | |
| 1990/06111 | m -= 22; p += 22; | |
| 1990/0613 | break; | |
| 1991/0706 | case 'm': /* * read colormap * * 'm' 1 * id 2 */ if(m < 3) error(Ebadblt); v = GSHORT(p+1); dst = &bit.map[v]; if(v<0 || v>=conf.nbitmap || dst->ldepth<0) error(Ebadbitmap); bit.mid = v; m -= 3; p += 3; break; | |
| 1992/0209 | case 'n': /* * allocate font * 'n' 1 * height 1 * ascent 1 * ldepth 2 * next read returns allocated font id */ if(m < 5) error(Ebadblt); v = GSHORT(p+3); if(v < 0) error(Ebadblt); for(i=0; i<conf.nfont; i++) if(bit.font[i].ldepth < 0) goto fontfound; error(Enofont); fontfound: ff = &bit.font[i]; ff->height = p[1]; ff->ascent = p[2]; ff->ldepth = v; ff->width = 0; ff->b = 0; m -= 5; p += 5; bit.lastfid = ff - bit.font; break; | |
| 1990/0722 | case 'p': /* * point * * 'p' 1 * id 2 * pt 8 * value 1 * code 2 */ if(m < 14) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0722 | v = GSHORT(p+1); dst = &bit.map[v]; if(v<0 || v>=conf.nbitmap || dst->ldepth<0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1990/0722 | off = 0; | |
| 1991/0706 | fc = GSHORT(p+12) & 0xF; if(v == 0){ if(flipping) fc = flipD[fc]; | |
| 1990/0722 | off = 1; | |
| 1991/0706 | } | |
| 1990/0722 | pt1.x = GLONG(p+3); pt1.y = GLONG(p+7); t = p[11]; if(off && !isoff){ cursoroff(1); isoff = 1; } | |
| 1991/0706 | gpoint(dst, pt1, t, fc); | |
| 1990/0722 | m -= 14; p += 14; break; | |
| 1992/0604 | case 'q': /* * clip rectangle * 'q' 1 * id 2 * rect 16 */ if(m < 19) error(Ebadblt); v = GSHORT(p+1); dst = &bit.map[v]; if(v<0 || v>=conf.nbitmap || dst->ldepth<0) error(Ebadbitmap); rect.min.x = GLONG(p+3); rect.min.y = GLONG(p+7); rect.max.x = GLONG(p+11); rect.max.y = GLONG(p+15); if(rectclip(&rect, dst->r)) dst->clipr = rect; else dst->clipr = dst->r; m -= 19; p += 19; break; | |
| 1990/0613 | case 'r': /* * read * 'r' 1 * src id 2 * miny 4 * maxy 4 */ if(m < 11) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0613 | v = GSHORT(p+1); src = &bit.map[v]; | |
| 1990/0623 | if(v<0 || v>=conf.nbitmap || src->ldepth<0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1990/0613 | miny = GLONG(p+3); maxy = GLONG(p+7); if(miny>maxy || miny<src->r.min.y || maxy>src->r.max.y) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0613 | bit.rid = v; bit.rminy = miny; bit.rmaxy = maxy; p += 11; m -= 11; | |
| 1990/06111 | break; | |
| 1990/0329 | case 's': /* | |
| 1992/0209 | * subfstring | |
| 1990/0329 | * 's' 1 * id 2 * pt 8 | |
| 1992/0209 | * subfont id 2 | |
| 1990/06111 | * code 2 | |
| 1990/0329 | * string n (null terminated) */ if(m < 16) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0329 | v = GSHORT(p+1); dst = &bit.map[v]; | |
| 1990/0623 | if(v<0 || v>=conf.nbitmap || dst->ldepth<0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1990/0504 | off = 0; | |
| 1991/0706 | fc = GSHORT(p+13) & 0xF; if(v == 0){ if(flipping) fc = flipD[fc]; | |
| 1990/0504 | off = 1; | |
| 1991/0706 | } | |
| 1990/0329 | pt.x = GLONG(p+3); pt.y = GLONG(p+7); v = GSHORT(p+11); | |
| 1992/0209 | f = &bit.subfont[v]; | |
| 1992/0208 | if(v<0 || v>=conf.nsubfont || f->bits==0 || f->bits->ldepth<0) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0329 | p += 15; m -= 15; q = memchr(p, 0, m); if(q == 0) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0721 | if(off && !isoff){ | |
| 1990/0504 | cursoroff(1); | |
| 1990/0721 | isoff = 1; } | |
| 1992/0208 | gsubfstring(dst, pt, f, (char*)p, fc); | |
| 1990/0329 | q++; m -= q-p; p = q; break; case 't': /* * texture * 't' 1 * dst id 2 | |
| 1992/0604 | * rect 16 | |
| 1990/0329 | * src id 2 * fcode 2 */ if(m < 23) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0329 | v = GSHORT(p+1); dst = &bit.map[v]; | |
| 1990/0623 | if(v<0 || v>=conf.nbitmap || dst->ldepth<0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1990/0504 | off = 0; | |
| 1991/0706 | fc = GSHORT(p+21) & 0xF; if(v == 0){ if(flipping) fc = flipD[fc]; | |
| 1990/0504 | off = 1; | |
| 1991/0706 | } | |
| 1990/0329 | rect.min.x = GLONG(p+3); rect.min.y = GLONG(p+7); rect.max.x = GLONG(p+11); rect.max.y = GLONG(p+15); v = GSHORT(p+19); src = &bit.map[v]; | |
| 1990/0623 | if(v<0 || v>=conf.nbitmap || src->ldepth<0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1991/0701 | if(off && !isoff){ cursoroff(1); isoff = 1; | |
| 1990/0329 | } | |
| 1991/0706 | gtexture(dst, rect, src, fc); | |
| 1990/0329 | m -= 23; p += 23; break; | |
| 1992/0209 | case 'u': /* * string * 'u' 1 * id 2 * pt 8 * font id 2 * code 2 * n 2 * cache indexes 2*n (not null terminated) */ if(m < 17) error(Ebadblt); v = GSHORT(p+1); dst = &bit.map[v]; if(v<0 || v>=conf.nbitmap || dst->ldepth<0) error(Ebadbitmap); off = 0; fc = GSHORT(p+13) & 0xF; if(v == 0){ if(flipping) fc = flipD[fc]; off = 1; } pt.x = GLONG(p+3); pt.y = GLONG(p+7); v = GSHORT(p+11); ff = &bit.font[v]; if(v<0 || v>=conf.nfont || ff->ldepth<0) error(Ebadblt); l = GSHORT(p+15)*2; p += 17; m -= 17; if(l > m) error(Ebadblt); if(off && !isoff){ cursoroff(1); isoff = 1; } bitstring(dst, pt, ff, p, l, fc); m -= l; p += l; break; case 'v': /* * clear font cache and bitmap * 'v' 1 * id 2 * width 2 */ if(m < 5) error(Ebadblt); v = GSHORT(p+1); ff = &bit.font[v]; if(v<0 || v>=conf.nfont || ff->ldepth<0) error(Ebadblt); /* * memset not necessary but helps avoid * confusion if the cache is mishandled by the * user. */ memset(ff->cache, 0, (NFCACHE+NFLOOK)*sizeof(ff->cache[0])); if(ff->b) bitfree(ff->b); ff->width = GSHORT(p+3); ff->b = 0; ff->b = bitalloc(Rect(0, 0, (NFCACHE+NFLOOK)*ff->width, ff->height), ff->ldepth); p += 5; m -= 5; break; | |
| 1990/0329 | case 'w': /* * write * 'w' 1 * dst id 2 * miny 4 * maxy 4 * data bytewidth*(maxy-miny) */ if(m < 11) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0329 | v = GSHORT(p+1); dst = &bit.map[v]; | |
| 1990/0623 | if(v<0 || v>=conf.nbitmap || dst->ldepth<0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1990/0504 | off = 0; if(v == 0) off = 1; | |
| 1990/0329 | miny = GLONG(p+3); maxy = GLONG(p+7); | |
| 1990/03291 | if(miny>maxy || miny<dst->r.min.y || maxy>dst->r.max.y) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0329 | ws = 1<<(3-dst->ldepth); /* pixels per byte */ /* set l to number of bytes of incoming data per scan line */ if(dst->r.min.x >= 0) l = (dst->r.max.x+ws-1)/ws - dst->r.min.x/ws; else{ /* make positive before divide */ t = (-dst->r.min.x)+ws-1; t = (t/ws)*ws; l = (t+dst->r.max.x+ws-1)/ws; } p += 11; m -= 11; if(m < l*(maxy-miny)) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0721 | if(off && !isoff){ | |
| 1990/0504 | cursoroff(1); | |
| 1990/0721 | isoff = 1; } | |
| 1990/0329 | for(y=miny; y<maxy; y++){ | |
| 1990/0912 | q = (uchar*)gaddr(dst, Pt(dst->r.min.x, y)); | |
| 1990/0911 | q += (dst->r.min.x&((sizeof(ulong))*ws-1))/ws; | |
| 1991/0706 | if(v == 0 && flipping) /* flip bits */ for(x=0; x<l; x++) | |
| 1992/0209 | *q++ = ~(*p++); | |
| 1991/0706 | else for(x=0; x<l; x++) | |
| 1992/0209 | *q++ = *p++; | |
| 1990/0329 | m -= l; } break; | |
| 1990/0826 | case 'x': /* * cursorset * * 'x' 1 * pt 8 */ if(m < 9) | |
| 1990/11211 | error(Ebadblt); | |
| 1990/0826 | pt1.x = GLONG(p+1); pt1.y = GLONG(p+5); | |
| 1991/0706 | /* if(!eqpt(mouse.xy, pt1))*/{ | |
| 1991/0619 | mouse.xy = pt1; mouse.track = 1; mouseclock(); } | |
| 1990/0826 | m -= 9; p += 9; break; | |
| 1991/0706 | ||
| 1992/0209 | case 'y': /* * load font from subfont * 'y' 1 * id 2 | |
| 1992/0212 | * cache index 2 | |
| 1992/0209 | * subfont id 2 * subfont index 2 */ if(m < 9) error(Ebadblt); v = GSHORT(p+1); ff = &bit.font[v]; if(v<0 || v>=conf.nfont || ff->ldepth<0 || ff->b==0) error(Ebadblt); l = GSHORT(p+3); if(l >= NFCACHE+NFLOOK) error(Ebadblt); v = GSHORT(p+5); f = &bit.subfont[v]; if(v<0 || v>=conf.nsubfont || f->bits->ldepth<0) error(Ebadblt); nw = GSHORT(p+7); if(nw >= f->n) error(Ebadblt); bitloadchar(ff, l, f, nw); p += 9; m -= 9; break; | |
| 1991/0706 | case 'z': /* * write the colormap * * 'z' 1 * id 2 * map 12*(2**bitmapdepth) */ if(m < 3) error(Ebadblt); v = GSHORT(p+1); if(v != 0) error(Ebadbitmap); m -= 3; p += 3; nw = 1 << (1 << bit.map[v].ldepth); if(m < 12*nw) error(Ebadblt); ok = 1; for(i = 0; i < nw; i++){ ok &= setcolor(i, GLONG(p), GLONG(p+4), GLONG(p+8)); p += 12; m -= 12; } if(!ok){ /* assume monochrome: possibly change flipping */ l = GLONG(p-12); getcolor(nw-1, &rv, &rv, &rv); flipping = (l != rv); } break; | |
| 1990/0327 | } | |
| 1991/0614 | poperror(); | |
| 1990/0721 | if(isoff) cursoron(1); | |
| 1990/0324 | return n; } | |
| 1992/0209 | GBitmap* bitalloc(Rectangle rect, int ld) { GBitmap *bp; ulong l, ws, nw; long t; if(bit.free == 0) error(Enobitmap); ws = 1<<(5-ld); /* pixels per word */ | |
| 1992/0519 | if(rect.min.x >= 0) { l = (rect.max.x+ws-1)/ws; l -= rect.min.x/ws; } | |
| 1992/0209 | else{ /* make positive before divide */ t = (-rect.min.x)+ws-1; t = (t/ws)*ws; l = (t+rect.max.x+ws-1)/ws; } nw = l*Dy(rect); if(bit.wfree+2+nw > bit.words+bit.nwords){ bitcompact(); if(bit.wfree+2+nw > bit.words+bit.nwords) error(Enobitstore); } bp = bit.free; bit.free = (GBitmap*)(bp->base); *bit.wfree++ = nw; *bit.wfree++ = (ulong)bp; bp->base = bit.wfree; memset(bp->base, 0, nw*sizeof(ulong)); bit.wfree += nw; bp->zero = l*rect.min.y; if(rect.min.x >= 0) bp->zero += rect.min.x/ws; else bp->zero -= (-rect.min.x+ws-1)/ws; bp->zero = -bp->zero; bp->width = l; bp->ldepth = ld; bp->r = rect; | |
| 1992/0604 | bp->clipr = rect; | |
| 1992/0209 | bp->cache = 0; return bp; } | |
| 1990/0324 | void | |
| 1990/0902 | bitfree(GBitmap *bp) | |
| 1990/0327 | { | |
| 1990/05313 | bp->base[-1] = 0; | |
| 1990/0327 | bp->ldepth = -1; bp->base = (ulong*)bit.free; bit.free = bp; } | |
| 1992/0209 | void bitstring(GBitmap *bp, Point pt, GFont *f, uchar *p, long l, Fcode fc) { int full; Rectangle rect; ushort r; GCacheinfo *c; full = (fc==S || fc==notS); /* for reverse-video */ if(full){ rect.min.y = 0; rect.max.y = f->height; } while(l > 0){ r = GSHORT(p); p += 2; l -= 2; | |
| 1992/0211 | if(r >= NFCACHE+NFLOOK) continue; | |
| 1992/0209 | c = &f->cache[r]; if(!full){ rect.min.y = c->top; rect.max.y = c->bottom; } rect.min.x = c->x; rect.max.x = c->xright; gbitblt(bp, Pt(pt.x+c->left, pt.y+rect.min.y), f->b, rect, fc); pt.x += c->width; } } void bitloadchar(GFont *f, int ci, GSubfont *subf, int si) { GCacheinfo *c; Rectangle rect; Fontchar *fi; | |
| 1992/0219 | int y; | |
| 1992/0209 | c = &f->cache[ci]; fi = &subf->info[si]; | |
| 1992/0219 | /* careful about sign extension: top and bottom are uchars */ y = fi->top + (f->ascent-subf->ascent); if(y < 0) y = 0; c->top = y; y = fi->bottom + (f->ascent-subf->ascent); if(y < 0) y = 0; c->bottom = y; | |
| 1992/0209 | c->width = fi->width; c->left = fi->left; c->x = ci*f->width; c->xright = c->x + ((fi+1)->x - fi->x); rect.min.y = 0; rect.max.y = f->height; rect.min.x = c->x; | |
| 1992/0214 | rect.max.x = c->x+f->width; gbitblt(f->b, rect.min, f->b, rect, 0); | |
| 1992/0209 | rect.min.x = fi->x; rect.max.x = (fi+1)->x; | |
| 1992/0219 | rect.max.y = subf->height; | |
| 1992/0209 | gbitblt(f->b, Pt(c->x, f->ascent-subf->ascent), subf->bits, rect, S); } | |
| 1990/08101 | QLock bitlock; | |
| 1992/0209 | GBitmap* | |
| 1990/08101 | id2bit(int k) { | |
| 1990/0902 | GBitmap *bp; | |
| 1990/08101 | bp = &bit.map[k]; if(k<0 || k>=conf.nbitmap || bp->ldepth < 0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1990/08101 | return bp; } | |
| 1990/0327 | void bitcompact(void) { ulong *p1, *p2; | |
| 1990/08101 | qlock(&bitlock); | |
| 1990/0327 | p1 = p2 = bit.words; while(p2 < bit.wfree){ if(p2[1] == 0){ p2 += 2 + p2[0]; continue; } if(p1 != p2){ | |
| 1991/0318 | memmove(p1, p2, (2+p2[0])*sizeof(ulong)); | |
| 1990/0902 | ((GBitmap*)p1[1])->base = p1+2; | |
| 1990/0327 | } p2 += 2 + p1[0]; p1 += 2 + p1[0]; } bit.wfree = p1; | |
| 1990/08101 | qunlock(&bitlock); | |
| 1990/0329 | } void | |
| 1990/05313 | Cursortocursor(Cursor *c) | |
| 1990/0329 | { | |
| 1990/0504 | int i; | |
| 1991/0731 | uchar *p; | |
| 1990/0504 | lock(&cursor); | |
| 1991/0318 | memmove(&cursor, c, sizeof(Cursor)); | |
| 1990/0504 | for(i=0; i<16; i++){ | |
| 1991/0731 | p = (uchar*)&setbits[i]; *p = c->set[2*i]; *(p+1) = c->set[2*i+1]; p = (uchar*)&clrbits[i]; *p = c->clr[2*i]; *(p+1) = c->clr[2*i+1]; | |
| 1990/0504 | } unlock(&cursor); } void cursoron(int dolock) { if(dolock) lock(&cursor); if(cursor.visible++ == 0){ cursor.r.min = mouse.xy; cursor.r.max = add(mouse.xy, Pt(16, 16)); cursor.r = raddp(cursor.r, cursor.offset); | |
| 1991/1225 | gbitblt(&cursorback, Pt(0, 0), &gscreen, cursor.r, S); gbitblt(&gscreen, add(mouse.xy, cursor.offset), | |
| 1991/0706 | &clr, Rect(0, 0, 16, 16), flipping? flipD[D&~S] : D&~S); | |
| 1991/1225 | gbitblt(&gscreen, add(mouse.xy, cursor.offset), | |
| 1991/0706 | &set, Rect(0, 0, 16, 16), flipping? flipD[S|D] : S|D); | |
| 1990/0504 | } if(dolock) unlock(&cursor); } void cursoroff(int dolock) { if(dolock) lock(&cursor); if(--cursor.visible == 0) | |
| 1991/1225 | gbitblt(&gscreen, cursor.r.min, &cursorback, Rect(0, 0, 16, 16), S); | |
| 1990/0504 | if(dolock) unlock(&cursor); } void | |
| 1991/0706 | mousedelta(int b, int dx, int dy) /* called at higher priority */ | |
| 1990/0504 | { | |
| 1991/0706 | mouse.dx += dx; mouse.dy += dy; mouse.newbuttons = b; mouse.track = 1; } void mousebuttons(int b) /* called at higher priority */ { | |
| 1990/0505 | /* * It is possible if you click very fast and get bad luck * you could miss a button click (down up). Doesn't seem * likely or important enough to worry about. */ mouse.newbuttons = b; mouse.track = 1; /* aggressive but o.k. */ mouseclock(); | |
| 1990/0504 | } | |
| 1991/0707 | ||
| 1990/0504 | void | |
| 1991/0707 | mouseupdate(int dolock) | |
| 1990/0504 | { | |
| 1991/0706 | int x, y; | |
| 1991/0707 | if(!mouse.track || (dolock && !canlock(&cursor))) return; x = mouse.xy.x + mouse.dx; if(x < gscreen.r.min.x) x = gscreen.r.min.x; if(x >= gscreen.r.max.x) x = gscreen.r.max.x; y = mouse.xy.y + mouse.dy; if(y < gscreen.r.min.y) y = gscreen.r.min.y; if(y >= gscreen.r.max.y) y = gscreen.r.max.y; cursoroff(0); mouse.xy = Pt(x, y); cursoron(0); mouse.dx = 0; mouse.dy = 0; mouse.clock = 0; mouse.track = 0; mouse.buttons = mouse.newbuttons; mouse.changed = 1; if(dolock){ | |
| 1991/0423 | unlock(&cursor); wakeup(&mouse.r); } } | |
| 1991/0605 | int mouseputc(IOQ *q, int c) { | |
| 1991/0706 | static short msg[5]; static int nb; static uchar b[] = {0, 4, 2, 6, 1, 5, 3, 7}; | |
| 1991/0605 | ||
| 1991/1115 | USED(q); | |
| 1991/0706 | if((c&0xF0) == 0x80) nb=0; msg[nb] = c; if(c & 0x80) msg[nb] |= 0xFF00; /* sign extend */ if(++nb == 5){ mouse.newbuttons = b[(msg[0]&7)^7]; mouse.dx = msg[1]+msg[3]; mouse.dy = -(msg[2]+msg[4]); mouse.track = 1; mouseclock(); nb = 0; | |
| 1990/0329 | } | |
| 1992/0522 | return 0; | |
| 1990/0505 | } int mousechanged(void *m) { | |
| 1991/1115 | USED(m); | |
| 1990/0505 | return mouse.changed; | |
| 1990/0324 | } | |