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

1.70    ! nicm        1: /* $OpenBSD: mode-key.c,v 1.69 2016/09/12 15:40:58 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:
                     41: /* Entry in the default mode key tables. */
                     42: struct mode_key_entry {
1.64      nicm       43:        key_code                key;
1.63      nicm       44:
                     45:        /*
                     46:         * Editing mode for vi: 0 is edit mode, keys not in the table are
                     47:         * returned as MODEKEY_OTHER; 1 is command mode, keys not in the table
                     48:         * are returned as MODEKEY_NONE. This is also matched on, allowing some
                     49:         * keys to be bound in edit mode.
                     50:         */
                     51:        int                     mode;
                     52:        enum mode_key_cmd       cmd;
1.69      nicm       53:        u_int                   repeat;
1.63      nicm       54: };
1.10      nicm       55:
                     56: /* Edit keys command strings. */
1.70    ! nicm       57: static const struct mode_key_cmdstr mode_key_cmdstr_edit[] = {
1.10      nicm       58:        { MODEKEYEDIT_BACKSPACE, "backspace" },
1.25      nicm       59:        { MODEKEYEDIT_CANCEL, "cancel" },
1.10      nicm       60:        { MODEKEYEDIT_COMPLETE, "complete" },
                     61:        { MODEKEYEDIT_CURSORLEFT, "cursor-left" },
                     62:        { MODEKEYEDIT_CURSORRIGHT, "cursor-right" },
                     63:        { MODEKEYEDIT_DELETE, "delete" },
1.16      nicm       64:        { MODEKEYEDIT_DELETELINE, "delete-line" },
1.10      nicm       65:        { MODEKEYEDIT_DELETETOENDOFLINE, "delete-end-of-line" },
1.40      nicm       66:        { MODEKEYEDIT_DELETEWORD, "delete-word" },
1.10      nicm       67:        { MODEKEYEDIT_ENDOFLINE, "end-of-line" },
                     68:        { MODEKEYEDIT_ENTER, "enter" },
                     69:        { MODEKEYEDIT_HISTORYDOWN, "history-down" },
                     70:        { MODEKEYEDIT_HISTORYUP, "history-up" },
1.43      nicm       71:        { MODEKEYEDIT_NEXTSPACE, "next-space" },
                     72:        { MODEKEYEDIT_NEXTSPACEEND, "next-space-end" },
1.40      nicm       73:        { MODEKEYEDIT_NEXTWORD, "next-word" },
                     74:        { MODEKEYEDIT_NEXTWORDEND, "next-word-end" },
1.10      nicm       75:        { MODEKEYEDIT_PASTE, "paste" },
1.43      nicm       76:        { MODEKEYEDIT_PREVIOUSSPACE, "previous-space" },
1.40      nicm       77:        { MODEKEYEDIT_PREVIOUSWORD, "previous-word" },
1.10      nicm       78:        { MODEKEYEDIT_STARTOFLINE, "start-of-line" },
                     79:        { MODEKEYEDIT_SWITCHMODE, "switch-mode" },
                     80:        { MODEKEYEDIT_SWITCHMODEAPPEND, "switch-mode-append" },
1.45      nicm       81:        { MODEKEYEDIT_SWITCHMODEAPPENDLINE, "switch-mode-append-line" },
                     82:        { MODEKEYEDIT_SWITCHMODEBEGINLINE, "switch-mode-begin-line" },
1.53      nicm       83:        { MODEKEYEDIT_SWITCHMODECHANGELINE, "switch-mode-change-line" },
                     84:        { MODEKEYEDIT_SWITCHMODESUBSTITUTE, "switch-mode-substitute" },
                     85:        { MODEKEYEDIT_SWITCHMODESUBSTITUTELINE, "switch-mode-substitute-line" },
1.17      nicm       86:        { MODEKEYEDIT_TRANSPOSECHARS, "transpose-chars" },
1.11      nicm       87:
                     88:        { 0, NULL }
1.10      nicm       89: };
1.25      nicm       90:
1.10      nicm       91: /* Choice keys command strings. */
1.70    ! nicm       92: static const struct mode_key_cmdstr mode_key_cmdstr_choice[] = {
1.46      nicm       93:        { MODEKEYCHOICE_BACKSPACE, "backspace" },
1.57      nicm       94:        { MODEKEYCHOICE_BOTTOMLINE, "bottom-line"},
1.10      nicm       95:        { MODEKEYCHOICE_CANCEL, "cancel" },
                     96:        { MODEKEYCHOICE_CHOOSE, "choose" },
                     97:        { MODEKEYCHOICE_DOWN, "down" },
1.57      nicm       98:        { MODEKEYCHOICE_ENDOFLIST, "end-of-list"},
1.10      nicm       99:        { MODEKEYCHOICE_PAGEDOWN, "page-down" },
                    100:        { MODEKEYCHOICE_PAGEUP, "page-up" },
1.30      nicm      101:        { MODEKEYCHOICE_SCROLLDOWN, "scroll-down" },
                    102:        { MODEKEYCHOICE_SCROLLUP, "scroll-up" },
1.46      nicm      103:        { MODEKEYCHOICE_STARTNUMBERPREFIX, "start-number-prefix" },
1.57      nicm      104:        { MODEKEYCHOICE_STARTOFLIST, "start-of-list"},
                    105:        { MODEKEYCHOICE_TOPLINE, "top-line"},
1.49      nicm      106:        { MODEKEYCHOICE_TREE_COLLAPSE, "tree-collapse" },
1.48      nicm      107:        { MODEKEYCHOICE_TREE_COLLAPSE_ALL, "tree-collapse-all" },
1.49      nicm      108:        { MODEKEYCHOICE_TREE_EXPAND, "tree-expand" },
1.48      nicm      109:        { MODEKEYCHOICE_TREE_EXPAND_ALL, "tree-expand-all" },
                    110:        { MODEKEYCHOICE_TREE_TOGGLE, "tree-toggle" },
1.10      nicm      111:        { MODEKEYCHOICE_UP, "up" },
1.11      nicm      112:
                    113:        { 0, NULL }
1.10      nicm      114: };
                    115:
                    116: /* Copy keys command strings. */
