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