|
|
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 20 ! 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, j, v, dx, dy, r, c; ! 411: ! 412: switch (n) { ! 413: case 1: r = 1; c = 1; break; ! 414: case 2: r = 2; c = 1; break; ! 415: case 3: case 4: r = 2; c = 2; break; ! 416: case 5: case 6: r = 3; c = 2; break; ! 417: case 7: case 8: case 9: r = 3; c = 3; break; ! 418: default: r = (n+2)/3; c = 3; break; /* finking out */ ! 419: } ! 420: dx = (Dc.x - Do.x) / c; ! 421: dy = (Dc.y - Do.y) / r; ! 422: v = 0; ! 423: for (i = 0; i < r && v < n; i++) ! 424: for (j = 0; j < c && v < n; j++) { ! 425: viewpt[v].vr = Drect; ! 426: viewpt[v].vr.origin.x = Do.x + j * dx; ! 427: viewpt[v].vr.corner.x = Do.x + (j+1) * dx; ! 428: viewpt[v].vr.origin.y = Do.y + i * dy; ! 429: viewpt[v].vr.corner.y = Do.y + (i+1) * dy; ! 430: v++; ! 431: } ! 432: for (i = 0; i < n; i++) { ! 433: viewpt[i].vr = shrink(viewpt[i].vr, MARGINPCT); ! 434: viewpt[i].xmax = viewpt[i].vr.corner.x - viewpt[i].vr.origin.x; ! 435: viewpt[i].ymax = viewpt[i].vr.corner.y - viewpt[i].vr.origin.y; ! 436: } ! 437: } ! 438: ! 439: drawrect(r, mode) ! 440: Rectangle r; ! 441: { ! 442: segment(&display, r.origin, Pt(r.origin.x,r.corner.y), mode); ! 443: segment(&display, r.origin, Pt(r.corner.x,r.origin.y), mode); ! 444: segment(&display, r.corner, Pt(r.origin.x,r.corner.y), mode); ! 445: segment(&display, r.corner, Pt(r.corner.x,r.origin.y), mode); ! 446: } ! 447: ! 448: do_rcv() ! 449: { ! 450: int c, n, b, m, i; ! 451: uchar *ip; ! 452: ! 453: top: ! 454: switch (c = readchar()) { ! 455: case P_INIT: /* initialize */ ! 456: break; ! 457: case P_ENDFILE: ! 458: *inp = 0; ! 459: return; ! 460: case P_CLEAR: ! 461: clear(); ! 462: break; ! 463: case P_DEFINE: ! 464: /* view, click, ... */ ! 465: c = readchar(); ! 466: assert(c == 'c' || c == 'v', "illegal define"); ! 467: i = readint(); ! 468: readstring(buf); ! 469: if (c == 'c') { ! 470: clickname[i] = alloc(strlen(buf)+1); ! 471: strcpy(clickname[i], buf); ! 472: nclick++; ! 473: } else { /* c == 'v' */ ! 474: viewname[i] = alloc(strlen(buf)+1); ! 475: strcpy(viewname[i], buf); ! 476: nview++; ! 477: } ! 478: break; ! 479: case P_OBJECT: /* read an object */ ! 480: if (nobj++ == 0) ! 481: view_setup(nview); ! 482: if (nobj % 100 == 0) ! 483: PUT "%d objects, %u/%u bytes", nobj, inp-input, memsize END ! 484: ip = read_obj(); ! 485: draw_obj(ip, F_XOR, Fwd); ! 486: break; ! 487: case P_PRINT: /* print a string */ ! 488: readstring(buf); ! 489: putstring(buf); ! 490: break; ! 491: case P_ERRPRINT: /* print an error string */ ! 492: readstring(buf); ! 493: ERRPUT buf END; ! 494: break; ! 495: default: ! 496: if (overflow) ! 497: break; ! 498: putstring("do_rcv error; unrecognized command: "); ! 499: for (pbuf = buf; c != '\n'; c = readchar()) ! 500: *pbuf++ = c; ! 501: *pbuf = 0; ! 502: putstring(buf); ! 503: break; ! 504: } ! 505: goto top; ! 506: } ! 507: ! 508: clear() ! 509: { ! 510: rectf(&display, Drect, F_CLR); /* clear screen */ ! 511: } ! 512: ! 513: ! 514: uchar *read_obj() /* read an object, stick it in input[] */ ! 515: { ! 516: int c, n, m; ! 517: uchar *p, *oinp = inp; ! 518: ! 519: if (inp > input+memsize-50) { /* eat up at least one */ ! 520: ERRPUT "overflow at %u bytes, limit %u", inp - input, memsize END; ! 521: /* overflow++; */ ! 522: /* return; */ ! 523: oinp = inp = input; /* reset to see end of picture */ ! 524: } ! 525: c = readchar(); ! 526: switch (c) { ! 527: case ' ': ! 528: case '\n': ! 529: break; ! 530: case 'b': ! 531: case 'l': ! 532: slotnum = readint(); ! 533: slot[slotnum] = inp-input; ! 534: p = savechar(c); ! 535: savechar(curview = readint()); ! 536: savechar(readint()); /* options */ ! 537: savept(readpt()); ! 538: savept(readpt()); ! 539: savect(inp-p); ! 540: break; ! 541: case 'o': ! 542: slotnum = readint(); ! 543: slot[slotnum] = inp-input; ! 544: p = savechar(c); ! 545: savechar(curview = readint()); ! 546: savechar(readint()); /* options */ ! 547: savept(readpt()); ! 548: saveint(readint()); /* radius */ ! 549: savect(inp-p); ! 550: break; ! 551: case 't': ! 552: slotnum = readint(); ! 553: slot[slotnum] = inp-input; ! 554: p = savechar(c); ! 555: savechar(curview = readint()); ! 556: savechar(readint()); /* options */ ! 557: savept(readpt()); ! 558: n = readstring(inp+1); /* +1 leaves a hole */ ! 559: *inp = n; /* insert count before string */ ! 560: inp += n + 2; /* +2 = count before and \0 on end */ ! 561: savect(inp-p); ! 562: break; ! 563: case 'e': ! 564: p = savechar(c); ! 565: savelong(slot[readint()]); ! 566: savect(inp-p); ! 567: break; ! 568: case 'c': ! 569: p = savechar(c); ! 570: savechar(readint()); ! 571: savect(inp-p); ! 572: break; ! 573: } ! 574: return oinp; ! 575: } ! 576: ! 577: Point readpt() /* read a Point */ ! 578: { ! 579: Point p; ! 580: ! 581: p.x = readint(); ! 582: p.y = readint(); ! 583: return p; ! 584: } ! 585: ! 586: uchar *savechar(c) ! 587: { ! 588: *inp++ = c; ! 589: return inp-1; ! 590: } ! 591: ! 592: savect(n) ! 593: { ! 594: if (n > 255) ! 595: putstring("text string too long"); ! 596: *inp++ = n; ! 597: } ! 598: ! 599: saveint(n) ! 600: { ! 601: *inp++ = n >> 8; ! 602: *inp++ = n & 0377; ! 603: } ! 604: ! 605: savelong(n) ! 606: long n; ! 607: { ! 608: *inp++ = n >> 24; ! 609: *inp++ = n >> 16; ! 610: *inp++ = n >> 8; ! 611: *inp++ = n; ! 612: } ! 613: ! 614: savept(p) ! 615: Point p; ! 616: { ! 617: *inp++ = p.x >> 8; ! 618: *inp++ = p.x & 0377; ! 619: *inp++ = p.y >> 8; ! 620: *inp++ = p.y & 0377; ! 621: } ! 622: ! 623: getpoint(ip) ! 624: uchar *ip; ! 625: { ! 626: return *ip << 8 | *(ip+1); ! 627: } ! 628: ! 629: long getlong(ip) ! 630: uchar *ip; ! 631: { ! 632: return *ip << 24 | *(ip+1) << 16 | *(ip+2) << 8 | *(ip+3); ! 633: } ! 634: ! 635: Point scalept(v, p) ! 636: Point p; ! 637: { ! 638: p.x = muldiv(p.x, viewpt[v].xmax, 10000); ! 639: p.y = viewpt[v].ymax - muldiv(p.y, viewpt[v].ymax, 10000); ! 640: return p; ! 641: } ! 642: ! 643: scalex(v, n) ! 644: { ! 645: return muldiv(n, viewpt[v].xmax, 10000); ! 646: } ! 647: ! 648: Point fetchpt(v, ip) ! 649: int v; ! 650: uchar *ip; ! 651: { ! 652: Point pt; ! 653: ! 654: pt.x = *ip << 8 | *(ip+1); ! 655: pt.y = *(ip+2) << 8 | *(ip+3); ! 656: pt = scalept(v, pt); ! 657: return add(pt, viewpt[v].vr.origin); ! 658: } ! 659: ! 660: /* ! 661: Encoding: type, view#, opts, coords, chars, etc., # = length of group ! 662: bvoxxyyxxyy# ! 663: lvoxxyyxxyy# ! 664: ovoxxyyrr# ! 665: tvoxxyynccc0# ! 666: ennnn# ! 667: cn# ! 668: ! 669: */ ! 670: ! 671: uchar *prev_obj(ip) ! 672: uchar *ip; ! 673: { ! 674: if (ip <= input) ! 675: return 0; ! 676: return ip - ip[-1] - 1; ! 677: } ! 678: ! 679: uchar *next_obj(ip) ! 680: uchar *ip; ! 681: { ! 682: if (ip < input || ip >= inp) ! 683: return 0; ! 684: switch (*ip) { ! 685: case 0: ! 686: return 0; ! 687: case 'b': ! 688: case 'l': ! 689: return ip + 12; ! 690: case 'o': ! 691: return ip + 10; ! 692: case 't': ! 693: return ip + ip[7] + 10; ! 694: case 'c': ! 695: return ip + 3; ! 696: case 'e': ! 697: return ip + 6; ! 698: default: ! 699: return 0; ! 700: } ! 701: } ! 702: ! 703: uchar *step_obj(ip, mode, dir) /* draw objs until one that changes something */ ! 704: uchar *ip; ! 705: { ! 706: int c; ! 707: ! 708: while (ip) { ! 709: c = *ip; ! 710: ip = draw_obj(ip, mode, dir); ! 711: if (c == 'b' || c == 'l' || c == 't' || c == 'e' || c == 'o') ! 712: return ip; ! 713: } ! 714: return ip; ! 715: } ! 716: ! 717: uchar *click_obj(ip, mode, dir) /* draw objs until matching click */ ! 718: uchar *ip; ! 719: { ! 720: int c; ! 721: uchar *oip; ! 722: ! 723: for (;;) { ! 724: oip = ip; ! 725: ip = draw_obj(ip, mode, dir); ! 726: if (ip == 0 || (oip && *oip == 'c' && clickval[oip[1]])) ! 727: return ip; ! 728: } ! 729: } ! 730: ! 731: uchar *draw_obj(ip, mode, dir) /* draw obj from coords at ip */ ! 732: uchar *ip; ! 733: int mode, dir; ! 734: { ! 735: int c, r, thick, n, shift, head; ! 736: Point p0, p1, p2; ! 737: ! 738: if (ip < input || ip >= inp) ! 739: return 0; ! 740: switch (c = *ip++) { ! 741: case 'b': ! 742: p0 = fetchpt(*ip, ip+2); ! 743: p1 = fetchpt(*ip, ip+6); ! 744: if (ip[1] == Bfill) { ! 745: if (p0.y < p1.y) ! 746: rectf(&display, Rpt(p0, p1), mode); ! 747: else ! 748: rectf(&display, Rect(p0.x,p1.y,p1.x,p0.y), mode); ! 749: } else { ! 750: segment(&display, p0, Pt(p0.x,p1.y), mode); ! 751: segment(&display, Pt(p0.x,p1.y), p1, mode); ! 752: segment(&display, p1, Pt(p1.x,p0.y), mode); ! 753: segment(&display, Pt(p1.x,p0.y), p0, mode); ! 754: } ! 755: if (dir == Fwd) ! 756: ip += 1+9+1; ! 757: else ! 758: ip -= (*(ip-2) + 2); ! 759: break; ! 760: case 'l': ! 761: p0 = fetchpt(*ip, ip+2); ! 762: p1 = fetchpt(*ip, ip+6); ! 763: thick = ip[1]/10; /* ought to be a macro! */ ! 764: if (thick == Ldotted/10 || thick == Ldashed/10) ! 765: thick = 1; ! 766: thick = 2 * thick - 1; /* 1,3,5 */ ! 767: fatline(p0, p1, mode, thick); ! 768: head = ip[1]%10; /* ditto */ ! 769: if (head == Larrow1 || head == Larrow3) ! 770: arrow(p0, p1, AW, AH, mode); ! 771: if (head == Larrow2 || head == Larrow3) ! 772: arrow(p1, p0, AW, AH, mode); ! 773: if (dir == Fwd) ! 774: ip += 1+9+1; ! 775: else ! 776: ip -= (*(ip-2) + 2); ! 777: break; ! 778: case 'o': ! 779: p0 = fetchpt(*ip, ip+2); ! 780: r = scalex(*ip, getpoint(ip+6)); ! 781: if (ip[1] == Cnofill) ! 782: fatcircle(p0, r, mode, 1); ! 783: else ! 784: disc(&display, p0, r + fatness, mode); ! 785: if (dir == Fwd) ! 786: ip += 1+7+1; ! 787: else ! 788: ip -= (*(ip-2) + 2); ! 789: break; ! 790: case 't': ! 791: p0 = fetchpt(*ip, ip+2); ! 792: n = ip[6]; ! 793: shift = (ip[1]/10) * 10; /* ought to be a macro! */ ! 794: if (shift == Tljust) ! 795: shift = 0; ! 796: else if (shift == Tcenter) ! 797: shift = (9 * n) / 2; /* 9 = char width */ ! 798: else ! 799: shift = 9 * n; ! 800: string(&defont, ip+7, &display, sub(p0, Pt(shift,8)), mode); ! 801: if (dir == Fwd) ! 802: ip += 1+5 + *(ip+6)+2 + 1; ! 803: else ! 804: ip -= (*(ip-2) + 2); ! 805: break; ! 806: case 'e': ! 807: erase(ip-1); ! 808: if (dir == Fwd) ! 809: ip += 5; ! 810: else ! 811: ip -= (*(ip-2) + 2); ! 812: break; ! 813: case 'c': ! 814: if (dir == Fwd) ! 815: ip += 2; ! 816: else ! 817: ip -= (*(ip-2) + 2); ! 818: break; ! 819: default: ! 820: ip = 0; ! 821: break; ! 822: } ! 823: return ip; ! 824: } ! 825: ! 826: erase(ip) ! 827: uchar *ip; ! 828: { ! 829: long target = getlong(ip+1); /* target label index */ ! 830: int mode = F_XOR; ! 831: ! 832: if (xormode == F_OR || xormode == F_CLR) ! 833: mode = dir == Fwd ? F_CLR : F_OR; ! 834: draw_obj(input+target, mode, Fwd); ! 835: } ! 836: ! 837: #define abs(x) ((x) >= 0 ? (x) : -(x)) ! 838: ! 839: fatline(p0, p1, mode, thick) ! 840: Point p0, p1; ! 841: { ! 842: int i, fat, beg, nl; ! 843: ! 844: fat = thick * (2 * fatness + 1); ! 845: beg = fat / 2; ! 846: if (abs(p1.x-p0.x) >= abs(p1.y-p0.y)) { /* horizontal */ ! 847: for (nl = 0, i = -beg; nl < fat; nl++, i++) ! 848: segment(&display, add(p0, Pt(0,i)), add(p1, Pt(0,i)), mode); ! 849: } else { ! 850: for (nl = 0, i = -beg; nl < fat; nl++, i++) ! 851: segment(&display, add(p0, Pt(i,0)), add(p1, Pt(i,0)), mode); ! 852: } ! 853: } ! 854: ! 855: fatcircle(p0, r, mode, thick) ! 856: Point p0; ! 857: int r, mode, thick; ! 858: { ! 859: int i, fat, beg, nl; ! 860: ! 861: fat = thick * (2 * fatness + 1); ! 862: beg = fat / 2; ! 863: for (nl = 0, i = -beg; nl < fat; nl++, i++) ! 864: circle(&display, p0, r+i, mode); ! 865: } ! 866: ! 867: arrow(p1, p2, w, h, c) ! 868: Point p1, p2; ! 869: int w, h, c; ! 870: /* ! 871: ** draw arrow of height,width (h,w) at p2 of segment p1,p2. ! 872: */ ! 873: { ! 874: Point d; ! 875: int norm, qx, qy, lx, ly; ! 876: ! 877: d = sub(p2, p1); ! 878: norm = sqrt((long)d.x*d.x + (long)d.y*d.y); ! 879: if (norm == 0) /* shouldn't happen, but ... */ ! 880: return; ! 881: qx = p2.x - muldiv(h, d.x, norm); ! 882: qy = p2.y - muldiv(h, d.y, norm); ! 883: lx = muldiv(w/2, -d.y, norm); ! 884: ly = muldiv(w/2, d.x, norm); ! 885: /* segment(&display, p1, p2, c); */ ! 886: segment(&display, Pt(qx+lx, qy+ly), p2, c); ! 887: segment(&display, Pt(qx-lx, qy-ly), p2, c); ! 888: } ! 889: ! 890: but(n) /* parameterize button1(), etc. */ ! 891: int n; ! 892: { ! 893: switch (n) { ! 894: case 1: return button1(); ! 895: case 2: return button2(); ! 896: case 3: return button3(); ! 897: case 12: return button12(); ! 898: case 13: return button1()|button3(); /* not built in */ ! 899: case 23: return button23(); ! 900: case 123: return button123(); ! 901: default: return 0; ! 902: } ! 903: } ! 904: ! 905: checkmouse() /* return button touched if any */ ! 906: { ! 907: int c, b; ! 908: char *p = NULL; ! 909: Point dp; ! 910: Texture *tp; ! 911: ! 912: if (!(own()&MOUSE) || !button123()) ! 913: return 0; /* no hit at all */ ! 914: tp = cursswitch(PTR); ! 915: last_but = 0; ! 916: last_hit = -1; ! 917: c = 0; ! 918: if (button3()) { ! 919: last_hit = menuhit(&mbut3, 3); ! 920: last_but = 3; ! 921: } else if (button2()) { ! 922: last_hit = menuhit(&mbut2, 2); ! 923: last_but = 2; ! 924: } else { /* button1() */ ! 925: last_but = 1; ! 926: } ! 927: while (button123()) ! 928: wait(MOUSE); ! 929: if (last_but == 3 && last_hit>=0) { ! 930: p = m3[last_hit]; ! 931: c = p[strlen(p) - 1]; ! 932: } ! 933: if (c == '?' && !confirm(last_but)) ! 934: last_hit = -1; ! 935: cursswitch(tp); ! 936: return last_but; ! 937: } ! 938: ! 939: confirm(but) /* ask for confirmation if menu item ends with '?' */ ! 940: { ! 941: int c; ! 942: static int but_cvt[8] = { 0, 3, 2, 0, 1, 0, 0, 0 }; ! 943: Texture *tp; ! 944: ! 945: tp = cursswitch(&skull); ! 946: while (!button123()) ! 947: wait(MOUSE); ! 948: c = mouse.buttons & 7; ! 949: while (button123()) ! 950: wait(MOUSE); ! 951: cursswitch(tp); ! 952: return but == but_cvt[c]; ! 953: } ! 954: ! 955: putstring(a1, a2, a3, a4, a5) ! 956: char *a1, *a2, *a3, *a4, *a5; ! 957: { ! 958: static Point p = {0, 0}; ! 959: static int jmax = 0, l; ! 960: char buf[100], *s; ! 961: ! 962: p = Drect.origin; ! 963: if (errline) ! 964: p.y += 16; ! 965: sprintf(buf, a1, a2, a3, a4, a5); ! 966: rectf(&display, Rect(p.x,p.y,p.x+jmax,p.y+16), F_CLR); ! 967: string(&defont, buf, &display, p, F_OR); ! 968: if ((l = jstrwidth(buf)) > jmax) ! 969: jmax = l; ! 970: errline = 0; ! 971: } ! 972: ! 973: assert(c, s) /* poor man's assertion */ ! 974: char *s; ! 975: { ! 976: if (!c) { ! 977: putstring("assertion %s failed\n", s); ! 978: sleep(60); ! 979: } ! 980: } ! 981: ! 982: readbyte() ! 983: { ! 984: int c; ! 985: ! 986: if ((c = rcvchar()) == -1) { ! 987: wait(RCV); ! 988: c = rcvchar(); ! 989: } ! 990: return c; ! 991: } ! 992: ! 993: sendbuf(buf, p) ! 994: char *buf, *p; ! 995: { ! 996: sendnchars((int) (p-buf), buf); ! 997: } ! 998: ! 999: do_kbd() ! 1000: { ! 1001: int c; ! 1002: ! 1003: pkbd = kbdline; ! 1004: for (wait(KBD); (c = kbdchar()) != -1; wait(KBD)) { ! 1005: if (c == '\b' && pkbd > kbdline) ! 1006: --pkbd; ! 1007: else if (c == '@') ! 1008: pkbd = kbdline; ! 1009: else ! 1010: *pkbd++ = c; ! 1011: *pkbd = '\0'; ! 1012: rectf(&display, Rect(Do.x,Do.y,Dc.x,Do.y+16), F_CLR); ! 1013: string(&defont, kbdline, &display, Do, F_STORE); ! 1014: if (c == '\n' || c == '\r') { ! 1015: pkbd[-1] = '\0'; ! 1016: return '\n'; ! 1017: } ! 1018: } ! 1019: } ! 1020:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.