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