xref: /minix/external/bsd/tmux/dist/mode-key.c (revision eda6f593)
1*eda6f593SDavid van Moolenbroek /* $Id: mode-key.c,v 1.1.1.2 2011/08/17 18:40:05 jmmv Exp $ */
2*eda6f593SDavid van Moolenbroek 
3*eda6f593SDavid van Moolenbroek /*
4*eda6f593SDavid van Moolenbroek  * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
5*eda6f593SDavid van Moolenbroek  *
6*eda6f593SDavid van Moolenbroek  * Permission to use, copy, modify, and distribute this software for any
7*eda6f593SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
8*eda6f593SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
9*eda6f593SDavid van Moolenbroek  *
10*eda6f593SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11*eda6f593SDavid van Moolenbroek  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*eda6f593SDavid van Moolenbroek  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13*eda6f593SDavid van Moolenbroek  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*eda6f593SDavid van Moolenbroek  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15*eda6f593SDavid van Moolenbroek  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16*eda6f593SDavid van Moolenbroek  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*eda6f593SDavid van Moolenbroek  */
18*eda6f593SDavid van Moolenbroek 
19*eda6f593SDavid van Moolenbroek #include <sys/types.h>
20*eda6f593SDavid van Moolenbroek 
21*eda6f593SDavid van Moolenbroek #include <string.h>
22*eda6f593SDavid van Moolenbroek 
23*eda6f593SDavid van Moolenbroek #include "tmux.h"
24*eda6f593SDavid van Moolenbroek 
25*eda6f593SDavid van Moolenbroek /*
26*eda6f593SDavid van Moolenbroek  * Mode keys. These are the key bindings used when editing (status prompt), and
27*eda6f593SDavid van Moolenbroek  * in the modes. They are split into two sets of three tables, one set of three
28*eda6f593SDavid van Moolenbroek  * for vi and the other for emacs key bindings. The three tables are for
29*eda6f593SDavid van Moolenbroek  * editing, for menu-like modes (choice, more), and for copy modes (copy,
30*eda6f593SDavid van Moolenbroek  * scroll).
31*eda6f593SDavid van Moolenbroek  *
32*eda6f593SDavid van Moolenbroek  * The fixed tables of struct mode_key_entry below are the defaults: they are
33*eda6f593SDavid van Moolenbroek  * built into a tree of struct mode_key_binding by mode_key_init_trees, which
34*eda6f593SDavid van Moolenbroek  * can then be modified.
35*eda6f593SDavid van Moolenbroek  *
36*eda6f593SDavid van Moolenbroek  * vi command mode is handled by having a mode flag in the struct which allows
37*eda6f593SDavid van Moolenbroek  * two sets of bindings to be swapped between. A couple of editing commands
38*eda6f593SDavid van Moolenbroek  * (MODEKEYEDIT_SWITCHMODE and MODEKEYEDIT_SWITCHMODEAPPEND) are special-cased
39*eda6f593SDavid van Moolenbroek  * to do this.
40*eda6f593SDavid van Moolenbroek  */
41*eda6f593SDavid van Moolenbroek 
42*eda6f593SDavid van Moolenbroek /* Edit keys command strings. */
43*eda6f593SDavid van Moolenbroek const struct mode_key_cmdstr mode_key_cmdstr_edit[] = {
44*eda6f593SDavid van Moolenbroek 	{ MODEKEYEDIT_BACKSPACE, "backspace" },
45*eda6f593SDavid van Moolenbroek 	{ MODEKEYEDIT_CANCEL, "cancel" },
46*eda6f593SDavid van Moolenbroek 	{ MODEKEYEDIT_COMPLETE, "complete" },
47*eda6f593SDavid van Moolenbroek 	{ MODEKEYEDIT_CURSORLEFT, "cursor-left" },
48*eda6f593SDavid van Moolenbroek 	{ MODEKEYEDIT_CURSORRIGHT, "cursor-right" },
49*eda6f593SDavid van Moolenbroek 	{ MODEKEYEDIT_DELETE, "delete" },
50*eda6f593SDavid van Moolenbroek 	{ MODEKEYEDIT_DELETELINE, "delete-line" },
51*eda6f593SDavid van Moolenbroek 	{ MODEKEYEDIT_DELETETOENDOFLINE, "delete-end-of-line" },
52*eda6f593SDavid van Moolenbroek 	{ MODEKEYEDIT_ENDOFLINE, "end-of-line" },
53*eda6f593SDavid van Moolenbroek 	{ MODEKEYEDIT_ENTER, "enter" },
54*eda6f593SDavid van Moolenbroek 	{ MODEKEYEDIT_HISTORYDOWN, "history-down" },
55*eda6f593SDavid van Moolenbroek 	{ MODEKEYEDIT_HISTORYUP, "history-up" },
56*eda6f593SDavid van Moolenbroek 	{ MODEKEYEDIT_PASTE, "paste" },
57*eda6f593SDavid van Moolenbroek 	{ MODEKEYEDIT_STARTOFLINE, "start-of-line" },
58*eda6f593SDavid van Moolenbroek 	{ MODEKEYEDIT_SWITCHMODE, "switch-mode" },
59*eda6f593SDavid van Moolenbroek 	{ MODEKEYEDIT_SWITCHMODEAPPEND, "switch-mode-append" },
60*eda6f593SDavid van Moolenbroek 	{ MODEKEYEDIT_TRANSPOSECHARS, "transpose-chars" },
61*eda6f593SDavid van Moolenbroek 
62*eda6f593SDavid van Moolenbroek 	{ 0, NULL }
63*eda6f593SDavid van Moolenbroek };
64*eda6f593SDavid van Moolenbroek 
65*eda6f593SDavid van Moolenbroek /* Choice keys command strings. */
66*eda6f593SDavid van Moolenbroek const struct mode_key_cmdstr mode_key_cmdstr_choice[] = {
67*eda6f593SDavid van Moolenbroek 	{ MODEKEYCHOICE_CANCEL, "cancel" },
68*eda6f593SDavid van Moolenbroek 	{ MODEKEYCHOICE_CHOOSE, "choose" },
69*eda6f593SDavid van Moolenbroek 	{ MODEKEYCHOICE_DOWN, "down" },
70*eda6f593SDavid van Moolenbroek 	{ MODEKEYCHOICE_PAGEDOWN, "page-down" },
71*eda6f593SDavid van Moolenbroek 	{ MODEKEYCHOICE_PAGEUP, "page-up" },
72*eda6f593SDavid van Moolenbroek 	{ MODEKEYCHOICE_SCROLLDOWN, "scroll-down" },
73*eda6f593SDavid van Moolenbroek 	{ MODEKEYCHOICE_SCROLLUP, "scroll-up" },
74*eda6f593SDavid van Moolenbroek 	{ MODEKEYCHOICE_UP, "up" },
75*eda6f593SDavid van Moolenbroek 
76*eda6f593SDavid van Moolenbroek 	{ 0, NULL }
77*eda6f593SDavid van Moolenbroek };
78*eda6f593SDavid van Moolenbroek 
79*eda6f593SDavid van Moolenbroek /* Copy keys command strings. */
80*eda6f593SDavid van Moolenbroek const struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
81*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_BACKTOINDENTATION, "back-to-indentation" },
82*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_BOTTOMLINE, "bottom-line" },
83*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_CANCEL, "cancel" },
84*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_CLEARSELECTION, "clear-selection" },
85*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_COPYLINE, "copy-line" },
86*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_COPYENDOFLINE, "copy-end-of-line" },
87*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_COPYSELECTION, "copy-selection" },
88*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_DOWN, "cursor-down" },
89*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_ENDOFLINE, "end-of-line" },
90*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_GOTOLINE, "goto-line" },
91*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_HISTORYBOTTOM, "history-bottom" },
92*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_HISTORYTOP, "history-top" },
93*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_JUMP, "jump-forward" },
94*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_JUMPAGAIN, "jump-again" },
95*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_JUMPREVERSE, "jump-reverse" },
96*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_JUMPBACK, "jump-backward" },
97*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_LEFT, "cursor-left" },
98*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_RECTANGLETOGGLE, "rectangle-toggle" },
99*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_MIDDLELINE, "middle-line" },
100*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_NEXTPAGE, "page-down" },
101*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_NEXTSPACE, "next-space" },
102*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_NEXTSPACEEND, "next-space-end" },
103*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_NEXTWORD, "next-word" },
104*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_NEXTWORDEND, "next-word-end" },
105*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_PREVIOUSPAGE, "page-up" },
106*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_PREVIOUSSPACE, "previous-space" },
107*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_PREVIOUSWORD, "previous-word" },
108*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_RIGHT, "cursor-right" },
109*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_SCROLLDOWN, "scroll-down" },
110*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_SCROLLUP, "scroll-up" },
111*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_SEARCHAGAIN, "search-again" },
112*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_SEARCHDOWN, "search-forward" },
113*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_SEARCHREVERSE, "search-reverse" },
114*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_SEARCHUP, "search-backward" },
115*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_SELECTLINE, "select-line" },
116*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_STARTNUMBERPREFIX, "start-number-prefix" },
117*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_STARTOFLINE, "start-of-line" },
118*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_STARTSELECTION, "begin-selection" },
119*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_TOPLINE, "top-line" },
120*eda6f593SDavid van Moolenbroek 	{ MODEKEYCOPY_UP, "cursor-up" },
121*eda6f593SDavid van Moolenbroek 
122*eda6f593SDavid van Moolenbroek 	{ 0, NULL }
123*eda6f593SDavid van Moolenbroek };
124*eda6f593SDavid van Moolenbroek 
125*eda6f593SDavid van Moolenbroek /* vi editing keys. */
126*eda6f593SDavid van Moolenbroek const struct mode_key_entry mode_key_vi_edit[] = {
127*eda6f593SDavid van Moolenbroek 	{ '\003' /* C-c */,	0, MODEKEYEDIT_CANCEL },
128*eda6f593SDavid van Moolenbroek 	{ '\010' /* C-h */, 	0, MODEKEYEDIT_BACKSPACE },
129*eda6f593SDavid van Moolenbroek 	{ '\025' /* C-u	*/,	0, MODEKEYEDIT_DELETELINE },
130*eda6f593SDavid van Moolenbroek 	{ '\011' /* Tab */,	0, MODEKEYEDIT_COMPLETE },
131*eda6f593SDavid van Moolenbroek 	{ '\033' /* Escape */,	0, MODEKEYEDIT_SWITCHMODE },
132*eda6f593SDavid van Moolenbroek 	{ '\r',			0, MODEKEYEDIT_ENTER },
133*eda6f593SDavid van Moolenbroek 	{ KEYC_BSPACE,		0, MODEKEYEDIT_BACKSPACE },
134*eda6f593SDavid van Moolenbroek 	{ KEYC_DC,		0, MODEKEYEDIT_DELETE },
135*eda6f593SDavid van Moolenbroek 
136*eda6f593SDavid van Moolenbroek 	{ '$',			1, MODEKEYEDIT_ENDOFLINE },
137*eda6f593SDavid van Moolenbroek 	{ '0',			1, MODEKEYEDIT_STARTOFLINE },
138*eda6f593SDavid van Moolenbroek 	{ 'D',			1, MODEKEYEDIT_DELETETOENDOFLINE },
139*eda6f593SDavid van Moolenbroek 	{ '\003' /* C-c */,	1, MODEKEYEDIT_CANCEL },
140*eda6f593SDavid van Moolenbroek 	{ '\010' /* C-h */, 	1, MODEKEYEDIT_BACKSPACE },
141*eda6f593SDavid van Moolenbroek 	{ '\r',			1, MODEKEYEDIT_ENTER },
142*eda6f593SDavid van Moolenbroek 	{ '^',			1, MODEKEYEDIT_STARTOFLINE },
143*eda6f593SDavid van Moolenbroek 	{ 'a',			1, MODEKEYEDIT_SWITCHMODEAPPEND },
144*eda6f593SDavid van Moolenbroek 	{ 'd',			1, MODEKEYEDIT_DELETELINE },
145*eda6f593SDavid van Moolenbroek 	{ 'h',			1, MODEKEYEDIT_CURSORLEFT },
146*eda6f593SDavid van Moolenbroek 	{ 'i',			1, MODEKEYEDIT_SWITCHMODE },
147*eda6f593SDavid van Moolenbroek 	{ 'j',			1, MODEKEYEDIT_HISTORYDOWN },
148*eda6f593SDavid van Moolenbroek 	{ 'k',			1, MODEKEYEDIT_HISTORYUP },
149*eda6f593SDavid van Moolenbroek 	{ 'l',			1, MODEKEYEDIT_CURSORRIGHT },
150*eda6f593SDavid van Moolenbroek 	{ 'p',			1, MODEKEYEDIT_PASTE },
151*eda6f593SDavid van Moolenbroek 	{ KEYC_BSPACE,		1, MODEKEYEDIT_BACKSPACE },
152*eda6f593SDavid van Moolenbroek 	{ KEYC_DC,		1, MODEKEYEDIT_DELETE },
153*eda6f593SDavid van Moolenbroek 	{ KEYC_DOWN,		1, MODEKEYEDIT_HISTORYDOWN },
154*eda6f593SDavid van Moolenbroek 	{ KEYC_LEFT,		1, MODEKEYEDIT_CURSORLEFT },
155*eda6f593SDavid van Moolenbroek 	{ KEYC_RIGHT,		1, MODEKEYEDIT_CURSORRIGHT },
156*eda6f593SDavid van Moolenbroek 	{ KEYC_UP,		1, MODEKEYEDIT_HISTORYUP },
157*eda6f593SDavid van Moolenbroek 
158*eda6f593SDavid van Moolenbroek 	{ 0,		       -1, 0 }
159*eda6f593SDavid van Moolenbroek };
160*eda6f593SDavid van Moolenbroek struct mode_key_tree mode_key_tree_vi_edit;
161*eda6f593SDavid van Moolenbroek 
162*eda6f593SDavid van Moolenbroek /* vi choice selection keys. */
163*eda6f593SDavid van Moolenbroek const struct mode_key_entry mode_key_vi_choice[] = {
164*eda6f593SDavid van Moolenbroek 	{ '\002' /* C-b */,     0, MODEKEYCHOICE_PAGEUP },
165*eda6f593SDavid van Moolenbroek 	{ '\003' /* C-c */,	0, MODEKEYCHOICE_CANCEL },
166*eda6f593SDavid van Moolenbroek 	{ '\005' /* C-e */,     0, MODEKEYCHOICE_SCROLLDOWN },
167*eda6f593SDavid van Moolenbroek 	{ '\006' /* C-f */,     0, MODEKEYCHOICE_PAGEDOWN },
168*eda6f593SDavid van Moolenbroek 	{ '\031' /* C-y */,     0, MODEKEYCHOICE_SCROLLUP },
169*eda6f593SDavid van Moolenbroek 	{ '\r',			0, MODEKEYCHOICE_CHOOSE },
170*eda6f593SDavid van Moolenbroek 	{ 'j',			0, MODEKEYCHOICE_DOWN },
171*eda6f593SDavid van Moolenbroek 	{ 'k',			0, MODEKEYCHOICE_UP },
172*eda6f593SDavid van Moolenbroek 	{ 'q',			0, MODEKEYCHOICE_CANCEL },
173*eda6f593SDavid van Moolenbroek 	{ KEYC_DOWN | KEYC_CTRL,0, MODEKEYCHOICE_SCROLLDOWN },
174*eda6f593SDavid van Moolenbroek 	{ KEYC_DOWN,		0, MODEKEYCHOICE_DOWN },
175*eda6f593SDavid van Moolenbroek 	{ KEYC_NPAGE,		0, MODEKEYCHOICE_PAGEDOWN },
176*eda6f593SDavid van Moolenbroek 	{ KEYC_PPAGE,		0, MODEKEYCHOICE_PAGEUP },
177*eda6f593SDavid van Moolenbroek 	{ KEYC_UP | KEYC_CTRL,	0, MODEKEYCHOICE_SCROLLUP },
178*eda6f593SDavid van Moolenbroek 	{ KEYC_UP,		0, MODEKEYCHOICE_UP },
179*eda6f593SDavid van Moolenbroek 
180*eda6f593SDavid van Moolenbroek 	{ 0,			-1, 0 }
181*eda6f593SDavid van Moolenbroek };
182*eda6f593SDavid van Moolenbroek struct mode_key_tree mode_key_tree_vi_choice;
183*eda6f593SDavid van Moolenbroek 
184*eda6f593SDavid van Moolenbroek /* vi copy mode keys. */
185*eda6f593SDavid van Moolenbroek const struct mode_key_entry mode_key_vi_copy[] = {
186*eda6f593SDavid van Moolenbroek 	{ ' ',			0, MODEKEYCOPY_STARTSELECTION },
187*eda6f593SDavid van Moolenbroek 	{ '$',			0, MODEKEYCOPY_ENDOFLINE },
188*eda6f593SDavid van Moolenbroek 	{ ',',			0, MODEKEYCOPY_JUMPREVERSE },
189*eda6f593SDavid van Moolenbroek 	{ ';',			0, MODEKEYCOPY_JUMPAGAIN },
190*eda6f593SDavid van Moolenbroek 	{ '/',			0, MODEKEYCOPY_SEARCHDOWN },
191*eda6f593SDavid van Moolenbroek 	{ '0',			0, MODEKEYCOPY_STARTOFLINE },
192*eda6f593SDavid van Moolenbroek 	{ '1',			0, MODEKEYCOPY_STARTNUMBERPREFIX },
193*eda6f593SDavid van Moolenbroek 	{ '2',			0, MODEKEYCOPY_STARTNUMBERPREFIX },
194*eda6f593SDavid van Moolenbroek 	{ '3',			0, MODEKEYCOPY_STARTNUMBERPREFIX },
195*eda6f593SDavid van Moolenbroek 	{ '4',			0, MODEKEYCOPY_STARTNUMBERPREFIX },
196*eda6f593SDavid van Moolenbroek 	{ '5',			0, MODEKEYCOPY_STARTNUMBERPREFIX },
197*eda6f593SDavid van Moolenbroek 	{ '6',			0, MODEKEYCOPY_STARTNUMBERPREFIX },
198*eda6f593SDavid van Moolenbroek 	{ '7',			0, MODEKEYCOPY_STARTNUMBERPREFIX },
199*eda6f593SDavid van Moolenbroek 	{ '8',			0, MODEKEYCOPY_STARTNUMBERPREFIX },
200*eda6f593SDavid van Moolenbroek 	{ '9',			0, MODEKEYCOPY_STARTNUMBERPREFIX },
201*eda6f593SDavid van Moolenbroek 	{ ':',			0, MODEKEYCOPY_GOTOLINE },
202*eda6f593SDavid van Moolenbroek 	{ '?',			0, MODEKEYCOPY_SEARCHUP },
203*eda6f593SDavid van Moolenbroek 	{ 'B',			0, MODEKEYCOPY_PREVIOUSSPACE },
204*eda6f593SDavid van Moolenbroek 	{ 'D',			0, MODEKEYCOPY_COPYENDOFLINE },
205*eda6f593SDavid van Moolenbroek 	{ 'E',			0, MODEKEYCOPY_NEXTSPACEEND },
206*eda6f593SDavid van Moolenbroek 	{ 'F',			0, MODEKEYCOPY_JUMPBACK },
207*eda6f593SDavid van Moolenbroek 	{ 'G',			0, MODEKEYCOPY_HISTORYBOTTOM },
208*eda6f593SDavid van Moolenbroek 	{ 'H',			0, MODEKEYCOPY_TOPLINE },
209*eda6f593SDavid van Moolenbroek 	{ 'J',			0, MODEKEYCOPY_SCROLLDOWN },
210*eda6f593SDavid van Moolenbroek 	{ 'K',			0, MODEKEYCOPY_SCROLLUP },
211*eda6f593SDavid van Moolenbroek 	{ 'L',			0, MODEKEYCOPY_BOTTOMLINE },
212*eda6f593SDavid van Moolenbroek 	{ 'M',			0, MODEKEYCOPY_MIDDLELINE },
213*eda6f593SDavid van Moolenbroek 	{ 'N',			0, MODEKEYCOPY_SEARCHREVERSE },
214*eda6f593SDavid van Moolenbroek 	{ 'W',			0, MODEKEYCOPY_NEXTSPACE },
215*eda6f593SDavid van Moolenbroek 	{ '\002' /* C-b */,	0, MODEKEYCOPY_PREVIOUSPAGE },
216*eda6f593SDavid van Moolenbroek 	{ '\003' /* C-c */,	0, MODEKEYCOPY_CANCEL },
217*eda6f593SDavid van Moolenbroek 	{ '\004' /* C-d */,	0, MODEKEYCOPY_HALFPAGEDOWN },
218*eda6f593SDavid van Moolenbroek 	{ '\005' /* C-e */,	0, MODEKEYCOPY_SCROLLDOWN },
219*eda6f593SDavid van Moolenbroek 	{ '\006' /* C-f */,	0, MODEKEYCOPY_NEXTPAGE },
220*eda6f593SDavid van Moolenbroek 	{ '\010' /* C-h */,	0, MODEKEYCOPY_LEFT },
221*eda6f593SDavid van Moolenbroek 	{ '\025' /* C-u */,	0, MODEKEYCOPY_HALFPAGEUP },
222*eda6f593SDavid van Moolenbroek 	{ '\031' /* C-y */,	0, MODEKEYCOPY_SCROLLUP },
223*eda6f593SDavid van Moolenbroek 	{ '\033' /* Escape */,	0, MODEKEYCOPY_CLEARSELECTION },
224*eda6f593SDavid van Moolenbroek 	{ '\r',			0, MODEKEYCOPY_COPYSELECTION },
225*eda6f593SDavid van Moolenbroek 	{ '^',			0, MODEKEYCOPY_BACKTOINDENTATION },
226*eda6f593SDavid van Moolenbroek 	{ 'b',			0, MODEKEYCOPY_PREVIOUSWORD },
227*eda6f593SDavid van Moolenbroek 	{ 'e',                  0, MODEKEYCOPY_NEXTWORDEND },
228*eda6f593SDavid van Moolenbroek 	{ 'f',			0, MODEKEYCOPY_JUMP },
229*eda6f593SDavid van Moolenbroek 	{ 'g',			0, MODEKEYCOPY_HISTORYTOP },
230*eda6f593SDavid van Moolenbroek 	{ 'h',			0, MODEKEYCOPY_LEFT },
231*eda6f593SDavid van Moolenbroek 	{ 'j',			0, MODEKEYCOPY_DOWN },
232*eda6f593SDavid van Moolenbroek 	{ 'k',			0, MODEKEYCOPY_UP },
233*eda6f593SDavid van Moolenbroek 	{ 'l',			0, MODEKEYCOPY_RIGHT },
234*eda6f593SDavid van Moolenbroek 	{ 'n',			0, MODEKEYCOPY_SEARCHAGAIN },
235*eda6f593SDavid van Moolenbroek 	{ 'q',			0, MODEKEYCOPY_CANCEL },
236*eda6f593SDavid van Moolenbroek 	{ 'v',			0, MODEKEYCOPY_RECTANGLETOGGLE },
237*eda6f593SDavid van Moolenbroek 	{ 'w',			0, MODEKEYCOPY_NEXTWORD },
238*eda6f593SDavid van Moolenbroek 	{ KEYC_BSPACE,		0, MODEKEYCOPY_LEFT },
239*eda6f593SDavid van Moolenbroek 	{ KEYC_DOWN | KEYC_CTRL,0, MODEKEYCOPY_SCROLLDOWN },
240*eda6f593SDavid van Moolenbroek 	{ KEYC_DOWN,		0, MODEKEYCOPY_DOWN },
241*eda6f593SDavid van Moolenbroek 	{ KEYC_LEFT,		0, MODEKEYCOPY_LEFT },
242*eda6f593SDavid van Moolenbroek 	{ KEYC_NPAGE,		0, MODEKEYCOPY_NEXTPAGE },
243*eda6f593SDavid van Moolenbroek 	{ KEYC_PPAGE,		0, MODEKEYCOPY_PREVIOUSPAGE },
244*eda6f593SDavid van Moolenbroek 	{ KEYC_RIGHT,		0, MODEKEYCOPY_RIGHT },
245*eda6f593SDavid van Moolenbroek 	{ KEYC_UP | KEYC_CTRL,	0, MODEKEYCOPY_SCROLLUP },
246*eda6f593SDavid van Moolenbroek 	{ KEYC_UP,		0, MODEKEYCOPY_UP },
247*eda6f593SDavid van Moolenbroek 
248*eda6f593SDavid van Moolenbroek 	{ 0,			-1, 0 }
249*eda6f593SDavid van Moolenbroek };
250*eda6f593SDavid van Moolenbroek struct mode_key_tree mode_key_tree_vi_copy;
251*eda6f593SDavid van Moolenbroek 
252*eda6f593SDavid van Moolenbroek /* emacs editing keys. */
253*eda6f593SDavid van Moolenbroek const struct mode_key_entry mode_key_emacs_edit[] = {
254*eda6f593SDavid van Moolenbroek 	{ '\001' /* C-a */,	0, MODEKEYEDIT_STARTOFLINE },
255*eda6f593SDavid van Moolenbroek 	{ '\002' /* C-b */,	0, MODEKEYEDIT_CURSORLEFT },
256*eda6f593SDavid van Moolenbroek 	{ '\003' /* C-c */,	0, MODEKEYEDIT_CANCEL },
257*eda6f593SDavid van Moolenbroek 	{ '\004' /* C-d */,	0, MODEKEYEDIT_DELETE },
258*eda6f593SDavid van Moolenbroek 	{ '\005' /* C-e	*/,	0, MODEKEYEDIT_ENDOFLINE },
259*eda6f593SDavid van Moolenbroek 	{ '\006' /* C-f */,	0, MODEKEYEDIT_CURSORRIGHT },
260*eda6f593SDavid van Moolenbroek 	{ '\010' /* C-H */, 	0, MODEKEYEDIT_BACKSPACE },
261*eda6f593SDavid van Moolenbroek 	{ '\011' /* Tab */,     0, MODEKEYEDIT_COMPLETE },
262*eda6f593SDavid van Moolenbroek 	{ '\013' /* C-k	*/,	0, MODEKEYEDIT_DELETETOENDOFLINE },
263*eda6f593SDavid van Moolenbroek 	{ '\016' /* C-n */,	0, MODEKEYEDIT_HISTORYDOWN },
264*eda6f593SDavid van Moolenbroek 	{ '\020' /* C-p */,	0, MODEKEYEDIT_HISTORYUP },
265*eda6f593SDavid van Moolenbroek 	{ '\024' /* C-t */,	0, MODEKEYEDIT_TRANSPOSECHARS },
266*eda6f593SDavid van Moolenbroek 	{ '\025' /* C-u	*/,	0, MODEKEYEDIT_DELETELINE },
267*eda6f593SDavid van Moolenbroek 	{ '\031' /* C-y */,	0, MODEKEYEDIT_PASTE },
268*eda6f593SDavid van Moolenbroek 	{ '\033' /* Escape */,	0, MODEKEYEDIT_CANCEL },
269*eda6f593SDavid van Moolenbroek 	{ '\r',			0, MODEKEYEDIT_ENTER },
270*eda6f593SDavid van Moolenbroek 	{ 'm' | KEYC_ESCAPE,	0, MODEKEYEDIT_STARTOFLINE },
271*eda6f593SDavid van Moolenbroek 	{ KEYC_BSPACE,		0, MODEKEYEDIT_BACKSPACE },
272*eda6f593SDavid van Moolenbroek 	{ KEYC_DC,		0, MODEKEYEDIT_DELETE },
273*eda6f593SDavid van Moolenbroek 	{ KEYC_DOWN,		0, MODEKEYEDIT_HISTORYDOWN },
274*eda6f593SDavid van Moolenbroek 	{ KEYC_LEFT,		0, MODEKEYEDIT_CURSORLEFT },
275*eda6f593SDavid van Moolenbroek 	{ KEYC_RIGHT,		0, MODEKEYEDIT_CURSORRIGHT },
276*eda6f593SDavid van Moolenbroek 	{ KEYC_UP,		0, MODEKEYEDIT_HISTORYUP },
277*eda6f593SDavid van Moolenbroek 
278*eda6f593SDavid van Moolenbroek 	{ 0,		       -1, 0 }
279*eda6f593SDavid van Moolenbroek };
280*eda6f593SDavid van Moolenbroek struct mode_key_tree mode_key_tree_emacs_edit;
281*eda6f593SDavid van Moolenbroek 
282*eda6f593SDavid van Moolenbroek /* emacs choice selection keys. */
283*eda6f593SDavid van Moolenbroek const struct mode_key_entry mode_key_emacs_choice[] = {
284*eda6f593SDavid van Moolenbroek 	{ '\003' /* C-c */,	0, MODEKEYCHOICE_CANCEL },
285*eda6f593SDavid van Moolenbroek 	{ '\016' /* C-n */,	0, MODEKEYCHOICE_DOWN },
286*eda6f593SDavid van Moolenbroek 	{ '\020' /* C-p */,	0, MODEKEYCHOICE_UP },
287*eda6f593SDavid van Moolenbroek 	{ '\026' /* C-v */,	0, MODEKEYCHOICE_PAGEDOWN },
288*eda6f593SDavid van Moolenbroek 	{ '\033' /* Escape */,	0, MODEKEYCHOICE_CANCEL },
289*eda6f593SDavid van Moolenbroek 	{ '\r',			0, MODEKEYCHOICE_CHOOSE },
290*eda6f593SDavid van Moolenbroek 	{ 'q',			0, MODEKEYCHOICE_CANCEL },
291*eda6f593SDavid van Moolenbroek 	{ 'v' | KEYC_ESCAPE,	0, MODEKEYCHOICE_PAGEUP },
292*eda6f593SDavid van Moolenbroek 	{ KEYC_DOWN | KEYC_CTRL,0, MODEKEYCHOICE_SCROLLDOWN },
293*eda6f593SDavid van Moolenbroek 	{ KEYC_DOWN,		0, MODEKEYCHOICE_DOWN },
294*eda6f593SDavid van Moolenbroek 	{ KEYC_NPAGE,		0, MODEKEYCHOICE_PAGEDOWN },
295*eda6f593SDavid van Moolenbroek 	{ KEYC_PPAGE,		0, MODEKEYCHOICE_PAGEUP },
296*eda6f593SDavid van Moolenbroek 	{ KEYC_UP | KEYC_CTRL,	0, MODEKEYCHOICE_SCROLLUP },
297*eda6f593SDavid van Moolenbroek 	{ KEYC_UP,		0, MODEKEYCHOICE_UP },
298*eda6f593SDavid van Moolenbroek 
299*eda6f593SDavid van Moolenbroek 	{ 0,			-1, 0 }
300*eda6f593SDavid van Moolenbroek };
301*eda6f593SDavid van Moolenbroek struct mode_key_tree mode_key_tree_emacs_choice;
302*eda6f593SDavid van Moolenbroek 
303*eda6f593SDavid van Moolenbroek /* emacs copy mode keys. */
304*eda6f593SDavid van Moolenbroek const struct mode_key_entry mode_key_emacs_copy[] = {
305*eda6f593SDavid van Moolenbroek 	{ ' ',			0, MODEKEYCOPY_NEXTPAGE },
306*eda6f593SDavid van Moolenbroek 	{ ',',			0, MODEKEYCOPY_JUMPREVERSE },
307*eda6f593SDavid van Moolenbroek 	{ ';',			0, MODEKEYCOPY_JUMPAGAIN },
308*eda6f593SDavid van Moolenbroek 	{ '1' | KEYC_ESCAPE,	0, MODEKEYCOPY_STARTNUMBERPREFIX },
309*eda6f593SDavid van Moolenbroek 	{ '2' | KEYC_ESCAPE,	0, MODEKEYCOPY_STARTNUMBERPREFIX },
310*eda6f593SDavid van Moolenbroek 	{ '3' | KEYC_ESCAPE,	0, MODEKEYCOPY_STARTNUMBERPREFIX },
311*eda6f593SDavid van Moolenbroek 	{ '4' | KEYC_ESCAPE,	0, MODEKEYCOPY_STARTNUMBERPREFIX },
312*eda6f593SDavid van Moolenbroek 	{ '5' | KEYC_ESCAPE,	0, MODEKEYCOPY_STARTNUMBERPREFIX },
313*eda6f593SDavid van Moolenbroek 	{ '6' | KEYC_ESCAPE,	0, MODEKEYCOPY_STARTNUMBERPREFIX },
314*eda6f593SDavid van Moolenbroek 	{ '7' | KEYC_ESCAPE,	0, MODEKEYCOPY_STARTNUMBERPREFIX },
315*eda6f593SDavid van Moolenbroek 	{ '8' | KEYC_ESCAPE,	0, MODEKEYCOPY_STARTNUMBERPREFIX },
316*eda6f593SDavid van Moolenbroek 	{ '9' | KEYC_ESCAPE,	0, MODEKEYCOPY_STARTNUMBERPREFIX },
317*eda6f593SDavid van Moolenbroek 	{ '<' | KEYC_ESCAPE,    0, MODEKEYCOPY_HISTORYTOP },
318*eda6f593SDavid van Moolenbroek 	{ '>' | KEYC_ESCAPE,    0, MODEKEYCOPY_HISTORYBOTTOM },
319*eda6f593SDavid van Moolenbroek 	{ 'F',			0, MODEKEYCOPY_JUMPBACK },
320*eda6f593SDavid van Moolenbroek 	{ 'N',			0, MODEKEYCOPY_SEARCHREVERSE },
321*eda6f593SDavid van Moolenbroek 	{ 'R' | KEYC_ESCAPE,	0, MODEKEYCOPY_TOPLINE },
322*eda6f593SDavid van Moolenbroek 	{ 'R',			0, MODEKEYCOPY_RECTANGLETOGGLE },
323*eda6f593SDavid van Moolenbroek 	{ '\000' /* C-Space */,	0, MODEKEYCOPY_STARTSELECTION },
324*eda6f593SDavid van Moolenbroek 	{ '\001' /* C-a */,	0, MODEKEYCOPY_STARTOFLINE },
325*eda6f593SDavid van Moolenbroek 	{ '\002' /* C-b */,	0, MODEKEYCOPY_LEFT },
326*eda6f593SDavid van Moolenbroek 	{ '\003' /* C-c */,	0, MODEKEYCOPY_CANCEL },
327*eda6f593SDavid van Moolenbroek 	{ '\005' /* C-e */,	0, MODEKEYCOPY_ENDOFLINE },
328*eda6f593SDavid van Moolenbroek 	{ '\006' /* C-f */,	0, MODEKEYCOPY_RIGHT },
329*eda6f593SDavid van Moolenbroek 	{ '\007' /* C-g */,	0, MODEKEYCOPY_CLEARSELECTION },
330*eda6f593SDavid van Moolenbroek 	{ '\013' /* C-k */,	0, MODEKEYCOPY_COPYENDOFLINE },
331*eda6f593SDavid van Moolenbroek 	{ '\016' /* C-n */,	0, MODEKEYCOPY_DOWN },
332*eda6f593SDavid van Moolenbroek 	{ '\020' /* C-p */,	0, MODEKEYCOPY_UP },
333*eda6f593SDavid van Moolenbroek 	{ '\022' /* C-r */,	0, MODEKEYCOPY_SEARCHUP },
334*eda6f593SDavid van Moolenbroek 	{ '\023' /* C-s */,	0, MODEKEYCOPY_SEARCHDOWN },
335*eda6f593SDavid van Moolenbroek 	{ '\026' /* C-v */,	0, MODEKEYCOPY_NEXTPAGE },
336*eda6f593SDavid van Moolenbroek 	{ '\027' /* C-w */,	0, MODEKEYCOPY_COPYSELECTION },
337*eda6f593SDavid van Moolenbroek 	{ '\033' /* Escape */,	0, MODEKEYCOPY_CANCEL },
338*eda6f593SDavid van Moolenbroek 	{ 'N',			0, MODEKEYCOPY_SEARCHREVERSE },
339*eda6f593SDavid van Moolenbroek 	{ 'b' | KEYC_ESCAPE,	0, MODEKEYCOPY_PREVIOUSWORD },
340*eda6f593SDavid van Moolenbroek 	{ 'f',			0, MODEKEYCOPY_JUMP },
341*eda6f593SDavid van Moolenbroek 	{ 'f' | KEYC_ESCAPE,	0, MODEKEYCOPY_NEXTWORDEND },
342*eda6f593SDavid van Moolenbroek 	{ 'g',			0, MODEKEYCOPY_GOTOLINE },
343*eda6f593SDavid van Moolenbroek 	{ 'm' | KEYC_ESCAPE,	0, MODEKEYCOPY_BACKTOINDENTATION },
344*eda6f593SDavid van Moolenbroek 	{ 'n',			0, MODEKEYCOPY_SEARCHAGAIN },
345*eda6f593SDavid van Moolenbroek 	{ 'q',			0, MODEKEYCOPY_CANCEL },
346*eda6f593SDavid van Moolenbroek 	{ 'r' | KEYC_ESCAPE,	0, MODEKEYCOPY_MIDDLELINE },
347*eda6f593SDavid van Moolenbroek 	{ 'v' | KEYC_ESCAPE,	0, MODEKEYCOPY_PREVIOUSPAGE },
348*eda6f593SDavid van Moolenbroek 	{ 'w' | KEYC_ESCAPE,	0, MODEKEYCOPY_COPYSELECTION },
349*eda6f593SDavid van Moolenbroek 	{ KEYC_DOWN | KEYC_CTRL,0, MODEKEYCOPY_SCROLLDOWN },
350*eda6f593SDavid van Moolenbroek 	{ KEYC_DOWN | KEYC_ESCAPE, 0, MODEKEYCOPY_HALFPAGEDOWN },
351*eda6f593SDavid van Moolenbroek 	{ KEYC_DOWN,		0, MODEKEYCOPY_DOWN },
352*eda6f593SDavid van Moolenbroek 	{ KEYC_LEFT,		0, MODEKEYCOPY_LEFT },
353*eda6f593SDavid van Moolenbroek 	{ KEYC_NPAGE,		0, MODEKEYCOPY_NEXTPAGE },
354*eda6f593SDavid van Moolenbroek 	{ KEYC_PPAGE,		0, MODEKEYCOPY_PREVIOUSPAGE },
355*eda6f593SDavid van Moolenbroek 	{ KEYC_RIGHT,		0, MODEKEYCOPY_RIGHT },
356*eda6f593SDavid van Moolenbroek 	{ KEYC_UP | KEYC_CTRL,	0, MODEKEYCOPY_SCROLLUP },
357*eda6f593SDavid van Moolenbroek 	{ KEYC_UP | KEYC_ESCAPE, 0, MODEKEYCOPY_HALFPAGEUP },
358*eda6f593SDavid van Moolenbroek 	{ KEYC_UP,		0, MODEKEYCOPY_UP },
359*eda6f593SDavid van Moolenbroek 
360*eda6f593SDavid van Moolenbroek 	{ 0,			-1, 0 }
361*eda6f593SDavid van Moolenbroek };
362*eda6f593SDavid van Moolenbroek struct mode_key_tree mode_key_tree_emacs_copy;
363*eda6f593SDavid van Moolenbroek 
364*eda6f593SDavid van Moolenbroek /* Table mapping key table names to default settings and trees. */
365*eda6f593SDavid van Moolenbroek const struct mode_key_table mode_key_tables[] = {
366*eda6f593SDavid van Moolenbroek 	{ "vi-edit", mode_key_cmdstr_edit,
367*eda6f593SDavid van Moolenbroek 	  &mode_key_tree_vi_edit, mode_key_vi_edit },
368*eda6f593SDavid van Moolenbroek 	{ "vi-choice", mode_key_cmdstr_choice,
369*eda6f593SDavid van Moolenbroek 	  &mode_key_tree_vi_choice, mode_key_vi_choice },
370*eda6f593SDavid van Moolenbroek 	{ "vi-copy", mode_key_cmdstr_copy,
371*eda6f593SDavid van Moolenbroek 	  &mode_key_tree_vi_copy, mode_key_vi_copy },
372*eda6f593SDavid van Moolenbroek 	{ "emacs-edit", mode_key_cmdstr_edit,
373*eda6f593SDavid van Moolenbroek 	  &mode_key_tree_emacs_edit, mode_key_emacs_edit },
374*eda6f593SDavid van Moolenbroek 	{ "emacs-choice", mode_key_cmdstr_choice,
375*eda6f593SDavid van Moolenbroek 	  &mode_key_tree_emacs_choice, mode_key_emacs_choice },
376*eda6f593SDavid van Moolenbroek 	{ "emacs-copy", mode_key_cmdstr_copy,
377*eda6f593SDavid van Moolenbroek 	  &mode_key_tree_emacs_copy, mode_key_emacs_copy },
378*eda6f593SDavid van Moolenbroek 
379*eda6f593SDavid van Moolenbroek 	{ NULL, NULL, NULL, NULL }
380*eda6f593SDavid van Moolenbroek };
381*eda6f593SDavid van Moolenbroek 
382*eda6f593SDavid van Moolenbroek SPLAY_GENERATE(mode_key_tree, mode_key_binding, entry, mode_key_cmp);
383*eda6f593SDavid van Moolenbroek 
384*eda6f593SDavid van Moolenbroek int
385*eda6f593SDavid van Moolenbroek mode_key_cmp(struct mode_key_binding *mbind1, struct mode_key_binding *mbind2)
386*eda6f593SDavid van Moolenbroek {
387*eda6f593SDavid van Moolenbroek 	if (mbind1->mode != mbind2->mode)
388*eda6f593SDavid van Moolenbroek 		return (mbind1->mode - mbind2->mode);
389*eda6f593SDavid van Moolenbroek 	return (mbind1->key - mbind2->key);
390*eda6f593SDavid van Moolenbroek }
391*eda6f593SDavid van Moolenbroek 
392*eda6f593SDavid van Moolenbroek const char *
393*eda6f593SDavid van Moolenbroek mode_key_tostring(const struct mode_key_cmdstr *cmdstr, enum mode_key_cmd cmd)
394*eda6f593SDavid van Moolenbroek {
395*eda6f593SDavid van Moolenbroek 	for (; cmdstr->name != NULL; cmdstr++) {
396*eda6f593SDavid van Moolenbroek 		if (cmdstr->cmd == cmd)
397*eda6f593SDavid van Moolenbroek 			return (cmdstr->name);
398*eda6f593SDavid van Moolenbroek 	}
399*eda6f593SDavid van Moolenbroek 	return (NULL);
400*eda6f593SDavid van Moolenbroek }
401*eda6f593SDavid van Moolenbroek 
402*eda6f593SDavid van Moolenbroek enum mode_key_cmd
403*eda6f593SDavid van Moolenbroek mode_key_fromstring(const struct mode_key_cmdstr *cmdstr, const char *name)
404*eda6f593SDavid van Moolenbroek {
405*eda6f593SDavid van Moolenbroek 	for (; cmdstr->name != NULL; cmdstr++) {
406*eda6f593SDavid van Moolenbroek 		if (strcasecmp(cmdstr->name, name) == 0)
407*eda6f593SDavid van Moolenbroek 			return (cmdstr->cmd);
408*eda6f593SDavid van Moolenbroek 	}
409*eda6f593SDavid van Moolenbroek 	return (MODEKEY_NONE);
410*eda6f593SDavid van Moolenbroek }
411*eda6f593SDavid van Moolenbroek 
412*eda6f593SDavid van Moolenbroek const struct mode_key_table *
413*eda6f593SDavid van Moolenbroek mode_key_findtable(const char *name)
414*eda6f593SDavid van Moolenbroek {
415*eda6f593SDavid van Moolenbroek 	const struct mode_key_table	*mtab;
416*eda6f593SDavid van Moolenbroek 
417*eda6f593SDavid van Moolenbroek 	for (mtab = mode_key_tables; mtab->name != NULL; mtab++) {
418*eda6f593SDavid van Moolenbroek 		if (strcasecmp(name, mtab->name) == 0)
419*eda6f593SDavid van Moolenbroek 			return (mtab);
420*eda6f593SDavid van Moolenbroek 	}
421*eda6f593SDavid van Moolenbroek 	return (NULL);
422*eda6f593SDavid van Moolenbroek }
423*eda6f593SDavid van Moolenbroek 
424*eda6f593SDavid van Moolenbroek void
425*eda6f593SDavid van Moolenbroek mode_key_init_trees(void)
426*eda6f593SDavid van Moolenbroek {
427*eda6f593SDavid van Moolenbroek 	const struct mode_key_table	*mtab;
428*eda6f593SDavid van Moolenbroek 	const struct mode_key_entry	*ment;
429*eda6f593SDavid van Moolenbroek 	struct mode_key_binding		*mbind;
430*eda6f593SDavid van Moolenbroek 
431*eda6f593SDavid van Moolenbroek 	for (mtab = mode_key_tables; mtab->name != NULL; mtab++) {
432*eda6f593SDavid van Moolenbroek 		SPLAY_INIT(mtab->tree);
433*eda6f593SDavid van Moolenbroek 		for (ment = mtab->table; ment->mode != -1; ment++) {
434*eda6f593SDavid van Moolenbroek 			mbind = xmalloc(sizeof *mbind);
435*eda6f593SDavid van Moolenbroek 			mbind->key = ment->key;
436*eda6f593SDavid van Moolenbroek 			mbind->mode = ment->mode;
437*eda6f593SDavid van Moolenbroek 			mbind->cmd = ment->cmd;
438*eda6f593SDavid van Moolenbroek 			SPLAY_INSERT(mode_key_tree, mtab->tree, mbind);
439*eda6f593SDavid van Moolenbroek 		}
440*eda6f593SDavid van Moolenbroek 	}
441*eda6f593SDavid van Moolenbroek }
442*eda6f593SDavid van Moolenbroek 
443*eda6f593SDavid van Moolenbroek void
444*eda6f593SDavid van Moolenbroek mode_key_init(struct mode_key_data *mdata, struct mode_key_tree *mtree)
445*eda6f593SDavid van Moolenbroek {
446*eda6f593SDavid van Moolenbroek 	mdata->tree = mtree;
447*eda6f593SDavid van Moolenbroek 	mdata->mode = 0;
448*eda6f593SDavid van Moolenbroek }
449*eda6f593SDavid van Moolenbroek 
450*eda6f593SDavid van Moolenbroek enum mode_key_cmd
451*eda6f593SDavid van Moolenbroek mode_key_lookup(struct mode_key_data *mdata, int key)
452*eda6f593SDavid van Moolenbroek {
453*eda6f593SDavid van Moolenbroek 	struct mode_key_binding	*mbind, mtmp;
454*eda6f593SDavid van Moolenbroek 
455*eda6f593SDavid van Moolenbroek 	mtmp.key = key;
456*eda6f593SDavid van Moolenbroek 	mtmp.mode = mdata->mode;
457*eda6f593SDavid van Moolenbroek 	if ((mbind = SPLAY_FIND(mode_key_tree, mdata->tree, &mtmp)) == NULL) {
458*eda6f593SDavid van Moolenbroek 		if (mdata->mode != 0)
459*eda6f593SDavid van Moolenbroek 			return (MODEKEY_NONE);
460*eda6f593SDavid van Moolenbroek 		return (MODEKEY_OTHER);
461*eda6f593SDavid van Moolenbroek 	}
462*eda6f593SDavid van Moolenbroek 
463*eda6f593SDavid van Moolenbroek 	switch (mbind->cmd) {
464*eda6f593SDavid van Moolenbroek 	case MODEKEYEDIT_SWITCHMODE:
465*eda6f593SDavid van Moolenbroek 	case MODEKEYEDIT_SWITCHMODEAPPEND:
466*eda6f593SDavid van Moolenbroek 		mdata->mode = 1 - mdata->mode;
467*eda6f593SDavid van Moolenbroek 		/* FALLTHROUGH */
468*eda6f593SDavid van Moolenbroek 	default:
469*eda6f593SDavid van Moolenbroek 		return (mbind->cmd);
470*eda6f593SDavid van Moolenbroek 	}
471*eda6f593SDavid van Moolenbroek }
472