Annotation of 3BSD/cmd/ex/ex_vget.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) 1979 Regents of the University of California */
                      2: #include "ex.h"
                      3: #include "ex_tty.h"
                      4: #include "ex_vis.h"
                      5: 
                      6: /*
                      7:  * Input routines for open/visual.
                      8:  * We handle upper case only terminals in visual and reading from the
                      9:  * echo area here as well as notification on large changes
                     10:  * which appears in the echo area.
                     11:  */
                     12: 
                     13: /*
                     14:  * Return the key.
                     15:  */
                     16: ungetkey(c)
                     17:        char c;
                     18: {
                     19: 
                     20:        if (Peekkey != ATTN)
                     21:                Peekkey = c;
                     22: }
                     23: 
                     24: /*
                     25:  * Return a keystroke, but never a ^@.
                     26:  */
                     27: getkey()
                     28: {
                     29:        register char c;
                     30: 
                     31:        do {
                     32:                c = getbr();
                     33:                if (c==0)
                     34:                        beep();
                     35:        } while (c == 0);
                     36:        return (c);
                     37: }
                     38: 
                     39: /*
                     40:  * Tell whether next keystroke would be a ^@.
                     41:  */
                     42: peekbr()
                     43: {
                     44: 
                     45:        Peekkey = getbr();
                     46:        return (Peekkey == 0);
                     47: }
                     48: 
                     49: short  precbksl;
                     50: 
                     51: /*
                     52:  * Get a keystroke, including a ^@.
                     53:  * If an key was returned with ungetkey, that
                     54:  * comes back first.  Next comes unread input (e.g.
                     55:  * from repeating commands with .), and finally new
                     56:  * keystrokes.
                     57:  *
                     58:  * The hard work here is in mapping of \ escaped
                     59:  * characters on upper case only terminals.
                     60:  */
                     61: getbr()
                     62: {
                     63:        char ch;
                     64:        register int c, d;
                     65:        register char *colp;
                     66: 
                     67: getATTN:
                     68:        if (Peekkey) {
                     69:                c = Peekkey;
                     70:                Peekkey = 0;
                     71:                return (c);
                     72:        }
                     73:        if (vglobp) {
                     74:                if (*vglobp)
                     75:                        return (lastvgk = *vglobp++);
                     76:                lastvgk = 0;
                     77:                return (ESCAPE);
                     78:        }
                     79:        if (vmacp) {
                     80:                if (*vmacp)
                     81:                        return(*vmacp++);
                     82:                /* End of a macro or set of nested macros */
                     83:                vmacp = 0;
                     84:                if (inopen == -1)       /* don't screw up undo for esc esc */
                     85:                        vundkind = VMANY;
                     86:                inopen = 1;     /* restore old setting now that macro done */
                     87:        }
                     88: #ifdef TRACE
                     89:        if (trace)
                     90:                fflush(trace);
                     91: #endif
                     92:        flusho();
                     93: again:
                     94:        if (read(0, &ch, 1) != 1) {
                     95:                if (errno == EINTR)
                     96:                        goto getATTN;
                     97:                error("Input read error");
                     98:        }
                     99:        c = ch & TRIM;
                    100: 
                    101: #ifdef UCVISUAL
                    102:        /*
                    103:         * The algorithm here is that of the UNIX kernel.
                    104:         * See the description in the programmers manual.
                    105:         */
                    106:        if (UPPERCASE) {
                    107:                if (isupper(c))
                    108:                        c = tolower(c);
                    109:                if (c == '\\') {
                    110:                        if (precbksl < 2)
                    111:                                precbksl++;
                    112:                        if (precbksl == 1)
                    113:                                goto again;
                    114:                } else if (precbksl) {
                    115:                        d = 0;
                    116:                        if (islower(c))
                    117:                                d = toupper(c);
                    118:                        else {
                    119:                                colp = "({)}!|^~'~";
                    120:                                while (d = *colp++)
                    121:                                        if (d == c) {
                    122:                                                d = *colp++;
                    123:                                                break;
                    124:                                        } else
                    125:                                                colp++;
                    126:                        }
                    127:                        if (precbksl == 2) {
                    128:                                if (!d) {
                    129:                                        Peekkey = c;
                    130:                                        precbksl = 0;
                    131:                                        c = '\\';
                    132:                                }
                    133:                        } else if (d)
                    134:                                c = d;
                    135:                        else {
                    136:                                Peekkey = c;
                    137:                                precbksl = 0;
                    138:                                c = '\\';
                    139:                        }
                    140:                }
                    141:                if (c != '\\')
                    142:                        precbksl = 0;
                    143:        }
                    144: #endif
                    145: #ifdef TRACE
                    146:        if (trace) {
                    147:                if (!techoin) {
                    148:                        tfixnl();
                    149:                        techoin = 1;
                    150:                        fprintf(trace, "*** Input: ");
                    151:                }
                    152:                tracec(c);
                    153:        }
                    154: #endif
                    155:        lastvgk = 0;
                    156:        return (c);
                    157: }
                    158: 
                    159: /*
                    160:  * Get a key, but if a delete, quit or attention
                    161:  * is typed return 0 so we will abort a partial command.
                    162:  */
                    163: getesc()
                    164: {
                    165:        register int c;
                    166: 
                    167:        c = getkey();
                    168:        switch (c) {
                    169: 
                    170:        case ATTN:
                    171:        case QUIT:
                    172:                ungetkey(c);
                    173:                return (0);
                    174: 
                    175:        case ESCAPE:
                    176:                return (0);
                    177:        }
                    178:        return (c);
                    179: }
                    180: 
                    181: /*
                    182:  * Peek at the next keystroke.
                    183:  */
                    184: peekkey()
                    185: {
                    186: 
                    187:        Peekkey = getkey();
                    188:        return (Peekkey);
                    189: }
                    190: 
                    191: /*
                    192:  * Read a line from the echo area, with single character prompt c.
                    193:  * A return value of 1 means the user blewit or blewit away.
                    194:  */
                    195: readecho(c)
                    196:        char c;
                    197: {
                    198:        register char *sc = cursor;
                    199:        register int (*OP)();
                    200:        bool waste;
                    201:        register int OPeek;
                    202: 
                    203:        if (WBOT == WECHO)
                    204:                vclean();
                    205:        else
                    206:                vclrech(0);
                    207:        splitw++;
                    208:        vgoto(WECHO, 0);
                    209:        putchar(c);
                    210:        vclreol();
                    211:        vgoto(WECHO, 1);
                    212:        cursor = linebuf; linebuf[0] = 0; genbuf[0] = c;
                    213:        if (peekbr()) {
                    214:                if (!INS[0] || (INS[0] & (QUOTE|TRIM)) == OVERBUF)
                    215:                        goto blewit;
                    216:                vglobp = INS;
                    217:        }
                    218:        OP = Pline; Pline = normline;
                    219:        ignore(vgetline(0, genbuf + 1, &waste));
                    220:        vscrap();
                    221:        Pline = OP;
                    222:        if (Peekkey != ATTN && Peekkey != QUIT && Peekkey != CTRL(h)) {
                    223:                cursor = sc;
                    224:                vclreol();
                    225:                return (0);
                    226:        }
                    227: blewit:
                    228:        OPeek = Peekkey==CTRL(h) ? 0 : Peekkey; Peekkey = 0;
                    229:        splitw = 0;
                    230:        vclean();
                    231:        vshow(dot, NOLINE);
                    232:        vnline(sc);
                    233:        Peekkey = OPeek;
                    234:        return (1);
                    235: }
                    236: 
                    237: /*
                    238:  * A complete command has been defined for
                    239:  * the purposes of repeat, so copy it from
                    240:  * the working to the previous command buffer.
                    241:  */
                    242: setLAST()
                    243: {
                    244: 
                    245:        if (vglobp)
                    246:                return;
                    247:        lastreg = vreg;
                    248:        lasthad = Xhadcnt;
                    249:        lastcnt = Xcnt;
                    250:        *lastcp = 0;
                    251:        CP(lastcmd, workcmd);
                    252: }
                    253: 
                    254: /*
                    255:  * Gather up some more text from an insert.
                    256:  * If the insertion buffer oveflows, then destroy
                    257:  * the repeatability of the insert.
                    258:  */
                    259: addtext(cp)
                    260:        char *cp;
                    261: {
                    262: 
                    263:        if (vglobp)
                    264:                return;
                    265:        addto(INS, cp);
                    266:        if ((INS[0] & (QUOTE|TRIM)) == OVERBUF)
                    267:                lastcmd[0] = 0;
                    268: }
                    269: 
                    270: setDEL()
                    271: {
                    272: 
                    273:        setBUF(DEL);
                    274: }
                    275: 
                    276: /*
                    277:  * Put text from cursor upto wcursor in BUF.
                    278:  */
                    279: setBUF(BUF)
                    280:        register char *BUF;
                    281: {
                    282:        register int c;
                    283:        register char *wp = wcursor;
                    284: 
                    285:        c = *wp;
                    286:        *wp = 0;
                    287:        BUF[0] = 0;
                    288:        addto(BUF, cursor);
                    289:        *wp = c;
                    290: }
                    291: 
                    292: addto(buf, str)
                    293:        register char *buf, *str;
                    294: {
                    295: 
                    296:        if ((buf[0] & (QUOTE|TRIM)) == OVERBUF)
                    297:                return;
                    298:        if (strlen(buf) + strlen(str) + 1 >= VBSIZE) {
                    299:                buf[0] = OVERBUF;
                    300:                return;
                    301:        }
                    302:        ignore(strcat(buf, str));
                    303: }
                    304: 
                    305: /*
                    306:  * Note a change affecting a lot of lines, or non-visible
                    307:  * lines.  If the parameter must is set, then we only want
                    308:  * to do this for open modes now; return and save for later
                    309:  * notification in visual.
                    310:  */
                    311: noteit(must)
                    312:        bool must;
                    313: {
                    314:        register int sdl = destline, sdc = destcol;
                    315: 
                    316:        if (notecnt < 2 || !must && state == VISUAL)
                    317:                return (0);
                    318:        splitw++;
                    319:        if (WBOT == WECHO)
                    320:                vmoveitup(1, 1);
                    321:        vigoto(WECHO, 0);
                    322:        printf("%d %sline", notecnt, notesgn);
                    323:        if (notecnt > 1)
                    324:                putchar('s');
                    325:        if (*notenam) {
                    326:                printf(" %s", notenam);
                    327:                if (*(strend(notenam) - 1) != 'e')
                    328:                        putchar('e');
                    329:                putchar('d');
                    330:        }
                    331:        vclreol();
                    332:        notecnt = 0;
                    333:        if (state != VISUAL)
                    334:                vcnt = vcline = 0;
                    335:        splitw = 0;
                    336:        if (state == ONEOPEN || state == CRTOPEN)
                    337:                vup1();
                    338:        destline = sdl; destcol = sdc;
                    339:        return (1);
                    340: }
                    341: 
                    342: /*
                    343:  * Rrrrringgggggg.
                    344:  * If possible, use flash (VB).
                    345:  */
                    346: beep()
                    347: {
                    348: 
                    349:        if (VB)
                    350:                vputp(VB, 0);
                    351:        else
                    352:                vputc(CTRL(g));
                    353: }
                    354: 
                    355: /*
                    356:  * Map the command input character c,
                    357:  * for keypads and labelled keys which do cursor
                    358:  * motions.  I.e. on an adm3a we might map ^K to ^P.
                    359:  * DM1520 for example has a lot of mappable characters.
                    360:  */
                    361: 
                    362: map(c,maps)
                    363:        register int c;
                    364:        register struct maps *maps;
                    365: {
                    366:        register int d;
                    367:        register char *p, *q;
                    368:        char b[10];     /* Assumption: no keypad sends string longer than 10 */
                    369: 
                    370:        /*
                    371:         * Mapping for special keys on the terminal only.
                    372:         * BUG: if there's a long sequence and it matches
                    373:         * some chars and then misses, we lose some chars.
                    374:         *
                    375:         * For this to work, some conditions must be met.
                    376:         * 1) Keypad sends SHORT (2 or 3 char) strings
                    377:         * 2) All strings sent are same length & similar
                    378:         * 3) The user is unlikely to type the first few chars of
                    379:         *    one of these strings very fast.
                    380:         * Note: some code has been fixed up since the above was laid out,
                    381:         * so conditions 1 & 2 are probably not required anymore.
                    382:         * However, this hasn't been tested with any first char
                    383:         * that means anything else except escape.
                    384:         */
                    385: #ifdef MDEBUG
                    386:        if (trace)
                    387:                fprintf(trace,"map(%c): ",c);
                    388: #endif
                    389:        b[0] = c;
                    390:        b[1] = 0;
                    391:        for (d=0; maps[d].mapto; d++) {
                    392: #ifdef MDEBUG
                    393:                if (trace)
                    394:                        fprintf(trace,"d=%d, ",d);
                    395: #endif
                    396:                if (p = maps[d].cap) {
                    397:                        for (q=b; *p; p++, q++) {
                    398: #ifdef MDEBUG
                    399:                                if (trace)
                    400:                                        fprintf(trace,"q->b[%d], ",q-b);
                    401: #endif
                    402:                                if (*q==0) {
                    403:                                        /*
                    404:                                         * This test is oversimplified, but
                    405:                                         * should work mostly. It handles the
                    406:                                         * case where we get an ESCAPE that
                    407:                                         * wasn't part of a keypad string.
                    408:                                         */
                    409:                                        if ((c=='#' ? peekkey() : fastpeekkey()) == 0) {
                    410: #ifdef MDEBUG
                    411:                                        if (trace)
                    412:                                                fprintf(trace,"fpk=0: return %c",c);
                    413: #endif
                    414:                                                macpush(&b[1],1);
                    415:                                                return(c);
                    416:                                        }
                    417:                                        *q = getkey();
                    418:                                        q[1] = 0;
                    419:                                }
                    420:                                if (*p != *q)
                    421:                                        goto contin;
                    422:                        }
                    423:                        macpush(maps[d].mapto,1);
                    424:                        c = getkey();
                    425: #ifdef MDEBUG
                    426:        if (trace)
                    427:                fprintf(trace,"Success: return %c",c);
                    428: #endif
                    429:                        return(c);      /* first char of map string */
                    430:                        contin:;
                    431:                }
                    432:        }
                    433: #ifdef MDEBUG
                    434:        if (trace)
                    435:                fprintf(trace,"Fail: return %c",c); /* DEBUG */
                    436: #endif
                    437:        macpush(&b[1],0);
                    438:        return(c);
                    439: }
                    440: 
                    441: /*
                    442:  * Push st onto the front of vmacp. This is tricky because we have to
                    443:  * worry about where vmacp was previously pointing. We also have to
                    444:  * check for overflow (which is typically from a recursive macro)
                    445:  * Finally we have to set a flag so the whole thing can be undone.
                    446:  * canundo is 1 iff we want to be able to undo the macro.  This
                    447:  * is false for, for example, pushing back lookahead from fastpeekkey(),
                    448:  * since otherwise two fast escapes can clobber our undo.
                    449:  */
                    450: macpush(st, canundo)
                    451: char *st;
                    452: int canundo;
                    453: {
                    454:        char tmpbuf[BUFSIZ];
                    455: 
                    456:        if (st==0 || *st==0)
                    457:                return;
                    458: #ifdef TRACE
                    459:        if (trace)
                    460:                fprintf(trace, "macpush(%s)",st);
                    461: #endif
                    462:        if (strlen(vmacp) + strlen(st) > BUFSIZ)
                    463:                error("Macro too long@ - maybe recursive?");
                    464:        if (vmacp) {
                    465:                strcpy(tmpbuf, vmacp);
                    466:                canundo = 0;    /* can't undo inside a macro anyway */
                    467:        }
                    468:        strcpy(vmacbuf, st);
                    469:        if (vmacp)
                    470:                strcat(vmacbuf, tmpbuf);
                    471:        vmacp = vmacbuf;
                    472:        /* arrange to be able to undo the whole macro */
                    473:        if (canundo) {
                    474:                inopen = -1;    /* no need to save since it had to be 1 or -1 before */
                    475:                otchng = tchng;
                    476:                vsave();
                    477:                saveall();
                    478:                vundkind = VMANY;
                    479:        }
                    480: #ifdef TRACE
                    481:        if (trace)
                    482:                fprintf(trace, "saveall for macro: undkind=%d, unddel=%d, undap1=%d, undap2=%d, dol=%d, unddol=%d, truedol=%d\n", undkind, lineno(unddel), lineno(undap1), lineno(undap2), lineno(dol), lineno(unddol), lineno(truedol));
                    483: #endif
                    484: }
                    485: 
                    486: /*
                    487:  * Get a count from the keyed input stream.
                    488:  * A zero count is indistinguishable from no count.
                    489:  */
                    490: vgetcnt()
                    491: {
                    492:        register int c, cnt;
                    493: 
                    494:        cnt = 0;
                    495:        for (;;) {
                    496:                c = getkey();
                    497:                if (!isdigit(c))
                    498:                        break;
                    499:                cnt *= 10, cnt += c - '0';
                    500:        }
                    501:        ungetkey(c);
                    502:        Xhadcnt = 1;
                    503:        Xcnt = cnt;
                    504:        return(cnt);
                    505: }
                    506: 
                    507: /*
                    508:  * fastpeekkey is just like peekkey but insists the character come in
                    509:  * fast (within 1 second). This will succeed if it is the 2nd char of
                    510:  * a machine generated sequence (such as a function pad from an escape
                    511:  * flavor terminal) but fail for a human hitting escape then waiting.
                    512:  */
                    513: fastpeekkey()
                    514: {
                    515:        int trapalarm();
                    516:        register int c;
                    517: 
                    518:        if (inopen == -1)       /* don't work inside macros! */
                    519:                return (0);
                    520:        signal(SIGALRM, trapalarm);
                    521:        alarm(1);
                    522:        CATCH
                    523:                c = peekkey();
                    524: #ifdef MDEBUG
                    525:        if (trace)
                    526:                fprintf(trace,"[OK]",c);
                    527: #endif
                    528:                alarm(0);
                    529:        ONERR
                    530:                c = 0;
                    531: #ifdef MDEBUG
                    532:        if (trace)
                    533:                fprintf(trace,"[TOUT]",c);
                    534: #endif
                    535:        ENDCATCH
                    536: #ifdef MDEBUG
                    537:        if (trace)
                    538:                fprintf(trace,"[fpk:%o]",c);
                    539: #endif
                    540:        return(c);
                    541: }
                    542: 
                    543: trapalarm() {
                    544:        alarm(0);
                    545:        longjmp(vreslab,1);
                    546: }

unix.superglobalmegacorp.com

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