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