wbsio(4): convert to Newbus and DragonFly -- welcome wbsio(4)!
[dragonfly.git] / games / larn / io.c
blob9ff751d5bda49bf2dde31298d77cdcabed7031e3
1 /* io.c Larn is copyrighted 1986 by Noah Morgan.
2 * $FreeBSD: src/games/larn/io.c,v 1.7 1999/11/16 02:57:22 billf Exp $
3 * $DragonFly: src/games/larn/io.c,v 1.7 2008/06/05 18:06:30 swildner Exp $
5 * Below are the functions in this file:
7 * setupvt100() Subroutine to set up terminal in correct mode for game
8 * clearvt100() Subroutine to clean up terminal when the game is over
9 * getchr() Routine to read in one character from the terminal
10 * scbr() Function to set cbreak -echo for the terminal
11 * sncbr() Function to set -cbreak echo for the terminal
12 * newgame() Subroutine to save the initial time and seed rnd()
14 * FILE OUTPUT ROUTINES
16 * lprintf(format, args...) printf to the output buffer
17 * lprint(integer) send binary integer to output buffer
18 * lwrite(buf,len) write a buffer to the output buffer
19 * lprcat(str) sent string to output buffer
21 * FILE OUTPUT MACROS (in header.h)
23 * lprc(character) put the character into the output buffer
25 * FILE INPUT ROUTINES
27 * long lgetc() read one character from input buffer
28 * long lrint_x() read one integer from input buffer
29 * lrfill(address,number) put input bytes into a buffer
30 * char *lgetw() get a whitespace ended word from input
31 * char *lgetl() get a \n or EOF ended line from input
33 * FILE OPEN / CLOSE ROUTINES
35 * lcreat(filename) create a new file for write
36 * lopen(filename) open a file for read
37 * lappend(filename) open for append to an existing file
38 * lrclose() close the input file
39 * lwclose() close output file
40 * lflush() flush the output buffer
42 * Other Routines
44 * cursor(x,y) position cursor at [x,y]
45 * cursors() position cursor at [1,24] (saves memory)
46 * cl_line(x,y) Clear line at [1,y] and leave cursor at [x,y]
47 * cl_up(x,y) Clear screen from [x,1] to current line.
48 * cl_dn(x,y) Clear screen from [1,y] to end of display.
49 * standout(str) Print the string in standout mode.
50 * set_score_output() Called when output should be literally printed.
51 * putchr(ch) Print one character in decoded output buffer.
52 * flush_buf() Flush buffer with decoded output.
53 * init_term() Terminal initialization -- setup termcap info
54 * char *tmcapcnv(sd,ss) Routine to convert VT100 \33's to termcap format
55 * beep() Routine to emit a beep if enabled (see no-beep in .larnopts)
57 * Note: ** entries are available only in termcap mode.
60 #include <stdarg.h>
61 #include <termios.h>
62 #include "header.h"
64 static int rawflg = 0;
65 static char saveeof, saveeol;
67 #define LINBUFSIZE 128 /* size of the lgetw() and lgetl() buffer */
68 int io_outfd; /* output file numbers */
69 int io_infd; /* input file numbers */
70 static struct termios ttx; /* storage for the tty modes */
71 static int ipoint=MAXIBUF, iepoint=MAXIBUF; /* input buffering pointers */
72 static char lgetwbuf[LINBUFSIZE]; /* get line (word) buffer */
74 #ifndef VT100
75 static int putchr(int);
76 static void flush_buf(void);
77 #endif
80 * setupvt100() Subroutine to set up terminal in correct mode for game
82 * Attributes off, clear screen, set scrolling region, set tty mode
84 void
85 setupvt100(void)
87 clear();
88 setscroll();
89 scbr();
93 * clearvt100() Subroutine to clean up terminal when the game is over
95 * Attributes off, clear screen, unset scrolling region, restore tty mode
97 void
98 clearvt100(void)
100 resetscroll();
101 clear();
102 sncbr();
106 * getchr() Routine to read in one character from the terminal
108 char
109 getchr(void)
111 char byt;
112 #ifdef EXTRA
113 c[BYTESIN]++;
114 #endif
115 lflush(); /* be sure output buffer is flushed */
116 read(0, &byt, 1); /* get byte from terminal */
117 return (byt);
121 * scbr() Function to set cbreak -echo for the terminal
123 * like: system("stty cbreak -echo")
125 void
126 scbr(void)
128 tcgetattr(0, &ttx);
129 /* doraw */
130 if (!rawflg) {
131 ++rawflg;
132 saveeof = ttx.c_cc[VMIN];
133 saveeol = ttx.c_cc[VTIME];
135 ttx.c_cc[VMIN] = 1;
136 ttx.c_cc[VTIME] = 1;
137 ttx.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL);
138 tcsetattr(0, TCSANOW, &ttx);
142 * sncbr() Function to set -cbreak echo for the terminal
144 * like: system("stty -cbreak echo")
146 void
147 sncbr(void)
149 tcgetattr(0, &ttx);
150 /* unraw */
151 ttx.c_cc[VMIN] = saveeof;
152 ttx.c_cc[VTIME] = saveeol;
153 ttx.c_lflag |= ICANON | ECHO | ECHOE | ECHOK | ECHONL;
154 tcsetattr(0, TCSANOW, &ttx);
158 * newgame() Subroutine to save the initial time and seed rnd()
160 void
161 newgame(void)
163 long *p, *pe;
164 for (p = c, pe = c + 100; p < pe; *p++ = 0)
166 time(&initialtime);
167 srandomdev();
168 lcreat(NULL); /* open buffering for output to terminal */
172 * lprintf(format, args...) printf to the output buffer
173 * char *format;
174 * ??? args...
176 * Enter with the format string in "format", as per printf() usage
177 * and any needed arguments following it
178 * Note: lprintf() only supports %s, %c and %d, with width modifier and left
179 * or right justification.
180 * No correct checking for output buffer overflow is done, but flushes
181 * are done beforehand if needed.
182 * Returns nothing of value.
184 void
185 lprintf(const char *fmt, ...)
187 va_list ap; /* pointer for variable argument list */
188 char *outb, *tmpb;
189 long wide, left, cont, n; /* data for lprintf */
190 char db[12]; /* %d buffer in lprintf */
192 va_start(ap, fmt); /* initialize the var args pointer */
193 if (lpnt >= lpend)
194 lflush();
195 outb = lpnt;
196 for (;;) {
197 while (*fmt != '%')
198 if (*fmt)
199 *outb++ = *fmt++;
200 else {
201 lpnt = outb;
202 return;
204 wide = 0;
205 left = 1;
206 cont = 1;
207 while (cont)
208 switch (*(++fmt)) {
209 case 'd':
210 n = va_arg(ap, long);
211 if (n < 0) {
212 n = -n;
213 *outb++ = '-';
214 if (wide)
215 --wide;
217 tmpb = db + 11;
218 *tmpb = (char)(n % 10 + '0');
219 while (n > 9)
220 *(--tmpb) = (char)((n /= 10) % 10 + '0');
221 if (wide == 0)
222 while (tmpb < db + 12)
223 *outb++ = *tmpb++;
224 else {
225 wide -= db - tmpb + 12;
226 if (left)
227 while (wide-- > 0)
228 *outb++ = ' ';
229 while (tmpb < db + 12)
230 *outb++ = *tmpb++;
231 if (left == 0)
232 while (wide-- > 0)
233 *outb++ = ' ';
235 cont = 0;
236 break;
238 case 's':
239 tmpb = va_arg(ap, char *);
240 if (wide == 0) {
241 while ((*outb++ = *tmpb++))
243 --outb;
244 } else {
245 n = wide - strlen(tmpb);
246 if (left)
247 while (n-- > 0)
248 *outb++ = ' ';
249 while ((*outb++ = *tmpb++))
251 --outb;
252 if (left == 0)
253 while (n-- > 0)
254 *outb++ = ' ';
256 cont = 0;
257 break;
259 case 'c':
260 *outb++ = va_arg(ap, int);
261 cont = 0;
262 break;
264 case '0':
265 case '1':
266 case '2':
267 case '3':
268 case '4':
269 case '5':
270 case '6':
271 case '7':
272 case '8':
273 case '9':
274 wide = 10 * wide + *fmt - '0';
275 break;
277 case '-':
278 left = 0;
279 break;
281 default:
282 *outb++ = *fmt;
283 cont = 0;
284 break;
287 fmt++;
289 va_end(ap);
293 * lprint(long-integer) send binary integer to output buffer
294 * long integer;
296 * +---------+---------+---------+---------+
297 * | high | | | low |
298 * | order | | | order |
299 * | byte | | | byte |
300 * +---------+---------+---------+---------+
301 * 31 --- 24 23 --- 16 15 --- 8 7 --- 0
303 * The save order is low order first, to high order (4 bytes total)
304 * and is written to be system independent.
305 * No checking for output buffer overflow is done, but flushes if needed!
306 * Returns nothing of value.
308 void
309 lprint(long x)
311 if (lpnt >= lpend)
312 lflush();
313 *lpnt++ = 255 & x;
314 *lpnt++ = 255 & (x >> 8);
315 *lpnt++ = 255 & (x >> 16);
316 *lpnt++ = 255 & (x >> 24);
320 * lwrite(buf,len) write a buffer to the output buffer
321 * char *buf;
322 * int len;
324 * Enter with the address and number of bytes to write out
325 * Returns nothing of value
327 void
328 lwrite(char *buf, int len)
330 char *str;
331 int num2;
333 if (len > 399) { /* don't copy data if can just write it */
334 #ifdef EXTRA
335 c[BYTESOUT] += len;
336 #endif
338 #ifndef VT100
339 for (str = buf; len > 0; --len)
340 lprc(*str++);
341 #else /* VT100 */
342 lflush();
343 write(io_outfd, buf, len);
344 #endif /* VT100 */
345 } else
346 while (len) {
347 if (lpnt >= lpend) /* if buffer is full flush it */
348 lflush();
349 num2 = lpbuf + BUFBIG - lpnt; /* # bytes left in output buffer */
350 if (num2 > len)
351 num2 = len;
352 str = lpnt;
353 len -= num2;
354 while (num2--) /* copy in the bytes */
355 *str++ = *buf++;
356 lpnt = str;
361 * long lgetc() Read one character from input buffer
363 * Returns 0 if EOF, otherwise the character
365 long
366 lgetc(void)
368 int i;
369 if (ipoint != iepoint)
370 return (inbuffer[ipoint++]);
371 if (iepoint != MAXIBUF)
372 return (0);
373 if ((i = read(io_infd, inbuffer, MAXIBUF)) <= 0) {
374 if (i != 0)
375 write(1, "error reading from input file\n", 30);
376 iepoint = ipoint = 0;
377 return (0);
379 ipoint = 1;
380 iepoint = i;
381 return (*inbuffer);
385 * long lrint_x() Read one integer from input buffer
387 * +---------+---------+---------+---------+
388 * | high | | | low |
389 * | order | | | order |
390 * | byte | | | byte |
391 * +---------+---------+---------+---------+
392 * 31 --- 24 23 --- 16 15 --- 8 7 --- 0
394 * The save order is low order first, to high order (4 bytes total)
395 * Returns the int read
397 long
398 lrint_x(void)
400 unsigned long i;
401 i = 255 & lgetc();
402 i |= (255 & lgetc()) << 8;
403 i |= (255 & lgetc()) << 16;
404 i |= (255 & lgetc()) << 24;
405 return (i);
409 * lrfill(address,number) put input bytes into a buffer
410 * char *address;
411 * int number;
413 * Reads "number" bytes into the buffer pointed to by "address".
414 * Returns nothing of value
416 void
417 lrfill(char *adr, int num)
419 char *pnt;
420 int num2;
421 while (num) {
422 if (iepoint == ipoint) {
423 if (num > 5) { /* fast way */
424 if (read(io_infd, adr, num) != num)
425 write(2, "error reading from input file\n", 30);
426 num = 0;
427 } else {
428 *adr++ = lgetc();
429 --num;
431 } else {
432 num2 = iepoint - ipoint; /* # of bytes left in the buffer */
433 if (num2 > num)
434 num2 = num;
435 pnt = inbuffer + ipoint;
436 num -= num2;
437 ipoint += num2;
438 while (num2--)
439 *adr++ = *pnt++;
445 * char *lgetw() Get a whitespace ended word from input
447 * Returns pointer to a buffer that contains word. If EOF, returns a NULL
449 char *
450 lgetw(void)
452 char *lgp, cc;
453 int n = LINBUFSIZE, quote = 0;
454 lgp = lgetwbuf;
456 cc = lgetc();
457 while ((cc <= 32) && (cc > '\0')); /* eat whitespace */
458 for (;; --n, cc = lgetc()) {
459 if ((cc == '\0') && (lgp == lgetwbuf)) /* EOF */
460 return (NULL);
461 if ((n <= 1) || ((cc <= 32) && (quote == 0))) {
462 *lgp = '\0';
463 return (lgetwbuf);
465 if (cc != '"')
466 *lgp++ = cc;
467 else
468 quote ^= 1;
473 * char *lgetl() Function to read in a line ended by newline or EOF
475 * Returns pointer to a buffer that contains the line. If EOF, returns NULL
477 char *
478 lgetl(void)
480 int i = LINBUFSIZE, ch;
481 char *str = lgetwbuf;
482 for (;; --i) {
483 if ((*str++ = ch = lgetc()) == '\0') {
484 if (str == lgetwbuf + 1) /* EOF */
485 return (NULL);
487 *str = 0;
488 return (lgetwbuf); /* line ended by EOF */
490 if ((ch == '\n') || (i <= 1)) /* line ended by \n */
491 goto ot;
496 * lcreat(filename) Create a new file for write
497 * char *filename;
499 * lcreat(NULL); means to the terminal
500 * Returns -1 if error, otherwise the file descriptor opened.
503 lcreat(char *str)
505 lpnt = lpbuf;
506 lpend = lpbuf + BUFBIG;
507 if (str == NULL)
508 return (io_outfd = 1);
509 if ((io_outfd = creat(str, 0644)) < 0) {
510 io_outfd = 1;
511 lprintf("error creating file <%s>\n", str);
512 lflush();
513 return (-1);
515 return (io_outfd);
519 * lopen(filename) Open a file for read
520 * char *filename;
522 * lopen(0) means from the terminal
523 * Returns -1 if error, otherwise the file descriptor opened.
526 lopen(char *str)
528 ipoint = iepoint = MAXIBUF;
529 if (str == NULL)
530 return (io_infd = 0);
531 if ((io_infd = open(str, O_RDONLY)) < 0) {
532 lwclose();
533 io_outfd = 1;
534 lpnt = lpbuf;
535 return (-1);
537 return (io_infd);
541 * lappend(filename) Open for append to an existing file
542 * char *filename;
544 * lappend(0) means to the terminal
545 * Returns -1 if error, otherwise the file descriptor opened.
548 lappend(char *str)
550 lpnt = lpbuf;
551 lpend = lpbuf + BUFBIG;
552 if (str == NULL)
553 return (io_outfd = 1);
554 if ((io_outfd = open(str, O_RDWR)) < 0) {
555 io_outfd = 1;
556 return (-1);
558 lseek(io_outfd, 0, SEEK_END); /* seek to end of file */
559 return (io_outfd);
563 * lrclose() close the input file
565 * Returns nothing of value.
567 void
568 lrclose(void)
570 if (io_infd > 0)
571 close(io_infd);
575 * lwclose() close output file flushing if needed
577 * Returns nothing of value.
579 void
580 lwclose(void)
582 lflush();
583 if (io_outfd > 2)
584 close(io_outfd);
588 * lprcat(string) append a string to the output buffer
589 * avoids calls to lprintf (time consuming)
591 void
592 lprcat(const char *str)
594 char *str2;
595 if (lpnt >= lpend)
596 lflush();
597 str2 = lpnt;
598 while ((*str2++ = *str++) != '\0')
599 continue;
600 lpnt = str2 - 1;
603 #ifdef VT100
605 * cursor(x,y) Subroutine to set the cursor position
607 * x and y are the cursor coordinates, and lpbuff is the output buffer where
608 * escape sequence will be placed.
610 static const char *y_num[]= { "\33[","\33[","\33[2","\33[3","\33[4","\33[5","\33[6",
611 "\33[7","\33[8","\33[9","\33[10","\33[11","\33[12","\33[13","\33[14",
612 "\33[15","\33[16","\33[17","\33[18","\33[19","\33[20","\33[21","\33[22",
613 "\33[23","\33[24" };
615 static const char *x_num[]= { "H","H",";2H",";3H",";4H",";5H",";6H",";7H",";8H",";9H",
616 ";10H",";11H",";12H",";13H",";14H",";15H",";16H",";17H",";18H",";19H",
617 ";20H",";21H",";22H",";23H",";24H",";25H",";26H",";27H",";28H",";29H",
618 ";30H",";31H",";32H",";33H",";34H",";35H",";36H",";37H",";38H",";39H",
619 ";40H",";41H",";42H",";43H",";44H",";45H",";46H",";47H",";48H",";49H",
620 ";50H",";51H",";52H",";53H",";54H",";55H",";56H",";57H",";58H",";59H",
621 ";60H",";61H",";62H",";63H",";64H",";65H",";66H",";67H",";68H",";69H",
622 ";70H",";71H",";72H",";73H",";74H",";75H",";76H",";77H",";78H",";79H",
623 ";80H" };
625 void
626 cursor(int x, int y)
628 char *p;
629 if (lpnt >= lpend)
630 lflush();
632 p = y_num[y]; /* get the string to print */
633 while (*p)
634 *lpnt++ = *p++; /* print the string */
636 p = x_num[x]; /* get the string to print */
637 while (*p)
638 *lpnt++ = *p++; /* print the string */
640 #else /* VT100 */
642 * cursor(x,y) Put cursor at specified coordinates staring at [1,1] (termcap)
644 void
645 cursor(int x, int y)
647 if (lpnt >= lpend)
648 lflush();
650 *lpnt++ = CURSOR;
651 *lpnt++ = x;
652 *lpnt++ = y;
654 #endif /* VT100 */
657 * Routine to position cursor at beginning of 24th line
659 void
660 cursors(void)
662 cursor(1, 24);
665 #ifndef VT100
667 * Warning: ringing the bell is control code 7. Don't use in defines.
668 * Don't change the order of these defines.
669 * Also used in helpfiles. Codes used in helpfiles should be \E[1 to \E[7 with
670 * obvious meanings.
673 static char cap[256];
674 char *CM, *CE, *CD, *CL, *SO, *SE, *AL, *DL;/* Termcap capabilities */
675 static char *outbuf = 0; /* translated output buffer */
678 * init_term() Terminal initialization -- setup termcap info
680 void
681 init_term(void)
683 char termbuf[1024];
684 char *capptr = cap + 10;
685 char *term;
687 switch (tgetent(termbuf, term = getenv("TERM"))) {
688 case -1:
689 write(2, "Cannot open termcap file.\n", 26);
690 exit(1);
691 case 0:
692 write(2, "Cannot find entry of ", 21);
693 write(2, term, strlen(term));
694 write(2, " in termcap\n", 12);
695 exit(1);
698 CM = tgetstr("cm", &capptr); /* Cursor motion */
699 CE = tgetstr("ce", &capptr); /* Clear to eoln */
700 CL = tgetstr("cl", &capptr); /* Clear screen */
702 /* OPTIONAL */
703 AL = tgetstr("al", &capptr); /* Insert line */
704 DL = tgetstr("dl", &capptr); /* Delete line */
705 SO = tgetstr("so", &capptr); /* Begin standout mode */
706 SE = tgetstr("se", &capptr); /* End standout mode */
707 CD = tgetstr("cd", &capptr); /* Clear to end of display */
709 if (!CM) { /* can't find cursor motion entry */
710 write(2, "Sorry, for a ", 13);
711 write(2, term, strlen(term));
712 write(2, ", I can't find the cursor motion entry in termcap\n", 50);
713 exit(1);
715 if (!CE) { /* can't find clear to end of line entry */
716 write(2, "Sorry, for a ", 13);
717 write(2, term, strlen(term));
718 write(2, ", I can't find the clear to end of line entry in termcap\n", 57);
719 exit(1);
721 if (!CL) { /* can't find clear entire screen entry */
722 write(2, "Sorry, for a ", 13);
723 write(2, term, strlen(term));
724 write(2, ", I can't find the clear entire screen entry in termcap\n", 56);
725 exit(1);
727 /* get memory for decoded output buffer*/
728 if ((outbuf = malloc(BUFBIG + 16)) == 0) {
729 write(2, "Error malloc'ing memory for decoded output buffer\n", 50);
730 died(-285); /* malloc() failure */
733 #endif /* VT100 */
736 * cl_line(x,y) Clear the whole line indicated by 'y' and leave cursor at [x,y]
738 void
739 cl_line(int x, int y)
741 #ifdef VT100
742 cursor(x, y);
743 lprcat("\33[2K");
744 #else /* VT100 */
745 cursor(1, y);
746 *lpnt++ = CL_LINE;
747 cursor(x, y);
748 #endif /* VT100 */
752 * cl_up(x,y) Clear screen from [x,1] to current position. Leave cursor at [x,y]
754 void
755 cl_up(int x, int y)
757 #ifdef VT100
758 cursor(x, y);
759 lprcat("\33[1J\33[2K");
760 #else /* VT100 */
761 int i;
762 cursor(1, 1);
763 for (i = 1; i <= y; i++) {
764 *lpnt++ = CL_LINE;
765 *lpnt++ = '\n';
767 cursor(x, y);
768 #endif /* VT100 */
772 * cl_dn(x,y) Clear screen from [1,y] to end of display. Leave cursor at [x,y]
774 void
775 cl_dn(int x, int y)
777 #ifdef VT100
778 cursor(x, y);
779 lprcat("\33[J\33[2K");
780 #else /* VT100 */
781 int i;
782 cursor(1, y);
783 if (!CD) {
784 *lpnt++ = CL_LINE;
785 for (i = y; i <= 24; i++) {
786 *lpnt++ = CL_LINE;
787 if (i != 24)
788 *lpnt++ = '\n';
790 cursor(x, y);
791 } else
792 *lpnt++ = CL_DOWN;
793 cursor(x, y);
794 #endif /* VT100 */
798 * standout(str) Print the argument string in inverse video (standout mode).
800 void
801 standout(const char *str)
803 #ifdef VT100
804 setbold();
805 while (*str)
806 *lpnt++ = *str++;
807 resetbold();
808 #else /* VT100 */
809 *lpnt++ = ST_START;
810 while (*str)
811 *lpnt++ = *str++;
812 *lpnt++ = ST_END;
813 #endif /* VT100 */
817 * set_score_output() Called when output should be literally printed.
819 void
820 set_score_output(void)
822 enable_scroll = -1;
826 * lflush() Flush the output buffer
828 * Returns nothing of value.
829 * for termcap version: Flush output in output buffer according to output
830 * status as indicated by `enable_scroll'
832 #ifndef VT100
833 static int scrline = 18; /* line # for wraparound instead of scrolling if no DL */
835 void
836 lflush(void)
838 int lpoint;
839 char *str;
840 static int curx = 0;
841 static int cury = 0;
843 if ((lpoint = lpnt - lpbuf) > 0) {
844 #ifdef EXTRA
845 c[BYTESOUT] += lpoint;
846 #endif
847 if (enable_scroll <= -1) {
848 flush_buf();
849 if (write(io_outfd, lpbuf, lpoint) != lpoint)
850 write(2, "error writing to output file\n", 29);
851 lpnt = lpbuf; /* point back to beginning of buffer */
852 return;
854 for (str = lpbuf; str < lpnt; str++) {
855 if (*str >= 32) {
856 putchr(*str);
857 curx++;
858 } else
859 switch (*str) {
860 case CLEAR:
861 tputs(CL, 0, putchr);
862 curx = cury = 0;
863 break;
865 case CL_LINE:
866 tputs(CE, 0, putchr);
867 break;
869 case CL_DOWN:
870 tputs(CD, 0, putchr);
871 break;
873 case ST_START:
874 tputs(SO, 0, putchr);
875 break;
877 case ST_END:
878 tputs(SE, 0, putchr);
879 break;
881 case CURSOR:
882 curx = *++str - 1;
883 cury = *++str - 1;
884 tputs(tgoto(CM, curx, cury), 0, putchr);
885 break;
887 case '\n':
888 if ((cury == 23) && enable_scroll) {
889 if (!DL || !AL) { /* wraparound or scroll? */
890 if (++scrline > 23)
891 scrline = 19;
893 if (++scrline > 23)
894 scrline = 19;
895 tputs(tgoto(CM, 0, scrline), 0, putchr);
896 tputs(CE, 0, putchr);
898 if (--scrline < 19)
899 scrline = 23;
900 tputs(tgoto(CM, 0, scrline), 0, putchr);
901 tputs(CE, 0, putchr);
902 } else {
903 tputs(tgoto(CM, 0, 19), 0, putchr);
904 tputs(DL, 0, putchr);
905 tputs(tgoto(CM, 0, 23), 0, putchr);
907 } else {
908 putchr('\n');
909 cury++;
911 curx = 0;
912 break;
914 default:
915 putchr(*str);
916 curx++;
920 lpnt = lpbuf;
921 flush_buf(); /* flush real output buffer now */
923 #else /* VT100 */
925 * lflush() flush the output buffer
927 * Returns nothing of value.
929 void
930 lflush(void)
932 int lpoint;
933 if ((lpoint = lpnt - lpbuf) > 0) {
934 #ifdef EXTRA
935 c[BYTESOUT] += lpoint;
936 #endif
937 if (write(io_outfd, lpbuf, lpoint) != lpoint)
938 write(2, "error writing to output file\n", 29);
940 lpnt = lpbuf; /* point back to beginning of buffer */
942 #endif /* VT100 */
944 #ifndef VT100
945 static int pindex = 0;
947 * putchr(ch) Print one character in decoded output buffer.
949 static int
950 putchr(int ch)
952 outbuf[pindex++] = ch;
953 if (pindex >= BUFBIG)
954 flush_buf();
955 return (0);
959 * flush_buf() Flush buffer with decoded output.
961 static void
962 flush_buf(void)
964 if (pindex)
965 write(io_outfd, outbuf, pindex);
966 pindex = 0;
970 * char *tmcapcnv(sd,ss) Routine to convert VT100 escapes to termcap format
972 * Processes only the \33[#m sequence (converts . files for termcap use
974 char *
975 tmcapcnv(char *sd, char *ss)
977 int tmstate = 0; /* 0=normal, 1=\33 2=[ 3=# */
978 char tmdigit = 0; /* the # in \33[#m */
979 while (*ss) {
980 switch (tmstate) {
981 case 0:
982 if (*ss == '\33') {
983 tmstate++;
984 break;
986 ign: *sd++ = *ss;
987 ign2: tmstate = 0;
988 break;
989 case 1:
990 if (*ss != '[')
991 goto ign;
992 tmstate++;
993 break;
994 case 2:
995 if (isdigit((int)*ss)) {
996 tmdigit = *ss - '0';
997 tmstate++;
998 break;
1000 if (*ss == 'm') {
1001 *sd++ = ST_END;
1002 goto ign2;
1004 goto ign;
1005 case 3:
1006 if (*ss == 'm') {
1007 if (tmdigit)
1008 *sd++ = ST_START;
1009 else
1010 *sd++ = ST_END;
1011 goto ign2;
1013 default:
1014 goto ign;
1016 ss++;
1018 *sd = 0; /* NULL terminator */
1019 return (sd);
1021 #endif /* VT100 */
1024 * beep() Routine to emit a beep if enabled (see no-beep in .larnopts)
1026 void
1027 beep(void)
1029 if (!nobeep)
1030 *lpnt++ = '\7';