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