[BACK]Return to kbd.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/kbd.c, Revision 1.24

1.24    ! kjell       1: /*     $OpenBSD: kbd.c,v 1.23 2006/12/21 18:06:02 kjell Exp $  */
1.17      kjell       2:
                      3: /* This file is in the public domain. */
1.4       niklas      4:
1.1       deraadt     5: /*
1.3       millert     6:  *     Terminal independent keyboard handling.
1.1       deraadt     7:  */
                      8:
1.3       millert     9: #include "def.h"
                     10: #include "kbd.h"
                     11: #include "key.h"
1.1       deraadt    12:
                     13: #ifndef NO_MACRO
                     14: #include "macro.h"
1.3       millert    15: #endif /* !NO_MACRO */
1.1       deraadt    16:
                     17: #ifndef METABIT
                     18: #define METABIT 0x80
1.3       millert    19: #endif /* !METABIT */
                     20:
                     21: #ifndef NO_DPROMPT
                     22: #define PROMPTL 80
1.9       mickey     23: char    prompt[PROMPTL] = "", *promptp = prompt;
1.3       millert    24: #endif /* !NO_DPROMPT */
1.1       deraadt    25:
1.24    ! kjell      26: static int mgwrap(PF, int, int);
        !            27:
1.3       millert    28: static int      use_metakey = TRUE;
                     29: static int      pushed = FALSE;
                     30: static int      pushedc;
                     31:
1.18      deraadt    32: struct map_element     *ele;
1.15      vincent    33:
                     34: struct key key;
1.1       deraadt    35:
                     36: /*
                     37:  * Toggle the value of use_metakey
                     38:  */
1.2       millert    39: int
1.14      vincent    40: do_meta(int f, int n)
1.1       deraadt    41: {
1.2       millert    42:        if (f & FFARG)
                     43:                use_metakey = n > 0;
                     44:        else
                     45:                use_metakey = !use_metakey;
1.1       deraadt    46:        ewprintf("Meta keys %sabled", use_metakey ? "en" : "dis");
1.16      db         47:        return (TRUE);
1.1       deraadt    48: }
                     49:
1.23      kjell      50: static int      bs_map = 0;
                     51:
1.1       deraadt    52: /*
                     53:  * Toggle backspace mapping
                     54:  */
1.2       millert    55: int
1.14      vincent    56: bsmap(int f, int n)
1.1       deraadt    57: {
1.2       millert    58:        if (f & FFARG)
                     59:                bs_map = n > 0;
                     60:        else
                     61:                bs_map = !bs_map;
1.1       deraadt    62:        ewprintf("Backspace mapping %sabled", bs_map ? "en" : "dis");
1.16      db         63:        return (TRUE);
1.1       deraadt    64: }
                     65:
1.8       art        66: void
1.14      vincent    67: ungetkey(int c)
1.1       deraadt    68: {
1.2       millert    69:        if (use_metakey && pushed && c == CCHR('['))
                     70:                pushedc |= METABIT;
1.1       deraadt    71:        else
                     72:                pushedc = c;
                     73:        pushed = TRUE;
                     74: }
                     75:
