1: /* $Header: term.c,v 4.3.1.3 85/09/10 11:05:23 lwall Exp $ 2: * 3: * $Log: term.c,v $ 4: * Revision 4.3.1.3 85/09/10 11:05:23 lwall 5: * Improved %m in in_char(). 6: * 7: * Revision 4.3.1.2 85/05/16 16:45:35 lwall 8: * Forced \r to \n on input. 9: * Fix for terminfo braindamage regarding bc emulation. 10: * 11: * Revision 4.3.1.1 85/05/10 11:41:03 lwall 12: * Branch for patches. 13: * 14: * Revision 4.3 85/05/01 11:51:10 lwall 15: * Baseline for release with 4.3bsd. 16: * 17: */ 18: 19: #include "EXTERN.h" 20: #include "common.h" 21: #include "util.h" 22: #include "final.h" 23: #include "help.h" 24: #include "cheat.h" 25: #include "intrp.h" 26: #include "INTERN.h" 27: #include "term.h" 28: 29: char ERASECH; /* rubout character */ 30: char KILLCH; /* line delete character */ 31: char tcarea[TCSIZE]; /* area for "compiled" termcap strings */ 32: 33: /* guarantee capability pointer != Nullch */ 34: /* (I believe terminfo will ignore the &tmpaddr argument.) */ 35: 36: #define Tgetstr(key) ((tmpstr = tgetstr(key,&tmpaddr)) ? tmpstr : nullstr) 37: 38: #ifdef PUSHBACK 39: struct keymap { 40: char km_type[128]; 41: union km_union { 42: struct keymap *km_km; 43: char *km_str; 44: } km_ptr[128]; 45: }; 46: 47: #define KM_NOTHIN 0 48: #define KM_STRING 1 49: #define KM_KEYMAP 2 50: #define KM_BOGUS 3 51: 52: #define KM_TMASK 3 53: #define KM_GSHIFT 4 54: #define KM_GMASK 7 55: 56: typedef struct keymap KEYMAP; 57: 58: KEYMAP *topmap INIT(Null(KEYMAP*)); 59: 60: void mac_init(); 61: KEYMAP *newkeymap(); 62: void show_keymap(); 63: void pushstring(); 64: #endif 65: 66: /* terminal initialization */ 67: 68: void 69: term_init() 70: { 71: savetty(); /* remember current tty state */ 72: 73: #ifdef TERMIO 74: ospeed = _tty.c_cflag & CBAUD; /* for tputs() */ 75: ERASECH = _tty.c_cc[VERASE]; /* for finish_command() */ 76: KILLCH = _tty.c_cc[VKILL]; /* for finish_command() */ 77: #else 78: ospeed = _tty.sg_ospeed; /* for tputs() */ 79: ERASECH = _tty.sg_erase; /* for finish_command() */ 80: KILLCH = _tty.sg_kill; /* for finish_command() */ 81: #endif 82: 83: /* The following could be a table but I can't be sure that there isn't */ 84: /* some degree of sparsity out there in the world. */ 85: 86: switch (ospeed) { /* 1 second of padding */ 87: #ifdef BEXTA 88: case BEXTA: just_a_sec = 1920; break; 89: #else 90: #ifdef B19200 91: case B19200: just_a_sec = 1920; break; 92: #endif 93: #endif 94: case B9600: just_a_sec = 960; break; 95: case B4800: just_a_sec = 480; break; 96: case B2400: just_a_sec = 240; break; 97: case B1800: just_a_sec = 180; break; 98: case B1200: just_a_sec = 120; break; 99: case B600: just_a_sec = 60; break; 100: case B300: just_a_sec = 30; break; 101: /* do I really have to type the rest of this??? */ 102: case B200: just_a_sec = 20; break; 103: case B150: just_a_sec = 15; break; 104: case B134: just_a_sec = 13; break; 105: case B110: just_a_sec = 11; break; 106: case B75: just_a_sec = 8; break; 107: case B50: just_a_sec = 5; break; 108: default: just_a_sec = 960; break; 109: /* if we are running detached I */ 110: } /* don't want to know about it! */ 111: } 112: 113: /* set terminal characteristics */ 114: 115: void 116: term_set(tcbuf) 117: char *tcbuf; /* temp area for "uncompiled" termcap entry */ 118: { 119: char *tmpaddr; /* must not be register */ 120: register char *tmpstr; 121: char *tgetstr(); 122: char *s; 123: int status; 124: 125: #ifdef PENDING 126: #ifndef FIONREAD 127: /* do no delay reads on something that always gets closed on exit */ 128: 129: devtty = open("/dev/tty",0); 130: if (devtty < 0) { 131: printf(cantopen,"/dev/tty") FLUSH; 132: finalize(1); 133: } 134: fcntl(devtty,F_SETFL,O_NDELAY); 135: #endif 136: #endif 137: 138: /* get all that good termcap stuff */ 139: 140: #ifdef HAVETERMLIB 141: status = tgetent(tcbuf,getenv("TERM")); /* get termcap entry */ 142: if (status < 1) { 143: #ifdef VERBOSE 144: printf("No termcap %s found.\n", status ? "file" : "entry") FLUSH; 145: #else 146: fputs("Termcap botch\n",stdout) FLUSH 147: #endif 148: finalize(1); 149: } 150: tmpaddr = tcarea; /* set up strange tgetstr pointer */ 151: s = Tgetstr("pc"); /* get pad character */ 152: PC = *s; /* get it where tputs wants it */ 153: if (!tgetflag("bs")) { /* is backspace not used? */ 154: BC = Tgetstr("bc"); /* find out what is */ 155: if (BC == nullstr) /* terminfo grok's 'bs' but not 'bc' */ 156: BC = Tgetstr("le"); 157: } else 158: BC = "\b"; /* make a backspace handy */ 159: UP = Tgetstr("up"); /* move up a line */ 160: if (!*UP) /* no UP string? */ 161: marking = 0; /* disable any marking */ 162: if (muck_up_clear) /* this is for weird HPs */ 163: CL = "\n\n\n\n"; 164: else 165: CL = Tgetstr("cl"); /* get clear string */ 166: CE = Tgetstr("ce"); /* clear to end of line string */ 167: #ifdef CLEAREOL 168: CM = Tgetstr("cm"); /* cursor motion - PWP */ 169: HO = Tgetstr("ho"); /* home cursor if no CM - PWP */ 170: CD = Tgetstr("cd"); /* clear to end of display - PWP */ 171: if (!*CE || !*CD || (!*CM && !*HO)) /* can we CE, CD, and home? */ 172: can_home_clear = FALSE; /* no, so disable use of clear eol */ 173: #endif CLEAREOL 174: SO = Tgetstr("so"); /* begin standout */ 175: SE = Tgetstr("se"); /* end standout */ 176: if ((SG = tgetnum("sg"))<0) 177: SG = 0; /* blanks left by SG, SE */ 178: US = Tgetstr("us"); /* start underline */ 179: UE = Tgetstr("ue"); /* end underline */ 180: if ((UG = tgetnum("ug"))<0) 181: UG = 0; /* blanks left by US, UE */ 182: if (*US) 183: UC = nullstr; /* UC must not be NULL */ 184: else 185: UC = Tgetstr("uc"); /* underline a character */ 186: if (!*US && !*UC) { /* no underline mode? */ 187: US = SO; /* substitute standout mode */ 188: UE = SE; 189: UG = SG; 190: } 191: LINES = tgetnum("li"); /* lines per page */ 192: COLS = tgetnum("co"); /* columns on page */ 193: AM = tgetflag("am"); /* terminal wraps automatically? */ 194: XN = tgetflag("xn"); /* then eats next newline? */ 195: VB = Tgetstr("vb"); 196: if (!*VB) 197: VB = "\007"; 198: CR = Tgetstr("cr"); 199: if (!*CR) { 200: if (tgetflag("nc") && *UP) { 201: CR = safemalloc((MEM_SIZE)strlen(UP)+2); 202: sprintf(CR,"%s\r",UP); 203: } 204: else 205: CR = "\r"; 206: } 207: #else 208: ?????? /* Roll your own... */ 209: #endif 210: if (LINES > 0) { /* is this a crt? */ 211: if (!initlines) /* no -i? */ 212: if (ospeed >= B9600) /* whole page at >= 9600 baud */ 213: initlines = LINES; 214: else if (ospeed >= B4800) /* 16 lines at 4800 */ 215: initlines = 16; 216: else /* otherwise just header */ 217: initlines = 8; 218: } 219: else { /* not a crt */ 220: LINES = 30000; /* so don't page */ 221: CL = "\n\n"; /* put a couple of lines between */ 222: if (!initlines) /* make initlines reasonable */ 223: initlines = 8; 224: } 225: if (COLS <= 0) 226: COLS = 80; 227: noecho(); /* turn off echo */ 228: crmode(); /* enter cbreak mode */ 229: 230: #ifdef PUSHBACK 231: mac_init(tcbuf); 232: #endif 233: } 234: 235: #ifdef PUSHBACK 236: void 237: mac_init(tcbuf) 238: char *tcbuf; 239: { 240: char tmpbuf[1024]; 241: 242: tmpfp = fopen(filexp(getval("RNMACRO",RNMACRO)),"r"); 243: if (tmpfp != Nullfp) { 244: while (fgets(tcbuf,1024,tmpfp) != Nullch) { 245: mac_line(tcbuf,tmpbuf,(sizeof tmpbuf)); 246: } 247: fclose(tmpfp); 248: } 249: } 250: 251: void 252: mac_line(line,tmpbuf,tbsize) 253: char *line; 254: char *tmpbuf; 255: int tbsize; 256: { 257: register char *s, *m; 258: register KEYMAP *curmap; 259: register int ch; 260: register int garbage = 0; 261: static char override[] = "\nkeymap overrides string\n"; 262: 263: if (topmap == Null(KEYMAP*)) 264: topmap = newkeymap(); 265: if (*line == '#' || *line == '\n') 266: return; 267: if (line[ch = strlen(line)-1] == '\n') 268: line[ch] = '\0'; 269: m = dointerp(tmpbuf,tbsize,line," \t"); 270: if (!*m) 271: return; 272: while (*m == ' ' || *m == '\t') m++; 273: for (s=tmpbuf,curmap=topmap; *s; s++) { 274: ch = *s & 0177; 275: if (s[1] == '+' && isdigit(s[2])) { 276: s += 2; 277: garbage = (*s & KM_GMASK) << KM_GSHIFT; 278: } 279: else 280: garbage = 0; 281: if (s[1]) { 282: if ((curmap->km_type[ch] & KM_TMASK) == KM_STRING) { 283: puts(override,stdout) FLUSH; 284: free(curmap->km_ptr[ch].km_str); 285: curmap->km_ptr[ch].km_str = Nullch; 286: } 287: curmap->km_type[ch] = KM_KEYMAP + garbage; 288: if (curmap->km_ptr[ch].km_km == Null(KEYMAP*)) 289: curmap->km_ptr[ch].km_km = newkeymap(); 290: curmap = curmap->km_ptr[ch].km_km; 291: } 292: else { 293: if ((curmap->km_type[ch] & KM_TMASK) == KM_KEYMAP) 294: puts(override,stdout) FLUSH; 295: else { 296: curmap->km_type[ch] = KM_STRING + garbage; 297: curmap->km_ptr[ch].km_str = savestr(m); 298: } 299: } 300: } 301: } 302: 303: KEYMAP* 304: newkeymap() 305: { 306: register int i; 307: register KEYMAP *map; 308: 309: #ifndef lint 310: map = (KEYMAP*)safemalloc(sizeof(KEYMAP)); 311: #else 312: map = Null(KEYMAP*); 313: #endif lint 314: for (i=127; i>=0; --i) { 315: map->km_ptr[i].km_km = Null(KEYMAP*); 316: map->km_type[i] = KM_NOTHIN; 317: } 318: return map; 319: } 320: 321: void 322: show_macros() 323: { 324: char prebuf[64]; 325: 326: if (topmap != Null(KEYMAP*)) { 327: print_lines("Macros:\n",STANDOUT); 328: *prebuf = '\0'; 329: show_keymap(topmap,prebuf); 330: } 331: } 332: 333: void 334: show_keymap(curmap,prefix) 335: register KEYMAP *curmap; 336: char *prefix; 337: { 338: register int i; 339: register char *next = prefix + strlen(prefix); 340: register int kt; 341: 342: for (i=0; i<128; i++) { 343: if (kt = curmap->km_type[i]) { 344: if (i < ' ') 345: sprintf(next,"^%c",i+64); 346: else if (i == ' ') 347: strcpy(next,"\\040"); 348: else if (i == 127) 349: strcpy(next,"^?"); 350: else 351: sprintf(next,"%c",i); 352: if ((kt >> KM_GSHIFT) & KM_GMASK) { 353: sprintf(cmd_buf,"+%d", (kt >> KM_GSHIFT) & KM_GMASK); 354: strcat(next,cmd_buf); 355: } 356: switch (kt & KM_TMASK) { 357: case KM_NOTHIN: 358: sprintf(cmd_buf,"%s %c\n",prefix,i); 359: print_lines(cmd_buf,NOMARKING); 360: break; 361: case KM_KEYMAP: 362: show_keymap(curmap->km_ptr[(char)i].km_km, prefix); 363: break; 364: case KM_STRING: 365: sprintf(cmd_buf,"%s %s\n",prefix,curmap->km_ptr[i].km_str); 366: print_lines(cmd_buf,NOMARKING); 367: break; 368: case KM_BOGUS: 369: sprintf(cmd_buf,"%s BOGUS\n",prefix); 370: print_lines(cmd_buf,STANDOUT); 371: break; 372: } 373: } 374: } 375: } 376: 377: #endif 378: 379: /* routine to pass to tputs */ 380: 381: char 382: putchr(ch) 383: register char ch; 384: { 385: putchar(ch); 386: #ifdef lint 387: ch = Null(char); 388: ch = ch; 389: #endif 390: } 391: 392: /* input the 2nd and succeeding characters of a multi-character command */ 393: /* returns TRUE if command finished, FALSE if they rubbed out first character */ 394: 395: bool 396: finish_command(donewline) 397: int donewline; 398: { 399: register char *s; 400: register bool quoteone = FALSE; 401: 402: s = buf; 403: if (s[1] != FINISHCMD) /* someone faking up a command? */ 404: return TRUE; 405: do { 406: top: 407: if (*s < ' ') { 408: putchar('^'); 409: putchar(*s | 64); 410: } 411: else if (*s == '\177') { 412: putchar('^'); 413: putchar('?'); 414: } 415: else 416: putchar(*s); /* echo previous character */ 417: s++; 418: re_read: 419: fflush(stdout); 420: getcmd(s); 421: if (quoteone) { 422: quoteone = FALSE; 423: continue; 424: } 425: if (errno || *s == Ctl('l')) { 426: *s = Ctl('r'); /* force rewrite on CONT */ 427: } 428: if (*s == '\033') { /* substitution desired? */ 429: #ifdef ESCSUBS 430: char tmpbuf[4], *cpybuf; 431: 432: tmpbuf[0] = '%'; 433: read_tty(&tmpbuf[1],1); 434: #ifdef RAWONLY 435: tmpbuf[1] &= 0177; 436: #endif 437: tmpbuf[2] = '\0'; 438: if (tmpbuf[1] == 'h') { 439: (void) help_subs(); 440: *s = '\0'; 441: reprint(); 442: goto re_read; 443: } 444: else if (tmpbuf[1] == '\033') { 445: *s = '\0'; 446: cpybuf = savestr(buf); 447: interp(buf, (sizeof buf), cpybuf); 448: free(cpybuf); 449: s = buf + strlen(buf); 450: reprint(); 451: goto re_read; 452: } 453: else { 454: interp(s,(sizeof buf) - (s-buf),tmpbuf); 455: fputs(s,stdout); 456: s += strlen(s); 457: } 458: goto re_read; 459: #else 460: notincl("^["); 461: *s = '\0'; 462: reprint(); 463: goto re_read; 464: #endif 465: } 466: else if (*s == ERASECH) { /* they want to rubout a char? */ 467: rubout(); 468: s--; /* discount the char rubbed out */ 469: if (*s < ' ' || *s == '\177') 470: rubout(); 471: if (s == buf) { /* entire string gone? */ 472: fflush(stdout); /* return to single char command mode */ 473: return FALSE; 474: } 475: else 476: goto re_read; 477: } 478: else if (*s == KILLCH) { /* wipe out the whole line? */ 479: while (s-- != buf) { /* emulate that many ERASEs */ 480: rubout(); 481: if (*s < ' ' || *s == '\177') 482: rubout(); 483: } 484: fflush(stdout); 485: return FALSE; /* return to single char mode */ 486: } 487: #ifdef WORDERASE 488: else if (*s == Ctl('w')) { /* wipe out one word? */ 489: *s-- = ' '; 490: while (!isspace(*s) || isspace(s[1])) { 491: rubout(); 492: if (s-- == buf) { 493: fflush(stdout); 494: return FALSE; /* return to single char mode */ 495: } 496: if (*s < ' ' || *s == '\177') 497: rubout(); 498: } 499: s++; 500: goto re_read; 501: } 502: #endif 503: else if (*s == Ctl('r')) { 504: *s = '\0'; 505: reprint(); 506: goto re_read; 507: } 508: else if (*s == Ctl('v')) { 509: putchar('^'); 510: backspace(); 511: fflush(stdout); 512: getcmd(s); 513: goto top; 514: } 515: else if (*s == '\\') { 516: quoteone = TRUE; 517: } 518: } while (*s != '\n'); /* till a newline (not echoed) */ 519: *s = '\0'; /* terminate the string nicely */ 520: if (donewline) 521: putchar('\n') FLUSH; 522: return TRUE; /* say we succeeded */ 523: } 524: 525: /* discard any characters typed ahead */ 526: 527: void 528: eat_typeahead() 529: { 530: #ifdef PUSHBACK 531: if (!typeahead && nextin==nextout) /* cancel only keyboard stuff */ 532: #else 533: if (!typeahead) 534: #endif 535: { 536: #ifdef PENDING 537: while (input_pending()) 538: read_tty(buf,sizeof(buf)); 539: #else /* this is probably v7 */ 540: ioctl(_tty_ch,TIOCSETP,&_tty); 541: #endif 542: } 543: } 544: 545: void 546: settle_down() 547: { 548: dingaling(); 549: fflush(stdout); 550: sleep(1); 551: #ifdef PUSHBACK 552: nextout = nextin; /* empty circlebuf */ 553: #endif 554: eat_typeahead(); 555: } 556: 557: #ifdef PUSHBACK 558: /* read a character from the terminal, with multi-character pushback */ 559: 560: int 561: read_tty(addr,size) 562: char *addr; 563: int size; 564: { 565: if (nextout != nextin) { 566: *addr = circlebuf[nextout++]; 567: nextout %= PUSHSIZE; 568: return 1; 569: } 570: else { 571: size = read(0,addr,size); 572: #ifdef RAWONLY 573: *addr &= 0177; 574: #endif 575: return size; 576: } 577: } 578: 579: #ifdef PENDING 580: #ifndef FIONREAD 581: int 582: circfill() 583: { 584: register int howmany = read(devtty,circlebuf+nextin,1); 585: 586: if (howmany) { 587: nextin += howmany; 588: nextin %= PUSHSIZE; 589: } 590: return howmany; 591: } 592: #endif PENDING 593: #endif FIONREAD 594: 595: void 596: pushchar(c) 597: char c; 598: { 599: nextout--; 600: if (nextout < 0) 601: nextout = PUSHSIZE - 1; 602: if (nextout == nextin) { 603: fputs("\npushback buffer overflow\n",stdout) FLUSH; 604: sig_catcher(0); 605: } 606: circlebuf[nextout] = c; 607: } 608: 609: #else PUSHBACK 610: #ifndef read_tty 611: /* read a character from the terminal, with hacks for O_NDELAY reads */ 612: 613: int 614: read_tty(addr,size) 615: char *addr; 616: int size; 617: { 618: if (is_input) { 619: *addr = pending_ch; 620: is_input = FALSE; 621: return 1; 622: } 623: else { 624: size = read(0,addr,size); 625: #ifdef RAWONLY 626: *addr &= 0177; 627: #endif 628: return size; 629: } 630: } 631: #endif read_tty 632: #endif PUSHBACK 633: 634: /* print an underlined string, one way or another */ 635: 636: void 637: underprint(s) 638: register char *s; 639: { 640: assert(UC); 641: if (*UC) { /* char by char underline? */ 642: while (*s) { 643: if (*s < ' ') { 644: putchar('^'); 645: backspace();/* back up over it */ 646: underchar();/* and do the underline */ 647: putchar(*s+64); 648: backspace();/* back up over it */ 649: underchar();/* and do the underline */ 650: } 651: else { 652: putchar(*s); 653: backspace();/* back up over it */ 654: underchar();/* and do the underline */ 655: } 656: s++; 657: } 658: } 659: else { /* start and stop underline */ 660: underline(); /* start underlining */ 661: while (*s) { 662: if (*s < ' ') { 663: putchar('^'); 664: putchar(*s+64); 665: } 666: else 667: putchar(*s); 668: s++; 669: } 670: un_underline(); /* stop underlining */ 671: } 672: } 673: 674: /* keep screen from flashing strangely on magic cookie terminals */ 675: 676: #ifdef NOFIREWORKS 677: void 678: no_sofire() 679: { 680: if (*UP && *SE) { /* should we disable fireworks? */ 681: putchar('\n'); 682: un_standout(); 683: up_line(); 684: carriage_return(); 685: } 686: } 687: 688: void 689: no_ulfire() 690: { 691: if (*UP && *US) { /* should we disable fireworks? */ 692: putchar('\n'); 693: un_underline(); 694: up_line(); 695: carriage_return(); 696: } 697: } 698: #endif 699: 700: /* get a character into a buffer */ 701: 702: void 703: getcmd(whatbuf) 704: register char *whatbuf; 705: { 706: #ifdef PUSHBACK 707: register KEYMAP *curmap; 708: register int i; 709: bool no_macros; 710: int times = 0; /* loop detector */ 711: char scrchar; 712: 713: tryagain: 714: curmap = topmap; 715: no_macros = (whatbuf != buf && nextin == nextout); 716: #endif 717: for (;;) { 718: int_count = 0; 719: errno = 0; 720: if (read_tty(whatbuf,1) < 0 && !errno) 721: errno = EINTR; 722: if (errno && errno != EINTR) { 723: perror(readerr); 724: sig_catcher(0); 725: } 726: #ifdef PUSHBACK 727: if (*whatbuf & 0200 || no_macros) { 728: *whatbuf &= 0177; 729: goto got_canonical; 730: } 731: if (curmap == Null(KEYMAP*)) 732: goto got_canonical; 733: for (i = (curmap->km_type[*whatbuf] >> KM_GSHIFT) & KM_GMASK; i; --i){ 734: read_tty(&scrchar,1); 735: } 736: switch (curmap->km_type[*whatbuf] & KM_TMASK) { 737: case KM_NOTHIN: /* no entry? */ 738: if (curmap == topmap) /* unmapped canonical */ 739: goto got_canonical; 740: settle_down(); 741: goto tryagain; 742: case KM_KEYMAP: /* another keymap? */ 743: curmap = curmap->km_ptr[*whatbuf].km_km; 744: assert(curmap != Null(KEYMAP*)); 745: break; 746: case KM_STRING: /* a string? */ 747: pushstring(curmap->km_ptr[*whatbuf].km_str); 748: if (++times > 20) { /* loop? */ 749: fputs("\nmacro loop?\n",stdout); 750: settle_down(); 751: } 752: no_macros = FALSE; 753: goto tryagain; 754: } 755: #else 756: #ifdef RAWONLY 757: *whatbuf &= 0177; 758: #endif 759: break; 760: #endif 761: } 762: 763: got_canonical: 764: #ifndef TERMIO 765: if (*whatbuf == '\r') 766: *whatbuf = '\n'; 767: #endif 768: if (whatbuf == buf) 769: whatbuf[1] = FINISHCMD; /* tell finish_command to work */ 770: } 771: 772: #ifdef PUSHBACK 773: void 774: pushstring(str) 775: char *str; 776: { 777: register int i; 778: char tmpbuf[PUSHSIZE]; 779: register char *s = tmpbuf; 780: 781: assert(str != Nullch); 782: interp(s,PUSHSIZE,str); 783: for (i = strlen(s)-1; i >= 0; --i) { 784: s[i] ^= 0200; 785: pushchar(s[i]); 786: } 787: } 788: #endif 789: 790: int 791: get_anything() 792: { 793: char tmpbuf[2]; 794: 795: reask_anything: 796: unflush_output(); /* disable any ^O in effect */ 797: standout(); 798: #ifdef VERBOSE 799: IF(verbose) 800: fputs("[Type space to continue] ",stdout); 801: ELSE 802: #endif 803: #ifdef TERSE 804: fputs("[MORE] ",stdout); 805: #endif 806: un_standout(); 807: fflush(stdout); 808: eat_typeahead(); 809: if (int_count) { 810: return -1; 811: } 812: collect_subjects(); /* loads subject cache until */ 813: /* input is pending */ 814: getcmd(tmpbuf); 815: if (errno || *tmpbuf == '\f') { 816: putchar('\n') FLUSH; /* if return from stop signal */ 817: goto reask_anything; /* give them a prompt again */ 818: } 819: if (*tmpbuf == 'h') { 820: #ifdef VERBOSE 821: IF(verbose) 822: fputs("\nType q to quit or space to continue.\n",stdout) FLUSH; 823: ELSE 824: #endif 825: #ifdef TERSE 826: fputs("\nq to quit, space to continue.\n",stdout) FLUSH; 827: #endif 828: goto reask_anything; 829: } 830: else if (*tmpbuf != ' ' && *tmpbuf != '\n') { 831: carriage_return(); 832: erase_eol(); /* erase the prompt */ 833: return *tmpbuf == 'q' ? -1 : *tmpbuf; 834: } 835: if (*tmpbuf == '\n') { 836: page_line = LINES - 1; 837: carriage_return(); 838: erase_eol(); 839: } 840: else { 841: page_line = 1; 842: if (erase_screen) /* -e? */ 843: clear(); /* clear screen */ 844: else { 845: carriage_return(); 846: erase_eol(); /* erase the prompt */ 847: } 848: } 849: return 0; 850: } 851: 852: void 853: in_char(prompt, newmode) 854: char *prompt; 855: char newmode; 856: { 857: char oldmode = mode; 858: 859: reask_in_char: 860: unflush_output(); /* disable any ^O in effect */ 861: fputs(prompt,stdout); 862: fflush(stdout); 863: eat_typeahead(); 864: mode = newmode; 865: getcmd(buf); 866: if (errno || *buf == '\f') { 867: putchar('\n') FLUSH; /* if return from stop signal */ 868: goto reask_in_char; /* give them a prompt again */ 869: } 870: mode = oldmode; 871: } 872: 873: int 874: print_lines(what_to_print,hilite) 875: char *what_to_print; 876: int hilite; 877: { 878: register char *s; 879: register int i; 880: 881: if (page_line < 0) /* they do not want to see this? */ 882: return -1; 883: for (s=what_to_print; *s; ) { 884: if (page_line >= LINES || int_count) { 885: if (i = -1, int_count || (i = get_anything())) { 886: page_line = -1; /* disable further print_lines */ 887: return i; 888: } 889: } 890: page_line++; 891: if (hilite == STANDOUT) { 892: #ifdef NOFIREWORKS 893: if (erase_screen) 894: no_sofire(); 895: #endif 896: standout(); 897: } 898: else if (hilite == UNDERLINE) { 899: #ifdef NOFIREWORKS 900: if (erase_screen) 901: no_ulfire(); 902: #endif 903: underline(); 904: } 905: for (i=0; i<COLS; i++) { 906: if (!*s) 907: break; 908: if (*s >= ' ') 909: putchar(*s); 910: else if (*s == '\t') { 911: putchar(*s); 912: i = ((i+8) & ~7) - 1; 913: } 914: else if (*s == '\n') { 915: i = 32000; 916: } 917: else { 918: i++; 919: putchar('^'); 920: putchar(*s + 64); 921: } 922: s++; 923: } 924: if (i) { 925: if (hilite == STANDOUT) 926: un_standout(); 927: else if (hilite == UNDERLINE) 928: un_underline(); 929: if (AM && i == COLS) 930: fflush(stdout); 931: else 932: putchar('\n') FLUSH; 933: } 934: } 935: return 0; 936: } 937: 938: void 939: page_init() 940: { 941: page_line = 1; 942: if (erase_screen) 943: clear(); 944: else 945: putchar('\n') FLUSH; 946: } 947: 948: void 949: pad(num) 950: int num; 951: { 952: register int i; 953: 954: for (i = num; i; --i) 955: putchar(PC); 956: fflush(stdout); 957: } 958: 959: /* echo the command just typed */ 960: 961: #ifdef VERIFY 962: void 963: printcmd() 964: { 965: if (verify && buf[1] == FINISHCMD) { 966: if (*buf < ' ') { 967: putchar('^'); 968: putchar(*buf | 64); 969: backspace(); 970: backspace(); 971: } 972: else { 973: putchar(*buf); 974: backspace(); 975: } 976: fflush(stdout); 977: } 978: } 979: #endif 980: 981: void 982: rubout() 983: { 984: backspace(); /* do the old backspace, */ 985: putchar(' '); /* space, */ 986: backspace(); /* backspace trick */ 987: } 988: 989: void 990: reprint() 991: { 992: register char *s; 993: 994: fputs("^R\n",stdout) FLUSH; 995: for (s = buf; *s; s++) { 996: if (*s < ' ') { 997: putchar('^'); 998: putchar(*s | 64); 999: } 1000: else 1001: putchar(*s); 1002: } 1003: } 1004: 1005: #ifdef CLEAREOL 1006: /* start of additions by Paul Placeway (PWP) */ 1007: 1008: void 1009: home_cursor() 1010: { 1011: char *tgoto(); 1012: 1013: if (!*HO) { /* no home sequence? */ 1014: if (!*CM) { /* no cursor motion either? */ 1015: fputs ("\n\n\n", stdout); 1016: return; /* forget it. */ 1017: } 1018: tputs (tgoto (CM, 0, 0), 1, putchr); /* go to home via CM */ 1019: return; 1020: } 1021: else { /* we have home sequence */ 1022: tputs (HO, 1, putchr); /* home via HO */ 1023: } 1024: } 1025: #endif CLEAREOL