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

1.23    ! nicm        1: /* $OpenBSD: mode-key.c,v 1.22 2009/10/07 15:58:40 nicm Exp $ */
1.1       nicm        2:
                      3: /*
                      4:  * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
                      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
                     38:  * (MODEKEYEDIT_SWITCHMODE and MODEKEYEDIT_SWITCHMODEAPPEND) are special-cased
                     39:  * to do this.
                     40:  */
                     41:
                     42: /* Edit keys command strings. */
                     43: struct mode_key_cmdstr mode_key_cmdstr_edit[] = {
                     44:        { MODEKEYEDIT_BACKSPACE, "backspace" },
                     45:        { MODEKEYEDIT_CANCEL, "cancel" },
                     46:        { MODEKEYEDIT_COMPLETE, "complete" },
                     47:        { MODEKEYEDIT_CURSORLEFT, "cursor-left" },
                     48:        { MODEKEYEDIT_CURSORRIGHT, "cursor-right" },
                     49:        { MODEKEYEDIT_DELETE, "delete" },
1.16      nicm       50:        { MODEKEYEDIT_DELETELINE, "delete-line" },
1.10      nicm       51:        { MODEKEYEDIT_DELETETOENDOFLINE, "delete-end-of-line" },
                     52:        { MODEKEYEDIT_ENDOFLINE, "end-of-line" },
                     53:        { MODEKEYEDIT_ENTER, "enter" },
                     54:        { MODEKEYEDIT_HISTORYDOWN, "history-down" },
                     55:        { MODEKEYEDIT_HISTORYUP, "history-up" },
                     56:        { MODEKEYEDIT_PASTE, "paste" },
                     57:        { MODEKEYEDIT_STARTOFLINE, "start-of-line" },
                     58:        { MODEKEYEDIT_SWITCHMODE, "switch-mode" },
                     59:        { MODEKEYEDIT_SWITCHMODEAPPEND, "switch-mode-append" },
1.17      nicm       60:        { MODEKEYEDIT_TRANSPOSECHARS, "transpose-chars" },
1.11      nicm       61:
                     62:        { 0, NULL }
1.10      nicm       63: };
                     64:
                     65: /* Choice keys command strings. */
                     66: struct mode_key_cmdstr mode_key_cmdstr_choice[] = {
                     67:        { MODEKEYCHOICE_CANCEL, "cancel" },
                     68:        { MODEKEYCHOICE_CHOOSE, "choose" },
                     69:        { MODEKEYCHOICE_DOWN, "down" },
                     70:        { MODEKEYCHOICE_PAGEDOWN, "page-down" },
                     71:        { MODEKEYCHOICE_PAGEUP, "page-up" },
                     72:        { MODEKEYCHOICE_UP, "up" },
1.11      nicm       73:
                     74:        { 0, NULL }
1.10      nicm       75: };
                     76:
                     77: /* Copy keys command strings. */
                     78: struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
1.15      nicm       79:        { MODEKEYCOPY_BACKTOINDENTATION, "back-to-indentation" },
1.23    ! nicm       80:        { MODEKEYCOPY_BOTTOMLINE, "bottom-line" },
1.10      nicm       81:        { MODEKEYCOPY_CANCEL, "cancel" },
                     82:        { MODEKEYCOPY_CLEARSELECTION, "clear-selection" },
                     83:        { MODEKEYCOPY_COPYSELECTION, "copy-selection" },
                     84:        { MODEKEYCOPY_DOWN, "cursor-down" },
                     85:        { MODEKEYCOPY_ENDOFLINE, "end-of-line" },
1.15      nicm       86:        { MODEKEYCOPY_GOTOLINE, "goto-line" },
1.10      nicm       87:        { MODEKEYCOPY_LEFT, "cursor-left" },
1.23    ! nicm       88:        { MODEKEYCOPY_MIDDLELINE, "middle-line" },
1.10      nicm       89:        { MODEKEYCOPY_NEXTPAGE, "page-down" },
                     90:        { MODEKEYCOPY_NEXTWORD, "next-word" },
                     91:        { MODEKEYCOPY_PREVIOUSPAGE, "page-up" },
                     92:        { MODEKEYCOPY_PREVIOUSWORD, "previous-word" },
                     93:        { MODEKEYCOPY_RIGHT, "cursor-right" },
