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