[BACK]Return to mode-key.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Annotation of src/usr.bin/tmux/mode-key.c, Revision 1.73

1.73    ! nicm        1: /* $OpenBSD: mode-key.c,v 1.72 2016/10/11 13:45:47 nicm Exp $ */
1.1       nicm        2:
                      3: /*
1.65      nicm        4:  * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
1.1       nicm        5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
                     15:  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                     16:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: #include <sys/types.h>
                     20:
1.11      nicm       21: #include <string.h>
                     22:
1.1       nicm       23: #include "tmux.h"
                     24:
1.10      nicm       25: /*
                     26:  * Mode keys. These are the key bindings used when editing (status prompt), and
                     27:  * in the modes. They are split into two sets of three tables, one set of three
                     28:  * for vi and the other for emacs key bindings. The three tables are for
                     29:  * editing, for menu-like modes (choice, more), and for copy modes (copy,
                     30:  * scroll).
                     31:  *
                     32:  * The fixed tables of struct mode_key_entry below are the defaults: they are
                     33:  * built into a tree of struct mode_key_binding by mode_key_init_trees, which
                     34:  * can then be modified.
                     35:  *
                     36:  * vi command mode is handled by having a mode flag in the struct which allows
                     37:  * two sets of bindings to be swapped between. A couple of editing commands
1.53      nicm       38:  * (any matching MODEKEYEDIT_SWITCHMODE*) are special-cased to do this.
1.10      nicm       39:  */
1.63      nicm       40:
1.72      nicm       41: /* Command to string mapping. */
                     42: struct mode_key_cmdstr {
                     43:        enum mode_key_cmd        cmd;
                     44:        const char              *name;
                     45: };
                     46:
1.63      nicm       47: /* Entry in the default mode key tables. */
                     48: struct mode_key_entry {
1.64      nicm       49:        key_code                key;
1.63      nicm       50:        enum mode_key_cmd       cmd;
                     51: };
1.10      nicm       52:
                     53: /* Choice keys command strings. */
1.70      nicm       54: static const struct mode_key_cmdstr mode_key_cmdstr_choice[] = {
1.46      nicm       55:        { MODEKEYCHOICE_BACKSPACE, "backspace" },
1.57      nicm       56:        { MODEKEYCHOICE_BOTTOMLINE, "bottom-line"},
1.10      nicm       57:        { MODEKEYCHOICE_CANCEL, "cancel" },
                     58:        { MODEKEYCHOICE_CHOOSE, "choose" },
                     59:        { MODEKEYCHOICE_DOWN, "down" },
1.57      nicm       60:        { MODEKEYCHOICE_ENDOFLIST, "end-of-list"},
1.10      nicm       61:        { MODEKEYCHOICE_PAGEDOWN, "page-down" },
                     62:        { MODEKEYCHOICE_PAGEUP, "page-up" },
1.30      nicm       63:        { MODEKEYCHOICE_SCROLLDOWN, "scroll-down" },
                     64:        { MODEKEYCHOICE_SCROLLUP, "scroll-up" },
1.46      nicm       65:        { MODEKEYCHOICE_STARTNUMBERPREFIX, "start-number-prefix" },
1.57      nicm       66:        { MODEKEYCHOICE_STARTOFLIST, "start-of-list"},
                     67:        { MODEKEYCHOICE_TOPLINE, "top-line"},
1.49      nicm       68:        { MODEKEYCHOICE_TREE_COLLAPSE, "tree-collapse" },
1.48      nicm       69:        { MODEKEYCHOICE_TREE_COLLAPSE_ALL, "tree-collapse-all" },
1.49      nicm       70:        { MODEKEYCHOICE_TREE_EXPAND, "tree-expand" },
1.48      nicm       71:        { MODEKEYCHOICE_TREE_EXPAND_ALL, "tree-expand-all" },
                     72:        { MODEKEYCHOICE_TREE_TOGGLE, "tree-toggle" },
1.10      nicm       73:        { MODEKEYCHOICE_UP, "up" },
1.11      nicm       74:
                     75:        { 0, NULL }
1.10      nicm       76: };
                     77:
