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