bsd-family-tree: Small sync with FreeBSD.
[dragonfly.git] / games / larn / io.c
blob55e587b12593ba5eca418dc2565210d82c0d916d
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 $
4 * Below are the functions in this file:
6 * setupvt100() Subroutine to set up terminal in correct mode for game
7 * clearvt100() Subroutine to clean up terminal when the game is over
8 * getchr() Routine to read in one character from the terminal
9 * scbr() Function to set cbreak -echo for the terminal
10 * sncbr() Function to set -cbreak echo for the terminal
11 * newgame() Subroutine to save the initial time and seed rnd()
13 * FILE OUTPUT ROUTINES
15 * lprintf(format, args...) printf to the output buffer
16 * lprint(integer) send binary integer to output buffer
17 * lwrite(buf,len) write a buffer to the output buffer
18 * lprcat(str) sent string to output buffer
20 * FILE OUTPUT MACROS (in header.h)
22 * lprc(character) put the character into the output buffer
24 * FILE INPUT ROUTINES
26 * long lgetc() read one character from input buffer
27 * long lrint_x() read one integer from input buffer
28 * lrfill(address,number) put input bytes into a buffer
29 * char *lgetw() get a whitespace ended word from input
30 * char *lgetl() get a \n or EOF ended line from input
32 * FILE OPEN / CLOSE ROUTINES
34 * lcreat(filename) create a new file for write
35 * lopen(filename) open a file for read
36 * lappend(filename) open for append to an existing file
37 * lrclose() close the input file
38 * lwclose() close output file
39 * lflush() flush the output buffer
41 * Other Routines
43 * cursor(x,y) position cursor at [x,y]
44 * cursors() position cursor at [1,24] (saves memory)
45 * cl_line(x,y) Clear line at [1,y] and leave cursor at [x,y]
46 * cl_up(x,y) Clear screen from [x,1] to current line.
47 * cl_dn(x,y) Clear screen from [1,y] to end of display.
48 * standout(str) Print the string in standout mode.
49 * set_score_output() Called when output should be literally printed.
50 * putchr(ch) Print one character in decoded output buffer.
51 * flush_buf() Flush buffer with decoded output.
52 * init_term() Terminal initialization -- setup termcap info
53 * char *tmcapcnv(sd,ss) Routine to convert VT100 \33's to termcap format
54 * beep() Routine to emit a beep if enabled (see no-beep in .larnopts)
56 * Note: ** entries are available only in termcap mode.
59 #include <stdarg.h>
60 #include <termios.h>
61 #include "header.h"
63 static int rawflg = 0;
64 static char saveeof, saveeol;
66 #define LINBUFSIZE 128 /* size of the lgetw() and lgetl() buffer */
67 int io_outfd; /* output file numbers */
68 int io_infd; /* input file numbers */
69 static struct termios ttx; /* storage for the tty modes */
70 static int ipoint=MAXIBUF, iepoint=MAXIBUF; /* input buffering pointers */
71 static char lgetwbuf[LINBUFSIZE]; /* get line (word) buffer */
73 #ifndef VT100
74 static int putchr(int);
75 static void flush_buf(void);
76 #endif
79 * setupvt100() Subroutine to set up terminal in correct mode for game
81 * Attributes off, clear screen, set scrolling region, set tty mode
83 void
84 setupvt100(void)
86 clear();
87 setscroll();
88 scbr();
92 * clearvt100() Subroutine to clean up terminal when the game is over
94 * Attributes off, clear screen, unset scrolling region, restore tty mode
96 void
97 clearvt100(void)
99 resetscroll();
100 clear();
101 sncbr();
105 * getchr() Routine to read in one character from the terminal
107 char
108 getchr(void)
110 char byt;
111 #ifdef EXTRA
112 c[BYTESIN]++;
113 #endif
114 lflush(); /* be sure output buffer is flushed */
115 read(0, &byt, 1); /* get byte from terminal */
116 return (byt);
120 * scbr() Function to set cbreak -echo for the terminal
122 * like: system("stty cbreak -echo")
124 void
125 scbr(void)
127 tcgetattr(0, &ttx);
128 /* doraw */
129 if (!rawflg) {
130 ++rawflg;
131 saveeof = ttx.c_cc[VMIN];
132 saveeol = ttx.c_cc[VTIME];
134 ttx.c_cc[VMIN] = 1;
135 ttx.c_cc[VTIME] = 1;
136 ttx.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL);
137 tcsetattr(0, TCSANOW, &ttx);
141 * sncbr() Function to set -cbreak echo for the terminal
143 * like: system("stty -cbreak echo")
145 void
146 sncbr(void)
148 tcgetattr(0, &ttx);
149 /* unraw */
150 ttx.c_cc[VMIN] = saveeof;
151 ttx.c_cc[VTIME] = saveeol;
152 ttx.c_lflag |= ICANON | ECHO | ECHOE | ECHOK | ECHONL;
153 tcsetattr(0, TCSANOW, &ttx);
157 * newgame() Subroutine to save the initial time and seed rnd()
159 void
160 newgame(void)
162 long *p, *pe;
163 for (p = c, pe = c + 100; p < pe; *p++ = 0)
165 time(&initialtime);
166 srandomdev();
167 lcreat(NULL); /* open buffering for output to terminal */
171 * lprintf(format, args...) printf to the output buffer
172 * char *format;
173 * ??? args...
175 * Enter with the format string in "format", as per printf() usage
176 * and any needed arguments following it
177 * Note: lprintf() only supports %s, %c and %d, with width modifier and left
178 * or right justification.
179 * No correct checking for output buffer overflow is done, but flushes
180 * are done beforehand if needed.
181 * Returns nothing of value.
183 void
184 lprintf(const char *fmt, ...)
186 va_list ap; /* pointer for variable argument list */
187 char *outb, *tmpb;
188 long wide, left, cont, n; /* data for lprintf */
189 char db[12]; /* %d buffer in lprintf */
191 va_start(ap, fmt); /* initialize the var args pointer */
192 if (lpnt >= lpend)
193 lflush();
194 outb = lpnt;
195 for (;;) {
196 while (*fmt != '%')
197 if (*fmt)
198 *outb++ = *fmt++;
199 else {
200 lpnt = outb;
201 return;
203 wide = 0;
204 left = 1;
205 cont = 1;
206 while (cont)
207 switch (*(++fmt)) {
208 case 'd':
209 n = va_arg(ap, long);
210 if (n < 0) {
211 n = -n;
212 *outb++ = '-';
213 if (wide)
214 --wide;
216 tmpb = db + 11;
217 *tmpb = (char)(n % 10 + '0');
218 while (n > 9)
219 *(--tmpb) = (char)((n /= 10) % 10 + '0');
220 if (wide == 0)
221 while (tmpb < db + 12)
222 *outb++ = *tmpb++;
223 else {
224 wide -= db - tmpb + 12;
225 if (left)
226 while (wide-- > 0)
227 *outb++ = ' ';
228 while (tmpb < db + 12)
229 *outb++ = *tmpb++;
230 if (left == 0)
231 while (wide-- > 0)
232 *outb++ = ' ';
234 cont = 0;
235 break;
237 case 's':
238 tmpb = va_arg(ap, char *);
239 if (wide == 0) {
240 while ((*outb++ = *tmpb++))
242 --outb;
243 } else {
244 n = wide - strlen(tmpb);
245 if (left)
246 while (n-- > 0)
247 *outb++ = ' ';
248 while ((*outb++ = *tmpb++))
250 --outb;
251 if (left == 0)
252 while (n-- > 0)
253 *outb++ = ' ';
255 cont = 0;
256 break;
258 case 'c':
259 *outb++ = va_arg(ap, int);
260 cont = 0;
261 break;
263 case '0':
264 case '1':
265 case '2':
266 case '3':
267 case '4':
268 case '5':
269 case '6':
270 case '7':
271 case '8':
272 case '9':
273 wide = 10 * wide + *fmt - '0';
274 break;
276 case '-':
277 left = 0;
278 break;
280 default:
281 *outb++ = *fmt;
282 cont = 0;
283 break;
285 fmt++;
287 va_end(ap);
291 * lprint(long-integer) send binary integer to output buffer
292 * long integer;
294 * +---------+---------+---------+---------+
295 * | high | | | low |
296 * | order | | | order |
297 * | byte | | | byte |
298 * +---------+---------+---------+---------+
299 * 31 --- 24 23 --- 16 15 --- 8 7 --- 0
301 * The save order is low order first, to high order (4 bytes total)
302 * and is written to be system independent.
303 * No checking for output buffer overflow is done, but flushes if needed!
304 * Returns nothing of value.
306 void
307 lprint(long x)
309 if (lpnt >= lpend)
310 lflush();
311 *lpnt++ = 255 & x;
312 *lpnt++ = 255 & (x >> 8);
313 *lpnt++ = 255 & (x >> 16);
314 *lpnt++ = 255 & (x >> 24);
318 * lwrite(buf,len) write a buffer to the output buffer
319 * char *buf;
320 * int len;
322 * Enter with the address and number of bytes to write out
323 * Returns nothing of value
325 void
326 lwrite(char *buf, int len)
328 char *str;
329 int num2;
331 if (len > 399) { /* don't copy data if can just write it */
332 #ifdef EXTRA
333 c[BYTESOUT] += len;
334 #endif
336 #ifndef VT100
337 for (str = buf; len > 0; --len)
338 lprc(*str++);
339 #else /* VT100 */
340 lflush();
341 write(io_outfd, buf, len);
342 #endif /* VT100 */
343 } else
344 while (len) {
345 if (lpnt >= lpend) /* if buffer is full flush it */
346 lflush();
347 num2 = lpbuf + BUFBIG - lpnt; /* # bytes left in output buffer */
348 if (num2 > len)
349 num2 = len;
350 str = lpnt;
351 len -= num2;
352 while (num2--) /* copy in the bytes */
353 *str++ = *buf++;
354 lpnt = str;
359 * long lgetc() Read one character from input buffer
361 * Returns 0 if EOF, otherwise the character
363 long
364 lgetc(void)
366 int i;
367 if (ipoint != iepoint)
368 return (inbuffer[ipoint++]);
369 if (iepoint != MAXIBUF)
370 return (0);
371 if ((i = read(io_infd, inbuffer, MAXIBUF)) <= 0) {
372 if (i != 0)
373 write(1, "error reading from input file\n", 30);
374 iepoint = ipoint = 0;
375 return (0);
377 ipoint = 1;
378 iepoint = i;
379 return (*inbuffer);
383 * long lrint_x() Read one integer from input buffer
385 * +---------+---------+---------+---------+
386 * | high | | | low |
387 * | order | | | order |
388 * | byte | | | byte |
389 * +---------+---------+---------+---------+
390 * 31 --- 24 23 --- 16 15 --- 8 7 --- 0
392 * The save order is low order first, to high order (4 bytes total)
393 * Returns the int read
395 long
396 lrint_x(void)
398 unsigned long i;
399 i = 255 & lgetc();
400 i |= (255 & lgetc()) << 8;
401 i |= (255 & lgetc()) << 16;
402 i |= (255 & lgetc()) << 24;
403 return (i);
407 * lrfill(address,number) put input bytes into a buffer
408 * char *address;
409 * int number;
411 * Reads "number" bytes into the buffer pointed to by "address".
412 * Returns nothing of value
414 void
415 lrfill(char *adr, int num)
417 char *pnt;
418 int num2;
419 while (num) {
420 if (iepoint == ipoint) {
421 if (num > 5) { /* fast way */
422 if (read(io_infd, adr, num) != num)
423 write(2, "error reading from input file\n", 30);
424 num = 0;
425 } else {
426 *adr++ = lgetc();
427 --num;
429 } else {
430 num2 = iepoint - ipoint; /* # of bytes left in the buffer */
431 if (num2 > num)
432 num2 = num;
433 pnt = inbuffer + ipoint;
434 num -= num2;
435 ipoint += num2;
436 while (num2--)
437 *adr++ = *pnt++;
443 * char *lgetw() Get a whitespace ended word from input
445 * Returns pointer to a buffer that contains word. If EOF, returns a NULL
447 char *
448 lgetw(void)
450 char *lgp, cc;
451 int n = LINBUFSIZE, quote = 0;
452 lgp = lgetwbuf;
454 cc = lgetc();
455 while ((cc <= 32) && (cc > '\0')); /* eat whitespace */
456 for (;; --n, cc = lgetc()) {
457 if ((cc == '\0') && (lgp == lgetwbuf)) /* EOF */
458 return (NULL);
459 if ((n <= 1) || ((cc <= 32) && (quote == 0))) {
460 *lgp = '\0';
461 return (lgetwbuf);
463 if (cc != '"')
464 *lgp++ = cc;
465 else
466 quote ^= 1;
471 * char *lgetl() Function to read in a line ended by newline or EOF
473 * Returns pointer to a buffer that contains the line. If EOF, returns NULL
475 char *
476 lgetl(void)
478 int i = LINBUFSIZE, ch;
479 char *str = lgetwbuf;
480 for (;; --i) {
481 if ((*str++ = ch = lgetc()) == '\0') {
482 if (str == lgetwbuf + 1) /* EOF */
483 return (NULL);
485 *str = 0;
486 return (lgetwbuf); /* line ended by EOF */
488 if ((ch == '\n') || (i <= 1)) /* line ended by \n */
489 goto ot;
494 * lcreat(filename) Create a new file for write
495 * char *filename;
497 * lcreat(NULL); means to the terminal
498 * Returns -1 if error, otherwise the file descriptor opened.
501 lcreat(char *str)
503 lpnt = lpbuf;
504 lpend = lpbuf + BUFBIG;
505 if (str == NULL)
506 return (io_outfd = 1);
507 if ((io_outfd = creat(str, 0644)) < 0) {
508 io_outfd = 1;
509 lprintf("error creating file <%s>\n", str);
510 lflush();
511 return (-1);
513 return (io_outfd);
517 * lopen(filename) Open a file for read
518 * char *filename;
520 * lopen(0) means from the terminal
521 * Returns -1 if error, otherwise the file descriptor opened.
524 lopen(char *str)
526 ipoint = iepoint = MAXIBUF;
527 if (str == NULL)
528 return (io_infd = 0);
529 if ((io_infd = open(str, O_RDONLY)) < 0) {
530 lwclose();
531 io_outfd = 1;
532 lpnt = lpbuf;
533 return (-1);
535 return (io_infd);
539 * lappend(filename) Open for append to an existing file
540 * char *filename;
542 * lappend(0) means to the terminal
543 * Returns -1 if error, otherwise the file descriptor opened.
546 lappend(char *str)
548 lpnt = lpbuf;
549 lpend = lpbuf + BUFBIG;
550 if (str == NULL)
551 return (io_outfd = 1);
552 if ((io_outfd = open(str, O_RDWR)) < 0) {
553 io_outfd = 1;
554 return (-1);
556 lseek(io_outfd, 0, SEEK_END); /* seek to end of file */
557 return (io_outfd);
561 * lrclose() close the input file
563 * Returns nothing of value.
565 void
566 lrclose(void)
568 if (io_infd > 0)
569 close(io_infd);
573 * lwclose() close output file flushing if needed
575 * Returns nothing of value.
577 void
578 lwclose(void)
580 lflush();
581 if (io_outfd > 2)
582 close(io_outfd);
586 * lprcat(string) append a string to the output buffer
587 * avoids calls to lprintf (time consuming)
589 void
590 lprcat(const char *str)
592 char *str2;
593 if (lpnt >= lpend)
594 lflush();
595 str2 = lpnt;
596 while ((*str2++ = *str++) != '\0')
597 continue;
598 lpnt = str2 - 1;
601 #ifdef VT100
603 * cursor(x,y) Subroutine to set the cursor position
605 * x and y are the cursor coordinates, and lpbuff is the output buffer where
606 * escape sequence will be placed.
608 static const char *y_num[]= { "\33[","\33[","\33[2","\33[3","\33[4","\33[5","\33[6",
609 "\33[7","\33[8","\33[9","\33[10","\33[11","\33[12","\33[13","\33[14",
610 "\33[15","\33[16","\33[17","\33[18","\33[19","\33[20","\33[21","\33[22",
611 "\33[23","\33[24" };
613 static const char *x_num[]= { "H","H",";2H",";3H",";4H",";5H",";6H",";7H",";8H",";9H",
614 ";10H",";11H",";12H",";13H",";14H",";15H",";16H",";17H",";18H",";19H",
615 ";20H",";21H",";22H",";23H",";24H",";25H",";26H",";27H",";28H",";29H",
616 ";30H",";31H",";32H",";33H",";34H",";35H",";36H",";37H",";38H",";39H",
617 ";40H",";41H",";42H",";43H",";44H",";45H",";46H",";47H",";48H",";49H",
618 ";50H",";51H",";52H",";53H",";54H",";55H",";56H",";57H",";58H",";59H",
619 ";60H",";61H",";62H",";63H",";64H",";65H",";66H",";67H",";68H",";69H",
620 ";70H",";71H",";72H",";73H",";74H",";75H",";76H",";77H",";78H",";79H",
621 ";80H" };
623 void
624 cursor(int x, int y)
626 char *p;
627 if (lpnt >= lpend)
628 lflush();
630 p = y_num[y]; /* get the string to print */
631 while (*p)
632 *lpnt++ = *p++; /* print the string */
634 p = x_num[x]; /* get the string to print */
635 while (*p)
636 *lpnt++ = *p++; /* print the string */
638 #else /* VT100 */
640 * cursor(x,y) Put cursor at specified coordinates staring at [1,1] (termcap)
642 void
643 cursor(int x, int y)
645 if (lpnt >= lpend)
646 lflush();
648 *lpnt++ = CURSOR;
649 *lpnt++ = x;
650 *lpnt++ = y;
652 #endif /* VT100 */
655 * Routine to position cursor at beginning of 24th line
657 void
658 cursors(void)
660 cursor(1, 24);
663 #ifndef VT100
665 * Warning: ringing the bell is control code 7. Don't use in defines.
666 * Don't change the order of these defines.
667 * Also used in helpfiles. Codes used in helpfiles should be \E[1 to \E[7 with
668 * obvious meanings.
671 static char cap[256];
672 char *CM, *CE, *CD, *CL, *SO, *SE, *AL, *DL;/* Termcap capabilities */
673 static char *outbuf = NULL; /* translated output buffer */
676 * init_term() Terminal initialization -- setup termcap info
678 void
679 init_term(void)
681 char termbuf[1024];
682 char *capptr = cap + 10;
683 char *term;
685 switch (tgetent(termbuf, term = getenv("TERM"))) {
686 case -1:
687 write(2, "Cannot open termcap file.\n", 26);
688 exit(1);
689 case 0:
690 write(2, "Cannot find entry of ", 21);
691 write(2, term, strlen(term));
692 write(2, " in termcap\n", 12);
693 exit(1);
696 CM = tgetstr("cm", &capptr); /* Cursor motion */
697 CE = tgetstr("ce", &capptr); /* Clear to eoln */
698 CL = tgetstr("cl", &capptr); /* Clear screen */
700 /* OPTIONAL */
701 AL = tgetstr("al", &capptr); /* Insert line */
702 DL = tgetstr("dl", &capptr); /* Delete line */
703 SO = tgetstr("so", &capptr); /* Begin standout mode */
704 SE = tgetstr("se", &capptr); /* End standout mode */
705 CD = tgetstr("cd", &capptr); /* Clear to end of display */
707 if (!CM) { /* can't find cursor motion entry */
708 write(2, "Sorry, for a ", 13);
709 write(2, term, strlen(term));
710 write(2, ", I can't find the cursor motion entry in termcap\n", 50);
711 exit(1);
713 if (!CE) { /* can't find clear to end of line entry */
714 write(2, "Sorry, for a ", 13);
715 write(2, term, strlen(term));
716 write(2, ", I can't find the clear to end of line entry in termcap\n", 57);
717 exit(1);
719 if (!CL) { /* can't find clear entire screen entry */
720 write(2, "Sorry, for a ", 13);
721 write(2, term, strlen(term));
722 write(2, ", I can't find the clear entire screen entry in termcap\n", 56);
723 exit(1);
725 /* get memory for decoded output buffer*/
726 if ((outbuf = malloc(BUFBIG + 16)) == NULL) {
727 write(2, "Error malloc'ing memory for decoded output buffer\n", 50);
728 died(-285); /* malloc() failure */
731 #endif /* VT100 */
734 * cl_line(x,y) Clear the whole line indicated by 'y' and leave cursor at [x,y]
736 void
737 cl_line(int x, int y)
739 #ifdef VT100
740 cursor(x, y);
741 lprcat("\33[2K");
742 #else /* VT100 */
743 cursor(1, y);
744 *lpnt++ = CL_LINE;
745 cursor(x, y);
746 #endif /* VT100 */
750 * cl_up(x,y) Clear screen from [x,1] to current position. Leave cursor at [x,y]
752 void
753 cl_up(int x, int y)
755 #ifdef VT100
756 cursor(x, y);
757 lprcat("\33[1J\33[2K");
758 #else /* VT100 */
759 int i;
760 cursor(1, 1);
761 for (i = 1; i <= y; i++) {
762 *lpnt++ = CL_LINE;
763 *lpnt++ = '\n';
765 cursor(x, y);
766 #endif /* VT100 */
770 * cl_dn(x,y) Clear screen from [1,y] to end of display. Leave cursor at [x,y]
772 void
773 cl_dn(int x, int y)
775 #ifdef VT100
776 cursor(x, y);
777 lprcat("\33[J\33[2K");
778 #else /* VT100 */
779 int i;
780 cursor(1, y);
781 if (!CD) {
782 *lpnt++ = CL_LINE;
783 for (i = y; i <= 24; i++) {
784 *lpnt++ = CL_LINE;
785 if (i != 24)
786 *lpnt++ = '\n';
788 cursor(x, y);
789 } else
790 *lpnt++ = CL_DOWN;
791 cursor(x, y);
792 #endif /* VT100 */
796 * standout(str) Print the argument string in inverse video (standout mode).
798 void
799 standout(const char *str)
801 #ifdef VT100
802 setbold();
803 while (*str)
804 *lpnt++ = *str++;
805 resetbold();
806 #else /* VT100 */
807 *lpnt++ = ST_START;
808 while (*str)
809 *lpnt++ = *str++;
810 *lpnt++ = ST_END;
811 #endif /* VT100 */
815 * set_score_output() Called when output should be literally printed.
817 void
818 set_score_output(void)
820 enable_scroll = -1;
824 * lflush() Flush the output buffer
826 * Returns nothing of value.
827 * for termcap version: Flush output in output buffer according to output
828 * status as indicated by `enable_scroll'
830 #ifndef VT100
831 static int scrline = 18; /* line # for wraparound instead of scrolling if no DL */
833 void
834 lflush(void)
836 int lpoint;
837 char *str;
838 static int curx = 0;
839 static int cury = 0;
841 if ((lpoint = lpnt - lpbuf) > 0) {
842 #ifdef EXTRA
843 c[BYTESOUT] += lpoint;
844 #endif
845 if (enable_scroll <= -1) {
846 flush_buf();
847 if (write(io_outfd, lpbuf, lpoint) != lpoint)
848 write(2, "error writing to output file\n", 29);
849 lpnt = lpbuf; /* point back to beginning of buffer */
850 return;
852 for (str = lpbuf; str < lpnt; str++) {
853 if (*str >= 32) {
854 putchr(*str);
855 curx++;
856 } else
857 switch (*str) {
858 case CLEAR:
859 tputs(CL, 0, putchr);
860 curx = cury = 0;
861 break;
863 case CL_LINE:
864 tputs(CE, 0, putchr);
865 break;
867 case CL_DOWN:
868 tputs(CD, 0, putchr);
869 break;
871 case ST_START:
872 tputs(SO, 0, putchr);
873 break;
875 case ST_END:
876 tputs(SE, 0, putchr);
877 break;
879 case CURSOR:
880 curx = *++str - 1;
881 cury = *++str - 1;
882 tputs(tgoto(CM, curx, cury), 0, putchr);
883 break;
885 case '\n':
886 if ((cury == 23) && enable_scroll) {
887 if (!DL || !AL) { /* wraparound or scroll? */
888 if (++scrline > 23)
889 scrline = 19;
891 if (++scrline > 23)
892 scrline = 19;
893 tputs(tgoto(CM, 0, scrline), 0, putchr);
894 tputs(CE, 0, putchr);
896 if (--scrline < 19)
897 scrline = 23;
898 tputs(tgoto(CM, 0, scrline), 0, putchr);
899 tputs(CE, 0, putchr);
900 } else {
901 tputs(tgoto(CM, 0, 19), 0, putchr);
902 tputs(DL, 0, putchr);
903 tputs(tgoto(CM, 0, 23), 0, putchr);
905 } else {
906 putchr('\n');
907 cury++;
909 curx = 0;
910 break;
912 default:
913 putchr(*str);
914 curx++;
918 lpnt = lpbuf;
919 flush_buf(); /* flush real output buffer now */
921 #else /* VT100 */
923 * lflush() flush the output buffer
925 * Returns nothing of value.
927 void
928 lflush(void)
930 int lpoint;
931 if ((lpoint = lpnt - lpbuf) > 0) {
932 #ifdef EXTRA
933 c[BYTESOUT] += lpoint;
934 #endif
935 if (write(io_outfd, lpbuf, lpoint) != lpoint)
936 write(2, "error writing to output file\n", 29);
938 lpnt = lpbuf; /* point back to beginning of buffer */
940 #endif /* VT100 */
942 #ifndef VT100
943 static int pindex = 0;
945 * putchr(ch) Print one character in decoded output buffer.
947 static int
948 putchr(int ch)
950 outbuf[pindex++] = ch;
951 if (pindex >= BUFBIG)
952 flush_buf();
953 return (0);
957 * flush_buf() Flush buffer with decoded output.
959 static void
960 flush_buf(void)
962 if (pindex)
963 write(io_outfd, outbuf, pindex);
964 pindex = 0;
968 * char *tmcapcnv(sd,ss) Routine to convert VT100 escapes to termcap format
970 * Processes only the \33[#m sequence (converts . files for termcap use
972 char *
973 tmcapcnv(char *sd, char *ss)
975 int tmstate = 0; /* 0=normal, 1=\33 2=[ 3=# */
976 char tmdigit = 0; /* the # in \33[#m */
977 while (*ss) {
978 switch (tmstate) {
979 case 0:
980 if (*ss == '\33') {
981 tmstate++;
982 break;
984 ign: *sd++ = *ss;
985 ign2: tmstate = 0;
986 break;
987 case 1:
988 if (*ss != '[')
989 goto ign;
990 tmstate++;
991 break;
992 case 2:
993 if (isdigit((int)*ss)) {
994 tmdigit = *ss - '0';
995 tmstate++;
996 break;
998 if (*ss == 'm') {
999 *sd++ = ST_END;
1000 goto ign2;
1002 goto ign;
1003 case 3:
1004 if (*ss == 'm') {
1005 if (tmdigit)
1006 *sd++ = ST_START;
1007 else
1008 *sd++ = ST_END;
1009 goto ign2;
1011 default:
1012 goto ign;
1014 ss++;
1016 *sd = 0; /* NULL terminator */
1017 return (sd);
1019 #endif /* VT100 */
1022 * beep() Routine to emit a beep if enabled (see no-beep in .larnopts)
1024 void
1025 beep(void)
1027 if (!nobeep)
1028 *lpnt++ = '\7';