|
|
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, n = 0; ! 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: if (++n % 100 == 0) /* return occasionally to see mouse */ ! 681: return ip; ! 682: } ! 683: } ! 684: ! 685: uchar *draw_obj(ip, mode, dir) /* draw obj from coords at ip */ ! 686: uchar *ip; ! 687: int mode, dir; ! 688: { ! 689: int c, r, thick, n, shift, head; ! 690: Point p0, p1, p2; ! 691: ! 692: if (ip < input || ip >= inp) ! 693: return 0; ! 694: switch (c = *ip++) { ! 695: case 'b': ! 696: p0 = fetchpt(*ip, ip+2); ! 697: p1 = fetchpt(*ip, ip+6); ! 698: if (ip[1] == Bfill) { ! 699: if (p0.y < p1.y) ! 700: rectf(&display, Rpt(p0, p1), mode); ! 701: else ! 702: rectf(&display, Rect(p0.x,p1.y,p1.x,p0.y), mode); ! 703: } else { ! 704: segment(&display, p0, Pt(p0.x,p1.y), mode); ! 705: segment(&display, Pt(p0.x,p1.y), p1, mode); ! 706: segment(&display, p1, Pt(p1.x,p0.y), mode); ! 707: segment(&display, Pt(p1.x,p0.y), p0, mode); ! 708: } ! 709: if (dir == Fwd) ! 710: ip += 1+9+1; ! 711: else ! 712: ip -= (*(ip-2) + 2); ! 713: break; ! 714: case 'l': ! 715: p0 = fetchpt(*ip, ip+2); ! 716: p1 = fetchpt(*ip, ip+6); ! 717: thick = ip[1]/10; /* ought to be a macro! */ ! 718: if (thick == Ldotted/10 || thick == Ldashed/10) ! 719: thick = 1; ! 720: thick = 2 * thick - 1; /* 1,3,5 */ ! 721: fatline(p0, p1, mode, thick); ! 722: head = ip[1]%10; /* ditto */ ! 723: if (head == Larrow1 || head == Larrow3) ! 724: arrow(p0, p1, AW, AH, mode); ! 725: if (head == Larrow2 || head == Larrow3) ! 726: arrow(p1, p0, AW, AH, mode); ! 727: if (dir == Fwd) ! 728: ip += 1+9+1; ! 729: else ! 730: ip -= (*(ip-2) + 2); ! 731: break; ! 732: case 'o': ! 733: p0 = fetchpt(*ip, ip+2); ! 734: r = scalex(*ip, getpoint(ip+6)); ! 735: if (ip[1] == Cnofill) ! 736: circle(&display, p0, r, mode); ! 737: else ! 738: disc(&display, p0, r, mode); ! 739: if (dir == Fwd) ! 740: ip += 1+7+1; ! 741: else ! 742: ip -= (*(ip-2) + 2); ! 743: break; ! 744: case 't': ! 745: p0 = fetchpt(*ip, ip+2); ! 746: n = ip[6]; ! 747: shift = (ip[1]/10) * 10; /* ought to be a macro! */ ! 748: if (shift == Tljust) ! 749: shift = 0; ! 750: else if (shift == Tcenter) ! 751: shift = (9 * n) / 2; /* 9 = char width */ ! 752: else ! 753: shift = 9 * n; ! 754: string(&defont, ip+7, &display, sub(p0, Pt(shift,8)), mode); ! 755: if (dir == Fwd) ! 756: ip += 1+5 + *(ip+6)+2 + 1; ! 757: else ! 758: ip -= (*(ip-2) + 2); ! 759: break; ! 760: case 'e': ! 761: erase(ip-1); ! 762: if (dir == Fwd) ! 763: ip += 5; ! 764: else ! 765: ip -= (*(ip-2) + 2); ! 766: break; ! 767: case 'c': ! 768: if (dir == Fwd) ! 769: ip += 2; ! 770: else ! 771: ip -= (*(ip-2) + 2); ! 772: break; ! 773: default: ! 774: ip = 0; ! 775: break; ! 776: } ! 777: return ip; ! 778: } ! 779: ! 780: erase(ip) ! 781: uchar *ip; ! 782: { ! 783: long target = getlong(ip+1); /* target label index */ ! 784: int mode = F_XOR; ! 785: ! 786: if (xormode == F_OR || xormode == F_CLR) ! 787: mode = dir == Fwd ? F_CLR : F_OR; ! 788: draw_obj(input+target, mode, Fwd); ! 789: } ! 790: ! 791: #define abs(x) ((x) >= 0 ? (x) : -(x)) ! 792: ! 793: fatline(p0, p1, mode, thick) ! 794: Point p0, p1; ! 795: { ! 796: int i, fat, beg, nl; ! 797: ! 798: fat = thick * (2 * fatness + 1); ! 799: beg = fat / 2; ! 800: if (abs(p1.x-p0.x) >= abs(p1.y-p0.y)) { /* horizontal */ ! 801: for (nl = 0, i = -beg; nl < fat; nl++, i++) ! 802: segment(&display, add(p0, Pt(0,i)), add(p1, Pt(0,i)), mode); ! 803: } else { ! 804: for (nl = 0, i = -beg; nl < fat; nl++, i++) ! 805: segment(&display, add(p0, Pt(i,0)), add(p1, Pt(i,0)), mode); ! 806: } ! 807: } ! 808: ! 809: arrow(p1, p2, w, h, c) ! 810: Point p1, p2; ! 811: int w, h, c; ! 812: /* ! 813: ** draw arrow of height,width (h,w) at p2 of segment p1,p2. ! 814: */ ! 815: { ! 816: Point d; ! 817: int norm, qx, qy, lx, ly; ! 818: ! 819: d = sub(p2, p1); ! 820: norm = sqrt((long)d.x*d.x + (long)d.y*d.y); ! 821: if (norm == 0) /* shouldn't happen, but ... */ ! 822: return; ! 823: qx = p2.x - h*d.x/norm; ! 824: qy = p2.y - h*d.y/norm; ! 825: lx = w/2 * -d.y/norm; ! 826: ly = w/2 * d.x/norm; ! 827: /* segment(&display, p1, p2, c); */ ! 828: segment(&display, Pt(qx+lx, qy+ly), p2, c); ! 829: segment(&display, Pt(qx-lx, qy-ly), p2, c); ! 830: } ! 831: ! 832: but(n) /* parameterize button1(), etc. */ ! 833: int n; ! 834: { ! 835: switch (n) { ! 836: case 1: return button1(); ! 837: case 2: return button2(); ! 838: case 3: return button3(); ! 839: case 12: return button12(); ! 840: case 13: return button1()|button3(); /* not built in */ ! 841: case 23: return button23(); ! 842: case 123: return button123(); ! 843: default: return 0; ! 844: } ! 845: } ! 846: ! 847: checkmouse() /* return button touched if any */ ! 848: { ! 849: int c, b; ! 850: char *p = NULL; ! 851: Point dp; ! 852: #ifdef V9 ! 853: Texture *tp; ! 854: #else ! 855: Texture16 *tp; ! 856: #endif ! 857: ! 858: if (!(own()&MOUSE) || !button123()) ! 859: return 0; /* no hit at all */ ! 860: tp = cursswitch(PTR); ! 861: last_but = 0; ! 862: last_hit = -1; ! 863: c = 0; ! 864: if (button3()) { ! 865: last_hit = menuhit(&mbut3, 3); ! 866: last_but = 3; ! 867: } else if (button2()) { ! 868: last_hit = menuhit(&mbut2, 2); ! 869: last_but = 2; ! 870: } else { /* button1() */ ! 871: last_but = 1; ! 872: } ! 873: while (button123()) ! 874: wait(MOUSE); ! 875: if (last_but == 3) { ! 876: p = m3[last_hit]; ! 877: c = p[strlen(p) - 1]; ! 878: } ! 879: if (c == '?' && !confirm(last_but)) ! 880: last_hit = -1; ! 881: cursswitch(tp); ! 882: return last_but; ! 883: } ! 884: ! 885: confirm(but) /* ask for confirmation if menu item ends with '?' */ ! 886: { ! 887: int c; ! 888: static int but_cvt[8] = { 0, 3, 2, 0, 1, 0, 0, 0 }; ! 889: #ifdef V9 ! 890: Texture *tp; ! 891: #else ! 892: Texture16 *tp; ! 893: #endif ! 894: ! 895: tp = cursswitch(&skull); ! 896: while (!button123()) ! 897: wait(MOUSE); ! 898: c = mouse.buttons & 7; ! 899: while (button123()) ! 900: wait(MOUSE); ! 901: cursswitch(tp); ! 902: return but == but_cvt[c]; ! 903: } ! 904: ! 905: putstring(a1, a2, a3, a4, a5) ! 906: char *a1, *a2, *a3, *a4, *a5; ! 907: { ! 908: static Point p = {0, 0}; ! 909: static int jmax = 0, l; ! 910: char buf[100], *s; ! 911: ! 912: p = Drect.origin; ! 913: sprintf(buf, a1, a2, a3, a4, a5); ! 914: rectf(&display, Rect(p.x,p.y,p.x+jmax,p.y+16), F_CLR); ! 915: string(&defont, buf, &display, p, F_OR); ! 916: if ((l = jstrwidth(buf)) > jmax) ! 917: jmax = l; ! 918: } ! 919: ! 920: assert(c, s) /* poor man's assertion */ ! 921: char *s; ! 922: { ! 923: if (!c) { ! 924: putstring("assertion %s failed\n", s); ! 925: sleep(60); ! 926: } ! 927: } ! 928: ! 929: readbyte() ! 930: { ! 931: int c; ! 932: ! 933: if ((c = rcvchar()) == -1) { ! 934: wait(RCV); ! 935: c = rcvchar(); ! 936: } ! 937: return c; ! 938: } ! 939: ! 940: sendbuf(buf, p) ! 941: char *buf, *p; ! 942: { ! 943: sendnchars((int) (p-buf), buf); ! 944: } ! 945: ! 946: do_kbd() ! 947: { ! 948: int c; ! 949: ! 950: pkbd = kbdline; ! 951: for (wait(KBD); (c = kbdchar()) != -1; wait(KBD)) { ! 952: if (c == '\b' && pkbd > kbdline) ! 953: --pkbd; ! 954: else if (c == '@') ! 955: pkbd = kbdline; ! 956: else ! 957: *pkbd++ = c; ! 958: *pkbd = '\0'; ! 959: rectf(&display, Rect(Do.x,Do.y,Dc.x,Do.y+16), F_CLR); ! 960: string(&defont, kbdline, &display, Do, F_STORE); ! 961: if (c == '\n' || c == '\r') { ! 962: pkbd[-1] = '\0'; ! 963: return '\n'; ! 964: } ! 965: } ! 966: } ! 967:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.