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