Use pread/pwrite instead of lseek followed by read/write.
[dragonfly.git] / games / larn / io.c
blob5678c84017cfa39a6c57e4c6f709758a13185298
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.7 2008/06/05 18:06:30 swildner Exp $
5 * Below are the functions in this file:
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 * getchr() 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()
14 * FILE OUTPUT ROUTINES
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
21 * FILE OUTPUT MACROS (in header.h)
23 * lprc(character) put the character into the output buffer
25 * FILE INPUT ROUTINES
27 * long lgetc() read one character from input buffer
28 * long lrint_x() 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
33 * FILE OPEN / CLOSE ROUTINES
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
42 * Other Routines
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 ** putchr(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)
57 * Note: ** entries are available only in termcap mode.
60 #include "header.h"
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
73 #else /* not SYSV */
75 #ifndef BSD
76 #define CBREAK RAW /* V7 has no CBREAK */
77 #endif
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 #define stty(_a,_b) ioctl(_a,TIOCSETP,_b)
83 #define gtty(_a,_b) ioctl(_a,TIOCGETP,_b)
84 #endif /* not SYSV */
86 #ifndef NOVARARGS /* if we have varargs */
87 #include <stdarg.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 */
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 */
103 #ifndef VT100
104 static int putchr(int);
105 static void flush_buf(void);
106 #endif
109 * setupvt100() Subroutine to set up terminal in correct mode for game
111 * Attributes off, clear screen, set scrolling region, set tty mode
113 void
114 setupvt100(void)
116 clear(); setscroll(); scbr();
120 * clearvt100() Subroutine to clean up terminal when the game is over
122 * Attributes off, clear screen, unset scrolling region, restore tty mode
124 void
125 clearvt100(void)
127 resetscroll(); clear(); sncbr();
130 * getchr() Routine to read in one character from the terminal
132 char
133 getchr(void)
135 char byt;
136 #ifdef EXTRA
137 c[BYTESIN]++;
138 #endif
139 lflush(); /* be sure output buffer is flushed */
140 read(0,&byt,1); /* get byte from terminal */
141 return(byt);
144 * scbr() Function to set cbreak -echo for the terminal
146 * like: system("stty cbreak -echo")
148 void
149 scbr(void)
151 gtty(0,&ttx); doraw(ttx); stty(0,&ttx);
155 * sncbr() Function to set -cbreak echo for the terminal
157 * like: system("stty -cbreak echo")
159 void
160 sncbr(void)
162 gtty(0,&ttx); unraw(ttx); stty(0,&ttx);
166 * newgame() Subroutine to save the initial time and seed rnd()
168 void
169 newgame(void)
171 long *p,*pe;
172 for (p=c,pe=c+100; p<pe; *p++ =0);
173 time(&initialtime); srandomdev();
174 lcreat((char*)0); /* open buffering for output to terminal */
178 * lprintf(format,args . . .) printf to the output buffer
179 * char *format;
180 * ??? args . . .
182 * Enter with the format string in "format", as per printf() usage
183 * and any needed arguments following it
184 * Note: lprintf() only supports %s, %c and %d, with width modifier and left
185 * or right justification.
186 * No correct checking for output buffer overflow is done, but flushes
187 * are done beforehand if needed.
188 * Returns nothing of value.
190 /*VARARGS*/
191 void
192 lprintf(const char *fmt, ...)
194 va_list ap; /* pointer for variable argument list */
195 char *outb,*tmpb;
196 long wide,left,cont,n; /* data for lprintf */
197 char db[12]; /* %d buffer in lprintf */
199 va_start(ap, fmt); /* initialize the var args pointer */
200 if (lpnt >= lpend) lflush();
201 outb = lpnt;
202 for ( ; ; )
204 while (*fmt != '%')
205 if (*fmt) *outb++ = *fmt++; else { lpnt=outb; return; }
206 wide = 0; left = 1; cont=1;
207 while (cont)
208 switch(*(++fmt))
210 case 'd': n = va_arg(ap, long);
211 if (n<0) { n = -n; *outb++ = '-'; if (wide) --wide; }
212 tmpb = db+11; *tmpb = (char)(n % 10 + '0');
213 while (n>9) *(--tmpb) = (char)((n /= 10) % 10 + '0');
214 if (wide==0) while (tmpb < db+12) *outb++ = *tmpb++;
215 else
217 wide -= db-tmpb+12;
218 if (left) while (wide-- > 0) *outb++ = ' ';
219 while (tmpb < db+12) *outb++ = *tmpb++;
220 if (left==0) while (wide-- > 0) *outb++ = ' ';
222 cont=0; break;
224 case 's': tmpb = va_arg(ap, char *);
225 if (wide==0) { while ((*outb++ = *tmpb++)); --outb; }
226 else
228 n = wide - strlen(tmpb);
229 if (left) while (n-- > 0) *outb++ = ' ';
230 while ((*outb++ = *tmpb++)); --outb;
231 if (left==0) while (n-- > 0) *outb++ = ' ';
233 cont=0; break;
235 case 'c': *outb++ = va_arg(ap, int); cont=0; break;
237 case '0':
238 case '1':
239 case '2':
240 case '3':
241 case '4':
242 case '5':
243 case '6':
244 case '7':
245 case '8':
246 case '9': wide = 10*wide + *fmt - '0'; break;
248 case '-': left = 0; break;
250 default: *outb++ = *fmt; cont=0; break;
252 fmt++;
254 va_end(ap);
258 * lprint(long-integer) send binary integer to output buffer
259 * long integer;
261 * +---------+---------+---------+---------+
262 * | high | | | low |
263 * | order | | | order |
264 * | byte | | | byte |
265 * +---------+---------+---------+---------+
266 * 31 --- 24 23 --- 16 15 --- 8 7 --- 0
268 * The save order is low order first, to high order (4 bytes total)
269 * and is written to be system independent.
270 * No checking for output buffer overflow is done, but flushes if needed!
271 * Returns nothing of value.
273 void
274 lprint(long x)
276 if (lpnt >= lpend) lflush();
277 *lpnt++ = 255 & x; *lpnt++ = 255 & (x>>8);
278 *lpnt++ = 255 & (x>>16); *lpnt++ = 255 & (x>>24);
282 * lwrite(buf,len) write a buffer to the output buffer
283 * char *buf;
284 * int len;
286 * Enter with the address and number of bytes to write out
287 * Returns nothing of value
289 void
290 lwrite(char *buf, int len)
292 char *str;
293 int num2;
294 if (len > 399) /* don't copy data if can just write it */
296 #ifdef EXTRA
297 c[BYTESOUT] += len;
298 #endif
300 #ifndef VT100
301 for (str=buf; len>0; --len)
302 lprc(*str++);
303 #else /* VT100 */
304 lflush();
305 write(lfd,buf,len);
306 #endif /* VT100 */
308 else while (len)
310 if (lpnt >= lpend) lflush(); /* if buffer is full flush it */
311 num2 = lpbuf+BUFBIG-lpnt; /* # bytes left in output buffer */
312 if (num2 > len) num2=len;
313 str = lpnt; len -= num2;
314 while (num2--) *str++ = *buf++; /* copy in the bytes */
315 lpnt = str;
320 * long lgetc() Read one character from input buffer
322 * Returns 0 if EOF, otherwise the character
324 long
325 lgetc(void)
327 int i;
328 if (ipoint != iepoint) return(inbuffer[ipoint++]);
329 if (iepoint!=MAXIBUF) return(0);
330 if ((i=read(fd,inbuffer,MAXIBUF))<=0)
332 if (i!=0) write(1,"error reading from input file\n",30);
333 iepoint = ipoint = 0; return(0);
335 ipoint=1; iepoint=i; return(*inbuffer);
339 * long lrint_x() Read one integer from input buffer
341 * +---------+---------+---------+---------+
342 * | high | | | low |
343 * | order | | | order |
344 * | byte | | | byte |
345 * +---------+---------+---------+---------+
346 * 31 --- 24 23 --- 16 15 --- 8 7 --- 0
348 * The save order is low order first, to high order (4 bytes total)
349 * Returns the int read
351 long
352 lrint_x(void)
354 unsigned long i;
355 i = 255 & lgetc(); i |= (255 & lgetc()) << 8;
356 i |= (255 & lgetc()) << 16; i |= (255 & lgetc()) << 24;
357 return(i);
361 * lrfill(address,number) put input bytes into a buffer
362 * char *address;
363 * int number;
365 * Reads "number" bytes into the buffer pointed to by "address".
366 * Returns nothing of value
368 void
369 lrfill(char *adr, int num)
371 char *pnt;
372 int num2;
373 while (num)
375 if (iepoint == ipoint)
377 if (num>5) /* fast way */
379 if (read(fd,adr,num) != num)
380 write(2,"error reading from input file\n",30);
381 num=0;
383 else { *adr++ = lgetc(); --num; }
385 else
387 num2 = iepoint-ipoint; /* # of bytes left in the buffer */
388 if (num2 > num) num2=num;
389 pnt = inbuffer+ipoint; num -= num2; ipoint += num2;
390 while (num2--) *adr++ = *pnt++;
396 * char *lgetw() Get a whitespace ended word from input
398 * Returns pointer to a buffer that contains word. If EOF, returns a NULL
400 char *
401 lgetw(void)
403 char *lgp,cc;
404 int n=LINBUFSIZE,quote=0;
405 lgp = lgetwbuf;
406 do cc=lgetc(); while ((cc <= 32) && (cc > 0)); /* eat whitespace */
407 for ( ; ; --n,cc=lgetc())
409 if ((cc==0) && (lgp==lgetwbuf)) return(NULL); /* EOF */
410 if ((n<=1) || ((cc<=32) && (quote==0))) { *lgp=0; return(lgetwbuf); }
411 if (cc != '"') *lgp++ = cc; else quote ^= 1;
416 * char *lgetl() Function to read in a line ended by newline or EOF
418 * Returns pointer to a buffer that contains the line. If EOF, returns NULL
420 char *
421 lgetl(void)
423 int i=LINBUFSIZE,ch;
424 char *str=lgetwbuf;
425 for ( ; ; --i)
427 if ((*str++ = ch = lgetc()) == 0)
429 if (str == lgetwbuf+1) return(NULL); /* EOF */
430 ot: *str = 0; return(lgetwbuf); /* line ended by EOF */
432 if ((ch=='\n') || (i<=1)) goto ot; /* line ended by \n */
437 * lcreat(filename) Create a new file for write
438 * char *filename;
440 * lcreat((char*)0); means to the terminal
441 * Returns -1 if error, otherwise the file descriptor opened.
444 lcreat(char *str)
446 lpnt = lpbuf; lpend = lpbuf+BUFBIG;
447 if (str==NULL) return(lfd=1);
448 if ((lfd=creat(str,0644)) < 0)
450 lfd=1; lprintf("error creating file <%s>\n",str); lflush(); return(-1);
452 return(lfd);
456 * lopen(filename) Open a file for read
457 * char *filename;
459 * lopen(0) means from the terminal
460 * Returns -1 if error, otherwise the file descriptor opened.
463 lopen(char *str)
465 ipoint = iepoint = MAXIBUF;
466 if (str==NULL) return(fd=0);
467 if ((fd=open(str,0)) < 0)
469 lwclose(); lfd=1; lpnt=lpbuf; return(-1);
471 return(fd);
475 * lappend(filename) Open for append to an existing file
476 * char *filename;
478 * lappend(0) means to the terminal
479 * Returns -1 if error, otherwise the file descriptor opened.
482 lappend(char *str)
484 lpnt = lpbuf; lpend = lpbuf+BUFBIG;
485 if (str==NULL) return(lfd=1);
486 if ((lfd=open(str,2)) < 0)
488 lfd=1; return(-1);
490 lseek(lfd,0,2); /* seek to end of file */
491 return(lfd);
495 * lrclose() close the input file
497 * Returns nothing of value.
499 void
500 lrclose(void)
502 if (fd > 0) close(fd);
506 * lwclose() close output file flushing if needed
508 * Returns nothing of value.
510 void
511 lwclose(void)
513 lflush(); if (lfd > 2) close(lfd);
517 * lprcat(string) append a string to the output buffer
518 * avoids calls to lprintf (time consuming)
520 void
521 lprcat(const char *str)
523 char *str2;
524 if (lpnt >= lpend) lflush();
525 str2 = lpnt;
526 while ((*str2++ = *str++));
527 lpnt = str2 - 1;
530 #ifdef VT100
532 * cursor(x,y) Subroutine to set the cursor position
534 * x and y are the cursor coordinates, and lpbuff is the output buffer where
535 * escape sequence will be placed.
537 static const char *y_num[]= { "\33[","\33[","\33[2","\33[3","\33[4","\33[5","\33[6",
538 "\33[7","\33[8","\33[9","\33[10","\33[11","\33[12","\33[13","\33[14",
539 "\33[15","\33[16","\33[17","\33[18","\33[19","\33[20","\33[21","\33[22",
540 "\33[23","\33[24" };
542 static const char *x_num[]= { "H","H",";2H",";3H",";4H",";5H",";6H",";7H",";8H",";9H",
543 ";10H",";11H",";12H",";13H",";14H",";15H",";16H",";17H",";18H",";19H",
544 ";20H",";21H",";22H",";23H",";24H",";25H",";26H",";27H",";28H",";29H",
545 ";30H",";31H",";32H",";33H",";34H",";35H",";36H",";37H",";38H",";39H",
546 ";40H",";41H",";42H",";43H",";44H",";45H",";46H",";47H",";48H",";49H",
547 ";50H",";51H",";52H",";53H",";54H",";55H",";56H",";57H",";58H",";59H",
548 ";60H",";61H",";62H",";63H",";64H",";65H",";66H",";67H",";68H",";69H",
549 ";70H",";71H",";72H",";73H",";74H",";75H",";76H",";77H",";78H",";79H",
550 ";80H" };
552 void
553 cursor(int x, int y)
555 char *p;
556 if (lpnt >= lpend) lflush();
558 p = y_num[y]; /* get the string to print */
559 while (*p) *lpnt++ = *p++; /* print the string */
561 p = x_num[x]; /* get the string to print */
562 while (*p) *lpnt++ = *p++; /* print the string */
564 #else /* VT100 */
566 * cursor(x,y) Put cursor at specified coordinates staring at [1,1] (termcap)
568 void
569 cursor(int x, int y)
571 if (lpnt >= lpend) lflush ();
573 *lpnt++ = CURSOR; *lpnt++ = x; *lpnt++ = y;
575 #endif /* VT100 */
578 * Routine to position cursor at beginning of 24th line
580 void
581 cursors(void)
583 cursor(1,24);
586 #ifndef VT100
588 * Warning: ringing the bell is control code 7. Don't use in defines.
589 * Don't change the order of these defines.
590 * Also used in helpfiles. Codes used in helpfiles should be \E[1 to \E[7 with
591 * obvious meanings.
594 static char cap[256];
595 char *CM, *CE, *CD, *CL, *SO, *SE, *AL, *DL;/* Termcap capabilities */
596 static char *outbuf=0; /* translated output buffer */
599 * init_term() Terminal initialization -- setup termcap info
601 void
602 init_term(void)
604 char termbuf[1024];
605 char *capptr = cap+10;
606 char *term;
608 switch (tgetent(termbuf, term = getenv("TERM")))
610 case -1:
611 write(2, "Cannot open termcap file.\n", 26); exit(1);
612 case 0:
613 write(2, "Cannot find entry of ", 21);
614 write(2, term, strlen (term));
615 write(2, " in termcap\n", 12);
616 exit(1);
619 CM = tgetstr("cm", &capptr); /* Cursor motion */
620 CE = tgetstr("ce", &capptr); /* Clear to eoln */
621 CL = tgetstr("cl", &capptr); /* Clear screen */
623 /* OPTIONAL */
624 AL = tgetstr("al", &capptr); /* Insert line */
625 DL = tgetstr("dl", &capptr); /* Delete line */
626 SO = tgetstr("so", &capptr); /* Begin standout mode */
627 SE = tgetstr("se", &capptr); /* End standout mode */
628 CD = tgetstr("cd", &capptr); /* Clear to end of display */
630 if (!CM) /* can't find cursor motion entry */
632 write(2, "Sorry, for a ",13); write(2, term, strlen(term));
633 write(2, ", I can't find the cursor motion entry in termcap\n",50);
634 exit(1);
636 if (!CE) /* can't find clear to end of line entry */
638 write(2, "Sorry, for a ",13); write(2, term, strlen(term));
639 write(2,", I can't find the clear to end of line entry in termcap\n",57);
640 exit(1);
642 if (!CL) /* can't find clear entire screen entry */
644 write(2, "Sorry, for a ",13); write(2, term, strlen(term));
645 write(2, ", I can't find the clear entire screen entry in termcap\n",56);
646 exit(1);
648 if ((outbuf=malloc(BUFBIG+16))==0) /* get memory for decoded output buffer*/
650 write(2,"Error malloc'ing memory for decoded output buffer\n",50);
651 died(-285); /* malloc() failure */
654 #endif /* VT100 */
657 * cl_line(x,y) Clear the whole line indicated by 'y' and leave cursor at [x,y]
659 void
660 cl_line(int x, int y)
662 #ifdef VT100
663 cursor(x,y); lprcat("\33[2K");
664 #else /* VT100 */
665 cursor(1,y); *lpnt++ = CL_LINE; cursor(x,y);
666 #endif /* VT100 */
670 * cl_up(x,y) Clear screen from [x,1] to current position. Leave cursor at [x,y]
672 void
673 cl_up(int x, int y)
675 #ifdef VT100
676 cursor(x,y); lprcat("\33[1J\33[2K");
677 #else /* VT100 */
678 int i;
679 cursor(1,1);
680 for (i=1; i<=y; i++) { *lpnt++ = CL_LINE; *lpnt++ = '\n'; }
681 cursor(x,y);
682 #endif /* VT100 */
686 * cl_dn(x,y) Clear screen from [1,y] to end of display. Leave cursor at [x,y]
688 void
689 cl_dn(int x, int y)
691 #ifdef VT100
692 cursor(x,y); lprcat("\33[J\33[2K");
693 #else /* VT100 */
694 int i;
695 cursor(1,y);
696 if (!CD)
698 *lpnt++ = CL_LINE;
699 for (i=y; i<=24; i++) { *lpnt++ = CL_LINE; if (i!=24) *lpnt++ = '\n'; }
700 cursor(x,y);
702 else
703 *lpnt++ = CL_DOWN;
704 cursor(x,y);
705 #endif /* VT100 */
709 * standout(str) Print the argument string in inverse video (standout mode).
711 void
712 standout(const char *str)
714 #ifdef VT100
715 setbold();
716 while (*str)
717 *lpnt++ = *str++;
718 resetbold();
719 #else /* VT100 */
720 *lpnt++ = ST_START;
721 while (*str)
722 *lpnt++ = *str++;
723 *lpnt++ = ST_END;
724 #endif /* VT100 */
728 * set_score_output() Called when output should be literally printed.
730 void
731 set_score_output(void)
733 enable_scroll = -1;
737 * lflush() Flush the output buffer
739 * Returns nothing of value.
740 * for termcap version: Flush output in output buffer according to output
741 * status as indicated by `enable_scroll'
743 #ifndef VT100
744 static int scrline=18; /* line # for wraparound instead of scrolling if no DL */
746 void
747 lflush(void)
749 int lpoint;
750 char *str;
751 static int curx = 0;
752 static int cury = 0;
754 if ((lpoint = lpnt - lpbuf) > 0)
756 #ifdef EXTRA
757 c[BYTESOUT] += lpoint;
758 #endif
759 if (enable_scroll <= -1)
761 flush_buf();
762 if (write(lfd,lpbuf,lpoint) != lpoint)
763 write(2,"error writing to output file\n",29);
764 lpnt = lpbuf; /* point back to beginning of buffer */
765 return;
767 for (str = lpbuf; str < lpnt; str++)
769 if (*str>=32) { putchr (*str); curx++; }
770 else switch (*str)
772 case CLEAR: tputs (CL, 0, putchr); curx = cury = 0;
773 break;
775 case CL_LINE: tputs (CE, 0, putchr);
776 break;
778 case CL_DOWN: tputs (CD, 0, putchr);
779 break;
781 case ST_START: tputs (SO, 0, putchr);
782 break;
784 case ST_END: tputs (SE, 0, putchr);
785 break;
787 case CURSOR: curx = *++str - 1; cury = *++str - 1;
788 tputs (tgoto (CM, curx, cury), 0, putchr);
789 break;
791 case '\n': if ((cury == 23) && enable_scroll)
793 if (!DL || !AL) /* wraparound or scroll? */
795 if (++scrline > 23) scrline=19;
797 if (++scrline > 23) scrline=19;
798 tputs (tgoto (CM, 0, scrline), 0, putchr);
799 tputs (CE, 0, putchr);
801 if (--scrline < 19) scrline=23;
802 tputs (tgoto (CM, 0, scrline), 0, putchr);
803 tputs (CE, 0, putchr);
805 else
807 tputs (tgoto (CM, 0, 19), 0, putchr);
808 tputs (DL, 0, putchr);
809 tputs (tgoto (CM, 0, 23), 0, putchr);
812 else
814 putchr('\n'); cury++;
816 curx = 0;
817 break;
819 default: putchr(*str); curx++;
823 lpnt = lpbuf;
824 flush_buf(); /* flush real output buffer now */
826 #else /* VT100 */
828 * lflush() flush the output buffer
830 * Returns nothing of value.
832 void
833 lflush(void)
835 int lpoint;
836 if ((lpoint = lpnt - lpbuf) > 0)
838 #ifdef EXTRA
839 c[BYTESOUT] += lpoint;
840 #endif
841 if (write(lfd,lpbuf,lpoint) != lpoint)
842 write(2,"error writing to output file\n",29);
844 lpnt = lpbuf; /* point back to beginning of buffer */
846 #endif /* VT100 */
848 #ifndef VT100
849 static int pindex=0;
851 * putchr(ch) Print one character in decoded output buffer.
853 static int
854 putchr(int ch)
856 outbuf[pindex++] = ch;
857 if (pindex >= BUFBIG) flush_buf();
858 return(0);
862 * flush_buf() Flush buffer with decoded output.
864 static void
865 flush_buf(void)
867 if (pindex) write(lfd, outbuf, pindex);
868 pindex = 0;
872 * char *tmcapcnv(sd,ss) Routine to convert VT100 escapes to termcap format
874 * Processes only the \33[#m sequence (converts . files for termcap use
876 char *
877 tmcapcnv(char *sd, char *ss)
879 int tmstate=0; /* 0=normal, 1=\33 2=[ 3=# */
880 char tmdigit=0; /* the # in \33[#m */
881 while (*ss)
883 switch(tmstate)
885 case 0: if (*ss=='\33') { tmstate++; break; }
886 ign: *sd++ = *ss;
887 ign2: tmstate = 0;
888 break;
889 case 1: if (*ss!='[') goto ign;
890 tmstate++;
891 break;
892 case 2: if (isdigit((int)*ss)) { tmdigit= *ss-'0'; tmstate++; break; }
893 if (*ss == 'm') { *sd++ = ST_END; goto ign2; }
894 goto ign;
895 case 3: if (*ss == 'm')
897 if (tmdigit) *sd++ = ST_START;
898 else *sd++ = ST_END;
899 goto ign2;
901 default: goto ign;
903 ss++;
905 *sd=0; /* NULL terminator */
906 return(sd);
908 #endif /* VT100 */
911 * beep() Routine to emit a beep if enabled (see no-beep in .larnopts)
913 void
914 beep(void)
916 if (!nobeep) *lpnt++ = '\7';