1.2       millert    76: int
1.14      vincent    77: getkey(int flag)
1.1       deraadt    78: {
1.3       millert    79:        int      c;
1.1       deraadt    80:
                     81: #ifndef NO_DPROMPT
1.2       millert    82:        if (flag && !pushed) {
1.5       art        83:                if (prompt[0] != '\0' && ttwait(2000)) {
1.3       millert    84:                        /* avoid problems with % */
                     85:                        ewprintf("%s", prompt);
                     86:                        /* put the cursor back */
                     87:                        update();
1.22      kjell      88:                        epresf = KCLEAR;
1.1       deraadt    89:                }
1.2       millert    90:                if (promptp > prompt)
                     91:                        *(promptp - 1) = ' ';
1.1       deraadt    92:        }
1.3       millert    93: #endif /* !NO_DPROMPT */
1.2       millert    94:        if (pushed) {
1.1       deraadt    95:                c = pushedc;
                     96:                pushed = FALSE;
1.2       millert    97:        } else
1.12      deraadt    98:                c = ttgetc();
1.23      kjell      99:
                    100:        if (bs_map) {
1.2       millert   101:                if (c == CCHR('H'))
                    102:                        c = CCHR('?');
                    103:                else if (c == CCHR('?'))
                    104:                        c = CCHR('H');
1.23      kjell     105:        }
1.2       millert   106:        if (use_metakey && (c & METABIT)) {
1.1       deraadt   107:                pushedc = c & ~METABIT;
                    108:                pushed = TRUE;
                    109:                c = CCHR('[');
                    110:        }
                    111: #ifndef NO_DPROMPT
1.2       millert   112:        if (flag && promptp < &prompt[PROMPTL - 5]) {
1.20      kjell     113:                promptp = getkeyname(promptp,
1.9       mickey    114:                    sizeof(prompt) - (promptp - prompt) - 1, c);
1.2       millert   115:                *promptp++ = '-';
                    116:                *promptp = '\0';
1.1       deraadt   117:        }
1.3       millert   118: #endif /* !NO_DPROMPT */
1.16      db        119:        return (c);
1.1       deraadt   120: }
                    121:
                    122: /*
                    123:  * doscan scans a keymap for a keyboard character and returns a pointer
                    124:  * to the function associated with that character.  Sets ele to the
                    125:  * keymap element the keyboard was found in as a side effect.
                    126:  */
1.2       millert   127: PF
1.14      vincent   128: doscan(KEYMAP *map, int c, KEYMAP **newmap)
1.2       millert   129: {
1.18      deraadt   130:        struct map_element      *elec = &map->map_element[0];
                    131:        struct map_element      *last = &map->map_element[map->map_num];
1.16      db        132:        PF               ret;
1.1       deraadt   133:
1.2       millert   134:        while (elec < last && c > elec->k_num)
                    135:                elec++;
1.3       millert   136:
                    137:        /* used by prefix and binding code */
                    138:        ele = elec;
1.2       millert   139:        if (elec >= last || c < elec->k_base)
1.7       art       140:                ret = map->map_default;
                    141:        else
                    142:                ret = elec->k_funcp[c - elec->k_base];
                    143:        if (ret == NULL && newmap != NULL)
                    144:                *newmap = elec->k_prefmap;
                    145:
1.16      db        146:        return (ret);
1.1       deraadt   147: }
                    148:
1.2       millert   149: int
1.14      vincent   150: doin(void)
1.1       deraadt   151: {
1.3       millert   152:        KEYMAP  *curmap;
                    153:        PF       funct;
1.1       deraadt   154:
                    155: #ifndef NO_DPROMPT
1.2       millert   156:        *(promptp = prompt) = '\0';
1.3       millert   157: #endif /* !NO_DPROMPT */
1.2       millert   158:        curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
                    159:        key.k_count = 0;
                    160:        while ((funct = doscan(curmap, (key.k_chars[key.k_count++] =
1.7       art       161:            getkey(TRUE)), &curmap)) == NULL)
1.16      db        162:                /* nothing */;
1.1       deraadt   163: #ifndef NO_MACRO
1.2       millert   164:        if (macrodef && macrocount < MAXMACRO)
                    165:                macro[macrocount++].m_funct = funct;
1.3       millert   166: #endif /* !NO_MACRO */
1.24    ! kjell     167:        return (mgwrap(funct, 0, 1));
1.1       deraadt   168: }
                    169:
1.2       millert   170: int
1.14      vincent   171: rescan(int f, int n)
1.1       deraadt   172: {
1.3       millert   173:        int      c;
                    174:        KEYMAP  *curmap;
                    175:        int      i;
                    176:        PF       fp = NULL;
1.21      kjell     177:        int      md = curbp->b_nmodes;
1.2       millert   178:
                    179:        for (;;) {
                    180:                if (ISUPPER(key.k_chars[key.k_count - 1])) {
                    181:                        c = TOLOWER(key.k_chars[key.k_count - 1]);
1.21      kjell     182:                        curmap = curbp->b_modes[md]->p_map;
1.2       millert   183:                        for (i = 0; i < key.k_count - 1; i++) {
1.24    ! kjell     184:                                if ((fp = doscan(curmap, (key.k_chars[i]),
        !           185:                                    &curmap)) != NULL)
1.2       millert   186:                                        break;
                    187:                        }
1.6       art       188:                        if (fp == NULL) {
1.7       art       189:                                if ((fp = doscan(curmap, c, NULL)) == NULL)
1.2       millert   190:                                        while ((fp = doscan(curmap,
                    191:                                            key.k_chars[key.k_count++] =
1.7       art       192:                                            getkey(TRUE), &curmap)) == NULL)
1.16      db        193:                                                /* nothing */;
1.2       millert   194:                                if (fp != rescan) {
                    195: #ifndef NO_MACRO
                    196:                                        if (macrodef && macrocount <= MAXMACRO)
1.10      mickey    197:                                                macro[macrocount - 1].m_funct
1.3       millert   198:                                                    = fp;
                    199: #endif /* !NO_MACRO */
1.24    ! kjell     200:
        !           201:                                        return (mgwrap(fp, f, n));
1.2       millert   202:                                }
                    203:                        }
                    204:                }
                    205:                /* try previous mode */
1.21      kjell     206:                if (--md < 0)
1.16      db        207:                        return (ABORT);
1.21      kjell     208:                curmap = curbp->b_modes[md]->p_map;
1.2       millert   209:                for (i = 0; i < key.k_count; i++) {
1.7       art       210:                        if ((fp = doscan(curmap, (key.k_chars[i]), &curmap)) != NULL)
1.2       millert   211:                                break;
                    212:                }
1.6       art       213:                if (fp == NULL) {
1.10      mickey    214:                        while ((fp = doscan(curmap, key.k_chars[i++] =
1.7       art       215:                            getkey(TRUE), &curmap)) == NULL)
1.16      db        216:                                /* nothing */;
1.2       millert   217:                        key.k_count = i;
                    218:                }
                    219:                if (fp != rescan && i >= key.k_count - 1) {
1.1       deraadt   220: #ifndef NO_MACRO
1.2       millert   221:                        if (macrodef && macrocount <= MAXMACRO)
                    222:                                macro[macrocount - 1].m_funct = fp;
1.3       millert   223: #endif /* !NO_MACRO */
1.24    ! kjell     224:                        return (mgwrap(fp, f, n));
1.1       deraadt   225:                }
                    226:        }
1.2       millert   227: }
                    228:
                    229: int
1.14      vincent   230: universal_argument(int f, int n)
1.2       millert   231: {
1.3       millert   232:        KEYMAP  *curmap;
                    233:        PF       funct;
1.16      db        234:        int      c, nn = 4;
1.2       millert   235:
                    236:        if (f & FFUNIV)
                    237:                nn *= n;
                    238:        for (;;) {
                    239:                key.k_chars[0] = c = getkey(TRUE);
                    240:                key.k_count = 1;
                    241:                if (c == '-')
1.16      db        242:                        return (negative_argument(f, nn));
1.2       millert   243:                if (c >= '0' && c <= '9')
1.16      db        244:                        return (digit_argument(f, nn));
1.2       millert   245:                curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
1.7       art       246:                while ((funct = doscan(curmap, c, &curmap)) == NULL) {
1.2       millert   247:                        key.k_chars[key.k_count++] = c = getkey(TRUE);
                    248:                }
                    249:                if (funct != universal_argument) {
1.1       deraadt   250: #ifndef NO_MACRO
1.2       millert   251:                        if (macrodef && macrocount < MAXMACRO - 1) {
                    252:                                if (f & FFARG)
                    253:                                        macrocount--;
                    254:                                macro[macrocount++].m_count = nn;
                    255:                                macro[macrocount++].m_funct = funct;
                    256:                        }
1.3       millert   257: #endif /* !NO_MACRO */
1.24    ! kjell     258:                        return (mgwrap(funct, FFUNIV, nn));
1.2       millert   259:                }
                    260:                nn <<= 2;
1.1       deraadt   261:        }
                    262: }
                    263:
1.2       millert   264: /* ARGSUSED */
                    265: int