1.70    ! nicm      117: static const struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
1.58      nicm      118:        { MODEKEYCOPY_APPENDSELECTION, "append-selection" },
1.15      nicm      119:        { MODEKEYCOPY_BACKTOINDENTATION, "back-to-indentation" },
1.23      nicm      120:        { MODEKEYCOPY_BOTTOMLINE, "bottom-line" },
1.10      nicm      121:        { MODEKEYCOPY_CANCEL, "cancel" },
                    122:        { MODEKEYCOPY_CLEARSELECTION, "clear-selection" },
1.52      nicm      123:        { MODEKEYCOPY_COPYPIPE, "copy-pipe" },
1.38      nicm      124:        { MODEKEYCOPY_COPYLINE, "copy-line" },
                    125:        { MODEKEYCOPY_COPYENDOFLINE, "copy-end-of-line" },
1.10      nicm      126:        { MODEKEYCOPY_COPYSELECTION, "copy-selection" },
                    127:        { MODEKEYCOPY_DOWN, "cursor-down" },
                    128:        { MODEKEYCOPY_ENDOFLINE, "end-of-line" },
1.15      nicm      129:        { MODEKEYCOPY_GOTOLINE, "goto-line" },
1.50      nicm      130:        { MODEKEYCOPY_HALFPAGEDOWN, "halfpage-down" },
                    131:        { MODEKEYCOPY_HALFPAGEUP, "halfpage-up" },
1.27      nicm      132:        { MODEKEYCOPY_HISTORYBOTTOM, "history-bottom" },
                    133:        { MODEKEYCOPY_HISTORYTOP, "history-top" },
1.35      nicm      134:        { MODEKEYCOPY_JUMP, "jump-forward" },
                    135:        { MODEKEYCOPY_JUMPAGAIN, "jump-again" },
                    136:        { MODEKEYCOPY_JUMPREVERSE, "jump-reverse" },
                    137:        { MODEKEYCOPY_JUMPBACK, "jump-backward" },
1.42      nicm      138:        { MODEKEYCOPY_JUMPTO, "jump-to-forward" },
                    139:        { MODEKEYCOPY_JUMPTOBACK, "jump-to-backward" },
1.10      nicm      140:        { MODEKEYCOPY_LEFT, "cursor-left" },
1.32      nicm      141:        { MODEKEYCOPY_RECTANGLETOGGLE, "rectangle-toggle" },
1.23      nicm      142:        { MODEKEYCOPY_MIDDLELINE, "middle-line" },
1.10      nicm      143:        { MODEKEYCOPY_NEXTPAGE, "page-down" },
1.68      nicm      144:        { MODEKEYCOPY_NEXTPARAGRAPH, "next-paragraph" },
1.31      nicm      145:        { MODEKEYCOPY_NEXTSPACE, "next-space" },
                    146:        { MODEKEYCOPY_NEXTSPACEEND, "next-space-end" },
1.10      nicm      147:        { MODEKEYCOPY_NEXTWORD, "next-word" },
1.28      nicm      148:        { MODEKEYCOPY_NEXTWORDEND, "next-word-end" },
1.60      nicm      149:        { MODEKEYCOPY_OTHEREND, "other-end" },
1.10      nicm      150:        { MODEKEYCOPY_PREVIOUSPAGE, "page-up" },
1.68      nicm      151:        { MODEKEYCOPY_PREVIOUSPARAGRAPH, "previous-paragraph" },
1.31      nicm      152:        { MODEKEYCOPY_PREVIOUSSPACE, "previous-space" },
1.10      nicm      153:        { MODEKEYCOPY_PREVIOUSWORD, "previous-word" },
                    154:        { MODEKEYCOPY_RIGHT, "cursor-right" },
1.21      nicm      155:        { MODEKEYCOPY_SCROLLDOWN, "scroll-down" },
                    156:        { MODEKEYCOPY_SCROLLUP, "scroll-up" },
1.15      nicm      157:        { MODEKEYCOPY_SEARCHAGAIN, "search-again" },
                    158:        { MODEKEYCOPY_SEARCHDOWN, "search-forward" },
1.33      nicm      159:        { MODEKEYCOPY_SEARCHREVERSE, "search-reverse" },
1.15      nicm      160:        { MODEKEYCOPY_SEARCHUP, "search-backward" },
1.38      nicm      161:        { MODEKEYCOPY_SELECTLINE, "select-line" },
1.59      nicm      162:        { MODEKEYCOPY_STARTNAMEDBUFFER, "start-named-buffer" },
1.34      nicm      163:        { MODEKEYCOPY_STARTNUMBERPREFIX, "start-number-prefix" },
1.10      nicm      164:        { MODEKEYCOPY_STARTOFLINE, "start-of-line" },
                    165:        { MODEKEYCOPY_STARTSELECTION, "begin-selection" },
1.23      nicm      166:        { MODEKEYCOPY_TOPLINE, "top-line" },
1.10      nicm      167:        { MODEKEYCOPY_UP, "cursor-up" },
1.11      nicm      168:
                    169:        { 0, NULL }
1.10      nicm      170: };
                    171:
