|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that the above copyright notice and this paragraph are
7: * duplicated in all such forms and that any documentation,
8: * advertising materials, and other materials related to such
9: * distribution and use acknowledge that the software was developed
10: * by the University of California, Berkeley. The name of the
11: * University may not be used to endorse or promote products derived
12: * from this software without specific prior written permission.
13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16: */
17:
18: #ifndef lint
19: static char sccsid[] = "@(#)fancy.c 5.4 (Berkeley) 6/18/88";
20: #endif /* not lint */
21:
22: #include "back.h"
23:
24: char PC; /* padding character */
25: char *BC; /* backspace sequence */
26: char *CD; /* clear to end of screen sequence */
27: char *CE; /* clear to end of line sequence */
28: char *CL; /* clear screen sequence */
29: char *CM; /* cursor movement instructions */
30: char *HO; /* home cursor sequence */
31: char *MC; /* column cursor movement map */
32: char *ML; /* row cursor movement map */
33: char *ND; /* forward cursor sequence */
34: char *UP; /* up cursor sequence */
35:
36: int lHO; /* length of HO */
37: int lBC; /* length of BC */
38: int lND; /* length of ND */
39: int lUP; /* length of UP */
40: int CO; /* number of columns */
41: int LI; /* number of lines */
42: int *linect; /* array of lengths of lines on screen
43: (the actual screen is not stored) */
44:
45: /* two letter codes */
46: char tcap[] = "bccdceclcmhomcmlndup";
47: /* corresponding strings */
48: char **tstr[] = { &BC, &CD, &CE, &CL, &CM, &HO, &MC, &ML, &ND, &UP };
49:
50: int buffnum; /* pointer to output buffer */
51:
52: char tbuf[1024]; /* buffer for decoded termcap entries */
53:
54: int oldb[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
55:
56: int oldr;
57: int oldw;
58: /* "real" cursor positions, so
59: * it knows when to reposition.
60: * These are -1 if curr and curc
61: * are accurate */
62: int realr;
63: int realc;
64:
65: void addbuf();
66:
67: fboard () {
68: register int i, j, l;
69:
70: curmove (0,0); /* do top line */
71: for (i = 0; i < 53; i++)
72: fancyc ('_');
73:
74: curmove (15,0); /* do botttom line */
75: for (i = 0; i < 53; i++)
76: fancyc ('_');
77:
78: l = 1; /* do vertical lines */
79: for (i = 52; i > -1; i -= 28) {
80: curmove ( (l == 1? 1: 15) ,i);
81: fancyc ('|');
82: for (j = 0; j < 14; j++) {
83: curmove (curr+l,curc-1);
84: fancyc ('|');
85: }
86: if (i == 24)
87: i += 32;
88: l = -l; /* alternate directions */
89: }
90:
91: curmove (2,1); /* label positions 13-18 */
92: for (i = 13; i < 18; i++) {
93: fancyc ('1');
94: fancyc ((i % 10)+'0');
95: curmove (curr,curc+2);
96: }
97: fancyc ('1');
98: fancyc ('8');
99:
100: curmove (2,29); /* label positions 19-24 */
101: fancyc ('1');
102: fancyc ('9');
103: for (i = 20; i < 25; i++) {
104: curmove (curr,curc+2);
105: fancyc ('2');
106: fancyc ((i % 10)+'0');
107: }
108:
109: curmove (14,1); /* label positions 12-7 */
110: fancyc ('1');
111: fancyc ('2');
112: for (i = 11; i > 6; i--) {
113: curmove (curr,curc+2);
114: fancyc (i > 9? '1': ' ');
115: fancyc ((i % 10)+'0');
116: }
117:
118: curmove (14,30); /* label positions 6-1 */
119: fancyc ('6');
120: for (i = 5; i > 0; i--) {
121: curmove (curr,curc+3);
122: fancyc (i+'0');
123: }
124:
125: for (i = 12; i > 6; i--) /* print positions 12-7 */
126: if (board[i])
127: bsect (board[i],13,1+4*(12-i),-1);
128:
129: if (board[0]) /* print red men on bar */
130: bsect (board[0],13,25,-1);
131:
132: for (i = 6; i > 0; i--) /* print positions 6-1 */
133: if (board[i])
134: bsect (board[i],13,29+4*(6-i),-1);
135:
136: l = (off[1] < 0? off[1]+15: off[1]); /* print white's home */
137: bsect (l,3,54,1);
138:
139: curmove (8,25); /* print the word BAR */
140: fancyc ('B');
141: fancyc ('A');
142: fancyc ('R');
143:
144: for (i = 13; i < 19; i++) /* print positions 13-18 */
145: if (board[i])
146: bsect (board[i],3,1+4*(i-13),1);
147:
148: if (board[25]) /* print white's men on bar */
149: bsect (board[25],3,25,1);
150:
151: for (i = 19; i < 25; i++) /* print positions 19-24 */
152: if (board[i])
153: bsect (board[i],3,29+4*(i-19),1);
154:
155: l = (off[0] < 0? off[0]+15: off[0]); /* print red's home */
156: bsect (-l,13,54,-1);
157:
158: for (i = 0; i < 26; i++) /* save board position
159: * for refresh later */
160: oldb[i] = board[i];
161: oldr = (off[1] < 0? off[1]+15: off[1]);
162: oldw = -(off[0] < 0? off[0]+15: off[0]);
163: }
164:
165: /*
166: * bsect (b,rpos,cpos,cnext)
167: * Print the contents of a board position. "b" has the value of the
168: * position, "rpos" is the row to start printing, "cpos" is the column to
169: * start printing, and "cnext" is positive if the position starts at the top
170: * and negative if it starts at the bottom. The value of "cpos" is checked
171: * to see if the position is a player's home, since those are printed
172: * differently.
173: */
174:
175: bsect (b,rpos,cpos,cnext)
176: int b; /* contents of position */
177: int rpos; /* row of position */
178: int cpos; /* column of position */
179: int cnext; /* direction of position */
180:
181: {
182: register int j; /* index */
183: register int n; /* number of men on position */
184: register int bct; /* counter */
185: int k; /* index */
186: char pc; /* color of men on position */
187:
188: n = abs(b); /* initialize n and pc */
189: pc = (b > 0? 'r': 'w');
190:
191: if (n < 6 && cpos < 54) /* position cursor at start */
192: curmove (rpos,cpos+1);
193: else
194: curmove (rpos,cpos);
195:
196: for (j = 0; j < 5; j++) { /* print position row by row */
197:
198: for (k = 0; k < 15; k += 5) /* print men */
199: if (n > j+k)
200: fancyc (pc);
201:
202: if (j < 4) { /* figure how far to
203: * back up for next
204: * row */
205: if (n < 6) { /* stop if none left */
206: if (j+1 == n)
207: break;
208: bct = 1; /* single column */
209: } else {
210: if (n < 11) { /* two columns */
211: if (cpos == 54) { /* home pos */
212: if (j+5 >= n)
213: bct = 1;
214: else
215: bct = 2;
216: }
217: if (cpos < 54) { /* not home */
218: if (j+6 >= n)
219: bct = 1;
220: else
221: bct = 2;
222: }
223: } else { /* three columns */
224: if (j+10 >= n)
225: bct = 2;
226: else
227: bct = 3;
228: }
229: }
230: curmove (curr+cnext,curc-bct); /* reposition cursor */
231: }
232: }
233: }
234:
235: refresh() {
236: register int i, r, c;
237:
238: r = curr; /* save current position */
239: c = curc;
240:
241: for (i = 12; i > 6; i--) /* fix positions 12-7 */
242: if (board[i] != oldb[i]) {
243: fixpos (oldb[i],board[i],13,1+(12-i)*4,-1);
244: oldb[i] = board[i];
245: }
246:
247: if (board[0] != oldb[0]) { /* fix red men on bar */
248: fixpos (oldb[0],board[0],13,25,-1);
249: oldb[0] = board[0];
250: }
251:
252: for (i = 6; i > 0; i--) /* fix positions 6-1 */
253: if (board[i] != oldb[i]) {
254: fixpos (oldb[i],board[i],13,29+(6-i)*4,-1);
255: oldb[i] = board[i];
256: }
257:
258: i = -(off[0] < 0? off[0]+15: off[0]); /* fix white's home */
259: if (oldw != i) {
260: fixpos (oldw,i,13,54,-1);
261: oldw = i;
262: }
263:
264: for (i = 13; i < 19; i++) /* fix positions 13-18 */
265: if (board[i] != oldb[i]) {
266: fixpos (oldb[i],board[i],3,1+(i-13)*4,1);
267: oldb[i] = board[i];
268: }
269:
270: if (board[25] != oldb[25]) { /* fix white men on bar */
271: fixpos (oldb[25],board[25],3,25,1);
272: oldb[25] = board[25];
273: }
274:
275: for (i = 19; i < 25; i++) /* fix positions 19-24 */
276: if (board[i] != oldb[i]) {
277: fixpos (oldb[i],board[i],3,29+(i-19)*4,1);
278: oldb[i] = board[i];
279: }
280:
281: i = (off[1] < 0? off[1]+15: off[1]); /* fix red's home */
282: if (oldr != i) {
283: fixpos (oldr,i,3,54,1);
284: oldr = i;
285: }
286:
287: curmove (r,c); /* return to saved position */
288: newpos();
289: buflush();
290: }
291:
292: fixpos (old,new,r,c,inc)
293: int old, new, r, c, inc;
294:
295: {
296: register int o, n, nv;
297: int ov, nc;
298: char col;
299:
300: if (old*new >= 0) {
301: ov = abs(old);
302: nv = abs(new);
303: col = (old+new > 0? 'r': 'w');
304: o = (ov-1)/5;
305: n = (nv-1)/5;
306: if (o == n) {
307: if (o == 2)
308: nc = c+2;
309: if (o == 1)
310: nc = c < 54? c: c+1;
311: if (o == 0)
312: nc = c < 54? c+1: c;
313: if (ov > nv)
314: fixcol (r+inc*(nv-n*5),nc,abs(ov-nv),' ',inc);
315: else
316: fixcol (r+inc*(ov-o*5),nc,abs(ov-nv),col,inc);
317: return;
318: } else {
319: if (c < 54) {
320: if (o+n == 1) {
321: if (n) {
322: fixcol (r,c,abs(nv-5),col,inc);
323: if (ov != 5)
324: fixcol (r+inc*ov,c+1,abs(ov-5),col,inc);
325: } else {
326: fixcol (r,c,abs(ov-5),' ',inc);
327: if (nv != 5)
328: fixcol (r+inc*nv,c+1,abs(nv-5),' ',inc);
329: }
330: return;
331: }
332: if (n == 2) {
333: if (ov != 10)
334: fixcol (r+inc*(ov-5),c,abs(ov-10),col,inc);
335: fixcol (r,c+2,abs(nv-10),col,inc);
336: } else {
337: if (nv != 10)
338: fixcol (r+inc*(nv-5),c,abs(nv-10),' ',inc);
339: fixcol (r,c+2,abs(ov-10),' ',inc);
340: }
341: return;
342: }
343: if (n > o) {
344: fixcol (r+inc*(ov%5),c+o,abs(5*n-ov),col,inc);
345: if (nv != 5*n)
346: fixcol (r,c+n,abs(5*n-nv),col,inc);
347: } else {
348: fixcol (r+inc*(nv%5),c+n,abs(5*n-nv),' ',inc);
349: if (ov != 5*o)
350: fixcol (r,c+o,abs(5*o-ov),' ',inc);
351: }
352: return;
353: }
354: }
355: nv = abs(new);
356: fixcol (r,c+1,nv,new > 0? 'r': 'w',inc);
357: if (abs(old) <= abs(new))
358: return;
359: fixcol (r+inc*new,c+1,abs(old+new),' ',inc);
360: }
361:
362: fixcol (r,c,l,ch,inc)
363: register int l, ch;
364: int r, c, inc;
365:
366: {
367: register int i;
368:
369: curmove (r,c);
370: fancyc (ch);
371: for (i = 1; i < l; i++) {
372: curmove (curr+inc,curc-1);
373: fancyc (ch);
374: }
375: }
376:
377: curmove (r,c)
378: register int r, c;
379:
380: {
381: if (curr == r && curc == c)
382: return;
383: if (realr == -1) {
384: realr = curr;
385: realc = curc;
386: }
387: curr = r;
388: curc = c;
389: }
390:
391: newpos () {
392: register int r; /* destination row */
393: register int c; /* destination column */
394: register int mode = -1; /* mode of movement */
395:
396: int count = 1000; /* character count */
397: int i; /* index */
398: int j; /* index */
399: int n; /* temporary variable */
400: char *m; /* string containing CM movement */
401:
402:
403: if (realr == -1) /* see if already there */
404: return;
405:
406: r = curr; /* set current and dest. positions */
407: c = curc;
408: curr = realr;
409: curc = realc;
410:
411: /* double check position */
412: if (curr == r && curc == c) {
413: realr = realc = -1;
414: return;
415: }
416:
417: if (CM) { /* try CM to get there */
418: mode = 0;
419: m = (char *)tgoto (CM,c,r);
420: count = strlen (m);
421: }
422:
423: /* try HO and local movement */
424: if (HO && (n = r+c*lND+lHO) < count) {
425: mode = 1;
426: count = n;
427: }
428:
429: /* try various LF combinations */
430: if (r >= curr) {
431: /* CR, LF, and ND */
432: if ((n = (r-curr)+c*lND+1) < count) {
433: mode = 2;
434: count = n;
435: }
436: /* LF, ND */
437: if (c >= curc && (n = (r-curr)+(c-curc)*lND) < count) {
438: mode = 3;
439: count = n;
440: }
441: /* LF, BS */
442: if (c < curc && (n = (r-curr)+(curc-c)*lBC) < count) {
443: mode = 4;
444: count = n;
445: }
446: }
447:
448: /* try corresponding UP combinations */
449: if (r < curr) {
450: /* CR, UP, and ND */
451: if ((n = (curr-r)*lUP+c*lND+1) < count) {
452: mode = 5;
453: count = n;
454: }
455: /* UP and ND */
456: if (c >= curc && (n = (curr-r)*lUP+(c-curc)*lND) < count) {
457: mode = 6;
458: count = n;
459: }
460: /* UP and BS */
461: if (c < curc && (n = (curr-r)*lUP+(curc-c)*lBC) < count) {
462: mode = 7;
463: count = n;
464: }
465: }
466:
467: /* space over */
468: if (curr == r && c > curc && linect[r] < curc && c-curc < count)
469: mode = 8;
470:
471: switch (mode) {
472:
473: case -1: /* error! */
474: write (2,"\r\nInternal cursor error.\r\n",26);
475: getout();
476:
477: /* direct cursor motion */
478: case 0:
479: tputs (m,abs(curr-r),addbuf);
480: break;
481:
482: /* relative to "home" */
483: case 1:
484: tputs (HO,r,addbuf);
485: for (i = 0; i < r; i++)
486: addbuf ('\012');
487: for (i = 0; i < c; i++)
488: tputs (ND,1,addbuf);
489: break;
490:
491: /* CR and down and over */
492: case 2:
493: addbuf ('\015');
494: for (i = 0; i < r-curr; i++)
495: addbuf ('\012');
496: for (i = 0; i < c; i++)
497: tputs (ND,1,addbuf);
498: break;
499:
500: /* down and over */
501: case 3:
502: for (i = 0; i < r-curr; i++)
503: addbuf ('\012');
504: for (i = 0; i < c-curc; i++)
505: tputs (ND,1,addbuf);
506: break;
507:
508: /* down and back */
509: case 4:
510: for (i = 0; i < r-curr; i++)
511: addbuf ('\012');
512: for (i = 0; i < curc-c; i++)
513: addbuf ('\010');
514: break;
515:
516: /* CR and up and over */
517: case 5:
518: addbuf ('\015');
519: for (i = 0; i < curr-r; i++)
520: tputs (UP,1,addbuf);
521: for (i = 0; i < c; i++)
522: tputs (ND,1,addbuf);
523: break;
524:
525: /* up and over */
526: case 6:
527: for (i = 0; i < curr-r; i++)
528: tputs (UP,1,addbuf);
529: for (i = 0; i < c-curc; i++)
530: tputs (ND,1,addbuf);
531: break;
532:
533: /* up and back */
534: case 7:
535: for (i = 0; i < curr-r; i++)
536: tputs (UP,1,addbuf);
537: for (i = 0; i < curc-c; i++) {
538: if (BC)
539: tputs (BC,1,addbuf);
540: else
541: addbuf ('\010');
542: }
543: break;
544:
545: /* safe space */
546: case 8:
547: for (i = 0; i < c-curc; i++)
548: addbuf (' ');
549: }
550:
551: /* fix positions */
552: curr = r;
553: curc = c;
554: realr = -1;
555: realc = -1;
556: }
557:
558: clear () {
559: register int i;
560:
561: /* double space if can't clear */
562: if (CL == 0) {
563: writel ("\n\n");
564: return;
565: }
566:
567: curr = curc = 0; /* fix position markers */
568: realr = realc = -1;
569: for (i = 0; i < 24; i++) /* clear line counts */
570: linect[i] = -1;
571: buffnum = -1; /* ignore leftover buffer contents */
572: tputs (CL,CO,addbuf); /* put CL in buffer */
573: }
574:
575: tos () { /* home cursor */
576: curmove (0,0);
577: }
578:
579: fancyc (c)
580: register char c; /* character to output */
581: {
582: register int sp; /* counts spaces in a tab */
583:
584: if (c == '\007') { /* bells go in blindly */
585: addbuf (c);
586: return;
587: }
588:
589: /* process tabs, use spaces if the
590: * the tab should be erasing things,
591: * otherwise use cursor movement
592: * routines. Note this does not use
593: * hardware tabs at all. */
594: if (c == '\t') {
595: sp = (curc+8) & (~ 7); /* compute spaces */
596: /* check line length */
597: if (linect[curr] >= curc || sp < 4) {
598: for (; sp > curc; sp--)
599: addbuf (' ');
600: curc = sp; /* fix curc */
601: } else
602: curmove (curr,sp);
603: return;
604: }
605:
606: /* do newline be calling newline */
607: if (c == '\n') {
608: newline();
609: return;
610: }
611:
612: /* ignore any other control chars */
613: if (c < ' ')
614: return;
615:
616: /* if an erasing space or non-space,
617: * just add it to buffer. Otherwise
618: * use cursor movement routine, so that
619: * multiple spaces will be grouped
620: * together */
621: if (c > ' ' || linect[curr] >= curc) {
622: newpos (); /* make sure position correct */
623: addbuf (c); /* add character to buffer */
624: /* fix line length */
625: if (c == ' ' && linect[curr] == curc)
626: linect[curr]--;
627: else if (linect[curr] < curc)
628: linect[curr] = curc;
629: curc++; /* fix curc */
630: } else
631: /* use cursor movement routine */
632: curmove (curr,curc+1);
633: }
634:
635: clend() {
636: register int i;
637: register char *s;
638:
639:
640: if (CD) {
641: tputs (CD,CO-curr,addbuf);
642: for (i = curr; i < LI; i++)
643: linect[i] = -1;
644: return;
645: }
646:
647: curmove (i = curr,0);
648: cline();
649: while (curr < LI-1) {
650: curmove (curr+1,0);
651: if (linect[curr] > -1)
652: cline ();
653: }
654: curmove (i,0);
655: }
656:
657: cline () {
658: register int i;
659: register int c;
660: register char *s;
661:
662: if (curc > linect[curr])
663: return;
664: newpos ();
665: if (CE) {
666: tputs (CE,1,addbuf);
667: linect[curr] = curc-1;
668: } else {
669: c = curc-1;
670: while (linect[curr] > c) {
671: addbuf (' ');
672: curc++;
673: linect[curr]--;
674: }
675: curmove (curr,c+1);
676: }
677: }
678:
679: newline () {
680: cline();
681: if (curr == LI-1)
682: curmove (begscr,0);
683: else
684: curmove (curr+1,0);
685: }
686:
687: getcaps (s)
688: register char *s;
689:
690: {
691: register char *code; /* two letter code */
692: register char ***cap; /* pointer to cap string */
693: char *bufp; /* pointer to cap buffer */
694: char tentry[1024]; /* temporary uncoded caps buffer */
695:
696: tgetent (tentry,s); /* get uncoded termcap entry */
697:
698: LI = tgetnum ("li"); /* get number of lines */
699: if (LI == -1)
700: LI = 12;
701: CO = tgetnum ("co"); /* get number of columns */
702: if (CO == -1)
703: CO = 65;
704:
705: bufp = tbuf; /* get padding character */
706: tgetstr ("pc",&bufp);
707: if (bufp != tbuf)
708: PC = *tbuf;
709: else
710: PC = 0;
711:
712: bufp = tbuf; /* get string entries */
713: cap = tstr;
714: for (code = tcap; *code; code += 2)
715: **cap++ = (char *)tgetstr (code,&bufp);
716:
717: /* get pertinent lengths */
718: if (HO)
719: lHO = strlen (HO);
720: if (BC)
721: lBC = strlen (BC);
722: else
723: lBC = 1;
724: if (UP)
725: lUP = strlen (UP);
726: if (ND)
727: lND = strlen (ND);
728: if (LI < 24 || CO < 72 || !(CL && UP && ND))
729: return (0);
730: linect = (int *)calloc (LI+1,sizeof(int));
731: return (1);
732: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.