Merge branch 'vendor/GCC44' into gcc442
[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.4 2006/08/08 16:36:11 pavalos Exp $
36  */
37
38 #include <string.h>
39 #include <termcap.h>
40 #include "back.h"
41
42 static void     bsect(int, int, int, int);
43 static void     fixpos(int, int, int, int, int);
44 static void     fixcol(int, int, int, int, int);
45 static void     newline(void);
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 void
89 fboard(void)
90 {
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
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 static void
199 bsect(int b, int rpos, int cpos, int cnext)
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         bct = 0;
208         n = abs(b);                             /* initialize n and pc */
209         pc = (b > 0? 'r': 'w');
210
211         if (n < 6 && cpos < 54)                 /* position cursor at start */
212                 curmove (rpos,cpos+1);
213         else
214                 curmove (rpos,cpos);
215
216         for (j = 0; j < 5; j++)  {              /* print position row by row */
217
218                 for (k = 0; k < 15; k += 5)             /* print men */
219                         if (n > j+k)
220                                 fancyc (pc);
221
222                 if (j < 4)  {                           /* figure how far to
223                                                          * back up for next
224                                                          * row */
225                         if (n < 6)  {                   /* stop if none left */
226                                 if (j+1 == n)
227                                         break;
228                                 bct = 1;                /* single column */
229                         } else  {
230                                 if (n < 11)  {          /* two columns */
231                                         if (cpos == 54)  {      /* home pos */
232                                                 if (j+5 >= n)
233                                                         bct = 1;
234                                                 else
235                                                         bct = 2;
236                                         }
237                                         if (cpos < 54)  {       /* not home */
238                                                 if (j+6 >= n)
239                                                         bct = 1;
240                                                 else
241                                                         bct = 2;
242                                         }
243                                 } else  {               /* three columns */
244                                         if (j+10 >= n)
245                                                 bct = 2;
246                                         else
247                                                 bct = 3;
248                                 }
249                         }
250                         curmove (curr+cnext,curc-bct);  /* reposition cursor */
251                 }
252         }
253 }
254
255 void
256 refresh(void)
257 {
258         int     i, r, c;
259
260         r = curr;                               /* save current position */
261         c = curc;
262
263         for (i = 12; i > 6; i--)                /* fix positions 12-7 */
264                 if (board[i] != oldb[i])  {
265                         fixpos (oldb[i],board[i],13,1+(12-i)*4,-1);
266                         oldb[i] = board[i];
267                 }
268
269         if (board[0] != oldb[0])  {             /* fix red men on bar */
270                 fixpos (oldb[0],board[0],13,25,-1);
271                 oldb[0] = board[0];
272         }
273
274         for (i = 6; i > 0; i--)                 /* fix positions 6-1 */
275                 if (board[i] != oldb[i])  {
276                         fixpos (oldb[i],board[i],13,29+(6-i)*4,-1);
277                         oldb[i] = board[i];
278                 }
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
286         for (i = 13; i < 19; i++)               /* fix positions 13-18 */
287                 if (board[i] != oldb[i])  {
288                         fixpos (oldb[i],board[i],3,1+(i-13)*4,1);
289                         oldb[i] = board[i];
290                 }
291
292         if (board[25] != oldb[25])  {           /* fix white men on bar */
293                 fixpos (oldb[25],board[25],3,25,1);
294                 oldb[25] = board[25];
295         }
296
297         for (i = 19; i < 25; i++)               /* fix positions 19-24 */
298                 if (board[i] != oldb[i])  {
299                         fixpos (oldb[i],board[i],3,29+(i-19)*4,1);
300                         oldb[i] = board[i];
301                 }
302
303         i = (off[1] < 0? off[1]+15: off[1]);    /* fix red's home */
304         if (oldr != i)  {
305                 fixpos (oldr,i,3,54,1);
306                 oldr = i;
307         }
308
309         curmove (r,c);                          /* return to saved position */
310         newpos();
311         buflush();
312 }
313
314 static void
315 fixpos(int cur, int new, int r, int c, int inc)
316 {
317         int             o, n, nv;
318         int             ov, nc;
319         char            col;
320
321         nc = 0;
322         if (cur*new >= 0)  {
323                 ov = abs(cur);
324                 nv = abs(new);
325                 col = (cur+new > 0? 'r': 'w');
326                 o = (ov-1)/5;
327                 n = (nv-1)/5;
328                 if (o == n)  {
329                         if (o == 2)
330                                 nc = c+2;
331                         if (o == 1)
332                                 nc = c < 54? c: c+1;
333                         if (o == 0)
334                                 nc = c < 54? c+1: c;
335                         if (ov > nv)
336                                 fixcol (r+inc*(nv-n*5),nc,abs(ov-nv),' ',inc);
337                         else
338                                 fixcol (r+inc*(ov-o*5),nc,abs(ov-nv),col,inc);
339                         return;
340                 } else  {
341                         if (c < 54)  {
342                                 if (o+n == 1)  {
343                                         if (n)  {
344                                                 fixcol (r,c,abs(nv-5),col,inc);
345                                                 if (ov != 5)
346                                                         fixcol (r+inc*ov,c+1,abs(ov-5),col,inc);
347                                         } else  {
348                                                 fixcol (r,c,abs(ov-5),' ',inc);
349                                                 if (nv != 5)
350                                                         fixcol (r+inc*nv,c+1,abs(nv-5),' ',inc);
351                                         }
352                                         return;
353                                 }
354                                 if (n == 2)  {
355                                         if (ov != 10)
356                                                 fixcol (r+inc*(ov-5),c,abs(ov-10),col,inc);
357                                         fixcol (r,c+2,abs(nv-10),col,inc);
358                                 } else  {
359                                         if (nv != 10)
360                                                 fixcol (r+inc*(nv-5),c,abs(nv-10),' ',inc);
361                                         fixcol (r,c+2,abs(ov-10),' ',inc);
362                                 }
363                                 return;
364                         }
365                         if (n > o)  {
366                                 fixcol (r+inc*(ov%5),c+o,abs(5*n-ov),col,inc);
367                                 if (nv != 5*n)
368                                         fixcol (r,c+n,abs(5*n-nv),col,inc);
369                         } else  {
370                                 fixcol (r+inc*(nv%5),c+n,abs(5*n-nv),' ',inc);
371                                 if (ov != 5*o)
372                                         fixcol (r,c+o,abs(5*o-ov),' ',inc);
373                         }
374                         return;
375                 }
376         }
377         nv = abs(new);
378         fixcol (r,c+1,nv,new > 0? 'r': 'w',inc);
379         if (abs(cur) <= abs(new))
380                 return;
381         fixcol (r+inc*new,c+1,abs(cur+new),' ',inc);
382 }
383
384 static void
385 fixcol(int r, int c, int l, int ch, int inc)
386 {
387         int     i;
388
389         curmove (r,c);
390         fancyc (ch);
391         for (i = 1; i < l; i++)  {
392                 curmove (curr+inc,curc-1);
393                 fancyc (ch);
394         }
395 }
396
397 void
398 curmove(int r, int c)
399 {
400         if (curr == r && curc == c)
401                 return;
402         if (realr == -1)  {
403                 realr = curr;
404                 realc = curc;
405         }
406         curr = r;
407         curc = c;
408 }
409
410 void
411 newpos(void)
412 {
413         int     r;              /* destination row */
414         int     c;              /* destination column */
415         int     mode = -1;      /* mode of movement */
416
417         int     ccount = 1000;          /* character count */
418         int     i;                      /* index */
419         int     n;                      /* temporary variable */
420         char    *m;                     /* string containing CM movement */
421
422         m = NULL;
423         if (realr == -1)                /* see if already there */
424                 return;
425
426         r = curr;                       /* set current and dest. positions */
427         c = curc;
428         curr = realr;
429         curc = realc;
430
431                                         /* double check position */
432         if (curr == r && curc == c)  {
433                 realr = realc = -1;
434                 return;
435         }
436
437         if (CM)  {                      /* try CM to get there */
438                 mode = 0;
439                 m = (char *)tgoto (CM,c,r);
440                 ccount = strlen (m);
441         }
442
443                                         /* try HO and local movement */
444         if (HO && (n = r+c*lND+lHO) < ccount)  {
445                 mode = 1;
446                 ccount = n;
447         }
448
449                                         /* try various LF combinations */
450         if (r >= curr)  {
451                                                 /* CR, LF, and ND */
452                 if ((n = (r-curr)+c*lND+1) < ccount)  {
453                         mode = 2;
454                         ccount = n;
455                 }
456                                                 /* LF, ND */
457                 if (c >= curc && (n = (r-curr)+(c-curc)*lND) < ccount)  {
458                         mode = 3;
459                         ccount = n;
460                 }
461                                                 /* LF, BS */
462                 if (c < curc && (n = (r-curr)+(curc-c)*lBC) < ccount)  {
463                         mode = 4;
464                         ccount = n;
465                 }
466         }
467
468                                         /* try corresponding UP combinations */
469         if (r < curr)  {
470                                                 /* CR, UP, and ND */
471                 if ((n = (curr-r)*lUP+c*lND+1) < ccount)  {
472                         mode = 5;
473                         ccount = n;
474                 }
475                                                 /* UP and ND */
476                 if (c >= curc && (n = (curr-r)*lUP+(c-curc)*lND) < ccount)  {
477                         mode = 6;
478                         ccount = n;
479                 }
480                                                 /* UP and BS */
481                 if (c < curc && (n = (curr-r)*lUP+(curc-c)*lBC) < ccount)  {
482                         mode = 7;
483                         ccount = n;
484                 }
485         }
486
487                                                 /* space over */
488         if (curr == r && c > curc && linect[r] < curc && c-curc < ccount)
489                 mode = 8;
490
491         switch (mode)  {
492
493         case -1:                                /* error! */
494                 write (2,"\r\nInternal cursor error.\r\n",26);
495                 getout();
496
497                                                 /* direct cursor motion */
498         case  0:
499                 tputs (m,abs(curr-r),addbuf);
500                 break;
501
502                                                 /* relative to "home" */
503         case  1:
504                 tputs (HO,r,addbuf);
505                 for (i = 0; i < r; i++)
506                         addbuf ('\012');
507                 for (i = 0; i < c; i++)
508                         tputs (ND,1,addbuf);
509                 break;
510
511                                                 /* CR and down and over */
512         case  2:
513                 addbuf ('\015');
514                 for (i = 0; i < r-curr; i++)
515                         addbuf ('\012');
516                 for (i = 0; i < c; i++)
517                         tputs (ND,1,addbuf);
518                 break;
519
520                                                 /* down and over */
521         case  3:
522                 for (i = 0; i < r-curr; i++)
523                         addbuf ('\012');
524                 for (i = 0; i < c-curc; i++)
525                         tputs (ND,1,addbuf);
526                 break;
527
528                                                 /* down and back */
529         case  4:
530                 for (i = 0; i < r-curr; i++)
531                         addbuf ('\012');
532                 for (i = 0; i < curc-c; i++)
533                         addbuf ('\010');
534                 break;
535
536                                                 /* CR and up and over */
537         case  5:
538                 addbuf ('\015');
539                 for (i = 0; i < curr-r; i++)
540                         tputs (UP,1,addbuf);
541                 for (i = 0; i < c; i++)
542                         tputs (ND,1,addbuf);
543                 break;
544
545                                                 /* up and over */
546         case  6:
547                 for (i = 0; i < curr-r; i++)
548                         tputs (UP,1,addbuf);
549                 for (i = 0; i < c-curc; i++)
550                         tputs (ND,1,addbuf);
551                 break;
552
553                                                 /* up and back */
554         case  7:
555                 for (i = 0; i < curr-r; i++)
556                         tputs (UP,1,addbuf);
557                 for (i = 0; i < curc-c; i++)  {
558                         if (BC)
559                                 tputs (BC,1,addbuf);
560                         else
561                                 addbuf ('\010');
562                 }
563                 break;
564
565                                                 /* safe space */
566         case  8:
567                 for (i = 0; i < c-curc; i++)
568                         addbuf (' ');
569         }
570
571                                                 /* fix positions */
572         curr = r;
573         curc = c;
574         realr = -1;
575         realc = -1;
576 }
577
578 void
579 clear(void)
580 {
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
598 /* input is character to output */
599 void
600 fancyc(char c)
601 {
602         int     sp;             /* counts spaces in a tab */
603
604         if (c == '\007')  {             /* bells go in blindly */
605                 addbuf (c);
606                 return;
607         }
608
609                                         /* process tabs, use spaces if the
610                                          * the tab should be erasing things,
611                                          * otherwise use cursor movement
612                                          * routines.  Note this does not use
613                                          * hardware tabs at all. */
614         if (c == '\t')  {
615                 sp = (curc+8) & (~ 7);          /* compute spaces */
616                                                 /* check line length */
617                 if (linect[curr] >= curc || sp < 4)  {
618                         for (; sp > curc; sp--)
619                                 addbuf (' ');
620                         curc = sp;              /* fix curc */
621                 } else
622                         curmove (curr,sp);
623                 return;
624         }
625
626                                         /* do newline be calling newline */
627         if (c == '\n')  {
628                 newline();
629                 return;
630         }
631
632                                         /* ignore any other control chars */
633         if (c < ' ')
634                 return;
635
636                                         /* if an erasing space or non-space,
637                                          * just add it to buffer.  Otherwise
638                                          * use cursor movement routine, so that
639                                          * multiple spaces will be grouped
640                                          * together */
641         if (c > ' ' || linect[curr] >= curc)  {
642                 newpos ();                      /* make sure position correct */
643                 addbuf (c);                     /* add character to buffer */
644                                                 /* fix line length */
645                 if (c == ' ' && linect[curr] == curc)
646                         linect[curr]--;
647                 else 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
667         curmove (i = curr,0);
668         cline();
669         while (curr < LI-1)  {
670                 curmove (curr+1,0);
671                 if (linect[curr] > -1)
672                         cline ();
673         }
674         curmove (i,0);
675 }
676
677 void
678 cline(void)
679 {
680         int     c;
681
682         if (curc > linect[curr])
683                 return;
684         newpos ();
685         if (CE)  {
686                 tputs (CE,1,addbuf);
687                 linect[curr] = curc-1;
688         } else  {
689                 c = curc-1;
690                 while (linect[curr] > c)  {
691                         addbuf (' ');
692                         curc++;
693                         linect[curr]--;
694                 }
695                 curmove (curr,c+1);
696         }
697 }
698
699 static void
700 newline(void)
701 {
702         cline();
703         if (curr == LI-1)
704                 curmove (begscr,0);
705         else
706                 curmove (curr+1,0);
707 }
708
709 int
710 getcaps(const char *s)
711 {
712         char    *code;          /* two letter code */
713         char    ***cap;         /* pointer to cap string */
714         char            *bufp;          /* pointer to cap buffer */
715         char            tentry[1024];   /* temporary uncoded caps buffer */
716
717         tgetent (tentry, s);            /* get uncoded termcap entry */
718
719         LI = tgetnum ("li");            /* get number of lines */
720         if (LI == -1)
721                 LI = 12;
722         CO = tgetnum ("co");            /* get number of columns */
723         if (CO == -1)
724                 CO = 65;
725
726         bufp = tbuf;                    /* get padding character */
727         tgetstr ("pc",&bufp);
728         if (bufp != tbuf)
729                 PC = *tbuf;
730         else
731                 PC = 0;
732
733         bufp = tbuf;                    /* get string entries */
734         cap = tstr;
735         for (code = tcap; *code; code += 2)
736                 **cap++ = (char *)tgetstr (code,&bufp);
737
738                                         /* get pertinent lengths */
739         if (HO)
740                 lHO = strlen (HO);
741         if (BC)
742                 lBC = strlen (BC);
743         else
744                 lBC = 1;
745         if (UP)
746                 lUP = strlen (UP);
747         if (ND)
748                 lND = strlen (ND);
749         if (LI < 24 || CO < 72 || !(CL && UP && ND))
750                 return (0);
751         linect = (int *)calloc (LI+1,sizeof(int));
752         return (1);
753 }