Annotation of 43BSD/contrib/rn/term.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.