1.8       nicm       78: /* vi choice selection keys. */
1.70      nicm       79: static const struct mode_key_entry mode_key_vi_choice[] = {
1.73    ! nicm       80:        { '0' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !            81:        { '1' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !            82:        { '2' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !            83:        { '3' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !            84:        { '4' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !            85:        { '5' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !            86:        { '6' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !            87:        { '7' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !            88:        { '8' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !            89:        { '9' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !            90:        { '\002' /* C-b */,         MODEKEYCHOICE_PAGEUP },
        !            91:        { '\003' /* C-c */,         MODEKEYCHOICE_CANCEL },
        !            92:        { '\005' /* C-e */,         MODEKEYCHOICE_SCROLLDOWN },
        !            93:        { '\006' /* C-f */,         MODEKEYCHOICE_PAGEDOWN },
        !            94:        { '\031' /* C-y */,         MODEKEYCHOICE_SCROLLUP },
        !            95:        { '\n',                     MODEKEYCHOICE_CHOOSE },
        !            96:        { '\r',                     MODEKEYCHOICE_CHOOSE },
        !            97:        { 'j',                      MODEKEYCHOICE_DOWN },
        !            98:        { 'k',                      MODEKEYCHOICE_UP },
        !            99:        { 'q',                      MODEKEYCHOICE_CANCEL },
        !           100:        { KEYC_HOME,                MODEKEYCHOICE_STARTOFLIST },
        !           101:        { 'g',                      MODEKEYCHOICE_STARTOFLIST },
        !           102:        { 'H',                      MODEKEYCHOICE_TOPLINE },
        !           103:        { 'L',                      MODEKEYCHOICE_BOTTOMLINE },
        !           104:        { 'G',                      MODEKEYCHOICE_ENDOFLIST },
        !           105:        { KEYC_END,                 MODEKEYCHOICE_ENDOFLIST },
        !           106:        { KEYC_BSPACE,              MODEKEYCHOICE_BACKSPACE },
        !           107:        { KEYC_DOWN | KEYC_CTRL,    MODEKEYCHOICE_SCROLLDOWN },
        !           108:        { KEYC_DOWN,                MODEKEYCHOICE_DOWN },
        !           109:        { KEYC_NPAGE,               MODEKEYCHOICE_PAGEDOWN },
        !           110:        { KEYC_PPAGE,               MODEKEYCHOICE_PAGEUP },
        !           111:        { KEYC_UP | KEYC_CTRL,      MODEKEYCHOICE_SCROLLUP },
        !           112:        { KEYC_UP,                  MODEKEYCHOICE_UP },
        !           113:        { ' ',                      MODEKEYCHOICE_TREE_TOGGLE },
        !           114:        { KEYC_LEFT,                MODEKEYCHOICE_TREE_COLLAPSE },
        !           115:        { KEYC_RIGHT,               MODEKEYCHOICE_TREE_EXPAND },
        !           116:        { KEYC_LEFT | KEYC_CTRL,    MODEKEYCHOICE_TREE_COLLAPSE_ALL },
        !           117:        { KEYC_RIGHT | KEYC_CTRL,   MODEKEYCHOICE_TREE_EXPAND_ALL },
        !           118:        { KEYC_MOUSEDOWN1_PANE,     MODEKEYCHOICE_CHOOSE },
        !           119:        { KEYC_MOUSEDOWN3_PANE,     MODEKEYCHOICE_TREE_TOGGLE },
        !           120:        { KEYC_WHEELUP_PANE,        MODEKEYCHOICE_UP },
        !           121:        { KEYC_WHEELDOWN_PANE,      MODEKEYCHOICE_DOWN },
1.8       nicm      122:
1.73    ! nicm      123:        { KEYC_NONE, -1 }
1.8       nicm      124: };
1.10      nicm      125: struct mode_key_tree mode_key_tree_vi_choice;
1.8       nicm      126:
                    127: /* emacs choice selection keys. */
1.70      nicm      128: static const struct mode_key_entry mode_key_emacs_choice[] = {
1.73    ! nicm      129:        { '0' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !           130:        { '1' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !           131:        { '2' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !           132:        { '3' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !           133:        { '4' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !           134:        { '5' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !           135:        { '6' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !           136:        { '7' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !           137:        { '8' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !           138:        { '9' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTNUMBERPREFIX },
        !           139:        { '\003' /* C-c */,         MODEKEYCHOICE_CANCEL },
        !           140:        { '\016' /* C-n */,         MODEKEYCHOICE_DOWN },
        !           141:        { '\020' /* C-p */,         MODEKEYCHOICE_UP },
        !           142:        { '\026' /* C-v */,         MODEKEYCHOICE_PAGEDOWN },
        !           143:        { '\033' /* Escape */,      MODEKEYCHOICE_CANCEL },
        !           144:        { '\n',                     MODEKEYCHOICE_CHOOSE },
        !           145:        { '\r',                     MODEKEYCHOICE_CHOOSE },
        !           146:        { 'q',                      MODEKEYCHOICE_CANCEL },
        !           147:        { 'v' | KEYC_ESCAPE,        MODEKEYCHOICE_PAGEUP },
        !           148:        { KEYC_HOME,                MODEKEYCHOICE_STARTOFLIST },
        !           149:        { '<' | KEYC_ESCAPE,        MODEKEYCHOICE_STARTOFLIST },
        !           150:        { 'R' | KEYC_ESCAPE,        MODEKEYCHOICE_TOPLINE },
        !           151:        { '>' | KEYC_ESCAPE,        MODEKEYCHOICE_ENDOFLIST },
        !           152:        { KEYC_END,                 MODEKEYCHOICE_ENDOFLIST },
        !           153:        { KEYC_BSPACE,              MODEKEYCHOICE_BACKSPACE },
        !           154:        { KEYC_DOWN | KEYC_CTRL,    MODEKEYCHOICE_SCROLLDOWN },
        !           155:        { KEYC_DOWN,                MODEKEYCHOICE_DOWN },
        !           156:        { KEYC_NPAGE,               MODEKEYCHOICE_PAGEDOWN },
        !           157:        { KEYC_PPAGE,               MODEKEYCHOICE_PAGEUP },
        !           158:        { KEYC_UP | KEYC_CTRL,      MODEKEYCHOICE_SCROLLUP },
        !           159:        { KEYC_UP,                  MODEKEYCHOICE_UP },
        !           160:        { ' ',                      MODEKEYCHOICE_TREE_TOGGLE },
        !           161:        { KEYC_LEFT,                MODEKEYCHOICE_TREE_COLLAPSE },
        !           162:        { KEYC_RIGHT,               MODEKEYCHOICE_TREE_EXPAND },
        !           163:        { KEYC_LEFT | KEYC_CTRL,    MODEKEYCHOICE_TREE_COLLAPSE_ALL },
        !           164:        { KEYC_RIGHT | KEYC_CTRL,   MODEKEYCHOICE_TREE_EXPAND_ALL },
        !           165:        { KEYC_MOUSEDOWN1_PANE,     MODEKEYCHOICE_CHOOSE },
        !           166:        { KEYC_MOUSEDOWN3_PANE,     MODEKEYCHOICE_TREE_TOGGLE },
        !           167:        { KEYC_WHEELUP_PANE,        MODEKEYCHOICE_UP },
        !           168:        { KEYC_WHEELDOWN_PANE,      MODEKEYCHOICE_DOWN },
1.8       nicm      169:
1.73    ! nicm      170:        { KEYC_NONE, -1 }
1.8       nicm      171: };
1.10      nicm      172: struct mode_key_tree mode_key_tree_emacs_choice;
1.8       nicm      173:
1.10      nicm      174: /* Table mapping key table names to default settings and trees. */
1.72      nicm      175: static const struct mode_key_table mode_key_tables[] = {
1.10      nicm      176:        { "vi-choice", mode_key_cmdstr_choice,
                    177:          &mode_key_tree_vi_choice, mode_key_vi_choice },
                    178:        { "emacs-choice", mode_key_cmdstr_choice,
                    179:          &mode_key_tree_emacs_choice, mode_key_emacs_choice },
                    180:
                    181:        { NULL, NULL, NULL, NULL }
                    182: };
                    183:
1.44      nicm      184: RB_GENERATE(mode_key_tree, mode_key_binding, entry, mode_key_cmp);
1.10      nicm      185:
                    186: int
                    187: mode_key_cmp(struct mode_key_binding *mbind1, struct mode_key_binding *mbind2)
                    188: {
1.64      nicm      189:        if (mbind1->key < mbind2->key)
                    190:                return (-1);
                    191:        if (mbind1->key > mbind2->key)
                    192:                return (1);
                    193:        return (0);
1.10      nicm      194: }
                    195:
                    196: const char *
1.36      nicm      197: mode_key_tostring(const struct mode_key_cmdstr *cmdstr, enum mode_key_cmd cmd)
1.10      nicm      198: {
                    199:        for (; cmdstr->name != NULL; cmdstr++) {
                    200:                if (cmdstr->cmd == cmd)
                    201:                        return (cmdstr->name);
1.11      nicm      202:        }
                    203:        return (NULL);
                    204: }
                    205:
                    206: enum mode_key_cmd
1.36      nicm      207: mode_key_fromstring(const struct mode_key_cmdstr *cmdstr, const char *name)
1.11      nicm      208: {
                    209:        for (; cmdstr->name != NULL; cmdstr++) {
                    210:                if (strcasecmp(cmdstr->name, name) == 0)
                    211:                        return (cmdstr->cmd);
                    212:        }
                    213:        return (MODEKEY_NONE);
                    214: }
                    215:
                    216: const struct mode_key_table *
                    217: mode_key_findtable(const char *name)
                    218: {
                    219:        const struct mode_key_table     *mtab;
1.25      nicm      220:
1.11      nicm      221:        for (mtab = mode_key_tables; mtab->name != NULL; mtab++) {
                    222:                if (strcasecmp(name, mtab->name) == 0)
                    223:                        return (mtab);
1.10      nicm      224:        }
                    225:        return (NULL);
                    226: }
1.1       nicm      227:
                    228: void
1.10      nicm      229: mode_key_init_trees(void)
1.1       nicm      230: {
1.10      nicm      231:        const struct mode_key_table     *mtab;
                    232:        const struct mode_key_entry     *ment;
                    233:        struct mode_key_binding         *mbind;
                    234:
                    235:        for (mtab = mode_key_tables; mtab->name != NULL; mtab++) {
1.44      nicm      236:                RB_INIT(mtab->tree);
1.73    ! nicm      237:                for (ment = mtab->table; ment->key != KEYC_NONE; ment++) {
1.10      nicm      238:                        mbind = xmalloc(sizeof *mbind);
                    239:                        mbind->key = ment->key;
                    240:                        mbind->cmd = ment->cmd;
1.44      nicm      241:                        RB_INSERT(mode_key_tree, mtab->tree, mbind);
1.10      nicm      242:                }
                    243:        }
                    244: }
                    245:
                    246: void
                    247: mode_key_init(struct mode_key_data *mdata, struct mode_key_tree *mtree)
                    248: {
                    249:        mdata->tree = mtree;
1.1       nicm      250: }
                    251:
                    252: enum mode_key_cmd
1.71      nicm      253: mode_key_lookup(struct mode_key_data *mdata, key_code key)
1.1       nicm      254: {
1.10      nicm      255:        struct mode_key_binding *mbind, mtmp;
                    256:
                    257:        mtmp.key = key;
1.73    ! nicm      258:        if ((mbind = RB_FIND(mode_key_tree, mdata->tree, &mtmp)) == NULL)
1.10      nicm      259:                return (MODEKEY_OTHER);
1.73    ! nicm      260:        return (mbind->cmd);
1.1       nicm      261: }