1.21      nicm       94:        { MODEKEYCOPY_SCROLLDOWN, "scroll-down" },
                     95:        { MODEKEYCOPY_SCROLLUP, "scroll-up" },
1.15      nicm       96:        { MODEKEYCOPY_SEARCHAGAIN, "search-again" },
                     97:        { MODEKEYCOPY_SEARCHDOWN, "search-forward" },
                     98:        { MODEKEYCOPY_SEARCHUP, "search-backward" },
1.10      nicm       99:        { MODEKEYCOPY_STARTOFLINE, "start-of-line" },
                    100:        { MODEKEYCOPY_STARTSELECTION, "begin-selection" },
1.23    ! nicm      101:        { MODEKEYCOPY_TOPLINE, "top-line" },
1.10      nicm      102:        { MODEKEYCOPY_UP, "cursor-up" },
1.11      nicm      103:
                    104:        { 0, NULL }
1.10      nicm      105: };
                    106:
1.8       nicm      107: /* vi editing keys. */
                    108: const struct mode_key_entry mode_key_vi_edit[] = {
                    109:        { '\003' /* C-c */,     0, MODEKEYEDIT_CANCEL },
                    110:        { '\010' /* C-h */,     0, MODEKEYEDIT_BACKSPACE },
                    111:        { '\011' /* Tab */,     0, MODEKEYEDIT_COMPLETE },
                    112:        { '\033' /* Escape */,  0, MODEKEYEDIT_SWITCHMODE },
                    113:        { '\r',                 0, MODEKEYEDIT_ENTER },
                    114:        { KEYC_BSPACE,          0, MODEKEYEDIT_BACKSPACE },
                    115:        { KEYC_DC,              0, MODEKEYEDIT_DELETE },
                    116:
                    117:        { '$',                  1, MODEKEYEDIT_ENDOFLINE },
                    118:        { '0',                  1, MODEKEYEDIT_STARTOFLINE },
1.16      nicm      119:        { 'd',                  1, MODEKEYEDIT_DELETELINE },
1.8       nicm      120:        { 'D',                  1, MODEKEYEDIT_DELETETOENDOFLINE },
                    121:        { '\003' /* C-c */,     1, MODEKEYEDIT_CANCEL },
                    122:        { '\010' /* C-h */,     1, MODEKEYEDIT_BACKSPACE },
                    123:        { '\r',                 1, MODEKEYEDIT_ENTER },
                    124:        { '^',                  1, MODEKEYEDIT_STARTOFLINE },
                    125:        { 'a',                  1, MODEKEYEDIT_SWITCHMODEAPPEND },
                    126:        { 'h',                  1, MODEKEYEDIT_CURSORLEFT },
                    127:        { 'i',                  1, MODEKEYEDIT_SWITCHMODE },
                    128:        { 'j',                  1, MODEKEYEDIT_HISTORYDOWN },
                    129:        { 'k',                  1, MODEKEYEDIT_HISTORYUP },
                    130:        { 'l',                  1, MODEKEYEDIT_CURSORRIGHT },
                    131:        { 'p',                  1, MODEKEYEDIT_PASTE },
                    132:        { KEYC_BSPACE,          1, MODEKEYEDIT_BACKSPACE },
                    133:        { KEYC_DC,              1, MODEKEYEDIT_DELETE },
                    134:        { KEYC_DOWN,            1, MODEKEYEDIT_HISTORYDOWN },
                    135:        { KEYC_LEFT,            1, MODEKEYEDIT_CURSORLEFT },
                    136:        { KEYC_RIGHT,           1, MODEKEYEDIT_CURSORRIGHT },
                    137:        { KEYC_UP,              1, MODEKEYEDIT_HISTORYUP },
                    138:
                    139:        { 0,                   -1, 0 }
                    140: };
