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