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