|
|
1.1 ! root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.