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