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