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