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: 194: #ifdef TIOCGWINSZ 195: { struct winsize ws; 196: if (ioctl(0, TIOCGWINSZ, &ws) >= 0 && ws.ws_row > 0 && ws.ws_col > 0) { 197: LINES = ws.ws_row; 198: COLS = ws.ws_col; 199: } 200: } 201: #endif 202: 203: AM = tgetflag("am"); /* terminal wraps automatically? */ 204: XN = tgetflag("xn"); /* then eats next newline? */ 205: VB = Tgetstr("vb"); 206: if (!*VB) 207: VB = "\007"; 208: CR = Tgetstr("cr"); 209: if (!*CR) { 210: if (tgetflag("nc") && *UP) { 211: CR = safemalloc((MEM_SIZE)strlen(UP)+2); 212: sprintf(CR,"%s\r",UP); 213: } 214: else 215: CR = "\r"; 216: } 217: #else 218: ?????? /* Roll your own... */ 219: #endif 220: if (LINES > 0) { /* is this a crt? */ 221: if (!initlines) /* no -i? */ 222: if (ospeed >= B9600) /* whole page at >= 9600 baud */ 223: initlines = LINES; 224: else if (ospeed >= B4800) /* 16 lines at 4800 */ 225: initlines = 16; 226: else /* otherwise just header */ 227: initlines = 8; 228: } 229: else { /* not a crt */ 230: LINES = 30000; /* so don't page */ 231: CL = "\n\n"; /* put a couple of lines between */ 232: if (!initlines) /* make initlines reasonable */ 233: initlines = 8; 234: } 235: if (COLS <= 0) 236: COLS = 80; 237: noecho(); /* turn off echo */ 238: crmode(); /* enter cbreak mode */ 239: 240: #ifdef PUSHBACK 241: mac_init(tcbuf); 242: #endif 243: } 244: 245: #ifdef PUSHBACK 246: void 247: mac_init(tcbuf) 248: char *tcbuf; 249: { 250: char tmpbuf[1024]; 251: 252: tmpfp = fopen(filexp(getval("RNMACRO",RNMACRO)),"r"); 253: if (tmpfp != Nullfp) { 254: while (fgets(tcbuf,1024,tmpfp) != Nullch) { 255: mac_line(tcbuf,tmpbuf,(sizeof tmpbuf)); 256: } 257: fclose(tmpfp); 258: } 259: } 260: 261: void 262: mac_line(line,tmpbuf,tbsize) 263: char *line; 264: char *tmpbuf; 265: int tbsize; 266: { 267: register char *s, *m; 268: register KEYMAP *curmap; 269: register int ch; 270: register int garbage = 0; 271: static char override[] = "\nkeymap overrides string\n"; 272: 273: if (topmap == Null(KEYMAP*)) 274: topmap = newkeymap(); 275: if (*line == '#' || *line == '\n') 276: return; 277: if (line[ch = strlen(line)-1] == '\n') 278: line[ch] = '\0'; 279: m = dointerp(tmpbuf,tbsize,line," \t"); 280: if (!*m) 281: return; 282: while (*m == ' ' || *m == '\t') m++; 283: for (s=tmpbuf,curmap=topmap; *s; s++) { 284: ch = *s & 0177; 285: if (s[1] == '+' && isdigit(s[2])) { 286: s += 2; 287: garbage = (*s & KM_GMASK) << KM_GSHIFT; 288: } 289: else 290: garbage = 0; 291: if (s[1]) { 292: if ((curmap->km_type[ch] & KM_TMASK) == KM_STRING) { 293: puts(override,stdout) FLUSH; 294: free(curmap->km_ptr[ch].km_str); 295: curmap->km_ptr[ch].km_str = Nullch; 296: } 297: curmap->km_type[ch] = KM_KEYMAP + garbage; 298: if (curmap->km_ptr[ch].km_km == Null(KEYMAP*)) 299: curmap->km_ptr[ch].km_km = newkeymap(); 300: curmap = curmap->km_ptr[ch].km_km; 301: } 302: else { 303: if ((curmap->km_type[ch] & KM_TMASK) == KM_KEYMAP) 304: puts(override,stdout) FLUSH; 305: else { 306: curmap->km_type[ch] = KM_STRING + garbage; 307: curmap->km_ptr[ch].km_str = savestr(m); 308: } 309: } 310: } 311: } 312: 313: KEYMAP* 314: newkeymap() 315: { 316: register int i; 317: register KEYMAP *map; 318: 319: #ifndef lint 320: map = (KEYMAP*)safemalloc(sizeof(KEYMAP)); 321: #else 322: map = Null(KEYMAP*); 323: #endif lint 324: for (i=127; i>=0; --i) { 325: map->km_ptr[i].km_km = Null(KEYMAP*); 326: map->km_type[i] = KM_NOTHIN; 327: } 328: return map; 329: } 330: 331: void 332: show_macros() 333: { 334: char prebuf[64]; 335: 336: if (topmap != Null(KEYMAP*)) { 337: print_lines("Macros:\n",STANDOUT); 338: *prebuf = '\0'; 339: show_keymap(topmap,prebuf); 340: } 341: } 342: 343: void 344: show_keymap(curmap,prefix) 345: register KEYMAP *curmap; 346: char *prefix; 347: { 348: register int i; 349: register char *next = prefix + strlen(prefix); 350: register int kt; 351: 352: for (i=0; i<128; i++) { 353: if (kt = curmap->km_type[i]) { 354: if (i < ' ') 355: sprintf(next,"^%c",i+64); 356: else if (i == ' ') 357: strcpy(next,"\\040"); 358: else if (i == 127) 359: strcpy(next,"^?"); 360: else 361: sprintf(next,"%c",i); 362: if ((kt >> KM_GSHIFT) & KM_GMASK) { 363: sprintf(cmd_buf,"+%d", (kt >> KM_GSHIFT) & KM_GMASK); 364: strcat(next,cmd_buf); 365: } 366: switch (kt & KM_TMASK) { 367: case KM_NOTHIN: 368: sprintf(cmd_buf,"%s %c\n",prefix,i); 369: print_lines(cmd_buf,NOMARKING); 370: break; 371: case KM_KEYMAP: 372: show_keymap(curmap->km_ptr[(char)i].km_km, prefix); 373: break; 374: case KM_STRING: 375: sprintf(cmd_buf,"%s %s\n",prefix,curmap->km_ptr[i].km_str); 376: print_lines(cmd_buf,NOMARKING); 377: break; 378: case KM_BOGUS: 379: sprintf(cmd_buf,"%s BOGUS\n",prefix); 380: print_lines(cmd_buf,STANDOUT); 381: break; 382: } 383: } 384: } 385: } 386: 387: #endif 388: 389: /* routine to pass to tputs */ 390: 391: char 392: putchr(ch) 393: register char ch; 394: { 395: putchar(ch); 396: #ifdef lint 397: ch = Null(char); 398: ch = ch; 399: #endif 400: } 401: 402: /* input the 2nd and succeeding characters of a multi-character command */ 403: /* returns TRUE if command finished, FALSE if they rubbed out first character */ 404: 405: bool 406: finish_command(donewline) 407: int donewline; 408: { 409: register char *s; 410: register bool quoteone = FALSE; 411: 412: s = buf; 413: if (s[1] != FINISHCMD) /* someone faking up a command? */ 414: return TRUE; 415: do { 416: top: 417: if (*s < ' ') { 418: putchar('^'); 419: putchar(*s | 64); 420: } 421: else if (*s == '\177') { 422: putchar('^'); 423: putchar('?'); 424: } 425: else 426: putchar(*s); /* echo previous character */ 427: s++; 428: re_read: 429: fflush(stdout); 430: getcmd(s); 431: if (quoteone) { 432: quoteone = FALSE; 433: continue; 434: } 435: if (errno || *s == Ctl('l')) { 436: *s = Ctl('r'); /* force rewrite on CONT */ 437: } 438: if (*s == '\033') { /* substitution desired? */ 439: #ifdef ESCSUBS 440: char tmpbuf[4], *cpybuf; 441: 442: tmpbuf[0] = '%'; 443: read_tty(&tmpbuf[1],1); 444: #ifdef RAWONLY 445: tmpbuf[1] &= 0177; 446: #endif 447: tmpbuf[2] = '\0'; 448: if (tmpbuf[1] == 'h') { 449: (void) help_subs(); 450: *s = '\0'; 451: reprint(); 452: goto re_read; 453: } 454: else if (tmpbuf[1] == '\033') { 455: *s = '\0'; 456: cpybuf = savestr(buf); 457: interp(buf, (sizeof buf), cpybuf); 458: free(cpybuf); 459: s = buf + strlen(buf); 460: reprint(); 461: goto re_read; 462: } 463: else { 464: interp(s,(sizeof buf) - (s-buf),tmpbuf); 465: fputs(s,stdout); 466: s += strlen(s); 467: } 468: goto re_read; 469: #else 470: notincl("^["); 471: *s = '\0'; 472: reprint(); 473: goto re_read; 474: #endif 475: } 476: else if (*s == ERASECH) { /* they want to rubout a char? */ 477: rubout(); 478: s--; /* discount the char rubbed out */ 479: if (*s < ' ' || *s == '\177') 480: rubout(); 481: if (s == buf) { /* entire string gone? */ 482: fflush(stdout); /* return to single char command mode */ 483: return FALSE; 484: } 485: else 486: goto re_read; 487: } 488: else if (*s == KILLCH) { /* wipe out the whole line? */ 489: while (s-- != buf) { /* emulate that many ERASEs */ 490: rubout(); 491: if (*s < ' ' || *s == '\177') 492: rubout(); 493: } 494: fflush(stdout); 495: return FALSE; /* return to single char mode */ 496: } 497: #ifdef WORDERASE 498: else if (*s == Ctl('w')) { /* wipe out one word? */ 499: *s-- = ' '; 500: while (!isspace(*s) || isspace(s[1])) { 501: rubout(); 502: if (s-- == buf) { 503: fflush(stdout); 504: return FALSE; /* return to single char mode */ 505: } 506: if (*s < ' ' || *s == '\177') 507: rubout(); 508: } 509: s++; 510: goto re_read; 511: } 512: #endif 513: else if (*s == Ctl('r')) { 514: *s = '\0'; 515: reprint(); 516: goto re_read; 517: } 518: else if (*s == Ctl('v')) { 519: putchar('^'); 520: backspace(); 521: fflush(stdout); 522: getcmd(s); 523: goto top; 524: } 525: else if (*s == '\\') { 526: quoteone = TRUE; 527: } 528: } while (*s != '\n'); /* till a newline (not echoed) */ 529: *s = '\0'; /* terminate the string nicely */ 530: if (donewline) 531: putchar('\n') FLUSH; 532: return TRUE; /* say we succeeded */ 533: } 534: 535: /* discard any characters typed ahead */ 536: 537: void 538: eat_typeahead() 539: { 540: #ifdef PUSHBACK 541: if (!typeahead && nextin==nextout) /* cancel only keyboard stuff */ 542: #else 543: if (!typeahead) 544: #endif 545: { 546: #ifdef PENDING 547: while (input_pending()) 548: read_tty(buf,sizeof(buf)); 549: #else /* this is probably v7 */ 550: ioctl(_tty_ch,TIOCSETP,&_tty); 551: #endif 552: } 553: } 554: 555: void 556: settle_down() 557: { 558: dingaling(); 559: fflush(stdout); 560: sleep(1); 561: #ifdef PUSHBACK 562: nextout = nextin; /* empty circlebuf */ 563: #endif 564: eat_typeahead(); 565: } 566: 567: #ifdef PUSHBACK 568: /* read a character from the terminal, with multi-character pushback */ 569: 570: int 571: read_tty(addr,size) 572: char *addr; 573: int size; 574: { 575: if (nextout != nextin) { 576: *addr = circlebuf[nextout++]; 577: nextout %= PUSHSIZE; 578: return 1; 579: } 580: else { 581: size = read(0,addr,size); 582: #ifdef RAWONLY 583: *addr &= 0177; 584: #endif 585: return size; 586: } 587: } 588: 589: #ifdef PENDING 590: #ifndef FIONREAD 591: int 592: circfill() 593: { 594: register int howmany = read(devtty,circlebuf+nextin,1); 595: 596: if (howmany) { 597: nextin += howmany; 598: nextin %= PUSHSIZE; 599: } 600: return howmany; 601: } 602: #endif PENDING 603: #endif FIONREAD 604: 605: void 606: pushchar(c) 607: char c; 608: { 609: nextout--; 610: if (nextout < 0) 611: nextout = PUSHSIZE - 1; 612: if (nextout == nextin) { 613: fputs("\npushback buffer overflow\n",stdout) FLUSH; 614: sig_catcher(0); 615: } 616: circlebuf[nextout] = c; 617: } 618: 619: #else PUSHBACK 620: #ifndef read_tty 621: /* read a character from the terminal, with hacks for O_NDELAY reads */ 622: 623: int 624: read_tty(addr,size) 625: char *addr; 626: int size; 627: { 628: if (is_input) { 629: *addr = pending_ch; 630: is_input = FALSE; 631: return 1; 632: } 633: else { 634: size = read(0,addr,size); 635: #ifdef RAWONLY 636: *addr &= 0177; 637: #endif 638: return size; 639: } 640: } 641: 642: #endif read_tty 643: pushchar(c) char c; { return;} 644: #endif PUSHBACK 645: 646: /* print an underlined string, one way or another */ 647: 648: void 649: underprint(s) 650: register char *s; 651: { 652: assert(UC); 653: if (*UC) { /* char by char underline? */ 654: while (*s) { 655: if (*s < ' ') { 656: putchar('^'); 657: backspace();/* back up over it */ 658: underchar();/* and do the underline */ 659: putchar(*s+64); 660: backspace();/* back up over it */ 661: underchar();/* and do the underline */ 662: } 663: else { 664: putchar(*s); 665: backspace();/* back up over it */ 666: underchar();/* and do the underline */ 667: } 668: s++; 669: } 670: } 671: else { /* start and stop underline */ 672: underline(); /* start underlining */ 673: while (*s) { 674: if (*s < ' ') { 675: putchar('^'); 676: putchar(*s+64); 677: } 678: else 679: putchar(*s); 680: s++; 681: } 682: un_underline(); /* stop underlining */ 683: } 684: } 685: 686: /* keep screen from flashing strangely on magic cookie terminals */ 687: 688: #ifdef NOFIREWORKS 689: void 690: no_sofire() 691: { 692: if (*UP && *SE) { /* should we disable fireworks? */ 693: putchar('\n'); 694: un_standout(); 695: up_line(); 696: carriage_return(); 697: } 698: } 699: 700: void 701: no_ulfire() 702: { 703: if (*UP && *US) { /* should we disable fireworks? */ 704: putchar('\n'); 705: un_underline(); 706: up_line(); 707: carriage_return(); 708: } 709: } 710: #endif 711: 712: /* get a character into a buffer */ 713: 714: void 715: getcmd(whatbuf) 716: register char *whatbuf; 717: { 718: #ifdef PUSHBACK 719: register KEYMAP *curmap; 720: register int i; 721: bool no_macros; 722: int times = 0; /* loop detector */ 723: char scrchar; 724: 725: tryagain: 726: curmap = topmap; 727: no_macros = (whatbuf != buf && nextin == nextout); 728: #endif 729: for (;;) { 730: int_count = 0; 731: errno = 0; 732: if (read_tty(whatbuf,1) < 0 && !errno) 733: errno = EINTR; 734: if (errno && errno != EINTR) { 735: perror(readerr); 736: sig_catcher(0); 737: } 738: #ifdef PUSHBACK 739: if (*whatbuf & 0200 || no_macros) { 740: *whatbuf &= 0177; 741: goto got_canonical; 742: } 743: if (curmap == Null(KEYMAP*)) 744: goto got_canonical; 745: for (i = (curmap->km_type[*whatbuf] >> KM_GSHIFT) & KM_GMASK; i; --i){ 746: read_tty(&scrchar,1); 747: } 748: switch (curmap->km_type[*whatbuf] & KM_TMASK) { 749: case KM_NOTHIN: /* no entry? */ 750: if (curmap == topmap) /* unmapped canonical */ 751: goto got_canonical; 752: settle_down(); 753: goto tryagain; 754: case KM_KEYMAP: /* another keymap? */ 755: curmap = curmap->km_ptr[*whatbuf].km_km; 756: assert(curmap != Null(KEYMAP*)); 757: break; 758: case KM_STRING: /* a string? */ 759: pushstring(curmap->km_ptr[*whatbuf].km_str); 760: if (++times > 20) { /* loop? */ 761: fputs("\nmacro loop?\n",stdout); 762: settle_down(); 763: } 764: no_macros = FALSE; 765: goto tryagain; 766: } 767: #else 768: #ifdef RAWONLY 769: *whatbuf &= 0177; 770: #endif 771: break; 772: #endif 773: } 774: 775: got_canonical: 776: #ifndef TERMIO 777: if (*whatbuf == '\r') 778: *whatbuf = '\n'; 779: #endif 780: if (whatbuf == buf) 781: whatbuf[1] = FINISHCMD; /* tell finish_command to work */ 782: } 783: 784: #ifdef PUSHBACK 785: void 786: pushstring(str) 787: char *str; 788: { 789: register int i; 790: char tmpbuf[PUSHSIZE]; 791: register char *s = tmpbuf; 792: 793: assert(str != Nullch); 794: interp(s,PUSHSIZE,str); 795: for (i = strlen(s)-1; i >= 0; --i) { 796: s[i] ^= 0200; 797: pushchar(s[i]); 798: } 799: } 800: #endif 801: 802: int 803: get_anything() 804: { 805: char tmpbuf[2]; 806: 807: reask_anything: 808: unflush_output(); /* disable any ^O in effect */ 809: standout(); 810: #ifdef VERBOSE 811: IF(verbose) 812: fputs("[Type space to continue] ",stdout); 813: ELSE 814: #endif 815: #ifdef TERSE 816: fputs("[MORE] ",stdout); 817: #endif 818: un_standout(); 819: fflush(stdout); 820: eat_typeahead(); 821: if (int_count) { 822: return -1; 823: } 824: collect_subjects(); /* loads subject cache until */ 825: /* input is pending */ 826: getcmd(tmpbuf); 827: if (errno || *tmpbuf == '\f') { 828: putchar('\n') FLUSH; /* if return from stop signal */ 829: goto reask_anything; /* give them a prompt again */ 830: } 831: if (*tmpbuf == 'h') { 832: #ifdef VERBOSE 833: IF(verbose) 834: fputs("\nType q to quit or space to continue.\n",stdout) FLUSH; 835: ELSE 836: #endif 837: #ifdef TERSE 838: fputs("\nq to quit, space to continue.\n",stdout) FLUSH; 839: #endif 840: goto reask_anything; 841: } 842: else if (*tmpbuf != ' ' && *tmpbuf != '\n') { 843: carriage_return(); 844: erase_eol(); /* erase the prompt */ 845: return *tmpbuf == 'q' ? -1 : *tmpbuf; 846: } 847: if (*tmpbuf == '\n') { 848: page_line = LINES - 1; 849: carriage_return(); 850: erase_eol(); 851: } 852: else { 853: page_line = 1; 854: if (erase_screen) /* -e? */ 855: clear(); /* clear screen */ 856: else { 857: carriage_return(); 858: erase_eol(); /* erase the prompt */ 859: } 860: } 861: return 0; 862: } 863: 864: void 865: in_char(prompt, newmode) 866: char *prompt; 867: char newmode; 868: { 869: char oldmode = mode; 870: 871: reask_in_char: 872: unflush_output(); /* disable any ^O in effect */ 873: fputs(prompt,stdout); 874: fflush(stdout); 875: eat_typeahead(); 876: mode = newmode; 877: getcmd(buf); 878: if (errno || *buf == '\f') { 879: putchar('\n') FLUSH; /* if return from stop signal */ 880: goto reask_in_char; /* give them a prompt again */ 881: } 882: mode = oldmode; 883: } 884: 885: int 886: print_lines(what_to_print,hilite) 887: char *what_to_print; 888: int hilite; 889: { 890: register char *s; 891: register int i; 892: 893: if (page_line < 0) /* they do not want to see this? */ 894: return -1; 895: for (s=what_to_print; *s; ) { 896: if (page_line >= LINES || int_count) { 897: if (i = -1, int_count || (i = get_anything())) { 898: page_line = -1; /* disable further print_lines */ 899: return i; 900: } 901: } 902: page_line++; 903: if (hilite == STANDOUT) { 904: #ifdef NOFIREWORKS 905: if (erase_screen) 906: no_sofire(); 907: #endif 908: standout(); 909: } 910: else if (hilite == UNDERLINE) { 911: #ifdef NOFIREWORKS 912: if (erase_screen) 913: no_ulfire(); 914: #endif 915: underline(); 916: } 917: for (i=0; i<COLS; i++) { 918: if (!*s) 919: break; 920: if (*s >= ' ') 921: putchar(*s); 922: else if (*s == '\t') { 923: putchar(*s); 924: i = ((i+8) & ~7) - 1; 925: } 926: else if (*s == '\n') { 927: i = 32000; 928: } 929: else { 930: i++; 931: putchar('^'); 932: putchar(*s + 64); 933: } 934: s++; 935: } 936: if (i) { 937: if (hilite == STANDOUT) 938: un_standout(); 939: else if (hilite == UNDERLINE) 940: un_underline(); 941: if (AM && i == COLS) 942: fflush(stdout); 943: else 944: putchar('\n') FLUSH; 945: } 946: } 947: return 0; 948: } 949: 950: void 951: page_init() 952: { 953: page_line = 1; 954: if (erase_screen) 955: clear(); 956: else 957: putchar('\n') FLUSH; 958: } 959: 960: void 961: pad(num) 962: int num; 963: { 964: register int i; 965: 966: for (i = num; i; --i) 967: putchar(PC); 968: fflush(stdout); 969: } 970: 971: /* echo the command just typed */ 972: 973: #ifdef VERIFY 974: void 975: printcmd() 976: { 977: if (verify && buf[1] == FINISHCMD) { 978: if (*buf < ' ') { 979: putchar('^'); 980: putchar(*buf | 64); 981: backspace(); 982: backspace(); 983: } 984: else { 985: putchar(*buf); 986: backspace(); 987: } 988: fflush(stdout); 989: } 990: } 991: #endif 992: 993: void 994: rubout() 995: { 996: backspace(); /* do the old backspace, */ 997: putchar(' '); /* space, */ 998: backspace(); /* backspace trick */ 999: } 1000: 1001: void 1002: reprint() 1003: { 1004: register char *s; 1005: 1006: fputs("^R\n",stdout) FLUSH; 1007: for (s = buf; *s; s++) { 1008: if (*s < ' ') { 1009: putchar('^'); 1010: putchar(*s | 64); 1011: } 1012: else 1013: putchar(*s); 1014: } 1015: } 1016: 1017: #ifdef CLEAREOL 1018: /* start of additions by Paul Placeway (PWP) */ 1019: 1020: void 1021: home_cursor() 1022: { 1023: char *tgoto(); 1024: 1025: if (!*HO) { /* no home sequence? */ 1026: if (!*CM) { /* no cursor motion either? */ 1027: fputs ("\n\n\n", stdout); 1028: return; /* forget it. */ 1029: } 1030: tputs (tgoto (CM, 0, 0), 1, putchr); /* go to home via CM */ 1031: return; 1032: } 1033: else { /* we have home sequence */ 1034: tputs (HO, 1, putchr); /* home via HO */ 1035: } 1036: } 1037: #endif CLEAREOL