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

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