1.10      nicm      141: struct mode_key_tree mode_key_tree_vi_edit;
1.8       nicm      142:
                    143: /* vi choice selection keys. */
                    144: const struct mode_key_entry mode_key_vi_choice[] = {
                    145:        { '\003' /* C-c */,     0, MODEKEYCHOICE_CANCEL },
                    146:        { '\r',                 0, MODEKEYCHOICE_CHOOSE },
                    147:        { 'j',                  0, MODEKEYCHOICE_DOWN },
                    148:        { 'k',                  0, MODEKEYCHOICE_UP },
                    149:        { 'q',                  0, MODEKEYCHOICE_CANCEL },
                    150:        { KEYC_DOWN,            0, MODEKEYCHOICE_DOWN },
                    151:        { KEYC_NPAGE,           0, MODEKEYCHOICE_PAGEDOWN },
                    152:        { KEYC_PPAGE,           0, MODEKEYCHOICE_PAGEUP },
                    153:        { KEYC_UP,              0, MODEKEYCHOICE_UP },
                    154:
                    155:        { 0,                    -1, 0 }
                    156: };
1.10      nicm      157: struct mode_key_tree mode_key_tree_vi_choice;
1.8       nicm      158:
                    159: /* vi copy mode keys. */
                    160: const struct mode_key_entry mode_key_vi_copy[] = {
                    161:        { ' ',                  0, MODEKEYCOPY_STARTSELECTION },
                    162:        { '$',                  0, MODEKEYCOPY_ENDOFLINE },
1.20      nicm      163:        { '/',                  0, MODEKEYCOPY_SEARCHDOWN },
1.8       nicm      164:        { '0',                  0, MODEKEYCOPY_STARTOFLINE },
1.20      nicm      165:        { ':',                  0, MODEKEYCOPY_GOTOLINE },
                    166:        { '?',                  0, MODEKEYCOPY_SEARCHUP },
1.23    ! nicm      167:        { 'H',                  0, MODEKEYCOPY_TOPLINE },
1.22      nicm      168:        { 'J',                  0, MODEKEYCOPY_SCROLLDOWN },
                    169:        { 'K',                  0, MODEKEYCOPY_SCROLLUP },
1.23    ! nicm      170:        { 'L',                  0, MODEKEYCOPY_BOTTOMLINE },
        !           171:        { 'M',                  0, MODEKEYCOPY_MIDDLELINE },
1.13      nicm      172:        { '\002' /* C-b */,     0, MODEKEYCOPY_PREVIOUSPAGE },
1.9       nicm      173:        { '\003' /* C-c */,     0, MODEKEYCOPY_CANCEL },
1.13      nicm      174:        { '\004' /* C-d */,     0, MODEKEYCOPY_HALFPAGEDOWN },
1.8       nicm      175:        { '\006' /* C-f */,     0, MODEKEYCOPY_NEXTPAGE },
                    176:        { '\010' /* C-h */,     0, MODEKEYCOPY_LEFT },
1.13      nicm      177:        { '\025' /* C-u */,     0, MODEKEYCOPY_HALFPAGEUP },
1.8       nicm      178:        { '\033' /* Escape */,  0, MODEKEYCOPY_CLEARSELECTION },
                    179:        { '\r',                 0, MODEKEYCOPY_COPYSELECTION },
                    180:        { '^',                  0, MODEKEYCOPY_BACKTOINDENTATION },
                    181:        { 'b',                  0, MODEKEYCOPY_PREVIOUSWORD },
                    182:        { 'h',                  0, MODEKEYCOPY_LEFT },
                    183:        { 'j',                  0, MODEKEYCOPY_DOWN },
                    184:        { 'k',                  0, MODEKEYCOPY_UP },
                    185:        { 'l',                  0, MODEKEYCOPY_RIGHT },
1.15      nicm      186:        { 'n',                  0, MODEKEYCOPY_SEARCHAGAIN },
1.9       nicm      187:        { 'q',                  0, MODEKEYCOPY_CANCEL },
1.8       nicm      188:        { 'w',                  0, MODEKEYCOPY_NEXTWORD },
                    189:        { KEYC_BSPACE,          0, MODEKEYCOPY_LEFT },
1.21      nicm      190:        { KEYC_DOWN | KEYC_CTRL,0, MODEKEYCOPY_SCROLLDOWN },
1.8       nicm      191:        { KEYC_DOWN,            0, MODEKEYCOPY_DOWN },
                    192:        { KEYC_LEFT,            0, MODEKEYCOPY_LEFT },
                    193:        { KEYC_NPAGE,           0, MODEKEYCOPY_NEXTPAGE },
                    194:        { KEYC_PPAGE,           0, MODEKEYCOPY_PREVIOUSPAGE },
                    195:        { KEYC_RIGHT,           0, MODEKEYCOPY_RIGHT },
1.21      nicm      196:        { KEYC_UP | KEYC_CTRL,  0, MODEKEYCOPY_SCROLLUP },
1.8       nicm      197:        { KEYC_UP,              0, MODEKEYCOPY_UP },
1.23    ! nicm      198:
1.8       nicm      199:        { 0,                    -1, 0 }
                    200: };
