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