Corrected some authors email addresses.
[midnight-commander.git] / edit / edit_key_translator.c
blob3ece101f5fe28ede64c3ff86cc73120d7c705a60
1 /*
2 these #defines are probably the ones most people will be interested in.
3 You can use these two #defines to hard code the key mappings --- just
4 uncomment the one you want. But only if you have trouble with learn
5 keys (which is unlikely).
6 */
8 /* KEY_BACKSPACE is the key learned in the learn keys menu : */
9 #define OUR_BACKSPACE_KEY KEY_BACKSPACE
10 /* ...otherwise ctrl-h : */
11 /* #define OUR_BACKSPACE_KEY XCTRL ('h') */
12 /* ...otherwise 127 or DEL in ascii : */
13 /* #define OUR_BACKSPACE_KEY 0177 */
15 /* KEY_DC is the key learned in the learn keys menu */
16 #define OUR_DELETE_KEY KEY_DC
17 /* ...otherwise ctrl-d : */
18 /* #define OUR_DELETE_KEY XCTRL ('d') */
19 /* ...otherwise 127 or DEL in ascii : */
20 /* #define OUR_DELETE_KEY 0177 */
24 This is #include'd into the function edit_translate_key in edit.c.
25 This sequence of code takes 'x_state' and 'x_key' and translates them
26 into either 'command' or 'char_for_insertion'. 'x_key' holds one of
27 KEY_NPAGE, KEY_HOME etc., and 'x_state' holds a bitwise inclusive OR of
28 CONTROL_PRESSED, ALT_PRESSED or SHIFT_PRESSED, although none may
29 be supported.
30 'command' is one of the editor commands editcmddef.h.
32 Almost any C code can go into this file. The code below is an example
33 that may by appended or modified by the user.
36 /* look in this file for the list of commands : */
37 #include "editcmddef.h"
39 #define KEY_NUMLOCK ???
41 /* ordinary translations. (Some of this may be redundant.) Note that keys listed
42 first take priority when a key is assigned to more than one command */
43 static const long *key_map;
44 static const long cooledit_key_map[] =
45 {OUR_BACKSPACE_KEY, CK_BackSpace, OUR_DELETE_KEY, CK_Delete,
46 XCTRL ('d'), CK_Delete, '\n', CK_Enter,
47 KEY_PPAGE, CK_Page_Up, KEY_NPAGE, CK_Page_Down, KEY_LEFT, CK_Left,
48 KEY_RIGHT, CK_Right, KEY_UP, CK_Up, KEY_DOWN, CK_Down, ALT ('\t'), CK_Return, ALT ('\n'), CK_Return,
49 KEY_HOME, CK_Home, KEY_END, CK_End, '\t', CK_Tab, XCTRL ('u'), CK_Undo, KEY_IC, CK_Toggle_Insert,
50 XCTRL ('o'), CK_Load, KEY_F (3), CK_Mark, KEY_F (13), CK_Column_Mark, KEY_F (5), CK_Copy,
51 KEY_F (6), CK_Move, KEY_F (8), CK_Remove, KEY_F (12), CK_Save_As,
52 KEY_F (2), CK_Save, XCTRL ('n'), CK_New,
53 XCTRL ('l'), CK_Refresh, ESC_CHAR, CK_Exit, KEY_F (10), CK_Exit,
54 KEY_F (11), /* edit user menu */ CK_User_Menu,
55 KEY_F (19), /*C formatter */ CK_Pipe_Block (0),
56 XCTRL ('p'), /*spell check */ CK_Pipe_Block (1),
57 KEY_F (15), CK_Insert_File,
58 XCTRL ('f'), CK_Save_Block, KEY_F (1), CK_Help,
59 ALT ('t'), CK_Sort, ALT ('m'), CK_Mail,
60 XCTRL ('z'), CK_Word_Left, XCTRL ('x'), CK_Word_Right,
61 KEY_F (4), CK_Replace, KEY_F (7), CK_Find, KEY_F (14), CK_Replace_Again,
62 XCTRL ('h'), CK_BackSpace, ALT ('l'), CK_Goto, ALT ('L'), CK_Goto, XCTRL ('y'), CK_Delete_Line,
63 KEY_F (17), CK_Find_Again, ALT ('p'), CK_Paragraph_Format,
64 0177, CK_BackSpace,
65 0, 0};
67 static long const emacs_key_map[] =
68 {OUR_BACKSPACE_KEY, CK_BackSpace, OUR_DELETE_KEY, CK_Delete, '\n', CK_Enter,
69 KEY_PPAGE, CK_Page_Up, KEY_NPAGE, CK_Page_Down, KEY_LEFT, CK_Left,
70 KEY_RIGHT, CK_Right, KEY_UP, CK_Up, KEY_DOWN, CK_Down, ALT ('\t'), CK_Return, ALT ('\n'), CK_Return,
71 KEY_HOME, CK_Home, KEY_END, CK_End, '\t', CK_Tab, XCTRL ('u'), CK_Undo, KEY_IC, CK_Toggle_Insert,
72 XCTRL ('o'), CK_Load, KEY_F (3), CK_Mark, KEY_F (13), CK_Column_Mark, KEY_F (5), CK_Copy,
73 KEY_F (6), CK_Move, KEY_F (8), CK_Remove, KEY_F (12), CK_Save_As,
74 KEY_F (2), CK_Save, ALT ('p'), CK_Paragraph_Format,
76 ALT ('t'), CK_Sort,
78 XCTRL ('a'), CK_Home, XCTRL ('e'), CK_End,
79 XCTRL ('b'), CK_Left, XCTRL ('f'), CK_Right,
80 XCTRL ('n'), CK_Down, XCTRL ('p'), CK_Up,
81 XCTRL ('d'), CK_Delete,
82 XCTRL ('v'), CK_Page_Down, ALT ('v'), CK_Page_Up,
83 XCTRL ('@'), CK_Mark,
84 XCTRL ('k'), CK_Delete_To_Line_End,
85 XCTRL ('s'), CK_Find,
87 ALT ('b'), CK_Word_Left, ALT ('f'), CK_Word_Right,
88 XCTRL ('w'), CK_XCut,
89 XCTRL ('y'), CK_XPaste,
90 ALT ('w'), CK_XStore,
92 XCTRL ('l'), CK_Refresh, ESC_CHAR, CK_Exit, KEY_F (10), CK_Exit,
93 KEY_F (11), /* edit user menu */ CK_User_Menu,
94 KEY_F (19), /*C formatter */ CK_Pipe_Block (0),
95 ALT ('$'), /*spell check */ CK_Pipe_Block (1),
96 KEY_F (15), CK_Insert_File,
97 KEY_F (1), CK_Help,
99 KEY_F (4), CK_Replace, KEY_F (7), CK_Find, KEY_F (14), CK_Replace_Again,
100 XCTRL ('h'), CK_BackSpace, ALT ('l'), CK_Goto, ALT ('L'), CK_Goto,
101 KEY_F (17), CK_Find_Again,
102 ALT ('<'), CK_Beginning_Of_Text,
103 ALT ('>'), CK_End_Of_Text,
104 0177, CK_BackSpace,
106 0, 0};
108 static long const key_pad_map[10] =
109 {XCTRL ('o'), KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT,
110 KEY_DOWN, KEY_RIGHT, KEY_HOME, KEY_UP, KEY_PPAGE};
113 #define DEFAULT_NUM_LOCK 0
115 static int num_lock = DEFAULT_NUM_LOCK;
116 int i = 0;
118 switch (edit_key_emulation) {
119 case EDIT_KEY_EMULATION_NORMAL:
120 key_map = cooledit_key_map;
121 break;
122 case EDIT_KEY_EMULATION_EMACS:
123 key_map = emacs_key_map;
124 if (x_key == XCTRL ('x')) {
125 int ext_key;
126 ext_key = edit_raw_key_query (" Ctrl-X ", _(" Emacs key: "), 0);
127 switch (ext_key) {
128 case 's':
129 command = CK_Save;
130 goto fin;
131 case 'x':
132 command = CK_Exit;
133 goto fin;
134 case 'k':
135 command = CK_New;
136 goto fin;
137 case 'e':
138 command = CK_Macro (edit_raw_key_query (_(" Execute Macro "), _(" Press macro hotkey: "), 1));
139 if (command == CK_Macro (0))
140 command = -1;
141 goto fin;
143 goto fin;
145 break;
148 if (x_key == XCTRL ('q')) {
149 char_for_insertion = edit_raw_key_query (_(" Insert Literal "), _(" Press any key: "), 0);
150 goto fin;
152 if (x_key == XCTRL ('a') && edit_key_emulation != EDIT_KEY_EMULATION_EMACS) {
153 command = CK_Macro (edit_raw_key_query (_(" Execute Macro "), _(" Press macro hotkey: "), 1));
154 if (command == CK_Macro (0))
155 command = -1;
156 goto fin;
158 /* edit is a pointer to the widget */
159 if (edit)
160 if (x_key == XCTRL ('r')) {
161 command = edit->macro_i < 0 ? CK_Begin_Record_Macro : CK_End_Record_Macro;
162 goto fin;
164 /* if (x_key == KEY_NUMLOCK) {
165 num_lock = 1 - num_lock;
166 return 1;
170 /* first translate the key-pad */
171 if (num_lock) {
172 if (x_key >= '0' && x_key <= '9') {
173 x_key = key_pad_map[x_key - '0'];
175 if (x_key == '.') {
176 x_key = KEY_DC;
179 if ((x_state & SHIFT_PRESSED) && (x_state & CONTROL_PRESSED)) {
180 switch (x_key) {
181 case KEY_PPAGE:
182 command = CK_Beginning_Of_Text_Highlight;
183 goto fin;
184 case KEY_NPAGE:
185 command = CK_End_Of_Text_Highlight;
186 goto fin;
187 case KEY_LEFT:
188 command = CK_Word_Left_Highlight;
189 goto fin;
190 case KEY_RIGHT:
191 command = CK_Word_Right_Highlight;
192 goto fin;
195 if ((x_state & SHIFT_PRESSED) && !(x_state & CONTROL_PRESSED)) {
196 switch (x_key) {
197 case KEY_PPAGE:
198 command = CK_Page_Up_Highlight;
199 goto fin;
200 case KEY_NPAGE:
201 command = CK_Page_Down_Highlight;
202 goto fin;
203 case KEY_LEFT:
204 command = CK_Left_Highlight;
205 goto fin;
206 case KEY_RIGHT:
207 command = CK_Right_Highlight;
208 goto fin;
209 case KEY_UP:
210 command = CK_Up_Highlight;
211 goto fin;
212 case KEY_DOWN:
213 command = CK_Down_Highlight;
214 goto fin;
215 case KEY_HOME:
216 command = CK_Home_Highlight;
217 goto fin;
218 case KEY_END:
219 command = CK_End_Highlight;
220 goto fin;
221 case KEY_IC:
222 command = CK_XPaste;
223 goto fin;
224 case KEY_DC:
225 command = CK_XCut;
226 goto fin;
229 /* things that need a control key */
230 if (x_state & CONTROL_PRESSED) {
231 switch (x_key) {
232 case KEY_F (2):
233 command = CK_Save_As;
234 goto fin;
235 case KEY_F (4):
236 command = CK_Replace_Again;
237 goto fin;
238 case KEY_F (7):
239 command = CK_Find_Again;
240 goto fin;
241 case KEY_BACKSPACE:
242 command = CK_Undo;
243 goto fin;
244 case KEY_PPAGE:
245 command = CK_Beginning_Of_Text;
246 goto fin;
247 case KEY_NPAGE:
248 command = CK_End_Of_Text;
249 goto fin;
250 case KEY_UP:
251 command = CK_Scroll_Up;
252 goto fin;
253 case KEY_DOWN:
254 command = CK_Scroll_Down;
255 goto fin;
256 case KEY_LEFT:
257 command = CK_Word_Left;
258 goto fin;
259 case KEY_RIGHT:
260 command = CK_Word_Right;
261 goto fin;
262 case KEY_IC:
263 command = CK_XStore;
264 goto fin;
265 case KEY_DC:
266 command = CK_Remove;
267 goto fin;
270 /* an ordinary insertable character */
271 if (x_key < 256 && is_printable (x_key)) {
272 char_for_insertion = x_key;
273 goto fin;
275 /* other commands */
276 i = 0;
277 while (key_map[i] != x_key && (key_map[i] || key_map[i + 1]))
278 i += 2;
279 command = key_map[i + 1];
280 if (command)
281 goto fin;
283 /* Function still not found for this key, so try macro's */
284 /* This allows the same macro to be
285 enabled by either eg "ALT('f')" or "XCTRL('f')" or "XCTRL('a'), 'f'" */
287 /* key.h: #define ALT(x) (0x200 | (x)) */
288 if (x_key & ALT (0)) { /* is an alt key ? */
289 command = CK_Macro (x_key - ALT (0));
290 goto fin;
292 /* key.h: #define XCTRL(x) ((x) & 31) */
293 if (x_key < ' ') { /* is a ctrl key ? */
294 command = CK_Macro (x_key);
295 goto fin;
297 fin: