disallow creation of files in removed directories
[unix-history] / usr / src / games / larn / io.c
CommitLineData
3bf4087a
KB
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)
65static int rawflg = 0;
66static 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 */
85typedef 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 */
93int lfd; /* output file numbers */
94int fd; /* input file numbers */
95static struct sgttyb ttx; /* storage for the tty modes */
96static int ipoint=MAXIBUF,iepoint=MAXIBUF; /* input buffering pointers */
97static 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 */
104setupvt100()
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 */
114clearvt100()
115 {
116 resetscroll(); clear(); sncbr(); /* system("stty -cbreak echo"); */
117 }
118
119/*
120 * getchar() Routine to read in one character from the terminal
121 */
122getchar()
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 */
138scbr()
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 */
148sncbr()
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 */
156newgame()
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*/
179lprintf(str)
180 char *str;
181 {
182 char *str2;
183 str2 = str;
184 str = str2; /* to make lint happy */
185 }
186/*VARARGS*/
187sprintf(str)
188 char *str;
189 {
190 char *str2;
191 str2 = str;
192 str = str2; /* to make lint happy */
193 }
194#else lint
195/*VARARGS*/
196lprintf(va_alist)
197va_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 */
281lprint(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 */
297lwrite(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 */
333long 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 */
359long 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 */
375lrfill(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 */
408char *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 */
427char *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 */
449lcreat(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 */
468lopen(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 */
487lappend(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 */
505lrclose()
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 */
515lwclose()
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 */
524lprcat(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 */
541static 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
546static 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
556cursor(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 */
572cursor (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 */
584cursors()
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
597static char cap[256];
598char *CM, *CE, *CD, *CL, *SO, *SE, *AL, *DL;/* Termcap capabilities */
599static char *outbuf=0; /* translated output buffer */
600
601int putchar ();
602
603/*
604 * init_term() Terminal initialization -- setup termcap info
605 */
606init_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 */
663cl_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 */
676cl_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 */
692cl_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 */
715standout(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 */
734set_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
747static int scrline=18; /* line # for wraparound instead of scrolling if no DL */
748lflush ()
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 */
834lflush()
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
850static int index=0;
851/*
852 * putchar(ch) Print one character in decoded output buffer.
853 */
854int putchar(c)
855int c;
856 {
857 outbuf[index++] = c;
858 if (index >= BUFBIG) flush_buf();
859 }
860
861/*
862 * flush_buf() Flush buffer with decoded output.
863 */
864flush_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 */
875char *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 */
912beep()
913 {
914 if (!nobeep) *lpnt++ = '\7';
915 }