Annotation of src/usr.bin/tmux/mode-key.c, Revision 1.71
1.71 ! nicm 1: /* $OpenBSD: mode-key.c,v 1.70 2016/10/10 21:29:23 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;
53: };
1.10 nicm 54:
55: /* Edit keys command strings. */
1.70 nicm 56: static const struct mode_key_cmdstr mode_key_cmdstr_edit[] = {
1.10 nicm 57: { MODEKEYEDIT_BACKSPACE, "backspace" },
1.25 nicm 58: { MODEKEYEDIT_CANCEL, "cancel" },
1.10 nicm 59: { MODEKEYEDIT_COMPLETE, "complete" },
60: { MODEKEYEDIT_CURSORLEFT, "cursor-left" },
61: { MODEKEYEDIT_CURSORRIGHT, "cursor-right" },
62: { MODEKEYEDIT_DELETE, "delete" },
1.16 nicm 63: { MODEKEYEDIT_DELETELINE, "delete-line" },
1.10 nicm 64: { MODEKEYEDIT_DELETETOENDOFLINE, "delete-end-of-line" },
1.40 nicm 65: { MODEKEYEDIT_DELETEWORD, "delete-word" },
1.10 nicm 66: { MODEKEYEDIT_ENDOFLINE, "end-of-line" },
67: { MODEKEYEDIT_ENTER, "enter" },
68: { MODEKEYEDIT_HISTORYDOWN, "history-down" },
69: { MODEKEYEDIT_HISTORYUP, "history-up" },
1.43 nicm 70: { MODEKEYEDIT_NEXTSPACE, "next-space" },
71: { MODEKEYEDIT_NEXTSPACEEND, "next-space-end" },
1.40 nicm 72: { MODEKEYEDIT_NEXTWORD, "next-word" },
73: { MODEKEYEDIT_NEXTWORDEND, "next-word-end" },
1.10 nicm 74: { MODEKEYEDIT_PASTE, "paste" },
1.43 nicm 75: { MODEKEYEDIT_PREVIOUSSPACE, "previous-space" },
1.40 nicm 76: { MODEKEYEDIT_PREVIOUSWORD, "previous-word" },
1.10 nicm 77: { MODEKEYEDIT_STARTOFLINE, "start-of-line" },
78: { MODEKEYEDIT_SWITCHMODE, "switch-mode" },
79: { MODEKEYEDIT_SWITCHMODEAPPEND, "switch-mode-append" },
1.45 nicm 80: { MODEKEYEDIT_SWITCHMODEAPPENDLINE, "switch-mode-append-line" },
81: { MODEKEYEDIT_SWITCHMODEBEGINLINE, "switch-mode-begin-line" },
1.53 nicm 82: { MODEKEYEDIT_SWITCHMODECHANGELINE, "switch-mode-change-line" },
83: { MODEKEYEDIT_SWITCHMODESUBSTITUTE, "switch-mode-substitute" },
84: { MODEKEYEDIT_SWITCHMODESUBSTITUTELINE, "switch-mode-substitute-line" },
1.17 nicm 85: { MODEKEYEDIT_TRANSPOSECHARS, "transpose-chars" },
1.11 nicm 86:
87: { 0, NULL }
1.10 nicm 88: };
1.25 nicm 89:
1.10 nicm 90: /* Choice keys command strings. */
1.70 nicm 91: static const struct mode_key_cmdstr mode_key_cmdstr_choice[] = {
1.46 nicm 92: { MODEKEYCHOICE_BACKSPACE, "backspace" },
1.57 nicm 93: { MODEKEYCHOICE_BOTTOMLINE, "bottom-line"},
1.10 nicm 94: { MODEKEYCHOICE_CANCEL, "cancel" },
95: { MODEKEYCHOICE_CHOOSE, "choose" },
96: { MODEKEYCHOICE_DOWN, "down" },
1.57 nicm 97: { MODEKEYCHOICE_ENDOFLIST, "end-of-list"},
1.10 nicm 98: { MODEKEYCHOICE_PAGEDOWN, "page-down" },
99: { MODEKEYCHOICE_PAGEUP, "page-up" },
1.30 nicm 100: { MODEKEYCHOICE_SCROLLDOWN, "scroll-down" },
101: { MODEKEYCHOICE_SCROLLUP, "scroll-up" },
1.46 nicm 102: { MODEKEYCHOICE_STARTNUMBERPREFIX, "start-number-prefix" },
1.57 nicm 103: { MODEKEYCHOICE_STARTOFLIST, "start-of-list"},
104: { MODEKEYCHOICE_TOPLINE, "top-line"},
1.49 nicm 105: { MODEKEYCHOICE_TREE_COLLAPSE, "tree-collapse" },
1.48 nicm 106: { MODEKEYCHOICE_TREE_COLLAPSE_ALL, "tree-collapse-all" },
1.49 nicm 107: { MODEKEYCHOICE_TREE_EXPAND, "tree-expand" },
1.48 nicm 108: { MODEKEYCHOICE_TREE_EXPAND_ALL, "tree-expand-all" },
109: { MODEKEYCHOICE_TREE_TOGGLE, "tree-toggle" },
1.10 nicm 110: { MODEKEYCHOICE_UP, "up" },
1.11 nicm 111:
112: { 0, NULL }
1.10 nicm 113: };
114:
1.8 nicm 115: /* vi editing keys. */
1.70 nicm 116: static const struct mode_key_entry mode_key_vi_edit[] = {
1.71 ! nicm 117: { '\003' /* C-c */, 0, MODEKEYEDIT_CANCEL },
! 118: { '\010' /* C-h */, 0, MODEKEYEDIT_BACKSPACE },
! 119: { '\011' /* Tab */, 0, MODEKEYEDIT_COMPLETE },
! 120: { '\025' /* C-u */, 0, MODEKEYEDIT_DELETELINE },
! 121: { '\027' /* C-w */, 0, MODEKEYEDIT_DELETEWORD },
! 122: { '\033' /* Escape */, 0, MODEKEYEDIT_SWITCHMODE },
! 123: { '\n', 0, MODEKEYEDIT_ENTER },
! 124: { '\r', 0, MODEKEYEDIT_ENTER },
! 125: { KEYC_BSPACE, 0, MODEKEYEDIT_BACKSPACE },
! 126: { KEYC_DC, 0, MODEKEYEDIT_DELETE },
! 127: { KEYC_DOWN, 0, MODEKEYEDIT_HISTORYDOWN },
! 128: { KEYC_LEFT, 0, MODEKEYEDIT_CURSORLEFT },
! 129: { KEYC_RIGHT, 0, MODEKEYEDIT_CURSORRIGHT },
! 130: { KEYC_UP, 0, MODEKEYEDIT_HISTORYUP },
! 131: { KEYC_HOME, 0, MODEKEYEDIT_STARTOFLINE },
! 132: { KEYC_END, 0, MODEKEYEDIT_ENDOFLINE },
! 133:
! 134: { '$', 1, MODEKEYEDIT_ENDOFLINE },
! 135: { '0', 1, MODEKEYEDIT_STARTOFLINE },
! 136: { 'A', 1, MODEKEYEDIT_SWITCHMODEAPPENDLINE },
! 137: { 'B', 1, MODEKEYEDIT_PREVIOUSSPACE },
! 138: { 'C', 1, MODEKEYEDIT_SWITCHMODECHANGELINE },
! 139: { 'D', 1, MODEKEYEDIT_DELETETOENDOFLINE },
! 140: { 'E', 1, MODEKEYEDIT_NEXTSPACEEND },
! 141: { 'I', 1, MODEKEYEDIT_SWITCHMODEBEGINLINE },
! 142: { 'S', 1, MODEKEYEDIT_SWITCHMODESUBSTITUTELINE },
! 143: { 'W', 1, MODEKEYEDIT_NEXTSPACE },
! 144: { 'X', 1, MODEKEYEDIT_BACKSPACE },
! 145: { '\003' /* C-c */, 1, MODEKEYEDIT_CANCEL },
! 146: { '\010' /* C-h */, 1, MODEKEYEDIT_BACKSPACE },
! 147: { '\n', 1, MODEKEYEDIT_ENTER },
! 148: { '\r', 1, MODEKEYEDIT_ENTER },
! 149: { '^', 1, MODEKEYEDIT_STARTOFLINE },
! 150: { 'a', 1, MODEKEYEDIT_SWITCHMODEAPPEND },
! 151: { 'b', 1, MODEKEYEDIT_PREVIOUSWORD },
! 152: { 'd', 1, MODEKEYEDIT_DELETELINE },
! 153: { 'e', 1, MODEKEYEDIT_NEXTWORDEND },
! 154: { 'h', 1, MODEKEYEDIT_CURSORLEFT },
! 155: { 'i', 1, MODEKEYEDIT_SWITCHMODE },
! 156: { 'j', 1, MODEKEYEDIT_HISTORYDOWN },
! 157: { 'k', 1, MODEKEYEDIT_HISTORYUP },
! 158: { 'l', 1, MODEKEYEDIT_CURSORRIGHT },
! 159: { 'p', 1, MODEKEYEDIT_PASTE },
! 160: { 's', 1, MODEKEYEDIT_SWITCHMODESUBSTITUTE },
! 161: { 'w', 1, MODEKEYEDIT_NEXTWORD },
! 162: { 'x', 1, MODEKEYEDIT_DELETE },
! 163: { KEYC_BSPACE, 1, MODEKEYEDIT_BACKSPACE },
! 164: { KEYC_DC, 1, MODEKEYEDIT_DELETE },
! 165: { KEYC_DOWN, 1, MODEKEYEDIT_HISTORYDOWN },
! 166: { KEYC_LEFT, 1, MODEKEYEDIT_CURSORLEFT },
! 167: { KEYC_RIGHT, 1, MODEKEYEDIT_CURSORRIGHT },
! 168: { KEYC_UP, 1, MODEKEYEDIT_HISTORYUP },
1.8 nicm 169:
1.71 ! nicm 170: { 0, -1, 0 }
1.8 nicm 171: };
1.10 nicm 172: struct mode_key_tree mode_key_tree_vi_edit;
1.8 nicm 173:
174: /* vi choice selection keys. */
1.70 nicm 175: static const struct mode_key_entry mode_key_vi_choice[] = {
1.71 ! nicm 176: { '0' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 177: { '1' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 178: { '2' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 179: { '3' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 180: { '4' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 181: { '5' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 182: { '6' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 183: { '7' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 184: { '8' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 185: { '9' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 186: { '\002' /* C-b */, 0, MODEKEYCHOICE_PAGEUP },
! 187: { '\003' /* C-c */, 0, MODEKEYCHOICE_CANCEL },
! 188: { '\005' /* C-e */, 0, MODEKEYCHOICE_SCROLLDOWN },
! 189: { '\006' /* C-f */, 0, MODEKEYCHOICE_PAGEDOWN },
! 190: { '\031' /* C-y */, 0, MODEKEYCHOICE_SCROLLUP },
! 191: { '\n', 0, MODEKEYCHOICE_CHOOSE },
! 192: { '\r', 0, MODEKEYCHOICE_CHOOSE },
! 193: { 'j', 0, MODEKEYCHOICE_DOWN },
! 194: { 'k', 0, MODEKEYCHOICE_UP },
! 195: { 'q', 0, MODEKEYCHOICE_CANCEL },
! 196: { KEYC_HOME, 0, MODEKEYCHOICE_STARTOFLIST },
! 197: { 'g', 0, MODEKEYCHOICE_STARTOFLIST },
! 198: { 'H', 0, MODEKEYCHOICE_TOPLINE },
! 199: { 'L', 0, MODEKEYCHOICE_BOTTOMLINE },
! 200: { 'G', 0, MODEKEYCHOICE_ENDOFLIST },
! 201: { KEYC_END, 0, MODEKEYCHOICE_ENDOFLIST },
! 202: { KEYC_BSPACE, 0, MODEKEYCHOICE_BACKSPACE },
! 203: { KEYC_DOWN | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLDOWN },
! 204: { KEYC_DOWN, 0, MODEKEYCHOICE_DOWN },
! 205: { KEYC_NPAGE, 0, MODEKEYCHOICE_PAGEDOWN },
! 206: { KEYC_PPAGE, 0, MODEKEYCHOICE_PAGEUP },
! 207: { KEYC_UP | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLUP },
! 208: { KEYC_UP, 0, MODEKEYCHOICE_UP },
! 209: { ' ', 0, MODEKEYCHOICE_TREE_TOGGLE },
! 210: { KEYC_LEFT, 0, MODEKEYCHOICE_TREE_COLLAPSE },
! 211: { KEYC_RIGHT, 0, MODEKEYCHOICE_TREE_EXPAND },
! 212: { KEYC_LEFT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_COLLAPSE_ALL },
! 213: { KEYC_RIGHT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_EXPAND_ALL },
! 214: { KEYC_MOUSEDOWN1_PANE, 0, MODEKEYCHOICE_CHOOSE },
! 215: { KEYC_MOUSEDOWN3_PANE, 0, MODEKEYCHOICE_TREE_TOGGLE },
! 216: { KEYC_WHEELUP_PANE, 0, MODEKEYCHOICE_UP },
! 217: { KEYC_WHEELDOWN_PANE, 0, MODEKEYCHOICE_DOWN },
1.8 nicm 218:
1.71 ! nicm 219: { 0, -1, 0 }
1.8 nicm 220: };
1.10 nicm 221: struct mode_key_tree mode_key_tree_vi_choice;
1.8 nicm 222:
223: /* emacs editing keys. */
1.70 nicm 224: static const struct mode_key_entry mode_key_emacs_edit[] = {
1.71 ! nicm 225: { '\001' /* C-a */, 0, MODEKEYEDIT_STARTOFLINE },
! 226: { '\002' /* C-b */, 0, MODEKEYEDIT_CURSORLEFT },
! 227: { '\003' /* C-c */, 0, MODEKEYEDIT_CANCEL },
! 228: { '\004' /* C-d */, 0, MODEKEYEDIT_DELETE },
! 229: { '\005' /* C-e */, 0, MODEKEYEDIT_ENDOFLINE },
! 230: { '\006' /* C-f */, 0, MODEKEYEDIT_CURSORRIGHT },
! 231: { '\010' /* C-H */, 0, MODEKEYEDIT_BACKSPACE },
! 232: { '\011' /* Tab */, 0, MODEKEYEDIT_COMPLETE },
! 233: { '\013' /* C-k */, 0, MODEKEYEDIT_DELETETOENDOFLINE },
! 234: { '\016' /* C-n */, 0, MODEKEYEDIT_HISTORYDOWN },
! 235: { '\020' /* C-p */, 0, MODEKEYEDIT_HISTORYUP },
! 236: { '\024' /* C-t */, 0, MODEKEYEDIT_TRANSPOSECHARS },
! 237: { '\025' /* C-u */, 0, MODEKEYEDIT_DELETELINE },
! 238: { '\027' /* C-w */, 0, MODEKEYEDIT_DELETEWORD },
! 239: { '\031' /* C-y */, 0, MODEKEYEDIT_PASTE },
! 240: { '\033' /* Escape */, 0, MODEKEYEDIT_CANCEL },
! 241: { '\n', 0, MODEKEYEDIT_ENTER },
! 242: { '\r', 0, MODEKEYEDIT_ENTER },
! 243: { 'b' | KEYC_ESCAPE, 0, MODEKEYEDIT_PREVIOUSWORD },
! 244: { 'f' | KEYC_ESCAPE, 0, MODEKEYEDIT_NEXTWORDEND },
! 245: { 'm' | KEYC_ESCAPE, 0, MODEKEYEDIT_STARTOFLINE },
! 246: { KEYC_BSPACE, 0, MODEKEYEDIT_BACKSPACE },
! 247: { KEYC_DC, 0, MODEKEYEDIT_DELETE },
! 248: { KEYC_DOWN, 0, MODEKEYEDIT_HISTORYDOWN },
! 249: { KEYC_LEFT, 0, MODEKEYEDIT_CURSORLEFT },
! 250: { KEYC_RIGHT, 0, MODEKEYEDIT_CURSORRIGHT },
! 251: { KEYC_UP, 0, MODEKEYEDIT_HISTORYUP },
! 252: { KEYC_HOME, 0, MODEKEYEDIT_STARTOFLINE },
! 253: { KEYC_END, 0, MODEKEYEDIT_ENDOFLINE },
1.8 nicm 254:
1.71 ! nicm 255: { 0, -1, 0 }
1.8 nicm 256: };
1.10 nicm 257: struct mode_key_tree mode_key_tree_emacs_edit;
1.8 nicm 258:
259: /* emacs choice selection keys. */
1.70 nicm 260: static const struct mode_key_entry mode_key_emacs_choice[] = {
1.71 ! nicm 261: { '0' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 262: { '1' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 263: { '2' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 264: { '3' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 265: { '4' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 266: { '5' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 267: { '6' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 268: { '7' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 269: { '8' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 270: { '9' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
! 271: { '\003' /* C-c */, 0, MODEKEYCHOICE_CANCEL },
! 272: { '\016' /* C-n */, 0, MODEKEYCHOICE_DOWN },
! 273: { '\020' /* C-p */, 0, MODEKEYCHOICE_UP },
! 274: { '\026' /* C-v */, 0, MODEKEYCHOICE_PAGEDOWN },
! 275: { '\033' /* Escape */, 0, MODEKEYCHOICE_CANCEL },
! 276: { '\n', 0, MODEKEYCHOICE_CHOOSE },
! 277: { '\r', 0, MODEKEYCHOICE_CHOOSE },
! 278: { 'q', 0, MODEKEYCHOICE_CANCEL },
! 279: { 'v' | KEYC_ESCAPE, 0, MODEKEYCHOICE_PAGEUP },
! 280: { KEYC_HOME, 0, MODEKEYCHOICE_STARTOFLIST },
! 281: { '<' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTOFLIST },
! 282: { 'R' | KEYC_ESCAPE, 0, MODEKEYCHOICE_TOPLINE },
! 283: { '>' | KEYC_ESCAPE, 0, MODEKEYCHOICE_ENDOFLIST },
! 284: { KEYC_END, 0, MODEKEYCHOICE_ENDOFLIST },
! 285: { KEYC_BSPACE, 0, MODEKEYCHOICE_BACKSPACE },
! 286: { KEYC_DOWN | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLDOWN },
! 287: { KEYC_DOWN, 0, MODEKEYCHOICE_DOWN },
! 288: { KEYC_NPAGE, 0, MODEKEYCHOICE_PAGEDOWN },
! 289: { KEYC_PPAGE, 0, MODEKEYCHOICE_PAGEUP },
! 290: { KEYC_UP | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLUP },
! 291: { KEYC_UP, 0, MODEKEYCHOICE_UP },
! 292: { ' ', 0, MODEKEYCHOICE_TREE_TOGGLE },
! 293: { KEYC_LEFT, 0, MODEKEYCHOICE_TREE_COLLAPSE },
! 294: { KEYC_RIGHT, 0, MODEKEYCHOICE_TREE_EXPAND },
! 295: { KEYC_LEFT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_COLLAPSE_ALL },
! 296: { KEYC_RIGHT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_EXPAND_ALL },
! 297: { KEYC_MOUSEDOWN1_PANE, 0, MODEKEYCHOICE_CHOOSE },
! 298: { KEYC_MOUSEDOWN3_PANE, 0, MODEKEYCHOICE_TREE_TOGGLE },
! 299: { KEYC_WHEELUP_PANE, 0, MODEKEYCHOICE_UP },
! 300: { KEYC_WHEELDOWN_PANE, 0, MODEKEYCHOICE_DOWN },
1.8 nicm 301:
1.71 ! nicm 302: { 0, -1, 0 }
1.8 nicm 303: };
1.10 nicm 304: struct mode_key_tree mode_key_tree_emacs_choice;
1.8 nicm 305:
1.10 nicm 306: /* Table mapping key table names to default settings and trees. */
307: const struct mode_key_table mode_key_tables[] = {
308: { "vi-edit", mode_key_cmdstr_edit,
309: &mode_key_tree_vi_edit, mode_key_vi_edit },
310: { "vi-choice", mode_key_cmdstr_choice,
311: &mode_key_tree_vi_choice, mode_key_vi_choice },
312: { "emacs-edit", mode_key_cmdstr_edit,
313: &mode_key_tree_emacs_edit, mode_key_emacs_edit },
314: { "emacs-choice", mode_key_cmdstr_choice,
315: &mode_key_tree_emacs_choice, mode_key_emacs_choice },
316:
317: { NULL, NULL, NULL, NULL }
318: };
319:
1.44 nicm 320: RB_GENERATE(mode_key_tree, mode_key_binding, entry, mode_key_cmp);
1.10 nicm 321:
322: int
323: mode_key_cmp(struct mode_key_binding *mbind1, struct mode_key_binding *mbind2)
324: {
1.64 nicm 325: if (mbind1->mode < mbind2->mode)
326: return (-1);
327: if (mbind1->mode > mbind2->mode)
328: return (1);
329: if (mbind1->key < mbind2->key)
330: return (-1);
331: if (mbind1->key > mbind2->key)
332: return (1);
333: return (0);
1.10 nicm 334: }
335:
336: const char *
1.36 nicm 337: mode_key_tostring(const struct mode_key_cmdstr *cmdstr, enum mode_key_cmd cmd)
1.10 nicm 338: {
339: for (; cmdstr->name != NULL; cmdstr++) {
340: if (cmdstr->cmd == cmd)
341: return (cmdstr->name);
1.11 nicm 342: }
343: return (NULL);
344: }
345:
346: enum mode_key_cmd
1.36 nicm 347: mode_key_fromstring(const struct mode_key_cmdstr *cmdstr, const char *name)
1.11 nicm 348: {
349: for (; cmdstr->name != NULL; cmdstr++) {
350: if (strcasecmp(cmdstr->name, name) == 0)
351: return (cmdstr->cmd);
352: }
353: return (MODEKEY_NONE);
354: }
355:
356: const struct mode_key_table *
357: mode_key_findtable(const char *name)
358: {
359: const struct mode_key_table *mtab;
1.25 nicm 360:
1.11 nicm 361: for (mtab = mode_key_tables; mtab->name != NULL; mtab++) {
362: if (strcasecmp(name, mtab->name) == 0)
363: return (mtab);
1.10 nicm 364: }
365: return (NULL);
366: }
1.1 nicm 367:
368: void
1.10 nicm 369: mode_key_init_trees(void)
1.1 nicm 370: {
1.10 nicm 371: const struct mode_key_table *mtab;
372: const struct mode_key_entry *ment;
373: struct mode_key_binding *mbind;
374:
375: for (mtab = mode_key_tables; mtab->name != NULL; mtab++) {
1.44 nicm 376: RB_INIT(mtab->tree);
1.10 nicm 377: for (ment = mtab->table; ment->mode != -1; ment++) {
378: mbind = xmalloc(sizeof *mbind);
379: mbind->key = ment->key;
380: mbind->mode = ment->mode;
381: mbind->cmd = ment->cmd;
1.44 nicm 382: RB_INSERT(mode_key_tree, mtab->tree, mbind);
1.10 nicm 383: }
384: }
385: }
386:
387: void
388: mode_key_init(struct mode_key_data *mdata, struct mode_key_tree *mtree)
389: {
390: mdata->tree = mtree;
1.8 nicm 391: mdata->mode = 0;
1.1 nicm 392: }
393:
394: enum mode_key_cmd
1.71 ! nicm 395: mode_key_lookup(struct mode_key_data *mdata, key_code key)
1.1 nicm 396: {
1.10 nicm 397: struct mode_key_binding *mbind, mtmp;
398:
399: mtmp.key = key;
400: mtmp.mode = mdata->mode;
1.44 nicm 401: if ((mbind = RB_FIND(mode_key_tree, mdata->tree, &mtmp)) == NULL) {
1.10 nicm 402: if (mdata->mode != 0)
403: return (MODEKEY_NONE);
404: return (MODEKEY_OTHER);
405: }
1.1 nicm 406:
1.10 nicm 407: switch (mbind->cmd) {
408: case MODEKEYEDIT_SWITCHMODE:
409: case MODEKEYEDIT_SWITCHMODEAPPEND:
1.45 nicm 410: case MODEKEYEDIT_SWITCHMODEAPPENDLINE:
411: case MODEKEYEDIT_SWITCHMODEBEGINLINE:
1.53 nicm 412: case MODEKEYEDIT_SWITCHMODECHANGELINE:
413: case MODEKEYEDIT_SWITCHMODESUBSTITUTE:
414: case MODEKEYEDIT_SWITCHMODESUBSTITUTELINE:
1.10 nicm 415: mdata->mode = 1 - mdata->mode;
416: /* FALLTHROUGH */
417: default:
418: return (mbind->cmd);
1.1 nicm 419: }
420: }