sockaddr's now require length (K. Sklower);
[unix-history] / usr / src / games / backgammon / common_source / fancy.c
CommitLineData
e0bbfbf9
DF
1/*
2 * Copyright (c) 1980 Regents of the University of California.
eee79f25
KB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
65c7d3b6
KB
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.
e0bbfbf9
DF
16 */
17
18#ifndef lint
65c7d3b6 19static char sccsid[] = "@(#)fancy.c 5.4 (Berkeley) %G%";
eee79f25 20#endif /* not lint */
a95eadb9
RH
21
22#include "back.h"
23
24char PC; /* padding character */
25char *BC; /* backspace sequence */
26char *CD; /* clear to end of screen sequence */
27char *CE; /* clear to end of line sequence */
28char *CL; /* clear screen sequence */
29char *CM; /* cursor movement instructions */
30char *HO; /* home cursor sequence */
31char *MC; /* column cursor movement map */
32char *ML; /* row cursor movement map */
33char *ND; /* forward cursor sequence */
34char *UP; /* up cursor sequence */
35
36int lHO; /* length of HO */
37int lBC; /* length of BC */
38int lND; /* length of ND */
39int lUP; /* length of UP */
40int CO; /* number of columns */
41int LI; /* number of lines */
42int *linect; /* array of lengths of lines on screen
43 (the actual screen is not stored) */
44
45 /* two letter codes */
46char tcap[] = "bccdceclcmhomcmlndup";
47 /* corresponding strings */
48char **tstr[] = { &BC, &CD, &CE, &CL, &CM, &HO, &MC, &ML, &ND, &UP };
49
50int buffnum; /* pointer to output buffer */
51
52char tbuf[1024]; /* buffer for decoded termcap entries */
53
54int 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
56int oldr;
57int oldw;
58 /* "real" cursor positions, so
59 * it knows when to reposition.
60 * These are -1 if curr and curc
61 * are accurate */
62int realr;
63int realc;
64
8c5f4ef6
KB
65void addbuf();
66
a95eadb9
RH
67fboard () {
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\f
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
175bsect (b,rpos,cpos,cnext)
176int b; /* contents of position */
177int rpos; /* row of position */
178int cpos; /* column of position */
179int 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\f
235refresh() {
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\f
292fixpos (old,new,r,c,inc)
293int 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
362fixcol (r,c,l,ch,inc)
363register int l, ch;
364int 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\f
377curmove (r,c)
378register 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
391newpos () {
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 */
a95eadb9
RH
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;
eee79f25 419 m = (char *)tgoto (CM,c,r);
a95eadb9
RH
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\f
558clear () {
559 register int i;
a95eadb9
RH
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
575tos () { /* home cursor */
576 curmove (0,0);
577}
578\f
579fancyc (c)
580register 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\f
635clend() {
636 register int i;
637 register char *s;
a95eadb9
RH
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
657cline () {
658 register int i;
659 register int c;
660 register char *s;
a95eadb9
RH
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
679newline () {
680 cline();
681 if (curr == LI-1)
682 curmove (begscr,0);
683 else
684 curmove (curr+1,0);
685}
686\f
687getcaps (s)
688register 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)
eee79f25 715 **cap++ = (char *)tgetstr (code,&bufp);
a95eadb9
RH
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);
eee79f25 730 linect = (int *)calloc (LI+1,sizeof(int));
a95eadb9
RH
731 return (1);
732}