| plan 9 kernel history: overview | file list | diff list |
1992/1112/port/devbit.c (diff list | history)
| port/devbit.c on 1990/0324 | ||
| 1990/0324 | #include "u.h" | |
| 1992/0321 | #include "../port/lib.h" | |
| 1992/1030 | #include <libg.h> #include <gnot.h> | |
| 1990/0324 | #include "mem.h" #include "dat.h" #include "fns.h" | |
| 1992/0111 | #include "../port/error.h" | |
| 1990/0324 | #include "devtab.h" | |
| 1991/0708 | #include "screen.h" | |
| 1990/0324 | ||
| 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 */ /* | |
| 1992/0622 | * Arena is a word containing N, followed by a pointer to the Arena, * followed by a pointer to the Bitmap, followed by N words. * The bitmap pointer is zero if block is free. | |
| 1992/0621 | * bit.map is an array of pointers to GBitmaps. The GBitmaps are * freed individually and their corresponding entries in bit.map are zeroed. * The index into bit.map is the Bitmap id as seen in libg. Subfonts and * fonts are handled similarly. | |
| 1990/0327 | */ | |
| 1990/0324 | ||
| 1992/0622 | typedef struct Arena Arena; struct Arena { ulong *words; /* storage */ ulong *wfree; /* pointer to next free word */ ulong nwords; /* total in arena */ int nbusy; /* number of busy blocks */ }; | |
| 1992/06271 | typedef struct BSubfont BSubfont; struct BSubfont { GSubfont; int ref; /* number of times this subfont is open */ ulong qid[2]; /* unique id used as a cache tag */ }; | |
| 1992/0912 | extern GSubfont *defont; BSubfont *bdefont; BSubfont bdefont0; | |
| 1990/05313 | struct { | |
| 1990/0324 | Ref; | |
| 1992/0622 | QLock; | |
| 1992/0621 | GBitmap **map; /* indexed array */ int nmap; /* number allocated */ GFont **font; /* indexed array */ int nfont; /* number allocated */ | |
| 1992/06271 | BSubfont**subfont; /* indexed array */ | |
| 1992/0621 | int nsubfont; /* number allocated */ | |
| 1992/0622 | Arena *arena; /* array */ int narena; /* number allocated */ | |
| 1992/0720 | int mouseopen; /* flag: mouse open */ | |
| 1992/0913 | int bitbltopen; /* flag: bitblt open */ | |
| 1992/0630 | int bid; /* last allocated bitmap id */ int subfid; /* last allocated subfont id */ int cacheid; /* last cached subfont id */ int fid; /* 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; | |
| 1992/0622 | #define DMAP 16 /* delta increase in size of arrays */ | |
| 1990/0327 | #define FREE 0x80000000 | |
| 1992/0622 | ||
| 1990/0327 | void bitcompact(void); | |
| 1992/0621 | int bitalloc(Rectangle, int); | |
| 1990/0902 | void bitfree(GBitmap*); | |
| 1992/0621 | void fontfree(GFont*); | |
| 1992/0702 | void subfontfree(BSubfont*, int); | |
| 1992/0622 | void arenafree(Arena*); | |
| 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; | |
| 1992/1020 | int mouseshifted; | |
| 1992/1021 | int mousetype; | |
| 1992/1106 | int islittle; | |
| 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, | |
| 1992/1020 | Qmousectl, | |
| 1990/0709 | Qscreen, | |
| 1990/0324 | }; Dirtab bitdir[]={ | |
| 1991/1112 | "bitblt", {Qbitblt}, 0, 0666, "mouse", {Qmouse}, 0, 0666, | |
| 1992/1020 | "mousectl", {Qmousectl}, 0, 0220, | |
| 1991/1112 | "screen", {Qscreen}, 0, 0444, | |
| 1990/0324 | }; #define NBIT (sizeof bitdir/sizeof(Dirtab)) | |
| 1992/06271 | #define NINFO 8192 /* max chars per subfont; sanity check only */ | |
| 1992/0622 | #define HDR 3 | |
| 1990/0324 | void | |
| 1992/1104 | lockedupdate(void) { qlock(&bit); if(waserror()){ qunlock(&bit); return; } screenupdate(); qunlock(&bit); poperror(); } void | |
| 1992/0706 | bitfreeup(void) { int i; BSubfont *s; /* free unused subfonts and compact */ for(i=0; i<bit.nsubfont; i++){ s = bit.subfont[i]; | |
| 1992/0912 | if(s && s!=bdefont && s->ref==0){ | |
| 1992/0706 | s->ref = 1; s->qid[0] = ~0; /* force cleanup */ subfontfree(s, i); } } bitcompact(); } void* bitmalloc(ulong n) { void *p; p = malloc(n); if(p) return p; bitfreeup(); return malloc(n); } void | |
| 1992/0704 | bitdebug(void) { int i; long l; Arena *a; l = 0; for(i=0; i<bit.narena; i++){ a = &bit.arena[i]; if(a->words){ l += a->nwords; | |
| 1992/0820 | print("%d: %ld bytes used; %ld total\n", i, | |
| 1992/0704 | (a->wfree-a->words)*sizeof(ulong), a->nwords*sizeof(ulong)); } } | |
| 1992/0820 | print("arena: %ld bytes\n", l*sizeof(ulong)); | |
| 1992/0704 | l = 0; for(i=0; i<bit.nmap; i++) if(bit.map[i]) l++; print("%d bitmaps ", l); l = 0; for(i=0; i<bit.nfont; i++) if(bit.font[i]) l++; print("%d fonts ", l); l = 0; for(i=0; i<bit.nsubfont; i++) if(bit.subfont[i]){ print("%d: %lux %lux ", i, bit.subfont[i]->qid[0], bit.subfont[i]->qid[1]); l++; } print("%d subfonts\n", l); } void | |
| 1990/0324 | bitreset(void) { | |
| 1992/0711 | int ws; | |
| 1991/0706 | ulong r; | |
| 1992/0622 | Arena *a; | |
| 1990/0327 | ||
| 1992/0807 | if(!conf.monitor) return; | |
| 1992/0914 | memmove(&bdefont0, defont, sizeof(*defont)); bdefont = &bdefont0; | |
| 1992/0621 | bit.map = smalloc(DMAP*sizeof(GBitmap*)); bit.nmap = DMAP; | |
| 1991/0706 | getcolor(0, &r, &r, &r); if(r == 0) flipping = 1; | |
| 1992/0630 | bit.bid = -1; bit.subfid = -1; bit.fid = -1; bit.cacheid = -1; | |
| 1992/0621 | bit.font = smalloc(DMAP*sizeof(GFont*)); bit.nfont = DMAP; | |
| 1992/06271 | bit.subfont = smalloc(DMAP*sizeof(BSubfont*)); | |
| 1992/0621 | bit.nsubfont = DMAP; | |
| 1992/0622 | bit.arena = smalloc(DMAP*sizeof(Arena)); bit.narena = DMAP; a = &bit.arena[0]; /* * Somewhat of a heuristic: start with three screensful and * allocate single screensful dynamically if needed. */ | |
| 1992/0706 | ws = BI2WD>>gscreen.ldepth; /* pixels per word */ a->nwords = 3*(HDR + gscreen.r.max.y*gscreen.r.max.x/ws); | |
| 1992/0622 | a->words = xalloc(a->nwords*sizeof(ulong)); | |
| 1992/0706 | if(a->words == 0){ /* try again */ print("bitreset: allocating only 1 screenful\n"); a->nwords /= 3; a->words = a->words = xalloc(a->nwords*sizeof(ulong)); if(a->words == 0) panic("bitreset"); } | |
| 1992/0622 | a->wfree = a->words; a->nbusy = 1; /* keep 0th arena from being freed */ | |
| 1990/05313 | Cursortocursor(&arrow); | |
| 1990/0324 | } | |
| 1992/1112 | /* * screen bit depth changed, reset backup map for cursor */ void bitdepth(void) { cursoroff(1); if(gscreen.ldepth > 3) cursorback.ldepth = 0; else{ cursorback.ldepth = gscreen.ldepth; cursorback.width = ((16 << gscreen.ldepth) + 31) >> 5; } cursoron(1); } | |
| 1990/0324 | void bitinit(void) { | |
| 1992/0807 | if(!conf.monitor) return; | |
| 1991/0706 | if(gscreen.ldepth > 3) cursorback.ldepth = 0; | |
| 1992/0621 | else{ | |
| 1991/0706 | cursorback.ldepth = gscreen.ldepth; cursorback.width = ((16 << gscreen.ldepth) + 31) >> 5; } | |
| 1990/0504 | cursoron(1); | |
| 1990/0324 | } Chan* bitattach(char *spec) { | |
| 1992/0807 | if(!conf.monitor) error(Egreg); | |
| 1990/0324 | return devattach('b', spec); } Chan* bitclone(Chan *c, Chan *nc) { | |
| 1992/0807 | if(!conf.monitor) error(Egreg); | |
| 1990/0324 | 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) { | |
| 1992/0807 | if(!conf.monitor) error(Egreg); | |
| 1990/0324 | return devwalk(c, name, bitdir, NBIT, devgen); } void bitstat(Chan *c, char *db) { | |
| 1992/0807 | if(!conf.monitor) error(Egreg); | |
| 1990/0324 | devstat(c, db, bitdir, NBIT, devgen); } | |
| 1992/0621 | Chan* | |
| 1990/0324 | bitopen(Chan *c, int omode) { | |
| 1992/0621 | GBitmap *b; | |
| 1992/0807 | if(!conf.monitor) error(Egreg); | |
| 1992/0720 | switch(c->qid.path){ case CHDIR: | |
| 1990/0324 | if(omode != OREAD) | |
| 1990/11211 | error(Eperm); | |
| 1992/0720 | break; case Qmouse: | |
| 1990/0324 | lock(&bit); | |
| 1992/0720 | if(bit.mouseopen){ unlock(&bit); error(Einuse); } bit.mouseopen = 1; bit.ref++; unlock(&bit); break; case Qbitblt: lock(&bit); | |
| 1992/0913 | if(bit.bitbltopen || bit.mouseopen){ | |
| 1990/0324 | unlock(&bit); | |
| 1990/11211 | error(Einuse); | |
| 1990/0324 | } | |
| 1992/0621 | b = smalloc(sizeof(GBitmap)); *b = gscreen; bit.map[0] = b; /* bitmap 0 is screen */ | |
| 1992/0912 | bit.subfont[0] = bdefont; /* subfont 0 is default */ | |
| 1992/06271 | bit.subfont[0]->ref = 1; bit.subfont[0]->qid[0] = 0; bit.subfont[0]->qid[1] = 0; | |
| 1992/0630 | bit.bid = -1; bit.fid = -1; bit.subfid = -1; bit.cacheid = -1; | |
| 1990/0613 | bit.rid = -1; | |
| 1991/0706 | bit.mid = -1; | |
| 1990/0604 | bit.init = 0; | |
| 1992/0913 | bit.bitbltopen = 1; | |
| 1990/05313 | Cursortocursor(&arrow); | |
| 1990/0324 | unlock(&bit); | |
| 1992/0720 | break; default: | |
| 1990/0324 | incref(&bit); | |
| 1992/0720 | } | |
| 1990/0324 | c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } void bitcreate(Chan *c, char *name, int omode, ulong perm) { | |
| 1992/0807 | if(!conf.monitor) error(Egreg); | |
| 1991/1115 | USED(c, name, omode, perm); | |
| 1990/11211 | error(Eperm); | |
| 1990/0324 | } void bitremove(Chan *c) { | |
| 1992/0807 | if(!conf.monitor) error(Egreg); | |
| 1991/1115 | USED(c); | |
| 1990/11211 | error(Eperm); | |
| 1990/0324 | } void bitwstat(Chan *c, char *db) { | |
| 1992/0807 | if(!conf.monitor) error(Egreg); | |
| 1991/1115 | USED(c, db); | |
| 1990/11211 | error(Eperm); | |
| 1990/0324 | } void bitclose(Chan *c) { | |
| 1992/0621 | GBitmap *b, **bp, **ebp; | |
| 1992/06271 | BSubfont *s, **sp, **esp; | |
| 1992/0621 | GFont *f, **fp, **efp; | |
| 1990/0327 | ||
| 1992/0807 | if(!conf.monitor) error(Egreg); | |
| 1990/11211 | if(c->qid.path!=CHDIR && (c->flag&COPEN)){ | |
| 1990/0329 | lock(&bit); | |
| 1992/0720 | if(c->qid.path == Qmouse) bit.mouseopen = 0; | |
| 1992/0913 | if(c->qid.path == Qbitblt) bit.bitbltopen = 0; | |
| 1990/0327 | if(--bit.ref == 0){ | |
| 1992/0621 | ebp = &bit.map[bit.nmap]; | |
| 1992/0630 | for(bp = bit.map; bp<ebp; bp++){ | |
| 1992/0621 | b = *bp; if(b){ bitfree(b); *bp = 0; } | |
| 1992/0209 | } | |
| 1992/0621 | esp = &bit.subfont[bit.nsubfont]; | |
| 1992/0630 | for(sp=bit.subfont; sp<esp; sp++){ | |
| 1992/0621 | s = *sp; | |
| 1992/0628 | if(s) | |
| 1992/0702 | subfontfree(s, sp-bit.subfont); | |
| 1992/0630 | /* don't clear *sp: cached */ | |
| 1992/0621 | } efp = &bit.font[bit.nfont]; for(fp=bit.font; fp<efp; fp++){ f = *fp; if(f){ fontfree(f); *fp = 0; } } | |
| 1990/0327 | } | |
| 1990/0324 | unlock(&bit); } } 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; | |
| 1992/0816 | ulong l, nw, ws, rv, gv, bv; | |
| 1992/0627 | int off, j; | |
| 1990/06231 | Fontchar *i; | |
| 1990/0902 | GBitmap *src; | |
| 1992/0628 | BSubfont *s; | |
| 1990/0327 | ||
| 1992/0807 | if(!conf.monitor) error(Egreg); | |
| 1990/11211 | if(c->qid.path & CHDIR) | |
| 1990/0324 | return devdirread(c, va, n, bitdir, NBIT, devgen); | |
| 1992/0622 | if(c->qid.path == Qmouse){ | |
| 1990/0329 | /* | |
| 1990/0505 | * mouse: * 'm' 1 * buttons 1 * point 8 | |
| 1992/06271 | * msec 4 | |
| 1990/0329 | */ | |
| 1992/06271 | if(n < 14) | |
| 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; | |
| 1992/0630 | BPLONG(p+2, mouse.xy.x); BPLONG(p+6, mouse.xy.y); BPLONG(p+10, TK2MS(MACHP(0)->ticks)); | |
| 1990/0505 | mouse.changed = 0; unlock(&cursor); | |
| 1992/06271 | return 14; | |
| 1992/0622 | } if(c->qid.path == 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); | |
| 1992/0622 | return 5*12; | |
| 1990/0709 | } | |
| 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)); | |
| 1992/0816 | memmove(p, q, l); if(flipping) /* is screen, so must be word aligned */ for(x=0; x<l; x+=sizeof(ulong),p+=sizeof(ulong)) *(ulong*)p ^= ~0; else p += l; | |
| 1990/0709 | n += l; } | |
| 1992/0622 | return n; } if(c->qid.path != Qbitblt) | |
| 1990/11211 | error(Egreg); | |
| 1992/0622 | qlock(&bit); if(waserror()){ qunlock(&bit); nexterror(); | |
| 1990/0327 | } | |
| 1992/0622 | p = va; /* * Fuss about and figure out what to say. */ if(bit.init){ /* * init: * 'I' 1 * ldepth 1 * rectangle 16 | |
| 1992/0627 | * clip rectangle 16 | |
| 1992/0622 | * font info 3*12 | |
| 1992/0912 | * fontchars 6*(bdefont->n+1) | |
| 1992/0622 | */ | |
| 1992/0627 | if(n < 34) | |
| 1992/0622 | error(Ebadblt); p[0] = 'I'; p[1] = gscreen.ldepth; | |
| 1992/0630 | BPLONG(p+2, gscreen.r.min.x); BPLONG(p+6, gscreen.r.min.y); BPLONG(p+10, gscreen.r.max.x); BPLONG(p+14, gscreen.r.max.y); BPLONG(p+18, gscreen.clipr.min.x); BPLONG(p+22, gscreen.clipr.min.y); BPLONG(p+26, gscreen.clipr.max.x); BPLONG(p+30, gscreen.clipr.max.y); | |
| 1992/0912 | if(n >= 34+3*12+6*(bdefont->n+1)){ | |
| 1992/0627 | p += 34; | |
| 1992/0912 | sprint((char*)p, "%11d %11d %11d ", bdefont->n, bdefont->height, bdefont->ascent); | |
| 1992/0622 | p += 3*12; | |
| 1992/0912 | for(i=bdefont->info,j=0; j<=bdefont->n; j++,i++,p+=6){ | |
| 1992/0630 | BPSHORT(p, i->x); | |
| 1992/0622 | p[2] = i->top; p[3] = i->bottom; p[4] = i->left; p[5] = i->width; } | |
| 1992/0912 | n = 34+3*12+6*(bdefont->n+1); | |
| 1992/0622 | }else | |
| 1992/0627 | n = 34; | |
| 1992/0622 | bit.init = 0; | |
| 1992/0630 | }else if(bit.bid > 0){ | |
| 1992/0622 | /* * allocate: * 'A' 1 * bitmap id 2 */ if(n < 3) error(Ebadblt); | |
| 1992/0630 | if(bit.bid<0 || bit.map[bit.bid]==0) error(Ebadbitmap); | |
| 1992/0622 | p[0] = 'A'; | |
| 1992/0630 | BPSHORT(p+1, bit.bid); bit.bid = -1; | |
| 1992/0622 | n = 3; | |
| 1992/0630 | }else if(bit.subfid > 0){ | |
| 1992/0622 | /* * allocate subfont: * 'K' 1 * subfont id 2 */ | |
| 1992/0630 | if(n<3 || bit.subfid<0) | |
| 1992/0622 | error(Ebadblt); | |
| 1992/0630 | s = bit.subfont[bit.subfid]; if(s==0 || s->ref==0) error(Ebadfont); | |
| 1992/0622 | p[0] = 'K'; | |
| 1992/0630 | BPSHORT(p+1, bit.subfid); bit.subfid = -1; | |
| 1992/0622 | n = 3; | |
| 1992/0630 | }else if(bit.cacheid >= 0){ | |
| 1992/0628 | /* | |
| 1992/0811 | * check cache for subfont: | |
| 1992/0628 | * 'J' 1 * subfont id 2 * font info 3*12 * fontchars 6*(subfont->n+1) */ p[0] = 'J'; | |
| 1992/0702 | if(bit.cacheid < 0) | |
| 1992/0630 | error(Ebadfont); s = bit.subfont[bit.cacheid]; if(s==0 || s->ref==0) error(Ebadfont); if(n < 3+3*12+6*(s->n+1)) | |
| 1992/0628 | error(Ebadblt); | |
| 1992/0630 | BPSHORT(p+1, bit.cacheid); | |
| 1992/0628 | p += 3; | |
| 1992/0630 | sprint((char*)p, "%11d %11d %11d ", s->n, s->height, s->ascent); | |
| 1992/0628 | p += 3*12; for(i=s->info,j=0; j<=s->n; j++,i++,p+=6){ | |
| 1992/0630 | BPSHORT(p, i->x); | |
| 1992/0628 | p[2] = i->top; p[3] = i->bottom; p[4] = i->left; p[5] = i->width; } n = 3+3*12+6*(s->n+1); | |
| 1992/0630 | bit.cacheid = -1; }else if(bit.fid >= 0){ | |
| 1992/0622 | /* * allocate font: * 'N' 1 * font id 2 */ if(n < 3) error(Ebadblt); | |
| 1992/0630 | if(bit.fid<0 || bit.font[bit.fid]==0) error(Ebadfont); | |
| 1992/0622 | p[0] = 'N'; | |
| 1992/0630 | BPSHORT(p+1, bit.fid); bit.fid = -1; | |
| 1992/0622 | n = 3; }else if(bit.mid >= 0){ /* * read colormap: * data 12*(2**bitmapdepth) */ src = bit.map[bit.mid]; if(src == 0) error(Ebadbitmap); l = (1<<src->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; } | |
| 1992/0630 | BPLONG(p, rv); BPLONG(p+4, gv); BPLONG(p+8, bv); | |
| 1992/0622 | p += 12; } bit.mid = -1; n = 12*nw; }else if(bit.rid >= 0){ /* * read bitmap: * data bytewidth*(maxy-miny) */ src = bit.map[bit.rid]; if(src == 0) error(Ebadbitmap); 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) error(Ebadblt); 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)) error(Ebadblt); if(off) cursoroff(1); n = 0; p = va; for(y=miny; y<maxy; y++){ q = (uchar*)gaddr(src, Pt(src->r.min.x, y)); q += (src->r.min.x&((sizeof(ulong))*ws-1))/ws; | |
| 1992/0816 | memmove(p, q, l); | |
| 1992/1106 | if(islittle) bitreverse(p, l); | |
| 1992/0816 | if(bit.rid==0 && flipping) /* is screen, so must be word aligned */ for(x=0; x<l; x+=sizeof(ulong),p+=sizeof(ulong)) *(ulong*)p ^= ~0; | |
| 1992/0622 | else | |
| 1992/0816 | p += l; | |
| 1992/0622 | n += l; } if(off) cursoron(1); bit.rid = -1; } | |
| 1990/0327 | ||
| 1992/0622 | poperror(); qunlock(&bit); | |
| 1990/0327 | return n; | |
| 1990/0324 | } | |
| 1992/1013 | Point bitstrsize(GFont *f, uchar *p, int l) { ushort r; Point s = {0,0}; GCacheinfo *c; while(l > 0){ r = BGSHORT(p); p += 2; l -= 2; if(r >= f->ncache) continue; c = &f->cache[r]; if(c->bottom > s.y) s.y = c->bottom; s.x += c->width; } return s; } | |
| 1990/0324 | long | |
| 1991/0411 | bitwrite(Chan *c, void *va, long n, ulong offset) | |
| 1990/0324 | { | |
| 1992/0816 | uchar *p, *q, *oq; | |
| 1992/0711 | long m, v, miny, maxy, t, x, y; | |
| 1992/0628 | ulong l, nw, ws, rv, q0, q1; | |
| 1992/0816 | ulong *lp; | |
| 1992/0621 | int off, isoff, i, j, ok; | |
| 1992/1107 | ulong *endscreen = gaddr(&gscreen, Pt(0, gscreen.r.max.y)); | |
| 1990/06111 | Point pt, pt1, pt2; | |
| 1990/0324 | Rectangle rect; | |
| 1990/05313 | Cursor curs; | |
| 1991/0706 | Fcode fc; | |
| 1990/0623 | Fontchar *fcp; | |
| 1992/0711 | GBitmap *src, *dst; | |
| 1992/0702 | BSubfont *f, *tf, **fp; | |
| 1992/0621 | GFont *ff, **ffp; | |
| 1992/0706 | GCacheinfo *gc; | |
| 1992/1020 | char buf[64]; | |
| 1990/0324 | ||
| 1992/0807 | if(!conf.monitor) error(Egreg); | |
| 1992/0711 | USED(offset); | |
| 1990/11211 | if(c->qid.path == CHDIR) error(Eisdir); | |
| 1990/0324 | ||
| 1992/1020 | if(c->qid.path == Qmousectl){ if(n >= sizeof(buf)) n = sizeof(buf)-1; strncpy(buf, va, n); buf[n] = 0; mousectl(buf); return n; } | |
| 1990/11211 | if(c->qid.path != Qbitblt) error(Egreg); | |
| 1990/0327 | ||
| 1990/0721 | isoff = 0; | |
| 1992/0622 | qlock(&bit); | |
| 1990/0721 | if(waserror()){ | |
| 1992/0622 | qunlock(&bit); | |
| 1990/0721 | if(isoff) cursoron(1); nexterror(); } | |
| 1990/0324 | p = va; m = n; | |
| 1992/0621 | SET(src, dst, f, ff); | |
| 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); | |
| 1992/0630 | rect.min.x = BGLONG(p+2); rect.min.y = BGLONG(p+6); rect.max.x = BGLONG(p+10); rect.max.y = BGLONG(p+14); | |
| 1991/0423 | if(Dx(rect) < 0 || Dy(rect) < 0) error(Ebadblt); | |
| 1992/0630 | bit.bid = bitalloc(rect, v); | |
| 1990/0327 | 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); | |
| 1992/0630 | fc = BGSHORT(p+29) & 0xF; v = BGSHORT(p+11); | |
| 1992/0621 | if(v<0 || v>=bit.nmap || (src=bit.map[v])==0) | |
| 1991/0706 | error(Ebadbitmap); off = 0; if(v == 0){ if(flipping) fc = flipS[fc]; off = 1; } | |
| 1992/0630 | v = BGSHORT(p+1); | |
| 1992/0621 | if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1991/0706 | if(v == 0){ if(flipping) fc = flipD[fc]; | |
| 1990/0504 | off = 1; | |
| 1991/0706 | } | |
| 1992/0630 | pt.x = BGLONG(p+3); pt.y = BGLONG(p+7); rect.min.x = BGLONG(p+13); rect.min.y = BGLONG(p+17); rect.max.x = BGLONG(p+21); rect.max.y = BGLONG(p+25); | |
| 1990/0721 | if(off && !isoff){ | |
| 1990/0504 | cursoroff(1); | |
| 1990/0721 | isoff = 1; } | |
| 1991/1225 | gbitblt(dst, pt, src, rect, fc); | |
| 1992/1104 | if(dst->base < endscreen) | |
| 1992/1013 | mbbrect(Rpt(pt, add(pt, sub(rect.max, rect.min)))); | |
| 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; } | |
| 1992/1107 | if(m == 2){ if(p[1]){ /* make damn sure */ cursor.disable = 0; isoff = 1; }else{ cursoroff(1); cursor.disable = 1; } m -= 2; p += 2; break; } | |
| 1990/05313 | if(m < 73) | |
| 1990/11211 | error(Ebadblt); | |
| 1992/0630 | curs.offset.x = BGLONG(p+1); curs.offset.y = BGLONG(p+5); | |
| 1991/0318 | memmove(curs.clr, p+9, 2*16); memmove(curs.set, p+41, 2*16); | |
| 1992/1106 | if(islittle){ bitreverse(curs.clr, 2*16); bitreverse(curs.set, 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); | |
| 1992/0630 | v = BGSHORT(p+1); | |
| 1992/0621 | if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1990/0327 | bitfree(dst); | |
| 1992/0621 | bit.map[v] = 0; | |
| 1990/0327 | m -= 3; p += 3; | |
| 1990/0604 | break; | |
| 1990/0623 | case 'g': /* | |
| 1992/0628 | * free subfont | |
| 1990/0623 | * 'g' 1 * id 2 */ if(m < 3) | |
| 1990/11211 | error(Ebadblt); | |
| 1992/0630 | v = BGSHORT(p+1); | |
| 1992/0628 | if(v<0 || v>=bit.nsubfont || (f=bit.subfont[v])==0 || f->ref==0) | |
| 1990/11211 | error(Ebadfont); | |
| 1992/0702 | subfontfree(f, v); | |
| 1990/0623 | m -= 3; p += 3; break; | |
| 1992/0209 | case 'h': /* * free font * 'h' 1 * id 2 */ if(m < 3) error(Ebadblt); | |
| 1992/0630 | v = BGSHORT(p+1); | |
| 1992/0621 | if(v<0 || v>=bit.nfont || (ff=bit.font[v])==0) | |
| 1992/0209 | error(Ebadfont); | |
| 1992/0621 | fontfree(ff); bit.font[v] = 0; | |
| 1992/0209 | m -= 3; p += 3; break; | |
| 1990/0604 | case 'i': /* * init * | |
| 1992/0627 | * 'i' 1 | |
| 1990/0604 | */ | |
| 1992/0627 | bit.init = 1; | |
| 1990/0604 | m -= 1; p += 1; | |
| 1990/0327 | break; | |
| 1990/0329 | ||
| 1992/06271 | case 'j': /* | |
| 1992/0628 | * subfont cache check | |
| 1992/06271 | * * 'j' 1 | |
| 1992/0702 | * qid 8 | |
| 1992/06271 | */ | |
| 1992/0628 | if(m < 9) error(Ebadblt); | |
| 1992/0630 | q0 = BGLONG(p+1); q1 = BGLONG(p+5); | |
| 1992/0629 | i = 0; if(q0 != ~0) for(; i<bit.nsubfont; i++){ f = bit.subfont[i]; if(f && f->qid[0]==q0 && f->qid[1]==q1) goto sfcachefound; } | |
| 1992/0628 | error(Esfnotcached); sfcachefound: f->ref++; | |
| 1992/0630 | bit.cacheid = i; | |
| 1992/06271 | m -= 9; p += 9; break; | |
| 1990/0623 | case 'k': /* | |
| 1992/0209 | * allocate subfont | |
| 1990/0623 | * 'k' 1 * n 2 * height 1 * ascent 1 * bitmap id 2 | |
| 1992/06271 | * qid 8 | |
| 1990/0707 | * fontchars 6*(n+1) | |
| 1990/0623 | * next read returns allocated font id */ | |
| 1992/06271 | if(m < 15) | |
| 1990/11211 | error(Ebadblt); | |
| 1992/0630 | v = BGSHORT(p+1); | |
| 1992/06271 | if(v<0 || v>NINFO || m<15+6*(v+1)) | |
| 1990/11211 | error(Ebadblt); | |
| 1992/0621 | for(i=1; i<bit.nsubfont; i++) if(bit.subfont[i] == 0) | |
| 1992/0209 | goto subfontfound; | |
| 1992/0706 | fp = bitmalloc((bit.nsubfont+DMAP)*sizeof(BSubfont*)); if(fp == 0) error(Enomem); memmove(fp, bit.subfont, bit.nsubfont*sizeof(BSubfont*)); free(bit.subfont); bit.subfont = fp; | |
| 1992/0621 | bit.nsubfont += DMAP; | |
| 1992/0209 | subfontfound: | |
| 1992/0706 | f = bitmalloc(sizeof(BSubfont)); if(f == 0) error(Enomem); f->info = bitmalloc((v+1)*sizeof(Fontchar)); if(f->info == 0){ free(f); error(Enomem); } | |
| 1992/1026 | bit.subfont[i] = f; | |
| 1990/0623 | f->n = v; f->height = p[3]; f->ascent = p[4]; | |
| 1992/0630 | f->qid[0] = BGLONG(p+7); f->qid[1] = BGLONG(p+11); | |
| 1992/0702 | /* check to see if already there, uncache if so */ for(j=0; j<bit.nsubfont; j++){ if(j == i) continue; tf = bit.subfont[j]; | |
| 1992/0704 | if(tf && tf->qid[0]==f->qid[0] && tf->qid[1]==f->qid[1]){ | |
| 1992/0702 | f->qid[0] = ~0; /* uncached */ | |
| 1992/0704 | break; } | |
| 1992/0702 | } | |
| 1992/0628 | f->ref = 1; | |
| 1992/0630 | v = BGSHORT(p+5); | |
| 1992/0621 | if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1992/06271 | f->bits = dst; bit.map[v] = 0; /* subfont now owns bitmap */ m -= 15; p += 15; | |
| 1990/0623 | fcp = f->info; | |
| 1992/0621 | for(j=0; j<=f->n; j++,fcp++){ | |
| 1992/0630 | fcp->x = BGSHORT(p); | |
| 1990/0623 | 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/0630 | bit.subfid = i; | |
| 1990/0623 | 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); | |
| 1992/0630 | v = BGSHORT(p+1); | |
| 1992/0621 | if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1990/06111 | off = 0; | |
| 1992/0630 | fc = BGSHORT(p+20) & 0xF; | |
| 1991/0706 | if(v == 0){ if(flipping) fc = flipD[fc]; | |
| 1990/06111 | off = 1; | |
| 1991/0706 | } | |
| 1992/0630 | pt1.x = BGLONG(p+3); pt1.y = BGLONG(p+7); pt2.x = BGLONG(p+11); pt2.y = BGLONG(p+15); | |
| 1990/06111 | t = p[19]; | |
| 1990/0721 | if(off && !isoff){ | |
| 1990/06111 | cursoroff(1); | |
| 1990/0721 | isoff = 1; } | |
| 1991/0706 | gsegment(dst, pt1, pt2, t, fc); | |
| 1992/1107 | if(dst->base < endscreen){ | |
| 1992/1013 | mbbpt(pt1); mbbpt(pt2); } | |
| 1990/06111 | m -= 22; p += 22; | |
| 1990/0613 | break; | |
| 1991/0706 | case 'm': /* * read colormap * * 'm' 1 * id 2 */ if(m < 3) error(Ebadblt); | |
| 1992/0630 | v = BGSHORT(p+1); | |
| 1992/0621 | if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) | |
| 1991/0706 | error(Ebadbitmap); bit.mid = v; m -= 3; p += 3; break; | |
| 1992/0209 | case 'n': /* * allocate font * 'n' 1 * height 1 * ascent 1 * ldepth 2 | |
| 1992/0627 | * ncache 2 | |
| 1992/0209 | * next read returns allocated font id */ | |
| 1992/0627 | if(m < 7) | |
| 1992/0209 | error(Ebadblt); | |
| 1992/0630 | v = BGSHORT(p+3); t = BGSHORT(p+5); | |
| 1992/0627 | if(v<0 || t<0) | |
| 1992/0209 | error(Ebadblt); | |
| 1992/0621 | for(i=0; i<bit.nfont; i++) if(bit.font[i] == 0) | |
| 1992/0209 | goto fontfound; | |
| 1992/0706 | ffp = bitmalloc((bit.nfont+DMAP)*sizeof(GFont*)); if(ffp == 0) error(Enomem); memmove(ffp, bit.font, bit.nfont*sizeof(GFont*)); free(bit.font); bit.font = ffp; | |
| 1992/0621 | bit.nfont += DMAP; | |
| 1992/0209 | fontfound: | |
| 1992/0706 | ff = bitmalloc(sizeof(GFont)); if(ff == 0) error(Enomem); | |
| 1992/0627 | ff->ncache = t; | |
| 1992/0706 | ff->cache = bitmalloc(t*sizeof(GCacheinfo)); if(ff->cache == 0){ free(ff); error(Enomem); } | |
| 1992/0621 | bit.font[i] = ff; ff = bit.font[i]; | |
| 1992/0209 | ff->height = p[1]; ff->ascent = p[2]; ff->ldepth = v; ff->width = 0; ff->b = 0; | |
| 1992/0627 | m -= 7; p += 7; | |
| 1992/0630 | bit.fid = i; | |
| 1992/0209 | break; | |
| 1990/0722 | case 'p': /* * point * * 'p' 1 * id 2 * pt 8 * value 1 * code 2 */ if(m < 14) | |
| 1990/11211 | error(Ebadblt); | |
| 1992/0630 | v = BGSHORT(p+1); | |
| 1992/0621 | if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1990/0722 | off = 0; | |
| 1992/0630 | fc = BGSHORT(p+12) & 0xF; | |
| 1991/0706 | if(v == 0){ if(flipping) fc = flipD[fc]; | |
| 1990/0722 | off = 1; | |
| 1991/0706 | } | |
| 1992/0630 | pt1.x = BGLONG(p+3); pt1.y = BGLONG(p+7); | |
| 1990/0722 | t = p[11]; if(off && !isoff){ cursoroff(1); isoff = 1; } | |
| 1991/0706 | gpoint(dst, pt1, t, fc); | |
| 1992/1104 | if(dst->base < endscreen) | |
| 1992/1013 | mbbpt(pt1); | |
| 1990/0722 | m -= 14; p += 14; break; | |
| 1992/0604 | case 'q': /* * clip rectangle * 'q' 1 * id 2 * rect 16 */ if(m < 19) error(Ebadblt); | |
| 1992/0630 | v = BGSHORT(p+1); | |
| 1992/0621 | if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) | |
| 1992/0604 | error(Ebadbitmap); | |
| 1992/0630 | rect.min.x = BGLONG(p+3); rect.min.y = BGLONG(p+7); rect.max.x = BGLONG(p+11); rect.max.y = BGLONG(p+15); | |
| 1992/0604 | 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); | |
| 1992/0630 | v = BGSHORT(p+1); | |
| 1992/0621 | if(v<0 || v>=bit.nmap || (src=bit.map[v])==0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1992/0630 | miny = BGLONG(p+3); maxy = BGLONG(p+7); | |
| 1990/0613 | 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; | |
| 1992/0627 | case 's': | |
| 1990/0329 | /* | |
| 1992/0209 | * string | |
| 1992/0627 | * 's' 1 | |
| 1992/0209 | * id 2 * pt 8 * font id 2 * code 2 * n 2 | |
| 1992/0627 | * cache indices 2*n (not null terminated) | |
| 1992/0209 | */ if(m < 17) error(Ebadblt); | |
| 1992/0630 | v = BGSHORT(p+1); | |
| 1992/0621 | if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) | |
| 1992/0209 | error(Ebadbitmap); off = 0; | |
| 1992/0630 | fc = BGSHORT(p+13) & 0xF; | |
| 1992/0209 | if(v == 0){ if(flipping) fc = flipD[fc]; off = 1; } | |
| 1992/0630 | pt.x = BGLONG(p+3); pt.y = BGLONG(p+7); v = BGSHORT(p+11); | |
| 1992/0621 | if(v<0 || v>=bit.nfont || (ff=bit.font[v])==0) | |
| 1992/0912 | error(Ebadfont); | |
| 1992/0630 | l = BGSHORT(p+15)*2; | |
| 1992/0209 | p += 17; m -= 17; if(l > m) error(Ebadblt); if(off && !isoff){ cursoroff(1); isoff = 1; } bitstring(dst, pt, ff, p, l, fc); | |
| 1992/1104 | if(dst->base < endscreen) | |
| 1992/1013 | mbbrect(Rpt(pt, add(pt, bitstrsize(ff, p, l)))); | |
| 1992/0209 | m -= l; p += l; break; | |
| 1992/0627 | case 't': /* * texture * 't' 1 * dst id 2 * rect 16 * src id 2 * fcode 2 */ if(m < 23) error(Ebadblt); | |
| 1992/0630 | v = BGSHORT(p+1); | |
| 1992/0627 | if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) error(Ebadbitmap); off = 0; | |
| 1992/0630 | fc = BGSHORT(p+21) & 0xF; | |
| 1992/0627 | if(v == 0){ if(flipping) fc = flipD[fc]; off = 1; } | |
| 1992/0630 | rect.min.x = BGLONG(p+3); rect.min.y = BGLONG(p+7); rect.max.x = BGLONG(p+11); rect.max.y = BGLONG(p+15); v = BGSHORT(p+19); | |
| 1992/0627 | if(v<0 || v>=bit.nmap || (src=bit.map[v])==0) error(Ebadbitmap); if(off && !isoff){ cursoroff(1); isoff = 1; } gtexture(dst, rect, src, fc); | |
| 1992/1104 | if(dst->base < endscreen) | |
| 1992/1013 | mbbrect(rect); | |
| 1992/0627 | m -= 23; p += 23; break; | |
| 1992/0209 | case 'v': /* | |
| 1992/0704 | * clear font cache and bitmap. * if error, font is unchanged. | |
| 1992/0209 | * 'v' 1 * id 2 | |
| 1992/06271 | * ncache 2 | |
| 1992/0209 | * width 2 */ | |
| 1992/06271 | if(m < 7) | |
| 1992/0209 | error(Ebadblt); | |
| 1992/0630 | v = BGSHORT(p+1); t = BGSHORT(p+3); | |
| 1992/06271 | if(t<0 || v<0 || v>=bit.nfont || (ff=bit.font[v])==0) | |
| 1992/0209 | error(Ebadblt); | |
| 1992/0704 | x = BGSHORT(p+5); i = bitalloc(Rect(0, 0, t*x, ff->height), ff->ldepth); | |
| 1992/0706 | if(t != ff->ncache){ gc = bitmalloc(t*sizeof(ff->cache[0])); if(gc == 0){ bitfree(bit.map[i]); bit.map[i] = 0; error(Enomem); } free(ff->cache); ff->cache = gc; ff->ncache = t; }else{ /* * memset not necessary but helps avoid * confusion if the cache is mishandled by the * user. */ memset(ff->cache, 0, t*sizeof(ff->cache[0])); } | |
| 1992/0704 | if(ff->b) bitfree(ff->b); ff->b = bit.map[i]; bit.map[i] = 0; /* disconnect it from GBitmap space */ ff->width = x; | |
| 1992/06271 | p += 7; m -= 7; | |
| 1992/0209 | 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); | |
| 1992/0630 | v = BGSHORT(p+1); | |
| 1992/0621 | if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) | |
| 1990/11211 | error(Ebadbitmap); | |
| 1990/0504 | off = 0; if(v == 0) off = 1; | |
| 1992/0630 | miny = BGLONG(p+3); maxy = BGLONG(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; } | |
| 1992/1104 | if(dst->base < endscreen) | |
| 1992/1013 | mbbrect(Rect(dst->r.min.x, miny, dst->r.max.x, maxy)); | |
| 1990/0329 | 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++){ | |
| 1992/0816 | oq = (uchar*)gaddr(dst, Pt(dst->r.min.x, y)); q = oq + (dst->r.min.x&((sizeof(ulong))*ws-1))/ws; memmove(q, p, l); | |
| 1992/1106 | if(islittle) bitreverse(q, l); | |
| 1992/0816 | if(v==0 && flipping){ /* flip bits */ /* we know it's all word aligned */ lp = (ulong*)oq; for(x=0; x<l; x+=sizeof(ulong)) *lp++ ^= ~0; } p += l; | |
| 1990/0329 | m -= l; } | |
| 1992/1010 | if(v == 0) hwscreenwrite(miny, maxy); | |
| 1990/0329 | break; | |
| 1990/0826 | case 'x': /* * cursorset * * 'x' 1 * pt 8 */ if(m < 9) | |
| 1990/11211 | error(Ebadblt); | |
| 1992/0630 | pt1.x = BGLONG(p+1); pt1.y = BGLONG(p+5); | |
| 1992/0816 | if(ptinrect(pt1, gscreen.r)){ | |
| 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); | |
| 1992/0630 | v = BGSHORT(p+1); | |
| 1992/0622 | if(v<0 || v>=bit.nfont || (ff=bit.font[v])==0) | |
| 1992/0209 | error(Ebadblt); | |
| 1992/0729 | if(ff->b == 0) error(Ebadbitmap); | |
| 1992/0630 | l = BGSHORT(p+3); if(l >= ff->ncache) | |
| 1992/0209 | error(Ebadblt); | |
| 1992/0630 | v = BGSHORT(p+5); | |
| 1992/0628 | if(v<0 || v>=bit.nsubfont || (f=bit.subfont[v])==0 || f->ref==0) error(Ebadfont); | |
| 1992/0630 | nw = BGSHORT(p+7); | |
| 1992/0209 | 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); | |
| 1992/0630 | v = BGSHORT(p+1); | |
| 1991/0706 | if(v != 0) error(Ebadbitmap); m -= 3; p += 3; | |
| 1992/0621 | nw = 1 << (1 << gscreen.ldepth); | |
| 1991/0706 | if(m < 12*nw) error(Ebadblt); ok = 1; for(i = 0; i < nw; i++){ | |
| 1992/1030 | ok &= setcolor(flipping ? ~i : i, BGLONG(p), BGLONG(p+4), BGLONG(p+8)); | |
| 1991/0706 | p += 12; m -= 12; } if(!ok){ /* assume monochrome: possibly change flipping */ | |
| 1992/0630 | l = BGLONG(p-12); | |
| 1991/0706 | getcolor(nw-1, &rv, &rv, &rv); flipping = (l != rv); } break; | |
| 1990/0327 | } | |
| 1991/0614 | poperror(); | |
| 1992/1107 | screenupdate(); | |
| 1990/0721 | if(isoff) cursoron(1); | |
| 1992/0622 | qunlock(&bit); | |
| 1990/0324 | return n; } | |
| 1992/0621 | int | |
| 1992/0209 | bitalloc(Rectangle rect, int ld) { | |
| 1992/0711 | Arena *a, *ea, *aa; | |
| 1992/0621 | GBitmap *b, **bp, **ep; | |
| 1992/0209 | ulong l, ws, nw; long t; | |
| 1992/0706 | ws = BI2WD>>ld; /* pixels per word */ | |
| 1992/0621 | if(rect.min.x >= 0){ | |
| 1992/0519 | l = (rect.max.x+ws-1)/ws; l -= rect.min.x/ws; | |
| 1992/0621 | }else{ /* make positive before divide */ | |
| 1992/0209 | t = (-rect.min.x)+ws-1; t = (t/ws)*ws; l = (t+rect.max.x+ws-1)/ws; } nw = l*Dy(rect); | |
| 1992/0622 | ea = &bit.arena[bit.narena]; /* first try easy fit */ for(a=bit.arena; a<ea; a++){ if(a->words == 0) continue; if(a->wfree+HDR+nw <= a->words+a->nwords) goto found; | |
| 1992/0209 | } | |
| 1992/0622 | /* compact and try again */ bitcompact(); aa = 0; for(a=bit.arena; a<ea; a++){ if(a->words == 0){ if(aa == 0) aa = a; continue; } if(a->wfree+HDR+nw <= a->words+a->nwords) goto found; } /* need new arena */ | |
| 1992/0630 | if(aa){ | |
| 1992/0622 | a = aa; | |
| 1992/0706 | a->nwords = HDR + (gscreen.r.max.y*gscreen.r.max.x)/ws; | |
| 1992/0630 | if(a->nwords < HDR+nw) a->nwords = HDR+nw; a->words = xalloc(a->nwords*sizeof(ulong)); if(a->words){ a->wfree = a->words; a->nbusy = 0; goto found; } | |
| 1992/0622 | } | |
| 1992/0630 | /* else can't grow list: bitmaps have backpointers */ | |
| 1992/0628 | ||
| 1992/0706 | bitfreeup(); | |
| 1992/0628 | for(a=bit.arena; a<ea; a++){ if(a->words == 0) continue; if(a->wfree+HDR+nw <= a->words+a->nwords) goto found; } if(a == ea) | |
| 1992/0622 | error(Enobitstore); found: | |
| 1992/0706 | b = bitmalloc(sizeof(GBitmap)); if(b == 0) error(Enomem); | |
| 1992/0622 | *a->wfree++ = nw; *a->wfree++ = (ulong)a; *a->wfree++ = (ulong)b; | |
| 1992/0706 | memset(a->wfree, 0, nw*sizeof(ulong)); | |
| 1992/0622 | b->base = a->wfree; a->wfree += nw; a->nbusy++; | |
| 1992/0621 | b->zero = l*rect.min.y; | |
| 1992/0209 | if(rect.min.x >= 0) | |
| 1992/0621 | b->zero += rect.min.x/ws; | |
| 1992/0209 | else | |
| 1992/0621 | b->zero -= (-rect.min.x+ws-1)/ws; b->zero = -b->zero; b->width = l; b->ldepth = ld; b->r = rect; b->clipr = rect; b->cache = 0; /* worth doing better than linear lookup? */ ep = bit.map+bit.nmap; for(bp=bit.map; bp<ep; bp++) if(*bp == 0) break; if(bp == ep){ | |
| 1992/0706 | bp = bitmalloc((bit.nmap+DMAP)*sizeof(GBitmap*)); if(bp == 0){ bitfree(b); error(Enomem); } memmove(bp, bit.map, bit.nmap*sizeof(GBitmap*)); free(bit.map); bit.map = bp; bp += bit.nmap; | |
| 1992/0621 | bit.nmap += DMAP; } *bp = b; return bp-bit.map; | |
| 1992/0209 | } | |
| 1990/0324 | void | |
| 1992/0621 | bitfree(GBitmap *b) | |
| 1990/0327 | { | |
| 1992/0622 | Arena *a; | |
| 1992/0630 | if(b->base != gscreen.base){ /* can't free screen memory */ a = (Arena*)(b->base[-2]); a->nbusy--; if(a->nbusy == 0) arenafree(a); b->base[-1] = 0; } | |
| 1992/0621 | free(b); | |
| 1990/0327 | } | |
| 1992/0209 | void | |
| 1992/0621 | fontfree(GFont *f) { if(f->b) bitfree(f->b); | |
| 1992/0627 | free(f->cache); | |
| 1992/0621 | free(f); } void | |
| 1992/0702 | subfontfree(BSubfont *s, int i) | |
| 1992/0621 | { | |
| 1992/0912 | if(s!=bdefont && s->ref>0){ /* don't free subfont 0, bdefont */ | |
| 1992/0630 | s->ref--; | |
| 1992/0702 | if(s->ref==0 && s->qid[0]==~0){ /* uncached */ bitfree(s->bits); free(s->info); free(s); bit.subfont[i] = 0; } } | |
| 1992/0628 | return; | |
| 1992/0621 | } void | |
| 1992/0622 | arenafree(Arena *a) { xfree(a->words); a->words = 0; } void | |
| 1992/0209 | bitstring(GBitmap *bp, Point pt, GFont *f, uchar *p, long l, Fcode fc) { int full; Rectangle rect; ushort r; GCacheinfo *c; | |
| 1992/0903 | int x; Fcode clr; | |
| 1992/0209 | ||
| 1992/0903 | clr = 0; full = (fc&~S)^(D&~S); /* result involves source */ | |
| 1992/0209 | if(full){ rect.min.y = 0; rect.max.y = f->height; | |
| 1992/0903 | /* set clr to result under fc if source pixel is zero */ /* hard to do without knowing layout of bits, so we cheat */ clr = (fc&3); /* fc&3 is result if source is zero */ clr |= clr<<2; /* fc&(3<<2) is result if source is one */ | |
| 1992/0209 | } while(l > 0){ | |
| 1992/0630 | r = BGSHORT(p); | |
| 1992/0209 | p += 2; l -= 2; | |
| 1992/0630 | if(r >= f->ncache) | |
| 1992/0211 | continue; | |
| 1992/0209 | c = &f->cache[r]; if(!full){ rect.min.y = c->top; rect.max.y = c->bottom; | |
| 1992/0903 | }else{ if(c->left > 0) gbitblt(bp, pt, bp, Rect(pt.x, pt.y, pt.x+c->left, pt.y+f->height), clr); x = c->left+(c->xright-c->x); if(x < c->width) gbitblt(bp, Pt(pt.x+x, pt.y), bp, Rect(pt.x+x, pt.y, pt.x+c->width, pt.y+f->height), clr); } | |
| 1992/0209 | 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); } | |
| 1992/0818 | QLock bitlock; GBitmap* id2bit(int v) { GBitmap *bp=0; if(v<0 || v>=bit.nmap || (bp=bit.map[v])==0) error(Ebadbitmap); return bp; } | |
| 1990/0327 | void bitcompact(void) { | |
| 1992/0711 | Arena *a, *ea, *na; | |
| 1992/0622 | ulong *p1, *p2, n; | |
| 1990/0327 | ||
| 1992/0818 | qlock(&bitlock); | |
| 1992/0622 | ea = &bit.arena[bit.narena]; for(a=bit.arena; a<ea; a++){ if(a->words == 0) | |
| 1990/0327 | continue; | |
| 1992/0622 | /* first compact what's here */ p1 = p2 = a->words; while(p2 < a->wfree){ n = HDR+p2[0]; if(p2[2] == 0){ p2 += n; continue; } if(p1 != p2){ memmove(p1, p2, n*sizeof(ulong)); ((GBitmap*)p1[2])->base = p1+HDR; } p2 += n; p1 += n; | |
| 1990/0327 | } | |
| 1992/0622 | /* now pull stuff from later arena to fill this one */ na = a+1; while(na<ea && p1<a->words+a->nwords){ p2 = na->words; if(p2 == 0){ na++; continue; } while(p2 < na->wfree){ n = HDR+p2[0]; if(p2[2] == 0){ p2 += n; continue; } if(p1+n < a->words+a->nwords){ memmove(p1, p2, n*sizeof(ulong)); ((GBitmap*)p1[2])->base = p1+HDR; /* block now in new arena... */ p1[1] = (ulong)a; a->nbusy++; /* ... not in old arena */ na->nbusy--; p2[2] = 0; p1 += n; } p2 += n; } na++; | |
| 1990/0327 | } | |
| 1992/0622 | a->wfree = p1; | |
| 1990/0327 | } | |
| 1992/0630 | for(a=bit.arena; a<ea; a++) if(a->words && a->nbusy==0) | |
| 1992/0622 | arenafree(a); | |
| 1992/0818 | 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) { | |
| 1992/1107 | if(cursor.disable) return; | |
| 1990/0504 | 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); | |
| 1992/1013 | gbitblt(&gscreen, cursor.r.min, | |
| 1991/0706 | &clr, Rect(0, 0, 16, 16), flipping? flipD[D&~S] : D&~S); | |
| 1992/1013 | gbitblt(&gscreen, cursor.r.min, | |
| 1991/0706 | &set, Rect(0, 0, 16, 16), flipping? flipD[S|D] : S|D); | |
| 1992/1104 | mbbrect(cursor.r); | |
| 1992/1107 | screenupdate(); | |
| 1990/0504 | } if(dolock) unlock(&cursor); } void cursoroff(int dolock) { | |
| 1992/1107 | if(cursor.disable) return; | |
| 1990/0504 | if(dolock) lock(&cursor); | |
| 1992/1013 | if(--cursor.visible == 0) { | |
| 1991/1225 | gbitblt(&gscreen, cursor.r.min, &cursorback, Rect(0, 0, 16, 16), S); | |
| 1992/1104 | mbbrect(cursor.r); | |
| 1992/1107 | screenupdate(); | |
| 1992/1013 | } | |
| 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 | } 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); | |
| 1992/1104 | mousescreenupdate(); | |
| 1991/0707 | 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); } } | |
| 1992/1020 | /* * microsoft 3 button, 7 bit bytes * * byte 0 - 1 L R Y7 Y6 X7 X6 * byte 1 - 0 X5 X4 X3 X2 X1 X0 * byte 2 - 0 Y5 Y4 Y3 Y2 Y1 Y0 * byte 3 - 0 M x x x x x (optional) * | |
| 1992/1021 | * shift & right button is the same as middle button (for 2 button mice) | |
| 1992/1020 | */ int m3mouseputc(IOQ *q, int c) { static uchar msg[3]; static int nb; | |
| 1992/1021 | static int middle; static uchar b[] = { 0, 4, 1, 5, 0, 2, 1, 5 }; | |
| 1992/1020 | short x; USED(q); /* * check bit 6 for consistency */ if(nb==0){ if((c&0x40) == 0){ /* an extra byte gets sent for the middle button */ | |
| 1992/1021 | middle = (c&0x20) ? 2 : 0; mousebuttons((mouse.buttons & ~2) | middle); | |
| 1992/1020 | return 0; } } msg[nb] = c; if(++nb == 3){ nb = 0; | |
| 1992/1021 | mouse.newbuttons = middle | b[(msg[0]>>4)&3 | (mouseshifted ? 4 : 0)]; | |
| 1992/1020 | x = (msg[0]&0x3)<<14; mouse.dx = (x>>8) | msg[1]; x = (msg[0]&0xc)<<12; mouse.dy = (x>>8) | msg[2]; mouse.track = 1; mouseclock(); } return 0; } /* * Logitech 5 byte packed binary mouse format, 8 bit bytes | |
| 1992/1021 | * * shift & right button is the same as middle button (for 2 button mice) | |
| 1992/1020 | */ | |
| 1991/0605 | int mouseputc(IOQ *q, int c) { | |
| 1991/0706 | static short msg[5]; static int nb; | |
| 1992/1021 | static uchar b[] = {0, 4, 2, 6, 1, 5, 3, 7, 0, 2, 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) | |
| 1992/0630 | msg[nb] |= ~0xFF; /* sign extend */ | |
| 1991/0706 | if(++nb == 5){ | |
| 1992/1107 | mouse.newbuttons = b[((msg[0]&7)^7) | (mouseshifted ? 8 : 0)]; | |
| 1991/0706 | 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; | |
| 1992/1106 | } /* | |
| 1992/1108 | * reverse the bits in a bitmap (converting between little & big endian) | |
| 1992/1106 | */ | |
| 1992/1108 | uchar bitrevtab[] = { | |
| 1992/1106 | 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff }; void bitreverse(uchar *p, int l) { uchar *e; e = p + l; for(; p < e; p++) | |
| 1992/1108 | *p = bitrevtab[*p]; | |
| 1990/0324 | } | |