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