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