1.8       nicm      172: /* vi editing keys. */
1.70    ! nicm      173: static const struct mode_key_entry mode_key_vi_edit[] = {
1.69      nicm      174:        { '\003' /* C-c */,         0, MODEKEYEDIT_CANCEL, 1 },
                    175:        { '\010' /* C-h */,         0, MODEKEYEDIT_BACKSPACE, 1 },
                    176:        { '\011' /* Tab */,         0, MODEKEYEDIT_COMPLETE, 1 },
                    177:        { '\025' /* C-u */,         0, MODEKEYEDIT_DELETELINE, 1 },
                    178:        { '\027' /* C-w */,         0, MODEKEYEDIT_DELETEWORD, 1 },
                    179:        { '\033' /* Escape */,      0, MODEKEYEDIT_SWITCHMODE, 1 },
                    180:        { '\n',                     0, MODEKEYEDIT_ENTER, 1 },
                    181:        { '\r',                     0, MODEKEYEDIT_ENTER, 1 },
                    182:        { KEYC_BSPACE,              0, MODEKEYEDIT_BACKSPACE, 1 },
                    183:        { KEYC_DC,                  0, MODEKEYEDIT_DELETE, 1 },
                    184:        { KEYC_DOWN,                0, MODEKEYEDIT_HISTORYDOWN, 1 },
                    185:        { KEYC_LEFT,                0, MODEKEYEDIT_CURSORLEFT, 1 },
                    186:        { KEYC_RIGHT,               0, MODEKEYEDIT_CURSORRIGHT, 1 },
                    187:        { KEYC_UP,                  0, MODEKEYEDIT_HISTORYUP, 1 },
                    188:        { KEYC_HOME,                0, MODEKEYEDIT_STARTOFLINE, 1 },
                    189:        { KEYC_END,                 0, MODEKEYEDIT_ENDOFLINE, 1 },
                    190:
                    191:        { '$',                      1, MODEKEYEDIT_ENDOFLINE, 1 },
                    192:        { '0',                      1, MODEKEYEDIT_STARTOFLINE, 1 },
                    193:        { 'A',                      1, MODEKEYEDIT_SWITCHMODEAPPENDLINE, 1 },
                    194:        { 'B',                      1, MODEKEYEDIT_PREVIOUSSPACE, 1 },
                    195:        { 'C',                      1, MODEKEYEDIT_SWITCHMODECHANGELINE, 1 },
                    196:        { 'D',                      1, MODEKEYEDIT_DELETETOENDOFLINE, 1 },
                    197:        { 'E',                      1, MODEKEYEDIT_NEXTSPACEEND, 1 },
                    198:        { 'I',                      1, MODEKEYEDIT_SWITCHMODEBEGINLINE, 1 },
                    199:        { 'S',                      1, MODEKEYEDIT_SWITCHMODESUBSTITUTELINE, 1 },
                    200:        { 'W',                      1, MODEKEYEDIT_NEXTSPACE, 1 },
                    201:        { 'X',                      1, MODEKEYEDIT_BACKSPACE, 1 },
                    202:        { '\003' /* C-c */,         1, MODEKEYEDIT_CANCEL, 1 },
                    203:        { '\010' /* C-h */,         1, MODEKEYEDIT_BACKSPACE, 1 },
                    204:        { '\n',                     1, MODEKEYEDIT_ENTER, 1 },
                    205:        { '\r',                     1, MODEKEYEDIT_ENTER, 1 },
                    206:        { '^',                      1, MODEKEYEDIT_STARTOFLINE, 1 },
                    207:        { 'a',                      1, MODEKEYEDIT_SWITCHMODEAPPEND, 1 },
                    208:        { 'b',                      1, MODEKEYEDIT_PREVIOUSWORD, 1 },
                    209:        { 'd',                      1, MODEKEYEDIT_DELETELINE, 1 },
                    210:        { 'e',                      1, MODEKEYEDIT_NEXTWORDEND, 1 },
                    211:        { 'h',                      1, MODEKEYEDIT_CURSORLEFT, 1 },
                    212:        { 'i',                      1, MODEKEYEDIT_SWITCHMODE, 1 },
                    213:        { 'j',                      1, MODEKEYEDIT_HISTORYDOWN, 1 },
                    214:        { 'k',                      1, MODEKEYEDIT_HISTORYUP, 1 },
                    215:        { 'l',                      1, MODEKEYEDIT_CURSORRIGHT, 1 },
                    216:        { 'p',                      1, MODEKEYEDIT_PASTE, 1 },
                    217:        { 's',                      1, MODEKEYEDIT_SWITCHMODESUBSTITUTE, 1 },
                    218:        { 'w',                      1, MODEKEYEDIT_NEXTWORD, 1 },
                    219:        { 'x',                      1, MODEKEYEDIT_DELETE, 1 },
                    220:        { KEYC_BSPACE,              1, MODEKEYEDIT_BACKSPACE, 1 },
                    221:        { KEYC_DC,                  1, MODEKEYEDIT_DELETE, 1 },
                    222:        { KEYC_DOWN,                1, MODEKEYEDIT_HISTORYDOWN, 1 },
                    223:        { KEYC_LEFT,                1, MODEKEYEDIT_CURSORLEFT, 1 },
                    224:        { KEYC_RIGHT,               1, MODEKEYEDIT_CURSORRIGHT, 1 },
                    225:        { KEYC_UP,                  1, MODEKEYEDIT_HISTORYUP, 1 },
1.8       nicm      226:
1.69      nicm      227:        { 0,                       -1, 0, 1 }
1.8       nicm      228: };
1.10      nicm      229: struct mode_key_tree mode_key_tree_vi_edit;
1.8       nicm      230:
                    231: /* vi choice selection keys. */
