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

Defined functions

circfill defined in line 581; used 2 times
get_anything defined in line 790; used 6 times
getcmd defined in line 702; used 9 times
home_cursor defined in line 1008; used 3 times
mac_init defined in line 236; used 3 times
mac_line defined in line 251; used 3 times
newkeymap defined in line 303; used 3 times
no_sofire defined in line 677; used 4 times
no_ulfire defined in line 688; used 4 times
pad defined in line 948; used 6 times
print_lines defined in line 873; used 43 times
pushstring defined in line 773; used 2 times
putchr defined in line 381; used 3 times
read_tty defined in line 613; never used
reprint defined in line 989; used 5 times
rubout defined in line 981; used 7 times
show_keymap defined in line 333; used 3 times
show_macros defined in line 321; used 3 times
term_init defined in line 68; used 2 times
term_set defined in line 115; used 2 times
underprint defined in line 636; used 2 times

Defined variables

ERASECH defined in line 29; used 3 times
KILLCH defined in line 30; used 3 times
tcarea defined in line 31; used 1 times
topmap defined in line 58; used 7 times

Defined struct's

keymap defined in line 39; used 4 times
  • in line 42(2), 56(2)

Defined union's

km_union defined in line 41; never used

Defined typedef's

KEYMAP defined in line 56; used 17 times

Defined macros

KM_BOGUS defined in line 50; used 1 times
KM_GMASK defined in line 54; used 4 times
KM_GSHIFT defined in line 53; used 4 times
KM_KEYMAP defined in line 49; used 3 times
KM_NOTHIN defined in line 47; used 2 times
KM_STRING defined in line 48; used 3 times
KM_TMASK defined in line 52; used 4 times
Tgetstr defined in line 36; used 16 times
Last modified: 1985-11-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3129
Valid CSS Valid XHTML 1.0 Strict