|
|
1.1 ! root 1: #include "u.h" ! 2: #include "../port/lib.h" ! 3: #include <libg.h> ! 4: #include <gnot.h> ! 5: #include "mem.h" ! 6: #include "dat.h" ! 7: #include "fns.h" ! 8: #include "../port/error.h" ! 9: ! 10: #include "devtab.h" ! 11: ! 12: #include "screen.h" ! 13: ! 14: /* ! 15: * Some monochrome screens are reversed from what we like: ! 16: * We want 0's bright and 1's dark. ! 17: * Indexed by an Fcode, these compensate for the source bitmap being wrong ! 18: * (exchange S rows) and destination (exchange D columns and invert result) ! 19: */ ! 20: int flipS[] = { ! 21: 0x0, 0x4, 0x8, 0xC, 0x1, 0x5, 0x9, 0xD, ! 22: 0x2, 0x6, 0xA, 0xE, 0x3, 0x7, 0xB, 0xF ! 23: }; ! 24: ! 25: int flipD[] = { ! 26: 0xF, 0xD, 0xE, 0xC, 0x7, 0x5, 0x6, 0x4, ! 27: 0xB, 0x9, 0xA, 0x8, 0x3, 0x1, 0x2, 0x0, ! 28: }; ! 29: ! 30: int flipping; /* are flip tables being used to transform Fcodes? */ ! 31: ! 32: /* ! 33: * Device (#b/bitblt) is exclusive use on open, so no locks are necessary ! 34: * for i/o ! 35: */ ! 36: ! 37: /* ! 38: * Arena is a word containing N, followed by a pointer to the Arena, ! 39: * followed by a pointer to the Bitmap, followed by N words. ! 40: * The bitmap pointer is zero if block is free. ! 41: * bit.map is an array of pointers to GBitmaps. The GBitmaps are ! 42: * freed individually and their corresponding entries in bit.map are zeroed. ! 43: * The index into bit.map is the Bitmap id as seen in libg. Subfonts and ! 44: * fonts are handled similarly. ! 45: */ ! 46: ! 47: typedef struct Arena Arena; ! 48: struct Arena ! 49: { ! 50: ulong *words; /* storage */ ! 51: ulong *wfree; /* pointer to next free word */ ! 52: ulong nwords; /* total in arena */ ! 53: int nbusy; /* number of busy blocks */ ! 54: }; ! 55: ! 56: typedef struct BSubfont BSubfont; ! 57: struct BSubfont ! 58: { ! 59: GSubfont; ! 60: int ref; /* number of times this subfont is open */ ! 61: ulong qid[2]; /* unique id used as a cache tag */ ! 62: }; ! 63: ! 64: extern GSubfont *defont; ! 65: BSubfont *bdefont; ! 66: BSubfont bdefont0; ! 67: ! 68: ! 69: struct ! 70: { ! 71: Ref; ! 72: QLock; ! 73: GBitmap **map; /* indexed array */ ! 74: int nmap; /* number allocated */ ! 75: GFont **font; /* indexed array */ ! 76: int nfont; /* number allocated */ ! 77: BSubfont**subfont; /* indexed array */ ! 78: int nsubfont; /* number allocated */ ! 79: Arena *arena; /* array */ ! 80: int narena; /* number allocated */ ! 81: int mouseopen; /* flag: mouse open */ ! 82: int bitbltopen; /* flag: bitblt open */ ! 83: int bid; /* last allocated bitmap id */ ! 84: int subfid; /* last allocated subfont id */ ! 85: int cacheid; /* last cached subfont id */ ! 86: int fid; /* last allocated font id */ ! 87: int init; /* freshly opened; init message pending */ ! 88: int rid; /* read bitmap id */ ! 89: int rminy; /* read miny */ ! 90: int rmaxy; /* read maxy */ ! 91: int mid; /* colormap read bitmap id */ ! 92: }bit; ! 93: ! 94: #define DMAP 16 /* delta increase in size of arrays */ ! 95: #define FREE 0x80000000 ! 96: ! 97: void bitcompact(void); ! 98: int bitalloc(Rectangle, int); ! 99: void bitfree(GBitmap*); ! 100: void fontfree(GFont*); ! 101: void subfontfree(BSubfont*, int); ! 102: void arenafree(Arena*); ! 103: void bitstring(GBitmap*, Point, GFont*, uchar*, long, Fcode); ! 104: void bitloadchar(GFont*, int, GSubfont*, int); ! 105: extern GBitmap gscreen; ! 106: ! 107: typedef struct Mouseinfo Mouseinfo; ! 108: typedef struct Cursorinfo Cursorinfo; ! 109: ! 110: struct Mouseinfo{ ! 111: /* ! 112: * First three fields are known in some l.s's ! 113: */ ! 114: int dx; ! 115: int dy; ! 116: int track; /* l.s has updated dx & dy */ ! 117: Mouse; ! 118: int redraw; /* update cursor on screen */ ! 119: ulong counter; /* increments every update */ ! 120: ulong lastcounter; /* value when /dev/mouse read */ ! 121: Rendez r; ! 122: }; ! 123: ! 124: struct Cursorinfo{ ! 125: Cursor; ! 126: Lock; ! 127: int visible; /* on screen */ ! 128: Rectangle r; /* location */ ! 129: }; ! 130: ! 131: Mouseinfo mouse; ! 132: Cursorinfo cursor; ! 133: Cursor curs; ! 134: int mouseshifted; ! 135: int mousetype; ! 136: int mouseswap; ! 137: int islittle; ! 138: int hwcurs; ! 139: ! 140: Cursor arrow = ! 141: { ! 142: {-1, -1}, ! 143: {0xFF, 0xE0, 0xFF, 0xE0, 0xFF, 0xC0, 0xFF, 0x00, ! 144: 0xFF, 0x00, 0xFF, 0x80, 0xFF, 0xC0, 0xFF, 0xE0, ! 145: 0xE7, 0xF0, 0xE3, 0xF8, 0xC1, 0xFC, 0x00, 0xFE, ! 146: 0x00, 0x7F, 0x00, 0x3E, 0x00, 0x1C, 0x00, 0x08, ! 147: }, ! 148: {0x00, 0x00, 0x7F, 0xC0, 0x7F, 0x00, 0x7C, 0x00, ! 149: 0x7E, 0x00, 0x7F, 0x00, 0x6F, 0x80, 0x67, 0xC0, ! 150: 0x43, 0xE0, 0x41, 0xF0, 0x00, 0xF8, 0x00, 0x7C, ! 151: 0x00, 0x3E, 0x00, 0x1C, 0x00, 0x08, 0x00, 0x00, ! 152: } ! 153: }; ! 154: ! 155: ulong setbits[16]; ! 156: GBitmap set = ! 157: { ! 158: setbits, ! 159: 0, ! 160: 1, ! 161: 0, ! 162: {0, 0, 16, 16}, ! 163: {0, 0, 16, 16} ! 164: }; ! 165: ! 166: ulong clrbits[16]; ! 167: GBitmap clr = ! 168: { ! 169: clrbits, ! 170: 0, ! 171: 1, ! 172: 0, ! 173: {0, 0, 16, 16}, ! 174: {0, 0, 16, 16} ! 175: }; ! 176: ! 177: ulong cursorbackbits[16*4]; ! 178: GBitmap cursorback = ! 179: { ! 180: cursorbackbits, ! 181: 0, ! 182: 1, ! 183: 0, ! 184: {0, 0, 16, 16}, ! 185: {0, 0, 16, 16} ! 186: }; ! 187: ! 188: void Cursortocursor(Cursor*); ! 189: int mousechanged(void*); ! 190: ! 191: enum{ ! 192: Qdir, ! 193: Qbitblt, ! 194: Qmouse, ! 195: Qmousectl, ! 196: Qscreen, ! 197: }; ! 198: ! 199: Dirtab bitdir[]={ ! 200: "bitblt", {Qbitblt}, 0, 0666, ! 201: "mouse", {Qmouse}, 0, 0666, ! 202: "mousectl", {Qmousectl}, 0, 0220, ! 203: "screen", {Qscreen}, 0, 0444, ! 204: }; ! 205: ! 206: #define NBIT (sizeof bitdir/sizeof(Dirtab)) ! 207: #define NINFO 8192 /* max chars per subfont; sanity check only */ ! 208: #define HDR 3 ! 209: ! 210: void ! 211: lockedupdate(void) ! 212: { ! 213: qlock(&bit); ! 214: if(waserror()){ ! 215: qunlock(&bit); ! 216: return; ! 217: } ! 218: screenupdate(); ! 219: qunlock(&bit); ! 220: poperror(); ! 221: } ! 222: ! 223: void ! 224: bitfreeup(void) ! 225: { ! 226: int i; ! 227: BSubfont *s; ! 228: ! 229: /* free unused subfonts and compact */ ! 230: for(i=0; i<bit.nsubfont; i++){ ! 231: s = bit.subfont[i]; ! 232: if(s && s!=bdefont && s->ref==0){ ! 233: s->ref = 1; ! 234: s->qid[0] = ~0; /* force cleanup */ ! 235: subfontfree(s, i); ! 236: } ! 237: } ! 238: bitcompact(); ! 239: } ! 240: ! 241: void* ! 242: bitmalloc(ulong n) ! 243: { ! 244: void *p; ! 245: ! 246: p = malloc(n); ! 247: if(p) ! 248: return p; ! 249: bitfreeup(); ! 250: return malloc(n); ! 251: } ! 252: ! 253: void ! 254: bitdebug(void) ! 255: { ! 256: int i; ! 257: long l; ! 258: Arena *a; ! 259: ! 260: l = 0; ! 261: for(i=0; i<bit.narena; i++){ ! 262: a = &bit.arena[i]; ! 263: if(a->words){ ! 264: l += a->nwords; ! 265: print("%d: %ld bytes used; %ld total\n", i, ! 266: (a->wfree-a->words)*sizeof(ulong), ! 267: a->nwords*sizeof(ulong)); ! 268: } ! 269: } ! 270: print("arena: %ld bytes\n", l*sizeof(ulong)); ! 271: l = 0; ! 272: for(i=0; i<bit.nmap; i++) ! 273: if(bit.map[i]) ! 274: l++; ! 275: print("%d bitmaps ", l); ! 276: l = 0; ! 277: for(i=0; i<bit.nfont; i++) ! 278: if(bit.font[i]) ! 279: l++; ! 280: print("%d fonts ", l); ! 281: l = 0; ! 282: for(i=0; i<bit.nsubfont; i++) ! 283: if(bit.subfont[i]){ ! 284: print("%d: %lux %lux ", i, bit.subfont[i]->qid[0], bit.subfont[i]->qid[1]); ! 285: l++; ! 286: } ! 287: print("%d subfonts\n", l); ! 288: } ! 289: ! 290: void ! 291: bitreset(void) ! 292: { ! 293: int ws; ! 294: ulong r; ! 295: Arena *a; ! 296: ! 297: if(!conf.monitor) ! 298: return; ! 299: ! 300: memmove(&bdefont0, defont, sizeof(*defont)); ! 301: bdefont = &bdefont0; ! 302: bit.map = smalloc(DMAP*sizeof(GBitmap*)); ! 303: bit.nmap = DMAP; ! 304: getcolor(0, &r, &r, &r); ! 305: if(r == 0) ! 306: flipping = 1; ! 307: bit.bid = -1; ! 308: bit.subfid = -1; ! 309: bit.fid = -1; ! 310: bit.cacheid = -1; ! 311: bit.font = smalloc(DMAP*sizeof(GFont*)); ! 312: bit.nfont = DMAP; ! 313: bit.subfont = smalloc(DMAP*sizeof(BSubfont*)); ! 314: bit.nsubfont = DMAP; ! 315: bit.arena = smalloc(DMAP*sizeof(Arena)); ! 316: bit.narena = DMAP; ! 317: a = &bit.arena[0]; ! 318: /* ! 319: * Somewhat of a heuristic: start with three screensful and ! 320: * allocate single screensful dynamically if needed. ! 321: */ ! 322: ! 323: ws = BI2WD>>gscreen.ldepth; /* pixels per word */ ! 324: a->nwords = 3*(HDR + gscreen.r.max.y*gscreen.r.max.x/ws); ! 325: a->words = xalloc(a->nwords*sizeof(ulong)); ! 326: if(a->words == 0){ ! 327: /* try again */ ! 328: print("bitreset: allocating only 1 screenful\n"); ! 329: a->nwords /= 3; ! 330: a->words = a->words = xalloc(a->nwords*sizeof(ulong)); ! 331: if(a->words == 0) ! 332: panic("bitreset"); ! 333: } ! 334: a->wfree = a->words; ! 335: a->nbusy = 1; /* keep 0th arena from being freed */ ! 336: Cursortocursor(&arrow); ! 337: } ! 338: ! 339: /* ! 340: * screen bit depth changed, reset backup map for cursor ! 341: */ ! 342: void ! 343: bitdepth(void) ! 344: { ! 345: cursoroff(1); ! 346: if(gscreen.ldepth > 3) ! 347: cursorback.ldepth = 0; ! 348: else{ ! 349: cursorback.ldepth = gscreen.ldepth; ! 350: cursorback.width = ((16 << gscreen.ldepth) + 31) >> 5; ! 351: } ! 352: cursoron(1); ! 353: } ! 354: ! 355: void ! 356: bitinit(void) ! 357: { ! 358: if(!conf.monitor) ! 359: return; ! 360: if(gscreen.ldepth > 3) ! 361: cursorback.ldepth = 0; ! 362: else{ ! 363: cursorback.ldepth = gscreen.ldepth; ! 364: cursorback.width = ((16 << gscreen.ldepth) + 31) >> 5; ! 365: } ! 366: cursoron(1); ! 367: } ! 368: ! 369: Chan* ! 370: bitattach(char *spec) ! 371: { ! 372: if(!conf.monitor) ! 373: error(Egreg); ! 374: return devattach('b', spec); ! 375: } ! 376: ! 377: Chan* ! 378: bitclone(Chan *c, Chan *nc) ! 379: { ! 380: if(!conf.monitor) ! 381: error(Egreg); ! 382: nc = devclone(c, nc); ! 383: if(c->qid.path != CHDIR) ! 384: incref(&bit); ! 385: return nc; ! 386: } ! 387: ! 388: int ! 389: bitwalk(Chan *c, char *name) ! 390: { ! 391: if(!conf.monitor) ! 392: error(Egreg); ! 393: return devwalk(c, name, bitdir, NBIT, devgen); ! 394: } ! 395: ! 396: void ! 397: bitstat(Chan *c, char *db) ! 398: { ! 399: if(!conf.monitor) ! 400: error(Egreg); ! 401: devstat(c, db, bitdir, NBIT, devgen); ! 402: } ! 403: ! 404: Chan* ! 405: bitopen(Chan *c, int omode) ! 406: { ! 407: GBitmap *b; ! 408: ! 409: if(!conf.monitor) ! 410: error(Egreg); ! 411: switch(c->qid.path){ ! 412: case CHDIR: ! 413: if(omode != OREAD) ! 414: error(Eperm); ! 415: break; ! 416: case Qmouse: ! 417: lock(&bit); ! 418: if(bit.mouseopen){ ! 419: unlock(&bit); ! 420: error(Einuse); ! 421: } ! 422: bit.mouseopen = 1; ! 423: bit.ref++; ! 424: unlock(&bit); ! 425: break; ! 426: case Qbitblt: ! 427: lock(&bit); ! 428: if(bit.bitbltopen || bit.mouseopen){ ! 429: unlock(&bit); ! 430: error(Einuse); ! 431: } ! 432: b = smalloc(sizeof(GBitmap)); ! 433: *b = gscreen; ! 434: bit.map[0] = b; /* bitmap 0 is screen */ ! 435: bit.subfont[0] = bdefont; /* subfont 0 is default */ ! 436: bit.subfont[0]->ref = 1; ! 437: bit.subfont[0]->qid[0] = 0; ! 438: bit.subfont[0]->qid[1] = 0; ! 439: bit.bid = -1; ! 440: bit.fid = -1; ! 441: bit.subfid = -1; ! 442: bit.cacheid = -1; ! 443: bit.rid = -1; ! 444: bit.mid = -1; ! 445: bit.init = 0; ! 446: bit.bitbltopen = 1; ! 447: Cursortocursor(&arrow); ! 448: unlock(&bit); ! 449: break; ! 450: default: ! 451: incref(&bit); ! 452: } ! 453: c->mode = openmode(omode); ! 454: c->flag |= COPEN; ! 455: c->offset = 0; ! 456: return c; ! 457: } ! 458: ! 459: void ! 460: bitcreate(Chan *c, char *name, int omode, ulong perm) ! 461: { ! 462: if(!conf.monitor) ! 463: error(Egreg); ! 464: USED(c, name, omode, perm); ! 465: error(Eperm); ! 466: } ! 467: ! 468: void ! 469: bitremove(Chan *c) ! 470: { ! 471: if(!conf.monitor) ! 472: error(Egreg); ! 473: USED(c); ! 474: error(Eperm); ! 475: } ! 476: ! 477: void ! 478: bitwstat(Chan *c, char *db) ! 479: { ! 480: if(!conf.monitor) ! 481: error(Egreg); ! 482: USED(c, db); ! 483: error(Eperm); ! 484: } ! 485: ! 486: void ! 487: bitclose(Chan *c) ! 488: { ! 489: GBitmap *b, **bp, **ebp; ! 490: BSubfont *s, **sp, **esp; ! 491: GFont *f, **fp, **efp; ! 492: ! 493: if(!conf.monitor) ! 494: error(Egreg); ! 495: if(c->qid.path!=CHDIR && (c->flag&COPEN)){ ! 496: lock(&bit); ! 497: if(c->qid.path == Qmouse) ! 498: bit.mouseopen = 0; ! 499: if(c->qid.path == Qbitblt) ! 500: bit.bitbltopen = 0; ! 501: if(--bit.ref == 0){ ! 502: ebp = &bit.map[bit.nmap]; ! 503: for(bp = bit.map; bp<ebp; bp++){ ! 504: b = *bp; ! 505: if(b){ ! 506: bitfree(b); ! 507: *bp = 0; ! 508: } ! 509: } ! 510: esp = &bit.subfont[bit.nsubfont]; ! 511: for(sp=bit.subfont; sp<esp; sp++){ ! 512: s = *sp; ! 513: if(s) ! 514: subfontfree(s, sp-bit.subfont); ! 515: /* don't clear *sp: cached */ ! 516: } ! 517: efp = &bit.font[bit.nfont]; ! 518: for(fp=bit.font; fp<efp; fp++){ ! 519: f = *fp; ! 520: if(f){ ! 521: fontfree(f); ! 522: *fp = 0; ! 523: } ! 524: } ! 525: } ! 526: unlock(&bit); ! 527: } ! 528: } ! 529: ! 530: long ! 531: bitread(Chan *c, void *va, long n, ulong offset) ! 532: { ! 533: uchar *p, *q; ! 534: long miny, maxy, t, x, y; ! 535: ulong l, nw, ws, rv, gv, bv; ! 536: int off, j; ! 537: Fontchar *i; ! 538: GBitmap *src; ! 539: BSubfont *s; ! 540: static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 }; ! 541: ! 542: if(!conf.monitor) ! 543: error(Egreg); ! 544: if(c->qid.path & CHDIR) ! 545: return devdirread(c, va, n, bitdir, NBIT, devgen); ! 546: ! 547: if(c->qid.path == Qmouse){ ! 548: /* ! 549: * mouse: ! 550: * 'm' 1 ! 551: * buttons 1 ! 552: * point 8 ! 553: * msec 4 ! 554: */ ! 555: if(n < 14) ! 556: error(Ebadblt); ! 557: while(mousechanged(0) == 0) ! 558: sleep(&mouse.r, mousechanged, 0); ! 559: lock(&cursor); ! 560: p = va; ! 561: p[0] = 'm'; ! 562: p[1] = mouseswap ? map[mouse.buttons&7] : mouse.buttons; ! 563: BPLONG(p+2, mouse.xy.x); ! 564: BPLONG(p+6, mouse.xy.y); ! 565: BPLONG(p+10, TK2MS(MACHP(0)->ticks)); ! 566: mouse.lastcounter = mouse.counter; ! 567: unlock(&cursor); ! 568: return 14; ! 569: } ! 570: if(c->qid.path == Qscreen){ ! 571: if(offset==0){ ! 572: if(n < 5*12) ! 573: error(Eio); ! 574: sprint(va, "%11d %11d %11d %11d %11d ", ! 575: gscreen.ldepth, gscreen.r.min.x, ! 576: gscreen.r.min.y, gscreen.r.max.x, ! 577: gscreen.r.max.y); ! 578: return 5*12; ! 579: } ! 580: ws = 1<<(3-gscreen.ldepth); /* pixels per byte */ ! 581: l = (gscreen.r.max.x+ws-1)/ws - gscreen.r.min.x/ws; ! 582: if(l == 0) ! 583: error(Ebadblt); ! 584: t = offset-5*12; ! 585: miny = t/l; /* unsigned computation */ ! 586: maxy = (t+n)/l; ! 587: if(miny >= gscreen.r.max.y) ! 588: return 0; ! 589: if(maxy >= gscreen.r.max.y) ! 590: maxy = gscreen.r.max.y; ! 591: n = 0; ! 592: p = va; ! 593: for(y=miny; y<maxy; y++){ ! 594: q = (uchar*)gaddr(&gscreen, Pt(0, y)); ! 595: memmove(p, q, l); ! 596: if(flipping) ! 597: /* is screen, so must be word aligned */ ! 598: for(x=0; x<l; x+=sizeof(ulong),p+=sizeof(ulong)) ! 599: *(ulong*)p ^= ~0; ! 600: else ! 601: p += l; ! 602: n += l; ! 603: } ! 604: return n; ! 605: } ! 606: if(c->qid.path != Qbitblt) ! 607: error(Egreg); ! 608: ! 609: qlock(&bit); ! 610: if(waserror()){ ! 611: qunlock(&bit); ! 612: nexterror(); ! 613: } ! 614: p = va; ! 615: /* ! 616: * Fuss about and figure out what to say. ! 617: */ ! 618: if(bit.init){ ! 619: /* ! 620: * init: ! 621: * 'I' 1 ! 622: * ldepth 1 ! 623: * rectangle 16 ! 624: * clip rectangle 16 ! 625: * font info 3*12 ! 626: * fontchars 6*(bdefont->n+1) ! 627: */ ! 628: if(n < 34) ! 629: error(Ebadblt); ! 630: p[0] = 'I'; ! 631: p[1] = gscreen.ldepth; ! 632: BPLONG(p+2, gscreen.r.min.x); ! 633: BPLONG(p+6, gscreen.r.min.y); ! 634: BPLONG(p+10, gscreen.r.max.x); ! 635: BPLONG(p+14, gscreen.r.max.y); ! 636: BPLONG(p+18, gscreen.clipr.min.x); ! 637: BPLONG(p+22, gscreen.clipr.min.y); ! 638: BPLONG(p+26, gscreen.clipr.max.x); ! 639: BPLONG(p+30, gscreen.clipr.max.y); ! 640: if(n >= 34+3*12+6*(bdefont->n+1)){ ! 641: p += 34; ! 642: sprint((char*)p, "%11d %11d %11d ", bdefont->n, ! 643: bdefont->height, bdefont->ascent); ! 644: p += 3*12; ! 645: for(i=bdefont->info,j=0; j<=bdefont->n; j++,i++,p+=6){ ! 646: BPSHORT(p, i->x); ! 647: p[2] = i->top; ! 648: p[3] = i->bottom; ! 649: p[4] = i->left; ! 650: p[5] = i->width; ! 651: } ! 652: n = 34+3*12+6*(bdefont->n+1); ! 653: }else ! 654: n = 34; ! 655: bit.init = 0; ! 656: }else if(bit.bid > 0){ ! 657: /* ! 658: * allocate: ! 659: * 'A' 1 ! 660: * bitmap id 2 ! 661: */ ! 662: if(n < 3) ! 663: error(Ebadblt); ! 664: if(bit.bid<0 || bit.map[bit.bid]==0) ! 665: error(Ebadbitmap); ! 666: p[0] = 'A'; ! 667: BPSHORT(p+1, bit.bid); ! 668: bit.bid = -1; ! 669: n = 3; ! 670: }else if(bit.subfid > 0){ ! 671: /* ! 672: * allocate subfont: ! 673: * 'K' 1 ! 674: * subfont id 2 ! 675: */ ! 676: if(n<3 || bit.subfid<0) ! 677: error(Ebadblt); ! 678: s = bit.subfont[bit.subfid]; ! 679: if(s==0 || s->ref==0) ! 680: error(Ebadfont); ! 681: p[0] = 'K'; ! 682: BPSHORT(p+1, bit.subfid); ! 683: bit.subfid = -1; ! 684: n = 3; ! 685: }else if(bit.cacheid >= 0){ ! 686: /* ! 687: * check cache for subfont: ! 688: * 'J' 1 ! 689: * subfont id 2 ! 690: * font info 3*12 ! 691: * fontchars 6*(subfont->n+1) ! 692: */ ! 693: p[0] = 'J'; ! 694: if(bit.cacheid < 0) ! 695: error(Ebadfont); ! 696: s = bit.subfont[bit.cacheid]; ! 697: if(s==0 || s->ref==0) ! 698: error(Ebadfont); ! 699: if(n < 3+3*12+6*(s->n+1)) ! 700: error(Ebadblt); ! 701: BPSHORT(p+1, bit.cacheid); ! 702: p += 3; ! 703: sprint((char*)p, "%11d %11d %11d ", s->n, s->height, s->ascent); ! 704: p += 3*12; ! 705: for(i=s->info,j=0; j<=s->n; j++,i++,p+=6){ ! 706: BPSHORT(p, i->x); ! 707: p[2] = i->top; ! 708: p[3] = i->bottom; ! 709: p[4] = i->left; ! 710: p[5] = i->width; ! 711: } ! 712: n = 3+3*12+6*(s->n+1); ! 713: bit.cacheid = -1; ! 714: }else if(bit.fid >= 0){ ! 715: /* ! 716: * allocate font: ! 717: * 'N' 1 ! 718: * font id 2 ! 719: */ ! 720: if(n < 3) ! 721: error(Ebadblt); ! 722: if(bit.fid<0 || bit.font[bit.fid]==0) ! 723: error(Ebadfont); ! 724: p[0] = 'N'; ! 725: BPSHORT(p+1, bit.fid); ! 726: bit.fid = -1; ! 727: n = 3; ! 728: }else if(bit.mid >= 0){ ! 729: /* ! 730: * read colormap: ! 731: * data 12*(2**bitmapdepth) ! 732: */ ! 733: src = bit.map[bit.mid]; ! 734: if(src == 0) ! 735: error(Ebadbitmap); ! 736: l = (1<<src->ldepth); ! 737: nw = 1 << l; ! 738: if(n < 12*nw) ! 739: error(Ebadblt); ! 740: for(j = 0; j < nw; j++){ ! 741: if(bit.mid == 0){ ! 742: getcolor(flipping? nw-j-1 : j, &rv, &gv, &bv); ! 743: }else{ ! 744: rv = j; ! 745: for(off = 32-l; off > 0; off -= l) ! 746: rv = (rv << l) | j; ! 747: gv = bv = rv; ! 748: } ! 749: BPLONG(p, rv); ! 750: BPLONG(p+4, gv); ! 751: BPLONG(p+8, bv); ! 752: p += 12; ! 753: } ! 754: bit.mid = -1; ! 755: n = 12*nw; ! 756: }else if(bit.rid >= 0){ ! 757: /* ! 758: * read bitmap: ! 759: * data bytewidth*(maxy-miny) ! 760: */ ! 761: src = bit.map[bit.rid]; ! 762: if(src == 0) ! 763: error(Ebadbitmap); ! 764: off = 0; ! 765: if(bit.rid == 0) ! 766: off = 1; ! 767: miny = bit.rminy; ! 768: maxy = bit.rmaxy; ! 769: if(miny>maxy || miny<src->r.min.y || maxy>src->r.max.y) ! 770: error(Ebadblt); ! 771: ws = 1<<(3-src->ldepth); /* pixels per byte */ ! 772: /* set l to number of bytes of incoming data per scan line */ ! 773: if(src->r.min.x >= 0) ! 774: l = (src->r.max.x+ws-1)/ws - src->r.min.x/ws; ! 775: else{ /* make positive before divide */ ! 776: t = (-src->r.min.x)+ws-1; ! 777: t = (t/ws)*ws; ! 778: l = (t+src->r.max.x+ws-1)/ws; ! 779: } ! 780: if(n < l*(maxy-miny)) ! 781: error(Ebadblt); ! 782: if(off) ! 783: cursoroff(1); ! 784: n = 0; ! 785: p = va; ! 786: for(y=miny; y<maxy; y++){ ! 787: q = (uchar*)gaddr(src, Pt(src->r.min.x, y)); ! 788: q += (src->r.min.x&((sizeof(ulong))*ws-1))/ws; ! 789: memmove(p, q, l); ! 790: if(islittle) ! 791: pixreverse(p, l, src->ldepth); ! 792: if(bit.rid==0 && flipping) ! 793: /* is screen, so must be word aligned */ ! 794: for(x=0; x<l; x+=sizeof(ulong),p+=sizeof(ulong)) ! 795: *(ulong*)p ^= ~0; ! 796: else ! 797: p += l; ! 798: n += l; ! 799: } ! 800: if(off) ! 801: cursoron(1); ! 802: bit.rid = -1; ! 803: } ! 804: ! 805: poperror(); ! 806: qunlock(&bit); ! 807: return n; ! 808: } ! 809: ! 810: Point ! 811: bitstrsize(GFont *f, uchar *p, int l) ! 812: { ! 813: ushort r; ! 814: Point s = {0,0}; ! 815: GCacheinfo *c; ! 816: ! 817: while(l > 0){ ! 818: r = BGSHORT(p); ! 819: p += 2; ! 820: l -= 2; ! 821: if(r >= f->ncache) ! 822: continue; ! 823: c = &f->cache[r]; ! 824: if(c->bottom > s.y) ! 825: s.y = c->bottom; ! 826: s.x += c->width; ! 827: } ! 828: return s; ! 829: } ! 830: ! 831: long ! 832: bitwrite(Chan *c, void *va, long n, ulong offset) ! 833: { ! 834: uchar *p, *q, *oq; ! 835: long m, v, miny, maxy, t, x, y; ! 836: ulong l, nw, ws, rv, q0, q1; ! 837: ulong *lp; ! 838: int off, isoff, i, j, ok; ! 839: ulong *endscreen = gaddr(&gscreen, Pt(0, gscreen.r.max.y)); ! 840: Point pt, pt1, pt2; ! 841: Rectangle rect; ! 842: Fcode fc; ! 843: Fontchar *fcp; ! 844: GBitmap *src, *dst; ! 845: BSubfont *f, *tf, **fp; ! 846: GFont *ff, **ffp; ! 847: GCacheinfo *gc; ! 848: char buf[64]; ! 849: ! 850: if(!conf.monitor) ! 851: error(Egreg); ! 852: USED(offset); ! 853: ! 854: if(c->qid.path == CHDIR) ! 855: error(Eisdir); ! 856: ! 857: if(c->qid.path == Qmousectl){ ! 858: if(n >= sizeof(buf)) ! 859: n = sizeof(buf)-1; ! 860: strncpy(buf, va, n); ! 861: buf[n] = 0; ! 862: mousectl(buf); ! 863: return n; ! 864: } ! 865: ! 866: if(c->qid.path != Qbitblt) ! 867: error(Egreg); ! 868: ! 869: isoff = 0; ! 870: qlock(&bit); ! 871: if(waserror()){ ! 872: qunlock(&bit); ! 873: if(isoff) ! 874: cursoron(1); ! 875: nexterror(); ! 876: } ! 877: p = va; ! 878: m = n; ! 879: SET(src, dst, f, ff); ! 880: while(m > 0) ! 881: switch(*p){ ! 882: default: ! 883: pprint("bitblt request 0x%x\n", *p); ! 884: error(Ebadblt); ! 885: ! 886: case 'a': ! 887: /* ! 888: * allocate: ! 889: * 'a' 1 ! 890: * ldepth 1 ! 891: * Rectangle 16 ! 892: * next read returns allocated bitmap id ! 893: */ ! 894: if(m < 18) ! 895: error(Ebadblt); ! 896: v = *(p+1); ! 897: if(v > 3) /* BUG */ ! 898: error(Ebadblt); ! 899: rect.min.x = BGLONG(p+2); ! 900: rect.min.y = BGLONG(p+6); ! 901: rect.max.x = BGLONG(p+10); ! 902: rect.max.y = BGLONG(p+14); ! 903: if(Dx(rect) < 0 || Dy(rect) < 0) ! 904: error(Ebadblt); ! 905: bit.bid = bitalloc(rect, v); ! 906: m -= 18; ! 907: p += 18; ! 908: break; ! 909: ! 910: case 'b': ! 911: /* ! 912: * bitblt ! 913: * 'b' 1 ! 914: * dst id 2 ! 915: * dst Point 8 ! 916: * src id 2 ! 917: * src Rectangle 16 ! 918: * code 2 ! 919: */ ! 920: if(m < 31) ! 921: error(Ebadblt); ! 922: fc = BGSHORT(p+29) & 0xF; ! 923: v = BGSHORT(p+11); ! 924: if(v<0 || v>=bit.nmap || (src=bit.map[v])==0) ! 925: error(Ebadbitmap); ! 926: off = 0; ! 927: if(v == 0){ ! 928: if(flipping) ! 929: fc = flipS[fc]; ! 930: off = 1; ! 931: } ! 932: v = BGSHORT(p+1); ! 933: if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) ! 934: error(Ebadbitmap); ! 935: if(v == 0){ ! 936: if(flipping) ! 937: fc = flipD[fc]; ! 938: off = 1; ! 939: } ! 940: pt.x = BGLONG(p+3); ! 941: pt.y = BGLONG(p+7); ! 942: rect.min.x = BGLONG(p+13); ! 943: rect.min.y = BGLONG(p+17); ! 944: rect.max.x = BGLONG(p+21); ! 945: rect.max.y = BGLONG(p+25); ! 946: if(off && !isoff){ ! 947: cursoroff(1); ! 948: isoff = 1; ! 949: } ! 950: gbitblt(dst, pt, src, rect, fc); ! 951: if(dst->base < endscreen) ! 952: mbbrect(Rpt(pt, add(pt, sub(rect.max, rect.min)))); ! 953: m -= 31; ! 954: p += 31; ! 955: break; ! 956: ! 957: case 'c': ! 958: /* ! 959: * cursorswitch ! 960: * 'c' 1 ! 961: * if nothing more: return to arrow; else ! 962: * Point 8 ! 963: * clr 32 ! 964: * set 32 ! 965: */ ! 966: if(m == 1){ ! 967: if(!isoff){ ! 968: cursoroff(1); ! 969: isoff = 1; ! 970: } ! 971: Cursortocursor(&arrow); ! 972: m -= 1; ! 973: p += 1; ! 974: break; ! 975: } ! 976: if(m < 73) ! 977: error(Ebadblt); ! 978: curs.offset.x = BGLONG(p+1); ! 979: curs.offset.y = BGLONG(p+5); ! 980: memmove(curs.clr, p+9, 2*16); ! 981: memmove(curs.set, p+41, 2*16); ! 982: if(islittle){ ! 983: pixreverse(curs.clr, 2*16, 0); ! 984: pixreverse(curs.set, 2*16, 0); ! 985: } ! 986: if(!isoff){ ! 987: cursoroff(1); ! 988: isoff = 1; ! 989: } ! 990: Cursortocursor(&curs); ! 991: m -= 73; ! 992: p += 73; ! 993: break; ! 994: ! 995: case 'e': ! 996: /* ! 997: * polysegment ! 998: * ! 999: * 'e' 1 ! 1000: * id 2 ! 1001: * pt 8 ! 1002: * value 1 ! 1003: * code 2 ! 1004: * n 2 ! 1005: * pts 2*n ! 1006: */ ! 1007: if(m < 16) ! 1008: error(Ebadblt); ! 1009: l = BGSHORT(p+14); ! 1010: if(m < 16+2*l) ! 1011: error(Ebadblt); ! 1012: v = BGSHORT(p+1); ! 1013: if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) ! 1014: error(Ebadbitmap); ! 1015: off = 0; ! 1016: fc = BGSHORT(p+12) & 0xF; ! 1017: if(v == 0){ ! 1018: if(flipping) ! 1019: fc = flipD[fc]; ! 1020: off = 1; ! 1021: } ! 1022: pt1.x = BGLONG(p+3); ! 1023: pt1.y = BGLONG(p+7); ! 1024: t = p[11]; ! 1025: if(off && !isoff){ ! 1026: cursoroff(1); ! 1027: isoff = 1; ! 1028: } ! 1029: p += 16; ! 1030: m -= 16; ! 1031: while(l > 0){ ! 1032: pt2.x = pt1.x + (schar)p[0]; ! 1033: pt2.y = pt1.y + (schar)p[1]; ! 1034: gsegment(dst, pt1, pt2, t, fc); ! 1035: if(dst->base < endscreen){ ! 1036: mbbpt(pt1); ! 1037: mbbpt(pt2); ! 1038: } ! 1039: pt1 = pt2; ! 1040: p += 2; ! 1041: m -= 2; ! 1042: l--; ! 1043: } ! 1044: break; ! 1045: ! 1046: case 'f': ! 1047: /* ! 1048: * free ! 1049: * 'f' 1 ! 1050: * id 2 ! 1051: */ ! 1052: if(m < 3) ! 1053: error(Ebadblt); ! 1054: v = BGSHORT(p+1); ! 1055: if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) ! 1056: error(Ebadbitmap); ! 1057: bitfree(dst); ! 1058: bit.map[v] = 0; ! 1059: m -= 3; ! 1060: p += 3; ! 1061: break; ! 1062: ! 1063: case 'g': ! 1064: /* ! 1065: * free subfont ! 1066: * 'g' 1 ! 1067: * id 2 ! 1068: */ ! 1069: if(m < 3) ! 1070: error(Ebadblt); ! 1071: v = BGSHORT(p+1); ! 1072: if(v<0 || v>=bit.nsubfont || (f=bit.subfont[v])==0 || f->ref==0) ! 1073: error(Ebadfont); ! 1074: subfontfree(f, v); ! 1075: m -= 3; ! 1076: p += 3; ! 1077: break; ! 1078: ! 1079: case 'h': ! 1080: /* ! 1081: * free font ! 1082: * 'h' 1 ! 1083: * id 2 ! 1084: */ ! 1085: if(m < 3) ! 1086: error(Ebadblt); ! 1087: v = BGSHORT(p+1); ! 1088: if(v<0 || v>=bit.nfont || (ff=bit.font[v])==0) ! 1089: error(Ebadfont); ! 1090: fontfree(ff); ! 1091: bit.font[v] = 0; ! 1092: m -= 3; ! 1093: p += 3; ! 1094: break; ! 1095: ! 1096: case 'i': ! 1097: /* ! 1098: * init ! 1099: * ! 1100: * 'i' 1 ! 1101: */ ! 1102: bit.init = 1; ! 1103: m -= 1; ! 1104: p += 1; ! 1105: break; ! 1106: ! 1107: case 'j': ! 1108: /* ! 1109: * subfont cache check ! 1110: * ! 1111: * 'j' 1 ! 1112: * qid 8 ! 1113: */ ! 1114: if(m < 9) ! 1115: error(Ebadblt); ! 1116: q0 = BGLONG(p+1); ! 1117: q1 = BGLONG(p+5); ! 1118: i = 0; ! 1119: if(q0 != ~0) ! 1120: for(; i<bit.nsubfont; i++){ ! 1121: f = bit.subfont[i]; ! 1122: if(f && f->qid[0]==q0 && f->qid[1]==q1) ! 1123: goto sfcachefound; ! 1124: } ! 1125: error(Esfnotcached); ! 1126: ! 1127: sfcachefound: ! 1128: f->ref++; ! 1129: bit.cacheid = i; ! 1130: m -= 9; ! 1131: p += 9; ! 1132: break; ! 1133: ! 1134: case 'k': ! 1135: /* ! 1136: * allocate subfont ! 1137: * 'k' 1 ! 1138: * n 2 ! 1139: * height 1 ! 1140: * ascent 1 ! 1141: * bitmap id 2 ! 1142: * qid 8 ! 1143: * fontchars 6*(n+1) ! 1144: * next read returns allocated font id ! 1145: */ ! 1146: if(m < 15) ! 1147: error(Ebadblt); ! 1148: v = BGSHORT(p+1); ! 1149: if(v<0 || v>NINFO || m<15+6*(v+1)) ! 1150: error(Ebadblt); ! 1151: for(i=1; i<bit.nsubfont; i++) ! 1152: if(bit.subfont[i] == 0) ! 1153: goto subfontfound; ! 1154: fp = bitmalloc((bit.nsubfont+DMAP)*sizeof(BSubfont*)); ! 1155: if(fp == 0) ! 1156: error(Enomem); ! 1157: memmove(fp, bit.subfont, bit.nsubfont*sizeof(BSubfont*)); ! 1158: free(bit.subfont); ! 1159: bit.subfont = fp; ! 1160: bit.nsubfont += DMAP; ! 1161: subfontfound: ! 1162: f = bitmalloc(sizeof(BSubfont)); ! 1163: if(f == 0) ! 1164: error(Enomem); ! 1165: f->info = bitmalloc((v+1)*sizeof(Fontchar)); ! 1166: if(f->info == 0){ ! 1167: free(f); ! 1168: error(Enomem); ! 1169: } ! 1170: bit.subfont[i] = f; ! 1171: f->n = v; ! 1172: f->height = p[3]; ! 1173: f->ascent = p[4]; ! 1174: f->qid[0] = BGLONG(p+7); ! 1175: f->qid[1] = BGLONG(p+11); ! 1176: /* check to see if already there, uncache if so */ ! 1177: for(j=0; j<bit.nsubfont; j++){ ! 1178: if(j == i) ! 1179: continue; ! 1180: tf = bit.subfont[j]; ! 1181: if(tf && tf->qid[0]==f->qid[0] && tf->qid[1]==f->qid[1]){ ! 1182: f->qid[0] = ~0; /* uncached */ ! 1183: break; ! 1184: } ! 1185: } ! 1186: f->ref = 1; ! 1187: v = BGSHORT(p+5); ! 1188: if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) ! 1189: error(Ebadbitmap); ! 1190: f->bits = dst; ! 1191: bit.map[v] = 0; /* subfont now owns bitmap */ ! 1192: m -= 15; ! 1193: p += 15; ! 1194: fcp = f->info; ! 1195: for(j=0; j<=f->n; j++,fcp++){ ! 1196: fcp->x = BGSHORT(p); ! 1197: fcp->top = p[2]; ! 1198: fcp->bottom = p[3]; ! 1199: fcp->left = p[4]; ! 1200: fcp->width = p[5]; ! 1201: fcp->top = p[2]; ! 1202: p += 6; ! 1203: m -= 6; ! 1204: } ! 1205: bit.subfid = i; ! 1206: break; ! 1207: ! 1208: case 'l': ! 1209: /* ! 1210: * line segment ! 1211: * ! 1212: * 'l' 1 ! 1213: * id 2 ! 1214: * pt1 8 ! 1215: * pt2 8 ! 1216: * value 1 ! 1217: * code 2 ! 1218: */ ! 1219: if(m < 22) ! 1220: error(Ebadblt); ! 1221: v = BGSHORT(p+1); ! 1222: if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) ! 1223: error(Ebadbitmap); ! 1224: off = 0; ! 1225: fc = BGSHORT(p+20) & 0xF; ! 1226: if(v == 0){ ! 1227: if(flipping) ! 1228: fc = flipD[fc]; ! 1229: off = 1; ! 1230: } ! 1231: pt1.x = BGLONG(p+3); ! 1232: pt1.y = BGLONG(p+7); ! 1233: pt2.x = BGLONG(p+11); ! 1234: pt2.y = BGLONG(p+15); ! 1235: t = p[19]; ! 1236: if(off && !isoff){ ! 1237: cursoroff(1); ! 1238: isoff = 1; ! 1239: } ! 1240: gsegment(dst, pt1, pt2, t, fc); ! 1241: if(dst->base < endscreen){ ! 1242: mbbpt(pt1); ! 1243: mbbpt(pt2); ! 1244: } ! 1245: m -= 22; ! 1246: p += 22; ! 1247: break; ! 1248: ! 1249: case 'm': ! 1250: /* ! 1251: * read colormap ! 1252: * ! 1253: * 'm' 1 ! 1254: * id 2 ! 1255: */ ! 1256: if(m < 3) ! 1257: error(Ebadblt); ! 1258: v = BGSHORT(p+1); ! 1259: if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) ! 1260: error(Ebadbitmap); ! 1261: bit.mid = v; ! 1262: m -= 3; ! 1263: p += 3; ! 1264: break; ! 1265: ! 1266: case 'n': ! 1267: /* ! 1268: * allocate font ! 1269: * 'n' 1 ! 1270: * height 1 ! 1271: * ascent 1 ! 1272: * ldepth 2 ! 1273: * ncache 2 ! 1274: * next read returns allocated font id ! 1275: */ ! 1276: if(m < 7) ! 1277: error(Ebadblt); ! 1278: v = BGSHORT(p+3); ! 1279: t = BGSHORT(p+5); ! 1280: if(v<0 || t<0) ! 1281: error(Ebadblt); ! 1282: for(i=0; i<bit.nfont; i++) ! 1283: if(bit.font[i] == 0) ! 1284: goto fontfound; ! 1285: ffp = bitmalloc((bit.nfont+DMAP)*sizeof(GFont*)); ! 1286: if(ffp == 0) ! 1287: error(Enomem); ! 1288: memmove(ffp, bit.font, bit.nfont*sizeof(GFont*)); ! 1289: free(bit.font); ! 1290: bit.font = ffp; ! 1291: bit.nfont += DMAP; ! 1292: fontfound: ! 1293: ff = bitmalloc(sizeof(GFont)); ! 1294: if(ff == 0) ! 1295: error(Enomem); ! 1296: ff->ncache = t; ! 1297: ff->cache = bitmalloc(t*sizeof(GCacheinfo)); ! 1298: if(ff->cache == 0){ ! 1299: free(ff); ! 1300: error(Enomem); ! 1301: } ! 1302: bit.font[i] = ff; ! 1303: ff = bit.font[i]; ! 1304: ff->height = p[1]; ! 1305: ff->ascent = p[2]; ! 1306: ff->ldepth = v; ! 1307: ff->width = 0; ! 1308: ff->b = 0; ! 1309: m -= 7; ! 1310: p += 7; ! 1311: bit.fid = i; ! 1312: break; ! 1313: ! 1314: case 'p': ! 1315: /* ! 1316: * point ! 1317: * ! 1318: * 'p' 1 ! 1319: * id 2 ! 1320: * pt 8 ! 1321: * value 1 ! 1322: * code 2 ! 1323: */ ! 1324: if(m < 14) ! 1325: error(Ebadblt); ! 1326: v = BGSHORT(p+1); ! 1327: if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) ! 1328: error(Ebadbitmap); ! 1329: off = 0; ! 1330: fc = BGSHORT(p+12) & 0xF; ! 1331: if(v == 0){ ! 1332: if(flipping) ! 1333: fc = flipD[fc]; ! 1334: off = 1; ! 1335: } ! 1336: pt1.x = BGLONG(p+3); ! 1337: pt1.y = BGLONG(p+7); ! 1338: t = p[11]; ! 1339: if(off && !isoff){ ! 1340: cursoroff(1); ! 1341: isoff = 1; ! 1342: } ! 1343: gpoint(dst, pt1, t, fc); ! 1344: if(dst->base < endscreen) ! 1345: mbbpt(pt1); ! 1346: m -= 14; ! 1347: p += 14; ! 1348: break; ! 1349: ! 1350: case 'q': ! 1351: /* ! 1352: * clip rectangle ! 1353: * 'q' 1 ! 1354: * id 2 ! 1355: * rect 16 ! 1356: */ ! 1357: if(m < 19) ! 1358: error(Ebadblt); ! 1359: v = BGSHORT(p+1); ! 1360: if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) ! 1361: error(Ebadbitmap); ! 1362: rect.min.x = BGLONG(p+3); ! 1363: rect.min.y = BGLONG(p+7); ! 1364: rect.max.x = BGLONG(p+11); ! 1365: rect.max.y = BGLONG(p+15); ! 1366: if(rectclip(&rect, dst->r)) ! 1367: dst->clipr = rect; ! 1368: m -= 19; ! 1369: p += 19; ! 1370: break; ! 1371: ! 1372: case 'r': ! 1373: /* ! 1374: * read ! 1375: * 'r' 1 ! 1376: * src id 2 ! 1377: * miny 4 ! 1378: * maxy 4 ! 1379: */ ! 1380: if(m < 11) ! 1381: error(Ebadblt); ! 1382: v = BGSHORT(p+1); ! 1383: if(v<0 || v>=bit.nmap || (src=bit.map[v])==0) ! 1384: error(Ebadbitmap); ! 1385: miny = BGLONG(p+3); ! 1386: maxy = BGLONG(p+7); ! 1387: if(miny>maxy || miny<src->r.min.y || maxy>src->r.max.y) ! 1388: error(Ebadblt); ! 1389: bit.rid = v; ! 1390: bit.rminy = miny; ! 1391: bit.rmaxy = maxy; ! 1392: p += 11; ! 1393: m -= 11; ! 1394: break; ! 1395: ! 1396: case 's': ! 1397: /* ! 1398: * string ! 1399: * 's' 1 ! 1400: * id 2 ! 1401: * pt 8 ! 1402: * font id 2 ! 1403: * code 2 ! 1404: * n 2 ! 1405: * cache indices 2*n (not null terminated) ! 1406: */ ! 1407: if(m < 17) ! 1408: error(Ebadblt); ! 1409: v = BGSHORT(p+1); ! 1410: if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) ! 1411: error(Ebadbitmap); ! 1412: off = 0; ! 1413: fc = BGSHORT(p+13) & 0xF; ! 1414: if(v == 0){ ! 1415: if(flipping) ! 1416: fc = flipD[fc]; ! 1417: off = 1; ! 1418: } ! 1419: pt.x = BGLONG(p+3); ! 1420: pt.y = BGLONG(p+7); ! 1421: v = BGSHORT(p+11); ! 1422: if(v<0 || v>=bit.nfont || (ff=bit.font[v])==0) ! 1423: error(Ebadfont); ! 1424: l = BGSHORT(p+15)*2; ! 1425: p += 17; ! 1426: m -= 17; ! 1427: if(l > m) ! 1428: error(Ebadblt); ! 1429: if(off && !isoff){ ! 1430: cursoroff(1); ! 1431: isoff = 1; ! 1432: } ! 1433: bitstring(dst, pt, ff, p, l, fc); ! 1434: if(dst->base < endscreen) ! 1435: mbbrect(Rpt(pt, add(pt, bitstrsize(ff, p, l)))); ! 1436: m -= l; ! 1437: p += l; ! 1438: break; ! 1439: ! 1440: case 't': ! 1441: /* ! 1442: * texture ! 1443: * 't' 1 ! 1444: * dst id 2 ! 1445: * rect 16 ! 1446: * src id 2 ! 1447: * fcode 2 ! 1448: */ ! 1449: if(m < 23) ! 1450: error(Ebadblt); ! 1451: v = BGSHORT(p+1); ! 1452: if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) ! 1453: error(Ebadbitmap); ! 1454: off = 0; ! 1455: fc = BGSHORT(p+21) & 0xF; ! 1456: if(v == 0){ ! 1457: if(flipping) ! 1458: fc = flipD[fc]; ! 1459: off = 1; ! 1460: } ! 1461: rect.min.x = BGLONG(p+3); ! 1462: rect.min.y = BGLONG(p+7); ! 1463: rect.max.x = BGLONG(p+11); ! 1464: rect.max.y = BGLONG(p+15); ! 1465: v = BGSHORT(p+19); ! 1466: if(v<0 || v>=bit.nmap || (src=bit.map[v])==0) ! 1467: error(Ebadbitmap); ! 1468: if(off && !isoff){ ! 1469: cursoroff(1); ! 1470: isoff = 1; ! 1471: } ! 1472: gtexture(dst, rect, src, fc); ! 1473: if(dst->base < endscreen) ! 1474: mbbrect(rect); ! 1475: m -= 23; ! 1476: p += 23; ! 1477: break; ! 1478: ! 1479: case 'v': ! 1480: /* ! 1481: * clear font cache and bitmap. ! 1482: * if error, font is unchanged. ! 1483: * 'v' 1 ! 1484: * id 2 ! 1485: * ncache 2 ! 1486: * width 2 ! 1487: */ ! 1488: if(m < 7) ! 1489: error(Ebadblt); ! 1490: v = BGSHORT(p+1); ! 1491: t = BGSHORT(p+3); ! 1492: if(t<0 || v<0 || v>=bit.nfont || (ff=bit.font[v])==0) ! 1493: error(Ebadblt); ! 1494: x = BGSHORT(p+5); ! 1495: i = bitalloc(Rect(0, 0, t*x, ff->height), ff->ldepth); ! 1496: if(t != ff->ncache){ ! 1497: gc = bitmalloc(t*sizeof(ff->cache[0])); ! 1498: if(gc == 0){ ! 1499: bitfree(bit.map[i]); ! 1500: bit.map[i] = 0; ! 1501: error(Enomem); ! 1502: } ! 1503: free(ff->cache); ! 1504: ff->cache = gc; ! 1505: ff->ncache = t; ! 1506: }else{ ! 1507: /* ! 1508: * memset not necessary but helps avoid ! 1509: * confusion if the cache is mishandled by the ! 1510: * user. ! 1511: */ ! 1512: memset(ff->cache, 0, t*sizeof(ff->cache[0])); ! 1513: } ! 1514: if(ff->b) ! 1515: bitfree(ff->b); ! 1516: ff->b = bit.map[i]; ! 1517: bit.map[i] = 0; /* disconnect it from GBitmap space */ ! 1518: ff->width = x; ! 1519: p += 7; ! 1520: m -= 7; ! 1521: break; ! 1522: ! 1523: case 'w': ! 1524: /* ! 1525: * write ! 1526: * 'w' 1 ! 1527: * dst id 2 ! 1528: * miny 4 ! 1529: * maxy 4 ! 1530: * data bytewidth*(maxy-miny) ! 1531: */ ! 1532: if(m < 11) ! 1533: error(Ebadblt); ! 1534: v = BGSHORT(p+1); ! 1535: if(v<0 || v>=bit.nmap || (dst=bit.map[v])==0) ! 1536: error(Ebadbitmap); ! 1537: off = 0; ! 1538: if(v == 0) ! 1539: off = 1; ! 1540: miny = BGLONG(p+3); ! 1541: maxy = BGLONG(p+7); ! 1542: if(miny>maxy || miny<dst->r.min.y || maxy>dst->r.max.y) ! 1543: error(Ebadblt); ! 1544: ws = 1<<(3-dst->ldepth); /* pixels per byte */ ! 1545: /* set l to number of bytes of incoming data per scan line */ ! 1546: if(dst->r.min.x >= 0) ! 1547: l = (dst->r.max.x+ws-1)/ws - dst->r.min.x/ws; ! 1548: else{ /* make positive before divide */ ! 1549: t = (-dst->r.min.x)+ws-1; ! 1550: t = (t/ws)*ws; ! 1551: l = (t+dst->r.max.x+ws-1)/ws; ! 1552: } ! 1553: if(dst->base < endscreen) ! 1554: mbbrect(Rect(dst->r.min.x, miny, dst->r.max.x, maxy)); ! 1555: p += 11; ! 1556: m -= 11; ! 1557: if(m < l*(maxy-miny)) ! 1558: error(Ebadblt); ! 1559: if(off && !isoff){ ! 1560: cursoroff(1); ! 1561: isoff = 1; ! 1562: } ! 1563: for(y=miny; y<maxy; y++){ ! 1564: oq = (uchar*)gaddr(dst, Pt(dst->r.min.x, y)); ! 1565: q = oq + (dst->r.min.x&((sizeof(ulong))*ws-1))/ws; ! 1566: memmove(q, p, l); ! 1567: if(islittle) ! 1568: pixreverse(q, l, dst->ldepth); ! 1569: if(v==0 && flipping){ /* flip bits */ ! 1570: /* we know it's all word aligned */ ! 1571: lp = (ulong*)oq; ! 1572: for(x=0; x<l; x+=sizeof(ulong)) ! 1573: *lp++ ^= ~0; ! 1574: } ! 1575: p += l; ! 1576: m -= l; ! 1577: } ! 1578: if(v == 0) ! 1579: hwscreenwrite(miny, maxy); ! 1580: break; ! 1581: ! 1582: case 'x': ! 1583: /* ! 1584: * cursorset ! 1585: * ! 1586: * 'x' 1 ! 1587: * pt 8 ! 1588: */ ! 1589: if(m < 9) ! 1590: error(Ebadblt); ! 1591: pt1.x = BGLONG(p+1); ! 1592: pt1.y = BGLONG(p+5); ! 1593: if(ptinrect(pt1, gscreen.r)){ ! 1594: mouse.xy = pt1; ! 1595: mouse.redraw = 1; ! 1596: mouse.track = 1; ! 1597: mouseclock(); ! 1598: } ! 1599: m -= 9; ! 1600: p += 9; ! 1601: break; ! 1602: ! 1603: case 'y': ! 1604: /* ! 1605: * load font from subfont ! 1606: * 'y' 1 ! 1607: * id 2 ! 1608: * cache index 2 ! 1609: * subfont id 2 ! 1610: * subfont index 2 ! 1611: */ ! 1612: if(m < 9) ! 1613: error(Ebadblt); ! 1614: v = BGSHORT(p+1); ! 1615: if(v<0 || v>=bit.nfont || (ff=bit.font[v])==0) ! 1616: error(Ebadblt); ! 1617: if(ff->b == 0) ! 1618: error(Ebadbitmap); ! 1619: l = BGSHORT(p+3); ! 1620: if(l >= ff->ncache) ! 1621: error(Ebadblt); ! 1622: v = BGSHORT(p+5); ! 1623: if(v<0 || v>=bit.nsubfont || (f=bit.subfont[v])==0 || f->ref==0) ! 1624: error(Ebadfont); ! 1625: nw = BGSHORT(p+7); ! 1626: if(nw >= f->n) ! 1627: error(Ebadblt); ! 1628: bitloadchar(ff, l, f, nw); ! 1629: p += 9; ! 1630: m -= 9; ! 1631: break; ! 1632: ! 1633: case 'z': ! 1634: /* ! 1635: * write the colormap ! 1636: * ! 1637: * 'z' 1 ! 1638: * id 2 ! 1639: * map 12*(2**bitmapdepth) ! 1640: */ ! 1641: if(m < 3) ! 1642: error(Ebadblt); ! 1643: v = BGSHORT(p+1); ! 1644: if(v != 0) ! 1645: error(Ebadbitmap); ! 1646: m -= 3; ! 1647: p += 3; ! 1648: nw = 1 << (1 << gscreen.ldepth); ! 1649: if(m < 12*nw) ! 1650: error(Ebadblt); ! 1651: ok = 1; ! 1652: for(i = 0; i < nw; i++){ ! 1653: ok &= setcolor(flipping ? ~i : i, BGLONG(p), BGLONG(p+4), BGLONG(p+8)); ! 1654: p += 12; ! 1655: m -= 12; ! 1656: } ! 1657: if(!ok){ ! 1658: /* assume monochrome: possibly change flipping */ ! 1659: l = BGLONG(p-12); ! 1660: getcolor(nw-1, &rv, &rv, &rv); ! 1661: flipping = (l != rv); ! 1662: } ! 1663: break; ! 1664: } ! 1665: ! 1666: poperror(); ! 1667: if(isoff) ! 1668: cursoron(1); ! 1669: screenupdate(); ! 1670: qunlock(&bit); ! 1671: return n; ! 1672: } ! 1673: ! 1674: int ! 1675: bitalloc(Rectangle rect, int ld) ! 1676: { ! 1677: Arena *a, *ea, *aa; ! 1678: GBitmap *b, **bp, **ep; ! 1679: ulong l, ws, nw; ! 1680: long t; ! 1681: ! 1682: ws = BI2WD>>ld; /* pixels per word */ ! 1683: if(rect.min.x >= 0){ ! 1684: l = (rect.max.x+ws-1)/ws; ! 1685: l -= rect.min.x/ws; ! 1686: }else{ /* make positive before divide */ ! 1687: t = (-rect.min.x)+ws-1; ! 1688: t = (t/ws)*ws; ! 1689: l = (t+rect.max.x+ws-1)/ws; ! 1690: } ! 1691: nw = l*Dy(rect); ! 1692: ea = &bit.arena[bit.narena]; ! 1693: ! 1694: /* first try easy fit */ ! 1695: for(a=bit.arena; a<ea; a++){ ! 1696: if(a->words == 0) ! 1697: continue; ! 1698: if(a->wfree+HDR+nw <= a->words+a->nwords) ! 1699: goto found; ! 1700: } ! 1701: ! 1702: /* compact and try again */ ! 1703: bitcompact(); ! 1704: aa = 0; ! 1705: for(a=bit.arena; a<ea; a++){ ! 1706: if(a->words == 0){ ! 1707: if(aa == 0) ! 1708: aa = a; ! 1709: continue; ! 1710: } ! 1711: if(a->wfree+HDR+nw <= a->words+a->nwords) ! 1712: goto found; ! 1713: } ! 1714: ! 1715: /* need new arena */ ! 1716: if(aa){ ! 1717: a = aa; ! 1718: a->nwords = HDR + (gscreen.r.max.y*gscreen.r.max.x)/ws; ! 1719: if(a->nwords < HDR+nw) ! 1720: a->nwords = HDR+nw; ! 1721: a->words = xalloc(a->nwords*sizeof(ulong)); ! 1722: if(a->words){ ! 1723: a->wfree = a->words; ! 1724: a->nbusy = 0; ! 1725: goto found; ! 1726: } ! 1727: } ! 1728: /* else can't grow list: bitmaps have backpointers */ ! 1729: ! 1730: bitfreeup(); ! 1731: ! 1732: for(a=bit.arena; a<ea; a++){ ! 1733: if(a->words == 0) ! 1734: continue; ! 1735: if(a->wfree+HDR+nw <= a->words+a->nwords) ! 1736: goto found; ! 1737: } ! 1738: if(a == ea) ! 1739: error(Enobitstore); ! 1740: ! 1741: found: ! 1742: b = bitmalloc(sizeof(GBitmap)); ! 1743: if(b == 0) ! 1744: error(Enomem); ! 1745: *a->wfree++ = nw; ! 1746: *a->wfree++ = (ulong)a; ! 1747: *a->wfree++ = (ulong)b; ! 1748: memset(a->wfree, 0, nw*sizeof(ulong)); ! 1749: b->base = a->wfree; ! 1750: a->wfree += nw; ! 1751: a->nbusy++; ! 1752: b->zero = l*rect.min.y; ! 1753: if(rect.min.x >= 0) ! 1754: b->zero += rect.min.x/ws; ! 1755: else ! 1756: b->zero -= (-rect.min.x+ws-1)/ws; ! 1757: b->zero = -b->zero; ! 1758: b->width = l; ! 1759: b->ldepth = ld; ! 1760: b->r = rect; ! 1761: b->clipr = rect; ! 1762: b->cache = 0; ! 1763: /* worth doing better than linear lookup? */ ! 1764: ep = bit.map+bit.nmap; ! 1765: for(bp=bit.map; bp<ep; bp++) ! 1766: if(*bp == 0) ! 1767: break; ! 1768: if(bp == ep){ ! 1769: bp = bitmalloc((bit.nmap+DMAP)*sizeof(GBitmap*)); ! 1770: if(bp == 0){ ! 1771: bitfree(b); ! 1772: error(Enomem); ! 1773: } ! 1774: memmove(bp, bit.map, bit.nmap*sizeof(GBitmap*)); ! 1775: free(bit.map); ! 1776: bit.map = bp; ! 1777: bp += bit.nmap; ! 1778: bit.nmap += DMAP; ! 1779: } ! 1780: *bp = b; ! 1781: return bp-bit.map; ! 1782: } ! 1783: ! 1784: void ! 1785: bitfree(GBitmap *b) ! 1786: { ! 1787: Arena *a; ! 1788: ! 1789: if(b->base != gscreen.base){ /* can't free screen memory */ ! 1790: a = (Arena*)(b->base[-2]); ! 1791: a->nbusy--; ! 1792: if(a->nbusy == 0) ! 1793: arenafree(a); ! 1794: b->base[-1] = 0; ! 1795: } ! 1796: free(b); ! 1797: } ! 1798: ! 1799: void ! 1800: fontfree(GFont *f) ! 1801: { ! 1802: if(f->b) ! 1803: bitfree(f->b); ! 1804: free(f->cache); ! 1805: free(f); ! 1806: } ! 1807: ! 1808: void ! 1809: subfontfree(BSubfont *s, int i) ! 1810: { ! 1811: if(s!=bdefont && s->ref>0){ /* don't free subfont 0, bdefont */ ! 1812: s->ref--; ! 1813: if(s->ref==0 && s->qid[0]==~0){ /* uncached */ ! 1814: bitfree(s->bits); ! 1815: free(s->info); ! 1816: free(s); ! 1817: bit.subfont[i] = 0; ! 1818: } ! 1819: } ! 1820: return; ! 1821: } ! 1822: ! 1823: void ! 1824: arenafree(Arena *a) ! 1825: { ! 1826: xfree(a->words); ! 1827: a->words = 0; ! 1828: } ! 1829: ! 1830: void ! 1831: bitstring(GBitmap *bp, Point pt, GFont *f, uchar *p, long l, Fcode fc) ! 1832: { ! 1833: int full; ! 1834: Rectangle rect; ! 1835: ushort r; ! 1836: GCacheinfo *c; ! 1837: int x; ! 1838: Fcode clr; ! 1839: ! 1840: clr = 0; ! 1841: full = (fc&~S)^(D&~S); /* result involves source */ ! 1842: if(full){ ! 1843: rect.min.y = 0; ! 1844: rect.max.y = f->height; ! 1845: /* set clr to result under fc if source pixel is zero */ ! 1846: /* hard to do without knowing layout of bits, so we cheat */ ! 1847: clr = (fc&3); /* fc&3 is result if source is zero */ ! 1848: clr |= clr<<2; /* fc&(3<<2) is result if source is one */ ! 1849: } ! 1850: ! 1851: while(l > 0){ ! 1852: r = BGSHORT(p); ! 1853: p += 2; ! 1854: l -= 2; ! 1855: if(r >= f->ncache) ! 1856: continue; ! 1857: c = &f->cache[r]; ! 1858: if(!full){ ! 1859: rect.min.y = c->top; ! 1860: rect.max.y = c->bottom; ! 1861: }else{ ! 1862: if(c->left > 0) ! 1863: gbitblt(bp, pt, bp, ! 1864: Rect(pt.x, pt.y, pt.x+c->left, pt.y+f->height), ! 1865: clr); ! 1866: x = c->left+(c->xright-c->x); ! 1867: if(x < c->width) ! 1868: gbitblt(bp, Pt(pt.x+x, pt.y), bp, ! 1869: Rect(pt.x+x, pt.y, pt.x+c->width, pt.y+f->height), ! 1870: clr); ! 1871: } ! 1872: rect.min.x = c->x; ! 1873: rect.max.x = c->xright; ! 1874: gbitblt(bp, Pt(pt.x+c->left, pt.y+rect.min.y), f->b, rect, fc); ! 1875: pt.x += c->width; ! 1876: } ! 1877: } ! 1878: ! 1879: void ! 1880: bitloadchar(GFont *f, int ci, GSubfont *subf, int si) ! 1881: { ! 1882: GCacheinfo *c; ! 1883: Rectangle rect; ! 1884: Fontchar *fi; ! 1885: int y; ! 1886: ! 1887: c = &f->cache[ci]; ! 1888: fi = &subf->info[si]; ! 1889: /* careful about sign extension: top and bottom are uchars */ ! 1890: y = fi->top + (f->ascent-subf->ascent); ! 1891: if(y < 0) ! 1892: y = 0; ! 1893: c->top = y; ! 1894: y = fi->bottom + (f->ascent-subf->ascent); ! 1895: if(y < 0) ! 1896: y = 0; ! 1897: c->bottom = y; ! 1898: c->width = fi->width; ! 1899: c->left = fi->left; ! 1900: c->x = ci*f->width; ! 1901: c->xright = c->x + ((fi+1)->x - fi->x); ! 1902: rect.min.y = 0; ! 1903: rect.max.y = f->height; ! 1904: rect.min.x = c->x; ! 1905: rect.max.x = c->x+f->width; ! 1906: gbitblt(f->b, rect.min, f->b, rect, 0); ! 1907: rect.min.x = fi->x; ! 1908: rect.max.x = (fi+1)->x; ! 1909: rect.max.y = subf->height; ! 1910: gbitblt(f->b, Pt(c->x, f->ascent-subf->ascent), subf->bits, rect, S); ! 1911: } ! 1912: ! 1913: QLock bitlock; ! 1914: ! 1915: GBitmap* ! 1916: id2bit(int v) ! 1917: { ! 1918: GBitmap *bp=0; ! 1919: ! 1920: if(v<0 || v>=bit.nmap || (bp=bit.map[v])==0) ! 1921: error(Ebadbitmap); ! 1922: return bp; ! 1923: } ! 1924: ! 1925: void ! 1926: bitcompact(void) ! 1927: { ! 1928: Arena *a, *ea, *na; ! 1929: ulong *p1, *p2, n; ! 1930: ! 1931: qlock(&bitlock); ! 1932: ea = &bit.arena[bit.narena]; ! 1933: for(a=bit.arena; a<ea; a++){ ! 1934: if(a->words == 0) ! 1935: continue; ! 1936: /* first compact what's here */ ! 1937: p1 = p2 = a->words; ! 1938: while(p2 < a->wfree){ ! 1939: n = HDR+p2[0]; ! 1940: if(p2[2] == 0){ ! 1941: p2 += n; ! 1942: continue; ! 1943: } ! 1944: if(p1 != p2){ ! 1945: memmove(p1, p2, n*sizeof(ulong)); ! 1946: ((GBitmap*)p1[2])->base = p1+HDR; ! 1947: } ! 1948: p2 += n; ! 1949: p1 += n; ! 1950: } ! 1951: /* now pull stuff from later arena to fill this one */ ! 1952: na = a+1; ! 1953: while(na<ea && p1<a->words+a->nwords){ ! 1954: p2 = na->words; ! 1955: if(p2 == 0){ ! 1956: na++; ! 1957: continue; ! 1958: } ! 1959: while(p2 < na->wfree){ ! 1960: n = HDR+p2[0]; ! 1961: if(p2[2] == 0){ ! 1962: p2 += n; ! 1963: continue; ! 1964: } ! 1965: if(p1+n < a->words+a->nwords){ ! 1966: memmove(p1, p2, n*sizeof(ulong)); ! 1967: ((GBitmap*)p1[2])->base = p1+HDR; ! 1968: /* block now in new arena... */ ! 1969: p1[1] = (ulong)a; ! 1970: a->nbusy++; ! 1971: /* ... not in old arena */ ! 1972: na->nbusy--; ! 1973: p2[2] = 0; ! 1974: p1 += n; ! 1975: } ! 1976: p2 += n; ! 1977: } ! 1978: na++; ! 1979: } ! 1980: a->wfree = p1; ! 1981: } ! 1982: for(a=bit.arena; a<ea; a++) ! 1983: if(a->words && a->nbusy==0) ! 1984: arenafree(a); ! 1985: qunlock(&bitlock); ! 1986: } ! 1987: ! 1988: void ! 1989: Cursortocursor(Cursor *c) ! 1990: { ! 1991: lock(&cursor); ! 1992: memmove(&cursor, c, sizeof(Cursor)); ! 1993: setcursor(c); ! 1994: unlock(&cursor); ! 1995: } ! 1996: ! 1997: int ! 1998: cursoron(int dolock) ! 1999: { ! 2000: int ret; ! 2001: ! 2002: if(dolock) ! 2003: lock(&cursor); ! 2004: ret = 0; ! 2005: if(hwcurs) ! 2006: ret = hwgcmove(mouse.xy); ! 2007: else if(cursor.visible++ == 0){ ! 2008: cursor.r.min = mouse.xy; ! 2009: cursor.r.max = add(mouse.xy, Pt(16, 16)); ! 2010: cursor.r = raddp(cursor.r, cursor.offset); ! 2011: gbitblt(&cursorback, Pt(0, 0), &gscreen, cursor.r, S); ! 2012: gbitblt(&gscreen, cursor.r.min, ! 2013: &clr, Rect(0, 0, 16, 16), flipping? flipD[D&~S] : D&~S); ! 2014: gbitblt(&gscreen, cursor.r.min, ! 2015: &set, Rect(0, 0, 16, 16), flipping? flipD[S|D] : S|D); ! 2016: mbbrect(cursor.r); ! 2017: } ! 2018: if(dolock) ! 2019: unlock(&cursor); ! 2020: ! 2021: return ret; ! 2022: } ! 2023: ! 2024: void ! 2025: cursoroff(int dolock) ! 2026: { ! 2027: if(hwcurs) ! 2028: return; ! 2029: if(dolock) ! 2030: lock(&cursor); ! 2031: if(--cursor.visible == 0) { ! 2032: gbitblt(&gscreen, cursor.r.min, &cursorback, Rect(0, 0, 16, 16), S); ! 2033: mbbrect(cursor.r); ! 2034: mousescreenupdate(); ! 2035: } ! 2036: if(dolock) ! 2037: unlock(&cursor); ! 2038: } ! 2039: ! 2040: /* ! 2041: * called by the clock routine to redraw the cursor ! 2042: */ ! 2043: void ! 2044: mouseclock(void) ! 2045: { ! 2046: if(mouse.track){ ! 2047: mousetrack(mouse.buttons, mouse.dx, mouse.dy); ! 2048: mouse.track = 0; ! 2049: mouse.dx = 0; ! 2050: mouse.dy = 0; ! 2051: } ! 2052: if(mouse.redraw && canlock(&cursor)){ ! 2053: mouse.redraw = 0; ! 2054: cursoroff(0); ! 2055: mouse.redraw = cursoron(0); ! 2056: mousescreenupdate(); ! 2057: unlock(&cursor); ! 2058: } ! 2059: } ! 2060: ! 2061: /* ! 2062: * called at interrupt level to update the structure and ! 2063: * awaken any waiting procs. ! 2064: */ ! 2065: void ! 2066: mousetrack(int b, int dx, int dy) ! 2067: { ! 2068: int x, y; ! 2069: ! 2070: x = mouse.xy.x + dx; ! 2071: if(x < gscreen.r.min.x) ! 2072: x = gscreen.r.min.x; ! 2073: if(x >= gscreen.r.max.x) ! 2074: x = gscreen.r.max.x; ! 2075: y = mouse.xy.y + dy; ! 2076: if(y < gscreen.r.min.y) ! 2077: y = gscreen.r.min.y; ! 2078: if(y >= gscreen.r.max.y) ! 2079: y = gscreen.r.max.y; ! 2080: mouse.counter++; ! 2081: mouse.xy = Pt(x, y); ! 2082: mouse.buttons = b; ! 2083: mouse.redraw = 1; ! 2084: wakeup(&mouse.r); ! 2085: } ! 2086: ! 2087: /* ! 2088: * microsoft 3 button, 7 bit bytes ! 2089: * ! 2090: * byte 0 - 1 L R Y7 Y6 X7 X6 ! 2091: * byte 1 - 0 X5 X4 X3 X2 X1 X0 ! 2092: * byte 2 - 0 Y5 Y4 Y3 Y2 Y1 Y0 ! 2093: * byte 3 - 0 M x x x x x (optional) ! 2094: * ! 2095: * shift & right button is the same as middle button (for 2 button mice) ! 2096: */ ! 2097: int ! 2098: m3mouseputc(IOQ *q, int c) ! 2099: { ! 2100: static uchar msg[3]; ! 2101: static int nb; ! 2102: static int middle; ! 2103: static uchar b[] = { 0, 4, 1, 5, 0, 2, 1, 5 }; ! 2104: short x; ! 2105: int dx, dy, newbuttons; ! 2106: ! 2107: USED(q); ! 2108: /* ! 2109: * check bit 6 for consistency ! 2110: */ ! 2111: if(nb==0){ ! 2112: if((c&0x40) == 0){ ! 2113: /* an extra byte gets sent for the middle button */ ! 2114: middle = (c&0x20) ? 2 : 0; ! 2115: newbuttons = (mouse.buttons & ~2) | middle; ! 2116: mousetrack(newbuttons, 0, 0); ! 2117: return 0; ! 2118: } ! 2119: } ! 2120: msg[nb] = c; ! 2121: if(++nb == 3){ ! 2122: nb = 0; ! 2123: newbuttons = middle | b[(msg[0]>>4)&3 | (mouseshifted ? 4 : 0)]; ! 2124: x = (msg[0]&0x3)<<14; ! 2125: dx = (x>>8) | msg[1]; ! 2126: x = (msg[0]&0xc)<<12; ! 2127: dy = (x>>8) | msg[2]; ! 2128: mousetrack(newbuttons, dx, dy); ! 2129: } ! 2130: return 0; ! 2131: } ! 2132: ! 2133: /* ! 2134: * Logitech 5 byte packed binary mouse format, 8 bit bytes ! 2135: * ! 2136: * shift & right button is the same as middle button (for 2 button mice) ! 2137: */ ! 2138: int ! 2139: mouseputc(IOQ *q, int c) ! 2140: { ! 2141: static short msg[5]; ! 2142: static int nb; ! 2143: static uchar b[] = {0, 4, 2, 6, 1, 5, 3, 7, 0, 2, 2, 6, 1, 5, 3, 7}; ! 2144: int dx, dy, newbuttons; ! 2145: ! 2146: USED(q); ! 2147: if((c&0xF0) == 0x80) ! 2148: nb=0; ! 2149: msg[nb] = c; ! 2150: if(c & 0x80) ! 2151: msg[nb] |= ~0xFF; /* sign extend */ ! 2152: if(++nb == 5){ ! 2153: newbuttons = b[((msg[0]&7)^7) | (mouseshifted ? 8 : 0)]; ! 2154: dx = msg[1]+msg[3]; ! 2155: dy = -(msg[2]+msg[4]); ! 2156: mousetrack(newbuttons, dx, dy); ! 2157: nb = 0; ! 2158: } ! 2159: return 0; ! 2160: } ! 2161: ! 2162: int ! 2163: mousechanged(void *m) ! 2164: { ! 2165: USED(m); ! 2166: return mouse.lastcounter != mouse.counter; ! 2167: } ! 2168: ! 2169: /* ! 2170: * reverse pixels into little endian order ! 2171: */ ! 2172: uchar revtab0[] = { ! 2173: 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, ! 2174: 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, ! 2175: 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, ! 2176: 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, ! 2177: 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, ! 2178: 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, ! 2179: 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, ! 2180: 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, ! 2181: 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, ! 2182: 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, ! 2183: 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, ! 2184: 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, ! 2185: 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, ! 2186: 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, ! 2187: 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, ! 2188: 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, ! 2189: 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, ! 2190: 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, ! 2191: 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, ! 2192: 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, ! 2193: 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, ! 2194: 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, ! 2195: 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, ! 2196: 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, ! 2197: 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, ! 2198: 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, ! 2199: 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, ! 2200: 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, ! 2201: 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, ! 2202: 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, ! 2203: 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, ! 2204: 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, ! 2205: }; ! 2206: uchar revtab1[] = { ! 2207: 0x00, 0x40, 0x80, 0xc0, 0x10, 0x50, 0x90, 0xd0, ! 2208: 0x20, 0x60, 0xa0, 0xe0, 0x30, 0x70, 0xb0, 0xf0, ! 2209: 0x04, 0x44, 0x84, 0xc4, 0x14, 0x54, 0x94, 0xd4, ! 2210: 0x24, 0x64, 0xa4, 0xe4, 0x34, 0x74, 0xb4, 0xf4, ! 2211: 0x08, 0x48, 0x88, 0xc8, 0x18, 0x58, 0x98, 0xd8, ! 2212: 0x28, 0x68, 0xa8, 0xe8, 0x38, 0x78, 0xb8, 0xf8, ! 2213: 0x0c, 0x4c, 0x8c, 0xcc, 0x1c, 0x5c, 0x9c, 0xdc, ! 2214: 0x2c, 0x6c, 0xac, 0xec, 0x3c, 0x7c, 0xbc, 0xfc, ! 2215: 0x01, 0x41, 0x81, 0xc1, 0x11, 0x51, 0x91, 0xd1, ! 2216: 0x21, 0x61, 0xa1, 0xe1, 0x31, 0x71, 0xb1, 0xf1, ! 2217: 0x05, 0x45, 0x85, 0xc5, 0x15, 0x55, 0x95, 0xd5, ! 2218: 0x25, 0x65, 0xa5, 0xe5, 0x35, 0x75, 0xb5, 0xf5, ! 2219: 0x09, 0x49, 0x89, 0xc9, 0x19, 0x59, 0x99, 0xd9, ! 2220: 0x29, 0x69, 0xa9, 0xe9, 0x39, 0x79, 0xb9, 0xf9, ! 2221: 0x0d, 0x4d, 0x8d, 0xcd, 0x1d, 0x5d, 0x9d, 0xdd, ! 2222: 0x2d, 0x6d, 0xad, 0xed, 0x3d, 0x7d, 0xbd, 0xfd, ! 2223: 0x02, 0x42, 0x82, 0xc2, 0x12, 0x52, 0x92, 0xd2, ! 2224: 0x22, 0x62, 0xa2, 0xe2, 0x32, 0x72, 0xb2, 0xf2, ! 2225: 0x06, 0x46, 0x86, 0xc6, 0x16, 0x56, 0x96, 0xd6, ! 2226: 0x26, 0x66, 0xa6, 0xe6, 0x36, 0x76, 0xb6, 0xf6, ! 2227: 0x0a, 0x4a, 0x8a, 0xca, 0x1a, 0x5a, 0x9a, 0xda, ! 2228: 0x2a, 0x6a, 0xaa, 0xea, 0x3a, 0x7a, 0xba, 0xfa, ! 2229: 0x0e, 0x4e, 0x8e, 0xce, 0x1e, 0x5e, 0x9e, 0xde, ! 2230: 0x2e, 0x6e, 0xae, 0xee, 0x3e, 0x7e, 0xbe, 0xfe, ! 2231: 0x03, 0x43, 0x83, 0xc3, 0x13, 0x53, 0x93, 0xd3, ! 2232: 0x23, 0x63, 0xa3, 0xe3, 0x33, 0x73, 0xb3, 0xf3, ! 2233: 0x07, 0x47, 0x87, 0xc7, 0x17, 0x57, 0x97, 0xd7, ! 2234: 0x27, 0x67, 0xa7, 0xe7, 0x37, 0x77, 0xb7, 0xf7, ! 2235: 0x0b, 0x4b, 0x8b, 0xcb, 0x1b, 0x5b, 0x9b, 0xdb, ! 2236: 0x2b, 0x6b, 0xab, 0xeb, 0x3b, 0x7b, 0xbb, 0xfb, ! 2237: 0x0f, 0x4f, 0x8f, 0xcf, 0x1f, 0x5f, 0x9f, 0xdf, ! 2238: 0x2f, 0x6f, 0xaf, 0xef, 0x3f, 0x7f, 0xbf, 0xff, ! 2239: }; ! 2240: uchar revtab2[] = { ! 2241: 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, ! 2242: 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, ! 2243: 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, ! 2244: 0x81, 0x91, 0xa1, 0xb1, 0xc1, 0xd1, 0xe1, 0xf1, ! 2245: 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, ! 2246: 0x82, 0x92, 0xa2, 0xb2, 0xc2, 0xd2, 0xe2, 0xf2, ! 2247: 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, ! 2248: 0x83, 0x93, 0xa3, 0xb3, 0xc3, 0xd3, 0xe3, 0xf3, ! 2249: 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, ! 2250: 0x84, 0x94, 0xa4, 0xb4, 0xc4, 0xd4, 0xe4, 0xf4, ! 2251: 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, ! 2252: 0x85, 0x95, 0xa5, 0xb5, 0xc5, 0xd5, 0xe5, 0xf5, ! 2253: 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, ! 2254: 0x86, 0x96, 0xa6, 0xb6, 0xc6, 0xd6, 0xe6, 0xf6, ! 2255: 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, ! 2256: 0x87, 0x97, 0xa7, 0xb7, 0xc7, 0xd7, 0xe7, 0xf7, ! 2257: 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, ! 2258: 0x88, 0x98, 0xa8, 0xb8, 0xc8, 0xd8, 0xe8, 0xf8, ! 2259: 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, ! 2260: 0x89, 0x99, 0xa9, 0xb9, 0xc9, 0xd9, 0xe9, 0xf9, ! 2261: 0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a, 0x6a, 0x7a, ! 2262: 0x8a, 0x9a, 0xaa, 0xba, 0xca, 0xda, 0xea, 0xfa, ! 2263: 0x0b, 0x1b, 0x2b, 0x3b, 0x4b, 0x5b, 0x6b, 0x7b, ! 2264: 0x8b, 0x9b, 0xab, 0xbb, 0xcb, 0xdb, 0xeb, 0xfb, ! 2265: 0x0c, 0x1c, 0x2c, 0x3c, 0x4c, 0x5c, 0x6c, 0x7c, ! 2266: 0x8c, 0x9c, 0xac, 0xbc, 0xcc, 0xdc, 0xec, 0xfc, ! 2267: 0x0d, 0x1d, 0x2d, 0x3d, 0x4d, 0x5d, 0x6d, 0x7d, ! 2268: 0x8d, 0x9d, 0xad, 0xbd, 0xcd, 0xdd, 0xed, 0xfd, ! 2269: 0x0e, 0x1e, 0x2e, 0x3e, 0x4e, 0x5e, 0x6e, 0x7e, ! 2270: 0x8e, 0x9e, 0xae, 0xbe, 0xce, 0xde, 0xee, 0xfe, ! 2271: 0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f, ! 2272: 0x8f, 0x9f, 0xaf, 0xbf, 0xcf, 0xdf, 0xef, 0xff, ! 2273: }; ! 2274: ! 2275: void ! 2276: pixreverse(uchar *p, int len, int ldepth) ! 2277: { ! 2278: uchar *e; ! 2279: uchar *tab; ! 2280: ! 2281: switch(ldepth){ ! 2282: case 0: ! 2283: tab = revtab0; ! 2284: break; ! 2285: case 1: ! 2286: tab = revtab1; ! 2287: break; ! 2288: case 2: ! 2289: tab = revtab2; ! 2290: break; ! 2291: default: ! 2292: return; ! 2293: } ! 2294: ! 2295: for(e = p + len; p < e; p++) ! 2296: *p = tab[*p]; ! 2297: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.