|
|
1.1 ! root 1: #include <jerq.h> ! 2: #include <font.h> ! 3: #include "anim.h" ! 4: ! 5: #define PTR (Texture *)0 ! 6: ! 7: Texture danger = { ! 8: 0x0180, 0x0240, 0x0420, 0x0990, 0x1188, 0x2184, 0x4182, 0x8181, ! 9: 0x8181, 0x4182, 0x2004, 0x1188, 0x0990, 0x0420, 0x0240, 0x0180, }; ! 10: Texture bullseye = { ! 11: 0x07E0, 0x1FF8, 0x399C, 0x63C6, 0x6FF6, 0xCDB3, 0xD99B, 0xFFFF, ! 12: 0xFFFF, 0xD99B, 0xCDB3, 0x6FF6, 0x63C6, 0x399C, 0x1FF8, 0x07E0, }; ! 13: Texture coffee = { ! 14: 0x0000, 0x0380, 0x0400, 0x03E0, 0x0010, 0x07E0, 0x1FFC, 0x1002, ! 15: 0x101A, 0x101A, 0x1002, 0x103C, 0x1810, 0x0FE0, 0x0000, 0x3FFC, }; ! 16: Texture deadmouse = { ! 17: 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x000C, 0x0082, 0x0441, ! 18: 0xFFE1, 0x5FF1, 0x3FFE, 0x17F0, 0x03E0, 0x0000, 0x0000, 0x0000, }; ! 19: Texture skull ={ ! 20: 0x0000, 0x0000, 0x0000, 0xC003, 0xE7E7, 0x3FFC, 0x0FF0, 0x0DB0, ! 21: 0x07E0, 0x0660, 0x37EC, 0xE427, 0xC3C3, 0x0000, 0x0000, 0x0000, }; ! 22: ! 23: #define Do Drect.origin ! 24: #define Dc Drect.corner ! 25: #define kbdrect Rect(Do.x+4, Do.y+4, Dc.x+4, Do.y+16+4) ! 26: ! 27: char kbdline[100]; /* keyboard input collects here */ ! 28: char *pkbd = kbdline; ! 29: ! 30: typedef unsigned char uchar; ! 31: ! 32: #define PUT { char buf[100]; sprintf(buf, ! 33: #define END ); putstring(buf); } ! 34: #define readpoint(p) { p.x = readint(); p.y = readint(); } ! 35: #define readpair(p1,p2) { readpoint(p1); readpoint(p2); } ! 36: ! 37: /* holds data for all input objects */ ! 38: ! 39: unsigned memsize; /* bytes */ ! 40: uchar *inbuf; /* input collected here */ ! 41: uchar *input; /* leave a null at front */ ! 42: uchar *inp; /* next free slot in input */ ! 43: int nobj = 0; /* number of objects in input */ ! 44: int overflow = 0; /* 1 => too much input */ ! 45: ! 46: long slot[2000]; /* slots */ ! 47: int slotnum; ! 48: ! 49: extern uchar *savechar(), *draw_obj(), *click_obj(), *step_obj(); ! 50: extern uchar *prev_obj(), *next_obj(); ! 51: ! 52: extern Point readpt(), fetchpt(), scalept(); ! 53: int xmax, ymax; ! 54: ! 55: #define MAXVIEW 10 ! 56: char *viewname[MAXVIEW]; ! 57: typedef struct { ! 58: Rectangle vr; ! 59: int xmax; ! 60: int ymax; ! 61: } View; ! 62: View viewpt[MAXVIEW]; ! 63: int curview = 0; ! 64: int nview = 0; ! 65: #define INSET 4 /* picture inset from frame */ ! 66: ! 67: #define AW 8 /* arrowhead width and height */ ! 68: #define AH 10 ! 69: ! 70: #define MARGINPCT 6 ! 71: int margin = MARGINPCT; /* percent margin around edges */ ! 72: ! 73: #define MAXCLICK 20 ! 74: char *clickname[MAXCLICK]; /* click names */ ! 75: int clickval[MAXCLICK]; /* 1 => click on this */ ! 76: int clicking = 0; /* number of active clicks */ ! 77: int nclick = 0; ! 78: ! 79: char buf[200]; ! 80: char *pbuf; ! 81: ! 82: #define Again 0 /* Menu items -- must be 0.. */ ! 83: #define Faster (Again+1) ! 84: #define Slower (Faster+1) ! 85: #define Step (Slower+1) ! 86: #define Forward (Step+1) ! 87: #define Fatter (Forward+1) ! 88: #define Thinner (Fatter+1) ! 89: #define Xor (Thinner+1) ! 90: #define File (Xor+1) ! 91: #define Quit (File+1) /* ... down this far */ ! 92: #define Backward (Quit+1) /* subsequent names are arbitrary */ ! 93: #define Proceed (Backward+1) ! 94: #define Hit (Proceed+1) ! 95: ! 96: int delay = 1; /* how long to delay between things */ ! 97: int singstep = 0; /* single step if 1 */ ! 98: #define Fwd 1 ! 99: #define Back 0 ! 100: int dir = Fwd; /* 1 = fwd, 0 = backward */ ! 101: int fatness = 0; /* n => draw with 2n+1 lines */ ! 102: int xormode = F_XOR; /* otherwise OR/CLR */ ! 103: ! 104: char *m3[] = { "again", "faster", "slower", "1 step", "backward", ! 105: "fatter", "thinner", "or mode", "new file", "Quit?", 0 }; ! 106: char *stepmenu[] = { "1 step", "run" }; ! 107: char *dirmenu[] = { "forward", "backward" }; ! 108: char *modemenu[] = { "or mode", "xor mode" }; ! 109: ! 110: char *m3gen(n) ! 111: { ! 112: static char buf[50]; ! 113: extern int delay; ! 114: ! 115: if (n < 0 || n > Quit) ! 116: return 0; ! 117: else if (n == Faster) { ! 118: sprintf(buf, "faster %d", delay); ! 119: return buf; ! 120: } else if (n == Slower) { ! 121: sprintf(buf, "slower %d", delay); ! 122: return buf; ! 123: } else if (n == Step) { ! 124: return stepmenu[singstep]; ! 125: } else if (n == Forward) { ! 126: return dirmenu[dir]; ! 127: } else if (n == Fatter) { ! 128: sprintf(buf, "fatter %d", fatness+1); ! 129: return buf; ! 130: } else if (n == Thinner) { ! 131: sprintf(buf, "thinner %d", fatness+1); ! 132: return buf; ! 133: } else if (n == Xor) { ! 134: return xormode == F_XOR ? modemenu[0] : modemenu[1]; ! 135: } else ! 136: return m3[n]; ! 137: } ! 138: ! 139: char *m2gen(n) ! 140: { ! 141: static char buf[50]; ! 142: ! 143: if (n < 0 || n >= nview+nclick) ! 144: return 0; ! 145: else if (n < nview) { ! 146: sprintf(buf, "view %s", viewname[n]); ! 147: return buf; ! 148: } else { ! 149: sprintf(buf, "click %s%s", ! 150: clickname[n-nview], clickval[n-nview] ? "*" : ""); ! 151: return buf; ! 152: } ! 153: } ! 154: ! 155: #ifdef V9 ! 156: Menu mbut3 = { (char **) 0, m3gen }; ! 157: Menu mbut2 = { (char **) 0, m2gen }; ! 158: #else ! 159: Menu mbut3 = { (char **) 0, 0,0,m3gen }; ! 160: Menu mbut2 = { (char **) 0, 0,0,m2gen }; ! 161: #endif ! 162: int last_hit; ! 163: int last_but; ! 164: ! 165: init_params() ! 166: { ! 167: int i; ! 168: ! 169: for (i = 0; i < MAXCLICK; i++) ! 170: if (clickname[i]) { ! 171: free(clickname[i]); ! 172: clickname[i] = 0; ! 173: clickval[i] = 0; ! 174: } ! 175: for (i = 0; i < MAXVIEW; i++) ! 176: if (viewname[i]) { ! 177: free(viewname[i]); ! 178: viewname[i] = 0; ! 179: } ! 180: nclick = nview = curview = nobj = clicking = overflow = slotnum = 0; ! 181: } ! 182: ! 183: main() ! 184: { ! 185: uchar *ip; ! 186: int i, n, c; ! 187: ! 188: request(KBD|MOUSE|SEND|RCV); ! 189: ! 190: top: ! 191: clear(); ! 192: init_params(); ! 193: putstring("terminal alive"); ! 194: memsize = readint(); ! 195: if (inbuf == (uchar*)NULL && (inbuf = (uchar *) alloc(memsize)) == (uchar*)NULL) { ! 196: PUT "can't allocate %d bytes", memsize END ! 197: sleep(1000); ! 198: exit(1); ! 199: } ! 200: input = inbuf+1; /* leave a null at front */ ! 201: inp = inbuf+1; /* next free slot in input */ ! 202: ! 203: cursswitch(&deadmouse); ! 204: do_rcv(); ! 205: PUT "%d objects, %d/%d bytes", nobj, inp-input, memsize END ! 206: cursswitch(PTR); ! 207: ! 208: dir = Fwd; ! 209: ip = inp; /* pointing at the end */ ! 210: again: ! 211: for ( ; ip; wait(CPU)) { ! 212: while (checkmouse() == 0) ! 213: wait(CPU); ! 214: n = domouse(); ! 215: if (n == Quit) { ! 216: send1char(P_QUIT); ! 217: flushproto(); ! 218: exit(); ! 219: } ! 220: if (n == Hit) /* wait for another mouse hit */ ! 221: continue; ! 222: if (n == Forward) { /* change from fwd to back -- fiddle ip */ ! 223: ip = next_obj(ip); ! 224: continue; ! 225: } ! 226: if (n == Backward) { ! 227: ip = prev_obj(ip); ! 228: continue; ! 229: } ! 230: if (n == File) { ! 231: putstring("filename? "); ! 232: if (do_kbd() == 0) ! 233: continue; ! 234: send1char(P_FILE); ! 235: sendstring(kbdline); ! 236: if ((c = readchar()) == P_FILE) ! 237: goto top; ! 238: PUT "can't open file %s", kbdline END; ! 239: continue; ! 240: } ! 241: if (n == Again) { ! 242: if (P->state & RESHAPED) { ! 243: view_setup(nview); ! 244: P->state &= ~RESHAPED; ! 245: } ! 246: clear(); ! 247: dir = Fwd; ! 248: ip = input; ! 249: } ! 250: if (singstep) { ! 251: if (clicking > 0) ! 252: ip = click_obj(ip, xormode, dir); ! 253: else ! 254: ip = step_obj(ip, xormode, dir); ! 255: } else { /* free running */ ! 256: while (ip) { ! 257: if (clicking > 0) ! 258: ip = click_obj(ip, xormode, dir); ! 259: else ! 260: ip = step_obj(ip, xormode, dir); ! 261: if (checkmouse()) ! 262: break; /* back round main loop */ ! 263: sleep(delay-1); ! 264: wait(CPU); ! 265: } ! 266: } ! 267: } ! 268: if (ip == 0) ! 269: ip = dir == Fwd ? inp : input; ! 270: goto again; ! 271: } ! 272: ! 273: domouse() ! 274: { ! 275: int n; ! 276: ! 277: if (last_but == 1) ! 278: return Proceed; ! 279: if (last_but == 3) { ! 280: switch (last_hit) { ! 281: case Again: ! 282: return Again; ! 283: case Faster: ! 284: if (delay > 1) ! 285: delay /= 2; ! 286: return Hit; ! 287: case Slower: ! 288: delay *= 2; ! 289: return Hit; ! 290: case Step: ! 291: singstep = 1 - singstep; ! 292: n = Step; ! 293: return Hit; ! 294: case Forward: ! 295: dir = 1 - dir; ! 296: if (xormode == F_OR) ! 297: xormode = F_CLR; ! 298: else if (xormode == F_CLR) ! 299: xormode = F_OR; ! 300: return dir == Fwd ? Forward : Backward; ! 301: case Fatter: ! 302: fatness++; ! 303: return Hit; ! 304: case Thinner: ! 305: if (fatness > 0) ! 306: fatness--; ! 307: return Hit; ! 308: case Xor: ! 309: if (xormode == F_OR || xormode == F_CLR) ! 310: xormode = F_XOR; ! 311: else if (dir == Fwd) ! 312: xormode = F_OR; ! 313: else ! 314: xormode = F_CLR; ! 315: return Hit; ! 316: case File: ! 317: return File; ! 318: case Quit: ! 319: return Quit; ! 320: default: ! 321: return Hit; ! 322: } ! 323: } else if (last_but == 2) { ! 324: Rectangle r, shrink(); ! 325: if (last_hit == -1) ! 326: return Hit; ! 327: else if (last_hit < nview) { ! 328: #ifdef V9 ! 329: r = getrect23(); ! 330: #else ! 331: r = getrect(); ! 332: #endif ! 333: if (r.origin.x == 0 && r.corner.x == 0) /* bailed out */ ! 334: return Hit; ! 335: if (eqpt(r.origin, r.corner)) ! 336: r = Drect; ! 337: drawrect(inset(viewpt[last_hit].vr, -(INSET+fatness)), F_CLR); ! 338: drawrect(r, F_OR); ! 339: viewpt[last_hit].vr = r = inset(r, INSET+fatness); ! 340: viewpt[last_hit].xmax = r.corner.x - r.origin.x; ! 341: viewpt[last_hit].ymax = r.corner.y - r.origin.y; ! 342: return Hit; ! 343: } else { /* a click */ ! 344: if (clickval[last_hit-nview]) { /* was on, so turn off */ ! 345: clickval[last_hit-nview] = 0; ! 346: clicking--; ! 347: } else { ! 348: clickval[last_hit-nview] = 1; ! 349: clicking++; ! 350: } ! 351: return Hit; ! 352: } ! 353: } ! 354: } ! 355: ! 356: Point pt(x, y) { Point p; p.x = x; p.y = y; return p; } ! 357: ! 358: Rectangle shrink(r, pct) /* shrink rectangle by 2*pct */ ! 359: Rectangle r; ! 360: { ! 361: int dx = muldiv(r.corner.x-r.origin.x, pct, 100); ! 362: int dy = muldiv(r.corner.y-r.origin.y, pct, 100); ! 363: r.origin = add(r.origin, Pt(dx,dy)); ! 364: r.corner = sub(r.corner, Pt(dx,dy)); ! 365: return r; ! 366: } ! 367: ! 368: view_setup(n) ! 369: int n; ! 370: { ! 371: int i, dx, dy; ! 372: ! 373: dx = (Dc.x - Do.x) / 2; ! 374: dy = (Dc.y - Do.y) / 2; ! 375: viewpt[0].vr = Drect; ! 376: switch (n) { ! 377: case 2: ! 378: viewpt[1].vr = Drect; ! 379: viewpt[0].vr.corner.y -= dy; ! 380: viewpt[1].vr.origin.y += dy; ! 381: break; ! 382: case 3: case 4: ! 383: viewpt[0].vr.corner = add(Drect.origin, Pt(dx,dy)); ! 384: viewpt[1].vr = raddp(viewpt[0].vr, Pt(0,dy)); ! 385: viewpt[2].vr = raddp(viewpt[0].vr, Pt(dx,0)); ! 386: viewpt[3].vr = raddp(viewpt[0].vr, Pt(dx,dy)); ! 387: break; ! 388: } ! 389: for (i = 0; i < n; i++) { ! 390: viewpt[i].vr = shrink(viewpt[i].vr, MARGINPCT); ! 391: viewpt[i].xmax = viewpt[i].vr.corner.x - viewpt[i].vr.origin.x; ! 392: viewpt[i].ymax = viewpt[i].vr.corner.y - viewpt[i].vr.origin.y; ! 393: } ! 394: } ! 395: ! 396: drawrect(r, mode) ! 397: Rectangle r; ! 398: { ! 399: segment(&display, r.origin, Pt(r.origin.x,r.corner.y), mode); ! 400: segment(&display, r.origin, Pt(r.corner.x,r.origin.y), mode); ! 401: segment(&display, r.corner, Pt(r.origin.x,r.corner.y), mode); ! 402: segment(&display, r.corner, Pt(r.corner.x,r.origin.y), mode); ! 403: } ! 404: ! 405: do_rcv() ! 406: { ! 407: int c, n, b, m, i; ! 408: uchar *ip; ! 409: ! 410: top: ! 411: switch (c = readchar()) { ! 412: case P_INIT: /* initialize */ ! 413: break; ! 414: case P_ENDFILE: ! 415: *inp = 0; ! 416: return; ! 417: case P_CLEAR: ! 418: clear(); ! 419: break; ! 420: case P_DEFINE: ! 421: /* view, click, ... */ ! 422: c = readchar(); ! 423: assert(c == 'c' || c == 'v', "illegal define"); ! 424: i = readint(); ! 425: readstring(buf); ! 426: if (c == 'c') { ! 427: clickname[i] = alloc(strlen(buf)+1); ! 428: strcpy(clickname[i], buf); ! 429: nclick++; ! 430: } else { /* c == 'v' */ ! 431: viewname[i] = alloc(strlen(buf)+1); ! 432: strcpy(viewname[i], buf); ! 433: nview++; ! 434: } ! 435: break; ! 436: case P_OBJECT: /* read an object */ ! 437: ip = inp; ! 438: if (nobj++ == 0) ! 439: view_setup(nview); ! 440: if (nobj % 100 == 0) ! 441: PUT "%d objects, %d/%d bytes", nobj, inp-input, memsize END ! 442: read_obj(); ! 443: draw_obj(ip, F_XOR, Fwd); ! 444: break; ! 445: case P_PRINT: /* print a string */ ! 446: readstring(buf); ! 447: putstring(buf); ! 448: break; ! 449: default: ! 450: if (overflow) ! 451: break; ! 452: putstring("do_rcv error; unrecognized command: "); ! 453: for (pbuf = buf; c != '\n'; c = readchar()) ! 454: *pbuf++ = c; ! 455: *pbuf = 0; ! 456: putstring(buf); ! 457: break; ! 458: } ! 459: goto top; ! 460: } ! 461: ! 462: clear() ! 463: { ! 464: rectf(&display, Drect, F_CLR); /* clear screen */ ! 465: } ! 466: ! 467: ! 468: read_obj() /* read an object, stick it in input[] */ ! 469: { ! 470: int c, n, m; ! 471: uchar *p; ! 472: ! 473: if (inp > input+memsize-50) { /* eat up at least one */ ! 474: PUT "overflow at %d bytes, limit %d", inp - input, memsize END ! 475: overflow++; ! 476: return; ! 477: } ! 478: c = readchar(); ! 479: switch (c) { ! 480: case ' ': ! 481: case '\n': ! 482: break; ! 483: case 'b': ! 484: case 'l': ! 485: slotnum = readint(); ! 486: slot[slotnum] = inp-input; ! 487: p = savechar(c); ! 488: savechar(curview = readint()); ! 489: savechar(readint()); /* options */ ! 490: savept(readpt()); ! 491: savept(readpt()); ! 492: savect(inp-p); ! 493: break; ! 494: case 'o': ! 495: slotnum = readint(); ! 496: slot[slotnum] = inp-input; ! 497: p = savechar(c); ! 498: savechar(curview = readint()); ! 499: savechar(readint()); /* options */ ! 500: savept(readpt()); ! 501: saveint(readint()); /* radius */ ! 502: savect(inp-p); ! 503: break; ! 504: case 't': ! 505: slotnum = readint(); ! 506: slot[slotnum] = inp-input; ! 507: p = savechar(c); ! 508: savechar(curview = readint()); ! 509: savechar(readint()); /* options */ ! 510: savept(readpt()); ! 511: n = readstring(inp+1); /* +1 leaves a hole */ ! 512: *inp = n; /* insert count before string */ ! 513: inp += n + 2; /* +2 = count before and \0 on end */ ! 514: savect(inp-p); ! 515: break; ! 516: case 'e': ! 517: p = savechar(c); ! 518: savelong(slot[readint()]); ! 519: savect(inp-p); ! 520: break; ! 521: case 'c': ! 522: p = savechar(c); ! 523: savechar(readint()); ! 524: savect(inp-p); ! 525: break; ! 526: } ! 527: } ! 528: ! 529: Point readpt() /* read a Point */ ! 530: { ! 531: Point p; ! 532: ! 533: p.x = readint(); ! 534: p.y = readint(); ! 535: return p; ! 536: } ! 537: ! 538: uchar *savechar(c) ! 539: { ! 540: *inp++ = c; ! 541: return inp-1; ! 542: } ! 543: ! 544: savect(n) ! 545: { ! 546: if (n > 255) ! 547: putstring("text string too long"); ! 548: *inp++ = n; ! 549: } ! 550: ! 551: saveint(n) ! 552: { ! 553: *inp++ = n >> 8; ! 554: *inp++ = n & 0377; ! 555: } ! 556: ! 557: savelong(n) ! 558: long n; ! 559: { ! 560: *inp++ = n >> 24; ! 561: *inp++ = n >> 16; ! 562: *inp++ = n >> 8; ! 563: *inp++ = n; ! 564: } ! 565: ! 566: savept(p) ! 567: Point p; ! 568: { ! 569: *inp++ = p.x >> 8; ! 570: *inp++ = p.x & 0377; ! 571: *inp++ = p.y >> 8; ! 572: *inp++ = p.y & 0377; ! 573: } ! 574: ! 575: getpoint(ip) ! 576: uchar *ip; ! 577: { ! 578: return *ip << 8 | *(ip+1); ! 579: } ! 580: ! 581: long getlong(ip) ! 582: uchar *ip; ! 583: { ! 584: return *ip << 24 | *(ip+1) << 16 | *(ip+2) << 8 | *(ip+3); ! 585: } ! 586: ! 587: Point scalept(v, p) ! 588: Point p; ! 589: { ! 590: p.x = p.x * viewpt[v].xmax / 10000; ! 591: p.y = viewpt[v].ymax - p.y * viewpt[v].ymax / 10000; ! 592: return p; ! 593: } ! 594: ! 595: scalex(v, n) ! 596: { ! 597: return n * viewpt[v].xmax / 10000; ! 598: } ! 599: ! 600: Point fetchpt(v, ip) ! 601: int v; ! 602: uchar *ip; ! 603: { ! 604: Point pt; ! 605: ! 606: pt.x = *ip << 8 | *(ip+1); ! 607: pt.y = *(ip+2) << 8 | *(ip+3); ! 608: pt = scalept(v, pt); ! 609: return add(pt, viewpt[v].vr.origin); ! 610: } ! 611: ! 612: /* ! 613: Encoding: type, view#, opts, coords, chars, etc., # = length of group ! 614: bvoxxyyxxyy# ! 615: lvoxxyyxxyy# ! 616: ovoxxyyrr# ! 617: tvoxxyynccc0# ! 618: ennnn# ! 619: cn# ! 620: ! 621: */ ! 622: ! 623: uchar *prev_obj(ip) ! 624: uchar *ip; ! 625: { ! 626: if (ip <= input) ! 627: return 0; ! 628: return ip - ip[-1] - 1; ! 629: } ! 630: ! 631: uchar *next_obj(ip) ! 632: uchar *ip; ! 633: { ! 634: if (ip < input || ip >= inp) ! 635: return 0; ! 636: switch (*ip) { ! 637: case 0: ! 638: return 0; ! 639: case 'b': ! 640: case 'l': ! 641: return ip + 12; ! 642: case 'o': ! 643: return ip + 10; ! 644: case 't': ! 645: return ip + ip[7] + 10; ! 646: case 'c': ! 647: return ip + 3; ! 648: case 'e': ! 649: return ip + 6; ! 650: default: ! 651: return 0; ! 652: } ! 653: } ! 654: ! 655: uchar *step_obj(ip, mode, dir) /* draw objs until one that changes something */ ! 656: uchar *ip; ! 657: { ! 658: int c; ! 659: ! 660: while (ip) { ! 661: c = *ip; ! 662: ip = draw_obj(ip, mode, dir); ! 663: if (c == 'b' || c == 'l' || c == 't' || c == 'e' || c == 'o') ! 664: return ip; ! 665: } ! 666: return ip; ! 667: } ! 668: ! 669: uchar *click_obj(ip, mode, dir) /* draw objs until matching click */ ! 670: uchar *ip; ! 671: { ! 672: int c; ! 673: uchar *oip; ! 674: ! 675: for (;;) { ! 676: oip = ip; ! 677: ip = draw_obj(ip, mode, dir); ! 678: if (ip == 0 || (oip && *oip == 'c' && clickval[oip[1]])) ! 679: return ip; ! 680: } ! 681: } ! 682: ! 683: uchar *draw_obj(ip, mode, dir) /* draw obj from coords at ip */ ! 684: uchar *ip; ! 685: int mode, dir; ! 686: { ! 687: int c, r, thick, n, shift, head; ! 688: Point p0, p1, p2; ! 689: ! 690: if (ip < input || ip >= inp) ! 691: return 0; ! 692: switch (c = *ip++) { ! 693: case 'b': ! 694: p0 = fetchpt(*ip, ip+2); ! 695: p1 = fetchpt(*ip, ip+6); ! 696: if (ip[1] == Bfill) { ! 697: if (p0.y < p1.y) ! 698: rectf(&display, Rpt(p0, p1), mode); ! 699: else ! 700: rectf(&display, Rect(p0.x,p1.y,p1.x,p0.y), mode); ! 701: } else { ! 702: segment(&display, p0, Pt(p0.x,p1.y), mode); ! 703: segment(&display, Pt(p0.x,p1.y), p1, mode); ! 704: segment(&display, p1, Pt(p1.x,p0.y), mode); ! 705: segment(&display, Pt(p1.x,p0.y), p0, mode); ! 706: } ! 707: if (dir == Fwd) ! 708: ip += 1+9+1; ! 709: else ! 710: ip -= (*(ip-2) + 2); ! 711: break; ! 712: case 'l': ! 713: p0 = fetchpt(*ip, ip+2); ! 714: p1 = fetchpt(*ip, ip+6); ! 715: thick = ip[1]/10; /* ought to be a macro! */ ! 716: if (thick == Ldotted/10 || thick == Ldashed/10) ! 717: thick = 1; ! 718: thick = 2 * thick - 1; /* 1,3,5 */ ! 719: fatline(p0, p1, mode, thick); ! 720: head = ip[1]%10; /* ditto */ ! 721: if (head == Larrow1 || head == Larrow3) ! 722: arrow(p0, p1, AW, AH, mode); ! 723: if (head == Larrow2 || head == Larrow3) ! 724: arrow(p1, p0, AW, AH, mode); ! 725: if (dir == Fwd) ! 726: ip += 1+9+1; ! 727: else ! 728: ip -= (*(ip-2) + 2); ! 729: break; ! 730: case 'o': ! 731: p0 = fetchpt(*ip, ip+2); ! 732: r = scalex(*ip, getpoint(ip+6)); ! 733: if (ip[1] == Cnofill) ! 734: circle(&display, p0, r, mode); ! 735: else ! 736: disc(&display, p0, r, mode); ! 737: if (dir == Fwd) ! 738: ip += 1+7+1; ! 739: else ! 740: ip -= (*(ip-2) + 2); ! 741: break; ! 742: case 't': ! 743: p0 = fetchpt(*ip, ip+2); ! 744: n = ip[6]; ! 745: shift = (ip[1]/10) * 10; /* ought to be a macro! */ ! 746: if (shift == Tljust) ! 747: shift = 0; ! 748: else if (shift == Tcenter) ! 749: shift = (9 * n) / 2; /* 9 = char width */ ! 750: else ! 751: shift = 9 * n; ! 752: string(&defont, ip+7, &display, sub(p0, Pt(shift,8)), mode); ! 753: if (dir == Fwd) ! 754: ip += 1+5 + *(ip+6)+2 + 1; ! 755: else ! 756: ip -= (*(ip-2) + 2); ! 757: break; ! 758: case 'e': ! 759: erase(ip-1); ! 760: if (dir == Fwd) ! 761: ip += 5; ! 762: else ! 763: ip -= (*(ip-2) + 2); ! 764: break; ! 765: case 'c': ! 766: if (dir == Fwd) ! 767: ip += 2; ! 768: else ! 769: ip -= (*(ip-2) + 2); ! 770: break; ! 771: default: ! 772: ip = 0; ! 773: break; ! 774: } ! 775: return ip; ! 776: } ! 777: ! 778: erase(ip) ! 779: uchar *ip; ! 780: { ! 781: long target = getlong(ip+1); /* target label index */ ! 782: int mode = F_XOR; ! 783: ! 784: if (xormode == F_OR || xormode == F_CLR) ! 785: mode = dir == Fwd ? F_CLR : F_OR; ! 786: draw_obj(input+target, mode, Fwd); ! 787: } ! 788: ! 789: #define abs(x) ((x) >= 0 ? (x) : -(x)) ! 790: ! 791: fatline(p0, p1, mode, thick) ! 792: Point p0, p1; ! 793: { ! 794: int i, fat, beg, nl; ! 795: ! 796: fat = thick * (2 * fatness + 1); ! 797: beg = fat / 2; ! 798: if (abs(p1.x-p0.x) >= abs(p1.y-p0.y)) { /* horizontal */ ! 799: for (nl = 0, i = -beg; nl < fat; nl++, i++) ! 800: segment(&display, add(p0, Pt(0,i)), add(p1, Pt(0,i)), mode); ! 801: } else { ! 802: for (nl = 0, i = -beg; nl < fat; nl++, i++) ! 803: segment(&display, add(p0, Pt(i,0)), add(p1, Pt(i,0)), mode); ! 804: } ! 805: } ! 806: ! 807: arrow(p1, p2, w, h, c) ! 808: Point p1, p2; ! 809: int w, h, c; ! 810: /* ! 811: ** draw arrow of height,width (h,w) at p2 of segment p1,p2. ! 812: */ ! 813: { ! 814: Point d; ! 815: int norm, qx, qy, lx, ly; ! 816: ! 817: d = sub(p2, p1); ! 818: norm = sqrt((long)d.x*d.x + (long)d.y*d.y); ! 819: if (norm == 0) /* shouldn't happen, but ... */ ! 820: return; ! 821: qx = p2.x - h*d.x/norm; ! 822: qy = p2.y - h*d.y/norm; ! 823: lx = w/2 * -d.y/norm; ! 824: ly = w/2 * d.x/norm; ! 825: /* segment(&display, p1, p2, c); */ ! 826: segment(&display, Pt(qx+lx, qy+ly), p2, c); ! 827: segment(&display, Pt(qx-lx, qy-ly), p2, c); ! 828: } ! 829: ! 830: but(n) /* parameterize button1(), etc. */ ! 831: int n; ! 832: { ! 833: switch (n) { ! 834: case 1: return button1(); ! 835: case 2: return button2(); ! 836: case 3: return button3(); ! 837: case 12: return button12(); ! 838: case 13: return button1()|button3(); /* not built in */ ! 839: case 23: return button23(); ! 840: case 123: return button123(); ! 841: default: return 0; ! 842: } ! 843: } ! 844: ! 845: checkmouse() /* return button touched if any */ ! 846: { ! 847: int c, b; ! 848: char *p = NULL; ! 849: Point dp; ! 850: #ifdef V9 ! 851: Texture *tp; ! 852: #else ! 853: Texture16 *tp; ! 854: #endif ! 855: ! 856: if (!(own()&MOUSE) || !button123()) ! 857: return 0; /* no hit at all */ ! 858: tp = cursswitch(PTR); ! 859: last_but = 0; ! 860: last_hit = -1; ! 861: c = 0; ! 862: if (button3()) { ! 863: last_hit = menuhit(&mbut3, 3); ! 864: last_but = 3; ! 865: } else if (button2()) { ! 866: last_hit = menuhit(&mbut2, 2); ! 867: last_but = 2; ! 868: } else { /* button1() */ ! 869: last_but = 1; ! 870: } ! 871: while (button123()) ! 872: wait(MOUSE); ! 873: if (last_but == 3) { ! 874: p = m3[last_hit]; ! 875: c = p[strlen(p) - 1]; ! 876: } ! 877: if (c == '?' && !confirm(last_but)) ! 878: last_hit = -1; ! 879: cursswitch(tp); ! 880: return last_but; ! 881: } ! 882: ! 883: confirm(but) /* ask for confirmation if menu item ends with '?' */ ! 884: { ! 885: int c; ! 886: static int but_cvt[8] = { 0, 3, 2, 0, 1, 0, 0, 0 }; ! 887: #ifdef V9 ! 888: Texture *tp; ! 889: #else ! 890: Texture16 *tp; ! 891: #endif ! 892: ! 893: tp = cursswitch(&skull); ! 894: while (!button123()) ! 895: wait(MOUSE); ! 896: c = mouse.buttons & 7; ! 897: while (button123()) ! 898: wait(MOUSE); ! 899: cursswitch(tp); ! 900: return but == but_cvt[c]; ! 901: } ! 902: ! 903: putstring(a1, a2, a3, a4, a5) ! 904: char *a1, *a2, *a3, *a4, *a5; ! 905: { ! 906: static Point p = {0, 0}; ! 907: static int jmax = 0, l; ! 908: char buf[100], *s; ! 909: ! 910: p = Drect.origin; ! 911: sprintf(buf, a1, a2, a3, a4, a5); ! 912: rectf(&display, Rect(p.x,p.y,p.x+jmax,p.y+16), F_CLR); ! 913: string(&defont, buf, &display, p, F_OR); ! 914: if ((l = jstrwidth(buf)) > jmax) ! 915: jmax = l; ! 916: } ! 917: ! 918: assert(c, s) /* poor man's assertion */ ! 919: char *s; ! 920: { ! 921: if (!c) { ! 922: putstring("assertion %s failed\n", s); ! 923: sleep(60); ! 924: } ! 925: } ! 926: ! 927: readbyte() ! 928: { ! 929: int c; ! 930: ! 931: if ((c = rcvchar()) == -1) { ! 932: wait(RCV); ! 933: c = rcvchar(); ! 934: } ! 935: return c; ! 936: } ! 937: ! 938: sendbuf(buf, p) ! 939: char *buf, *p; ! 940: { ! 941: sendnchars((int) (p-buf), buf); ! 942: } ! 943: ! 944: do_kbd() ! 945: { ! 946: int c; ! 947: ! 948: pkbd = kbdline; ! 949: for (wait(KBD); (c = kbdchar()) != -1; wait(KBD)) { ! 950: if (c == '\b' && pkbd > kbdline) ! 951: --pkbd; ! 952: else if (c == '@') ! 953: pkbd = kbdline; ! 954: else ! 955: *pkbd++ = c; ! 956: *pkbd = '\0'; ! 957: rectf(&display, Rect(Do.x,Do.y,Dc.x,Do.y+16), F_CLR); ! 958: string(&defont, kbdline, &display, Do, F_STORE); ! 959: if (c == '\n' || c == '\r') { ! 960: pkbd[-1] = '\0'; ! 961: return '\n'; ! 962: } ! 963: } ! 964: } ! 965:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.