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