1.10      nicm      201: struct mode_key_tree mode_key_tree_vi_copy;
1.8       nicm      202:
                    203: /* emacs editing keys. */
                    204: const struct mode_key_entry mode_key_emacs_edit[] = {
                    205:        { '\001' /* C-a */,     0, MODEKEYEDIT_STARTOFLINE },
1.18      nicm      206:        { '\002' /* C-b */,     0, MODEKEYEDIT_CURSORLEFT },
1.14      nicm      207:        { '\003' /* C-c */,     0, MODEKEYEDIT_CANCEL },
1.8       nicm      208:        { '\004' /* C-d */,     0, MODEKEYEDIT_DELETE },
                    209:        { '\005' /* C-e */,     0, MODEKEYEDIT_ENDOFLINE },
                    210:        { '\006' /* C-f */,     0, MODEKEYEDIT_CURSORRIGHT },
                    211:        { '\010' /* C-H */,     0, MODEKEYEDIT_BACKSPACE },
1.16      nicm      212:        { '\011' /* Tab */,     0, MODEKEYEDIT_COMPLETE },
1.8       nicm      213:        { '\013' /* C-k */,     0, MODEKEYEDIT_DELETETOENDOFLINE },
                    214:        { '\016' /* C-n */,     0, MODEKEYEDIT_HISTORYDOWN },
                    215:        { '\020' /* C-p */,     0, MODEKEYEDIT_HISTORYUP },
1.17      nicm      216:        { '\024' /* C-t */,     0, MODEKEYEDIT_TRANSPOSECHARS },
1.16      nicm      217:        { '\025' /* C-u */,     0, MODEKEYEDIT_DELETELINE },
1.8       nicm      218:        { '\031' /* C-y */,     0, MODEKEYEDIT_PASTE },
1.14      nicm      219:        { '\033' /* Escape */,  0, MODEKEYEDIT_CANCEL },
1.8       nicm      220:        { '\r',                 0, MODEKEYEDIT_ENTER },
                    221:        { 'm' | KEYC_ESCAPE,    0, MODEKEYEDIT_STARTOFLINE },
                    222:        { KEYC_BSPACE,          0, MODEKEYEDIT_BACKSPACE },
                    223:        { KEYC_DC,              0, MODEKEYEDIT_DELETE },
                    224:        { KEYC_DOWN,            0, MODEKEYEDIT_HISTORYDOWN },
                    225:        { KEYC_LEFT,            0, MODEKEYEDIT_CURSORLEFT },
                    226:        { KEYC_RIGHT,           0, MODEKEYEDIT_CURSORRIGHT },
                    227:        { KEYC_UP,              0, MODEKEYEDIT_HISTORYUP },
                    228:
                    229:        { 0,                   -1, 0 }
                    230: };
