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