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