1.10      nicm      231: struct mode_key_tree mode_key_tree_emacs_edit;
1.8       nicm      232:
                    233: /* emacs choice selection keys. */
                    234: const struct mode_key_entry mode_key_emacs_choice[] = {
                    235:        { '\003' /* C-c */,     0, MODEKEYCHOICE_CANCEL },
1.18      nicm      236:        { '\016' /* C-n */,     0, MODEKEYCHOICE_DOWN },
                    237:        { '\020' /* C-p */,     0, MODEKEYCHOICE_UP },
1.19      nicm      238:        { '\026' /* C-v */,     0, MODEKEYCHOICE_PAGEDOWN },
1.8       nicm      239:        { '\033' /* Escape */,  0, MODEKEYCHOICE_CANCEL },
                    240:        { '\r',                 0, MODEKEYCHOICE_CHOOSE },
                    241:        { 'q',                  0, MODEKEYCHOICE_CANCEL },
1.19      nicm      242:        { 'v' | KEYC_ESCAPE,    0, MODEKEYCHOICE_PAGEUP },
1.8       nicm      243:        { KEYC_DOWN,            0, MODEKEYCHOICE_DOWN },
                    244:        { KEYC_NPAGE,           0, MODEKEYCHOICE_PAGEDOWN },
                    245:        { KEYC_PPAGE,           0, MODEKEYCHOICE_PAGEUP },
                    246:        { KEYC_UP,              0, MODEKEYCHOICE_UP },
                    247:
                    248:        { 0,                    -1, 0 }
                    249: };
1.10      nicm      250: struct mode_key_tree mode_key_tree_emacs_choice;
1.8       nicm      251:
                    252: /* emacs copy mode keys. */
                    253: const struct mode_key_entry mode_key_emacs_copy[] = {
                    254:        { ' ',                  0, MODEKEYCOPY_NEXTPAGE },
                    255:        { '\000' /* C-Space */, 0, MODEKEYCOPY_STARTSELECTION },
                    256:        { '\001' /* C-a */,     0, MODEKEYCOPY_STARTOFLINE },
                    257:        { '\002' /* C-b */,     0, MODEKEYCOPY_LEFT },
1.9       nicm      258:        { '\003' /* C-c */,     0, MODEKEYCOPY_CANCEL },
1.8       nicm      259:        { '\005' /* C-e */,     0, MODEKEYCOPY_ENDOFLINE },
                    260:        { '\006' /* C-f */,     0, MODEKEYCOPY_RIGHT },
                    261:        { '\007' /* C-g */,     0, MODEKEYCOPY_CLEARSELECTION },
                    262:        { '\016' /* C-n */,     0, MODEKEYCOPY_DOWN },
                    263:        { '\020' /* C-p */,     0, MODEKEYCOPY_UP },
1.15      nicm      264:        { '\022' /* C-r */,     0, MODEKEYCOPY_SEARCHUP },
                    265:        { '\023' /* C-s */,     0, MODEKEYCOPY_SEARCHDOWN },
1.8       nicm      266:        { '\026' /* C-v */,     0, MODEKEYCOPY_NEXTPAGE },
                    267:        { '\027' /* C-w */,     0, MODEKEYCOPY_COPYSELECTION },
1.9       nicm      268:        { '\033' /* Escape */,  0, MODEKEYCOPY_CANCEL },
1.8       nicm      269:        { 'b' | KEYC_ESCAPE,    0, MODEKEYCOPY_PREVIOUSWORD },
                    270:        { 'f' | KEYC_ESCAPE,    0, MODEKEYCOPY_NEXTWORD },
1.15      nicm      271:        { 'g',                  0, MODEKEYCOPY_GOTOLINE },
1.8       nicm      272:        { 'm' | KEYC_ESCAPE,    0, MODEKEYCOPY_BACKTOINDENTATION },
1.15      nicm      273:        { 'n',                  0, MODEKEYCOPY_SEARCHAGAIN },
1.9       nicm      274:        { 'q',                  0, MODEKEYCOPY_CANCEL },
1.23    ! nicm      275:        { 'r' | KEYC_ESCAPE,    0, MODEKEYCOPY_MIDDLELINE },
        !           276:        { 'R' | KEYC_ESCAPE,    0, MODEKEYCOPY_TOPLINE },
1.8       nicm      277:        { 'v' | KEYC_ESCAPE,    0, MODEKEYCOPY_PREVIOUSPAGE },
                    278:        { 'w' | KEYC_ESCAPE,    0, MODEKEYCOPY_COPYSELECTION },
1.21      nicm      279:        { KEYC_DOWN | KEYC_CTRL,0, MODEKEYCOPY_SCROLLDOWN },
1.13      nicm      280:        { KEYC_DOWN | KEYC_ESCAPE, 0, MODEKEYCOPY_HALFPAGEDOWN },
1.8       nicm      281:        { KEYC_DOWN,            0, MODEKEYCOPY_DOWN },
                    282:        { KEYC_LEFT,            0, MODEKEYCOPY_LEFT },
                    283:        { KEYC_NPAGE,           0, MODEKEYCOPY_NEXTPAGE },
                    284:        { KEYC_PPAGE,           0, MODEKEYCOPY_PREVIOUSPAGE },
                    285:        { KEYC_RIGHT,           0, MODEKEYCOPY_RIGHT },
1.21      nicm      286:        { KEYC_UP | KEYC_CTRL,  0, MODEKEYCOPY_SCROLLUP },
1.13      nicm      287:        { KEYC_UP | KEYC_ESCAPE, 0, MODEKEYCOPY_HALFPAGEUP },
1.8       nicm      288:        { KEYC_UP,              0, MODEKEYCOPY_UP },
                    289:
                    290:        { 0,                    -1, 0 }
                    291: };
