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