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