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