Annotation of 3BSD/cmd/ex/ex_vget.c, revision 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.