Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / games / larn / io.c
1 /* io.c                  Larn is copyrighted 1986 by Noah Morgan.
2  * $FreeBSD: src/games/larn/io.c,v 1.7 1999/11/16 02:57:22 billf Exp $
3  * $DragonFly: src/games/larn/io.c,v 1.2 2003/06/17 04:25:24 dillon Exp $
4  *
5  *      Below are the functions in this file:
6  *
7  *      setupvt100()    Subroutine to set up terminal in correct mode for game
8  *      clearvt100()    Subroutine to clean up terminal when the game is over
9  *      getchar()               Routine to read in one character from the terminal
10  *      scbr()                  Function to set cbreak -echo for the terminal
11  *      sncbr()                 Function to set -cbreak echo for the terminal
12  *      newgame()               Subroutine to save the initial time and seed rnd()
13  *
14  *      FILE OUTPUT ROUTINES
15  *
16  *      lprintf(format,args . . .)      printf to the output buffer
17  *      lprint(integer)                         send binary integer to output buffer
18  *      lwrite(buf,len)                         write a buffer to the output buffer
19  *      lprcat(str)                                     sent string to output buffer
20  *
21  *      FILE OUTPUT MACROS (in header.h)
22  *
23  *      lprc(character)                         put the character into the output buffer
24  *
25  *      FILE INPUT ROUTINES
26  *
27  *      long lgetc()                            read one character from input buffer
28  *      long lrint()                            read one integer from input buffer
29  *      lrfill(address,number)          put input bytes into a buffer
30  *      char *lgetw()                           get a whitespace ended word from input
31  *      char *lgetl()                           get a \n or EOF ended line from input
32  *
33  *      FILE OPEN / CLOSE ROUTINES
34  *
35  *      lcreat(filename)                        create a new file for write
36  *      lopen(filename)                         open a file for read
37  *      lappend(filename)                       open for append to an existing file
38  *      lrclose()                                       close the input file
39  *      lwclose()                                       close output file
40  *      lflush()                                        flush the output buffer
41  *
42  *      Other Routines
43  *
44  *      cursor(x,y)                                     position cursor at [x,y]
45  *      cursors()                                       position cursor at [1,24] (saves memory)
46  *  cl_line(x,y)                        Clear line at [1,y] and leave cursor at [x,y]
47  *  cl_up(x,y)                                  Clear screen from [x,1] to current line.
48  *  cl_dn(x,y)                                  Clear screen from [1,y] to end of display.
49  *  standout(str)                               Print the string in standout mode.
50  *  set_score_output()                  Called when output should be literally printed.
51  ** putchar(ch)                                 Print one character in decoded output buffer.
52  ** flush_buf()                                 Flush buffer with decoded output.
53  ** init_term()                                 Terminal initialization -- setup termcap info
54  **     char *tmcapcnv(sd,ss)           Routine to convert VT100 \33's to termcap format
55  *      beep()          Routine to emit a beep if enabled (see no-beep in .larnopts)
56  *
57  * Note: ** entries are available only in termcap mode.
58  */
59
60 #include "header.h"
61
62 #ifdef SYSV     /* system III or system V */
63 #include <termio.h>
64 #define sgttyb termio
65 #define stty(_a,_b) ioctl(_a,TCSETA,_b)
66 #define gtty(_a,_b) ioctl(_a,TCGETA,_b)
67 static int rawflg = 0;
68 static char saveeof,saveeol;
69 #define doraw(_a) if(!rawflg){++rawflg;saveeof=_a.c_cc[VMIN];saveeol=_a.c_cc[VTIME];}\
70     _a.c_cc[VMIN]=1;_a.c_cc[VTIME]=1;_a.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL)
71 #define unraw(_a) _a.c_cc[VMIN]=saveeof;_a.c_cc[VTIME]=saveeol;_a.c_lflag |= ICANON|ECHO|ECHOE|ECHOK|ECHONL
72
73 #else not SYSV
74
75 #ifndef BSD
76 #define CBREAK RAW              /* V7 has no CBREAK */
77 #endif
78
79 #define doraw(_a) (_a.sg_flags |= CBREAK,_a.sg_flags &= ~ECHO)
80 #define unraw(_a) (_a.sg_flags &= ~CBREAK,_a.sg_flags |= ECHO)
81 #include <sgtty.h>
82 #endif not SYSV
83
84 #ifndef NOVARARGS       /* if we have varargs */
85 #include <varargs.h>
86 #else NOVARARGS /* if we don't have varargs */
87 typedef char *va_list;
88 #define va_dcl int va_alist;
89 #define va_start(plist) plist = (char *) &va_alist
90 #define va_end(plist)
91 #define va_arg(plist,mode) ((mode *)(plist += sizeof(mode)))[-1]
92 #endif NOVARARGS
93
94 #define LINBUFSIZE 128          /* size of the lgetw() and lgetl() buffer               */
95 int lfd;                                        /*  output file numbers                                                 */
96 int fd;                                         /*  input file numbers                                                  */
97 static struct sgttyb ttx;       /* storage for the tty modes                                    */
98 static int ipoint=MAXIBUF,iepoint=MAXIBUF;      /*  input buffering pointers    */
99 static char lgetwbuf[LINBUFSIZE];       /* get line (word) buffer                               */
100
101 /*
102  *      setupvt100()            Subroutine to set up terminal in correct mode for game
103  *
104  *      Attributes off, clear screen, set scrolling region, set tty mode
105  */
106 setupvt100()
107         {
108         clear();  setscroll();  scbr(); /* system("stty cbreak -echo"); */
109         }
110
111 /*
112  *      clearvt100()            Subroutine to clean up terminal when the game is over
113  *
114  *      Attributes off, clear screen, unset scrolling region, restore tty mode
115  */
116 clearvt100()
117         {
118         resetscroll();  clear();  sncbr(); /* system("stty -cbreak echo"); */
119         }
120
121 /*
122  *      getchar()               Routine to read in one character from the terminal
123  */
124 getchar()
125         {
126         char byt;
127 #ifdef EXTRA
128         c[BYTESIN]++;
129 #endif
130         lflush();               /* be sure output buffer is flushed */
131         read(0,&byt,1);         /* get byte from terminal */
132         return(byt);
133         }
134
135 /*
136  *      scbr()          Function to set cbreak -echo for the terminal
137  *
138  *      like: system("stty cbreak -echo")
139  */
140 scbr()
141         {
142         gtty(0,&ttx);           doraw(ttx);             stty(0,&ttx);
143         }
144
145 /*
146  *      sncbr()         Function to set -cbreak echo for the terminal
147  *
148  *      like: system("stty -cbreak echo")
149  */
150 sncbr()
151         {
152         gtty(0,&ttx);           unraw(ttx);             stty(0,&ttx);
153         }
154
155 /*
156  *      newgame()               Subroutine to save the initial time and seed rnd()
157  */
158 newgame()
159         {
160         long *p,*pe;
161         for (p=c,pe=c+100; p<pe; *p++ =0);
162         time(&initialtime);             srandomdev();
163         lcreat((char*)0);       /* open buffering for output to terminal */
164         }
165
166 /*
167  *      lprintf(format,args . . .)              printf to the output buffer
168  *              char *format;
169  *              ??? args . . .
170  *
171  *      Enter with the format string in "format", as per printf() usage
172  *              and any needed arguments following it
173  *      Note: lprintf() only supports %s, %c and %d, with width modifier and left
174  *              or right justification.
175  *      No correct checking for output buffer overflow is done, but flushes
176  *              are done beforehand if needed.
177  *      Returns nothing of value.
178  */
179 #ifdef lint
180 /*VARARGS*/
181 lprintf(str)
182         char *str;
183         {
184         char *str2;
185         str2 = str;
186         str = str2; /* to make lint happy */
187         }
188 /*VARARGS*/
189 sprintf(str)
190         char *str;
191         {
192         char *str2;
193         str2 = str;
194         str = str2; /* to make lint happy */
195         }
196 #else lint
197 /*VARARGS*/
198 lprintf(va_alist)
199 va_dcl
200     {
201         va_list ap;     /* pointer for variable argument list */
202         char *fmt;
203         char *outb,*tmpb;
204         long wide,left,cont,n;          /* data for lprintf     */
205         char db[12];                    /* %d buffer in lprintf */
206
207         va_start(ap);   /* initialize the var args pointer */
208         fmt = va_arg(ap, char *);       /* pointer to format string */
209         if (lpnt >= lpend) lflush();
210         outb = lpnt;
211         for ( ; ; )
212                 {
213                 while (*fmt != '%')
214                         if (*fmt) *outb++ = *fmt++;  else { lpnt=outb;  return; }
215                 wide = 0;       left = 1;       cont=1;
216                 while (cont)
217                   switch(*(++fmt))
218                         {
219                         case 'd':       n = va_arg(ap, long);
220                                                 if (n<0) { n = -n;  *outb++ = '-';  if (wide) --wide; }
221                                                 tmpb = db+11;   *tmpb = (char)(n % 10 + '0');
222                                                 while (n>9)  *(--tmpb) = (char)((n /= 10) % 10 + '0');
223                                                 if (wide==0)  while (tmpb < db+12) *outb++ = *tmpb++;
224                                                 else
225                                                         {
226                                                         wide -= db-tmpb+12;
227                                                         if (left)  while (wide-- > 0) *outb++ = ' ';
228                                                         while (tmpb < db+12) *outb++ = *tmpb++;
229                                                         if (left==0)  while (wide-- > 0) *outb++ = ' ';
230                                                         }
231                                                 cont=0; break;
232
233                         case 's':       tmpb = va_arg(ap, char *);
234                                                 if (wide==0)  { while (*outb++ = *tmpb++);  --outb; }
235                                                 else
236                                                         {
237                                                         n = wide - strlen(tmpb);
238                                                         if (left)  while (n-- > 0) *outb++ = ' ';
239                                                         while (*outb++ = *tmpb++);  --outb;
240                                                         if (left==0)  while (n-- > 0) *outb++ = ' ';
241                                                         }
242                                                 cont=0; break;
243
244                         case 'c':       *outb++ = va_arg(ap, int);      cont=0;  break;
245
246                         case '0':
247                         case '1':
248                         case '2':
249                         case '3':
250                         case '4':
251                         case '5':
252                         case '6':
253                         case '7':
254                         case '8':
255                         case '9':       wide = 10*wide + *fmt - '0';    break;
256
257                         case '-':       left = 0;       break;
258
259                         default:        *outb++ = *fmt;  cont=0;        break;
260                         };
261                 fmt++;
262                 }
263         va_end(ap);
264         }
265 #endif lint
266
267 /*
268  *      lprint(long-integer)                            send binary integer to output buffer
269  *              long integer;
270  *
271  *              +---------+---------+---------+---------+
272  *              |       high  |                 |                 |       low   |
273  *              |  order  |                     |                 |  order      |
274  *              |   byte  |                     |                 |       byte  |
275  *              +---------+---------+---------+---------+
276  *         31  ---  24 23 --- 16 15 ---  8 7  ---   0
277  *
278  *      The save order is low order first, to high order (4 bytes total)
279  *              and is written to be system independent.
280  *      No checking for output buffer overflow is done, but flushes if needed!
281  *      Returns nothing of value.
282  */
283 lprint(x)
284         long x;
285         {
286         if (lpnt >= lpend) lflush();
287         *lpnt++ =  255 & x;                     *lpnt++ =  255 & (x>>8);
288         *lpnt++ =  255 & (x>>16);       *lpnt++ =  255 & (x>>24);
289         }
290
291 /*
292  *      lwrite(buf,len)                                 write a buffer to the output buffer
293  *              char *buf;
294  *              int len;
295  *
296  *      Enter with the address and number of bytes to write out
297  *      Returns nothing of value
298  */
299 lwrite(buf,len)
300     char *buf;
301     int len;
302     {
303         char *str;
304         int num2;
305         if (len > 399)  /* don't copy data if can just write it */
306                 {
307 #ifdef EXTRA
308                 c[BYTESOUT] += len;
309 #endif
310
311 #ifndef VT100
312                 for (str=buf;  len>0; --len)
313                         lprc(*str++);
314 #else VT100
315                 lflush();
316                 write(lfd,buf,len);
317 #endif VT100
318                 }
319         else while (len)
320                 {
321                 if (lpnt >= lpend) lflush();    /* if buffer is full flush it   */
322                 num2 = lpbuf+BUFBIG-lpnt;       /*      # bytes left in output buffer   */
323                 if (num2 > len) num2=len;
324                 str = lpnt;  len -= num2;
325                 while (num2--)  *str++ = *buf++;        /* copy in the bytes */
326                 lpnt = str;
327                 }
328     }
329
330 /*
331  *      long lgetc()                            Read one character from input buffer
332  *
333  *  Returns 0 if EOF, otherwise the character
334  */
335 long lgetc()
336     {
337     int i;
338     if (ipoint != iepoint)  return(inbuffer[ipoint++]);
339     if (iepoint!=MAXIBUF)   return(0);
340     if ((i=read(fd,inbuffer,MAXIBUF))<=0)
341         {
342         if (i!=0)  write(1,"error reading from input file\n",30);
343                 iepoint = ipoint = 0;           return(0);
344         }
345     ipoint=1;  iepoint=i;  return(*inbuffer);
346     }
347
348 /*
349  *      long lrint()                    Read one integer from input buffer
350  *
351  *              +---------+---------+---------+---------+
352  *              |       high  |                 |                 |       low   |
353  *              |  order  |                     |                 |  order      |
354  *              |   byte  |                     |                 |       byte  |
355  *              +---------+---------+---------+---------+
356  *         31  ---  24 23 --- 16 15 ---  8 7  ---   0
357  *
358  *      The save order is low order first, to high order (4 bytes total)
359  *      Returns the int read
360  */
361 long lrint()
362         {
363         unsigned long i;
364         i  = 255 & lgetc();                             i |= (255 & lgetc()) << 8;
365         i |= (255 & lgetc()) << 16;             i |= (255 & lgetc()) << 24;
366         return(i);
367         }
368
369 /*
370  *      lrfill(address,number)                  put input bytes into a buffer
371  *              char *address;
372  *              int number;
373  *
374  *      Reads "number" bytes into the buffer pointed to by "address".
375  *      Returns nothing of value
376  */
377 lrfill(adr,num)
378         char *adr;
379         int num;
380         {
381         char *pnt;
382         int num2;
383         while (num)
384                 {
385                 if (iepoint == ipoint)
386                         {
387                         if (num>5) /* fast way */
388                                 {
389                                 if (read(fd,adr,num) != num)
390                                         write(2,"error reading from input file\n",30);
391                                 num=0;
392                                 }
393                         else { *adr++ = lgetc();  --num; }
394                         }
395                 else
396                         {
397                         num2 = iepoint-ipoint;  /*      # of bytes left in the buffer   */
398                         if (num2 > num) num2=num;
399                         pnt = inbuffer+ipoint;  num -= num2;  ipoint += num2;
400                         while (num2--)  *adr++ = *pnt++;
401                         }
402                 }
403         }
404
405 /*
406  *      char *lgetw()                   Get a whitespace ended word from input
407  *
408  *      Returns pointer to a buffer that contains word.  If EOF, returns a NULL
409  */
410 char *lgetw()
411         {
412         char *lgp,cc;
413         int n=LINBUFSIZE,quote=0;
414         lgp = lgetwbuf;
415         do cc=lgetc();  while ((cc <= 32) && (cc > NULL));  /* eat whitespace */
416         for ( ; ; --n,cc=lgetc())
417                 {
418                 if ((cc==NULL) && (lgp==lgetwbuf))  return(NULL);       /* EOF */
419                 if ((n<=1) || ((cc<=32) && (quote==0))) { *lgp=NULL; return(lgetwbuf); }
420                 if (cc != '"') *lgp++ = cc;   else quote ^= 1;
421                 }
422         }
423
424 /*
425  *      char *lgetl()           Function to read in a line ended by newline or EOF
426  *
427  *      Returns pointer to a buffer that contains the line.  If EOF, returns NULL
428  */
429 char *lgetl()
430         {
431         int i=LINBUFSIZE,ch;
432         char *str=lgetwbuf;
433         for ( ; ; --i)
434                 {
435                 if ((*str++ = ch = lgetc()) == NULL)
436                         {
437                         if (str == lgetwbuf+1)  return(NULL); /* EOF */
438                 ot:     *str = NULL;    return(lgetwbuf);       /* line ended by EOF */
439                         }
440                 if ((ch=='\n') || (i<=1))  goto ot; /* line ended by \n */
441                 }
442         }
443
444 /*
445  *      lcreat(filename)                        Create a new file for write
446  *              char *filename;
447  *
448  *      lcreat((char*)0); means to the terminal
449  *      Returns -1 if error, otherwise the file descriptor opened.
450  */
451 lcreat(str)
452         char *str;
453         {
454         lpnt = lpbuf;   lpend = lpbuf+BUFBIG;
455         if (str==NULL) return(lfd=1);
456         if ((lfd=creat(str,0644)) < 0)
457                 {
458                 lfd=1; lprintf("error creating file <%s>\n",str); lflush(); return(-1);
459                 }
460         return(lfd);
461         }
462
463 /*
464  *      lopen(filename)                 Open a file for read
465  *              char *filename;
466  *
467  *      lopen(0) means from the terminal
468  *      Returns -1 if error, otherwise the file descriptor opened.
469  */
470 lopen(str)
471         char *str;
472         {
473         ipoint = iepoint = MAXIBUF;
474         if (str==NULL) return(fd=0);
475         if ((fd=open(str,0)) < 0)
476                 {
477                 lwclose(); lfd=1; lpnt=lpbuf; return(-1);
478                 }
479         return(fd);
480         }
481
482 /*
483  *      lappend(filename)               Open for append to an existing file
484  *              char *filename;
485  *
486  *      lappend(0) means to the terminal
487  *      Returns -1 if error, otherwise the file descriptor opened.
488  */
489 lappend(str)
490         char *str;
491         {
492         lpnt = lpbuf;   lpend = lpbuf+BUFBIG;
493         if (str==NULL) return(lfd=1);
494         if ((lfd=open(str,2)) < 0)
495                 {
496                 lfd=1; return(-1);
497                 }
498         lseek(lfd,0,2); /* seek to end of file */
499         return(lfd);
500         }
501
502 /*
503  *      lrclose()                                               close the input file
504  *
505  *      Returns nothing of value.
506  */
507 lrclose()
508         {
509         if (fd > 0) close(fd);
510         }
511
512 /*
513  *      lwclose()                                               close output file flushing if needed
514  *
515  *      Returns nothing of value.
516  */
517 lwclose()
518         {
519         lflush();       if (lfd > 2) close(lfd);
520         }
521
522 /*
523  *      lprcat(string)                                  append a string to the output buffer
524  *                                                                  avoids calls to lprintf (time consuming)
525  */
526 lprcat(str)
527     char *str;
528     {
529         char *str2;
530         if (lpnt >= lpend) lflush();
531         str2 = lpnt;
532         while (*str2++ = *str++);
533         lpnt = str2 - 1;
534     }
535
536 #ifdef VT100
537 /*
538  *      cursor(x,y)             Subroutine to set the cursor position
539  *
540  *      x and y are the cursor coordinates, and lpbuff is the output buffer where
541  *      escape sequence will be placed.
542  */
543 static char *y_num[]= { "\33[","\33[","\33[2","\33[3","\33[4","\33[5","\33[6",
544         "\33[7","\33[8","\33[9","\33[10","\33[11","\33[12","\33[13","\33[14",
545         "\33[15","\33[16","\33[17","\33[18","\33[19","\33[20","\33[21","\33[22",
546         "\33[23","\33[24" };
547
548 static char *x_num[]= { "H","H",";2H",";3H",";4H",";5H",";6H",";7H",";8H",";9H",
549         ";10H",";11H",";12H",";13H",";14H",";15H",";16H",";17H",";18H",";19H",
550         ";20H",";21H",";22H",";23H",";24H",";25H",";26H",";27H",";28H",";29H",
551         ";30H",";31H",";32H",";33H",";34H",";35H",";36H",";37H",";38H",";39H",
552         ";40H",";41H",";42H",";43H",";44H",";45H",";46H",";47H",";48H",";49H",
553         ";50H",";51H",";52H",";53H",";54H",";55H",";56H",";57H",";58H",";59H",
554         ";60H",";61H",";62H",";63H",";64H",";65H",";66H",";67H",";68H",";69H",
555         ";70H",";71H",";72H",";73H",";74H",";75H",";76H",";77H",";78H",";79H",
556         ";80H" };
557
558 cursor(x,y)
559         int x,y;
560         {
561         char *p;
562         if (lpnt >= lpend) lflush();
563
564         p = y_num[y];   /* get the string to print */
565         while (*p) *lpnt++ = *p++;      /* print the string */
566
567         p = x_num[x];   /* get the string to print */
568         while (*p) *lpnt++ = *p++;      /* print the string */
569         }
570 #else VT100
571 /*
572  * cursor(x,y)    Put cursor at specified coordinates staring at [1,1] (termcap)
573  */
574 cursor (x,y)
575         int x,y;
576         {
577         if (lpnt >= lpend) lflush ();
578
579         *lpnt++ = CURSOR;               *lpnt++ = x;            *lpnt++ = y;
580         }
581 #endif VT100
582
583 /*
584  *      Routine to position cursor at beginning of 24th line
585  */
586 cursors()
587         {
588         cursor(1,24);
589         }
590
591 #ifndef VT100
592 /*
593  * Warning: ringing the bell is control code 7. Don't use in defines.
594  * Don't change the order of these defines.
595  * Also used in helpfiles. Codes used in helpfiles should be \E[1 to \E[7 with
596  * obvious meanings.
597  */
598
599 static char cap[256];
600 char *CM, *CE, *CD, *CL, *SO, *SE, *AL, *DL;/* Termcap capabilities */
601 static char *outbuf=0;  /* translated output buffer */
602
603 int putchar ();
604
605 /*
606  * init_term()          Terminal initialization -- setup termcap info
607  */
608 init_term()
609         {
610         char termbuf[1024];
611         char *capptr = cap+10;
612         char *term;
613         struct sgttyb tt;
614
615         switch (tgetent(termbuf, term = getenv("TERM")))
616                 {
617                 case -1:
618                         write(2, "Cannot open termcap file.\n", 26); exit(1);
619                 case 0:
620                         write(2, "Cannot find entry of ", 21);
621                         write(2, term, strlen (term));
622                         write(2, " in termcap\n", 12);
623                         exit(1);
624                 };
625
626         if (gtty(0, &tt) == 0)
627                 /* ospeed = tt.sg_ospeed */ ;
628
629         CM = tgetstr("cm", &capptr);  /* Cursor motion */
630         CE = tgetstr("ce", &capptr);  /* Clear to eoln */
631         CL = tgetstr("cl", &capptr);  /* Clear screen */
632
633 /* OPTIONAL */
634         AL = tgetstr("al", &capptr);  /* Insert line */
635         DL = tgetstr("dl", &capptr);  /* Delete line */
636         SO = tgetstr("so", &capptr);  /* Begin standout mode */
637         SE = tgetstr("se", &capptr);  /* End standout mode */
638         CD = tgetstr("cd", &capptr);  /* Clear to end of display */
639
640         if (!CM)        /* can't find cursor motion entry */
641                 {
642                 write(2, "Sorry, for a ",13);           write(2, term, strlen(term));
643                 write(2, ", I can't find the cursor motion entry in termcap\n",50);
644                 exit(1);
645                 }
646         if (!CE)        /* can't find clear to end of line entry */
647                 {
648                 write(2, "Sorry, for a ",13);           write(2, term, strlen(term));
649                 write(2,", I can't find the clear to end of line entry in termcap\n",57);
650                 exit(1);
651                 }
652         if (!CL)        /* can't find clear entire screen entry */
653                 {
654                 write(2, "Sorry, for a ",13);           write(2, term, strlen(term));
655                 write(2, ", I can't find the clear entire screen entry in termcap\n",56);
656                 exit(1);
657                 }
658         if ((outbuf=malloc(BUFBIG+16))==0) /* get memory for decoded output buffer*/
659                 {
660                 write(2,"Error malloc'ing memory for decoded output buffer\n",50);
661                 died(-285);     /* malloc() failure */
662                 }
663         }
664 #endif VT100
665
666 /*
667  * cl_line(x,y)  Clear the whole line indicated by 'y' and leave cursor at [x,y]
668  */
669 cl_line(x,y)
670         int x,y;
671         {
672 #ifdef VT100
673         cursor(x,y);            lprcat("\33[2K");
674 #else VT100
675         cursor(1,y);            *lpnt++ = CL_LINE;              cursor(x,y);
676 #endif VT100
677         }
678
679 /*
680  * cl_up(x,y) Clear screen from [x,1] to current position. Leave cursor at [x,y]
681  */
682 cl_up(x,y)
683         int x,y;
684         {
685 #ifdef VT100
686         cursor(x,y);  lprcat("\33[1J\33[2K");
687 #else VT100
688         int i;
689         cursor(1,1);
690         for (i=1; i<=y; i++)   { *lpnt++ = CL_LINE;  *lpnt++ = '\n'; }
691         cursor(x,y);
692 #endif VT100
693         }
694
695 /*
696  * cl_dn(x,y)   Clear screen from [1,y] to end of display. Leave cursor at [x,y]
697  */
698 cl_dn(x,y)
699         int x,y;
700         {
701 #ifdef VT100
702         cursor(x,y); lprcat("\33[J\33[2K");
703 #else VT100
704         int i;
705         cursor(1,y);
706         if (!CD)
707                 {
708                 *lpnt++ = CL_LINE;
709                 for (i=y; i<=24; i++) { *lpnt++ = CL_LINE;  if (i!=24) *lpnt++ = '\n'; }
710                 cursor(x,y);
711                 }
712         else
713                 *lpnt++ = CL_DOWN;
714         cursor(x,y);
715 #endif VT100
716         }
717
718 /*
719  * standout(str)        Print the argument string in inverse video (standout mode).
720  */
721 standout(str)
722         char *str;
723         {
724 #ifdef VT100
725         setbold();
726         while (*str)
727                 *lpnt++ = *str++;
728         resetbold();
729 #else VT100
730         *lpnt++ = ST_START;
731         while (*str)
732                 *lpnt++ = *str++;
733         *lpnt++ = ST_END;
734 #endif VT100
735         }
736
737 /*
738  * set_score_output()   Called when output should be literally printed.
739  */
740 set_score_output()
741         {
742         enable_scroll = -1;
743         }
744
745 /*
746  *      lflush()                                                Flush the output buffer
747  *
748  *      Returns nothing of value.
749  *      for termcap version: Flush output in output buffer according to output
750  *                                                      status as indicated by `enable_scroll'
751  */
752 #ifndef VT100
753 static int scrline=18; /* line # for wraparound instead of scrolling if no DL */
754 lflush ()
755         {
756         int lpoint;
757         char *str;
758         static int curx = 0;
759         static int cury = 0;
760
761         if ((lpoint = lpnt - lpbuf) > 0)
762                 {
763 #ifdef EXTRA
764                 c[BYTESOUT] += lpoint;
765 #endif
766                 if (enable_scroll <= -1)
767                         {
768                         flush_buf();
769                 if (write(lfd,lpbuf,lpoint) != lpoint)
770                                 write(2,"error writing to output file\n",29);
771                         lpnt = lpbuf;   /* point back to beginning of buffer */
772                         return;
773                         }
774                 for (str = lpbuf; str < lpnt; str++)
775                         {
776                         if (*str>=32)   { putchar (*str); curx++; }
777                         else switch (*str)
778                                 {
779                                 case CLEAR:             tputs (CL, 0, putchar);         curx = cury = 0;
780                                                                 break;
781
782                                 case CL_LINE:   tputs (CE, 0, putchar);
783                                                                 break;
784
785                                 case CL_DOWN:   tputs (CD, 0, putchar);
786                                                                 break;
787
788                                 case ST_START:  tputs (SO, 0, putchar);
789                                                                 break;
790
791                                 case ST_END:    tputs (SE, 0, putchar);
792                                                                 break;
793
794                                 case CURSOR:    curx = *++str - 1;              cury = *++str - 1;
795                                                                 tputs (tgoto (CM, curx, cury), 0, putchar);
796                                                                 break;
797
798                                 case '\n':              if ((cury == 23) && enable_scroll)
799                                                                   {
800                                                                   if (!DL || !AL) /* wraparound or scroll? */
801                                                                         {
802                                                                         if (++scrline > 23) scrline=19;
803
804                                                                         if (++scrline > 23) scrline=19;
805                                                                         tputs (tgoto (CM, 0, scrline), 0, putchar);
806                                                                         tputs (CE, 0, putchar);
807
808                                                                         if (--scrline < 19) scrline=23;
809                                                                         tputs (tgoto (CM, 0, scrline), 0, putchar);
810                                                                         tputs (CE, 0, putchar);
811                                                                         }
812                                                                   else
813                                                                         {
814                                                                         tputs (tgoto (CM, 0, 19), 0, putchar);
815                                                                         tputs (DL, 0, putchar);
816                                                                         tputs (tgoto (CM, 0, 23), 0, putchar);
817                                                                 /*      tputs (AL, 0, putchar); */
818                                                                         }
819                                                                   }
820                                                                 else
821                                                                   {
822                                                                   putchar ('\n');               cury++;
823                                                                   }
824                                                                 curx = 0;
825                                                                 break;
826
827                                 default:                putchar (*str); curx++;
828                                 };
829                         }
830                 }
831         lpnt = lpbuf;
832         flush_buf();    /* flush real output buffer now */
833         }
834 #else VT100
835 /*
836  *      lflush()                                                flush the output buffer
837  *
838  *      Returns nothing of value.
839  */
840 lflush()
841     {
842         int lpoint;
843         if ((lpoint = lpnt - lpbuf) > 0)
844         {
845 #ifdef EXTRA
846                 c[BYTESOUT] += lpoint;
847 #endif
848         if (write(lfd,lpbuf,lpoint) != lpoint)
849                         write(2,"error writing to output file\n",29);
850         }
851         lpnt = lpbuf;   /* point back to beginning of buffer */
852     }
853 #endif VT100
854
855 #ifndef VT100
856 static int pindex=0;
857 /*
858  * putchar(ch)          Print one character in decoded output buffer.
859  */
860 int putchar(c)
861 int c;
862         {
863         outbuf[pindex++] = c;
864         if (pindex >= BUFBIG)  flush_buf();
865         }
866
867 /*
868  * flush_buf()                  Flush buffer with decoded output.
869  */
870 flush_buf()
871         {
872         if (pindex) write(lfd, outbuf, pindex);
873         pindex = 0;
874         }
875
876 /*
877  *      char *tmcapcnv(sd,ss)  Routine to convert VT100 escapes to termcap format
878  *
879  *      Processes only the \33[#m sequence (converts . files for termcap use
880  */
881 char *tmcapcnv(sd,ss)
882         char *sd,*ss;
883         {
884         int tmstate=0;  /* 0=normal, 1=\33 2=[ 3=# */
885         char tmdigit=0; /* the # in \33[#m */
886         while (*ss)
887                 {
888                 switch(tmstate)
889                         {
890                         case 0: if (*ss=='\33')  { tmstate++; break; }
891                           ign:  *sd++ = *ss;
892                           ign2: tmstate = 0;
893                                         break;
894                         case 1: if (*ss!='[') goto ign;
895                                         tmstate++;
896                                         break;
897                         case 2: if (isdigit(*ss)) { tmdigit= *ss-'0'; tmstate++; break; }
898                                         if (*ss == 'm') { *sd++ = ST_END; goto ign2; }
899                                         goto ign;
900                         case 3: if (*ss == 'm')
901                                                 {
902                                                 if (tmdigit) *sd++ = ST_START;
903                                                         else *sd++ = ST_END;
904                                                 goto ign2;
905                                                 }
906                         default: goto ign;
907                         };
908                 ss++;
909                 }
910         *sd=0; /* NULL terminator */
911         return(sd);
912         }
913 #endif VT100
914
915 /*
916  *      beep()          Routine to emit a beep if enabled (see no-beep in .larnopts)
917  */
918 beep()
919         {
920         if (!nobeep) *lpnt++ = '\7';
921         }