summaryrefslogtreecommitdiffstats
path: root/larn/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'larn/io.c')
-rw-r--r--larn/io.c915
1 files changed, 915 insertions, 0 deletions
diff --git a/larn/io.c b/larn/io.c
new file mode 100644
index 00000000..dc0d5e7c
--- /dev/null
+++ b/larn/io.c
@@ -0,0 +1,915 @@
+/* io.c Larn is copyrighted 1986 by Noah Morgan.
+ *
+ * Below are the functions in this file:
+ *
+ * setupvt100() Subroutine to set up terminal in correct mode for game
+ * clearvt100() Subroutine to clean up terminal when the game is over
+ * getchar() Routine to read in one character from the terminal
+ * scbr() Function to set cbreak -echo for the terminal
+ * sncbr() Function to set -cbreak echo for the terminal
+ * newgame() Subroutine to save the initial time and seed rnd()
+ *
+ * FILE OUTPUT ROUTINES
+ *
+ * lprintf(format,args . . .) printf to the output buffer
+ * lprint(integer) send binary integer to output buffer
+ * lwrite(buf,len) write a buffer to the output buffer
+ * lprcat(str) sent string to output buffer
+ *
+ * FILE OUTPUT MACROS (in header.h)
+ *
+ * lprc(character) put the character into the output buffer
+ *
+ * FILE INPUT ROUTINES
+ *
+ * long lgetc() read one character from input buffer
+ * long lrint() read one integer from input buffer
+ * lrfill(address,number) put input bytes into a buffer
+ * char *lgetw() get a whitespace ended word from input
+ * char *lgetl() get a \n or EOF ended line from input
+ *
+ * FILE OPEN / CLOSE ROUTINES
+ *
+ * lcreat(filename) create a new file for write
+ * lopen(filename) open a file for read
+ * lappend(filename) open for append to an existing file
+ * lrclose() close the input file
+ * lwclose() close output file
+ * lflush() flush the output buffer
+ *
+ * Other Routines
+ *
+ * cursor(x,y) position cursor at [x,y]
+ * cursors() position cursor at [1,24] (saves memory)
+ * cl_line(x,y) Clear line at [1,y] and leave cursor at [x,y]
+ * cl_up(x,y) Clear screen from [x,1] to current line.
+ * cl_dn(x,y) Clear screen from [1,y] to end of display.
+ * standout(str) Print the string in standout mode.
+ * set_score_output() Called when output should be literally printed.
+ ** putchar(ch) Print one character in decoded output buffer.
+ ** flush_buf() Flush buffer with decoded output.
+ ** init_term() Terminal initialization -- setup termcap info
+ ** char *tmcapcnv(sd,ss) Routine to convert VT100 \33's to termcap format
+ * beep() Routine to emit a beep if enabled (see no-beep in .larnopts)
+ *
+ * Note: ** entries are available only in termcap mode.
+ */
+
+#include "header.h"
+
+#ifdef SYSV /* system III or system V */
+#include <termio.h>
+#define sgttyb termio
+#define stty(_a,_b) ioctl(_a,TCSETA,_b)
+#define gtty(_a,_b) ioctl(_a,TCGETA,_b)
+static int rawflg = 0;
+static char saveeof,saveeol;
+#define doraw(_a) if(!rawflg){++rawflg;saveeof=_a.c_cc[VMIN];saveeol=_a.c_cc[VTIME];}\
+ _a.c_cc[VMIN]=1;_a.c_cc[VTIME]=1;_a.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL)
+#define unraw(_a) _a.c_cc[VMIN]=saveeof;_a.c_cc[VTIME]=saveeol;_a.c_lflag |= ICANON|ECHO|ECHOE|ECHOK|ECHONL
+
+#else not SYSV
+
+#ifndef BSD
+#define CBREAK RAW /* V7 has no CBREAK */
+#endif
+
+#define doraw(_a) (_a.sg_flags |= CBREAK,_a.sg_flags &= ~ECHO)
+#define unraw(_a) (_a.sg_flags &= ~CBREAK,_a.sg_flags |= ECHO)
+#include <sgtty.h>
+#endif not SYSV
+
+#ifndef NOVARARGS /* if we have varargs */
+#include <varargs.h>
+#else NOVARARGS /* if we don't have varargs */
+typedef char *va_list;
+#define va_dcl int va_alist;
+#define va_start(plist) plist = (char *) &va_alist
+#define va_end(plist)
+#define va_arg(plist,mode) ((mode *)(plist += sizeof(mode)))[-1]
+#endif NOVARARGS
+
+#define LINBUFSIZE 128 /* size of the lgetw() and lgetl() buffer */
+int lfd; /* output file numbers */
+int fd; /* input file numbers */
+static struct sgttyb ttx; /* storage for the tty modes */
+static int ipoint=MAXIBUF,iepoint=MAXIBUF; /* input buffering pointers */
+static char lgetwbuf[LINBUFSIZE]; /* get line (word) buffer */
+
+/*
+ * setupvt100() Subroutine to set up terminal in correct mode for game
+ *
+ * Attributes off, clear screen, set scrolling region, set tty mode
+ */
+setupvt100()
+ {
+ clear(); setscroll(); scbr(); /* system("stty cbreak -echo"); */
+ }
+
+/*
+ * clearvt100() Subroutine to clean up terminal when the game is over
+ *
+ * Attributes off, clear screen, unset scrolling region, restore tty mode
+ */
+clearvt100()
+ {
+ resetscroll(); clear(); sncbr(); /* system("stty -cbreak echo"); */
+ }
+
+/*
+ * getchar() Routine to read in one character from the terminal
+ */
+getchar()
+ {
+ char byt;
+#ifdef EXTRA
+ c[BYTESIN]++;
+#endif
+ lflush(); /* be sure output buffer is flushed */
+ read(0,&byt,1); /* get byte from terminal */
+ return(byt);
+ }
+
+/*
+ * scbr() Function to set cbreak -echo for the terminal
+ *
+ * like: system("stty cbreak -echo")
+ */
+scbr()
+ {
+ gtty(0,&ttx); doraw(ttx); stty(0,&ttx);
+ }
+
+/*
+ * sncbr() Function to set -cbreak echo for the terminal
+ *
+ * like: system("stty -cbreak echo")
+ */
+sncbr()
+ {
+ gtty(0,&ttx); unraw(ttx); stty(0,&ttx);
+ }
+
+/*
+ * newgame() Subroutine to save the initial time and seed rnd()
+ */
+newgame()
+ {
+ register long *p,*pe;
+ for (p=c,pe=c+100; p<pe; *p++ =0);
+ time(&initialtime); srand(initialtime);
+ lcreat((char*)0); /* open buffering for output to terminal */
+ }
+
+/*
+ * lprintf(format,args . . .) printf to the output buffer
+ * char *format;
+ * ??? args . . .
+ *
+ * Enter with the format string in "format", as per printf() usage
+ * and any needed arguments following it
+ * Note: lprintf() only supports %s, %c and %d, with width modifier and left
+ * or right justification.
+ * No correct checking for output buffer overflow is done, but flushes
+ * are done beforehand if needed.
+ * Returns nothing of value.
+ */
+#ifdef lint
+/*VARARGS*/
+lprintf(str)
+ char *str;
+ {
+ char *str2;
+ str2 = str;
+ str = str2; /* to make lint happy */
+ }
+/*VARARGS*/
+sprintf(str)
+ char *str;
+ {
+ char *str2;
+ str2 = str;
+ str = str2; /* to make lint happy */
+ }
+#else lint
+/*VARARGS*/
+lprintf(va_alist)
+va_dcl
+ {
+ va_list ap; /* pointer for variable argument list */
+ register char *fmt;
+ register char *outb,*tmpb;
+ register long wide,left,cont,n; /* data for lprintf */
+ char db[12]; /* %d buffer in lprintf */
+
+ va_start(ap); /* initialize the var args pointer */
+ fmt = va_arg(ap, char *); /* pointer to format string */
+ if (lpnt >= lpend) lflush();
+ outb = lpnt;
+ for ( ; ; )
+ {
+ while (*fmt != '%')
+ if (*fmt) *outb++ = *fmt++; else { lpnt=outb; return; }
+ wide = 0; left = 1; cont=1;
+ while (cont)
+ switch(*(++fmt))
+ {
+ case 'd': n = va_arg(ap, long);
+ if (n<0) { n = -n; *outb++ = '-'; if (wide) --wide; }
+ tmpb = db+11; *tmpb = (char)(n % 10 + '0');
+ while (n>9) *(--tmpb) = (char)((n /= 10) % 10 + '0');
+ if (wide==0) while (tmpb < db+12) *outb++ = *tmpb++;
+ else
+ {
+ wide -= db-tmpb+12;
+ if (left) while (wide-- > 0) *outb++ = ' ';
+ while (tmpb < db+12) *outb++ = *tmpb++;
+ if (left==0) while (wide-- > 0) *outb++ = ' ';
+ }
+ cont=0; break;
+
+ case 's': tmpb = va_arg(ap, char *);
+ if (wide==0) { while (*outb++ = *tmpb++); --outb; }
+ else
+ {
+ n = wide - strlen(tmpb);
+ if (left) while (n-- > 0) *outb++ = ' ';
+ while (*outb++ = *tmpb++); --outb;
+ if (left==0) while (n-- > 0) *outb++ = ' ';
+ }
+ cont=0; break;
+
+ case 'c': *outb++ = va_arg(ap, int); cont=0; break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': wide = 10*wide + *fmt - '0'; break;
+
+ case '-': left = 0; break;
+
+ default: *outb++ = *fmt; cont=0; break;
+ };
+ fmt++;
+ }
+ va_end(ap);
+ }
+#endif lint
+
+/*
+ * lprint(long-integer) send binary integer to output buffer
+ * long integer;
+ *
+ * +---------+---------+---------+---------+
+ * | high | | | low |
+ * | order | | | order |
+ * | byte | | | byte |
+ * +---------+---------+---------+---------+
+ * 31 --- 24 23 --- 16 15 --- 8 7 --- 0
+ *
+ * The save order is low order first, to high order (4 bytes total)
+ * and is written to be system independent.
+ * No checking for output buffer overflow is done, but flushes if needed!
+ * Returns nothing of value.
+ */
+lprint(x)
+ register long x;
+ {
+ if (lpnt >= lpend) lflush();
+ *lpnt++ = 255 & x; *lpnt++ = 255 & (x>>8);
+ *lpnt++ = 255 & (x>>16); *lpnt++ = 255 & (x>>24);
+ }
+
+/*
+ * lwrite(buf,len) write a buffer to the output buffer
+ * char *buf;
+ * int len;
+ *
+ * Enter with the address and number of bytes to write out
+ * Returns nothing of value
+ */
+lwrite(buf,len)
+ register char *buf;
+ int len;
+ {
+ register char *str;
+ register int num2;
+ if (len > 399) /* don't copy data if can just write it */
+ {
+#ifdef EXTRA
+ c[BYTESOUT] += len;
+#endif
+
+#ifndef VT100
+ for (str=buf; len>0; --len)
+ lprc(*str++);
+#else VT100
+ lflush();
+ write(lfd,buf,len);
+#endif VT100
+ }
+ else while (len)
+ {
+ if (lpnt >= lpend) lflush(); /* if buffer is full flush it */
+ num2 = lpbuf+BUFBIG-lpnt; /* # bytes left in output buffer */
+ if (num2 > len) num2=len;
+ str = lpnt; len -= num2;
+ while (num2--) *str++ = *buf++; /* copy in the bytes */
+ lpnt = str;
+ }
+ }
+
+/*
+ * long lgetc() Read one character from input buffer
+ *
+ * Returns 0 if EOF, otherwise the character
+ */
+long lgetc()
+ {
+ register int i;
+ if (ipoint != iepoint) return(inbuffer[ipoint++]);
+ if (iepoint!=MAXIBUF) return(0);
+ if ((i=read(fd,inbuffer,MAXIBUF))<=0)
+ {
+ if (i!=0) write(1,"error reading from input file\n",30);
+ iepoint = ipoint = 0; return(0);
+ }
+ ipoint=1; iepoint=i; return(*inbuffer);
+ }
+
+/*
+ * long lrint() Read one integer from input buffer
+ *
+ * +---------+---------+---------+---------+
+ * | high | | | low |
+ * | order | | | order |
+ * | byte | | | byte |
+ * +---------+---------+---------+---------+
+ * 31 --- 24 23 --- 16 15 --- 8 7 --- 0
+ *
+ * The save order is low order first, to high order (4 bytes total)
+ * Returns the int read
+ */
+long lrint()
+ {
+ register unsigned long i;
+ i = 255 & lgetc(); i |= (255 & lgetc()) << 8;
+ i |= (255 & lgetc()) << 16; i |= (255 & lgetc()) << 24;
+ return(i);
+ }
+
+/*
+ * lrfill(address,number) put input bytes into a buffer
+ * char *address;
+ * int number;
+ *
+ * Reads "number" bytes into the buffer pointed to by "address".
+ * Returns nothing of value
+ */
+lrfill(adr,num)
+ register char *adr;
+ int num;
+ {
+ register char *pnt;
+ register int num2;
+ while (num)
+ {
+ if (iepoint == ipoint)
+ {
+ if (num>5) /* fast way */
+ {
+ if (read(fd,adr,num) != num)
+ write(2,"error reading from input file\n",30);
+ num=0;
+ }
+ else { *adr++ = lgetc(); --num; }
+ }
+ else
+ {
+ num2 = iepoint-ipoint; /* # of bytes left in the buffer */
+ if (num2 > num) num2=num;
+ pnt = inbuffer+ipoint; num -= num2; ipoint += num2;
+ while (num2--) *adr++ = *pnt++;
+ }
+ }
+ }
+
+/*
+ * char *lgetw() Get a whitespace ended word from input
+ *
+ * Returns pointer to a buffer that contains word. If EOF, returns a NULL
+ */
+char *lgetw()
+ {
+ register char *lgp,cc;
+ register int n=LINBUFSIZE,quote=0;
+ lgp = lgetwbuf;
+ do cc=lgetc(); while ((cc <= 32) && (cc > NULL)); /* eat whitespace */
+ for ( ; ; --n,cc=lgetc())
+ {
+ if ((cc==NULL) && (lgp==lgetwbuf)) return(NULL); /* EOF */
+ if ((n<=1) || ((cc<=32) && (quote==0))) { *lgp=NULL; return(lgetwbuf); }
+ if (cc != '"') *lgp++ = cc; else quote ^= 1;
+ }
+ }
+
+/*
+ * char *lgetl() Function to read in a line ended by newline or EOF
+ *
+ * Returns pointer to a buffer that contains the line. If EOF, returns NULL
+ */
+char *lgetl()
+ {
+ register int i=LINBUFSIZE,ch;
+ register char *str=lgetwbuf;
+ for ( ; ; --i)
+ {
+ if ((*str++ = ch = lgetc()) == NULL)
+ {
+ if (str == lgetwbuf+1) return(NULL); /* EOF */
+ ot: *str = NULL; return(lgetwbuf); /* line ended by EOF */
+ }
+ if ((ch=='\n') || (i<=1)) goto ot; /* line ended by \n */
+ }
+ }
+
+/*
+ * lcreat(filename) Create a new file for write
+ * char *filename;
+ *
+ * lcreat((char*)0); means to the terminal
+ * Returns -1 if error, otherwise the file descriptor opened.
+ */
+lcreat(str)
+ char *str;
+ {
+ lpnt = lpbuf; lpend = lpbuf+BUFBIG;
+ if (str==NULL) return(lfd=1);
+ if ((lfd=creat(str,0644)) < 0)
+ {
+ lfd=1; lprintf("error creating file <%s>\n",str); lflush(); return(-1);
+ }
+ return(lfd);
+ }
+
+/*
+ * lopen(filename) Open a file for read
+ * char *filename;
+ *
+ * lopen(0) means from the terminal
+ * Returns -1 if error, otherwise the file descriptor opened.
+ */
+lopen(str)
+ char *str;
+ {
+ ipoint = iepoint = MAXIBUF;
+ if (str==NULL) return(fd=0);
+ if ((fd=open(str,0)) < 0)
+ {
+ lwclose(); lfd=1; lpnt=lpbuf; return(-1);
+ }
+ return(fd);
+ }
+
+/*
+ * lappend(filename) Open for append to an existing file
+ * char *filename;
+ *
+ * lappend(0) means to the terminal
+ * Returns -1 if error, otherwise the file descriptor opened.
+ */
+lappend(str)
+ char *str;
+ {
+ lpnt = lpbuf; lpend = lpbuf+BUFBIG;
+ if (str==NULL) return(lfd=1);
+ if ((lfd=open(str,2)) < 0)
+ {
+ lfd=1; return(-1);
+ }
+ lseek(lfd,0,2); /* seek to end of file */
+ return(lfd);
+ }
+
+/*
+ * lrclose() close the input file
+ *
+ * Returns nothing of value.
+ */
+lrclose()
+ {
+ if (fd > 0) close(fd);
+ }
+
+/*
+ * lwclose() close output file flushing if needed
+ *
+ * Returns nothing of value.
+ */
+lwclose()
+ {
+ lflush(); if (lfd > 2) close(lfd);
+ }
+
+/*
+ * lprcat(string) append a string to the output buffer
+ * avoids calls to lprintf (time consuming)
+ */
+lprcat(str)
+ register char *str;
+ {
+ register char *str2;
+ if (lpnt >= lpend) lflush();
+ str2 = lpnt;
+ while (*str2++ = *str++);
+ lpnt = str2 - 1;
+ }
+
+#ifdef VT100
+/*
+ * cursor(x,y) Subroutine to set the cursor position
+ *
+ * x and y are the cursor coordinates, and lpbuff is the output buffer where
+ * escape sequence will be placed.
+ */
+static char *y_num[]= { "\33[","\33[","\33[2","\33[3","\33[4","\33[5","\33[6",
+ "\33[7","\33[8","\33[9","\33[10","\33[11","\33[12","\33[13","\33[14",
+ "\33[15","\33[16","\33[17","\33[18","\33[19","\33[20","\33[21","\33[22",
+ "\33[23","\33[24" };
+
+static char *x_num[]= { "H","H",";2H",";3H",";4H",";5H",";6H",";7H",";8H",";9H",
+ ";10H",";11H",";12H",";13H",";14H",";15H",";16H",";17H",";18H",";19H",
+ ";20H",";21H",";22H",";23H",";24H",";25H",";26H",";27H",";28H",";29H",
+ ";30H",";31H",";32H",";33H",";34H",";35H",";36H",";37H",";38H",";39H",
+ ";40H",";41H",";42H",";43H",";44H",";45H",";46H",";47H",";48H",";49H",
+ ";50H",";51H",";52H",";53H",";54H",";55H",";56H",";57H",";58H",";59H",
+ ";60H",";61H",";62H",";63H",";64H",";65H",";66H",";67H",";68H",";69H",
+ ";70H",";71H",";72H",";73H",";74H",";75H",";76H",";77H",";78H",";79H",
+ ";80H" };
+
+cursor(x,y)
+ int x,y;
+ {
+ register char *p;
+ if (lpnt >= lpend) lflush();
+
+ p = y_num[y]; /* get the string to print */
+ while (*p) *lpnt++ = *p++; /* print the string */
+
+ p = x_num[x]; /* get the string to print */
+ while (*p) *lpnt++ = *p++; /* print the string */
+ }
+#else VT100
+/*
+ * cursor(x,y) Put cursor at specified coordinates staring at [1,1] (termcap)
+ */
+cursor (x,y)
+ int x,y;
+ {
+ if (lpnt >= lpend) lflush ();
+
+ *lpnt++ = CURSOR; *lpnt++ = x; *lpnt++ = y;
+ }
+#endif VT100
+
+/*
+ * Routine to position cursor at beginning of 24th line
+ */
+cursors()
+ {
+ cursor(1,24);
+ }
+
+#ifndef VT100
+/*
+ * Warning: ringing the bell is control code 7. Don't use in defines.
+ * Don't change the order of these defines.
+ * Also used in helpfiles. Codes used in helpfiles should be \E[1 to \E[7 with
+ * obvious meanings.
+ */
+
+static char cap[256];
+char *CM, *CE, *CD, *CL, *SO, *SE, *AL, *DL;/* Termcap capabilities */
+static char *outbuf=0; /* translated output buffer */
+
+int putchar ();
+
+/*
+ * init_term() Terminal initialization -- setup termcap info
+ */
+init_term()
+ {
+ char termbuf[1024];
+ char *capptr = cap+10;
+ char *term;
+
+ switch (tgetent(termbuf, term = getenv("TERM")))
+ {
+ case -1:
+ write(2, "Cannot open termcap file.\n", 26); exit();
+ case 0:
+ write(2, "Cannot find entry of ", 21);
+ write(2, term, strlen (term));
+ write(2, " in termcap\n", 12);
+ exit();
+ };
+
+ CM = tgetstr("cm", &capptr); /* Cursor motion */
+ CE = tgetstr("ce", &capptr); /* Clear to eoln */
+ CL = tgetstr("cl", &capptr); /* Clear screen */
+
+/* OPTIONAL */
+ AL = tgetstr("al", &capptr); /* Insert line */
+ DL = tgetstr("dl", &capptr); /* Delete line */
+ SO = tgetstr("so", &capptr); /* Begin standout mode */
+ SE = tgetstr("se", &capptr); /* End standout mode */
+ CD = tgetstr("cd", &capptr); /* Clear to end of display */
+
+ if (!CM) /* can't find cursor motion entry */
+ {
+ write(2, "Sorry, for a ",13); write(2, term, strlen(term));
+ write(2, ", I can't find the cursor motion entry in termcap\n",50);
+ exit();
+ }
+ if (!CE) /* can't find clear to end of line entry */
+ {
+ write(2, "Sorry, for a ",13); write(2, term, strlen(term));
+ write(2,", I can't find the clear to end of line entry in termcap\n",57);
+ exit();
+ }
+ if (!CL) /* can't find clear entire screen entry */
+ {
+ write(2, "Sorry, for a ",13); write(2, term, strlen(term));
+ write(2, ", I can't find the clear entire screen entry in termcap\n",56);
+ exit();
+ }
+ if ((outbuf=malloc(BUFBIG+16))==0) /* get memory for decoded output buffer*/
+ {
+ write(2,"Error malloc'ing memory for decoded output buffer\n",50);
+ died(-285); /* malloc() failure */
+ }
+ }
+#endif VT100
+
+/*
+ * cl_line(x,y) Clear the whole line indicated by 'y' and leave cursor at [x,y]
+ */
+cl_line(x,y)
+ int x,y;
+ {
+#ifdef VT100
+ cursor(x,y); lprcat("\33[2K");
+#else VT100
+ cursor(1,y); *lpnt++ = CL_LINE; cursor(x,y);
+#endif VT100
+ }
+
+/*
+ * cl_up(x,y) Clear screen from [x,1] to current position. Leave cursor at [x,y]
+ */
+cl_up(x,y)
+ register int x,y;
+ {
+#ifdef VT100
+ cursor(x,y); lprcat("\33[1J\33[2K");
+#else VT100
+ register int i;
+ cursor(1,1);
+ for (i=1; i<=y; i++) { *lpnt++ = CL_LINE; *lpnt++ = '\n'; }
+ cursor(x,y);
+#endif VT100
+ }
+
+/*
+ * cl_dn(x,y) Clear screen from [1,y] to end of display. Leave cursor at [x,y]
+ */
+cl_dn(x,y)
+ register int x,y;
+ {
+#ifdef VT100
+ cursor(x,y); lprcat("\33[J\33[2K");
+#else VT100
+ register int i;
+ cursor(1,y);
+ if (!CD)
+ {
+ *lpnt++ = CL_LINE;
+ for (i=y; i<=24; i++) { *lpnt++ = CL_LINE; if (i!=24) *lpnt++ = '\n'; }
+ cursor(x,y);
+ }
+ else
+ *lpnt++ = CL_DOWN;
+ cursor(x,y);
+#endif VT100
+ }
+
+/*
+ * standout(str) Print the argument string in inverse video (standout mode).
+ */
+standout(str)
+ register char *str;
+ {
+#ifdef VT100
+ setbold();
+ while (*str)
+ *lpnt++ = *str++;
+ resetbold();
+#else VT100
+ *lpnt++ = ST_START;
+ while (*str)
+ *lpnt++ = *str++;
+ *lpnt++ = ST_END;
+#endif VT100
+ }
+
+/*
+ * set_score_output() Called when output should be literally printed.
+ */
+set_score_output()
+ {
+ enable_scroll = -1;
+ }
+
+/*
+ * lflush() Flush the output buffer
+ *
+ * Returns nothing of value.
+ * for termcap version: Flush output in output buffer according to output
+ * status as indicated by `enable_scroll'
+ */
+#ifndef VT100
+static int scrline=18; /* line # for wraparound instead of scrolling if no DL */
+lflush ()
+ {
+ register int lpoint;
+ register char *str;
+ static int curx = 0;
+ static int cury = 0;
+
+ if ((lpoint = lpnt - lpbuf) > 0)
+ {
+#ifdef EXTRA
+ c[BYTESOUT] += lpoint;
+#endif
+ if (enable_scroll <= -1)
+ {
+ flush_buf();
+ if (write(lfd,lpbuf,lpoint) != lpoint)
+ write(2,"error writing to output file\n",29);
+ lpnt = lpbuf; /* point back to beginning of buffer */
+ return;
+ }
+ for (str = lpbuf; str < lpnt; str++)
+ {
+ if (*str>=32) { putchar (*str); curx++; }
+ else switch (*str)
+ {
+ case CLEAR: tputs (CL, 0, putchar); curx = cury = 0;
+ break;
+
+ case CL_LINE: tputs (CE, 0, putchar);
+ break;
+
+ case CL_DOWN: tputs (CD, 0, putchar);
+ break;
+
+ case ST_START: tputs (SO, 0, putchar);
+ break;
+
+ case ST_END: tputs (SE, 0, putchar);
+ break;
+
+ case CURSOR: curx = *++str - 1; cury = *++str - 1;
+ tputs (tgoto (CM, curx, cury), 0, putchar);
+ break;
+
+ case '\n': if ((cury == 23) && enable_scroll)
+ {
+ if (!DL || !AL) /* wraparound or scroll? */
+ {
+ if (++scrline > 23) scrline=19;
+
+ if (++scrline > 23) scrline=19;
+ tputs (tgoto (CM, 0, scrline), 0, putchar);
+ tputs (CE, 0, putchar);
+
+ if (--scrline < 19) scrline=23;
+ tputs (tgoto (CM, 0, scrline), 0, putchar);
+ tputs (CE, 0, putchar);
+ }
+ else
+ {
+ tputs (tgoto (CM, 0, 19), 0, putchar);
+ tputs (DL, 0, putchar);
+ tputs (tgoto (CM, 0, 23), 0, putchar);
+ /* tputs (AL, 0, putchar); */
+ }
+ }
+ else
+ {
+ putchar ('\n'); cury++;
+ }
+ curx = 0;
+ break;
+
+ default: putchar (*str); curx++;
+ };
+ }
+ }
+ lpnt = lpbuf;
+ flush_buf(); /* flush real output buffer now */
+ }
+#else VT100
+/*
+ * lflush() flush the output buffer
+ *
+ * Returns nothing of value.
+ */
+lflush()
+ {
+ register int lpoint;
+ if ((lpoint = lpnt - lpbuf) > 0)
+ {
+#ifdef EXTRA
+ c[BYTESOUT] += lpoint;
+#endif
+ if (write(lfd,lpbuf,lpoint) != lpoint)
+ write(2,"error writing to output file\n",29);
+ }
+ lpnt = lpbuf; /* point back to beginning of buffer */
+ }
+#endif VT100
+
+#ifndef VT100
+static int index=0;
+/*
+ * putchar(ch) Print one character in decoded output buffer.
+ */
+int putchar(c)
+int c;
+ {
+ outbuf[index++] = c;
+ if (index >= BUFBIG) flush_buf();
+ }
+
+/*
+ * flush_buf() Flush buffer with decoded output.
+ */
+flush_buf()
+ {
+ if (index) write(lfd, outbuf, index);
+ index = 0;
+ }
+
+/*
+ * char *tmcapcnv(sd,ss) Routine to convert VT100 escapes to termcap format
+ *
+ * Processes only the \33[#m sequence (converts . files for termcap use
+ */
+char *tmcapcnv(sd,ss)
+ register char *sd,*ss;
+ {
+ register int tmstate=0; /* 0=normal, 1=\33 2=[ 3=# */
+ char tmdigit=0; /* the # in \33[#m */
+ while (*ss)
+ {
+ switch(tmstate)
+ {
+ case 0: if (*ss=='\33') { tmstate++; break; }
+ ign: *sd++ = *ss;
+ ign2: tmstate = 0;
+ break;
+ case 1: if (*ss!='[') goto ign;
+ tmstate++;
+ break;
+ case 2: if (isdigit(*ss)) { tmdigit= *ss-'0'; tmstate++; break; }
+ if (*ss == 'm') { *sd++ = ST_END; goto ign2; }
+ goto ign;
+ case 3: if (*ss == 'm')
+ {
+ if (tmdigit) *sd++ = ST_START;
+ else *sd++ = ST_END;
+ goto ign2;
+ }
+ default: goto ign;
+ };
+ ss++;
+ }
+ *sd=0; /* NULL terminator */
+ return(sd);
+ }
+#endif VT100
+
+/*
+ * beep() Routine to emit a beep if enabled (see no-beep in .larnopts)
+ */
+beep()
+ {
+ if (!nobeep) *lpnt++ = '\7';
+ }