[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.20

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