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