2 Keyboard support routines.
4 Copyright (C) 1994-2016
5 Free Software Foundation, Inc.
8 Miguel de Icaza, 1994, 1995
9 Janne Kukonlehto, 1994, 1995
12 Denys Vlasenko <vda.linux@googlemail.com>, 2013
13 Slava Zanko <slavazanko@gmail.com>, 2013
14 Egmont Koblinger <egmont@gmail.com>, 2013
16 This file is part of the Midnight Commander.
18 The Midnight Commander is free software: you can redistribute it
19 and/or modify it under the terms of the GNU General Public License as
20 published by the Free Software Foundation, either version 3 of the License,
21 or (at your option) any later version.
23 The Midnight Commander is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 GNU General Public License for more details.
28 You should have received a copy of the GNU General Public License
29 along with this program. If not, see <http://www.gnu.org/licenses/>.
33 * \brief Source: keyboard support routines
44 #include <sys/types.h>
47 #include "lib/global.h"
49 #include "lib/vfs/vfs.h"
52 #include "tty-internal.h" /* mouse_enabled */
56 #include "lib/widget.h" /* mc_refresh() */
58 #ifdef HAVE_TEXTMODE_X11_SUPPORT
63 #if defined(__GLIBC__) && (__GLIBC__ < 2)
64 #include <linux/termios.h> /* TIOCLINUX */
68 #ifdef HAVE_SYS_IOCTL_H
69 #include <sys/ioctl.h>
71 #endif /* __linux__ */
75 #ifdef HAVE_SYS_IOCTL_H
76 #include <sys/ioctl.h>
78 #endif /* __CYGWIN__ */
83 #include <sys/dcmd_chr.h>
84 #endif /* __QNXNTO__ */
86 /*** global variables ****************************************************************************/
88 int mou_auto_repeat
= 100;
89 int double_click_speed
= 250;
91 /* timeout for old_esc_mode in usec */
92 int old_esc_mode_timeout
= 1000000; /* settable via env */
93 int use_8th_bit_as_meta
= 0;
95 gboolean bracketed_pasting_in_progress
= FALSE
;
97 /* This table is a mapping between names and the constants we use
98 * We use this to allow users to define alternate definitions for
99 * certain keys that may be missing from the terminal database
101 const key_code_name_t key_name_conv_tab
[] = {
102 {ESC_CHAR
, "escape", N_("Escape"), "Esc"},
103 /* KEY_F(0) is not here, since we are mapping it to f10, so there is no reason
104 to define f0 as well. Also, it makes Learn keys a bunch of problems :( */
105 {KEY_F (1), "f1", N_("Function key 1"), "F1"},
106 {KEY_F (2), "f2", N_("Function key 2"), "F2"},
107 {KEY_F (3), "f3", N_("Function key 3"), "F3"},
108 {KEY_F (4), "f4", N_("Function key 4"), "F4"},
109 {KEY_F (5), "f5", N_("Function key 5"), "F5"},
110 {KEY_F (6), "f6", N_("Function key 6"), "F6"},
111 {KEY_F (7), "f7", N_("Function key 7"), "F7"},
112 {KEY_F (8), "f8", N_("Function key 8"), "F8"},
113 {KEY_F (9), "f9", N_("Function key 9"), "F9"},
114 {KEY_F (10), "f10", N_("Function key 10"), "F10"},
115 {KEY_F (11), "f11", N_("Function key 11"), "F11"},
116 {KEY_F (12), "f12", N_("Function key 12"), "F12"},
117 {KEY_F (13), "f13", N_("Function key 13"), "F13"},
118 {KEY_F (14), "f14", N_("Function key 14"), "F14"},
119 {KEY_F (15), "f15", N_("Function key 15"), "F15"},
120 {KEY_F (16), "f16", N_("Function key 16"), "F16"},
121 {KEY_F (17), "f17", N_("Function key 17"), "F17"},
122 {KEY_F (18), "f18", N_("Function key 18"), "F18"},
123 {KEY_F (19), "f19", N_("Function key 19"), "F19"},
124 {KEY_F (20), "f20", N_("Function key 20"), "F20"},
125 {ALT ('\t'), "complete", N_("Completion/M-tab"), "Meta-Tab"},
126 {KEY_BTAB
, "backtab", N_("BackTab/S-tab"), "Shift-Tab"},
127 {KEY_BACKSPACE
, "backspace", N_("Backspace"), "Backspace"},
128 {KEY_UP
, "up", N_("Up arrow"), "Up"},
129 {KEY_DOWN
, "down", N_("Down arrow"), "Down"},
130 {KEY_LEFT
, "left", N_("Left arrow"), "Left"},
131 {KEY_RIGHT
, "right", N_("Right arrow"), "Right"},
132 {KEY_IC
, "insert", N_("Insert"), "Ins"},
133 {KEY_DC
, "delete", N_("Delete"), "Del"},
134 {KEY_HOME
, "home", N_("Home"), "Home"},
135 {KEY_END
, "end", N_("End key"), "End"},
136 {KEY_PPAGE
, "pgup", N_("Page Up"), "PgUp"},
137 {KEY_NPAGE
, "pgdn", N_("Page Down"), "PgDn"},
138 {(int) '/', "kpslash", N_("/ on keypad"), "/"},
139 {KEY_KP_MULTIPLY
, "kpasterisk", N_("* on keypad"), "*"},
140 {KEY_KP_SUBTRACT
, "kpminus", N_("- on keypad"), "-"},
141 {KEY_KP_ADD
, "kpplus", N_("+ on keypad"), "+"},
143 /* From here on, these won't be shown in Learn keys (no space) */
144 {KEY_LEFT
, "kpleft", N_("Left arrow keypad"), "Left"},
145 {KEY_RIGHT
, "kpright", N_("Right arrow keypad"), "Right"},
146 {KEY_UP
, "kpup", N_("Up arrow keypad"), "Up"},
147 {KEY_DOWN
, "kpdown", N_("Down arrow keypad"), "Down"},
148 {KEY_HOME
, "kphome", N_("Home on keypad"), "Home"},
149 {KEY_END
, "kpend", N_("End on keypad"), "End"},
150 {KEY_NPAGE
, "kpnpage", N_("Page Down keypad"), "PgDn"},
151 {KEY_PPAGE
, "kpppage", N_("Page Up keypad"), "PgUp"},
152 {KEY_IC
, "kpinsert", N_("Insert on keypad"), "Ins"},
153 {KEY_DC
, "kpdelete", N_("Delete on keypad"), "Del"},
154 {(int) '\n', "kpenter", N_("Enter on keypad"), "Enter"},
155 {KEY_F (21), "f21", N_("Function key 21"), "F21"},
156 {KEY_F (22), "f22", N_("Function key 22"), "F22"},
157 {KEY_F (23), "f23", N_("Function key 23"), "F23"},
158 {KEY_F (24), "f24", N_("Function key 24"), "F24"},
159 {KEY_A1
, "a1", N_("A1 key"), "A1"},
160 {KEY_C1
, "c1", N_("C1 key"), "C1"},
162 /* Alternative label */
163 {ESC_CHAR
, "esc", N_("Escape"), "Esc"},
164 {KEY_BACKSPACE
, "bs", N_("Backspace"), "Bakspace"},
165 {KEY_IC
, "ins", N_("Insert"), "Ins"},
166 {KEY_DC
, "del", N_("Delete"), "Del"},
167 {(int) '*', "asterisk", N_("Asterisk"), "*"},
168 {(int) '-', "minus", N_("Minus"), "-"},
169 {(int) '+', "plus", N_("Plus"), "+"},
170 {(int) '.', "dot", N_("Dot"), "."},
171 {(int) '<', "lt", N_("Less than"), "<"},
172 {(int) '>', "gt", N_("Great than"), ">"},
173 {(int) '=', "equal", N_("Equal"), "="},
174 {(int) ',', "comma", N_("Comma"), ","},
175 {(int) '\'', "apostrophe", N_("Apostrophe"), "\'"},
176 {(int) ':', "colon", N_("Colon"), ":"},
177 {(int) ';', "semicolon", N_("Semicolon"), ";"},
178 {(int) '!', "exclamation", N_("Exclamation mark"), "!"},
179 {(int) '?', "question", N_("Question mark"), "?"},
180 {(int) '&', "ampersand", N_("Ampersand"), "&"},
181 {(int) '$', "dollar", N_("Dollar sign"), "$"},
182 {(int) '"', "quota", N_("Quotation mark"), "\""},
183 {(int) '%', "percent", N_("Percent sign"), "%"},
184 {(int) '^', "caret", N_("Caret"), "^"},
185 {(int) '~', "tilda", N_("Tilda"), "~"},
186 {(int) '`', "prime", N_("Prime"), "`"},
187 {(int) '_', "underline", N_("Underline"), "_"},
188 {(int) '_', "understrike", N_("Understrike"), "_"},
189 {(int) '|', "pipe", N_("Pipe"), "|"},
190 {(int) '(', "lparenthesis", N_("Left parenthesis"), "("},
191 {(int) ')', "rparenthesis", N_("Right parenthesis"), ")"},
192 {(int) '[', "lbracket", N_("Left bracket"), "["},
193 {(int) ']', "rbracket", N_("Right bracket"), "]"},
194 {(int) '{', "lbrace", N_("Left brace"), "{"},
195 {(int) '}', "rbrace", N_("Right brace"), "}"},
196 {(int) '\n', "enter", N_("Enter"), "Enter"},
197 {(int) '\t', "tab", N_("Tab key"), "Tab"},
198 {(int) ' ', "space", N_("Space key"), "Space"},
199 {(int) '/', "slash", N_("Slash key"), "/"},
200 {(int) '\\', "backslash", N_("Backslash key"), "\\"},
201 {(int) '#', "number", N_("Number sign #"), "#"},
202 {(int) '#', "hash", N_("Number sign #"), "#"},
203 /* TRANSLATORS: Please translate as in "at sign" (@). */
204 {(int) '@', "at", N_("At sign"), "@"},
207 {KEY_M_CTRL
, "control", N_("Ctrl"), "C"},
208 {KEY_M_CTRL
, "ctrl", N_("Ctrl"), "C"},
209 {KEY_M_ALT
, "meta", N_("Alt"), "M"},
210 {KEY_M_ALT
, "alt", N_("Alt"), "M"},
211 {KEY_M_ALT
, "ralt", N_("Alt"), "M"},
212 {KEY_M_SHIFT
, "shift", N_("Shift"), "S"},
214 {0, NULL
, NULL
, NULL
}
217 /*** file scope macro definitions ****************************************************************/
219 #define GET_TIME(tv) (gettimeofday(&tv, (struct timezone *) NULL))
220 #define DIF_TIME(t1, t2) ((t2.tv_sec - t1.tv_sec) * 1000 + (t2.tv_usec - t1.tv_usec)/1000)
222 /* The maximum sequence length (32 + null terminator) */
223 #define SEQ_BUFFER_LEN 33
225 /*** file scope type declarations ****************************************************************/
227 /* Linux console keyboard modifiers */
230 SHIFT_PRESSED
= (1 << 0),
231 ALTR_PRESSED
= (1 << 1),
232 CONTROL_PRESSED
= (1 << 2),
233 ALTL_PRESSED
= (1 << 3)
236 typedef struct key_def
238 char ch
; /* Holds the matching char code */
239 int code
; /* The code returned, valid if child == NULL */
240 struct key_def
*next
;
241 struct key_def
*child
; /* sequence continuation */
242 int action
; /* optional action to be done. Now used only
243 to mark that we are just after the first
254 /* File descriptor monitoring add/remove routines */
255 typedef struct SelectList
260 struct SelectList
*next
;
263 typedef enum KeySortType
271 typedef int (*ph_dv_f
) (void *, void *);
272 typedef int (*ph_ov_f
) (void *);
273 typedef int (*ph_pqc_f
) (unsigned short, PhCursorInfo_t
*);
276 /*** file scope variables ************************************************************************/
278 static key_define_t mc_default_keys
[] = {
279 {ESC_CHAR
, ESC_STR
, MCKEY_ESCAPE
},
280 {ESC_CHAR
, ESC_STR ESC_STR
, MCKEY_NOACTION
},
281 {MCKEY_BRACKETED_PASTING_START
, ESC_STR
"[200~", MCKEY_NOACTION
},
282 {MCKEY_BRACKETED_PASTING_END
, ESC_STR
"[201~", MCKEY_NOACTION
},
283 {0, NULL
, MCKEY_NOACTION
},
286 /* Broken terminfo and termcap databases on xterminals */
287 static key_define_t xterm_key_defines
[] = {
288 {KEY_F (1), ESC_STR
"OP", MCKEY_NOACTION
},
289 {KEY_F (2), ESC_STR
"OQ", MCKEY_NOACTION
},
290 {KEY_F (3), ESC_STR
"OR", MCKEY_NOACTION
},
291 {KEY_F (4), ESC_STR
"OS", MCKEY_NOACTION
},
292 {KEY_F (1), ESC_STR
"[11~", MCKEY_NOACTION
},
293 {KEY_F (2), ESC_STR
"[12~", MCKEY_NOACTION
},
294 {KEY_F (3), ESC_STR
"[13~", MCKEY_NOACTION
},
295 {KEY_F (4), ESC_STR
"[14~", MCKEY_NOACTION
},
296 {KEY_F (5), ESC_STR
"[15~", MCKEY_NOACTION
},
297 {KEY_F (6), ESC_STR
"[17~", MCKEY_NOACTION
},
298 {KEY_F (7), ESC_STR
"[18~", MCKEY_NOACTION
},
299 {KEY_F (8), ESC_STR
"[19~", MCKEY_NOACTION
},
300 {KEY_F (9), ESC_STR
"[20~", MCKEY_NOACTION
},
301 {KEY_F (10), ESC_STR
"[21~", MCKEY_NOACTION
},
303 /* old xterm Shift-arrows */
304 {KEY_M_SHIFT
| KEY_UP
, ESC_STR
"O2A", MCKEY_NOACTION
},
305 {KEY_M_SHIFT
| KEY_DOWN
, ESC_STR
"O2B", MCKEY_NOACTION
},
306 {KEY_M_SHIFT
| KEY_RIGHT
, ESC_STR
"O2C", MCKEY_NOACTION
},
307 {KEY_M_SHIFT
| KEY_LEFT
, ESC_STR
"O2D", MCKEY_NOACTION
},
309 /* new xterm Shift-arrows */
310 {KEY_M_SHIFT
| KEY_UP
, ESC_STR
"[1;2A", MCKEY_NOACTION
},
311 {KEY_M_SHIFT
| KEY_DOWN
, ESC_STR
"[1;2B", MCKEY_NOACTION
},
312 {KEY_M_SHIFT
| KEY_RIGHT
, ESC_STR
"[1;2C", MCKEY_NOACTION
},
313 {KEY_M_SHIFT
| KEY_LEFT
, ESC_STR
"[1;2D", MCKEY_NOACTION
},
315 /* more xterm keys with modifiers */
316 {KEY_M_CTRL
| KEY_PPAGE
, ESC_STR
"[5;5~", MCKEY_NOACTION
},
317 {KEY_M_CTRL
| KEY_NPAGE
, ESC_STR
"[6;5~", MCKEY_NOACTION
},
318 {KEY_M_CTRL
| KEY_IC
, ESC_STR
"[2;5~", MCKEY_NOACTION
},
319 {KEY_M_CTRL
| KEY_DC
, ESC_STR
"[3;5~", MCKEY_NOACTION
},
320 {KEY_M_CTRL
| KEY_HOME
, ESC_STR
"[1;5H", MCKEY_NOACTION
},
321 {KEY_M_CTRL
| KEY_END
, ESC_STR
"[1;5F", MCKEY_NOACTION
},
322 {KEY_M_SHIFT
| KEY_HOME
, ESC_STR
"[1;2H", MCKEY_NOACTION
},
323 {KEY_M_SHIFT
| KEY_END
, ESC_STR
"[1;2F", MCKEY_NOACTION
},
324 {KEY_M_CTRL
| KEY_UP
, ESC_STR
"[1;5A", MCKEY_NOACTION
},
325 {KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"[1;5B", MCKEY_NOACTION
},
326 {KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"[1;5C", MCKEY_NOACTION
},
327 {KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"[1;5D", MCKEY_NOACTION
},
328 {KEY_M_SHIFT
| KEY_IC
, ESC_STR
"[2;2~", MCKEY_NOACTION
},
329 {KEY_M_SHIFT
| KEY_DC
, ESC_STR
"[3;2~", MCKEY_NOACTION
},
330 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_UP
, ESC_STR
"[1;6A", MCKEY_NOACTION
},
331 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"[1;6B", MCKEY_NOACTION
},
332 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"[1;6C", MCKEY_NOACTION
},
333 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"[1;6D", MCKEY_NOACTION
},
334 {KEY_M_SHIFT
| '\t', ESC_STR
"[Z", MCKEY_NOACTION
},
337 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_UP
, ESC_STR
"[[1;6A", MCKEY_NOACTION
},
338 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"[[1;6B", MCKEY_NOACTION
},
339 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"[[1;6C", MCKEY_NOACTION
},
340 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"[[1;6D", MCKEY_NOACTION
},
342 /* putty alt-arrow keys */
343 /* removed as source esc esc esc trouble */
345 { KEY_M_ALT | KEY_UP, ESC_STR ESC_STR "OA", MCKEY_NOACTION },
346 { KEY_M_ALT | KEY_DOWN, ESC_STR ESC_STR "OB", MCKEY_NOACTION },
347 { KEY_M_ALT | KEY_RIGHT, ESC_STR ESC_STR "OC", MCKEY_NOACTION },
348 { KEY_M_ALT | KEY_LEFT, ESC_STR ESC_STR "OD", MCKEY_NOACTION },
349 { KEY_M_ALT | KEY_PPAGE, ESC_STR ESC_STR "[5~", MCKEY_NOACTION },
350 { KEY_M_ALT | KEY_NPAGE, ESC_STR ESC_STR "[6~", MCKEY_NOACTION },
351 { KEY_M_ALT | KEY_HOME, ESC_STR ESC_STR "[1~", MCKEY_NOACTION },
352 { KEY_M_ALT | KEY_END, ESC_STR ESC_STR "[4~", MCKEY_NOACTION },
354 { KEY_M_CTRL | KEY_M_ALT | KEY_UP, ESC_STR ESC_STR "[1;2A", MCKEY_NOACTION },
355 { KEY_M_CTRL | KEY_M_ALT | KEY_DOWN, ESC_STR ESC_STR "[1;2B", MCKEY_NOACTION },
356 { KEY_M_CTRL | KEY_M_ALT | KEY_RIGHT, ESC_STR ESC_STR "[1;2C", MCKEY_NOACTION },
357 { KEY_M_CTRL | KEY_M_ALT | KEY_LEFT, ESC_STR ESC_STR "[1;2D", MCKEY_NOACTION },
359 { KEY_M_CTRL | KEY_M_ALT | KEY_PPAGE, ESC_STR ESC_STR "[[5;5~", MCKEY_NOACTION },
360 { KEY_M_CTRL | KEY_M_ALT | KEY_NPAGE, ESC_STR ESC_STR "[[6;5~", MCKEY_NOACTION },
361 { KEY_M_CTRL | KEY_M_ALT | KEY_HOME, ESC_STR ESC_STR "[1;5H", MCKEY_NOACTION },
362 { KEY_M_CTRL | KEY_M_ALT | KEY_END, ESC_STR ESC_STR "[1;5F", MCKEY_NOACTION },
364 /* xterm alt-arrow keys */
365 {KEY_M_ALT
| KEY_UP
, ESC_STR
"[1;3A", MCKEY_NOACTION
},
366 {KEY_M_ALT
| KEY_DOWN
, ESC_STR
"[1;3B", MCKEY_NOACTION
},
367 {KEY_M_ALT
| KEY_RIGHT
, ESC_STR
"[1;3C", MCKEY_NOACTION
},
368 {KEY_M_ALT
| KEY_LEFT
, ESC_STR
"[1;3D", MCKEY_NOACTION
},
369 {KEY_M_ALT
| KEY_PPAGE
, ESC_STR
"[5;3~", MCKEY_NOACTION
},
370 {KEY_M_ALT
| KEY_NPAGE
, ESC_STR
"[6;3~", MCKEY_NOACTION
},
371 {KEY_M_ALT
| KEY_HOME
, ESC_STR
"[1~", MCKEY_NOACTION
},
372 {KEY_M_ALT
| KEY_END
, ESC_STR
"[4~", MCKEY_NOACTION
},
373 {KEY_M_CTRL
| KEY_M_ALT
| KEY_UP
, ESC_STR
"[1;7A", MCKEY_NOACTION
},
374 {KEY_M_CTRL
| KEY_M_ALT
| KEY_DOWN
, ESC_STR
"[1;7B", MCKEY_NOACTION
},
375 {KEY_M_CTRL
| KEY_M_ALT
| KEY_RIGHT
, ESC_STR
"[1;7C", MCKEY_NOACTION
},
376 {KEY_M_CTRL
| KEY_M_ALT
| KEY_LEFT
, ESC_STR
"[1;7D", MCKEY_NOACTION
},
377 {KEY_M_CTRL
| KEY_M_ALT
| KEY_PPAGE
, ESC_STR
"[5;7~", MCKEY_NOACTION
},
378 {KEY_M_CTRL
| KEY_M_ALT
| KEY_NPAGE
, ESC_STR
"[6;7~", MCKEY_NOACTION
},
379 {KEY_M_CTRL
| KEY_M_ALT
| KEY_HOME
, ESC_STR
"OH", MCKEY_NOACTION
},
380 {KEY_M_CTRL
| KEY_M_ALT
| KEY_END
, ESC_STR
"OF", MCKEY_NOACTION
},
382 /* rxvt keys with modifiers */
383 {KEY_M_SHIFT
| KEY_UP
, ESC_STR
"[a", MCKEY_NOACTION
},
384 {KEY_M_SHIFT
| KEY_DOWN
, ESC_STR
"[b", MCKEY_NOACTION
},
385 {KEY_M_SHIFT
| KEY_RIGHT
, ESC_STR
"[c", MCKEY_NOACTION
},
386 {KEY_M_SHIFT
| KEY_LEFT
, ESC_STR
"[d", MCKEY_NOACTION
},
387 {KEY_M_CTRL
| KEY_UP
, ESC_STR
"Oa", MCKEY_NOACTION
},
388 {KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"Ob", MCKEY_NOACTION
},
389 {KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"Oc", MCKEY_NOACTION
},
390 {KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"Od", MCKEY_NOACTION
},
391 {KEY_M_CTRL
| KEY_PPAGE
, ESC_STR
"[5^", MCKEY_NOACTION
},
392 {KEY_M_CTRL
| KEY_NPAGE
, ESC_STR
"[6^", MCKEY_NOACTION
},
393 {KEY_M_CTRL
| KEY_HOME
, ESC_STR
"[7^", MCKEY_NOACTION
},
394 {KEY_M_CTRL
| KEY_END
, ESC_STR
"[8^", MCKEY_NOACTION
},
395 {KEY_M_SHIFT
| KEY_HOME
, ESC_STR
"[7$", MCKEY_NOACTION
},
396 {KEY_M_SHIFT
| KEY_END
, ESC_STR
"[8$", MCKEY_NOACTION
},
397 {KEY_M_CTRL
| KEY_IC
, ESC_STR
"[2^", MCKEY_NOACTION
},
398 {KEY_M_CTRL
| KEY_DC
, ESC_STR
"[3^", MCKEY_NOACTION
},
399 {KEY_M_SHIFT
| KEY_DC
, ESC_STR
"[3$", MCKEY_NOACTION
},
401 /* konsole keys with modifiers */
402 {KEY_M_SHIFT
| KEY_HOME
, ESC_STR
"O2H", MCKEY_NOACTION
},
403 {KEY_M_SHIFT
| KEY_END
, ESC_STR
"O2F", MCKEY_NOACTION
},
406 {KEY_M_SHIFT
| KEY_UP
, ESC_STR
"[2A", MCKEY_NOACTION
},
407 {KEY_M_SHIFT
| KEY_DOWN
, ESC_STR
"[2B", MCKEY_NOACTION
},
408 {KEY_M_SHIFT
| KEY_RIGHT
, ESC_STR
"[2C", MCKEY_NOACTION
},
409 {KEY_M_SHIFT
| KEY_LEFT
, ESC_STR
"[2D", MCKEY_NOACTION
},
410 {KEY_M_CTRL
| KEY_UP
, ESC_STR
"[5A", MCKEY_NOACTION
},
411 {KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"[5B", MCKEY_NOACTION
},
412 {KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"[5C", MCKEY_NOACTION
},
413 {KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"[5D", MCKEY_NOACTION
},
414 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_UP
, ESC_STR
"[6A", MCKEY_NOACTION
},
415 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"[6B", MCKEY_NOACTION
},
416 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"[6C", MCKEY_NOACTION
},
417 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"[6D", MCKEY_NOACTION
},
419 /* gnome-terminal - application mode */
420 {KEY_M_CTRL
| KEY_UP
, ESC_STR
"O5A", MCKEY_NOACTION
},
421 {KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"O5B", MCKEY_NOACTION
},
422 {KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"O5C", MCKEY_NOACTION
},
423 {KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"O5D", MCKEY_NOACTION
},
424 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_UP
, ESC_STR
"O6A", MCKEY_NOACTION
},
425 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"O6B", MCKEY_NOACTION
},
426 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"O6C", MCKEY_NOACTION
},
427 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"O6D", MCKEY_NOACTION
},
430 {KEY_M_SHIFT
| KEY_PPAGE
, ESC_STR
"[5;2~", MCKEY_NOACTION
},
431 {KEY_M_SHIFT
| KEY_NPAGE
, ESC_STR
"[6;2~", MCKEY_NOACTION
},
434 {KEY_M_SHIFT
| KEY_PPAGE
, ESC_STR
"[[5;53~", MCKEY_NOACTION
},
435 {KEY_M_SHIFT
| KEY_NPAGE
, ESC_STR
"[[6;53~", MCKEY_NOACTION
},
438 {KEY_IC
, ESC_STR
"Op", MCKEY_NOACTION
},
439 {KEY_DC
, ESC_STR
"On", MCKEY_NOACTION
},
440 {'/', ESC_STR
"Oo", MCKEY_NOACTION
},
441 {'\n', ESC_STR
"OM", MCKEY_NOACTION
},
443 {0, NULL
, MCKEY_NOACTION
},
446 /* qansi-m terminals have a much more key combinatios,
447 which are undefined in termcap/terminfo */
448 static key_define_t qansi_key_defines
[] = {
449 /* qansi-m terminal */
450 {KEY_M_CTRL
| KEY_NPAGE
, ESC_STR
"[u", MCKEY_NOACTION
}, /* Ctrl-PgDown */
451 {KEY_M_CTRL
| KEY_PPAGE
, ESC_STR
"[v", MCKEY_NOACTION
}, /* Ctrl-PgUp */
452 {KEY_M_CTRL
| KEY_HOME
, ESC_STR
"[h", MCKEY_NOACTION
}, /* Ctrl-Home */
453 {KEY_M_CTRL
| KEY_END
, ESC_STR
"[y", MCKEY_NOACTION
}, /* Ctrl-End */
454 {KEY_M_CTRL
| KEY_IC
, ESC_STR
"[`", MCKEY_NOACTION
}, /* Ctrl-Insert */
455 {KEY_M_CTRL
| KEY_DC
, ESC_STR
"[p", MCKEY_NOACTION
}, /* Ctrl-Delete */
456 {KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"[d", MCKEY_NOACTION
}, /* Ctrl-Left */
457 {KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"[c", MCKEY_NOACTION
}, /* Ctrl-Right */
458 {KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"[b", MCKEY_NOACTION
}, /* Ctrl-Down */
459 {KEY_M_CTRL
| KEY_UP
, ESC_STR
"[a", MCKEY_NOACTION
}, /* Ctrl-Up */
460 {KEY_M_CTRL
| KEY_KP_ADD
, ESC_STR
"[s", MCKEY_NOACTION
}, /* Ctrl-Gr-Plus */
461 {KEY_M_CTRL
| KEY_KP_SUBTRACT
, ESC_STR
"[t", MCKEY_NOACTION
}, /* Ctrl-Gr-Minus */
462 {KEY_M_CTRL
| '\t', ESC_STR
"[z", MCKEY_NOACTION
}, /* Ctrl-Tab */
463 {KEY_M_SHIFT
| '\t', ESC_STR
"[Z", MCKEY_NOACTION
}, /* Shift-Tab */
464 {KEY_M_CTRL
| KEY_F (1), ESC_STR
"[1~", MCKEY_NOACTION
}, /* Ctrl-F1 */
465 {KEY_M_CTRL
| KEY_F (2), ESC_STR
"[2~", MCKEY_NOACTION
}, /* Ctrl-F2 */
466 {KEY_M_CTRL
| KEY_F (3), ESC_STR
"[3~", MCKEY_NOACTION
}, /* Ctrl-F3 */
467 {KEY_M_CTRL
| KEY_F (4), ESC_STR
"[4~", MCKEY_NOACTION
}, /* Ctrl-F4 */
468 {KEY_M_CTRL
| KEY_F (5), ESC_STR
"[5~", MCKEY_NOACTION
}, /* Ctrl-F5 */
469 {KEY_M_CTRL
| KEY_F (6), ESC_STR
"[6~", MCKEY_NOACTION
}, /* Ctrl-F6 */
470 {KEY_M_CTRL
| KEY_F (7), ESC_STR
"[7~", MCKEY_NOACTION
}, /* Ctrl-F7 */
471 {KEY_M_CTRL
| KEY_F (8), ESC_STR
"[8~", MCKEY_NOACTION
}, /* Ctrl-F8 */
472 {KEY_M_CTRL
| KEY_F (9), ESC_STR
"[9~", MCKEY_NOACTION
}, /* Ctrl-F9 */
473 {KEY_M_CTRL
| KEY_F (10), ESC_STR
"[10~", MCKEY_NOACTION
}, /* Ctrl-F10 */
474 {KEY_M_CTRL
| KEY_F (11), ESC_STR
"[11~", MCKEY_NOACTION
}, /* Ctrl-F11 */
475 {KEY_M_CTRL
| KEY_F (12), ESC_STR
"[12~", MCKEY_NOACTION
}, /* Ctrl-F12 */
476 {KEY_M_ALT
| KEY_F (1), ESC_STR
"[17~", MCKEY_NOACTION
}, /* Alt-F1 */
477 {KEY_M_ALT
| KEY_F (2), ESC_STR
"[18~", MCKEY_NOACTION
}, /* Alt-F2 */
478 {KEY_M_ALT
| KEY_F (3), ESC_STR
"[19~", MCKEY_NOACTION
}, /* Alt-F3 */
479 {KEY_M_ALT
| KEY_F (4), ESC_STR
"[20~", MCKEY_NOACTION
}, /* Alt-F4 */
480 {KEY_M_ALT
| KEY_F (5), ESC_STR
"[21~", MCKEY_NOACTION
}, /* Alt-F5 */
481 {KEY_M_ALT
| KEY_F (6), ESC_STR
"[22~", MCKEY_NOACTION
}, /* Alt-F6 */
482 {KEY_M_ALT
| KEY_F (7), ESC_STR
"[23~", MCKEY_NOACTION
}, /* Alt-F7 */
483 {KEY_M_ALT
| KEY_F (8), ESC_STR
"[24~", MCKEY_NOACTION
}, /* Alt-F8 */
484 {KEY_M_ALT
| KEY_F (9), ESC_STR
"[25~", MCKEY_NOACTION
}, /* Alt-F9 */
485 {KEY_M_ALT
| KEY_F (10), ESC_STR
"[26~", MCKEY_NOACTION
}, /* Alt-F10 */
486 {KEY_M_ALT
| KEY_F (11), ESC_STR
"[27~", MCKEY_NOACTION
}, /* Alt-F11 */
487 {KEY_M_ALT
| KEY_F (12), ESC_STR
"[28~", MCKEY_NOACTION
}, /* Alt-F12 */
488 {KEY_M_ALT
| 'a', ESC_STR
"Na", MCKEY_NOACTION
}, /* Alt-a */
489 {KEY_M_ALT
| 'b', ESC_STR
"Nb", MCKEY_NOACTION
}, /* Alt-b */
490 {KEY_M_ALT
| 'c', ESC_STR
"Nc", MCKEY_NOACTION
}, /* Alt-c */
491 {KEY_M_ALT
| 'd', ESC_STR
"Nd", MCKEY_NOACTION
}, /* Alt-d */
492 {KEY_M_ALT
| 'e', ESC_STR
"Ne", MCKEY_NOACTION
}, /* Alt-e */
493 {KEY_M_ALT
| 'f', ESC_STR
"Nf", MCKEY_NOACTION
}, /* Alt-f */
494 {KEY_M_ALT
| 'g', ESC_STR
"Ng", MCKEY_NOACTION
}, /* Alt-g */
495 {KEY_M_ALT
| 'h', ESC_STR
"Nh", MCKEY_NOACTION
}, /* Alt-h */
496 {KEY_M_ALT
| 'i', ESC_STR
"Ni", MCKEY_NOACTION
}, /* Alt-i */
497 {KEY_M_ALT
| 'j', ESC_STR
"Nj", MCKEY_NOACTION
}, /* Alt-j */
498 {KEY_M_ALT
| 'k', ESC_STR
"Nk", MCKEY_NOACTION
}, /* Alt-k */
499 {KEY_M_ALT
| 'l', ESC_STR
"Nl", MCKEY_NOACTION
}, /* Alt-l */
500 {KEY_M_ALT
| 'm', ESC_STR
"Nm", MCKEY_NOACTION
}, /* Alt-m */
501 {KEY_M_ALT
| 'n', ESC_STR
"Nn", MCKEY_NOACTION
}, /* Alt-n */
502 {KEY_M_ALT
| 'o', ESC_STR
"No", MCKEY_NOACTION
}, /* Alt-o */
503 {KEY_M_ALT
| 'p', ESC_STR
"Np", MCKEY_NOACTION
}, /* Alt-p */
504 {KEY_M_ALT
| 'q', ESC_STR
"Nq", MCKEY_NOACTION
}, /* Alt-q */
505 {KEY_M_ALT
| 'r', ESC_STR
"Nr", MCKEY_NOACTION
}, /* Alt-r */
506 {KEY_M_ALT
| 's', ESC_STR
"Ns", MCKEY_NOACTION
}, /* Alt-s */
507 {KEY_M_ALT
| 't', ESC_STR
"Nt", MCKEY_NOACTION
}, /* Alt-t */
508 {KEY_M_ALT
| 'u', ESC_STR
"Nu", MCKEY_NOACTION
}, /* Alt-u */
509 {KEY_M_ALT
| 'v', ESC_STR
"Nv", MCKEY_NOACTION
}, /* Alt-v */
510 {KEY_M_ALT
| 'w', ESC_STR
"Nw", MCKEY_NOACTION
}, /* Alt-w */
511 {KEY_M_ALT
| 'x', ESC_STR
"Nx", MCKEY_NOACTION
}, /* Alt-x */
512 {KEY_M_ALT
| 'y', ESC_STR
"Ny", MCKEY_NOACTION
}, /* Alt-y */
513 {KEY_M_ALT
| 'z', ESC_STR
"Nz", MCKEY_NOACTION
}, /* Alt-z */
514 {KEY_KP_SUBTRACT
, ESC_STR
"[S", MCKEY_NOACTION
}, /* Gr-Minus */
515 {KEY_KP_ADD
, ESC_STR
"[T", MCKEY_NOACTION
}, /* Gr-Plus */
516 {0, NULL
, MCKEY_NOACTION
},
519 /* This holds all the key definitions */
520 static key_def
*keys
= NULL
;
523 static int disabled_channels
= 0; /* Disable channels checking */
525 static SelectList
*select_list
= NULL
;
527 static int seq_buffer
[SEQ_BUFFER_LEN
];
528 static int *seq_append
= NULL
;
530 static int *pending_keys
= NULL
;
534 ph_ov_f ph_input_group
;
535 ph_pqc_f ph_query_cursor
;
538 #ifdef HAVE_TEXTMODE_X11_SUPPORT
539 static Display
*x11_display
;
540 static Window x11_window
;
541 #endif /* HAVE_TEXTMODE_X11_SUPPORT */
543 static KeySortType has_been_sorted
= KEY_NOSORT
;
546 static const size_t key_conv_tab_size
= G_N_ELEMENTS (key_name_conv_tab
) - 1;
549 static const key_code_name_t
*key_conv_tab_sorted
[G_N_ELEMENTS (key_name_conv_tab
) - 1];
551 /*** file scope functions ************************************************************************/
552 /* --------------------------------------------------------------------------------------------- */
555 add_selects (fd_set
* select_set
)
559 if (disabled_channels
== 0)
563 for (p
= select_list
; p
!= NULL
; p
= p
->next
)
565 FD_SET (p
->fd
, select_set
);
574 /* --------------------------------------------------------------------------------------------- */
577 check_selects (fd_set
* select_set
)
579 if (disabled_channels
== 0)
588 for (p
= select_list
; p
; p
= p
->next
)
589 if (FD_ISSET (p
->fd
, select_set
))
591 FD_CLR (p
->fd
, select_set
);
592 (*p
->callback
) (p
->fd
, p
->info
);
601 /* --------------------------------------------------------------------------------------------- */
602 /* If set timeout is set, then we wait 0.1 seconds, else, we block */
605 try_channels (int set_timeout
)
607 struct timeval time_out
;
608 static fd_set select_set
;
612 struct timeval
*timeptr
= NULL
;
615 FD_ZERO (&select_set
);
616 FD_SET (input_fd
, &select_set
); /* Add stdin */
617 maxfdp
= max (add_selects (&select_set
), input_fd
);
622 time_out
.tv_usec
= 100000;
626 v
= select (maxfdp
+ 1, &select_set
, NULL
, NULL
, timeptr
);
629 check_selects (&select_set
);
630 if (FD_ISSET (input_fd
, &select_set
))
636 /* --------------------------------------------------------------------------------------------- */
639 create_sequence (const char *seq
, int code
, int action
)
641 key_def
*base
, *p
, *attach
;
643 for (base
= attach
= NULL
; *seq
; seq
++)
645 p
= g_new (key_def
, 1);
653 p
->child
= p
->next
= NULL
;
657 p
->action
= MCKEY_NOACTION
;
663 /* --------------------------------------------------------------------------------------------- */
666 define_sequences (const key_define_t
* kd
)
670 for (i
= 0; kd
[i
].code
!= 0; i
++)
671 define_sequence (kd
[i
].code
, kd
[i
].seq
, kd
[i
].action
);
674 /* --------------------------------------------------------------------------------------------- */
676 #ifdef HAVE_TEXTMODE_X11_SUPPORT
680 if (getenv ("DISPLAY") != NULL
&& !mc_global
.tty
.disable_x11
)
682 x11_display
= mc_XOpenDisplay (0);
684 if (x11_display
!= NULL
)
685 x11_window
= DefaultRootWindow (x11_display
);
688 #endif /* HAVE_TEXTMODE_X11_SUPPORT */
690 /* --------------------------------------------------------------------------------------------- */
691 /* Workaround for System V Curses vt100 bug */
694 getch_with_delay (void)
698 /* This routine could be used on systems without mouse support,
699 so we need to do the select check :-( */
702 if (pending_keys
== NULL
)
705 /* Try to get a character */
706 c
= get_key_code (0);
709 /* Failed -> wait 0.1 secs and try again */
712 /* Success -> return the character */
716 /* --------------------------------------------------------------------------------------------- */
719 xmouse_get_event (Gpm_Event
* ev
, gboolean extended
)
721 static struct timeval tv1
= { 0, 0 }; /* Force first click as single */
722 static struct timeval tv2
;
723 static int clicks
= 0;
724 static int last_btn
= 0;
727 /* Decode Xterm mouse information to a GPM style event */
731 /* Variable btn has following meaning: */
732 /* 0 = btn1 dn, 1 = btn2 dn, 2 = btn3 dn, 3 = btn up */
733 btn
= tty_lowlevel_getch () - 32;
734 /* Coordinates are 33-based */
735 /* Transform them to 1-based */
736 ev
->x
= tty_lowlevel_getch () - 32;
737 ev
->y
= tty_lowlevel_getch () - 32;
741 /* SGR 1006 extension (e.g. "\e[<0;12;300M"):
742 - Numbers are encoded in decimal to make it ASCII-safe
743 and to overcome the limit of 223 columns/rows.
744 - Mouse release is encoded by trailing 'm' rather than 'M'
745 so that the released button can be reported.
746 - Numbers are no longer offset by 32. */
748 btn
= ev
->x
= ev
->y
= 0;
749 ev
->type
= 0; /* In case we return on an invalid sequence */
750 while ((c
= tty_lowlevel_getch ()) != ';')
752 if (c
< '0' || c
> '9')
754 btn
= 10 * btn
+ (c
- '0');
756 while ((c
= tty_lowlevel_getch ()) != ';')
758 if (c
< '0' || c
> '9')
760 ev
->x
= 10 * ev
->x
+ (c
- '0');
762 while ((c
= tty_lowlevel_getch ()) != 'M' && c
!= 'm')
764 if (c
< '0' || c
> '9')
766 ev
->y
= 10 * ev
->y
+ (c
- '0');
768 /* Legacy mouse protocol doesn't tell which button was released,
769 conveniently all of mc's widgets are written not to rely on this
770 information. With the SGR extension the released button becomes
771 known, but for the sake of simplicity we just ignore it. */
776 /* There seems to be no way of knowing which button was released */
777 /* So we assume all the buttons were released */
783 if ((last_btn
& (GPM_B_UP
| GPM_B_DOWN
)) != 0)
785 /* FIXME: DIRTY HACK */
786 /* don't generate GPM_UP after mouse wheel */
787 /* need for menu event handling */
794 ev
->type
= GPM_UP
| (GPM_SINGLE
<< clicks
);
803 /* Bogus event, maybe mouse wheel */
809 if (btn
>= 32 && btn
<= 34)
818 if (tv1
.tv_sec
&& (DIF_TIME (tv1
, tv2
) < double_click_speed
))
829 ev
->buttons
= GPM_B_LEFT
;
832 ev
->buttons
= GPM_B_MIDDLE
;
835 ev
->buttons
= GPM_B_RIGHT
;
838 ev
->buttons
= GPM_B_UP
;
842 ev
->buttons
= GPM_B_DOWN
;
851 last_btn
= ev
->buttons
;
855 /* --------------------------------------------------------------------------------------------- */
857 * Get modifier state (shift, alt, ctrl) for the last key pressed.
858 * We are assuming that the state didn't change since the key press.
859 * This is only correct if get_modifier() is called very fast after
860 * the input was received, so that the user didn't release the
870 static int in_photon
= 0;
871 static int ph_ig
= 0;
872 PhCursorInfo_t cursor_info
;
873 #endif /* __QNXNTO__ */
875 #ifdef HAVE_TEXTMODE_X11_SUPPORT
883 mc_XQueryPointer (x11_display
, x11_window
, &root
, &child
, &root_x
,
884 &root_y
, &win_x
, &win_y
, &mask
);
886 if (mask
& ShiftMask
)
887 result
|= KEY_M_SHIFT
;
888 if (mask
& ControlMask
)
889 result
|= KEY_M_CTRL
;
892 #endif /* HAVE_TEXTMODE_X11_SUPPORT */
897 /* First time here, let's load Photon library and attach
900 if (getenv ("PHOTON2_PATH") != NULL
)
902 /* QNX 6.x has no support for RTLD_LAZY */
903 void *ph_handle
= dlopen ("/usr/lib/libph.so", RTLD_NOW
);
904 if (ph_handle
!= NULL
)
906 ph_attach
= (ph_dv_f
) dlsym (ph_handle
, "PhAttach");
907 ph_input_group
= (ph_ov_f
) dlsym (ph_handle
, "PhInputGroup");
908 ph_query_cursor
= (ph_pqc_f
) dlsym (ph_handle
, "PhQueryCursor");
909 if ((ph_attach
!= NULL
) && (ph_input_group
!= NULL
) && (ph_query_cursor
!= NULL
))
911 if ((*ph_attach
) (0, 0))
913 ph_ig
= (*ph_input_group
) (0);
920 /* We do not have Photon running. Assume we are in text
924 int shift_ext_status
;
926 if (devctl (fileno (stdin
), DCMD_CHR_LINESTATUS
, &mod_status
, sizeof (mod_status
), NULL
) ==
930 shift_ext_status
= mod_status
& 0xffffff00UL
;
932 if (mod_status
& _LINESTATUS_CON_ALT
)
934 if (mod_status
& _LINESTATUS_CON_CTRL
)
935 result
|= KEY_M_CTRL
;
936 if ((mod_status
& _LINESTATUS_CON_SHIFT
) || (shift_ext_status
& 0x00000800UL
))
937 result
|= KEY_M_SHIFT
;
941 (*ph_query_cursor
) (ph_ig
, &cursor_info
);
942 if (cursor_info
.key_mods
& 0x04)
944 if (cursor_info
.key_mods
& 0x02)
945 result
|= KEY_M_CTRL
;
946 if (cursor_info
.key_mods
& 0x01)
947 result
|= KEY_M_SHIFT
;
949 #endif /* __QNXNTO__ */
951 #if defined __linux__ || (defined __CYGWIN__ && defined TIOCLINUX)
953 unsigned char modifiers
= 6;
955 if (ioctl (0, TIOCLINUX
, &modifiers
) < 0)
958 /* Translate Linux modifiers into mc modifiers */
959 if (modifiers
& SHIFT_PRESSED
)
960 result
|= KEY_M_SHIFT
;
961 if (modifiers
& (ALTL_PRESSED
| ALTR_PRESSED
))
963 if (modifiers
& CONTROL_PRESSED
)
964 result
|= KEY_M_CTRL
;
966 #endif /* !__linux__ */
970 /* --------------------------------------------------------------------------------------------- */
975 gboolean ret
= FALSE
;
977 if (seq_append
== NULL
)
978 seq_append
= seq_buffer
;
980 if (seq_append
!= &(seq_buffer
[SEQ_BUFFER_LEN
- 2]))
990 /* --------------------------------------------------------------------------------------------- */
991 /* Apply corrections for the keycode generated in get_key_code() */
994 correct_key_code (int code
)
996 unsigned int c
= code
& ~KEY_M_MASK
; /* code without modifier */
997 unsigned int mod
= code
& KEY_M_MASK
; /* modifier */
999 unsigned int qmod
; /* bunch of the QNX console
1000 modifiers needs unchanged */
1001 #endif /* __QNXNTO__ */
1004 * Add key modifiers directly from X11 or OS.
1005 * Ordinary characters only get modifiers from sequences.
1007 if (c
< 32 || c
>= 256)
1009 mod
|= get_modifier ();
1012 /* This is needed if the newline is reported as carriage return */
1016 /* This is reported to be useful on AIX */
1017 if (c
== KEY_SCANCEL
)
1020 /* Convert Back Tab to Shift+Tab */
1027 /* F0 is the same as F10 for out purposes */
1032 * We are not interested if Ctrl was pressed when entering control
1033 * characters, so assume that it was. When checking for such keys,
1034 * XCTRL macro should be used. In some cases, we are interested,
1035 * e.g. to distinguish Ctrl-Enter from Enter.
1039 /* Special case for backspase ('\b' < 32) */
1043 else if (c
< 32 && c
!= ESC_CHAR
&& c
!= '\t' && c
!= '\n')
1049 qmod
= get_modifier ();
1051 if ((c
== 127) && (mod
== 0))
1052 { /* Add Ctrl/Alt/Shift-BackSpace */
1053 mod
|= get_modifier ();
1057 if ((c
== '0') && (mod
== 0))
1058 { /* Add Shift-Insert on key pad */
1059 if ((qmod
& KEY_M_SHIFT
) == KEY_M_SHIFT
)
1066 if ((c
== '.') && (mod
== 0))
1067 { /* Add Shift-Del on key pad */
1068 if ((qmod
& KEY_M_SHIFT
) == KEY_M_SHIFT
)
1074 #endif /* __QNXNTO__ */
1076 /* Unrecognized 0177 is delete (preserve Ctrl) */
1083 /* Unrecognized Ctrl-d is delete */
1084 if (c
== (31 & 'd'))
1090 /* Unrecognized Ctrl-h is backspace */
1091 if (c
== (31 & 'h'))
1098 /* Shift+BackSpace is backspace */
1099 if (c
== KEY_BACKSPACE
&& (mod
& KEY_M_SHIFT
))
1101 mod
&= ~KEY_M_SHIFT
;
1104 /* Convert Shift+Fn to F(n+10) */
1105 if (c
>= KEY_F (1) && c
<= KEY_F (10) && (mod
& KEY_M_SHIFT
))
1110 /* Remove Shift information from function keys */
1111 if (c
>= KEY_F (1) && c
<= KEY_F (20))
1113 mod
&= ~KEY_M_SHIFT
;
1116 if (!mc_global
.tty
.alternate_plus_minus
)
1122 case KEY_KP_SUBTRACT
:
1125 case KEY_KP_MULTIPLY
:
1135 /* --------------------------------------------------------------------------------------------- */
1138 getch_with_timeout (unsigned int delay_us
)
1142 struct timeval time_out
;
1144 time_out
.tv_sec
= delay_us
/ 1000000u;
1145 time_out
.tv_usec
= delay_us
% 1000000u;
1147 FD_ZERO (&Read_FD_Set
);
1148 FD_SET (input_fd
, &Read_FD_Set
);
1149 select (input_fd
+ 1, &Read_FD_Set
, NULL
, NULL
, &time_out
);
1150 c
= tty_lowlevel_getch ();
1151 tty_nodelay (FALSE
);
1155 /* --------------------------------------------------------------------------------------------- */
1158 learn_store_key (char *buffer
, char **p
, int c
)
1160 if (*p
- buffer
> 253)
1170 *(*p
)++ = c
+ 'a' - 1;
1181 /* --------------------------------------------------------------------------------------------- */
1184 k_dispose (key_def
* k
)
1188 k_dispose (k
->child
);
1189 k_dispose (k
->next
);
1194 /* --------------------------------------------------------------------------------------------- */
1197 s_dispose (SelectList
* sel
)
1201 s_dispose (sel
->next
);
1206 /* --------------------------------------------------------------------------------------------- */
1209 key_code_comparator_by_name (const void *p1
, const void *p2
)
1211 const key_code_name_t
*n1
= *(const key_code_name_t
**) p1
;
1212 const key_code_name_t
*n2
= *(const key_code_name_t
**) p2
;
1214 return g_ascii_strcasecmp (n1
->name
, n2
->name
);
1217 /* --------------------------------------------------------------------------------------------- */
1220 key_code_comparator_by_code (const void *p1
, const void *p2
)
1222 const key_code_name_t
*n1
= *(const key_code_name_t
**) p1
;
1223 const key_code_name_t
*n2
= *(const key_code_name_t
**) p2
;
1225 return n1
->code
- n2
->code
;
1228 /* --------------------------------------------------------------------------------------------- */
1231 sort_key_conv_tab (enum KeySortType type_sort
)
1233 if (has_been_sorted
!= type_sort
)
1236 for (i
= 0; i
< key_conv_tab_size
; i
++)
1237 key_conv_tab_sorted
[i
] = &key_name_conv_tab
[i
];
1239 if (type_sort
== KEY_SORTBYNAME
)
1241 qsort (key_conv_tab_sorted
, key_conv_tab_size
, sizeof (key_conv_tab_sorted
[0]),
1242 &key_code_comparator_by_name
);
1244 else if (type_sort
== KEY_SORTBYCODE
)
1246 qsort (key_conv_tab_sorted
, key_conv_tab_size
, sizeof (key_conv_tab_sorted
[0]),
1247 &key_code_comparator_by_code
);
1249 has_been_sorted
= type_sort
;
1253 /* --------------------------------------------------------------------------------------------- */
1256 lookup_keyname (const char *name
, int *idx
)
1258 if (name
[0] != '\0')
1260 const key_code_name_t key
= { 0, name
, NULL
, NULL
};
1261 const key_code_name_t
*keyp
= &key
;
1262 key_code_name_t
**res
;
1264 if (name
[1] == '\0')
1267 return (int) name
[0];
1270 sort_key_conv_tab (KEY_SORTBYNAME
);
1272 res
= bsearch (&keyp
, key_conv_tab_sorted
, key_conv_tab_size
,
1273 sizeof (key_conv_tab_sorted
[0]), key_code_comparator_by_name
);
1277 *idx
= (int) (res
- (key_code_name_t
**) key_conv_tab_sorted
);
1278 return (*res
)->code
;
1286 /* --------------------------------------------------------------------------------------------- */
1289 lookup_keycode (const long code
, int *idx
)
1293 const key_code_name_t key
= { code
, NULL
, NULL
, NULL
};
1294 const key_code_name_t
*keyp
= &key
;
1295 key_code_name_t
**res
;
1297 sort_key_conv_tab (KEY_SORTBYCODE
);
1299 res
= bsearch (&keyp
, key_conv_tab_sorted
, key_conv_tab_size
,
1300 sizeof (key_conv_tab_sorted
[0]), key_code_comparator_by_code
);
1304 *idx
= (int) (res
- (key_code_name_t
**) key_conv_tab_sorted
);
1313 /* --------------------------------------------------------------------------------------------- */
1314 /*** public functions ****************************************************************************/
1315 /* --------------------------------------------------------------------------------------------- */
1316 /* This has to be called before init_slang or whatever routine
1317 calls any define_sequence */
1322 const char *term
= getenv ("TERM");
1324 /* This has to be the first define_sequence */
1325 /* So, we can assume that the first keys member has ESC */
1326 define_sequences (mc_default_keys
);
1328 /* Terminfo on irix does not have some keys */
1329 if (mc_global
.tty
.xterm_flag
1331 && (strncmp (term
, "iris-ansi", 9) == 0
1332 || strncmp (term
, "xterm", 5) == 0
1333 || strncmp (term
, "rxvt", 4) == 0 || strncmp (term
, "screen", 6) == 0)))
1334 define_sequences (xterm_key_defines
);
1336 /* load some additional keys (e.g. direct Alt-? support) */
1337 load_xtra_key_defines ();
1340 if ((term
!= NULL
) && (strncmp (term
, "qnx", 3) == 0))
1342 /* Modify the default value of use_8th_bit_as_meta: we would
1343 * like to provide a working mc for a newbie who knows nothing
1344 * about [Options|Display bits|Full 8 bits input]...
1346 * Don't use 'meta'-bit, when we are dealing with a
1347 * 'qnx*'-type terminal: clear the default value!
1348 * These terminal types use 0xFF as an escape character,
1349 * so use_8th_bit_as_meta==1 must not be enabled!
1351 * [mc-4.1.21+,slint.c/getch(): the DEC_8BIT_HACK stuff
1352 * is not used now (doesn't even depend on use_8th_bit_as_meta
1353 * as in mc-3.1.2)...GREAT!...no additional code is required!]
1355 use_8th_bit_as_meta
= 0;
1357 #endif /* __QNX__ */
1359 #ifdef HAVE_TEXTMODE_X11_SUPPORT
1363 /* Load the qansi-m key definitions
1364 if we are running under the qansi-m terminal */
1365 if (term
!= NULL
&& (strncmp (term
, "qansi-m", 7) == 0))
1366 define_sequences (qansi_key_defines
);
1369 /* --------------------------------------------------------------------------------------------- */
1371 * This has to be called after SLang_init_tty/slint_init
1375 init_key_input_fd (void)
1378 input_fd
= SLang_TT_Read_FD
;
1382 /* --------------------------------------------------------------------------------------------- */
1388 s_dispose (select_list
);
1390 #ifdef HAVE_TEXTMODE_X11_SUPPORT
1392 mc_XCloseDisplay (x11_display
);
1396 /* --------------------------------------------------------------------------------------------- */
1399 add_select_channel (int fd
, select_fn callback
, void *info
)
1403 new = g_new (SelectList
, 1);
1405 new->callback
= callback
;
1407 new->next
= select_list
;
1411 /* --------------------------------------------------------------------------------------------- */
1414 delete_select_channel (int fd
)
1416 SelectList
*p
= select_list
;
1417 SelectList
*p_prev
= NULL
;
1426 p_prev
->next
= p_next
;
1428 select_list
= p_next
;
1440 /* --------------------------------------------------------------------------------------------- */
1445 if (disabled_channels
== 0)
1446 fputs ("Error: channels_up called with disabled_channels = 0\n", stderr
);
1447 disabled_channels
--;
1450 /* --------------------------------------------------------------------------------------------- */
1453 channels_down (void)
1455 disabled_channels
++;
1458 /* --------------------------------------------------------------------------------------------- */
1460 * Return the code associated with the symbolic name keyname
1464 lookup_key (const char *name
, char **label
)
1466 char **lc_keys
, **p
;
1478 name
= g_strstrip (g_strdup (name
));
1479 lc_keys
= g_strsplit_set (name
, "-+ ", -1);
1480 g_free ((char *) name
);
1482 for (p
= lc_keys
; p
!= NULL
&& *p
!= NULL
; p
++)
1484 if ((*p
)[0] != '\0')
1488 key
= lookup_keyname (g_strstrip (*p
), &idx
);
1490 if (key
== KEY_M_ALT
)
1492 else if (key
== KEY_M_CTRL
)
1494 else if (key
== KEY_M_SHIFT
)
1505 g_strfreev (lc_keys
);
1515 s
= g_string_new ("");
1519 g_string_append (s
, key_conv_tab_sorted
[use_meta
]->shortcut
);
1520 g_string_append_c (s
, '-');
1524 g_string_append (s
, key_conv_tab_sorted
[use_ctrl
]->shortcut
);
1525 g_string_append_c (s
, '-');
1527 if (use_shift
!= -1)
1530 g_string_append_c (s
, (gchar
) g_ascii_toupper ((gchar
) k
));
1533 g_string_append (s
, key_conv_tab_sorted
[use_shift
]->shortcut
);
1534 g_string_append_c (s
, '-');
1535 g_string_append (s
, key_conv_tab_sorted
[lc_index
]->shortcut
);
1540 if ((k
>= 'A') || (lc_index
< 0) || (key_conv_tab_sorted
[lc_index
]->shortcut
== NULL
))
1541 g_string_append_c (s
, (gchar
) g_ascii_tolower ((gchar
) k
));
1543 g_string_append (s
, key_conv_tab_sorted
[lc_index
]->shortcut
);
1545 else if ((lc_index
!= -1) && (key_conv_tab_sorted
[lc_index
]->shortcut
!= NULL
))
1546 g_string_append (s
, key_conv_tab_sorted
[lc_index
]->shortcut
);
1548 g_string_append_c (s
, (gchar
) g_ascii_tolower ((gchar
) key
));
1550 *label
= g_string_free (s
, FALSE
);
1553 if (use_shift
!= -1)
1555 if (k
< 127 && k
> 31)
1556 k
= g_ascii_toupper ((gchar
) k
);
1575 /* --------------------------------------------------------------------------------------------- */
1578 lookup_key_by_code (const int keycode
)
1580 /* code without modifier */
1581 unsigned int k
= keycode
& ~KEY_M_MASK
;
1583 unsigned int mod
= keycode
& KEY_M_MASK
;
1590 s
= g_string_sized_new (8);
1592 if (lookup_keycode (k
, &key_idx
) || (k
> 0 && k
< 256))
1594 if (mod
& KEY_M_ALT
)
1596 if (lookup_keycode (KEY_M_ALT
, &idx
))
1598 g_string_append (s
, key_conv_tab_sorted
[idx
]->name
);
1599 g_string_append_c (s
, '-');
1602 if (mod
& KEY_M_CTRL
)
1604 /* non printeble chars like a CTRL-[A..Z] */
1608 if (lookup_keycode (KEY_M_CTRL
, &idx
))
1610 g_string_append (s
, key_conv_tab_sorted
[idx
]->name
);
1611 g_string_append_c (s
, '-');
1614 if (mod
& KEY_M_SHIFT
)
1616 if (lookup_keycode (KEY_M_ALT
, &idx
))
1619 g_string_append_c (s
, (gchar
) g_ascii_toupper ((gchar
) k
));
1622 g_string_append (s
, key_conv_tab_sorted
[idx
]->name
);
1623 g_string_append_c (s
, '-');
1624 g_string_append (s
, key_conv_tab_sorted
[key_idx
]->name
);
1630 if ((k
>= 'A') || (key_idx
< 0) || (key_conv_tab_sorted
[key_idx
]->name
== NULL
))
1631 g_string_append_c (s
, (gchar
) k
);
1633 g_string_append (s
, key_conv_tab_sorted
[key_idx
]->name
);
1635 else if ((key_idx
!= -1) && (key_conv_tab_sorted
[key_idx
]->name
!= NULL
))
1636 g_string_append (s
, key_conv_tab_sorted
[key_idx
]->name
);
1638 g_string_append_c (s
, (gchar
) keycode
);
1641 return g_string_free (s
, s
->len
== 0);
1644 /* --------------------------------------------------------------------------------------------- */
1646 * Return TRUE on success, FALSE on error.
1647 * An error happens if SEQ is a beginning of an existing longer sequence.
1651 define_sequence (int code
, const char *seq
, int action
)
1655 if (strlen (seq
) > SEQ_BUFFER_LEN
- 1)
1658 for (base
= keys
; (base
!= NULL
) && (*seq
!= '\0');)
1659 if (*seq
== base
->ch
)
1661 if (base
->child
== 0)
1663 if (*(seq
+ 1) != '\0')
1664 base
->child
= create_sequence (seq
+ 1, code
, action
);
1667 /* The sequence matches an existing one. */
1669 base
->action
= action
;
1683 base
->next
= create_sequence (seq
, code
, action
);
1690 /* Attempt to redefine a sequence with a shorter sequence. */
1694 keys
= create_sequence (seq
, code
, action
);
1698 /* --------------------------------------------------------------------------------------------- */
1700 * Check if we are idle, i.e. there are no pending keyboard or mouse
1701 * events. Return 1 is idle, 0 is there are pending events.
1708 struct timeval time_out
;
1710 FD_ZERO (&select_set
);
1711 FD_SET (input_fd
, &select_set
);
1712 nfd
= max (0, input_fd
) + 1;
1713 time_out
.tv_sec
= 0;
1714 time_out
.tv_usec
= 0;
1716 if (mouse_enabled
&& use_mouse_p
== MOUSE_GPM
)
1720 FD_SET (gpm_fd
, &select_set
);
1721 nfd
= max (nfd
, gpm_fd
+ 1);
1725 if (mouse_fd
>= 0) /* error indicative */
1727 if (FD_ISSET (mouse_fd
, &select_set
))
1728 FD_CLR (mouse_fd
, &select_set
);
1731 /* gpm_fd == -2 means under some X terminal */
1734 mouse_enabled
= FALSE
;
1735 use_mouse_p
= MOUSE_NONE
;
1740 return (select (nfd
, &select_set
, 0, 0, &time_out
) <= 0);
1743 /* --------------------------------------------------------------------------------------------- */
1746 get_key_code (int no_delay
)
1749 static key_def
*this = NULL
, *parent
;
1750 static struct timeval esctime
= { -1, -1 };
1751 static int lastnodelay
= -1;
1753 if (no_delay
!= lastnodelay
)
1756 lastnodelay
= no_delay
;
1760 if (pending_keys
!= NULL
)
1765 d
= *pending_keys
++;
1766 while (d
== ESC_CHAR
)
1767 d
= ALT (*pending_keys
++);
1769 bad_seq
= (*pending_keys
!= ESC_CHAR
&& *pending_keys
!= 0);
1770 if (*pending_keys
== '\0' || bad_seq
)
1771 pending_keys
= seq_append
= NULL
;
1775 /* This is an unknown ESC sequence.
1776 * To prevent interpreting its tail as a random garbage,
1777 * eat and discard all buffered and quickly following chars.
1778 * Small, but non-zero timeout is needed to reconnect
1779 * escape sequence split up by e.g. a serial line.
1783 while (getch_with_timeout (old_esc_mode_timeout
) >= 0 && --paranoia
!= 0)
1785 goto nodelay_try_again
;
1788 if (d
> 127 && d
< 256 && use_8th_bit_as_meta
)
1792 return correct_key_code (d
);
1799 c
= tty_lowlevel_getch ();
1800 #if (defined(USE_NCURSES) || defined(USE_NCURSESW)) && defined(KEY_RESIZE)
1801 if (c
== KEY_RESIZE
)
1802 goto nodelay_try_again
;
1806 tty_nodelay (FALSE
);
1809 if (this != NULL
&& parent
!= NULL
&& parent
->action
== MCKEY_ESCAPE
&& old_esc_mode
)
1811 struct timeval current
, time_out
;
1813 if (esctime
.tv_sec
== -1)
1816 time_out
.tv_sec
= old_esc_mode_timeout
/ 1000000 + esctime
.tv_sec
;
1817 time_out
.tv_usec
= old_esc_mode_timeout
% 1000000 + esctime
.tv_usec
;
1818 if (time_out
.tv_usec
> 1000000)
1820 time_out
.tv_usec
-= 1000000;
1823 if (current
.tv_sec
< time_out
.tv_sec
)
1825 if (current
.tv_sec
== time_out
.tv_sec
&& current
.tv_usec
< time_out
.tv_usec
)
1828 pending_keys
= seq_append
= NULL
;
1836 /* Maybe we got an incomplete match.
1837 This we do only in delay mode, since otherwise
1838 tty_lowlevel_getch can return -1 at any time. */
1839 if (seq_append
!= NULL
)
1841 pending_keys
= seq_buffer
;
1848 /* Search the key on the root */
1849 if (!no_delay
|| this == NULL
)
1854 if ((c
> 127 && c
< 256) && use_8th_bit_as_meta
)
1858 /* The first sequence defined starts with esc */
1864 while (this != NULL
)
1868 if (this->child
== NULL
)
1870 /* We got a complete match, return and reset search */
1873 pending_keys
= seq_append
= NULL
;
1876 return correct_key_code (code
);
1878 /* No match yet, but it may be a prefix for a valid seq */
1881 pending_keys
= seq_buffer
;
1886 if (parent
->action
== MCKEY_ESCAPE
&& old_esc_mode
)
1891 goto nodelay_try_again
;
1893 esctime
.tv_sec
= -1;
1894 c
= getch_with_timeout (old_esc_mode_timeout
);
1897 pending_keys
= seq_append
= NULL
;
1904 goto nodelay_try_again
;
1905 c
= tty_lowlevel_getch ();
1909 /* c != this->ch. Try other keys with this prefix */
1910 if (this->next
!= NULL
)
1916 /* No match found. Is it one of our ESC <key> specials? */
1917 if ((parent
!= NULL
) && (parent
->action
== MCKEY_ESCAPE
))
1919 /* Convert escape-digits to F-keys */
1920 if (g_ascii_isdigit (c
))
1921 c
= KEY_F (c
- '0');
1927 pending_keys
= seq_append
= NULL
;
1929 return correct_key_code (c
);
1932 /* Unknown sequence. Maybe a prefix of a longer one. Save it. */
1934 pending_keys
= seq_buffer
;
1937 } /* while (this != NULL) */
1940 return correct_key_code (c
);
1943 /* --------------------------------------------------------------------------------------------- */
1944 /* Returns a character read from stdin with appropriate interpretation */
1945 /* Also takes care of generated mouse events */
1946 /* Returns EV_MOUSE if it is a mouse event */
1947 /* Returns EV_NONE if non-blocking or interrupt set and nothing was done */
1950 tty_get_event (struct Gpm_Event
*event
, gboolean redo_event
, gboolean block
)
1953 int flag
= 0; /* Return value from select */
1955 static struct Gpm_Event ev
; /* Mouse event */
1957 struct timeval time_out
;
1958 struct timeval
*time_addr
= NULL
;
1959 static int dirty
= 3;
1961 if ((dirty
== 3) || is_idle ())
1969 vfs_timeout_handler ();
1971 /* Ok, we use (event->x < 0) to signal that the event does not contain
1972 a suitable position for the mouse, so we can't use show_mouse_pointer
1977 show_mouse_pointer (event
->x
, event
->y
);
1982 /* Repeat if using mouse */
1983 while (pending_keys
== NULL
)
1988 FD_ZERO (&select_set
);
1989 FD_SET (input_fd
, &select_set
);
1990 nfd
= max (add_selects (&select_set
), max (0, input_fd
)) + 1;
1993 if (mouse_enabled
&& (use_mouse_p
== MOUSE_GPM
))
1997 FD_SET (gpm_fd
, &select_set
);
1998 nfd
= max (nfd
, gpm_fd
+ 1);
2002 if (mouse_fd
>= 0) /* error indicative */
2004 if (FD_ISSET (mouse_fd
, &select_set
))
2005 FD_CLR (mouse_fd
, &select_set
);
2008 /* gpm_fd == -2 means under some X terminal */
2011 mouse_enabled
= FALSE
;
2012 use_mouse_p
= MOUSE_NONE
;
2021 time_out
.tv_usec
= mou_auto_repeat
* 1000;
2022 time_out
.tv_sec
= 0;
2024 time_addr
= &time_out
;
2030 seconds
= vfs_timeouts ();
2035 /* the timeout could be improved and actually be
2036 * the number of seconds until the next vfs entry
2037 * timeouts in the stamp list.
2040 time_out
.tv_sec
= seconds
;
2041 time_out
.tv_usec
= 0;
2042 time_addr
= &time_out
;
2046 if (!block
|| mc_global
.tty
.winch_flag
!= 0)
2048 time_addr
= &time_out
;
2049 time_out
.tv_sec
= 0;
2050 time_out
.tv_usec
= 0;
2053 tty_enable_interrupt_key ();
2054 flag
= select (nfd
, &select_set
, NULL
, NULL
, time_addr
);
2055 tty_disable_interrupt_key ();
2057 /* select timed out: it could be for any of the following reasons:
2058 * redo_event -> it was because of the MOU_REPEAT handler
2059 * !block -> we did not block in the select call
2060 * else -> 10 second timeout to check the vfs status.
2066 if (!block
|| mc_global
.tty
.winch_flag
!= 0)
2068 vfs_timeout_handler ();
2070 if (flag
== -1 && errno
== EINTR
)
2073 check_selects (&select_set
);
2075 if (FD_ISSET (input_fd
, &select_set
))
2078 if (mouse_enabled
&& use_mouse_p
== MOUSE_GPM
)
2082 if (FD_ISSET (gpm_fd
, &select_set
))
2086 status
= Gpm_GetEvent (&ev
);
2087 if (status
== 1) /* success */
2093 else if (status
== 0) /* connection closed; -1 == error */
2095 if (mouse_fd
>= 0 && FD_ISSET (mouse_fd
, &select_set
))
2096 FD_CLR (mouse_fd
, &select_set
);
2098 /* Try to reopen gpm_mouse connection */
2106 if (mouse_fd
>= 0) /* error indicative */
2108 if (FD_ISSET (mouse_fd
, &select_set
))
2109 FD_CLR (mouse_fd
, &select_set
);
2112 /* gpm_fd == -2 means under some X terminal */
2115 mouse_enabled
= FALSE
;
2116 use_mouse_p
= MOUSE_NONE
;
2121 #endif /* !HAVE_LIBGPM */
2125 flag
= is_wintouched (stdscr
);
2126 untouchwin (stdscr
);
2127 #endif /* !HAVE_SLANG */
2128 c
= block
? getch_with_delay () : get_key_code (1);
2132 tty_touch_screen ();
2133 #endif /* !HAVE_SLANG */
2135 if (mouse_enabled
&& (c
== MCKEY_MOUSE
2138 #endif /* KEY_MOUSE */
2139 || c
== MCKEY_EXTENDED_MOUSE
))
2142 xmouse_get_event (event
, c
== MCKEY_EXTENDED_MOUSE
);
2143 c
= (event
->type
!= 0) ? EV_MOUSE
: EV_NONE
;
2145 else if (c
== MCKEY_BRACKETED_PASTING_START
)
2147 bracketed_pasting_in_progress
= TRUE
;
2150 else if (c
== MCKEY_BRACKETED_PASTING_END
)
2152 bracketed_pasting_in_progress
= FALSE
;
2159 /* --------------------------------------------------------------------------------------------- */
2160 /* Returns a key press, mouse events are discarded */
2169 while ((key
= tty_get_event (&ev
, FALSE
, TRUE
)) == EV_NONE
);
2173 /* --------------------------------------------------------------------------------------------- */
2178 /* LEARN_TIMEOUT in usec */
2179 #define LEARN_TIMEOUT 200000
2182 struct timeval endtime
;
2183 struct timeval time_out
;
2188 tty_keypad (FALSE
); /* disable intepreting keys by ncurses */
2189 c
= tty_lowlevel_getch ();
2191 c
= tty_lowlevel_getch (); /* Sanity check, should be unnecessary */
2192 learn_store_key (buffer
, &p
, c
);
2194 endtime
.tv_usec
+= LEARN_TIMEOUT
;
2195 if (endtime
.tv_usec
> 1000000)
2197 endtime
.tv_usec
-= 1000000;
2203 while ((c
= tty_lowlevel_getch ()) == -1)
2205 GET_TIME (time_out
);
2206 time_out
.tv_usec
= endtime
.tv_usec
- time_out
.tv_usec
;
2207 if (time_out
.tv_usec
< 0)
2209 time_out
.tv_sec
= endtime
.tv_sec
- time_out
.tv_sec
;
2210 if (time_out
.tv_sec
>= 0 && time_out
.tv_usec
> 0)
2212 FD_ZERO (&Read_FD_Set
);
2213 FD_SET (input_fd
, &Read_FD_Set
);
2214 select (input_fd
+ 1, &Read_FD_Set
, NULL
, NULL
, &time_out
);
2221 learn_store_key (buffer
, &p
, c
);
2224 tty_nodelay (FALSE
);
2226 return g_strdup (buffer
);
2227 #undef LEARN_TIMEOUT
2230 /* --------------------------------------------------------------------------------------------- */
2231 /* xterm and linux console only: set keypad to numeric or application
2232 mode. Only in application keypad mode it's possible to distinguish
2233 the '+' key and the '+' on the keypad ('*' and '-' ditto) */
2236 numeric_keypad_mode (void)
2238 if (mc_global
.tty
.console_flag
!= '\0' || mc_global
.tty
.xterm_flag
)
2240 fputs (ESC_STR
">", stdout
);
2245 /* --------------------------------------------------------------------------------------------- */
2248 application_keypad_mode (void)
2250 if (mc_global
.tty
.console_flag
!= '\0' || mc_global
.tty
.xterm_flag
)
2252 fputs (ESC_STR
"=", stdout
);
2257 /* --------------------------------------------------------------------------------------------- */
2260 enable_bracketed_paste (void)
2262 printf (ESC_STR
"[?2004h");
2266 /* --------------------------------------------------------------------------------------------- */
2269 disable_bracketed_paste (void)
2271 printf (ESC_STR
"[?2004l");
2273 bracketed_pasting_in_progress
= FALSE
;
2276 /* --------------------------------------------------------------------------------------------- */