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

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