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 addbuf(); 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: }