1.14      vincent   266: digit_argument(int f, int n)
1.1       deraadt   267: {
1.3       millert   268:        KEYMAP  *curmap;
                    269:        PF       funct;
                    270:        int      nn, c;
1.2       millert   271:
                    272:        nn = key.k_chars[key.k_count - 1] - '0';
                    273:        for (;;) {
                    274:                c = getkey(TRUE);
                    275:                if (c < '0' || c > '9')
                    276:                        break;
                    277:                nn *= 10;
                    278:                nn += c - '0';
                    279:        }
                    280:        key.k_chars[0] = c;
1.1       deraadt   281:        key.k_count = 1;
                    282:        curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
1.7       art       283:        while ((funct = doscan(curmap, c, &curmap)) == NULL) {
1.2       millert   284:                key.k_chars[key.k_count++] = c = getkey(TRUE);
1.1       deraadt   285:        }
                    286: #ifndef NO_MACRO
1.2       millert   287:        if (macrodef && macrocount < MAXMACRO - 1) {
                    288:                if (f & FFARG)
                    289:                        macrocount--;
                    290:                else
                    291:                        macro[macrocount - 1].m_funct = universal_argument;
1.1       deraadt   292:                macro[macrocount++].m_count = nn;
                    293:                macro[macrocount++].m_funct = funct;
                    294:        }
1.3       millert   295: #endif /* !NO_MACRO */
1.24    ! kjell     296:        return (mgwrap(funct, FFOTHARG, nn));
1.1       deraadt   297: }
                    298:
1.2       millert   299: int
1.14      vincent   300: negative_argument(int f, int n)
1.1       deraadt   301: {
1.3       millert   302:        KEYMAP  *curmap;
                    303:        PF       funct;
                    304:        int      c;
                    305:        int      nn = 0;
1.2       millert   306:
                    307:        for (;;) {
                    308:                c = getkey(TRUE);
                    309:                if (c < '0' || c > '9')
                    310:                        break;
                    311:                nn *= 10;
                    312:                nn += c - '0';
                    313:        }
                    314:        if (nn)
                    315:                nn = -nn;
                    316:        else
                    317:                nn = -n;
                    318:        key.k_chars[0] = c;
                    319:        key.k_count = 1;
                    320:        curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
1.7       art       321:        while ((funct = doscan(curmap, c, &curmap)) == NULL) {
1.2       millert   322:                key.k_chars[key.k_count++] = c = getkey(TRUE);
                    323:        }
1.1       deraadt   324: #ifndef NO_MACRO
1.2       millert   325:        if (macrodef && macrocount < MAXMACRO - 1) {
                    326:                if (f & FFARG)
                    327:                        macrocount--;
                    328:                else
                    329:                        macro[macrocount - 1].m_funct = universal_argument;
                    330:                macro[macrocount++].m_count = nn;
                    331:                macro[macrocount++].m_funct = funct;
                    332:        }
1.3       millert   333: #endif /* !NO_MACRO */
1.24    ! kjell     334:        return (mgwrap(funct, FFNEGARG, nn));
1.1       deraadt   335: }
                    336:
                    337: /*
                    338:  * Insert a character. While defining a macro, create a "LINE" containing
                    339:  * all inserted characters.
                    340:  */