1.10      nicm      292: struct mode_key_tree mode_key_tree_emacs_copy;
                    293:
                    294: /* Table mapping key table names to default settings and trees. */
                    295: const struct mode_key_table mode_key_tables[] = {
                    296:        { "vi-edit", mode_key_cmdstr_edit,
                    297:          &mode_key_tree_vi_edit, mode_key_vi_edit },
                    298:        { "vi-choice", mode_key_cmdstr_choice,
                    299:          &mode_key_tree_vi_choice, mode_key_vi_choice },
                    300:        { "vi-copy", mode_key_cmdstr_copy,
                    301:          &mode_key_tree_vi_copy, mode_key_vi_copy },
                    302:        { "emacs-edit", mode_key_cmdstr_edit,
                    303:          &mode_key_tree_emacs_edit, mode_key_emacs_edit },
                    304:        { "emacs-choice", mode_key_cmdstr_choice,
                    305:          &mode_key_tree_emacs_choice, mode_key_emacs_choice },
                    306:        { "emacs-copy", mode_key_cmdstr_copy,
                    307:          &mode_key_tree_emacs_copy, mode_key_emacs_copy },
                    308:
                    309:        { NULL, NULL, NULL, NULL }
                    310: };
                    311:
                    312: SPLAY_GENERATE(mode_key_tree, mode_key_binding, entry, mode_key_cmp);
                    313:
                    314: int
                    315: mode_key_cmp(struct mode_key_binding *mbind1, struct mode_key_binding *mbind2)
                    316: {
                    317:        if (mbind1->mode != mbind2->mode)
                    318:                return (mbind1->mode - mbind2->mode);
                    319:        return (mbind1->key - mbind2->key);
                    320: }
                    321:
                    322: const char *
                    323: mode_key_tostring(struct mode_key_cmdstr *cmdstr, enum mode_key_cmd cmd)
                    324: {
                    325:        for (; cmdstr->name != NULL; cmdstr++) {
                    326:                if (cmdstr->cmd == cmd)
                    327:                        return (cmdstr->name);
1.11      nicm      328:        }
                    329:        return (NULL);
                    330: }
                    331:
                    332: enum mode_key_cmd
                    333: mode_key_fromstring(struct mode_key_cmdstr *cmdstr, const char *name)
                    334: {
                    335:        for (; cmdstr->name != NULL; cmdstr++) {
                    336:                if (strcasecmp(cmdstr->name, name) == 0)
                    337:                        return (cmdstr->cmd);
                    338:        }
                    339:        return (MODEKEY_NONE);
                    340: }
                    341:
                    342: const struct mode_key_table *
                    343: mode_key_findtable(const char *name)
                    344: {
                    345:        const struct mode_key_table     *mtab;
                    346:
                    347:        for (mtab = mode_key_tables; mtab->name != NULL; mtab++) {
                    348:                if (strcasecmp(name, mtab->name) == 0)
                    349:                        return (mtab);
1.10      nicm      350:        }
                    351:        return (NULL);
                    352: }