1.70    ! nicm      232: static const struct mode_key_entry mode_key_vi_choice[] = {
1.69      nicm      233:        { '0' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    234:        { '1' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    235:        { '2' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    236:        { '3' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    237:        { '4' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    238:        { '5' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    239:        { '6' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    240:        { '7' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    241:        { '8' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    242:        { '9' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    243:        { '\002' /* C-b */,         0, MODEKEYCHOICE_PAGEUP, 1 },
                    244:        { '\003' /* C-c */,         0, MODEKEYCHOICE_CANCEL, 1 },
                    245:        { '\005' /* C-e */,         0, MODEKEYCHOICE_SCROLLDOWN, 1 },
                    246:        { '\006' /* C-f */,         0, MODEKEYCHOICE_PAGEDOWN, 1 },
                    247:        { '\031' /* C-y */,         0, MODEKEYCHOICE_SCROLLUP, 1 },
                    248:        { '\n',                     0, MODEKEYCHOICE_CHOOSE, 1 },
                    249:        { '\r',                     0, MODEKEYCHOICE_CHOOSE, 1 },
                    250:        { 'j',                      0, MODEKEYCHOICE_DOWN, 1 },
                    251:        { 'k',                      0, MODEKEYCHOICE_UP, 1 },
                    252:        { 'q',                      0, MODEKEYCHOICE_CANCEL, 1 },
                    253:        { KEYC_HOME,                0, MODEKEYCHOICE_STARTOFLIST, 1 },
                    254:        { 'g',                      0, MODEKEYCHOICE_STARTOFLIST, 1 },
                    255:        { 'H',                      0, MODEKEYCHOICE_TOPLINE, 1 },
                    256:        { 'L',                      0, MODEKEYCHOICE_BOTTOMLINE, 1 },
                    257:        { 'G',                      0, MODEKEYCHOICE_ENDOFLIST, 1 },
                    258:        { KEYC_END,                 0, MODEKEYCHOICE_ENDOFLIST, 1 },
                    259:        { KEYC_BSPACE,              0, MODEKEYCHOICE_BACKSPACE, 1 },
                    260:        { KEYC_DOWN | KEYC_CTRL,    0, MODEKEYCHOICE_SCROLLDOWN, 1 },
                    261:        { KEYC_DOWN,                0, MODEKEYCHOICE_DOWN, 1 },
                    262:        { KEYC_NPAGE,               0, MODEKEYCHOICE_PAGEDOWN, 1 },
                    263:        { KEYC_PPAGE,               0, MODEKEYCHOICE_PAGEUP, 1 },
                    264:        { KEYC_UP | KEYC_CTRL,      0, MODEKEYCHOICE_SCROLLUP, 1 },
                    265:        { KEYC_UP,                  0, MODEKEYCHOICE_UP, 1 },
                    266:        { ' ',                      0, MODEKEYCHOICE_TREE_TOGGLE, 1 },
                    267:        { KEYC_LEFT,                0, MODEKEYCHOICE_TREE_COLLAPSE, 1 },
                    268:        { KEYC_RIGHT,               0, MODEKEYCHOICE_TREE_EXPAND, 1 },
                    269:        { KEYC_LEFT | KEYC_CTRL,    0, MODEKEYCHOICE_TREE_COLLAPSE_ALL, 1 },
                    270:        { KEYC_RIGHT | KEYC_CTRL,   0, MODEKEYCHOICE_TREE_EXPAND_ALL, 1 },
                    271:        { KEYC_MOUSEDOWN1_PANE,     0, MODEKEYCHOICE_CHOOSE, 1 },
                    272:        { KEYC_MOUSEDOWN3_PANE,     0, MODEKEYCHOICE_TREE_TOGGLE, 1 },
                    273:        { KEYC_WHEELUP_PANE,        0, MODEKEYCHOICE_UP, 1 },
                    274:        { KEYC_WHEELDOWN_PANE,      0, MODEKEYCHOICE_DOWN, 1 },
1.8       nicm      275:
1.69      nicm      276:        { 0,                       -1, 0, 1 }
1.8       nicm      277: };
1.10      nicm      278: struct mode_key_tree mode_key_tree_vi_choice;
1.8       nicm      279:
                    280: /* vi copy mode keys. */
1.70    ! nicm      281: static const struct mode_key_entry mode_key_vi_copy[] = {
1.69      nicm      282:        { ' ',                      0, MODEKEYCOPY_STARTSELECTION, 1 },
                    283:        { '"',                      0, MODEKEYCOPY_STARTNAMEDBUFFER, 1 },
                    284:        { '$',                      0, MODEKEYCOPY_ENDOFLINE, 1 },
                    285:        { ',',                      0, MODEKEYCOPY_JUMPREVERSE, 1 },
                    286:        { ';',                      0, MODEKEYCOPY_JUMPAGAIN, 1 },
                    287:        { '/',                      0, MODEKEYCOPY_SEARCHDOWN, 1 },
                    288:        { '0',                      0, MODEKEYCOPY_STARTOFLINE, 1 },
                    289:        { '1',                      0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
                    290:        { '2',                      0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
                    291:        { '3',                      0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
                    292:        { '4',                      0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
                    293:        { '5',                      0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
                    294:        { '6',                      0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
                    295:        { '7',                      0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
                    296:        { '8',                      0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
                    297:        { '9',                      0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
                    298:        { ':',                      0, MODEKEYCOPY_GOTOLINE, 1 },
                    299:        { '?',                      0, MODEKEYCOPY_SEARCHUP, 1 },
                    300:        { 'A',                      0, MODEKEYCOPY_APPENDSELECTION, 1 },
                    301:        { 'B',                      0, MODEKEYCOPY_PREVIOUSSPACE, 1 },
                    302:        { 'D',                      0, MODEKEYCOPY_COPYENDOFLINE, 1 },
                    303:        { 'E',                      0, MODEKEYCOPY_NEXTSPACEEND, 1 },
                    304:        { 'F',                      0, MODEKEYCOPY_JUMPBACK, 1 },
                    305:        { 'G',                      0, MODEKEYCOPY_HISTORYBOTTOM, 1 },
                    306:        { 'H',                      0, MODEKEYCOPY_TOPLINE, 1 },
                    307:        { 'J',                      0, MODEKEYCOPY_SCROLLDOWN, 1 },
                    308:        { 'K',                      0, MODEKEYCOPY_SCROLLUP, 1 },
                    309:        { 'L',                      0, MODEKEYCOPY_BOTTOMLINE, 1 },
                    310:        { 'M',                      0, MODEKEYCOPY_MIDDLELINE, 1 },
                    311:        { 'N',                      0, MODEKEYCOPY_SEARCHREVERSE, 1 },
                    312:        { 'T',                      0, MODEKEYCOPY_JUMPTOBACK, 1 },
                    313:        { 'V',                      0, MODEKEYCOPY_SELECTLINE, 1 },
                    314:        { 'W',                      0, MODEKEYCOPY_NEXTSPACE, 1 },
                    315:        { '\002' /* C-b */,         0, MODEKEYCOPY_PREVIOUSPAGE, 1 },
                    316:        { '\003' /* C-c */,         0, MODEKEYCOPY_CANCEL, 1 },
                    317:        { '\004' /* C-d */,         0, MODEKEYCOPY_HALFPAGEDOWN, 1 },
                    318:        { '\005' /* C-e */,         0, MODEKEYCOPY_SCROLLDOWN, 1 },
                    319:        { '\006' /* C-f */,         0, MODEKEYCOPY_NEXTPAGE, 1 },
                    320:        { '\010' /* C-h */,         0, MODEKEYCOPY_LEFT, 1 },
                    321:        { '\025' /* C-u */,         0, MODEKEYCOPY_HALFPAGEUP, 1 },
                    322:        { '\031' /* C-y */,         0, MODEKEYCOPY_SCROLLUP, 1 },
                    323:        { '\033' /* Escape */,      0, MODEKEYCOPY_CLEARSELECTION, 1 },
                    324:        { '\n',                     0, MODEKEYCOPY_COPYSELECTION, 1 },
                    325:        { '\r',                     0, MODEKEYCOPY_COPYSELECTION, 1 },
                    326:        { '^',                      0, MODEKEYCOPY_BACKTOINDENTATION, 1 },
                    327:        { 'b',                      0, MODEKEYCOPY_PREVIOUSWORD, 1 },
                    328:        { 'e',                      0, MODEKEYCOPY_NEXTWORDEND, 1 },
                    329:        { 'f',                      0, MODEKEYCOPY_JUMP, 1 },
                    330:        { 'g',                      0, MODEKEYCOPY_HISTORYTOP, 1 },
                    331:        { 'h',                      0, MODEKEYCOPY_LEFT, 1 },
                    332:        { 'j',                      0, MODEKEYCOPY_DOWN, 1 },
                    333:        { 'k',                      0, MODEKEYCOPY_UP, 1 },
                    334:        { 'l',                      0, MODEKEYCOPY_RIGHT, 1 },
                    335:        { 'n',                      0, MODEKEYCOPY_SEARCHAGAIN, 1 },
                    336:        { 'o',                      0, MODEKEYCOPY_OTHEREND, 1 },
                    337:        { 't',                      0, MODEKEYCOPY_JUMPTO, 1 },
                    338:        { 'q',                      0, MODEKEYCOPY_CANCEL, 1 },
                    339:        { 'v',                      0, MODEKEYCOPY_RECTANGLETOGGLE, 1 },
                    340:        { 'w',                      0, MODEKEYCOPY_NEXTWORD, 1 },
                    341:        { '{',                      0, MODEKEYCOPY_PREVIOUSPARAGRAPH, 1 },
                    342:        { '}',                      0, MODEKEYCOPY_NEXTPARAGRAPH, 1 },
                    343:        { KEYC_BSPACE,              0, MODEKEYCOPY_LEFT, 1 },
                    344:        { KEYC_DOWN | KEYC_CTRL,    0, MODEKEYCOPY_SCROLLDOWN, 1 },
                    345:        { KEYC_DOWN,                0, MODEKEYCOPY_DOWN, 1 },
                    346:        { KEYC_LEFT,                0, MODEKEYCOPY_LEFT, 1 },
                    347:        { KEYC_NPAGE,               0, MODEKEYCOPY_NEXTPAGE, 1 },
                    348:        { KEYC_PPAGE,               0, MODEKEYCOPY_PREVIOUSPAGE, 1 },
                    349:        { KEYC_RIGHT,               0, MODEKEYCOPY_RIGHT, 1 },
                    350:        { KEYC_UP | KEYC_CTRL,      0, MODEKEYCOPY_SCROLLUP, 1 },
                    351:        { KEYC_UP,                  0, MODEKEYCOPY_UP, 1 },
                    352:        { KEYC_WHEELUP_PANE,        0, MODEKEYCOPY_SCROLLUP, 1 },
                    353:        { KEYC_WHEELDOWN_PANE,      0, MODEKEYCOPY_SCROLLDOWN, 1 },
                    354:        { KEYC_MOUSEDRAG1_PANE,     0, MODEKEYCOPY_STARTSELECTION, 1 },
                    355:        { KEYC_MOUSEDRAGEND1_PANE,  0, MODEKEYCOPY_COPYSELECTION, 1 },
1.25      nicm      356:
1.69      nicm      357:        { 0,                       -1, 0, 1 }
1.8       nicm      358: };
1.10      nicm      359: struct mode_key_tree mode_key_tree_vi_copy;
1.8       nicm      360:
                    361: /* emacs editing keys. */
1.70    ! nicm      362: static const struct mode_key_entry mode_key_emacs_edit[] = {
1.69      nicm      363:        { '\001' /* C-a */,         0, MODEKEYEDIT_STARTOFLINE, 1 },
                    364:        { '\002' /* C-b */,         0, MODEKEYEDIT_CURSORLEFT, 1 },
                    365:        { '\003' /* C-c */,         0, MODEKEYEDIT_CANCEL, 1 },
                    366:        { '\004' /* C-d */,         0, MODEKEYEDIT_DELETE, 1 },
                    367:        { '\005' /* C-e */,         0, MODEKEYEDIT_ENDOFLINE, 1 },
                    368:        { '\006' /* C-f */,         0, MODEKEYEDIT_CURSORRIGHT, 1 },
                    369:        { '\010' /* C-H */,         0, MODEKEYEDIT_BACKSPACE, 1 },
                    370:        { '\011' /* Tab */,         0, MODEKEYEDIT_COMPLETE, 1 },
                    371:        { '\013' /* C-k */,         0, MODEKEYEDIT_DELETETOENDOFLINE, 1 },
                    372:        { '\016' /* C-n */,         0, MODEKEYEDIT_HISTORYDOWN, 1 },
                    373:        { '\020' /* C-p */,         0, MODEKEYEDIT_HISTORYUP, 1 },
                    374:        { '\024' /* C-t */,         0, MODEKEYEDIT_TRANSPOSECHARS, 1 },
                    375:        { '\025' /* C-u */,         0, MODEKEYEDIT_DELETELINE, 1 },
                    376:        { '\027' /* C-w */,         0, MODEKEYEDIT_DELETEWORD, 1 },
                    377:        { '\031' /* C-y */,         0, MODEKEYEDIT_PASTE, 1 },
                    378:        { '\033' /* Escape */,      0, MODEKEYEDIT_CANCEL, 1 },
                    379:        { '\n',                     0, MODEKEYEDIT_ENTER, 1 },
                    380:        { '\r',                     0, MODEKEYEDIT_ENTER, 1 },
                    381:        { 'b' | KEYC_ESCAPE,        0, MODEKEYEDIT_PREVIOUSWORD, 1 },
                    382:        { 'f' | KEYC_ESCAPE,        0, MODEKEYEDIT_NEXTWORDEND, 1 },
                    383:        { 'm' | KEYC_ESCAPE,        0, MODEKEYEDIT_STARTOFLINE, 1 },
                    384:        { KEYC_BSPACE,              0, MODEKEYEDIT_BACKSPACE, 1 },
                    385:        { KEYC_DC,                  0, MODEKEYEDIT_DELETE, 1 },
                    386:        { KEYC_DOWN,                0, MODEKEYEDIT_HISTORYDOWN, 1 },
                    387:        { KEYC_LEFT,                0, MODEKEYEDIT_CURSORLEFT, 1 },
                    388:        { KEYC_RIGHT,               0, MODEKEYEDIT_CURSORRIGHT, 1 },
                    389:        { KEYC_UP,                  0, MODEKEYEDIT_HISTORYUP, 1 },
                    390:        { KEYC_HOME,                0, MODEKEYEDIT_STARTOFLINE, 1 },
                    391:        { KEYC_END,                 0, MODEKEYEDIT_ENDOFLINE, 1 },
1.8       nicm      392:
1.69      nicm      393:        { 0,                       -1, 0, 1 }
1.8       nicm      394: };
1.10      nicm      395: struct mode_key_tree mode_key_tree_emacs_edit;
1.8       nicm      396:
                    397: /* emacs choice selection keys. */
1.70    ! nicm      398: static const struct mode_key_entry mode_key_emacs_choice[] = {
1.69      nicm      399:        { '0' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    400:        { '1' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    401:        { '2' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    402:        { '3' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    403:        { '4' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    404:        { '5' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    405:        { '6' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    406:        { '7' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    407:        { '8' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    408:        { '9' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
                    409:        { '\003' /* C-c */,         0, MODEKEYCHOICE_CANCEL, 1 },
                    410:        { '\016' /* C-n */,         0, MODEKEYCHOICE_DOWN, 1 },
                    411:        { '\020' /* C-p */,         0, MODEKEYCHOICE_UP, 1 },
                    412:        { '\026' /* C-v */,         0, MODEKEYCHOICE_PAGEDOWN, 1 },
                    413:        { '\033' /* Escape */,      0, MODEKEYCHOICE_CANCEL, 1 },
                    414:        { '\n',                     0, MODEKEYCHOICE_CHOOSE, 1 },
                    415:        { '\r',                     0, MODEKEYCHOICE_CHOOSE, 1 },
                    416:        { 'q',                      0, MODEKEYCHOICE_CANCEL, 1 },
                    417:        { 'v' | KEYC_ESCAPE,        0, MODEKEYCHOICE_PAGEUP, 1 },
                    418:        { KEYC_HOME,                0, MODEKEYCHOICE_STARTOFLIST, 1 },
                    419:        { '<' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTOFLIST, 1 },
                    420:        { 'R' | KEYC_ESCAPE,        0, MODEKEYCHOICE_TOPLINE, 1 },
                    421:        { '>' | KEYC_ESCAPE,        0, MODEKEYCHOICE_ENDOFLIST, 1 },
                    422:        { KEYC_END,                 0, MODEKEYCHOICE_ENDOFLIST, 1 },
                    423:        { KEYC_BSPACE,              0, MODEKEYCHOICE_BACKSPACE, 1 },
                    424:        { KEYC_DOWN | KEYC_CTRL,    0, MODEKEYCHOICE_SCROLLDOWN, 1 },
                    425:        { KEYC_DOWN,                0, MODEKEYCHOICE_DOWN, 1 },
                    426:        { KEYC_NPAGE,               0, MODEKEYCHOICE_PAGEDOWN, 1 },
                    427:        { KEYC_PPAGE,               0, MODEKEYCHOICE_PAGEUP, 1 },
                    428:        { KEYC_UP | KEYC_CTRL,      0, MODEKEYCHOICE_SCROLLUP, 1 },
                    429:        { KEYC_UP,                  0, MODEKEYCHOICE_UP, 1 },
                    430:        { ' ',                      0, MODEKEYCHOICE_TREE_TOGGLE, 1 },
                    431:        { KEYC_LEFT,                0, MODEKEYCHOICE_TREE_COLLAPSE, 1 },
                    432:        { KEYC_RIGHT,               0, MODEKEYCHOICE_TREE_EXPAND, 1 },
                    433:        { KEYC_LEFT | KEYC_CTRL,    0, MODEKEYCHOICE_TREE_COLLAPSE_ALL, 1 },
                    434:        { KEYC_RIGHT | KEYC_CTRL,   0, MODEKEYCHOICE_TREE_EXPAND_ALL, 1 },
                    435:        { KEYC_MOUSEDOWN1_PANE,     0, MODEKEYCHOICE_CHOOSE, 1 },
                    436:        { KEYC_MOUSEDOWN3_PANE,     0, MODEKEYCHOICE_TREE_TOGGLE, 1 },
                    437:        { KEYC_WHEELUP_PANE,        0, MODEKEYCHOICE_UP, 5 },
                    438:        { KEYC_WHEELDOWN_PANE,      0, MODEKEYCHOICE_DOWN, 5 },
1.8       nicm      439:
1.69      nicm      440:        { 0,                       -1, 0, 1 }
1.8       nicm      441: };
1.10      nicm      442: struct mode_key_tree mode_key_tree_emacs_choice;
1.8       nicm      443:
                    444: /* emacs copy mode keys. */
1.70    ! nicm      445: static const struct mode_key_entry mode_key_emacs_copy[] = {
1.69      nicm      446:        { ' ',                      0, MODEKEYCOPY_NEXTPAGE, 1 },
                    447:        { ',',                      0, MODEKEYCOPY_JUMPREVERSE, 1 },
                    448:        { ';',                      0, MODEKEYCOPY_JUMPAGAIN, 1 },
                    449:        { '1' | KEYC_ESCAPE,        0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
                    450:        { '2' | KEYC_ESCAPE,        0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
                    451:        { '3' | KEYC_ESCAPE,        0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
                    452:        { '4' | KEYC_ESCAPE,        0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
                    453:        { '5' | KEYC_ESCAPE,        0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
                    454:        { '6' | KEYC_ESCAPE,        0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
                    455:        { '7' | KEYC_ESCAPE,        0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
                    456:        { '8' | KEYC_ESCAPE,        0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
                    457:        { '9' | KEYC_ESCAPE,        0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
                    458:        { '<' | KEYC_ESCAPE,        0, MODEKEYCOPY_HISTORYTOP, 1 },
                    459:        { '>' | KEYC_ESCAPE,        0, MODEKEYCOPY_HISTORYBOTTOM, 1 },
                    460:        { 'F',                      0, MODEKEYCOPY_JUMPBACK, 1 },
                    461:        { 'N',                      0, MODEKEYCOPY_SEARCHREVERSE, 1 },
                    462:        { 'R' | KEYC_ESCAPE,        0, MODEKEYCOPY_TOPLINE, 1 },
                    463:        { 'R',                      0, MODEKEYCOPY_RECTANGLETOGGLE, 1 },
                    464:        { 'T',                      0, MODEKEYCOPY_JUMPTOBACK, 1 },
                    465:        { '\000' /* C-Space */,     0, MODEKEYCOPY_STARTSELECTION, 1 },
                    466:        { '\001' /* C-a */,         0, MODEKEYCOPY_STARTOFLINE, 1 },
                    467:        { '\002' /* C-b */,         0, MODEKEYCOPY_LEFT, 1 },
                    468:        { '\003' /* C-c */,         0, MODEKEYCOPY_CANCEL, 1 },
                    469:        { '\005' /* C-e */,         0, MODEKEYCOPY_ENDOFLINE, 1 },
                    470:        { '\006' /* C-f */,         0, MODEKEYCOPY_RIGHT, 1 },
                    471:        { '\007' /* C-g */,         0, MODEKEYCOPY_CLEARSELECTION, 1 },
                    472:        { '\013' /* C-k */,         0, MODEKEYCOPY_COPYENDOFLINE, 1 },
                    473:        { '\016' /* C-n */,         0, MODEKEYCOPY_DOWN, 1 },
                    474:        { '\020' /* C-p */,         0, MODEKEYCOPY_UP, 1 },
                    475:        { '\022' /* C-r */,         0, MODEKEYCOPY_SEARCHUP, 1 },
                    476:        { '\023' /* C-s */,         0, MODEKEYCOPY_SEARCHDOWN, 1 },
                    477:        { '\026' /* C-v */,         0, MODEKEYCOPY_NEXTPAGE, 1 },
                    478:        { '\027' /* C-w */,         0, MODEKEYCOPY_COPYSELECTION, 1 },
                    479:        { '\033' /* Escape */,      0, MODEKEYCOPY_CANCEL, 1 },
                    480:        { 'b' | KEYC_ESCAPE,        0, MODEKEYCOPY_PREVIOUSWORD, 1 },
                    481:        { 'f',                      0, MODEKEYCOPY_JUMP, 1 },
                    482:        { 'f' | KEYC_ESCAPE,        0, MODEKEYCOPY_NEXTWORDEND, 1 },
                    483:        { 'g',                      0, MODEKEYCOPY_GOTOLINE, 1 },
                    484:        { 'm' | KEYC_ESCAPE,        0, MODEKEYCOPY_BACKTOINDENTATION, 1 },
                    485:        { 'n',                      0, MODEKEYCOPY_SEARCHAGAIN, 1 },
                    486:        { 'q',                      0, MODEKEYCOPY_CANCEL, 1 },
                    487:        { 'r' | KEYC_ESCAPE,        0, MODEKEYCOPY_MIDDLELINE, 1 },
                    488:        { 't',                      0, MODEKEYCOPY_JUMPTO, 1 },
                    489:        { 'v' | KEYC_ESCAPE,        0, MODEKEYCOPY_PREVIOUSPAGE, 1 },
                    490:        { 'w' | KEYC_ESCAPE,        0, MODEKEYCOPY_COPYSELECTION, 1 },
                    491:        { '{' | KEYC_ESCAPE,        0, MODEKEYCOPY_PREVIOUSPARAGRAPH, 1 },
                    492:        { '}' | KEYC_ESCAPE,        0, MODEKEYCOPY_NEXTPARAGRAPH, 1 },
                    493:        { KEYC_DOWN | KEYC_CTRL,    0, MODEKEYCOPY_SCROLLDOWN, 1 },
                    494:        { KEYC_DOWN | KEYC_ESCAPE,  0, MODEKEYCOPY_HALFPAGEDOWN, 1 },
                    495:        { KEYC_DOWN,                0, MODEKEYCOPY_DOWN, 1 },
                    496:        { KEYC_LEFT,                0, MODEKEYCOPY_LEFT, 1 },
                    497:        { KEYC_NPAGE,               0, MODEKEYCOPY_NEXTPAGE, 1 },
                    498:        { KEYC_PPAGE,               0, MODEKEYCOPY_PREVIOUSPAGE, 1 },
                    499:        { KEYC_RIGHT,               0, MODEKEYCOPY_RIGHT, 1 },
                    500:        { KEYC_UP | KEYC_CTRL,      0, MODEKEYCOPY_SCROLLUP, 1 },
                    501:        { KEYC_UP | KEYC_ESCAPE,    0, MODEKEYCOPY_HALFPAGEUP, 1 },
                    502:        { KEYC_UP,                  0, MODEKEYCOPY_UP, 1 },
                    503:        { KEYC_WHEELUP_PANE,        0, MODEKEYCOPY_SCROLLUP, 5 },
                    504:        { KEYC_WHEELDOWN_PANE,      0, MODEKEYCOPY_SCROLLDOWN, 5 },
                    505:        { KEYC_MOUSEDRAG1_PANE,     0, MODEKEYCOPY_STARTSELECTION, 1 },
                    506:        { KEYC_MOUSEDRAGEND1_PANE,  0, MODEKEYCOPY_COPYSELECTION, 1 },
1.8       nicm      507:
1.69      nicm      508:        { 0,                       -1, 0, 1 }
1.8       nicm      509: };
1.10      nicm      510: struct mode_key_tree mode_key_tree_emacs_copy;
                    511:
                    512: /* Table mapping key table names to default settings and trees. */
                    513: const struct mode_key_table mode_key_tables[] = {
                    514:        { "vi-edit", mode_key_cmdstr_edit,
                    515:          &mode_key_tree_vi_edit, mode_key_vi_edit },
                    516:        { "vi-choice", mode_key_cmdstr_choice,
                    517:          &mode_key_tree_vi_choice, mode_key_vi_choice },
                    518:        { "vi-copy", mode_key_cmdstr_copy,
                    519:          &mode_key_tree_vi_copy, mode_key_vi_copy },
                    520:        { "emacs-edit", mode_key_cmdstr_edit,
                    521:          &mode_key_tree_emacs_edit, mode_key_emacs_edit },
                    522:        { "emacs-choice", mode_key_cmdstr_choice,
                    523:          &mode_key_tree_emacs_choice, mode_key_emacs_choice },
                    524:        { "emacs-copy", mode_key_cmdstr_copy,
                    525:          &mode_key_tree_emacs_copy, mode_key_emacs_copy },
                    526:
                    527:        { NULL, NULL, NULL, NULL }
                    528: };
                    529:
1.44      nicm      530: RB_GENERATE(mode_key_tree, mode_key_binding, entry, mode_key_cmp);
1.10      nicm      531:
                    532: int
                    533: mode_key_cmp(struct mode_key_binding *mbind1, struct mode_key_binding *mbind2)
                    534: {
1.64      nicm      535:        if (mbind1->mode < mbind2->mode)
                    536:                return (-1);
                    537:        if (mbind1->mode > mbind2->mode)
                    538:                return (1);
                    539:        if (mbind1->key < mbind2->key)
                    540:                return (-1);
                    541:        if (mbind1->key > mbind2->key)
                    542:                return (1);
                    543:        return (0);
1.10      nicm      544: }
                    545:
                    546: const char *
1.36      nicm      547: mode_key_tostring(const struct mode_key_cmdstr *cmdstr, enum mode_key_cmd cmd)
1.10      nicm      548: {
                    549:        for (; cmdstr->name != NULL; cmdstr++) {
                    550:                if (cmdstr->cmd == cmd)
                    551:                        return (cmdstr->name);
1.11      nicm      552:        }
                    553:        return (NULL);
                    554: }
                    555:
                    556: enum mode_key_cmd
1.36      nicm      557: mode_key_fromstring(const struct mode_key_cmdstr *cmdstr, const char *name)
1.11      nicm      558: {
                    559:        for (; cmdstr->name != NULL; cmdstr++) {
                    560:                if (strcasecmp(cmdstr->name, name) == 0)
                    561:                        return (cmdstr->cmd);
                    562:        }
                    563:        return (MODEKEY_NONE);
                    564: }
                    565:
                    566: const struct mode_key_table *
                    567: mode_key_findtable(const char *name)
                    568: {
                    569:        const struct mode_key_table     *mtab;
1.25      nicm      570:
1.11      nicm      571:        for (mtab = mode_key_tables; mtab->name != NULL; mtab++) {
                    572:                if (strcasecmp(name, mtab->name) == 0)
                    573:                        return (mtab);
1.10      nicm      574:        }
                    575:        return (NULL);
                    576: }
1.1       nicm      577:
                    578: void
1.10      nicm      579: mode_key_init_trees(void)
1.1       nicm      580: {
1.10      nicm      581:        const struct mode_key_table     *mtab;
                    582:        const struct mode_key_entry     *ment;
                    583:        struct mode_key_binding         *mbind;
                    584:
                    585:        for (mtab = mode_key_tables; mtab->name != NULL; mtab++) {
1.44      nicm      586:                RB_INIT(mtab->tree);
1.10      nicm      587:                for (ment = mtab->table; ment->mode != -1; ment++) {
                    588:                        mbind = xmalloc(sizeof *mbind);
                    589:                        mbind->key = ment->key;
1.69      nicm      590:                        mbind->repeat = ment->repeat;
1.10      nicm      591:                        mbind->mode = ment->mode;
                    592:                        mbind->cmd = ment->cmd;
1.52      nicm      593:                        mbind->arg = NULL;
1.44      nicm      594:                        RB_INSERT(mode_key_tree, mtab->tree, mbind);
1.10      nicm      595:                }
                    596:        }
                    597: }
                    598:
                    599: void
                    600: mode_key_init(struct mode_key_data *mdata, struct mode_key_tree *mtree)
                    601: {
                    602:        mdata->tree = mtree;
1.8       nicm      603:        mdata->mode = 0;
1.1       nicm      604: }
                    605:
                    606: enum mode_key_cmd
1.69      nicm      607: mode_key_lookup(struct mode_key_data *mdata, key_code key, const char **arg,
                    608:     u_int *repeat)
1.1       nicm      609: {
1.10      nicm      610:        struct mode_key_binding *mbind, mtmp;
                    611:
                    612:        mtmp.key = key;
                    613:        mtmp.mode = mdata->mode;
1.44      nicm      614:        if ((mbind = RB_FIND(mode_key_tree, mdata->tree, &mtmp)) == NULL) {
1.10      nicm      615:                if (mdata->mode != 0)
                    616:                        return (MODEKEY_NONE);
                    617:                return (MODEKEY_OTHER);
                    618:        }
1.69      nicm      619:        if (repeat != NULL)
                    620:                *repeat = mbind->repeat;
1.1       nicm      621:
1.10      nicm      622:        switch (mbind->cmd) {
                    623:        case MODEKEYEDIT_SWITCHMODE:
                    624:        case MODEKEYEDIT_SWITCHMODEAPPEND:
1.45      nicm      625:        case MODEKEYEDIT_SWITCHMODEAPPENDLINE:
                    626:        case MODEKEYEDIT_SWITCHMODEBEGINLINE:
1.53      nicm      627:        case MODEKEYEDIT_SWITCHMODECHANGELINE:
                    628:        case MODEKEYEDIT_SWITCHMODESUBSTITUTE:
                    629:        case MODEKEYEDIT_SWITCHMODESUBSTITUTELINE:
1.10      nicm      630:                mdata->mode = 1 - mdata->mode;
                    631:                /* FALLTHROUGH */
                    632:        default:
1.52      nicm      633:                if (arg != NULL)
                    634:                        *arg = mbind->arg;
1.10      nicm      635:                return (mbind->cmd);
1.1       nicm      636:        }
                    637: }