Annotation of researchv10no/cmd/ex/ex_vget.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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