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