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

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

unix.superglobalmegacorp.com

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