|
|
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.