This source file includes following definitions.
- select_cmp_by_fd_set
- select_cmp_by_fd
- add_selects
- check_selects
- try_channels
- create_sequence
- define_sequences
- init_key_x11
- getch_with_delay
- xmouse_get_event
- get_modifier
- push_char
- correct_key_code
- getch_with_timeout
- learn_store_key
- k_dispose
- key_code_comparator_by_name
- key_code_comparator_by_code
- sort_key_conv_tab
- lookup_keyname
- lookup_keycode
- init_key
- init_key_input_fd
- done_key
- add_select_channel
- delete_select_channel
- channels_up
- channels_down
- tty_keyname_to_keycode
- tty_keycode_to_keyname
- define_sequence
- is_idle
- get_key_code
- tty_get_event
- tty_getch
- learn_key
- numeric_keypad_mode
- application_keypad_mode
- enable_bracketed_paste
- disable_bracketed_paste
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 #include <config.h>
37
38 #include <ctype.h>
39 #include <errno.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #ifdef HAVE_SYS_SELECT_H
44 #include <sys/select.h>
45 #else
46 #include <sys/time.h>
47 #include <sys/types.h>
48 #include <unistd.h>
49 #endif
50
51 #include "lib/global.h"
52
53 #include "lib/vfs/vfs.h"
54
55 #include "tty.h"
56 #include "tty-internal.h"
57 #include "mouse.h"
58 #include "key.h"
59
60 #include "lib/widget.h"
61
62 #ifdef HAVE_TEXTMODE_X11_SUPPORT
63 #include "x11conn.h"
64 #endif
65
66 #ifdef __linux__
67 #if defined(__GLIBC__) && (__GLIBC__ < 2)
68 #include <linux/termios.h>
69 #else
70 #include <termios.h>
71 #endif
72 #ifdef HAVE_SYS_IOCTL_H
73 #include <sys/ioctl.h>
74 #endif
75 #endif
76
77 #ifdef __CYGWIN__
78 #include <termios.h>
79 #ifdef HAVE_SYS_IOCTL_H
80 #include <sys/ioctl.h>
81 #endif
82 #endif
83
84 #ifdef __QNXNTO__
85 #include <dlfcn.h>
86 #include <Ph.h>
87 #include <sys/dcmd_chr.h>
88 #endif
89
90
91
92 int mou_auto_repeat = 100;
93 int double_click_speed = 250;
94 gboolean old_esc_mode = TRUE;
95
96 int old_esc_mode_timeout = G_USEC_PER_SEC;
97
98 gboolean bracketed_pasting_in_progress = FALSE;
99
100
101
102
103
104 const key_code_name_t key_name_conv_tab[] = {
105 { ESC_CHAR, "escape", N_ ("Escape"), "Esc" },
106
107
108 { KEY_F (1), "f1", N_ ("Function key 1"), "F1" },
109 { KEY_F (2), "f2", N_ ("Function key 2"), "F2" },
110 { KEY_F (3), "f3", N_ ("Function key 3"), "F3" },
111 { KEY_F (4), "f4", N_ ("Function key 4"), "F4" },
112 { KEY_F (5), "f5", N_ ("Function key 5"), "F5" },
113 { KEY_F (6), "f6", N_ ("Function key 6"), "F6" },
114 { KEY_F (7), "f7", N_ ("Function key 7"), "F7" },
115 { KEY_F (8), "f8", N_ ("Function key 8"), "F8" },
116 { KEY_F (9), "f9", N_ ("Function key 9"), "F9" },
117 { KEY_F (10), "f10", N_ ("Function key 10"), "F10" },
118 { KEY_F (11), "f11", N_ ("Function key 11"), "F11" },
119 { KEY_F (12), "f12", N_ ("Function key 12"), "F12" },
120 { KEY_F (13), "f13", N_ ("Function key 13"), "F13" },
121 { KEY_F (14), "f14", N_ ("Function key 14"), "F14" },
122 { KEY_F (15), "f15", N_ ("Function key 15"), "F15" },
123 { KEY_F (16), "f16", N_ ("Function key 16"), "F16" },
124 { KEY_F (17), "f17", N_ ("Function key 17"), "F17" },
125 { KEY_F (18), "f18", N_ ("Function key 18"), "F18" },
126 { KEY_F (19), "f19", N_ ("Function key 19"), "F19" },
127 { KEY_F (20), "f20", N_ ("Function key 20"), "F20" },
128 { ALT ('\t'), "complete", N_ ("Completion/M-tab"), "Meta-Tab" },
129 { KEY_BTAB, "backtab", N_ ("BackTab/S-tab"), "Shift-Tab" },
130 { KEY_BACKSPACE, "backspace", N_ ("Backspace"), "Backspace" },
131 { KEY_UP, "up", N_ ("Up arrow"), "Up" },
132 { KEY_DOWN, "down", N_ ("Down arrow"), "Down" },
133 { KEY_LEFT, "left", N_ ("Left arrow"), "Left" },
134 { KEY_RIGHT, "right", N_ ("Right arrow"), "Right" },
135 { KEY_IC, "insert", N_ ("Insert"), "Ins" },
136 { KEY_DC, "delete", N_ ("Delete"), "Del" },
137 { KEY_HOME, "home", N_ ("Home"), "Home" },
138 { KEY_END, "end", N_ ("End key"), "End" },
139 { KEY_PPAGE, "pgup", N_ ("Page Up"), "PgUp" },
140 { KEY_NPAGE, "pgdn", N_ ("Page Down"), "PgDn" },
141 { (int) '/', "kpslash", N_ ("/ on keypad"), "/" },
142 { KEY_KP_MULTIPLY, "kpasterisk", N_ ("* on keypad"), "*" },
143 { KEY_KP_SUBTRACT, "kpminus", N_ ("- on keypad"), "-" },
144 { KEY_KP_ADD, "kpplus", N_ ("+ on keypad"), "+" },
145
146
147 { KEY_LEFT, "kpleft", N_ ("Left arrow keypad"), "Left" },
148 { KEY_RIGHT, "kpright", N_ ("Right arrow keypad"), "Right" },
149 { KEY_UP, "kpup", N_ ("Up arrow keypad"), "Up" },
150 { KEY_DOWN, "kpdown", N_ ("Down arrow keypad"), "Down" },
151 { KEY_HOME, "kphome", N_ ("Home on keypad"), "Home" },
152 { KEY_END, "kpend", N_ ("End on keypad"), "End" },
153 { KEY_NPAGE, "kpnpage", N_ ("Page Down keypad"), "PgDn" },
154 { KEY_PPAGE, "kpppage", N_ ("Page Up keypad"), "PgUp" },
155 { KEY_IC, "kpinsert", N_ ("Insert on keypad"), "Ins" },
156 { KEY_DC, "kpdelete", N_ ("Delete on keypad"), "Del" },
157 { (int) '\n', "kpenter", N_ ("Enter on keypad"), "Enter" },
158 { KEY_F (21), "f21", N_ ("Function key 21"), "F21" },
159 { KEY_F (22), "f22", N_ ("Function key 22"), "F22" },
160 { KEY_F (23), "f23", N_ ("Function key 23"), "F23" },
161 { KEY_F (24), "f24", N_ ("Function key 24"), "F24" },
162 { KEY_A1, "a1", N_ ("A1 key"), "A1" },
163 { KEY_C1, "c1", N_ ("C1 key"), "C1" },
164
165
166 { ESC_CHAR, "esc", N_ ("Escape"), "Esc" },
167 { KEY_BACKSPACE, "bs", N_ ("Backspace"), "Bakspace" },
168 { KEY_IC, "ins", N_ ("Insert"), "Ins" },
169 { KEY_DC, "del", N_ ("Delete"), "Del" },
170 { (int) '*', "asterisk", N_ ("Asterisk"), "*" },
171 { (int) '-', "minus", N_ ("Minus"), "-" },
172 { (int) '+', "plus", N_ ("Plus"), "+" },
173 { (int) '.', "dot", N_ ("Dot"), "." },
174 { (int) '<', "lt", N_ ("Less than"), "<" },
175 { (int) '>', "gt", N_ ("Great than"), ">" },
176 { (int) '=', "equal", N_ ("Equal"), "=" },
177 { (int) ',', "comma", N_ ("Comma"), "," },
178 { (int) '\'', "apostrophe", N_ ("Apostrophe"), "\'" },
179 { (int) ':', "colon", N_ ("Colon"), ":" },
180 { (int) ';', "semicolon", N_ ("Semicolon"), ";" },
181 { (int) '!', "exclamation", N_ ("Exclamation mark"), "!" },
182 { (int) '?', "question", N_ ("Question mark"), "?" },
183 { (int) '&', "ampersand", N_ ("Ampersand"), "&" },
184 { (int) '$', "dollar", N_ ("Dollar sign"), "$" },
185 { (int) '"', "quota", N_ ("Quotation mark"), "\"" },
186 { (int) '%', "percent", N_ ("Percent sign"), "%" },
187 { (int) '^', "caret", N_ ("Caret"), "^" },
188 { (int) '~', "tilda", N_ ("Tilda"), "~" },
189 { (int) '`', "prime", N_ ("Prime"), "`" },
190 { (int) '_', "underline", N_ ("Underline"), "_" },
191 { (int) '_', "understrike", N_ ("Understrike"), "_" },
192 { (int) '|', "pipe", N_ ("Pipe"), "|" },
193 { (int) '(', "lparenthesis", N_ ("Left parenthesis"), "(" },
194 { (int) ')', "rparenthesis", N_ ("Right parenthesis"), ")" },
195 { (int) '[', "lbracket", N_ ("Left bracket"), "[" },
196 { (int) ']', "rbracket", N_ ("Right bracket"), "]" },
197 { (int) '{', "lbrace", N_ ("Left brace"), "{" },
198 { (int) '}', "rbrace", N_ ("Right brace"), "}" },
199 { (int) '\n', "enter", N_ ("Enter"), "Enter" },
200 { (int) '\t', "tab", N_ ("Tab key"), "Tab" },
201 { (int) ' ', "space", N_ ("Space key"), "Space" },
202 { (int) '/', "slash", N_ ("Slash key"), "/" },
203 { (int) '\\', "backslash", N_ ("Backslash key"), "\\" },
204 { (int) '#', "number", N_ ("Number sign #"), "#" },
205 { (int) '#', "hash", N_ ("Number sign #"), "#" },
206
207 { (int) '@', "at", N_ ("At sign"), "@" },
208
209
210 { KEY_M_CTRL, "control", N_ ("Ctrl"), "C" },
211 { KEY_M_CTRL, "ctrl", N_ ("Ctrl"), "C" },
212 { KEY_M_ALT, "meta", N_ ("Alt"), "M" },
213 { KEY_M_ALT, "alt", N_ ("Alt"), "M" },
214 { KEY_M_ALT, "ralt", N_ ("Alt"), "M" },
215 { KEY_M_SHIFT, "shift", N_ ("Shift"), "S" },
216
217 { 0, NULL, NULL, NULL },
218 };
219
220
221
222 #define MC_USEC_PER_MSEC 1000
223
224
225 #define SEQ_BUFFER_LEN 33
226
227
228
229
230 typedef enum
231 {
232 SHIFT_PRESSED = (1 << 0),
233 ALTR_PRESSED = (1 << 1),
234 CONTROL_PRESSED = (1 << 2),
235 ALTL_PRESSED = (1 << 3)
236 } mod_pressed_t;
237
238 typedef struct key_def
239 {
240 char ch;
241 int code;
242 struct key_def *next;
243 struct key_def *child;
244 int action;
245
246
247 } key_def;
248
249 typedef struct
250 {
251 int code;
252 const char *seq;
253 int action;
254 } key_define_t;
255
256
257 typedef struct
258 {
259 int fd;
260 select_fn callback;
261 void *info;
262 } select_t;
263
264 typedef enum KeySortType
265 {
266 KEY_NOSORT = 0,
267 KEY_SORTBYNAME,
268 KEY_SORTBYCODE
269 } KeySortType;
270
271 #ifdef __QNXNTO__
272 typedef int (*ph_dv_f) (void *, void *);
273 typedef int (*ph_ov_f) (void *);
274 typedef int (*ph_pqc_f) (unsigned short, PhCursorInfo_t *);
275 #endif
276
277
278
279
280
281 static key_define_t mc_default_keys[] = {
282 { ESC_CHAR, ESC_STR, MCKEY_ESCAPE },
283 { ESC_CHAR, ESC_STR ESC_STR, MCKEY_NOACTION },
284 { MCKEY_BRACKETED_PASTING_START, ESC_STR "[200~", MCKEY_NOACTION },
285 { MCKEY_BRACKETED_PASTING_END, ESC_STR "[201~", MCKEY_NOACTION },
286 { 0, NULL, MCKEY_NOACTION },
287 };
288
289
290 static key_define_t xterm_key_defines[] = {
291 { KEY_F (1), ESC_STR "OP", MCKEY_NOACTION },
292 { KEY_F (2), ESC_STR "OQ", MCKEY_NOACTION },
293 { KEY_F (3), ESC_STR "OR", MCKEY_NOACTION },
294 { KEY_F (4), ESC_STR "OS", MCKEY_NOACTION },
295 { KEY_F (1), ESC_STR "[11~", MCKEY_NOACTION },
296 { KEY_F (2), ESC_STR "[12~", MCKEY_NOACTION },
297 { KEY_F (3), ESC_STR "[13~", MCKEY_NOACTION },
298 { KEY_F (4), ESC_STR "[14~", MCKEY_NOACTION },
299 { KEY_F (5), ESC_STR "[15~", MCKEY_NOACTION },
300 { KEY_F (6), ESC_STR "[17~", MCKEY_NOACTION },
301 { KEY_F (7), ESC_STR "[18~", MCKEY_NOACTION },
302 { KEY_F (8), ESC_STR "[19~", MCKEY_NOACTION },
303 { KEY_F (9), ESC_STR "[20~", MCKEY_NOACTION },
304 { KEY_F (10), ESC_STR "[21~", MCKEY_NOACTION },
305
306
307 { KEY_M_SHIFT | KEY_UP, ESC_STR "O2A", MCKEY_NOACTION },
308 { KEY_M_SHIFT | KEY_DOWN, ESC_STR "O2B", MCKEY_NOACTION },
309 { KEY_M_SHIFT | KEY_RIGHT, ESC_STR "O2C", MCKEY_NOACTION },
310 { KEY_M_SHIFT | KEY_LEFT, ESC_STR "O2D", MCKEY_NOACTION },
311
312
313 { KEY_M_SHIFT | KEY_UP, ESC_STR "[1;2A", MCKEY_NOACTION },
314 { KEY_M_SHIFT | KEY_DOWN, ESC_STR "[1;2B", MCKEY_NOACTION },
315 { KEY_M_SHIFT | KEY_RIGHT, ESC_STR "[1;2C", MCKEY_NOACTION },
316 { KEY_M_SHIFT | KEY_LEFT, ESC_STR "[1;2D", MCKEY_NOACTION },
317
318
319 { KEY_M_CTRL | KEY_PPAGE, ESC_STR "[5;5~", MCKEY_NOACTION },
320 { KEY_M_CTRL | KEY_NPAGE, ESC_STR "[6;5~", MCKEY_NOACTION },
321 { KEY_M_CTRL | KEY_IC, ESC_STR "[2;5~", MCKEY_NOACTION },
322 { KEY_M_CTRL | KEY_DC, ESC_STR "[3;5~", MCKEY_NOACTION },
323 { KEY_M_CTRL | KEY_HOME, ESC_STR "[1;5H", MCKEY_NOACTION },
324 { KEY_M_CTRL | KEY_END, ESC_STR "[1;5F", MCKEY_NOACTION },
325 { KEY_M_SHIFT | KEY_HOME, ESC_STR "[1;2H", MCKEY_NOACTION },
326 { KEY_M_SHIFT | KEY_END, ESC_STR "[1;2F", MCKEY_NOACTION },
327 { KEY_M_CTRL | KEY_UP, ESC_STR "[1;5A", MCKEY_NOACTION },
328 { KEY_M_CTRL | KEY_DOWN, ESC_STR "[1;5B", MCKEY_NOACTION },
329 { KEY_M_CTRL | KEY_RIGHT, ESC_STR "[1;5C", MCKEY_NOACTION },
330 { KEY_M_CTRL | KEY_LEFT, ESC_STR "[1;5D", MCKEY_NOACTION },
331 { KEY_M_SHIFT | KEY_IC, ESC_STR "[2;2~", MCKEY_NOACTION },
332 { KEY_M_SHIFT | KEY_DC, ESC_STR "[3;2~", MCKEY_NOACTION },
333 { KEY_M_SHIFT | KEY_M_CTRL | KEY_UP, ESC_STR "[1;6A", MCKEY_NOACTION },
334 { KEY_M_SHIFT | KEY_M_CTRL | KEY_DOWN, ESC_STR "[1;6B", MCKEY_NOACTION },
335 { KEY_M_SHIFT | KEY_M_CTRL | KEY_RIGHT, ESC_STR "[1;6C", MCKEY_NOACTION },
336 { KEY_M_SHIFT | KEY_M_CTRL | KEY_LEFT, ESC_STR "[1;6D", MCKEY_NOACTION },
337 { KEY_M_SHIFT | '\t', ESC_STR "[Z", MCKEY_NOACTION },
338
339
340 { KEY_M_SHIFT | KEY_M_CTRL | KEY_UP, ESC_STR "[[1;6A", MCKEY_NOACTION },
341 { KEY_M_SHIFT | KEY_M_CTRL | KEY_DOWN, ESC_STR "[[1;6B", MCKEY_NOACTION },
342 { KEY_M_SHIFT | KEY_M_CTRL | KEY_RIGHT, ESC_STR "[[1;6C", MCKEY_NOACTION },
343 { KEY_M_SHIFT | KEY_M_CTRL | KEY_LEFT, ESC_STR "[[1;6D", MCKEY_NOACTION },
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368 { KEY_M_ALT | KEY_UP, ESC_STR "[1;3A", MCKEY_NOACTION },
369 { KEY_M_ALT | KEY_DOWN, ESC_STR "[1;3B", MCKEY_NOACTION },
370 { KEY_M_ALT | KEY_RIGHT, ESC_STR "[1;3C", MCKEY_NOACTION },
371 { KEY_M_ALT | KEY_LEFT, ESC_STR "[1;3D", MCKEY_NOACTION },
372 { KEY_M_ALT | KEY_PPAGE, ESC_STR "[5;3~", MCKEY_NOACTION },
373 { KEY_M_ALT | KEY_NPAGE, ESC_STR "[6;3~", MCKEY_NOACTION },
374 { KEY_M_ALT | KEY_HOME, ESC_STR "[1~", MCKEY_NOACTION },
375 { KEY_M_ALT | KEY_END, ESC_STR "[4~", MCKEY_NOACTION },
376 { KEY_M_CTRL | KEY_M_ALT | KEY_UP, ESC_STR "[1;7A", MCKEY_NOACTION },
377 { KEY_M_CTRL | KEY_M_ALT | KEY_DOWN, ESC_STR "[1;7B", MCKEY_NOACTION },
378 { KEY_M_CTRL | KEY_M_ALT | KEY_RIGHT, ESC_STR "[1;7C", MCKEY_NOACTION },
379 { KEY_M_CTRL | KEY_M_ALT | KEY_LEFT, ESC_STR "[1;7D", MCKEY_NOACTION },
380 { KEY_M_CTRL | KEY_M_ALT | KEY_PPAGE, ESC_STR "[5;7~", MCKEY_NOACTION },
381 { KEY_M_CTRL | KEY_M_ALT | KEY_NPAGE, ESC_STR "[6;7~", MCKEY_NOACTION },
382 { KEY_M_CTRL | KEY_M_ALT | KEY_HOME, ESC_STR "OH", MCKEY_NOACTION },
383 { KEY_M_CTRL | KEY_M_ALT | KEY_END, ESC_STR "OF", MCKEY_NOACTION },
384
385 { KEY_M_SHIFT | KEY_M_ALT | KEY_UP, ESC_STR "[1;4A", MCKEY_NOACTION },
386 { KEY_M_SHIFT | KEY_M_ALT | KEY_DOWN, ESC_STR "[1;4B", MCKEY_NOACTION },
387 { KEY_M_SHIFT | KEY_M_ALT | KEY_RIGHT, ESC_STR "[1;4C", MCKEY_NOACTION },
388 { KEY_M_SHIFT | KEY_M_ALT | KEY_LEFT, ESC_STR "[1;4D", MCKEY_NOACTION },
389
390
391 { KEY_M_SHIFT | KEY_UP, ESC_STR "[a", MCKEY_NOACTION },
392 { KEY_M_SHIFT | KEY_DOWN, ESC_STR "[b", MCKEY_NOACTION },
393 { KEY_M_SHIFT | KEY_RIGHT, ESC_STR "[c", MCKEY_NOACTION },
394 { KEY_M_SHIFT | KEY_LEFT, ESC_STR "[d", MCKEY_NOACTION },
395 { KEY_M_CTRL | KEY_UP, ESC_STR "Oa", MCKEY_NOACTION },
396 { KEY_M_CTRL | KEY_DOWN, ESC_STR "Ob", MCKEY_NOACTION },
397 { KEY_M_CTRL | KEY_RIGHT, ESC_STR "Oc", MCKEY_NOACTION },
398 { KEY_M_CTRL | KEY_LEFT, ESC_STR "Od", MCKEY_NOACTION },
399 { KEY_M_CTRL | KEY_PPAGE, ESC_STR "[5^", MCKEY_NOACTION },
400 { KEY_M_CTRL | KEY_NPAGE, ESC_STR "[6^", MCKEY_NOACTION },
401 { KEY_M_CTRL | KEY_HOME, ESC_STR "[7^", MCKEY_NOACTION },
402 { KEY_M_CTRL | KEY_END, ESC_STR "[8^", MCKEY_NOACTION },
403 { KEY_M_SHIFT | KEY_HOME, ESC_STR "[7$", MCKEY_NOACTION },
404 { KEY_M_SHIFT | KEY_END, ESC_STR "[8$", MCKEY_NOACTION },
405 { KEY_M_CTRL | KEY_IC, ESC_STR "[2^", MCKEY_NOACTION },
406 { KEY_M_CTRL | KEY_DC, ESC_STR "[3^", MCKEY_NOACTION },
407 { KEY_M_SHIFT | KEY_DC, ESC_STR "[3$", MCKEY_NOACTION },
408
409
410 { KEY_M_SHIFT | KEY_HOME, ESC_STR "O2H", MCKEY_NOACTION },
411 { KEY_M_SHIFT | KEY_END, ESC_STR "O2F", MCKEY_NOACTION },
412
413
414 { KEY_M_SHIFT | KEY_UP, ESC_STR "[2A", MCKEY_NOACTION },
415 { KEY_M_SHIFT | KEY_DOWN, ESC_STR "[2B", MCKEY_NOACTION },
416 { KEY_M_SHIFT | KEY_RIGHT, ESC_STR "[2C", MCKEY_NOACTION },
417 { KEY_M_SHIFT | KEY_LEFT, ESC_STR "[2D", MCKEY_NOACTION },
418 { KEY_M_CTRL | KEY_UP, ESC_STR "[5A", MCKEY_NOACTION },
419 { KEY_M_CTRL | KEY_DOWN, ESC_STR "[5B", MCKEY_NOACTION },
420 { KEY_M_CTRL | KEY_RIGHT, ESC_STR "[5C", MCKEY_NOACTION },
421 { KEY_M_CTRL | KEY_LEFT, ESC_STR "[5D", MCKEY_NOACTION },
422 { KEY_M_SHIFT | KEY_M_CTRL | KEY_UP, ESC_STR "[6A", MCKEY_NOACTION },
423 { KEY_M_SHIFT | KEY_M_CTRL | KEY_DOWN, ESC_STR "[6B", MCKEY_NOACTION },
424 { KEY_M_SHIFT | KEY_M_CTRL | KEY_RIGHT, ESC_STR "[6C", MCKEY_NOACTION },
425 { KEY_M_SHIFT | KEY_M_CTRL | KEY_LEFT, ESC_STR "[6D", MCKEY_NOACTION },
426
427
428 { KEY_M_CTRL | KEY_UP, ESC_STR "O5A", MCKEY_NOACTION },
429 { KEY_M_CTRL | KEY_DOWN, ESC_STR "O5B", MCKEY_NOACTION },
430 { KEY_M_CTRL | KEY_RIGHT, ESC_STR "O5C", MCKEY_NOACTION },
431 { KEY_M_CTRL | KEY_LEFT, ESC_STR "O5D", MCKEY_NOACTION },
432 { KEY_M_SHIFT | KEY_M_CTRL | KEY_UP, ESC_STR "O6A", MCKEY_NOACTION },
433 { KEY_M_SHIFT | KEY_M_CTRL | KEY_DOWN, ESC_STR "O6B", MCKEY_NOACTION },
434 { KEY_M_SHIFT | KEY_M_CTRL | KEY_RIGHT, ESC_STR "O6C", MCKEY_NOACTION },
435 { KEY_M_SHIFT | KEY_M_CTRL | KEY_LEFT, ESC_STR "O6D", MCKEY_NOACTION },
436
437
438 { KEY_M_SHIFT | KEY_PPAGE, ESC_STR "[5;2~", MCKEY_NOACTION },
439 { KEY_M_SHIFT | KEY_NPAGE, ESC_STR "[6;2~", MCKEY_NOACTION },
440
441
442 { KEY_M_SHIFT | KEY_PPAGE, ESC_STR "[[5;53~", MCKEY_NOACTION },
443 { KEY_M_SHIFT | KEY_NPAGE, ESC_STR "[[6;53~", MCKEY_NOACTION },
444
445
446 { KEY_IC, ESC_STR "Op", MCKEY_NOACTION },
447 { KEY_DC, ESC_STR "On", MCKEY_NOACTION },
448 { '/', ESC_STR "Oo", MCKEY_NOACTION },
449 { '\n', ESC_STR "OM", MCKEY_NOACTION },
450
451 { 0, NULL, MCKEY_NOACTION },
452 };
453
454
455
456 static key_define_t qansi_key_defines[] = {
457
458 { KEY_M_CTRL | KEY_NPAGE, ESC_STR "[u", MCKEY_NOACTION },
459 { KEY_M_CTRL | KEY_PPAGE, ESC_STR "[v", MCKEY_NOACTION },
460 { KEY_M_CTRL | KEY_HOME, ESC_STR "[h", MCKEY_NOACTION },
461 { KEY_M_CTRL | KEY_END, ESC_STR "[y", MCKEY_NOACTION },
462 { KEY_M_CTRL | KEY_IC, ESC_STR "[`", MCKEY_NOACTION },
463 { KEY_M_CTRL | KEY_DC, ESC_STR "[p", MCKEY_NOACTION },
464 { KEY_M_CTRL | KEY_LEFT, ESC_STR "[d", MCKEY_NOACTION },
465 { KEY_M_CTRL | KEY_RIGHT, ESC_STR "[c", MCKEY_NOACTION },
466 { KEY_M_CTRL | KEY_DOWN, ESC_STR "[b", MCKEY_NOACTION },
467 { KEY_M_CTRL | KEY_UP, ESC_STR "[a", MCKEY_NOACTION },
468 { KEY_M_CTRL | KEY_KP_ADD, ESC_STR "[s", MCKEY_NOACTION },
469 { KEY_M_CTRL | KEY_KP_SUBTRACT, ESC_STR "[t", MCKEY_NOACTION },
470 { KEY_M_CTRL | '\t', ESC_STR "[z", MCKEY_NOACTION },
471 { KEY_M_SHIFT | '\t', ESC_STR "[Z", MCKEY_NOACTION },
472 { KEY_M_CTRL | KEY_F (1), ESC_STR "[1~", MCKEY_NOACTION },
473 { KEY_M_CTRL | KEY_F (2), ESC_STR "[2~", MCKEY_NOACTION },
474 { KEY_M_CTRL | KEY_F (3), ESC_STR "[3~", MCKEY_NOACTION },
475 { KEY_M_CTRL | KEY_F (4), ESC_STR "[4~", MCKEY_NOACTION },
476 { KEY_M_CTRL | KEY_F (5), ESC_STR "[5~", MCKEY_NOACTION },
477 { KEY_M_CTRL | KEY_F (6), ESC_STR "[6~", MCKEY_NOACTION },
478 { KEY_M_CTRL | KEY_F (7), ESC_STR "[7~", MCKEY_NOACTION },
479 { KEY_M_CTRL | KEY_F (8), ESC_STR "[8~", MCKEY_NOACTION },
480 { KEY_M_CTRL | KEY_F (9), ESC_STR "[9~", MCKEY_NOACTION },
481 { KEY_M_CTRL | KEY_F (10), ESC_STR "[10~", MCKEY_NOACTION },
482 { KEY_M_CTRL | KEY_F (11), ESC_STR "[11~", MCKEY_NOACTION },
483 { KEY_M_CTRL | KEY_F (12), ESC_STR "[12~", MCKEY_NOACTION },
484 { KEY_M_ALT | KEY_F (1), ESC_STR "[17~", MCKEY_NOACTION },
485 { KEY_M_ALT | KEY_F (2), ESC_STR "[18~", MCKEY_NOACTION },
486 { KEY_M_ALT | KEY_F (3), ESC_STR "[19~", MCKEY_NOACTION },
487 { KEY_M_ALT | KEY_F (4), ESC_STR "[20~", MCKEY_NOACTION },
488 { KEY_M_ALT | KEY_F (5), ESC_STR "[21~", MCKEY_NOACTION },
489 { KEY_M_ALT | KEY_F (6), ESC_STR "[22~", MCKEY_NOACTION },
490 { KEY_M_ALT | KEY_F (7), ESC_STR "[23~", MCKEY_NOACTION },
491 { KEY_M_ALT | KEY_F (8), ESC_STR "[24~", MCKEY_NOACTION },
492 { KEY_M_ALT | KEY_F (9), ESC_STR "[25~", MCKEY_NOACTION },
493 { KEY_M_ALT | KEY_F (10), ESC_STR "[26~", MCKEY_NOACTION },
494 { KEY_M_ALT | KEY_F (11), ESC_STR "[27~", MCKEY_NOACTION },
495 { KEY_M_ALT | KEY_F (12), ESC_STR "[28~", MCKEY_NOACTION },
496 { KEY_M_ALT | 'a', ESC_STR "Na", MCKEY_NOACTION },
497 { KEY_M_ALT | 'b', ESC_STR "Nb", MCKEY_NOACTION },
498 { KEY_M_ALT | 'c', ESC_STR "Nc", MCKEY_NOACTION },
499 { KEY_M_ALT | 'd', ESC_STR "Nd", MCKEY_NOACTION },
500 { KEY_M_ALT | 'e', ESC_STR "Ne", MCKEY_NOACTION },
501 { KEY_M_ALT | 'f', ESC_STR "Nf", MCKEY_NOACTION },
502 { KEY_M_ALT | 'g', ESC_STR "Ng", MCKEY_NOACTION },
503 { KEY_M_ALT | 'h', ESC_STR "Nh", MCKEY_NOACTION },
504 { KEY_M_ALT | 'i', ESC_STR "Ni", MCKEY_NOACTION },
505 { KEY_M_ALT | 'j', ESC_STR "Nj", MCKEY_NOACTION },
506 { KEY_M_ALT | 'k', ESC_STR "Nk", MCKEY_NOACTION },
507 { KEY_M_ALT | 'l', ESC_STR "Nl", MCKEY_NOACTION },
508 { KEY_M_ALT | 'm', ESC_STR "Nm", MCKEY_NOACTION },
509 { KEY_M_ALT | 'n', ESC_STR "Nn", MCKEY_NOACTION },
510 { KEY_M_ALT | 'o', ESC_STR "No", MCKEY_NOACTION },
511 { KEY_M_ALT | 'p', ESC_STR "Np", MCKEY_NOACTION },
512 { KEY_M_ALT | 'q', ESC_STR "Nq", MCKEY_NOACTION },
513 { KEY_M_ALT | 'r', ESC_STR "Nr", MCKEY_NOACTION },
514 { KEY_M_ALT | 's', ESC_STR "Ns", MCKEY_NOACTION },
515 { KEY_M_ALT | 't', ESC_STR "Nt", MCKEY_NOACTION },
516 { KEY_M_ALT | 'u', ESC_STR "Nu", MCKEY_NOACTION },
517 { KEY_M_ALT | 'v', ESC_STR "Nv", MCKEY_NOACTION },
518 { KEY_M_ALT | 'w', ESC_STR "Nw", MCKEY_NOACTION },
519 { KEY_M_ALT | 'x', ESC_STR "Nx", MCKEY_NOACTION },
520 { KEY_M_ALT | 'y', ESC_STR "Ny", MCKEY_NOACTION },
521 { KEY_M_ALT | 'z', ESC_STR "Nz", MCKEY_NOACTION },
522 { KEY_KP_SUBTRACT, ESC_STR "[S", MCKEY_NOACTION },
523 { KEY_KP_ADD, ESC_STR "[T", MCKEY_NOACTION },
524 { 0, NULL, MCKEY_NOACTION },
525 };
526
527
528 static key_def *keys = NULL;
529
530 static int input_fd;
531 static int disabled_channels = 0;
532
533 static GSList *select_list = NULL;
534
535 static int seq_buffer[SEQ_BUFFER_LEN];
536 static int *seq_append = NULL;
537
538 static int *pending_keys = NULL;
539
540 #ifdef __QNXNTO__
541 ph_dv_f ph_attach;
542 ph_ov_f ph_input_group;
543 ph_pqc_f ph_query_cursor;
544 #endif
545
546 #ifdef HAVE_TEXTMODE_X11_SUPPORT
547 static Display *x11_display;
548 static Window x11_window;
549 #endif
550
551 static KeySortType has_been_sorted = KEY_NOSORT;
552
553 static const size_t key_conv_tab_size = G_N_ELEMENTS (key_name_conv_tab) - 1;
554
555 static const key_code_name_t *key_conv_tab_sorted[G_N_ELEMENTS (key_name_conv_tab) - 1];
556
557
558
559
560
561 static int
562 select_cmp_by_fd_set (gconstpointer a, gconstpointer b)
563 {
564 const select_t *s = (const select_t *) a;
565 const fd_set *f = (const fd_set *) b;
566
567 return (FD_ISSET (s->fd, f) ? 0 : 1);
568 }
569
570
571
572 static int
573 select_cmp_by_fd (gconstpointer a, gconstpointer b)
574 {
575 const select_t *s = (const select_t *) a;
576 const int fd = GPOINTER_TO_INT (b);
577
578 return (s->fd == fd ? 0 : 1);
579 }
580
581
582
583 static int
584 add_selects (fd_set *select_set)
585 {
586 int top_fd = 0;
587
588 if (disabled_channels == 0)
589 {
590 GSList *s;
591
592 for (s = select_list; s != NULL; s = g_slist_next (s))
593 {
594 select_t *p = (select_t *) s->data;
595
596 FD_SET (p->fd, select_set);
597 if (p->fd > top_fd)
598 top_fd = p->fd;
599 }
600 }
601
602 return top_fd;
603 }
604
605
606
607 static void
608 check_selects (fd_set *select_set)
609 {
610 while (disabled_channels == 0)
611 {
612 GSList *s;
613 select_t *p;
614
615 s = g_slist_find_custom (select_list, select_set, select_cmp_by_fd_set);
616 if (s == NULL)
617 break;
618
619 p = (select_t *) s->data;
620 FD_CLR (p->fd, select_set);
621 p->callback (p->fd, p->info);
622 }
623 }
624
625
626
627
628 static void
629 try_channels (gboolean set_timeout)
630 {
631 struct timeval time_out;
632 static fd_set select_set;
633
634 while (TRUE)
635 {
636 struct timeval *timeptr = NULL;
637 int maxfdp, v;
638
639 FD_ZERO (&select_set);
640 FD_SET (input_fd, &select_set);
641 maxfdp = MAX (add_selects (&select_set), input_fd);
642
643 if (set_timeout)
644 {
645 time_out.tv_sec = 0;
646 time_out.tv_usec = 100 * MC_USEC_PER_MSEC;
647 timeptr = &time_out;
648 }
649
650 v = select (maxfdp + 1, &select_set, NULL, NULL, timeptr);
651 if (v > 0)
652 {
653 check_selects (&select_set);
654 if (FD_ISSET (input_fd, &select_set))
655 break;
656 }
657 }
658 }
659
660
661
662 static key_def *
663 create_sequence (const char *seq, int code, int action)
664 {
665 key_def *base, *attach;
666
667 for (base = attach = NULL; *seq != '\0'; seq++)
668 {
669 key_def *p;
670
671 p = g_new (key_def, 1);
672 if (base == NULL)
673 base = p;
674 if (attach != NULL)
675 attach->child = p;
676
677 p->ch = *seq;
678 p->code = code;
679 p->child = NULL;
680 p->next = NULL;
681 p->action = seq[1] == '\0' ? action : MCKEY_NOACTION;
682 attach = p;
683 }
684 return base;
685 }
686
687
688
689 static void
690 define_sequences (const key_define_t *kd)
691 {
692 int i;
693
694 for (i = 0; kd[i].code != 0; i++)
695 define_sequence (kd[i].code, kd[i].seq, kd[i].action);
696 }
697
698
699
700 #ifdef HAVE_TEXTMODE_X11_SUPPORT
701 static void
702 init_key_x11 (void)
703 {
704 if (getenv ("DISPLAY") != NULL && !mc_global.tty.disable_x11)
705 {
706 x11_display = mc_XOpenDisplay (0);
707
708 if (x11_display != NULL)
709 x11_window = DefaultRootWindow (x11_display);
710 }
711 }
712 #endif
713
714
715
716
717 static int
718 getch_with_delay (void)
719 {
720 int c;
721
722
723
724 while (TRUE)
725 {
726 if (pending_keys == NULL)
727 try_channels (FALSE);
728
729
730 c = get_key_code (0);
731 if (c != -1)
732 break;
733
734
735 try_channels (TRUE);
736 }
737
738
739 return c;
740 }
741
742
743
744 static void
745 xmouse_get_event (Gpm_Event *ev, gboolean extended)
746 {
747 static gint64 tv1 = 0;
748 static int clicks = 0;
749 static int last_btn = 0;
750 int btn;
751
752
753
754 if (!extended)
755 {
756
757
758 btn = tty_lowlevel_getch () - 32;
759
760
761 ev->x = tty_lowlevel_getch () - 32;
762 ev->y = tty_lowlevel_getch () - 32;
763 }
764 else
765 {
766
767
768
769
770
771
772 char c;
773
774 btn = ev->x = ev->y = 0;
775 ev->type = 0;
776
777 while ((c = tty_lowlevel_getch ()) != ';')
778 {
779 if (c < '0' || c > '9')
780 return;
781 btn = 10 * btn + (c - '0');
782 }
783 while ((c = tty_lowlevel_getch ()) != ';')
784 {
785 if (c < '0' || c > '9')
786 return;
787 ev->x = 10 * ev->x + (c - '0');
788 }
789 while ((c = tty_lowlevel_getch ()) != 'M' && c != 'm')
790 {
791 if (c < '0' || c > '9')
792 return;
793 ev->y = 10 * ev->y + (c - '0');
794 }
795
796
797
798
799 if (c == 'm')
800 btn = 3;
801 }
802
803
804
805
806 if (btn == 3)
807 {
808 if (last_btn != 0)
809 {
810 if ((last_btn & (GPM_B_UP | GPM_B_DOWN)) != 0)
811 {
812
813
814
815 ev->type = 0;
816 tv1 = 0;
817 }
818 else
819 {
820 ev->type = GPM_UP | (GPM_SINGLE << clicks);
821 }
822 ev->buttons = 0;
823 last_btn = 0;
824 }
825 else
826 {
827
828 ev->type = 0;
829 }
830 }
831 else
832 {
833 gint64 tv2;
834
835 tv2 = g_get_monotonic_time ();
836 if (tv1 != 0 && tv2 - tv1 < (gint64) double_click_speed * MC_USEC_PER_MSEC)
837 {
838 clicks++;
839 clicks %= 3;
840 }
841 else
842 clicks = 0;
843
844 if (btn >= 32 && btn <= 34)
845 {
846 btn -= 32;
847 ev->type = GPM_DRAG;
848 }
849 else
850 {
851 ev->type = GPM_DOWN;
852 tv1 = g_get_monotonic_time ();
853 }
854
855 switch (btn)
856 {
857 case 0:
858 ev->buttons = GPM_B_LEFT;
859 break;
860 case 1:
861 ev->buttons = GPM_B_MIDDLE;
862 break;
863 case 2:
864 ev->buttons = GPM_B_RIGHT;
865 break;
866 case 64:
867 ev->buttons = GPM_B_UP;
868 clicks = 0;
869 break;
870 case 65:
871 ev->buttons = GPM_B_DOWN;
872 clicks = 0;
873 break;
874 default:
875
876 ev->type = 0;
877 ev->buttons = 0;
878 break;
879 }
880 ev->type |= (GPM_SINGLE << clicks);
881 last_btn = ev->buttons;
882 }
883 }
884
885
886
887
888
889
890
891
892
893
894 static int
895 get_modifier (void)
896 {
897 int result = 0;
898 #ifdef __QNXNTO__
899 static int in_photon = 0;
900 static int ph_ig = 0;
901 #endif
902
903 #ifdef HAVE_TEXTMODE_X11_SUPPORT
904 if (x11_window != 0)
905 {
906 Window root, child;
907 int root_x, root_y;
908 int win_x, win_y;
909 unsigned int mask;
910
911 mc_XQueryPointer (x11_display, x11_window, &root, &child, &root_x, &root_y, &win_x, &win_y,
912 &mask);
913
914 if ((mask & ShiftMask) != 0)
915 result |= KEY_M_SHIFT;
916 if ((mask & ControlMask) != 0)
917 result |= KEY_M_CTRL;
918 return result;
919 }
920 #endif
921
922 #ifdef __QNXNTO__
923 if (in_photon == 0)
924 {
925
926 in_photon = -1;
927
928 if (getenv ("PHOTON2_PATH") != NULL)
929 {
930
931 void *ph_handle;
932
933 ph_handle = dlopen ("/usr/lib/libph.so", RTLD_NOW);
934 if (ph_handle != NULL)
935 {
936 ph_attach = (ph_dv_f) dlsym (ph_handle, "PhAttach");
937 ph_input_group = (ph_ov_f) dlsym (ph_handle, "PhInputGroup");
938 ph_query_cursor = (ph_pqc_f) dlsym (ph_handle, "PhQueryCursor");
939 if ((ph_attach != NULL) && (ph_input_group != NULL) && (ph_query_cursor != NULL)
940 && (*ph_attach) (0, 0) != NULL)
941 {
942
943 ph_ig = (*ph_input_group) (0);
944 in_photon = 1;
945 }
946 }
947 }
948 }
949
950 if (in_photon == -1)
951 {
952 int mod_status;
953 int shift_ext_status;
954
955 if (devctl (fileno (stdin), DCMD_CHR_LINESTATUS, &mod_status, sizeof (mod_status), NULL)
956 == -1)
957 return 0;
958
959 shift_ext_status = mod_status & 0xffffff00UL;
960 mod_status &= 0x7f;
961 if ((mod_status & _LINESTATUS_CON_ALT) != 0)
962 result |= KEY_M_ALT;
963 if ((mod_status & _LINESTATUS_CON_CTRL) != 0)
964 result |= KEY_M_CTRL;
965 if ((mod_status & _LINESTATUS_CON_SHIFT) != 0 || (shift_ext_status & 0x00000800UL) != 0)
966 result |= KEY_M_SHIFT;
967 }
968 else
969 {
970 PhCursorInfo_t cursor_info;
971
972 (*ph_query_cursor) (ph_ig, &cursor_info);
973 if ((cursor_info.key_mods & 0x04) != 0)
974 result |= KEY_M_ALT;
975 if ((cursor_info.key_mods & 0x02) != 0)
976 result |= KEY_M_CTRL;
977 if ((cursor_info.key_mods & 0x01) != 0)
978 result |= KEY_M_SHIFT;
979 }
980 #endif
981
982 #if defined __linux__ || (defined __CYGWIN__ && defined TIOCLINUX)
983 {
984 unsigned char modifiers = 6;
985
986 if (ioctl (0, TIOCLINUX, &modifiers) < 0)
987 return 0;
988
989
990 if ((modifiers & SHIFT_PRESSED) != 0)
991 result |= KEY_M_SHIFT;
992 if ((modifiers & (ALTL_PRESSED | ALTR_PRESSED)) != 0)
993 result |= KEY_M_ALT;
994 if ((modifiers & CONTROL_PRESSED) != 0)
995 result |= KEY_M_CTRL;
996 }
997 #endif
998
999 return result;
1000 }
1001
1002
1003
1004 static gboolean
1005 push_char (int c)
1006 {
1007 gboolean ret = FALSE;
1008
1009 if (seq_append == NULL)
1010 seq_append = seq_buffer;
1011
1012 if (seq_append != &(seq_buffer[SEQ_BUFFER_LEN - 2]))
1013 {
1014 *(seq_append++) = c;
1015 *seq_append = '\0';
1016 ret = TRUE;
1017 }
1018
1019 return ret;
1020 }
1021
1022
1023
1024
1025 static int
1026 correct_key_code (int code)
1027 {
1028 unsigned int c = code & ~KEY_M_MASK;
1029 unsigned int mod = code & KEY_M_MASK;
1030 #ifdef __QNXNTO__
1031 unsigned int qmod;
1032
1033 #endif
1034
1035
1036
1037
1038
1039 if (c < 32 || c >= 256)
1040 mod |= get_modifier ();
1041
1042
1043 if (c == '\r')
1044 c = '\n';
1045
1046
1047 if (c == KEY_SCANCEL)
1048 c = '\t';
1049
1050
1051 if (c == KEY_BTAB)
1052 {
1053 c = '\t';
1054 mod = KEY_M_SHIFT;
1055 }
1056
1057
1058 if (c == KEY_F (0))
1059 c = KEY_F (10);
1060
1061
1062
1063
1064
1065
1066
1067 if (c == '\b')
1068 {
1069
1070 c = KEY_BACKSPACE;
1071 mod &= ~KEY_M_CTRL;
1072 }
1073 else if (c < 32 && c != ESC_CHAR && c != '\t' && c != '\n')
1074 mod |= KEY_M_CTRL;
1075
1076 #ifdef __QNXNTO__
1077 qmod = get_modifier ();
1078
1079 if (c == 127 && mod == 0)
1080 {
1081
1082 mod |= get_modifier ();
1083 c = KEY_BACKSPACE;
1084 }
1085
1086 if (c == '0' && mod == 0 && (qmod & KEY_M_SHIFT) == KEY_M_SHIFT)
1087 {
1088
1089 mod = KEY_M_SHIFT;
1090 c = KEY_IC;
1091 }
1092
1093 if (c == '.' && mod == 0 && (qmod & KEY_M_SHIFT) == KEY_M_SHIFT)
1094 {
1095
1096 mod = KEY_M_SHIFT;
1097 c = KEY_DC;
1098 }
1099 #endif
1100
1101
1102 if (c == 0177)
1103 c = KEY_BACKSPACE;
1104
1105 #if 0
1106
1107 if (c == 'd' & 31)
1108 {
1109 c = KEY_DC;
1110 mod &= ~KEY_M_CTRL;
1111 }
1112
1113
1114 if (c == 'h' & 31)
1115 {
1116 c = KEY_BACKSPACE;
1117 mod &= ~KEY_M_CTRL;
1118 }
1119 #endif
1120
1121
1122 if (c == KEY_BACKSPACE && (mod & KEY_M_SHIFT) != 0)
1123 mod &= ~KEY_M_SHIFT;
1124
1125
1126 if (c >= KEY_F (1) && c <= KEY_F (10) && (mod & KEY_M_SHIFT) != 0)
1127 c += 10;
1128
1129
1130 if (c >= KEY_F (1) && c <= KEY_F (20))
1131 mod &= ~KEY_M_SHIFT;
1132
1133 if (!mc_global.tty.alternate_plus_minus)
1134 switch (c)
1135 {
1136 case KEY_KP_ADD:
1137 c = '+';
1138 break;
1139 case KEY_KP_SUBTRACT:
1140 c = '-';
1141 break;
1142 case KEY_KP_MULTIPLY:
1143 c = '*';
1144 break;
1145 default:
1146 break;
1147 }
1148
1149 return (mod | c);
1150 }
1151
1152
1153
1154 static int
1155 getch_with_timeout (unsigned int delay_us)
1156 {
1157 fd_set Read_FD_Set;
1158 int c;
1159 struct timeval time_out;
1160
1161 time_out.tv_sec = delay_us / G_USEC_PER_SEC;
1162 time_out.tv_usec = delay_us % G_USEC_PER_SEC;
1163 tty_nodelay (TRUE);
1164 FD_ZERO (&Read_FD_Set);
1165 FD_SET (input_fd, &Read_FD_Set);
1166 select (input_fd + 1, &Read_FD_Set, NULL, NULL, &time_out);
1167 c = tty_lowlevel_getch ();
1168 tty_nodelay (FALSE);
1169 return c;
1170 }
1171
1172
1173
1174 static void
1175 learn_store_key (GString *buffer, int c)
1176 {
1177 if (c == ESC_CHAR)
1178 g_string_append (buffer, "\\e");
1179 else if (c < ' ')
1180 {
1181 g_string_append_c (buffer, '^');
1182 g_string_append_c (buffer, c + 'a' - 1);
1183 }
1184 else if (c == '^')
1185 g_string_append (buffer, "^^");
1186 else
1187 g_string_append_c (buffer, (char) c);
1188 }
1189
1190
1191
1192 static void
1193 k_dispose (key_def *k)
1194 {
1195 if (k != NULL)
1196 {
1197 k_dispose (k->child);
1198 k_dispose (k->next);
1199 g_free (k);
1200 }
1201 }
1202
1203
1204
1205 static int
1206 key_code_comparator_by_name (const void *p1, const void *p2)
1207 {
1208 const key_code_name_t *n1 = *(const key_code_name_t *const *) p1;
1209 const key_code_name_t *n2 = *(const key_code_name_t *const *) p2;
1210
1211 return g_ascii_strcasecmp (n1->name, n2->name);
1212 }
1213
1214
1215
1216 static int
1217 key_code_comparator_by_code (const void *p1, const void *p2)
1218 {
1219 const key_code_name_t *n1 = *(const key_code_name_t *const *) p1;
1220 const key_code_name_t *n2 = *(const key_code_name_t *const *) p2;
1221
1222 return n1->code - n2->code;
1223 }
1224
1225
1226
1227 static inline void
1228 sort_key_conv_tab (enum KeySortType type_sort)
1229 {
1230 if (has_been_sorted != type_sort)
1231 {
1232 size_t i;
1233
1234 for (i = 0; i < key_conv_tab_size; i++)
1235 key_conv_tab_sorted[i] = &key_name_conv_tab[i];
1236
1237 if (type_sort == KEY_SORTBYNAME)
1238 qsort (key_conv_tab_sorted, key_conv_tab_size, sizeof (key_conv_tab_sorted[0]),
1239 &key_code_comparator_by_name);
1240 else if (type_sort == KEY_SORTBYCODE)
1241 qsort (key_conv_tab_sorted, key_conv_tab_size, sizeof (key_conv_tab_sorted[0]),
1242 &key_code_comparator_by_code);
1243
1244 has_been_sorted = type_sort;
1245 }
1246 }
1247
1248
1249
1250 static int
1251 lookup_keyname (const char *name, int *idx)
1252 {
1253 if (name[0] != '\0')
1254 {
1255 const key_code_name_t key = { 0, name, NULL, NULL };
1256 const key_code_name_t *keyp = &key;
1257 const key_code_name_t **res;
1258
1259 if (name[1] == '\0')
1260 {
1261 *idx = -1;
1262 return (int) name[0];
1263 }
1264
1265 sort_key_conv_tab (KEY_SORTBYNAME);
1266
1267 res = bsearch (&keyp, key_conv_tab_sorted, key_conv_tab_size,
1268 sizeof (key_conv_tab_sorted[0]), key_code_comparator_by_name);
1269
1270 if (res != NULL)
1271 {
1272 *idx = (int) (res - key_conv_tab_sorted);
1273 return (*res)->code;
1274 }
1275 }
1276
1277 *idx = -1;
1278 return 0;
1279 }
1280
1281
1282
1283 static gboolean
1284 lookup_keycode (const int code, int *idx)
1285 {
1286 if (code != 0)
1287 {
1288 const key_code_name_t key = { code, NULL, NULL, NULL };
1289 const key_code_name_t *keyp = &key;
1290 const key_code_name_t **res;
1291
1292 sort_key_conv_tab (KEY_SORTBYCODE);
1293
1294 res = bsearch (&keyp, key_conv_tab_sorted, key_conv_tab_size,
1295 sizeof (key_conv_tab_sorted[0]), key_code_comparator_by_code);
1296
1297 if (res != NULL)
1298 {
1299 *idx = (int) (res - key_conv_tab_sorted);
1300 return TRUE;
1301 }
1302 }
1303
1304 *idx = -1;
1305 return FALSE;
1306 }
1307
1308
1309
1310
1311
1312
1313
1314 void
1315 init_key (void)
1316 {
1317 const char *term;
1318
1319 term = getenv ("TERM");
1320
1321
1322
1323 define_sequences (mc_default_keys);
1324
1325
1326 if (mc_global.tty.xterm_flag
1327 || (term != NULL
1328 && (strncmp (term, "iris-ansi", 9) == 0 || strncmp (term, "xterm", 5) == 0
1329 || strncmp (term, "rxvt", 4) == 0 || strncmp (term, "screen", 6) == 0)))
1330 define_sequences (xterm_key_defines);
1331
1332
1333 load_xtra_key_defines ();
1334
1335 #ifdef HAVE_TEXTMODE_X11_SUPPORT
1336 init_key_x11 ();
1337 #endif
1338
1339
1340
1341 if (term != NULL && (strncmp (term, "qansi-m", 7) == 0))
1342 define_sequences (qansi_key_defines);
1343 }
1344
1345
1346
1347
1348
1349
1350 void
1351 init_key_input_fd (void)
1352 {
1353 #ifdef HAVE_SLANG
1354 input_fd = SLang_TT_Read_FD;
1355 #endif
1356 }
1357
1358
1359
1360 void
1361 done_key (void)
1362 {
1363 k_dispose (keys);
1364 g_slist_free_full (select_list, g_free);
1365
1366 #ifdef HAVE_TEXTMODE_X11_SUPPORT
1367 if (x11_display)
1368 mc_XCloseDisplay (x11_display);
1369 #endif
1370 }
1371
1372
1373
1374 void
1375 add_select_channel (int fd, select_fn callback, void *info)
1376 {
1377 select_t *new;
1378
1379 new = g_new (select_t, 1);
1380 new->fd = fd;
1381 new->callback = callback;
1382 new->info = info;
1383
1384 select_list = g_slist_prepend (select_list, new);
1385 }
1386
1387
1388
1389 void
1390 delete_select_channel (int fd)
1391 {
1392 GSList *p;
1393
1394 p = g_slist_find_custom (select_list, GINT_TO_POINTER (fd), select_cmp_by_fd);
1395 if (p != NULL)
1396 select_list = g_slist_delete_link (select_list, p);
1397 }
1398
1399
1400
1401 void
1402 channels_up (void)
1403 {
1404 if (disabled_channels == 0)
1405 fputs ("Error: channels_up called with disabled_channels = 0\n", stderr);
1406 disabled_channels--;
1407 }
1408
1409
1410
1411 void
1412 channels_down (void)
1413 {
1414 disabled_channels++;
1415 }
1416
1417
1418
1419
1420
1421
1422 int
1423 tty_keyname_to_keycode (const char *name, char **label)
1424 {
1425 char **lc_keys, **p;
1426 char *cname;
1427 int k = -1;
1428 int key = 0;
1429 int lc_index = -1;
1430
1431 int use_meta = -1;
1432 int use_ctrl = -1;
1433 int use_shift = -1;
1434
1435 if (name == NULL)
1436 return 0;
1437
1438 cname = g_strstrip (g_strdup (name));
1439 lc_keys = g_strsplit_set (cname, "-+ ", -1);
1440 g_free (cname);
1441
1442 for (p = lc_keys; p != NULL && *p != NULL; p++)
1443 {
1444 if ((*p)[0] != '\0')
1445 {
1446 int idx;
1447
1448 key = lookup_keyname (g_strstrip (*p), &idx);
1449
1450 if (key == KEY_M_ALT)
1451 use_meta = idx;
1452 else if (key == KEY_M_CTRL)
1453 use_ctrl = idx;
1454 else if (key == KEY_M_SHIFT)
1455 use_shift = idx;
1456 else
1457 {
1458 k = key;
1459 lc_index = idx;
1460 break;
1461 }
1462 }
1463 }
1464
1465 g_strfreev (lc_keys);
1466
1467
1468 if (k <= 0)
1469 return 0;
1470
1471 if (label != NULL)
1472 {
1473 GString *s;
1474
1475 s = g_string_new ("");
1476
1477 if (use_meta != -1)
1478 {
1479 g_string_append (s, key_conv_tab_sorted[use_meta]->shortcut);
1480 g_string_append_c (s, '-');
1481 }
1482 if (use_ctrl != -1)
1483 {
1484 g_string_append (s, key_conv_tab_sorted[use_ctrl]->shortcut);
1485 g_string_append_c (s, '-');
1486 }
1487 if (use_shift != -1)
1488 {
1489 if (k < 127)
1490 g_string_append_c (s, (gchar) g_ascii_toupper ((gchar) k));
1491 else
1492 {
1493 g_string_append (s, key_conv_tab_sorted[use_shift]->shortcut);
1494 g_string_append_c (s, '-');
1495 g_string_append (s, key_conv_tab_sorted[lc_index]->shortcut);
1496 }
1497 }
1498 else if (k < 128)
1499 {
1500 if ((k >= 'A') || (lc_index < 0) || (key_conv_tab_sorted[lc_index]->shortcut == NULL))
1501 g_string_append_c (s, (gchar) g_ascii_tolower ((gchar) k));
1502 else
1503 g_string_append (s, key_conv_tab_sorted[lc_index]->shortcut);
1504 }
1505 else if ((lc_index != -1) && (key_conv_tab_sorted[lc_index]->shortcut != NULL))
1506 g_string_append (s, key_conv_tab_sorted[lc_index]->shortcut);
1507 else
1508 g_string_append_c (s, (gchar) g_ascii_tolower ((gchar) key));
1509
1510 *label = g_string_free (s, FALSE);
1511 }
1512
1513 if (use_shift != -1)
1514 {
1515 if (k < 127 && k > 31)
1516 k = g_ascii_toupper ((gchar) k);
1517 else
1518 k |= KEY_M_SHIFT;
1519 }
1520
1521 if (use_ctrl != -1)
1522 {
1523 if (k < 256)
1524 k = XCTRL (k);
1525 else
1526 k |= KEY_M_CTRL;
1527 }
1528
1529 if (use_meta != -1)
1530 k = ALT (k);
1531
1532 return k;
1533 }
1534
1535
1536
1537 char *
1538 tty_keycode_to_keyname (const int keycode)
1539 {
1540
1541 unsigned int k = keycode & ~KEY_M_MASK;
1542
1543 unsigned int mod = keycode & KEY_M_MASK;
1544
1545 int key_idx = -1;
1546
1547 GString *s;
1548 int idx;
1549
1550 s = g_string_sized_new (8);
1551
1552 if (lookup_keycode (k, &key_idx) || (k > 0 && k < 256))
1553 {
1554 if ((mod & KEY_M_ALT) != 0 && lookup_keycode (KEY_M_ALT, &idx))
1555 {
1556 g_string_append (s, key_conv_tab_sorted[idx]->name);
1557 g_string_append_c (s, '-');
1558 }
1559
1560 if ((mod & KEY_M_CTRL) != 0)
1561 {
1562
1563 if (k < 32)
1564 k += 64;
1565
1566 if (lookup_keycode (KEY_M_CTRL, &idx))
1567 {
1568 g_string_append (s, key_conv_tab_sorted[idx]->name);
1569 g_string_append_c (s, '-');
1570 }
1571 }
1572
1573 if ((mod & KEY_M_SHIFT) != 0)
1574 {
1575 if (lookup_keycode (KEY_M_ALT, &idx))
1576 {
1577 if (k < 127)
1578 g_string_append_c (s, (gchar) g_ascii_toupper ((gchar) k));
1579 else
1580 {
1581 g_string_append (s, key_conv_tab_sorted[idx]->name);
1582 g_string_append_c (s, '-');
1583 g_string_append (s, key_conv_tab_sorted[key_idx]->name);
1584 }
1585 }
1586 }
1587 else if (k < 128)
1588 {
1589 if ((k >= 'A') || (key_idx < 0) || (key_conv_tab_sorted[key_idx]->name == NULL))
1590 g_string_append_c (s, (gchar) k);
1591 else
1592 g_string_append (s, key_conv_tab_sorted[key_idx]->name);
1593 }
1594 else if ((key_idx != -1) && (key_conv_tab_sorted[key_idx]->name != NULL))
1595 g_string_append (s, key_conv_tab_sorted[key_idx]->name);
1596 else
1597 g_string_append_c (s, (gchar) keycode);
1598 }
1599
1600 return g_string_free (s, s->len == 0);
1601 }
1602
1603
1604
1605
1606
1607
1608
1609 gboolean
1610 define_sequence (int code, const char *seq, int action)
1611 {
1612 key_def *base;
1613
1614 if (strlen (seq) > SEQ_BUFFER_LEN - 1)
1615 return FALSE;
1616
1617 for (base = keys; (base != NULL) && (*seq != '\0');)
1618 if (*seq == base->ch)
1619 {
1620 if (base->child == NULL)
1621 {
1622 if (*(seq + 1) != '\0')
1623 base->child = create_sequence (seq + 1, code, action);
1624 else
1625 {
1626
1627 base->code = code;
1628 base->action = action;
1629 }
1630 return TRUE;
1631 }
1632
1633 base = base->child;
1634 seq++;
1635 }
1636 else
1637 {
1638 if (base->next != NULL)
1639 base = base->next;
1640 else
1641 {
1642 base->next = create_sequence (seq, code, action);
1643 return TRUE;
1644 }
1645 }
1646
1647 if (*seq == '\0')
1648 {
1649
1650 return FALSE;
1651 }
1652
1653 keys = create_sequence (seq, code, action);
1654 return TRUE;
1655 }
1656
1657
1658
1659
1660
1661
1662 gboolean
1663 is_idle (void)
1664 {
1665 int nfd;
1666 fd_set select_set;
1667 struct timeval time_out;
1668
1669 FD_ZERO (&select_set);
1670 FD_SET (input_fd, &select_set);
1671 nfd = MAX (0, input_fd) + 1;
1672 time_out.tv_sec = 0;
1673 time_out.tv_usec = 0;
1674 #ifdef HAVE_LIBGPM
1675 if (mouse_enabled && use_mouse_p == MOUSE_GPM)
1676 {
1677 if (gpm_fd >= 0)
1678 {
1679 FD_SET (gpm_fd, &select_set);
1680 nfd = MAX (nfd, gpm_fd + 1);
1681 }
1682 else
1683 {
1684 if (mouse_fd >= 0)
1685 {
1686 if (FD_ISSET (mouse_fd, &select_set))
1687 FD_CLR (mouse_fd, &select_set);
1688 mouse_fd = gpm_fd;
1689 }
1690
1691 if (gpm_fd == -1)
1692 {
1693 mouse_enabled = FALSE;
1694 use_mouse_p = MOUSE_NONE;
1695 }
1696 }
1697 }
1698 #endif
1699 return (select (nfd, &select_set, 0, 0, &time_out) <= 0);
1700 }
1701
1702
1703
1704 int
1705 get_key_code (int no_delay)
1706 {
1707 int c;
1708 static key_def *this = NULL, *parent;
1709 static gint64 esc_time = -1;
1710 static int lastnodelay = -1;
1711
1712 if (no_delay != lastnodelay)
1713 {
1714 this = NULL;
1715 lastnodelay = no_delay;
1716 }
1717
1718 pend_send:
1719 if (pending_keys != NULL)
1720 {
1721 gboolean bad_seq;
1722
1723 c = *pending_keys++;
1724 while (c == ESC_CHAR)
1725 c = ALT (*pending_keys++);
1726
1727 bad_seq = (*pending_keys != ESC_CHAR && *pending_keys != '\0');
1728 if (*pending_keys == '\0' || bad_seq)
1729 pending_keys = seq_append = NULL;
1730
1731 if (bad_seq)
1732 {
1733
1734
1735
1736
1737
1738
1739 int paranoia = 20;
1740
1741 while (getch_with_timeout (old_esc_mode_timeout) >= 0 && --paranoia != 0)
1742 ;
1743 }
1744 else
1745 goto done;
1746 }
1747
1748 nodelay_try_again:
1749 if (no_delay != 0)
1750 tty_nodelay (TRUE);
1751
1752 c = tty_lowlevel_getch ();
1753 #if (defined(USE_NCURSES) || defined(USE_NCURSESW)) && defined(KEY_RESIZE)
1754 if (c == KEY_RESIZE)
1755 goto nodelay_try_again;
1756 #endif
1757
1758 if (no_delay != 0)
1759 {
1760 tty_nodelay (FALSE);
1761 if (c == -1)
1762 {
1763 if (this == NULL || parent == NULL || parent->action != MCKEY_ESCAPE || !old_esc_mode
1764 || esc_time == -1 || g_get_monotonic_time () < esc_time + old_esc_mode_timeout)
1765 return -1;
1766
1767 this = NULL;
1768 pending_keys = seq_append = NULL;
1769 return ESC_CHAR;
1770 }
1771 }
1772 else if (c == -1)
1773 {
1774
1775
1776
1777 if (seq_append == NULL)
1778 {
1779 this = NULL;
1780 return -1;
1781 }
1782
1783 pending_keys = seq_buffer;
1784 goto pend_send;
1785 }
1786
1787
1788 if (no_delay == 0 || this == NULL)
1789 {
1790 this = keys;
1791 parent = NULL;
1792 }
1793
1794 while (this != NULL)
1795 {
1796 if (c == this->ch)
1797 {
1798 if (this->child == NULL)
1799 {
1800
1801 pending_keys = seq_append = NULL;
1802 c = this->code;
1803 goto done;
1804 }
1805
1806
1807 if (!push_char (c))
1808 {
1809 pending_keys = seq_buffer;
1810 goto pend_send;
1811 }
1812
1813 parent = this;
1814 this = this->child;
1815 if (parent->action == MCKEY_ESCAPE && old_esc_mode)
1816 {
1817 if (no_delay != 0)
1818 {
1819 esc_time = g_get_monotonic_time ();
1820 goto nodelay_try_again;
1821 }
1822
1823 esc_time = -1;
1824 c = getch_with_timeout (old_esc_mode_timeout);
1825 if (c != -1)
1826 continue;
1827
1828 pending_keys = seq_append = NULL;
1829 this = NULL;
1830 return ESC_CHAR;
1831 }
1832
1833 if (no_delay != 0)
1834 goto nodelay_try_again;
1835 c = tty_lowlevel_getch ();
1836 continue;
1837 }
1838
1839
1840 if (this->next != NULL)
1841 {
1842 this = this->next;
1843 continue;
1844 }
1845
1846
1847 if ((parent != NULL) && (parent->action == MCKEY_ESCAPE))
1848 {
1849
1850 if (g_ascii_isdigit (c))
1851 c = KEY_F (c - '0');
1852 else if (c == ' ')
1853 c = ESC_CHAR;
1854 else
1855 c = ALT (c);
1856
1857 pending_keys = seq_append = NULL;
1858 goto done;
1859 }
1860
1861
1862 push_char (c);
1863 pending_keys = seq_buffer;
1864 goto pend_send;
1865 }
1866
1867 done:
1868 this = NULL;
1869 return correct_key_code (c);
1870 }
1871
1872
1873
1874
1875
1876
1877
1878 int
1879 tty_get_event (struct Gpm_Event *event, gboolean redo_event, gboolean block)
1880 {
1881 int c;
1882 int flag = 0;
1883 #ifdef HAVE_LIBGPM
1884 static struct Gpm_Event ev;
1885 #endif
1886 struct timeval time_out;
1887 struct timeval *time_addr = NULL;
1888 static int dirty = 3;
1889
1890 if ((dirty == 3) || is_idle ())
1891 {
1892 mc_refresh ();
1893 dirty = 1;
1894 }
1895 else
1896 dirty++;
1897
1898 vfs_timeout_handler ();
1899
1900
1901
1902
1903
1904 if (event->x > 0)
1905 {
1906 show_mouse_pointer (event->x, event->y);
1907 if (!redo_event)
1908 event->x = -1;
1909 }
1910
1911
1912 while (pending_keys == NULL)
1913 {
1914 int nfd;
1915 fd_set select_set;
1916
1917 FD_ZERO (&select_set);
1918 FD_SET (input_fd, &select_set);
1919 nfd = MAX (add_selects (&select_set), MAX (0, input_fd)) + 1;
1920
1921 #ifdef HAVE_LIBGPM
1922 if (mouse_enabled && (use_mouse_p == MOUSE_GPM))
1923 {
1924 if (gpm_fd >= 0)
1925 {
1926 FD_SET (gpm_fd, &select_set);
1927 nfd = MAX (nfd, gpm_fd + 1);
1928 }
1929 else
1930 {
1931 if (mouse_fd >= 0)
1932 {
1933 if (FD_ISSET (mouse_fd, &select_set))
1934 FD_CLR (mouse_fd, &select_set);
1935 mouse_fd = gpm_fd;
1936 }
1937
1938 if (gpm_fd == -1)
1939 {
1940 mouse_enabled = FALSE;
1941 use_mouse_p = MOUSE_NONE;
1942 }
1943 break;
1944 }
1945 }
1946 #endif
1947
1948 if (redo_event)
1949 {
1950 time_out.tv_usec = mou_auto_repeat * MC_USEC_PER_MSEC;
1951 time_out.tv_sec = 0;
1952
1953 time_addr = &time_out;
1954 }
1955 else
1956 {
1957 int seconds;
1958
1959 seconds = vfs_timeouts ();
1960 time_addr = NULL;
1961
1962 if (seconds != 0)
1963 {
1964
1965
1966
1967
1968
1969 time_out.tv_sec = seconds;
1970 time_out.tv_usec = 0;
1971 time_addr = &time_out;
1972 }
1973 }
1974
1975 if (!block || tty_got_winch ())
1976 {
1977 time_addr = &time_out;
1978 time_out.tv_sec = 0;
1979 time_out.tv_usec = 0;
1980 }
1981
1982 tty_enable_interrupt_key ();
1983 flag = select (nfd, &select_set, NULL, NULL, time_addr);
1984 tty_disable_interrupt_key ();
1985
1986
1987
1988
1989
1990
1991 if (flag == 0)
1992 {
1993 if (redo_event)
1994 return EV_MOUSE;
1995 if (!block || tty_got_winch ())
1996 return EV_NONE;
1997 vfs_timeout_handler ();
1998 }
1999 if (flag == -1 && errno == EINTR)
2000 return EV_NONE;
2001
2002 check_selects (&select_set);
2003
2004 if (FD_ISSET (input_fd, &select_set))
2005 break;
2006
2007 #ifdef HAVE_LIBGPM
2008 if (mouse_enabled && use_mouse_p == MOUSE_GPM)
2009 {
2010 if (gpm_fd >= 0)
2011 {
2012 if (FD_ISSET (gpm_fd, &select_set))
2013 {
2014 int status;
2015
2016 status = Gpm_GetEvent (&ev);
2017 if (status == 1)
2018 {
2019 Gpm_FitEvent (&ev);
2020 *event = ev;
2021 return EV_MOUSE;
2022 }
2023 if (status <= 0)
2024 {
2025 if (mouse_fd >= 0 && FD_ISSET (mouse_fd, &select_set))
2026 FD_CLR (mouse_fd, &select_set);
2027
2028 disable_mouse ();
2029 return EV_NONE;
2030 }
2031 }
2032 }
2033 else
2034 {
2035 if (mouse_fd >= 0)
2036 {
2037 if (FD_ISSET (mouse_fd, &select_set))
2038 FD_CLR (mouse_fd, &select_set);
2039 mouse_fd = gpm_fd;
2040 }
2041
2042 if (gpm_fd == -1)
2043 {
2044 mouse_enabled = FALSE;
2045 use_mouse_p = MOUSE_NONE;
2046 }
2047 break;
2048 }
2049 }
2050 #endif
2051 }
2052
2053 #ifndef HAVE_SLANG
2054 flag = is_wintouched (stdscr);
2055 untouchwin (stdscr);
2056 #endif
2057 c = block ? getch_with_delay () : get_key_code (1);
2058
2059 #ifndef HAVE_SLANG
2060 if (flag > 0)
2061 tty_touch_screen ();
2062 #endif
2063
2064 if (mouse_enabled
2065 && (c == MCKEY_MOUSE
2066 #ifdef KEY_MOUSE
2067 || c == KEY_MOUSE
2068 #endif
2069 || c == MCKEY_EXTENDED_MOUSE))
2070 {
2071
2072 gboolean extended = c == MCKEY_EXTENDED_MOUSE;
2073
2074 #ifdef KEY_MOUSE
2075 extended = extended || (c == KEY_MOUSE && ncurses_key_mouse_means_extended);
2076 #endif
2077
2078 xmouse_get_event (event, extended);
2079 c = (event->type != 0) ? EV_MOUSE : EV_NONE;
2080 }
2081 else if (c == MCKEY_BRACKETED_PASTING_START)
2082 {
2083 bracketed_pasting_in_progress = TRUE;
2084 c = EV_NONE;
2085 }
2086 else if (c == MCKEY_BRACKETED_PASTING_END)
2087 {
2088 bracketed_pasting_in_progress = FALSE;
2089 c = EV_NONE;
2090 }
2091
2092 return c;
2093 }
2094
2095
2096
2097
2098 int
2099 tty_getch (void)
2100 {
2101 Gpm_Event ev;
2102 int key;
2103
2104 ev.x = -1;
2105 while ((key = tty_get_event (&ev, FALSE, TRUE)) == EV_NONE)
2106 ;
2107 return key;
2108 }
2109
2110
2111
2112 char *
2113 learn_key (void)
2114 {
2115
2116 #define LEARN_TIMEOUT 200
2117
2118 fd_set Read_FD_Set;
2119 gint64 end_time;
2120 int c;
2121 GString *buffer;
2122
2123 buffer = g_string_sized_new (16);
2124
2125 tty_keypad (FALSE);
2126 c = tty_lowlevel_getch ();
2127 while (c == -1)
2128 c = tty_lowlevel_getch ();
2129 learn_store_key (buffer, c);
2130
2131 end_time = g_get_monotonic_time () + LEARN_TIMEOUT * MC_USEC_PER_MSEC;
2132
2133 tty_nodelay (TRUE);
2134 while (TRUE)
2135 {
2136 while ((c = tty_lowlevel_getch ()) == -1)
2137 {
2138 gint64 time_out;
2139 struct timeval tv;
2140
2141 time_out = end_time - g_get_monotonic_time ();
2142 if (time_out <= 0)
2143 break;
2144
2145 tv.tv_sec = time_out / G_USEC_PER_SEC;
2146 tv.tv_usec = time_out % G_USEC_PER_SEC;
2147 FD_ZERO (&Read_FD_Set);
2148 FD_SET (input_fd, &Read_FD_Set);
2149 select (input_fd + 1, &Read_FD_Set, NULL, NULL, &tv);
2150 }
2151 if (c == -1)
2152 break;
2153 learn_store_key (buffer, c);
2154 }
2155 tty_keypad (TRUE);
2156 tty_nodelay (FALSE);
2157
2158 return g_string_free (buffer, buffer->len == 0);
2159 #undef LEARN_TIMEOUT
2160 }
2161
2162
2163
2164
2165
2166
2167 void
2168 numeric_keypad_mode (void)
2169 {
2170 if (mc_global.tty.console_flag != '\0' || mc_global.tty.xterm_flag)
2171 {
2172 fputs (ESC_STR ">", stdout);
2173 fflush (stdout);
2174 }
2175 }
2176
2177
2178
2179 void
2180 application_keypad_mode (void)
2181 {
2182 if (mc_global.tty.console_flag != '\0' || mc_global.tty.xterm_flag)
2183 {
2184 fputs (ESC_STR "=", stdout);
2185 fflush (stdout);
2186 }
2187 }
2188
2189
2190
2191 void
2192 enable_bracketed_paste (void)
2193 {
2194 printf (ESC_STR "[?2004h");
2195 fflush (stdout);
2196 }
2197
2198
2199
2200 void
2201 disable_bracketed_paste (void)
2202 {
2203 printf (ESC_STR "[?2004l");
2204 fflush (stdout);
2205 bracketed_pasting_in_progress = FALSE;
2206 }
2207
2208