1.1       nicm      353:
                    354: void
1.10      nicm      355: mode_key_init_trees(void)
1.1       nicm      356: {
1.10      nicm      357:        const struct mode_key_table     *mtab;
                    358:        const struct mode_key_entry     *ment;
                    359:        struct mode_key_binding         *mbind;
                    360:
                    361:        for (mtab = mode_key_tables; mtab->name != NULL; mtab++) {
                    362:                SPLAY_INIT(mtab->tree);
                    363:                for (ment = mtab->table; ment->mode != -1; ment++) {
                    364:                        mbind = xmalloc(sizeof *mbind);
                    365:                        mbind->key = ment->key;
                    366:                        mbind->mode = ment->mode;
                    367:                        mbind->cmd = ment->cmd;
                    368:                        SPLAY_INSERT(mode_key_tree, mtab->tree, mbind);
                    369:                }
                    370:        }
                    371: }
                    372:
                    373: void
                    374: mode_key_free_trees(void)
                    375: {
                    376:        const struct mode_key_table     *mtab;
                    377:        struct mode_key_binding         *mbind;
                    378:
                    379:        for (mtab = mode_key_tables; mtab->name != NULL; mtab++) {
                    380:                while (!SPLAY_EMPTY(mtab->tree)) {
                    381:                        mbind = SPLAY_ROOT(mtab->tree);
                    382:                        SPLAY_REMOVE(mode_key_tree, mtab->tree, mbind);
1.12      nicm      383:                        xfree(mbind);
1.10      nicm      384:                }
                    385:        }
                    386: }
                    387:
                    388: void
                    389: mode_key_init(struct mode_key_data *mdata, struct mode_key_tree *mtree)
                    390: {
                    391:        mdata->tree = mtree;
1.8       nicm      392:        mdata->mode = 0;
1.1       nicm      393: }
                    394:
                    395: enum mode_key_cmd
                    396: mode_key_lookup(struct mode_key_data *mdata, int key)
                    397: {
1.10      nicm      398:        struct mode_key_binding *mbind, mtmp;
                    399:
                    400:        mtmp.key = key;
                    401:        mtmp.mode = mdata->mode;
                    402:        if ((mbind = SPLAY_FIND(mode_key_tree, mdata->tree, &mtmp)) == NULL) {
                    403:                if (mdata->mode != 0)
                    404:                        return (MODEKEY_NONE);
                    405:                return (MODEKEY_OTHER);
                    406:        }
1.1       nicm      407:
1.10      nicm      408:        switch (mbind->cmd) {
                    409:        case MODEKEYEDIT_SWITCHMODE:
                    410:        case MODEKEYEDIT_SWITCHMODEAPPEND:
                    411:                mdata->mode = 1 - mdata->mode;
                    412:                /* FALLTHROUGH */
                    413:        default:
                    414:                return (mbind->cmd);
1.1       nicm      415:        }
                    416: }