123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738 |
- /* $NetBSD: fancy.c,v 1.12 2004/04/23 02:58:27 simonb Exp $ */
- /*
- * Copyright (c) 1980, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
- #include <sys/cdefs.h>
- #ifndef lint
- #if 0
- static char sccsid[] = "@(#)fancy.c 8.1 (Berkeley) 5/31/93";
- #else
- __RCSID("$NetBSD: fancy.c,v 1.12 2004/04/23 02:58:27 simonb Exp $");
- #endif
- #endif /* not lint */
- #include "back.h"
- extern char PC; /* padding character */
- extern char *BC; /* backspace sequence */
- char *CD; /* clear to end of screen sequence */
- char *CE; /* clear to end of line sequence */
- char *CL; /* clear screen sequence */
- char *CM; /* cursor movement instructions */
- char *HO; /* home cursor sequence */
- char *MC; /* column cursor movement map */
- char *ML; /* row cursor movement map */
- char *ND; /* forward cursor sequence */
- extern char *UP; /* up cursor sequence */
- int lHO; /* length of HO */
- int lBC; /* length of BC */
- int lND; /* length of ND */
- int lUP; /* length of UP */
- int CO; /* number of columns */
- int LI; /* number of lines */
- int *linect; /* array of lengths of lines on screen (the
- * actual screen is not stored) */
- /* two letter codes */
- char tcap[] = "bccdceclcmhomcmlndup";
- /* corresponding strings */
- char **tstr[] = {&BC, &CD, &CE, &CL, &CM, &HO, &MC, &ML, &ND, &UP};
- extern int buffnum; /* pointer to output buffer */
- char tbuf[1024]; /* buffer for decoded termcap entries */
- 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};
- int oldr;
- int oldw;
- /* "real" cursor positions, so it knows when to reposition. These are -1 if
- * curr and curc are accurate */
- int realr;
- int realc;
- void
- fboard()
- {
- int i, j, l;
- curmove(0, 0); /* do top line */
- for (i = 0; i < 53; i++)
- fancyc('_');
- curmove(15, 0); /* do botttom line */
- for (i = 0; i < 53; i++)
- fancyc('_');
- l = 1; /* do vertical lines */
- for (i = 52; i > -1; i -= 28) {
- curmove((l == 1 ? 1 : 15), i);
- fancyc('|');
- for (j = 0; j < 14; j++) {
- curmove(curr + l, curc - 1);
- fancyc('|');
- }
- if (i == 24)
- i += 32;
- l = -l; /* alternate directions */
- }
- curmove(2, 1); /* label positions 13-18 */
- for (i = 13; i < 18; i++) {
- fancyc('1');
- fancyc((i % 10) + '0');
- curmove(curr, curc + 2);
- }
- fancyc('1');
- fancyc('8');
- curmove(2, 29); /* label positions 19-24 */
- fancyc('1');
- fancyc('9');
- for (i = 20; i < 25; i++) {
- curmove(curr, curc + 2);
- fancyc('2');
- fancyc((i % 10) + '0');
- }
- curmove(14, 1); /* label positions 12-7 */
- fancyc('1');
- fancyc('2');
- for (i = 11; i > 6; i--) {
- curmove(curr, curc + 2);
- fancyc(i > 9 ? '1' : ' ');
- fancyc((i % 10) + '0');
- }
- curmove(14, 30); /* label positions 6-1 */
- fancyc('6');
- for (i = 5; i > 0; i--) {
- curmove(curr, curc + 3);
- fancyc(i + '0');
- }
- for (i = 12; i > 6; i--)/* print positions 12-7 */
- if (board[i])
- bsect(board[i], 13, 1 + 4 * (12 - i), -1);
- if (board[0]) /* print red men on bar */
- bsect(board[0], 13, 25, -1);
- for (i = 6; i > 0; i--) /* print positions 6-1 */
- if (board[i])
- bsect(board[i], 13, 29 + 4 * (6 - i), -1);
- l = (off[1] < 0 ? off[1] + 15 : off[1]); /* print white's home */
- bsect(l, 3, 54, 1);
- curmove(8, 25); /* print the word BAR */
- fancyc('B');
- fancyc('A');
- fancyc('R');
- for (i = 13; i < 19; i++) /* print positions 13-18 */
- if (board[i])
- bsect(board[i], 3, 1 + 4 * (i - 13), 1);
- if (board[25]) /* print white's men on bar */
- bsect(board[25], 3, 25, 1);
- for (i = 19; i < 25; i++) /* print positions 19-24 */
- if (board[i])
- bsect(board[i], 3, 29 + 4 * (i - 19), 1);
- l = (off[0] < 0 ? off[0] + 15 : off[0]); /* print red's home */
- bsect(-l, 13, 54, -1);
- for (i = 0; i < 26; i++)/* save board position for refresh later */
- oldb[i] = board[i];
- oldr = (off[1] < 0 ? off[1] + 15 : off[1]);
- oldw = -(off[0] < 0 ? off[0] + 15 : off[0]);
- }
- /*
- * bsect (b,rpos,cpos,cnext)
- * Print the contents of a board position. "b" has the value of the
- * position, "rpos" is the row to start printing, "cpos" is the column to
- * start printing, and "cnext" is positive if the position starts at the top
- * and negative if it starts at the bottom. The value of "cpos" is checked
- * to see if the position is a player's home, since those are printed
- * differently.
- */
- void
- bsect(b, rpos, cpos, cnext)
- int b; /* contents of position */
- int rpos; /* row of position */
- int cpos; /* column of position */
- int cnext; /* direction of position */
- {
- int j; /* index */
- int n; /* number of men on position */
- int bct; /* counter */
- int k; /* index */
- char pc; /* color of men on position */
- bct = 0;
- n = abs(b); /* initialize n and pc */
- pc = (b > 0 ? 'r' : 'w');
- if (n < 6 && cpos < 54) /* position cursor at start */
- curmove(rpos, cpos + 1);
- else
- curmove(rpos, cpos);
- for (j = 0; j < 5; j++) { /* print position row by row */
- for (k = 0; k < 15; k += 5) /* print men */
- if (n > j + k)
- fancyc(pc);
- if (j < 4) { /* figure how far to back up for next row */
- if (n < 6) { /* stop if none left */
- if (j + 1 == n)
- break;
- bct = 1; /* single column */
- } else {
- if (n < 11) { /* two columns */
- if (cpos == 54) { /* home pos */
- if (j + 5 >= n)
- bct = 1;
- else
- bct = 2;
- }
- if (cpos < 54) { /* not home */
- if (j + 6 >= n)
- bct = 1;
- else
- bct = 2;
- }
- } else { /* three columns */
- if (j + 10 >= n)
- bct = 2;
- else
- bct = 3;
- }
- }
- curmove(curr + cnext, curc - bct); /* reposition cursor */
- }
- }
- }
- void
- refresh()
- {
- int i, r, c;
- r = curr; /* save current position */
- c = curc;
- for (i = 12; i > 6; i--)/* fix positions 12-7 */
- if (board[i] != oldb[i]) {
- fixpos(oldb[i], board[i], 13, 1 + (12 - i) * 4, -1);
- oldb[i] = board[i];
- }
- if (board[0] != oldb[0]) { /* fix red men on bar */
- fixpos(oldb[0], board[0], 13, 25, -1);
- oldb[0] = board[0];
- }
- for (i = 6; i > 0; i--) /* fix positions 6-1 */
- if (board[i] != oldb[i]) {
- fixpos(oldb[i], board[i], 13, 29 + (6 - i) * 4, -1);
- oldb[i] = board[i];
- }
- i = -(off[0] < 0 ? off[0] + 15 : off[0]); /* fix white's home */
- if (oldw != i) {
- fixpos(oldw, i, 13, 54, -1);
- oldw = i;
- }
- for (i = 13; i < 19; i++) /* fix positions 13-18 */
- if (board[i] != oldb[i]) {
- fixpos(oldb[i], board[i], 3, 1 + (i - 13) * 4, 1);
- oldb[i] = board[i];
- }
- if (board[25] != oldb[25]) { /* fix white men on bar */
- fixpos(oldb[25], board[25], 3, 25, 1);
- oldb[25] = board[25];
- }
- for (i = 19; i < 25; i++) /* fix positions 19-24 */
- if (board[i] != oldb[i]) {
- fixpos(oldb[i], board[i], 3, 29 + (i - 19) * 4, 1);
- oldb[i] = board[i];
- }
- i = (off[1] < 0 ? off[1] + 15 : off[1]); /* fix red's home */
- if (oldr != i) {
- fixpos(oldr, i, 3, 54, 1);
- oldr = i;
- }
- curmove(r, c); /* return to saved position */
- newpos();
- buflush();
- }
- void
- fixpos(old, new, r, c, inc)
- int old, new, r, c, inc;
- {
- int o, n, nv;
- int ov, nc;
- char col;
- nc = 0;
- if (old * new >= 0) {
- ov = abs(old);
- nv = abs(new);
- col = (old + new > 0 ? 'r' : 'w');
- o = (ov - 1) / 5;
- n = (nv - 1) / 5;
- if (o == n) {
- if (o == 2)
- nc = c + 2;
- if (o == 1)
- nc = c < 54 ? c : c + 1;
- if (o == 0)
- nc = c < 54 ? c + 1 : c;
- if (ov > nv)
- fixcol(r + inc * (nv - n * 5), nc, abs(ov - nv), ' ', inc);
- else
- fixcol(r + inc * (ov - o * 5), nc, abs(ov - nv), col, inc);
- return;
- } else {
- if (c < 54) {
- if (o + n == 1) {
- if (n) {
- fixcol(r, c, abs(nv - 5), col, inc);
- if (ov != 5)
- fixcol(r + inc * ov, c + 1,
- abs(ov - 5), col, inc);
- } else {
- fixcol(r, c, abs(ov - 5), ' ', inc);
- if (nv != 5)
- fixcol(r + inc * nv, c + 1,
- abs(nv - 5), ' ', inc);
- }
- return;
- }
- if (n == 2) {
- if (ov != 10)
- fixcol(r + inc * (ov - 5), c,
- abs(ov - 10), col, inc);
- fixcol(r, c + 2, abs(nv - 10), col, inc);
- } else {
- if (nv != 10)
- fixcol(r + inc * (nv - 5), c,
- abs(nv - 10), ' ', inc);
- fixcol(r, c + 2, abs(ov - 10), ' ', inc);
- }
- return;
- }
- if (n > o) {
- fixcol(r + inc * (ov % 5), c + o, abs(5 * n - ov), col, inc);
- if (nv != 5 * n)
- fixcol(r, c + n, abs(5 * n - nv), col, inc);
- } else {
- fixcol(r + inc * (nv % 5), c + n, abs(5 * n - nv), ' ', inc);
- if (ov != 5 * o)
- fixcol(r, c + o, abs(5 * o - ov), ' ', inc);
- }
- return;
- }
- }
- nv = abs(new);
- fixcol(r, c + 1, nv, new > 0 ? 'r' : 'w', inc);
- if (abs(old) <= abs(new))
- return;
- fixcol(r + inc * new, c + 1, abs(old + new), ' ', inc);
- }
- void
- fixcol(r, c, l, ch, inc)
- int l, ch, r, c, inc;
- {
- int i;
- curmove(r, c);
- fancyc(ch);
- for (i = 1; i < l; i++) {
- curmove(curr + inc, curc - 1);
- fancyc(ch);
- }
- }
- void
- curmove(r, c)
- int r, c;
- {
- if (curr == r && curc == c)
- return;
- if (realr == -1) {
- realr = curr;
- realc = curc;
- }
- curr = r;
- curc = c;
- }
- void
- newpos()
- {
- int r; /* destination row */
- int c; /* destination column */
- int mode = -1; /* mode of movement */
- int count = 1000; /* character count */
- int i; /* index */
- int n; /* temporary variable */
- char *m; /* string containing CM movement */
- m = NULL;
- if (realr == -1) /* see if already there */
- return;
- r = curr; /* set current and dest. positions */
- c = curc;
- curr = realr;
- curc = realc;
- /* double check position */
- if (curr == r && curc == c) {
- realr = realc = -1;
- return;
- }
- if (CM) { /* try CM to get there */
- mode = 0;
- m = (char *) tgoto(CM, c, r);
- count = strlen(m);
- }
- /* try HO and local movement */
- if (HO && (n = r + c * lND + lHO) < count) {
- mode = 1;
- count = n;
- }
- /* try various LF combinations */
- if (r >= curr) {
- /* CR, LF, and ND */
- if ((n = (r - curr) + c * lND + 1) < count) {
- mode = 2;
- count = n;
- }
- /* LF, ND */
- if (c >= curc && (n = (r - curr) + (c - curc) * lND) < count) {
- mode = 3;
- count = n;
- }
- /* LF, BS */
- if (c < curc && (n = (r - curr) + (curc - c) * lBC) < count) {
- mode = 4;
- count = n;
- }
- }
- /* try corresponding UP combinations */
- if (r < curr) {
- /* CR, UP, and ND */
- if ((n = (curr - r) * lUP + c * lND + 1) < count) {
- mode = 5;
- count = n;
- }
- /* UP and ND */
- if (c >= curc && (n = (curr - r) * lUP + (c - curc) * lND) < count) {
- mode = 6;
- count = n;
- }
- /* UP and BS */
- if (c < curc && (n = (curr - r) * lUP + (curc - c) * lBC) < count) {
- mode = 7;
- count = n;
- }
- }
- /* space over */
- if (curr == r && c > curc && linect[r] < curc && c - curc < count)
- mode = 8;
- switch (mode) {
- case -1: /* error! */
- write(2, "\r\nInternal cursor error.\r\n", 26);
- getout(0);
- /* direct cursor motion */
- case 0:
- tputs(m, abs(curr - r), addbuf);
- break;
- /* relative to "home" */
- case 1:
- tputs(HO, r, addbuf);
- for (i = 0; i < r; i++)
- addbuf('\012');
- for (i = 0; i < c; i++)
- tputs(ND, 1, addbuf);
- break;
- /* CR and down and over */
- case 2:
- addbuf('\015');
- for (i = 0; i < r - curr; i++)
- addbuf('\012');
- for (i = 0; i < c; i++)
- tputs(ND, 1, addbuf);
- break;
- /* down and over */
- case 3:
- for (i = 0; i < r - curr; i++)
- addbuf('\012');
- for (i = 0; i < c - curc; i++)
- tputs(ND, 1, addbuf);
- break;
- /* down and back */
- case 4:
- for (i = 0; i < r - curr; i++)
- addbuf('\012');
- for (i = 0; i < curc - c; i++)
- addbuf('\010');
- break;
- /* CR and up and over */
- case 5:
- addbuf('\015');
- for (i = 0; i < curr - r; i++)
- tputs(UP, 1, addbuf);
- for (i = 0; i < c; i++)
- tputs(ND, 1, addbuf);
- break;
- /* up and over */
- case 6:
- for (i = 0; i < curr - r; i++)
- tputs(UP, 1, addbuf);
- for (i = 0; i < c - curc; i++)
- tputs(ND, 1, addbuf);
- break;
- /* up and back */
- case 7:
- for (i = 0; i < curr - r; i++)
- tputs(UP, 1, addbuf);
- for (i = 0; i < curc - c; i++) {
- if (BC)
- tputs(BC, 1, addbuf);
- else
- addbuf('\010');
- }
- break;
- /* safe space */
- case 8:
- for (i = 0; i < c - curc; i++)
- addbuf(' ');
- }
- /* fix positions */
- curr = r;
- curc = c;
- realr = -1;
- realc = -1;
- }
- void
- clear()
- {
- int i;
- /* double space if can't clear */
- if (CL == 0) {
- writel("\n\n");
- return;
- }
- curr = curc = 0; /* fix position markers */
- realr = realc = -1;
- for (i = 0; i < 24; i++)/* clear line counts */
- linect[i] = -1;
- buffnum = -1; /* ignore leftover buffer contents */
- tputs(CL, CO, addbuf); /* put CL in buffer */
- }
- void
- fancyc(c)
- char c; /* character to output */
- {
- int sp; /* counts spaces in a tab */
- if (c == '\007') { /* bells go in blindly */
- addbuf(c);
- return;
- }
- /* process tabs, use spaces if the tab should be erasing things,
- * otherwise use cursor movement routines. Note this does not use
- * hardware tabs at all. */
- if (c == '\t') {
- sp = (curc + 8) & (~7); /* compute spaces */
- /* check line length */
- if (linect[curr] >= curc || sp < 4) {
- for (; sp > curc; sp--)
- addbuf(' ');
- curc = sp; /* fix curc */
- } else
- curmove(curr, sp);
- return;
- }
- /* do newline be calling newline */
- if (c == '\n') {
- newline();
- return;
- }
- /* ignore any other control chars */
- if (c < ' ')
- return;
- /* if an erasing space or non-space, just add it to buffer. Otherwise
- * use cursor movement routine, so that multiple spaces will be
- * grouped together */
- if (c > ' ' || linect[curr] >= curc) {
- newpos(); /* make sure position correct */
- addbuf(c); /* add character to buffer */
- /* fix line length */
- if (c == ' ' && linect[curr] == curc)
- linect[curr]--;
- else
- if (linect[curr] < curc)
- linect[curr] = curc;
- curc++; /* fix curc */
- } else
- /* use cursor movement routine */
- curmove(curr, curc + 1);
- }
- void
- clend()
- {
- int i;
- if (CD) {
- tputs(CD, CO - curr, addbuf);
- for (i = curr; i < LI; i++)
- linect[i] = -1;
- return;
- }
- curmove(i = curr, 0);
- cline();
- while (curr < LI - 1) {
- curmove(curr + 1, 0);
- if (linect[curr] > -1)
- cline();
- }
- curmove(i, 0);
- }
- void
- cline()
- {
- int c;
- if (curc > linect[curr])
- return;
- newpos();
- if (CE) {
- tputs(CE, 1, addbuf);
- linect[curr] = curc - 1;
- } else {
- c = curc - 1;
- while (linect[curr] > c) {
- addbuf(' ');
- curc++;
- linect[curr]--;
- }
- curmove(curr, c + 1);
- }
- }
- void
- newline()
- {
- cline();
- if (curr == LI - 1)
- curmove(begscr, 0);
- else
- curmove(curr + 1, 0);
- }
- int
- getcaps(s)
- const char *s;
- {
- char *code; /* two letter code */
- char ***cap; /* pointer to cap string */
- char *bufp; /* pointer to cap buffer */
- char tentry[1024]; /* temporary uncoded caps buffer */
- tgetent(tentry, s); /* get uncoded termcap entry */
- LI = tgetnum("li"); /* get number of lines */
- if (LI == -1)
- LI = 12;
- CO = tgetnum("co"); /* get number of columns */
- if (CO == -1)
- CO = 65;
- bufp = tbuf; /* get padding character */
- tgetstr("pc", &bufp);
- if (bufp != tbuf)
- PC = *tbuf;
- else
- PC = 0;
- bufp = tbuf; /* get string entries */
- cap = tstr;
- for (code = tcap; *code; code += 2)
- **cap++ = (char *) tgetstr(code, &bufp);
- /* get pertinent lengths */
- if (HO)
- lHO = strlen(HO);
- if (BC)
- lBC = strlen(BC);
- else
- lBC = 1;
- if (UP)
- lUP = strlen(UP);
- if (ND)
- lND = strlen(ND);
- if (LI < 24 || CO < 72 || !(CL && UP && ND))
- return (0);
- linect = (int *) calloc(LI + 1, sizeof(int));
- if (linect == NULL) {
- write(2, "\r\nOut of memory!\r\n", 18);
- getout(0);
- }
- return (1);
- }
|