1.2       millert   341: int
1.14      vincent   342: selfinsert(int f, int n)
1.1       deraadt   343: {
                    344: #ifndef NO_MACRO
1.18      deraadt   345:        struct line     *lp;
1.3       millert   346: #endif /* !NO_MACRO */
                    347:        int      c;
                    348:        int      count;
1.1       deraadt   349:
1.2       millert   350:        if (n < 0)
1.16      db        351:                return (FALSE);
1.2       millert   352:        if (n == 0)
1.16      db        353:                return (TRUE);
1.2       millert   354:        c = key.k_chars[key.k_count - 1];
1.1       deraadt   355: #ifndef NO_MACRO
1.2       millert   356:        if (macrodef && macrocount < MAXMACRO) {
                    357:                if (f & FFARG)
                    358:                        macrocount -= 2;
1.3       millert   359:
                    360:                /* last command was insert -- tack on the end */
                    361:                if (lastflag & CFINS) {
1.2       millert   362:                        macrocount--;
1.11      vincent   363:                        /* Ensure the line can handle the new characters */
1.2       millert   364:                        if (maclcur->l_size < maclcur->l_used + n) {
1.11      vincent   365:                                if (lrealloc(maclcur, maclcur->l_used + n) ==
                    366:                                    FALSE)
1.16      db        367:                                        return (FALSE);
1.2       millert   368:                        }
1.11      vincent   369:                        maclcur->l_used += n;
                    370:                        /* Copy in the new data */
                    371:                        for (count = maclcur->l_used - n;
1.13      deraadt   372:                            count < maclcur->l_used; count++)
1.11      vincent   373:                                maclcur->l_text[count] = c;
1.2       millert   374:                } else {
                    375:                        macro[macrocount - 1].m_funct = insert;
1.11      vincent   376:                        if ((lp = lalloc(n)) == NULL)
1.16      db        377:                                return (FALSE);
1.2       millert   378:                        lp->l_bp = maclcur;
                    379:                        lp->l_fp = maclcur->l_fp;
                    380:                        maclcur->l_fp = lp;
                    381:                        maclcur = lp;
                    382:                        for (count = 0; count < n; count++)
                    383:                                lp->l_text[count] = c;
                    384:                }
                    385:                thisflag |= CFINS;
                    386:        }
1.3       millert   387: #endif /* !NO_MACRO */
1.2       millert   388:        if (c == '\n') {
                    389:                do {
                    390:                        count = lnewline();
                    391:                } while (--n && count == TRUE);
1.16      db        392:                return (count);
1.2       millert   393:        }
1.3       millert   394:
                    395:        /* overwrite mode */
                    396:        if (curbp->b_flag & BFOVERWRITE) {
1.2       millert   397:                lchange(WFEDIT);
                    398:                while (curwp->w_doto < llength(curwp->w_dotp) && n--)
                    399:                        lputc(curwp->w_dotp, curwp->w_doto++, c);
                    400:                if (n <= 0)
1.16      db        401:                        return (TRUE);
1.2       millert   402:        }
1.16      db        403:        return (linsert(n, c));
1.1       deraadt   404: }
                    405:
                    406: /*
1.16      db        407:  * This could be implemented as a keymap with everything defined as self-insert.
1.1       deraadt   408:  */
1.2       millert   409: int
1.14      vincent   410: quote(int f, int n)
1.1       deraadt   411: {
1.3       millert   412:        int      c;
1.1       deraadt   413:
1.2       millert   414:        key.k_count = 1;
                    415:        if ((key.k_chars[0] = getkey(TRUE)) >= '0' && key.k_chars[0] <= '7') {
                    416:                key.k_chars[0] -= '0';
                    417:                if ((c = getkey(TRUE)) >= '0' && c <= '7') {
                    418:                        key.k_chars[0] <<= 3;
                    419:                        key.k_chars[0] += c - '0';
                    420:                        if ((c = getkey(TRUE)) >= '0' && c <= '7') {
                    421:                                key.k_chars[0] <<= 3;
                    422:                                key.k_chars[0] += c - '0';
                    423:                        } else
                    424:                                ungetkey(c);
                    425:                } else
                    426:                        ungetkey(c);
                    427:        }
1.16      db        428:        return (selfinsert(f, n));
1.24    ! kjell     429: }
        !           430:
        !           431: /*
        !           432:  * Wraper function to count invocation repeats.
        !           433:  * We ignore any function whose sole purpose is to get us
        !           434:  * to the intended function.
        !           435:  */
        !           436: static int
        !           437: mgwrap(PF funct, int f, int n)
        !           438: {
        !           439:        static   PF ofp;
        !           440:
        !           441:        if (funct != rescan &&
        !           442:            funct != negative_argument &&
        !           443:            funct != digit_argument &&
        !           444:            funct != universal_argument) {
        !           445:                if (funct == ofp)
        !           446:                        rptcount++;
        !           447:                else
        !           448:                        rptcount = 0;
        !           449:                ofp = funct;
        !           450:        }
        !           451:
        !           452:        return ((*funct)(f, n));
1.1       deraadt   453: }