#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.20 2024/11/29 21:48:44 dholland Exp $");
#endif
#endif
#include "back.h"
static void bsect(int, int, int, int);
static void fixpos(int, int, int, int, int);
static void fixcol(int, int, int, int, int);
static void newline(void);
#if 0
char PC;
char *BC;
#endif
static char *CD;
static char *CE;
static char *CL;
static char *CM;
static char *HO;
static char *MC;
static char *ML;
static char *ND;
#if 0
char *UP;
#endif
static int lHO;
static int lBC;
static int lND;
static int lUP;
static int CO;
static int LI;
static int *linect;
static char tcap[] = "bccdceclcmhomcmlndup";
static char **tstr[] = {&BC, &CD, &CE, &CL, &CM, &HO, &MC, &ML, &ND, &UP};
static char tbuf[1024];
static 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};
static int oldr;
static int oldw;
static int realr;
static int realc;
void
fboard(void)
{
int i, j, l;
curmove(0, 0);
for (i = 0; i < 53; i++)
fancyc('_');
curmove(15, 0);
for (i = 0; i < 53; i++)
fancyc('_');
l = 1;
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;
}
curmove(2, 1);
for (i = 13; i < 18; i++) {
fancyc('1');
fancyc((i % 10) + '0');
curmove(curr, curc + 2);
}
fancyc('1');
fancyc('8');
curmove(2, 29);
fancyc('1');
fancyc('9');
for (i = 20; i < 25; i++) {
curmove(curr, curc + 2);
fancyc('2');
fancyc((i % 10) + '0');
}
curmove(14, 1);
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);
fancyc('6');
for (i = 5; i > 0; i--) {
curmove(curr, curc + 3);
fancyc(i + '0');
}
for (i = 12; i > 6; i--)
if (board[i])
bsect(board[i], 13, 1 + 4 * (12 - i), -1);
if (board[0])
bsect(board[0], 13, 25, -1);
for (i = 6; i > 0; i--)
if (board[i])
bsect(board[i], 13, 29 + 4 * (6 - i), -1);
l = (off[1] < 0 ? off[1] + 15 : off[1]);
bsect(l, 3, 54, 1);
curmove(8, 25);
fancyc('B');
fancyc('A');
fancyc('R');
for (i = 13; i < 19; i++)
if (board[i])
bsect(board[i], 3, 1 + 4 * (i - 13), 1);
if (board[25])
bsect(board[25], 3, 25, 1);
for (i = 19; i < 25; i++)
if (board[i])
bsect(board[i], 3, 29 + 4 * (i - 19), 1);
l = (off[0] < 0 ? off[0] + 15 : off[0]);
bsect(-l, 13, 54, -1);
for (i = 0; i < 26; i++)
oldb[i] = board[i];
oldr = (off[1] < 0 ? off[1] + 15 : off[1]);
oldw = -(off[0] < 0 ? off[0] + 15 : off[0]);
}
static void
bsect(int b, int rpos, int cpos, int cnext)
{
int j;
int n;
int bct;
int k;
char pc;
bct = 0;
n = abs(b);
pc = (b > 0 ? 'r' : 'w');
if (n < 6 && cpos < 54)
curmove(rpos, cpos + 1);
else
curmove(rpos, cpos);
for (j = 0; j < 5; j++) {
for (k = 0; k < 15; k += 5)
if (n > j + k)
fancyc(pc);
if (j < 4) {
if (n < 6) {
if (j + 1 == n)
break;
bct = 1;
} else {
if (n < 11) {
if (cpos == 54) {
if (j + 5 >= n)
bct = 1;
else
bct = 2;
}
if (cpos < 54) {
if (j + 6 >= n)
bct = 1;
else
bct = 2;
}
} else {
if (j + 10 >= n)
bct = 2;
else
bct = 3;
}
}
curmove(curr + cnext, curc - bct);
}
}
}
void
refresh(void)
{
int i, r, c;
r = curr;
c = curc;
for (i = 12; i > 6; i--)
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]) {
fixpos(oldb[0], board[0], 13, 25, -1);
oldb[0] = board[0];
}
for (i = 6; i > 0; i--)
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]);
if (oldw != i) {
fixpos(oldw, i, 13, 54, -1);
oldw = i;
}
for (i = 13; i < 19; i++)
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]) {
fixpos(oldb[25], board[25], 3, 25, 1);
oldb[25] = board[25];
}
for (i = 19; i < 25; i++)
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]);
if (oldr != i) {
fixpos(oldr, i, 3, 54, 1);
oldr = i;
}
curmove(r, c);
newpos();
buflush();
}
static void
fixpos(int cur, int new, int r, int c, int inc)
{
int o, n, nv;
int ov, nc;
char col;
nc = 0;
if (cur * new >= 0) {
ov = abs(cur);
nv = abs(new);
col = (cur + 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(cur) <= abs(new))
return;
fixcol(r + inc * new, c + 1, abs(cur + new), ' ', inc);
}
static void
fixcol(int r, int c, int l, int ch, int inc)
{
int i;
curmove(r, c);
fancyc(ch);
for (i = 1; i < l; i++) {
curmove(curr + inc, curc - 1);
fancyc(ch);
}
}
void
curmove(int r, int c)
{
if (curr == r && curc == c)
return;
if (realr == -1) {
realr = curr;
realc = curc;
}
curr = r;
curc = c;
}
void
newpos(void)
{
int r;
int c;
int mode = -1;
int ccount = 1000;
int i;
int n;
char *m;
m = NULL;
if (realr == -1)
return;
r = curr;
c = curc;
curr = realr;
curc = realc;
if (curr == r && curc == c) {
realr = realc = -1;
return;
}
if (CM) {
mode = 0;
m = (char *) tgoto(CM, c, r);
ccount = (int)strlen(m);
}
if (HO && (n = r + c * lND + lHO) < ccount) {
mode = 1;
ccount = n;
}
if (r >= curr) {
if ((n = (r - curr) + c * lND + 1) < ccount) {
mode = 2;
ccount = n;
}
if (c >= curc && (n = (r - curr) + (c - curc) * lND) < ccount) {
mode = 3;
ccount = n;
}
if (c < curc && (n = (r - curr) + (curc - c) * lBC) < ccount) {
mode = 4;
ccount = n;
}
}
if (r < curr) {
if ((n = (curr - r) * lUP + c * lND + 1) < ccount) {
mode = 5;
ccount = n;
}
if (c >= curc &&
(n = (curr - r) * lUP + (c - curc) * lND) < ccount) {
mode = 6;
ccount = n;
}
if (c < curc &&
(n = (curr - r) * lUP + (curc - c) * lBC) < ccount) {
mode = 7;
ccount = n;
}
}
if (curr == r && c > curc && linect[r] < curc && c - curc < ccount)
mode = 8;
switch (mode) {
case -1:
write(2, "\r\nInternal cursor error.\r\n", 26);
getout(0);
case 0:
tputs(m, abs(curr - r), addbuf);
break;
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;
case 2:
addbuf('\015');
for (i = 0; i < r - curr; i++)
addbuf('\012');
for (i = 0; i < c; i++)
tputs(ND, 1, addbuf);
break;
case 3:
for (i = 0; i < r - curr; i++)
addbuf('\012');
for (i = 0; i < c - curc; i++)
tputs(ND, 1, addbuf);
break;
case 4:
for (i = 0; i < r - curr; i++)
addbuf('\012');
for (i = 0; i < curc - c; i++)
addbuf('\010');
break;
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;
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;
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;
case 8:
for (i = 0; i < c - curc; i++)
addbuf(' ');
}
curr = r;
curc = c;
realr = -1;
realc = -1;
}
void
clear(void)
{
int i;
if (CL == NULL) {
writel("\n\n");
return;
}
curr = curc = 0;
realr = realc = -1;
for (i = 0; i < 24; i++)
linect[i] = -1;
buffnum = -1;
tputs(CL, CO, addbuf);
}
void
fancyc(int c)
{
int sp;
if (c == '\007') {
addbuf(c);
return;
}
if (c == '\t') {
sp = (curc + 8) & (~7);
if (linect[curr] >= curc || sp < 4) {
for (; sp > curc; sp--)
addbuf(' ');
curc = sp;
} else
curmove(curr, sp);
return;
}
if (c == '\n') {
newline();
return;
}
if (c < ' ')
return;
if (c > ' ' || linect[curr] >= curc) {
newpos();
addbuf(c);
if (c == ' ' && linect[curr] == curc)
linect[curr]--;
else
if (linect[curr] < curc)
linect[curr] = curc;
curc++;
} else
curmove(curr, curc + 1);
}
void
clend(void)
{
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(void)
{
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);
}
}
static void
newline(void)
{
cline();
if (curr == LI - 1)
curmove(begscr, 0);
else
curmove(curr + 1, 0);
}
int
getcaps(const char *s)
{
char *code;
char ***cap;
char *bufp;
char tentry[1024];
tgetent(tentry, s);
LI = tgetnum("li");
if (LI == -1)
LI = 12;
CO = tgetnum("co");
if (CO == -1)
CO = 65;
bufp = tbuf;
tgetstr("pc", &bufp);
if (bufp != tbuf)
PC = *tbuf;
else
PC = 0;
bufp = tbuf;
cap = tstr;
for (code = tcap; *code; code += 2)
**cap++ = (char *) tgetstr(code, &bufp);
if (HO)
lHO = (int)strlen(HO);
if (BC)
lBC = (int)strlen(BC);
else
lBC = 1;
if (UP)
lUP = (int)strlen(UP);
if (ND)
lND = (int)strlen(ND);
if (LI < 24 || CO < 72 || !(CL && UP && ND)) {
CL = NULL;
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);
}