2 Keyboard support routines.
4 Copyright (C) 1994-2024
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
43 #ifdef HAVE_SYS_SELECT_H
44 #include <sys/select.h>
47 #include <sys/types.h>
51 #include "lib/global.h"
53 #include "lib/vfs/vfs.h"
56 #include "tty-internal.h" /* mouse_enabled */
60 #include "lib/widget.h" /* mc_refresh() */
62 #ifdef HAVE_TEXTMODE_X11_SUPPORT
67 #if defined(__GLIBC__) && (__GLIBC__ < 2)
68 #include <linux/termios.h> /* TIOCLINUX */
72 #ifdef HAVE_SYS_IOCTL_H
73 #include <sys/ioctl.h>
75 #endif /* __linux__ */
79 #ifdef HAVE_SYS_IOCTL_H
80 #include <sys/ioctl.h>
82 #endif /* __CYGWIN__ */
87 #include <sys/dcmd_chr.h>
88 #endif /* __QNXNTO__ */
90 /*** global variables ****************************************************************************/
92 int mou_auto_repeat
= 100; /* ms */
93 int double_click_speed
= 250; /* ms */
94 gboolean old_esc_mode
= TRUE
;
95 /* timeout for old_esc_mode in usec */
96 int old_esc_mode_timeout
= G_USEC_PER_SEC
; /* us, settable via env */
97 gboolean use_8th_bit_as_meta
= FALSE
;
99 gboolean bracketed_pasting_in_progress
= FALSE
;
101 /* This table is a mapping between names and the constants we use
102 * We use this to allow users to define alternate definitions for
103 * certain keys that may be missing from the terminal database
105 const key_code_name_t key_name_conv_tab
[] = {
106 {ESC_CHAR
, "escape", N_("Escape"), "Esc"},
107 /* KEY_F(0) is not here, since we are mapping it to f10, so there is no reason
108 to define f0 as well. Also, it makes Learn keys a bunch of problems :( */
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"), "+"},
147 /* From here on, these won't be shown in Learn keys (no space) */
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"},
166 /* Alternative label */
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 /* TRANSLATORS: Please translate as in "at sign" (@). */
208 {(int) '@', "at", N_("At sign"), "@"},
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"},
218 {0, NULL
, NULL
, NULL
}
221 /*** file scope macro definitions ****************************************************************/
223 #define MC_USEC_PER_MSEC 1000
225 /* The maximum sequence length (32 + null terminator) */
226 #define SEQ_BUFFER_LEN 33
228 /*** file scope type declarations ****************************************************************/
230 /* Linux console keyboard modifiers */
233 SHIFT_PRESSED
= (1 << 0),
234 ALTR_PRESSED
= (1 << 1),
235 CONTROL_PRESSED
= (1 << 2),
236 ALTL_PRESSED
= (1 << 3)
239 typedef struct key_def
241 char ch
; /* Holds the matching char code */
242 int code
; /* The code returned, valid if child == NULL */
243 struct key_def
*next
;
244 struct key_def
*child
; /* sequence continuation */
245 int action
; /* optional action to be done. Now used only
246 to mark that we are just after the first
257 /* File descriptor monitoring add/remove routines */
265 typedef enum KeySortType
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
*);
278 /*** forward declarations (file scope functions) *************************************************/
280 /*** file scope variables ************************************************************************/
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
},
290 /* Broken terminfo and termcap databases on xterminals */
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
},
307 /* old xterm Shift-arrows */
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
},
313 /* new xterm Shift-arrows */
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
},
319 /* more xterm keys with modifiers */
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
},
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
},
346 /* putty alt-arrow keys */
347 /* removed as source esc esc esc trouble */
349 { KEY_M_ALT | KEY_UP, ESC_STR ESC_STR "OA", MCKEY_NOACTION },
350 { KEY_M_ALT | KEY_DOWN, ESC_STR ESC_STR "OB", MCKEY_NOACTION },
351 { KEY_M_ALT | KEY_RIGHT, ESC_STR ESC_STR "OC", MCKEY_NOACTION },
352 { KEY_M_ALT | KEY_LEFT, ESC_STR ESC_STR "OD", MCKEY_NOACTION },
353 { KEY_M_ALT | KEY_PPAGE, ESC_STR ESC_STR "[5~", MCKEY_NOACTION },
354 { KEY_M_ALT | KEY_NPAGE, ESC_STR ESC_STR "[6~", MCKEY_NOACTION },
355 { KEY_M_ALT | KEY_HOME, ESC_STR ESC_STR "[1~", MCKEY_NOACTION },
356 { KEY_M_ALT | KEY_END, ESC_STR ESC_STR "[4~", MCKEY_NOACTION },
358 { KEY_M_CTRL | KEY_M_ALT | KEY_UP, ESC_STR ESC_STR "[1;2A", MCKEY_NOACTION },
359 { KEY_M_CTRL | KEY_M_ALT | KEY_DOWN, ESC_STR ESC_STR "[1;2B", MCKEY_NOACTION },
360 { KEY_M_CTRL | KEY_M_ALT | KEY_RIGHT, ESC_STR ESC_STR "[1;2C", MCKEY_NOACTION },
361 { KEY_M_CTRL | KEY_M_ALT | KEY_LEFT, ESC_STR ESC_STR "[1;2D", MCKEY_NOACTION },
363 { KEY_M_CTRL | KEY_M_ALT | KEY_PPAGE, ESC_STR ESC_STR "[[5;5~", MCKEY_NOACTION },
364 { KEY_M_CTRL | KEY_M_ALT | KEY_NPAGE, ESC_STR ESC_STR "[[6;5~", MCKEY_NOACTION },
365 { KEY_M_CTRL | KEY_M_ALT | KEY_HOME, ESC_STR ESC_STR "[1;5H", MCKEY_NOACTION },
366 { KEY_M_CTRL | KEY_M_ALT | KEY_END, ESC_STR ESC_STR "[1;5F", MCKEY_NOACTION },
368 /* xterm alt-arrow keys */
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
},
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
},
391 /* rxvt keys with modifiers */
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
},
410 /* konsole keys with modifiers */
411 {KEY_M_SHIFT
| KEY_HOME
, ESC_STR
"O2H", MCKEY_NOACTION
},
412 {KEY_M_SHIFT
| KEY_END
, ESC_STR
"O2F", MCKEY_NOACTION
},
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
},
428 /* gnome-terminal - application mode */
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
},
439 {KEY_M_SHIFT
| KEY_PPAGE
, ESC_STR
"[5;2~", MCKEY_NOACTION
},
440 {KEY_M_SHIFT
| KEY_NPAGE
, ESC_STR
"[6;2~", MCKEY_NOACTION
},
443 {KEY_M_SHIFT
| KEY_PPAGE
, ESC_STR
"[[5;53~", MCKEY_NOACTION
},
444 {KEY_M_SHIFT
| KEY_NPAGE
, ESC_STR
"[[6;53~", MCKEY_NOACTION
},
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
},
452 {0, NULL
, MCKEY_NOACTION
},
455 /* qansi-m terminals have a much more key combinations,
456 which are undefined in termcap/terminfo */
457 static key_define_t qansi_key_defines
[] = {
458 /* qansi-m terminal */
459 {KEY_M_CTRL
| KEY_NPAGE
, ESC_STR
"[u", MCKEY_NOACTION
}, /* Ctrl-PgDown */
460 {KEY_M_CTRL
| KEY_PPAGE
, ESC_STR
"[v", MCKEY_NOACTION
}, /* Ctrl-PgUp */
461 {KEY_M_CTRL
| KEY_HOME
, ESC_STR
"[h", MCKEY_NOACTION
}, /* Ctrl-Home */
462 {KEY_M_CTRL
| KEY_END
, ESC_STR
"[y", MCKEY_NOACTION
}, /* Ctrl-End */
463 {KEY_M_CTRL
| KEY_IC
, ESC_STR
"[`", MCKEY_NOACTION
}, /* Ctrl-Insert */
464 {KEY_M_CTRL
| KEY_DC
, ESC_STR
"[p", MCKEY_NOACTION
}, /* Ctrl-Delete */
465 {KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"[d", MCKEY_NOACTION
}, /* Ctrl-Left */
466 {KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"[c", MCKEY_NOACTION
}, /* Ctrl-Right */
467 {KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"[b", MCKEY_NOACTION
}, /* Ctrl-Down */
468 {KEY_M_CTRL
| KEY_UP
, ESC_STR
"[a", MCKEY_NOACTION
}, /* Ctrl-Up */
469 {KEY_M_CTRL
| KEY_KP_ADD
, ESC_STR
"[s", MCKEY_NOACTION
}, /* Ctrl-Gr-Plus */
470 {KEY_M_CTRL
| KEY_KP_SUBTRACT
, ESC_STR
"[t", MCKEY_NOACTION
}, /* Ctrl-Gr-Minus */
471 {KEY_M_CTRL
| '\t', ESC_STR
"[z", MCKEY_NOACTION
}, /* Ctrl-Tab */
472 {KEY_M_SHIFT
| '\t', ESC_STR
"[Z", MCKEY_NOACTION
}, /* Shift-Tab */
473 {KEY_M_CTRL
| KEY_F (1), ESC_STR
"[1~", MCKEY_NOACTION
}, /* Ctrl-F1 */
474 {KEY_M_CTRL
| KEY_F (2), ESC_STR
"[2~", MCKEY_NOACTION
}, /* Ctrl-F2 */
475 {KEY_M_CTRL
| KEY_F (3), ESC_STR
"[3~", MCKEY_NOACTION
}, /* Ctrl-F3 */
476 {KEY_M_CTRL
| KEY_F (4), ESC_STR
"[4~", MCKEY_NOACTION
}, /* Ctrl-F4 */
477 {KEY_M_CTRL
| KEY_F (5), ESC_STR
"[5~", MCKEY_NOACTION
}, /* Ctrl-F5 */
478 {KEY_M_CTRL
| KEY_F (6), ESC_STR
"[6~", MCKEY_NOACTION
}, /* Ctrl-F6 */
479 {KEY_M_CTRL
| KEY_F (7), ESC_STR
"[7~", MCKEY_NOACTION
}, /* Ctrl-F7 */
480 {KEY_M_CTRL
| KEY_F (8), ESC_STR
"[8~", MCKEY_NOACTION
}, /* Ctrl-F8 */
481 {KEY_M_CTRL
| KEY_F (9), ESC_STR
"[9~", MCKEY_NOACTION
}, /* Ctrl-F9 */
482 {KEY_M_CTRL
| KEY_F (10), ESC_STR
"[10~", MCKEY_NOACTION
}, /* Ctrl-F10 */
483 {KEY_M_CTRL
| KEY_F (11), ESC_STR
"[11~", MCKEY_NOACTION
}, /* Ctrl-F11 */
484 {KEY_M_CTRL
| KEY_F (12), ESC_STR
"[12~", MCKEY_NOACTION
}, /* Ctrl-F12 */
485 {KEY_M_ALT
| KEY_F (1), ESC_STR
"[17~", MCKEY_NOACTION
}, /* Alt-F1 */
486 {KEY_M_ALT
| KEY_F (2), ESC_STR
"[18~", MCKEY_NOACTION
}, /* Alt-F2 */
487 {KEY_M_ALT
| KEY_F (3), ESC_STR
"[19~", MCKEY_NOACTION
}, /* Alt-F3 */
488 {KEY_M_ALT
| KEY_F (4), ESC_STR
"[20~", MCKEY_NOACTION
}, /* Alt-F4 */
489 {KEY_M_ALT
| KEY_F (5), ESC_STR
"[21~", MCKEY_NOACTION
}, /* Alt-F5 */
490 {KEY_M_ALT
| KEY_F (6), ESC_STR
"[22~", MCKEY_NOACTION
}, /* Alt-F6 */
491 {KEY_M_ALT
| KEY_F (7), ESC_STR
"[23~", MCKEY_NOACTION
}, /* Alt-F7 */
492 {KEY_M_ALT
| KEY_F (8), ESC_STR
"[24~", MCKEY_NOACTION
}, /* Alt-F8 */
493 {KEY_M_ALT
| KEY_F (9), ESC_STR
"[25~", MCKEY_NOACTION
}, /* Alt-F9 */
494 {KEY_M_ALT
| KEY_F (10), ESC_STR
"[26~", MCKEY_NOACTION
}, /* Alt-F10 */
495 {KEY_M_ALT
| KEY_F (11), ESC_STR
"[27~", MCKEY_NOACTION
}, /* Alt-F11 */
496 {KEY_M_ALT
| KEY_F (12), ESC_STR
"[28~", MCKEY_NOACTION
}, /* Alt-F12 */
497 {KEY_M_ALT
| 'a', ESC_STR
"Na", MCKEY_NOACTION
}, /* Alt-a */
498 {KEY_M_ALT
| 'b', ESC_STR
"Nb", MCKEY_NOACTION
}, /* Alt-b */
499 {KEY_M_ALT
| 'c', ESC_STR
"Nc", MCKEY_NOACTION
}, /* Alt-c */
500 {KEY_M_ALT
| 'd', ESC_STR
"Nd", MCKEY_NOACTION
}, /* Alt-d */
501 {KEY_M_ALT
| 'e', ESC_STR
"Ne", MCKEY_NOACTION
}, /* Alt-e */
502 {KEY_M_ALT
| 'f', ESC_STR
"Nf", MCKEY_NOACTION
}, /* Alt-f */
503 {KEY_M_ALT
| 'g', ESC_STR
"Ng", MCKEY_NOACTION
}, /* Alt-g */
504 {KEY_M_ALT
| 'h', ESC_STR
"Nh", MCKEY_NOACTION
}, /* Alt-h */
505 {KEY_M_ALT
| 'i', ESC_STR
"Ni", MCKEY_NOACTION
}, /* Alt-i */
506 {KEY_M_ALT
| 'j', ESC_STR
"Nj", MCKEY_NOACTION
}, /* Alt-j */
507 {KEY_M_ALT
| 'k', ESC_STR
"Nk", MCKEY_NOACTION
}, /* Alt-k */
508 {KEY_M_ALT
| 'l', ESC_STR
"Nl", MCKEY_NOACTION
}, /* Alt-l */
509 {KEY_M_ALT
| 'm', ESC_STR
"Nm", MCKEY_NOACTION
}, /* Alt-m */
510 {KEY_M_ALT
| 'n', ESC_STR
"Nn", MCKEY_NOACTION
}, /* Alt-n */
511 {KEY_M_ALT
| 'o', ESC_STR
"No", MCKEY_NOACTION
}, /* Alt-o */
512 {KEY_M_ALT
| 'p', ESC_STR
"Np", MCKEY_NOACTION
}, /* Alt-p */
513 {KEY_M_ALT
| 'q', ESC_STR
"Nq", MCKEY_NOACTION
}, /* Alt-q */
514 {KEY_M_ALT
| 'r', ESC_STR
"Nr", MCKEY_NOACTION
}, /* Alt-r */
515 {KEY_M_ALT
| 's', ESC_STR
"Ns", MCKEY_NOACTION
}, /* Alt-s */
516 {KEY_M_ALT
| 't', ESC_STR
"Nt", MCKEY_NOACTION
}, /* Alt-t */
517 {KEY_M_ALT
| 'u', ESC_STR
"Nu", MCKEY_NOACTION
}, /* Alt-u */
518 {KEY_M_ALT
| 'v', ESC_STR
"Nv", MCKEY_NOACTION
}, /* Alt-v */
519 {KEY_M_ALT
| 'w', ESC_STR
"Nw", MCKEY_NOACTION
}, /* Alt-w */
520 {KEY_M_ALT
| 'x', ESC_STR
"Nx", MCKEY_NOACTION
}, /* Alt-x */
521 {KEY_M_ALT
| 'y', ESC_STR
"Ny", MCKEY_NOACTION
}, /* Alt-y */
522 {KEY_M_ALT
| 'z', ESC_STR
"Nz", MCKEY_NOACTION
}, /* Alt-z */
523 {KEY_KP_SUBTRACT
, ESC_STR
"[S", MCKEY_NOACTION
}, /* Gr-Minus */
524 {KEY_KP_ADD
, ESC_STR
"[T", MCKEY_NOACTION
}, /* Gr-Plus */
525 {0, NULL
, MCKEY_NOACTION
},
528 /* This holds all the key definitions */
529 static key_def
*keys
= NULL
;
532 static int disabled_channels
= 0; /* Disable channels checking */
534 static GSList
*select_list
= NULL
;
536 static int seq_buffer
[SEQ_BUFFER_LEN
];
537 static int *seq_append
= NULL
;
539 static int *pending_keys
= NULL
;
543 ph_ov_f ph_input_group
;
544 ph_pqc_f ph_query_cursor
;
547 #ifdef HAVE_TEXTMODE_X11_SUPPORT
548 static Display
*x11_display
;
549 static Window x11_window
;
550 #endif /* HAVE_TEXTMODE_X11_SUPPORT */
552 static KeySortType has_been_sorted
= KEY_NOSORT
;
555 static const size_t key_conv_tab_size
= G_N_ELEMENTS (key_name_conv_tab
) - 1;
558 static const key_code_name_t
*key_conv_tab_sorted
[G_N_ELEMENTS (key_name_conv_tab
) - 1];
560 /* --------------------------------------------------------------------------------------------- */
561 /*** file scope functions ************************************************************************/
562 /* --------------------------------------------------------------------------------------------- */
565 select_cmp_by_fd_set (gconstpointer a
, gconstpointer b
)
567 const select_t
*s
= (const select_t
*) a
;
568 const fd_set
*f
= (const fd_set
*) b
;
570 return (FD_ISSET (s
->fd
, f
) ? 0 : 1);
573 /* --------------------------------------------------------------------------------------------- */
576 select_cmp_by_fd (gconstpointer a
, gconstpointer b
)
578 const select_t
*s
= (const select_t
*) a
;
579 const int fd
= GPOINTER_TO_INT (b
);
581 return (s
->fd
== fd
? 0 : 1);
584 /* --------------------------------------------------------------------------------------------- */
587 add_selects (fd_set
*select_set
)
591 if (disabled_channels
== 0)
595 for (s
= select_list
; s
!= NULL
; s
= g_slist_next (s
))
597 select_t
*p
= (select_t
*) s
->data
;
599 FD_SET (p
->fd
, select_set
);
608 /* --------------------------------------------------------------------------------------------- */
611 check_selects (fd_set
*select_set
)
613 while (disabled_channels
== 0)
618 s
= g_slist_find_custom (select_list
, select_set
, select_cmp_by_fd_set
);
622 p
= (select_t
*) s
->data
;
623 FD_CLR (p
->fd
, select_set
);
624 p
->callback (p
->fd
, p
->info
);
628 /* --------------------------------------------------------------------------------------------- */
629 /* If set timeout is set, then we wait 0.1 seconds, else, we block */
632 try_channels (gboolean set_timeout
)
634 struct timeval time_out
;
635 static fd_set select_set
;
639 struct timeval
*timeptr
= NULL
;
642 FD_ZERO (&select_set
);
643 FD_SET (input_fd
, &select_set
); /* Add stdin */
644 maxfdp
= MAX (add_selects (&select_set
), input_fd
);
649 time_out
.tv_usec
= 100 * MC_USEC_PER_MSEC
;
653 v
= select (maxfdp
+ 1, &select_set
, NULL
, NULL
, timeptr
);
656 check_selects (&select_set
);
657 if (FD_ISSET (input_fd
, &select_set
))
663 /* --------------------------------------------------------------------------------------------- */
666 create_sequence (const char *seq
, int code
, int action
)
668 key_def
*base
, *attach
;
670 for (base
= attach
= NULL
; *seq
!= '\0'; seq
++)
674 p
= g_new (key_def
, 1);
684 p
->action
= seq
[1] == '\0' ? action
: MCKEY_NOACTION
;
690 /* --------------------------------------------------------------------------------------------- */
693 define_sequences (const key_define_t
*kd
)
697 for (i
= 0; kd
[i
].code
!= 0; i
++)
698 define_sequence (kd
[i
].code
, kd
[i
].seq
, kd
[i
].action
);
701 /* --------------------------------------------------------------------------------------------- */
703 #ifdef HAVE_TEXTMODE_X11_SUPPORT
707 if (getenv ("DISPLAY") != NULL
&& !mc_global
.tty
.disable_x11
)
709 x11_display
= mc_XOpenDisplay (0);
711 if (x11_display
!= NULL
)
712 x11_window
= DefaultRootWindow (x11_display
);
715 #endif /* HAVE_TEXTMODE_X11_SUPPORT */
717 /* --------------------------------------------------------------------------------------------- */
718 /* Workaround for System V Curses vt100 bug */
721 getch_with_delay (void)
725 /* This routine could be used on systems without mouse support,
726 so we need to do the select check :-( */
729 if (pending_keys
== NULL
)
730 try_channels (FALSE
);
732 /* Try to get a character */
733 c
= get_key_code (0);
737 /* Failed -> wait 0.1 secs and try again */
741 /* Success -> return the character */
745 /* --------------------------------------------------------------------------------------------- */
748 xmouse_get_event (Gpm_Event
*ev
, gboolean extended
)
750 static gint64 tv1
= 0; /* Force first click as single */
751 static int clicks
= 0;
752 static int last_btn
= 0;
755 /* Decode Xterm mouse information to a GPM style event */
759 /* Variable btn has following meaning: */
760 /* 0 = btn1 dn, 1 = btn2 dn, 2 = btn3 dn, 3 = btn up */
761 btn
= tty_lowlevel_getch () - 32;
762 /* Coordinates are 33-based */
763 /* Transform them to 1-based */
764 ev
->x
= tty_lowlevel_getch () - 32;
765 ev
->y
= tty_lowlevel_getch () - 32;
769 /* SGR 1006 extension (e.g. "\e[<0;12;300M"):
770 - Numbers are encoded in decimal to make it ASCII-safe
771 and to overcome the limit of 223 columns/rows.
772 - Mouse release is encoded by trailing 'm' rather than 'M'
773 so that the released button can be reported.
774 - Numbers are no longer offset by 32. */
777 btn
= ev
->x
= ev
->y
= 0;
778 ev
->type
= 0; /* In case we return on an invalid sequence */
780 while ((c
= tty_lowlevel_getch ()) != ';')
782 if (c
< '0' || c
> '9')
784 btn
= 10 * btn
+ (c
- '0');
786 while ((c
= tty_lowlevel_getch ()) != ';')
788 if (c
< '0' || c
> '9')
790 ev
->x
= 10 * ev
->x
+ (c
- '0');
792 while ((c
= tty_lowlevel_getch ()) != 'M' && c
!= 'm')
794 if (c
< '0' || c
> '9')
796 ev
->y
= 10 * ev
->y
+ (c
- '0');
798 /* Legacy mouse protocol doesn't tell which button was released,
799 conveniently all of mc's widgets are written not to rely on this
800 information. With the SGR extension the released button becomes
801 known, but for the sake of simplicity we just ignore it. */
806 /* There seems to be no way of knowing which button was released */
807 /* So we assume all the buttons were released */
813 if ((last_btn
& (GPM_B_UP
| GPM_B_DOWN
)) != 0)
815 /* FIXME: DIRTY HACK */
816 /* don't generate GPM_UP after mouse wheel */
817 /* need for menu event handling */
823 ev
->type
= GPM_UP
| (GPM_SINGLE
<< clicks
);
824 tv1
= g_get_monotonic_time ();
832 /* Bogus event, maybe mouse wheel */
840 if (btn
>= 32 && btn
<= 34)
848 tv2
= g_get_monotonic_time ();
849 if (tv1
!= 0 && tv2
- tv1
< (gint64
) double_click_speed
* MC_USEC_PER_MSEC
)
860 ev
->buttons
= GPM_B_LEFT
;
863 ev
->buttons
= GPM_B_MIDDLE
;
866 ev
->buttons
= GPM_B_RIGHT
;
869 ev
->buttons
= GPM_B_UP
;
873 ev
->buttons
= GPM_B_DOWN
;
882 last_btn
= ev
->buttons
;
886 /* --------------------------------------------------------------------------------------------- */
888 * Get modifier state (shift, alt, ctrl) for the last key pressed.
889 * We are assuming that the state didn't change since the key press.
890 * This is only correct if get_modifier() is called very fast after
891 * the input was received, so that the user didn't release the
900 static int in_photon
= 0;
901 static int ph_ig
= 0;
902 #endif /* __QNXNTO__ */
904 #ifdef HAVE_TEXTMODE_X11_SUPPORT
912 mc_XQueryPointer (x11_display
, x11_window
, &root
, &child
, &root_x
,
913 &root_y
, &win_x
, &win_y
, &mask
);
915 if ((mask
& ShiftMask
) != 0)
916 result
|= KEY_M_SHIFT
;
917 if ((mask
& ControlMask
) != 0)
918 result
|= KEY_M_CTRL
;
921 #endif /* HAVE_TEXTMODE_X11_SUPPORT */
926 /* First time here, let's load Photon library and attach to Photon */
929 if (getenv ("PHOTON2_PATH") != NULL
)
931 /* QNX 6.x has no support for RTLD_LAZY */
934 ph_handle
= dlopen ("/usr/lib/libph.so", RTLD_NOW
);
935 if (ph_handle
!= NULL
)
937 ph_attach
= (ph_dv_f
) dlsym (ph_handle
, "PhAttach");
938 ph_input_group
= (ph_ov_f
) dlsym (ph_handle
, "PhInputGroup");
939 ph_query_cursor
= (ph_pqc_f
) dlsym (ph_handle
, "PhQueryCursor");
940 if ((ph_attach
!= NULL
) && (ph_input_group
!= NULL
) && (ph_query_cursor
!= NULL
)
941 && (*ph_attach
) (0, 0) != NULL
)
944 ph_ig
= (*ph_input_group
) (0);
950 /* We do not have Photon running. Assume we are in text console or xterm */
954 int shift_ext_status
;
956 if (devctl (fileno (stdin
), DCMD_CHR_LINESTATUS
, &mod_status
, sizeof (mod_status
), NULL
) ==
960 shift_ext_status
= mod_status
& 0xffffff00UL
;
962 if ((mod_status
& _LINESTATUS_CON_ALT
) != 0)
964 if ((mod_status
& _LINESTATUS_CON_CTRL
) != 0)
965 result
|= KEY_M_CTRL
;
966 if ((mod_status
& _LINESTATUS_CON_SHIFT
) != 0 || (shift_ext_status
& 0x00000800UL
) != 0)
967 result
|= KEY_M_SHIFT
;
971 PhCursorInfo_t cursor_info
;
973 (*ph_query_cursor
) (ph_ig
, &cursor_info
);
974 if ((cursor_info
.key_mods
& 0x04) != 0)
976 if ((cursor_info
.key_mods
& 0x02) != 0)
977 result
|= KEY_M_CTRL
;
978 if ((cursor_info
.key_mods
& 0x01) != 0)
979 result
|= KEY_M_SHIFT
;
981 #endif /* __QNXNTO__ */
983 #if defined __linux__ || (defined __CYGWIN__ && defined TIOCLINUX)
985 unsigned char modifiers
= 6;
987 if (ioctl (0, TIOCLINUX
, &modifiers
) < 0)
990 /* Translate Linux modifiers into mc modifiers */
991 if ((modifiers
& SHIFT_PRESSED
) != 0)
992 result
|= KEY_M_SHIFT
;
993 if ((modifiers
& (ALTL_PRESSED
| ALTR_PRESSED
)) != 0)
995 if ((modifiers
& CONTROL_PRESSED
) != 0)
996 result
|= KEY_M_CTRL
;
998 #endif /* !__linux__ */
1003 /* --------------------------------------------------------------------------------------------- */
1008 gboolean ret
= FALSE
;
1010 if (seq_append
== NULL
)
1011 seq_append
= seq_buffer
;
1013 if (seq_append
!= &(seq_buffer
[SEQ_BUFFER_LEN
- 2]))
1015 *(seq_append
++) = c
;
1023 /* --------------------------------------------------------------------------------------------- */
1024 /* Apply corrections for the keycode generated in get_key_code() */
1027 correct_key_code (int code
)
1029 unsigned int c
= code
& ~KEY_M_MASK
; /* code without modifier */
1030 unsigned int mod
= code
& KEY_M_MASK
; /* modifier */
1032 unsigned int qmod
; /* bunch of the QNX console
1033 modifiers needs unchanged */
1034 #endif /* __QNXNTO__ */
1037 * Add key modifiers directly from X11 or OS.
1038 * Ordinary characters only get modifiers from sequences.
1040 if (c
< 32 || c
>= 256)
1041 mod
|= get_modifier ();
1043 /* This is needed if the newline is reported as carriage return */
1047 /* This is reported to be useful on AIX */
1048 if (c
== KEY_SCANCEL
)
1051 /* Convert Back Tab to Shift+Tab */
1058 /* F0 is the same as F10 for out purposes */
1063 * We are not interested if Ctrl was pressed when entering control
1064 * characters, so assume that it was. When checking for such keys,
1065 * XCTRL macro should be used. In some cases, we are interested,
1066 * e.g. to distinguish Ctrl-Enter from Enter.
1070 /* Special case for backspase ('\b' < 32) */
1074 else if (c
< 32 && c
!= ESC_CHAR
&& c
!= '\t' && c
!= '\n')
1078 qmod
= get_modifier ();
1080 if (c
== 127 && mod
== 0)
1082 /* Add Ctrl/Alt/Shift-BackSpace */
1083 mod
|= get_modifier ();
1087 if (c
== '0' && mod
== 0 && (qmod
& KEY_M_SHIFT
) == KEY_M_SHIFT
)
1089 /* Add Shift-Insert on key pad */
1094 if (c
== '.' && mod
== 0 && (qmod
& KEY_M_SHIFT
) == KEY_M_SHIFT
)
1096 /* Add Shift-Del on key pad */
1100 #endif /* __QNXNTO__ */
1102 /* Unrecognized 0177 is delete (preserve Ctrl) */
1107 /* Unrecognized Ctrl-d is delete */
1114 /* Unrecognized Ctrl-h is backspace */
1122 /* Shift+BackSpace is backspace */
1123 if (c
== KEY_BACKSPACE
&& (mod
& KEY_M_SHIFT
) != 0)
1124 mod
&= ~KEY_M_SHIFT
;
1126 /* Convert Shift+Fn to F(n+10) */
1127 if (c
>= KEY_F (1) && c
<= KEY_F (10) && (mod
& KEY_M_SHIFT
) != 0)
1130 /* Remove Shift information from function keys */
1131 if (c
>= KEY_F (1) && c
<= KEY_F (20))
1132 mod
&= ~KEY_M_SHIFT
;
1134 if (!mc_global
.tty
.alternate_plus_minus
)
1140 case KEY_KP_SUBTRACT
:
1143 case KEY_KP_MULTIPLY
:
1153 /* --------------------------------------------------------------------------------------------- */
1156 getch_with_timeout (unsigned int delay_us
)
1160 struct timeval time_out
;
1162 time_out
.tv_sec
= delay_us
/ G_USEC_PER_SEC
;
1163 time_out
.tv_usec
= delay_us
% G_USEC_PER_SEC
;
1165 FD_ZERO (&Read_FD_Set
);
1166 FD_SET (input_fd
, &Read_FD_Set
);
1167 select (input_fd
+ 1, &Read_FD_Set
, NULL
, NULL
, &time_out
);
1168 c
= tty_lowlevel_getch ();
1169 tty_nodelay (FALSE
);
1173 /* --------------------------------------------------------------------------------------------- */
1176 learn_store_key (GString
*buffer
, int c
)
1179 g_string_append (buffer
, "\\e");
1182 g_string_append_c (buffer
, '^');
1183 g_string_append_c (buffer
, c
+ 'a' - 1);
1186 g_string_append (buffer
, "^^");
1188 g_string_append_c (buffer
, (char) c
);
1191 /* --------------------------------------------------------------------------------------------- */
1194 k_dispose (key_def
*k
)
1198 k_dispose (k
->child
);
1199 k_dispose (k
->next
);
1204 /* --------------------------------------------------------------------------------------------- */
1207 key_code_comparator_by_name (const void *p1
, const void *p2
)
1209 const key_code_name_t
*n1
= *(const key_code_name_t
* const *) p1
;
1210 const key_code_name_t
*n2
= *(const key_code_name_t
* const *) p2
;
1212 return g_ascii_strcasecmp (n1
->name
, n2
->name
);
1215 /* --------------------------------------------------------------------------------------------- */
1218 key_code_comparator_by_code (const void *p1
, const void *p2
)
1220 const key_code_name_t
*n1
= *(const key_code_name_t
* const *) p1
;
1221 const key_code_name_t
*n2
= *(const key_code_name_t
* const *) p2
;
1223 return n1
->code
- n2
->code
;
1226 /* --------------------------------------------------------------------------------------------- */
1229 sort_key_conv_tab (enum KeySortType type_sort
)
1231 if (has_been_sorted
!= type_sort
)
1235 for (i
= 0; i
< key_conv_tab_size
; i
++)
1236 key_conv_tab_sorted
[i
] = &key_name_conv_tab
[i
];
1238 if (type_sort
== KEY_SORTBYNAME
)
1239 qsort (key_conv_tab_sorted
, key_conv_tab_size
, sizeof (key_conv_tab_sorted
[0]),
1240 &key_code_comparator_by_name
);
1241 else if (type_sort
== KEY_SORTBYCODE
)
1242 qsort (key_conv_tab_sorted
, key_conv_tab_size
, sizeof (key_conv_tab_sorted
[0]),
1243 &key_code_comparator_by_code
);
1245 has_been_sorted
= type_sort
;
1249 /* --------------------------------------------------------------------------------------------- */
1252 lookup_keyname (const char *name
, int *idx
)
1254 if (name
[0] != '\0')
1256 const key_code_name_t key
= { 0, name
, NULL
, NULL
};
1257 const key_code_name_t
*keyp
= &key
;
1258 const key_code_name_t
**res
;
1260 if (name
[1] == '\0')
1263 return (int) name
[0];
1266 sort_key_conv_tab (KEY_SORTBYNAME
);
1268 res
= bsearch (&keyp
, key_conv_tab_sorted
, key_conv_tab_size
,
1269 sizeof (key_conv_tab_sorted
[0]), key_code_comparator_by_name
);
1273 *idx
= (int) (res
- key_conv_tab_sorted
);
1274 return (*res
)->code
;
1282 /* --------------------------------------------------------------------------------------------- */
1285 lookup_keycode (const long code
, int *idx
)
1289 const key_code_name_t key
= { code
, NULL
, NULL
, NULL
};
1290 const key_code_name_t
*keyp
= &key
;
1291 const key_code_name_t
**res
;
1293 sort_key_conv_tab (KEY_SORTBYCODE
);
1295 res
= bsearch (&keyp
, key_conv_tab_sorted
, key_conv_tab_size
,
1296 sizeof (key_conv_tab_sorted
[0]), key_code_comparator_by_code
);
1300 *idx
= (int) (res
- key_conv_tab_sorted
);
1309 /* --------------------------------------------------------------------------------------------- */
1310 /*** public functions ****************************************************************************/
1311 /* --------------------------------------------------------------------------------------------- */
1312 /* This has to be called before init_slang or whatever routine
1313 calls any define_sequence */
1320 term
= getenv ("TERM");
1322 /* This has to be the first define_sequence */
1323 /* So, we can assume that the first keys member has ESC */
1324 define_sequences (mc_default_keys
);
1326 /* Terminfo on irix does not have some keys */
1327 if (mc_global
.tty
.xterm_flag
1329 && (strncmp (term
, "iris-ansi", 9) == 0
1330 || strncmp (term
, "xterm", 5) == 0
1331 || strncmp (term
, "rxvt", 4) == 0 || strncmp (term
, "screen", 6) == 0)))
1332 define_sequences (xterm_key_defines
);
1334 /* load some additional keys (e.g. direct Alt-? support) */
1335 load_xtra_key_defines ();
1338 if ((term
!= NULL
) && (strncmp (term
, "qnx", 3) == 0))
1340 /* Modify the default value of use_8th_bit_as_meta: we would
1341 * like to provide a working mc for a newbie who knows nothing
1342 * about [Options|Display bits|Full 8 bits input]...
1344 * Don't use 'meta'-bit, when we are dealing with a
1345 * 'qnx*'-type terminal: clear the default value!
1346 * These terminal types use 0xFF as an escape character,
1347 * so use_8th_bit_as_meta==1 must not be enabled!
1349 * [mc-4.1.21+,slint.c/getch(): the DEC_8BIT_HACK stuff
1350 * is not used now (doesn't even depend on use_8th_bit_as_meta
1351 * as in mc-3.1.2)...GREAT!...no additional code is required!]
1353 use_8th_bit_as_meta
= FALSE
;
1355 #endif /* __QNX__ */
1357 #ifdef HAVE_TEXTMODE_X11_SUPPORT
1361 /* Load the qansi-m key definitions
1362 if we are running under the qansi-m terminal */
1363 if (term
!= NULL
&& (strncmp (term
, "qansi-m", 7) == 0))
1364 define_sequences (qansi_key_defines
);
1367 /* --------------------------------------------------------------------------------------------- */
1369 * This has to be called after SLang_init_tty/slint_init
1373 init_key_input_fd (void)
1376 input_fd
= SLang_TT_Read_FD
;
1380 /* --------------------------------------------------------------------------------------------- */
1386 g_slist_free_full (select_list
, g_free
);
1388 #ifdef HAVE_TEXTMODE_X11_SUPPORT
1390 mc_XCloseDisplay (x11_display
);
1394 /* --------------------------------------------------------------------------------------------- */
1397 add_select_channel (int fd
, select_fn callback
, void *info
)
1401 new = g_new (select_t
, 1);
1403 new->callback
= callback
;
1406 select_list
= g_slist_prepend (select_list
, new);
1409 /* --------------------------------------------------------------------------------------------- */
1412 delete_select_channel (int fd
)
1416 p
= g_slist_find_custom (select_list
, GINT_TO_POINTER (fd
), select_cmp_by_fd
);
1418 select_list
= g_slist_delete_link (select_list
, p
);
1421 /* --------------------------------------------------------------------------------------------- */
1426 if (disabled_channels
== 0)
1427 fputs ("Error: channels_up called with disabled_channels = 0\n", stderr
);
1428 disabled_channels
--;
1431 /* --------------------------------------------------------------------------------------------- */
1434 channels_down (void)
1436 disabled_channels
++;
1439 /* --------------------------------------------------------------------------------------------- */
1441 * Return the code associated with the symbolic name keyname
1445 tty_keyname_to_keycode (const char *name
, char **label
)
1447 char **lc_keys
, **p
;
1460 cname
= g_strstrip (g_strdup (name
));
1461 lc_keys
= g_strsplit_set (cname
, "-+ ", -1);
1464 for (p
= lc_keys
; p
!= NULL
&& *p
!= NULL
; p
++)
1466 if ((*p
)[0] != '\0')
1470 key
= lookup_keyname (g_strstrip (*p
), &idx
);
1472 if (key
== KEY_M_ALT
)
1474 else if (key
== KEY_M_CTRL
)
1476 else if (key
== KEY_M_SHIFT
)
1487 g_strfreev (lc_keys
);
1497 s
= g_string_new ("");
1501 g_string_append (s
, key_conv_tab_sorted
[use_meta
]->shortcut
);
1502 g_string_append_c (s
, '-');
1506 g_string_append (s
, key_conv_tab_sorted
[use_ctrl
]->shortcut
);
1507 g_string_append_c (s
, '-');
1509 if (use_shift
!= -1)
1512 g_string_append_c (s
, (gchar
) g_ascii_toupper ((gchar
) k
));
1515 g_string_append (s
, key_conv_tab_sorted
[use_shift
]->shortcut
);
1516 g_string_append_c (s
, '-');
1517 g_string_append (s
, key_conv_tab_sorted
[lc_index
]->shortcut
);
1522 if ((k
>= 'A') || (lc_index
< 0) || (key_conv_tab_sorted
[lc_index
]->shortcut
== NULL
))
1523 g_string_append_c (s
, (gchar
) g_ascii_tolower ((gchar
) k
));
1525 g_string_append (s
, key_conv_tab_sorted
[lc_index
]->shortcut
);
1527 else if ((lc_index
!= -1) && (key_conv_tab_sorted
[lc_index
]->shortcut
!= NULL
))
1528 g_string_append (s
, key_conv_tab_sorted
[lc_index
]->shortcut
);
1530 g_string_append_c (s
, (gchar
) g_ascii_tolower ((gchar
) key
));
1532 *label
= g_string_free (s
, FALSE
);
1535 if (use_shift
!= -1)
1537 if (k
< 127 && k
> 31)
1538 k
= g_ascii_toupper ((gchar
) k
);
1557 /* --------------------------------------------------------------------------------------------- */
1560 tty_keycode_to_keyname (const int keycode
)
1562 /* code without modifier */
1563 unsigned int k
= keycode
& ~KEY_M_MASK
;
1565 unsigned int mod
= keycode
& KEY_M_MASK
;
1572 s
= g_string_sized_new (8);
1574 if (lookup_keycode (k
, &key_idx
) || (k
> 0 && k
< 256))
1576 if ((mod
& KEY_M_ALT
) != 0 && lookup_keycode (KEY_M_ALT
, &idx
))
1578 g_string_append (s
, key_conv_tab_sorted
[idx
]->name
);
1579 g_string_append_c (s
, '-');
1582 if ((mod
& KEY_M_CTRL
) != 0)
1584 /* non printeble chars like a CTRL-[A..Z] */
1588 if (lookup_keycode (KEY_M_CTRL
, &idx
))
1590 g_string_append (s
, key_conv_tab_sorted
[idx
]->name
);
1591 g_string_append_c (s
, '-');
1595 if ((mod
& KEY_M_SHIFT
) != 0)
1597 if (lookup_keycode (KEY_M_ALT
, &idx
))
1600 g_string_append_c (s
, (gchar
) g_ascii_toupper ((gchar
) k
));
1603 g_string_append (s
, key_conv_tab_sorted
[idx
]->name
);
1604 g_string_append_c (s
, '-');
1605 g_string_append (s
, key_conv_tab_sorted
[key_idx
]->name
);
1611 if ((k
>= 'A') || (key_idx
< 0) || (key_conv_tab_sorted
[key_idx
]->name
== NULL
))
1612 g_string_append_c (s
, (gchar
) k
);
1614 g_string_append (s
, key_conv_tab_sorted
[key_idx
]->name
);
1616 else if ((key_idx
!= -1) && (key_conv_tab_sorted
[key_idx
]->name
!= NULL
))
1617 g_string_append (s
, key_conv_tab_sorted
[key_idx
]->name
);
1619 g_string_append_c (s
, (gchar
) keycode
);
1622 return g_string_free (s
, s
->len
== 0);
1625 /* --------------------------------------------------------------------------------------------- */
1627 * Return TRUE on success, FALSE on error.
1628 * An error happens if SEQ is a beginning of an existing longer sequence.
1632 define_sequence (int code
, const char *seq
, int action
)
1636 if (strlen (seq
) > SEQ_BUFFER_LEN
- 1)
1639 for (base
= keys
; (base
!= NULL
) && (*seq
!= '\0');)
1640 if (*seq
== base
->ch
)
1642 if (base
->child
== NULL
)
1644 if (*(seq
+ 1) != '\0')
1645 base
->child
= create_sequence (seq
+ 1, code
, action
);
1648 /* The sequence matches an existing one. */
1650 base
->action
= action
;
1660 if (base
->next
!= NULL
)
1664 base
->next
= create_sequence (seq
, code
, action
);
1671 /* Attempt to redefine a sequence with a shorter sequence. */
1675 keys
= create_sequence (seq
, code
, action
);
1679 /* --------------------------------------------------------------------------------------------- */
1681 * Check if we are idle, i.e. there are no pending keyboard or mouse
1682 * events. Return 1 is idle, 0 is there are pending events.
1689 struct timeval time_out
;
1691 FD_ZERO (&select_set
);
1692 FD_SET (input_fd
, &select_set
);
1693 nfd
= MAX (0, input_fd
) + 1;
1694 time_out
.tv_sec
= 0;
1695 time_out
.tv_usec
= 0;
1697 if (mouse_enabled
&& use_mouse_p
== MOUSE_GPM
)
1701 FD_SET (gpm_fd
, &select_set
);
1702 nfd
= MAX (nfd
, gpm_fd
+ 1);
1706 if (mouse_fd
>= 0) /* error indicative */
1708 if (FD_ISSET (mouse_fd
, &select_set
))
1709 FD_CLR (mouse_fd
, &select_set
);
1712 /* gpm_fd == -2 means under some X terminal */
1715 mouse_enabled
= FALSE
;
1716 use_mouse_p
= MOUSE_NONE
;
1721 return (select (nfd
, &select_set
, 0, 0, &time_out
) <= 0);
1724 /* --------------------------------------------------------------------------------------------- */
1727 get_key_code (int no_delay
)
1730 static key_def
*this = NULL
, *parent
;
1731 static gint64 esc_time
= -1;
1732 static int lastnodelay
= -1;
1734 if (no_delay
!= lastnodelay
)
1737 lastnodelay
= no_delay
;
1741 if (pending_keys
!= NULL
)
1745 c
= *pending_keys
++;
1746 while (c
== ESC_CHAR
)
1747 c
= ALT (*pending_keys
++);
1749 bad_seq
= (*pending_keys
!= ESC_CHAR
&& *pending_keys
!= '\0');
1750 if (*pending_keys
== '\0' || bad_seq
)
1751 pending_keys
= seq_append
= NULL
;
1755 /* This is an unknown ESC sequence.
1756 * To prevent interpreting its tail as a random garbage,
1757 * eat and discard all buffered and quickly following chars.
1758 * Small, but non-zero timeout is needed to reconnect
1759 * escape sequence split up by e.g. a serial line.
1763 while (getch_with_timeout (old_esc_mode_timeout
) >= 0 && --paranoia
!= 0)
1768 if (c
> 127 && c
< 256 && use_8th_bit_as_meta
)
1779 c
= tty_lowlevel_getch ();
1780 #if (defined(USE_NCURSES) || defined(USE_NCURSESW)) && defined(KEY_RESIZE)
1781 if (c
== KEY_RESIZE
)
1782 goto nodelay_try_again
;
1787 tty_nodelay (FALSE
);
1790 if (this == NULL
|| parent
== NULL
|| parent
->action
!= MCKEY_ESCAPE
|| !old_esc_mode
||
1791 esc_time
== -1 || g_get_monotonic_time () < esc_time
+ old_esc_mode_timeout
)
1795 pending_keys
= seq_append
= NULL
;
1801 /* Maybe we got an incomplete match.
1802 This we do only in delay mode, since otherwise
1803 tty_lowlevel_getch can return -1 at any time. */
1804 if (seq_append
== NULL
)
1810 pending_keys
= seq_buffer
;
1814 /* Search the key on the root */
1815 if (no_delay
== 0 || this == NULL
)
1820 if (c
> 127 && c
< 256 && use_8th_bit_as_meta
)
1824 /* The first sequence defined starts with esc */
1830 while (this != NULL
)
1834 if (this->child
== NULL
)
1836 /* We got a complete match, return and reset search */
1837 pending_keys
= seq_append
= NULL
;
1842 /* No match yet, but it may be a prefix for a valid seq */
1845 pending_keys
= seq_buffer
;
1851 if (parent
->action
== MCKEY_ESCAPE
&& old_esc_mode
)
1855 esc_time
= g_get_monotonic_time ();
1856 goto nodelay_try_again
;
1860 c
= getch_with_timeout (old_esc_mode_timeout
);
1864 pending_keys
= seq_append
= NULL
;
1870 goto nodelay_try_again
;
1871 c
= tty_lowlevel_getch ();
1875 /* c != this->ch. Try other keys with this prefix */
1876 if (this->next
!= NULL
)
1882 /* No match found. Is it one of our ESC <key> specials? */
1883 if ((parent
!= NULL
) && (parent
->action
== MCKEY_ESCAPE
))
1885 /* Convert escape-digits to F-keys */
1886 if (g_ascii_isdigit (c
))
1887 c
= KEY_F (c
- '0');
1893 pending_keys
= seq_append
= NULL
;
1897 /* Unknown sequence. Maybe a prefix of a longer one. Save it. */
1899 pending_keys
= seq_buffer
;
1901 } /* while (this != NULL) */
1905 return correct_key_code (c
);
1908 /* --------------------------------------------------------------------------------------------- */
1909 /* Returns a character read from stdin with appropriate interpretation */
1910 /* Also takes care of generated mouse events */
1911 /* Returns EV_MOUSE if it is a mouse event */
1912 /* Returns EV_NONE if non-blocking or interrupt set and nothing was done */
1915 tty_get_event (struct Gpm_Event
*event
, gboolean redo_event
, gboolean block
)
1918 int flag
= 0; /* Return value from select */
1920 static struct Gpm_Event ev
; /* Mouse event */
1922 struct timeval time_out
;
1923 struct timeval
*time_addr
= NULL
;
1924 static int dirty
= 3;
1926 if ((dirty
== 3) || is_idle ())
1934 vfs_timeout_handler ();
1936 /* Ok, we use (event->x < 0) to signal that the event does not contain
1937 a suitable position for the mouse, so we can't use show_mouse_pointer
1942 show_mouse_pointer (event
->x
, event
->y
);
1947 /* Repeat if using mouse */
1948 while (pending_keys
== NULL
)
1953 FD_ZERO (&select_set
);
1954 FD_SET (input_fd
, &select_set
);
1955 nfd
= MAX (add_selects (&select_set
), MAX (0, input_fd
)) + 1;
1958 if (mouse_enabled
&& (use_mouse_p
== MOUSE_GPM
))
1962 FD_SET (gpm_fd
, &select_set
);
1963 nfd
= MAX (nfd
, gpm_fd
+ 1);
1967 if (mouse_fd
>= 0) /* error indicative */
1969 if (FD_ISSET (mouse_fd
, &select_set
))
1970 FD_CLR (mouse_fd
, &select_set
);
1973 /* gpm_fd == -2 means under some X terminal */
1976 mouse_enabled
= FALSE
;
1977 use_mouse_p
= MOUSE_NONE
;
1986 time_out
.tv_usec
= mou_auto_repeat
* MC_USEC_PER_MSEC
;
1987 time_out
.tv_sec
= 0;
1989 time_addr
= &time_out
;
1995 seconds
= vfs_timeouts ();
2000 /* the timeout could be improved and actually be
2001 * the number of seconds until the next vfs entry
2002 * timeouts in the stamp list.
2005 time_out
.tv_sec
= seconds
;
2006 time_out
.tv_usec
= 0;
2007 time_addr
= &time_out
;
2011 if (!block
|| tty_got_winch ())
2013 time_addr
= &time_out
;
2014 time_out
.tv_sec
= 0;
2015 time_out
.tv_usec
= 0;
2018 tty_enable_interrupt_key ();
2019 flag
= select (nfd
, &select_set
, NULL
, NULL
, time_addr
);
2020 tty_disable_interrupt_key ();
2022 /* select timed out: it could be for any of the following reasons:
2023 * redo_event -> it was because of the MOU_REPEAT handler
2024 * !block -> we did not block in the select call
2025 * else -> 10 second timeout to check the vfs status.
2031 if (!block
|| tty_got_winch ())
2033 vfs_timeout_handler ();
2035 if (flag
== -1 && errno
== EINTR
)
2038 check_selects (&select_set
);
2040 if (FD_ISSET (input_fd
, &select_set
))
2044 if (mouse_enabled
&& use_mouse_p
== MOUSE_GPM
)
2048 if (FD_ISSET (gpm_fd
, &select_set
))
2052 status
= Gpm_GetEvent (&ev
);
2053 if (status
== 1) /* success */
2059 if (status
<= 0) /* connection closed; -1 == error */
2061 if (mouse_fd
>= 0 && FD_ISSET (mouse_fd
, &select_set
))
2062 FD_CLR (mouse_fd
, &select_set
);
2071 if (mouse_fd
>= 0) /* error indicative */
2073 if (FD_ISSET (mouse_fd
, &select_set
))
2074 FD_CLR (mouse_fd
, &select_set
);
2077 /* gpm_fd == -2 means under some X terminal */
2080 mouse_enabled
= FALSE
;
2081 use_mouse_p
= MOUSE_NONE
;
2086 #endif /* !HAVE_LIBGPM */
2090 flag
= is_wintouched (stdscr
);
2091 untouchwin (stdscr
);
2092 #endif /* !HAVE_SLANG */
2093 c
= block
? getch_with_delay () : get_key_code (1);
2097 tty_touch_screen ();
2098 #endif /* !HAVE_SLANG */
2100 if (mouse_enabled
&& (c
== MCKEY_MOUSE
2103 #endif /* KEY_MOUSE */
2104 || c
== MCKEY_EXTENDED_MOUSE
))
2106 /* Mouse event. See tickets 2956 and 3954 for extended mode detection. */
2107 gboolean extended
= c
== MCKEY_EXTENDED_MOUSE
;
2110 extended
= extended
|| (c
== KEY_MOUSE
&& xmouse_seq
== NULL
2111 && xmouse_extended_seq
!= NULL
);
2112 #endif /* KEY_MOUSE */
2114 xmouse_get_event (event
, extended
);
2115 c
= (event
->type
!= 0) ? EV_MOUSE
: EV_NONE
;
2117 else if (c
== MCKEY_BRACKETED_PASTING_START
)
2119 bracketed_pasting_in_progress
= TRUE
;
2122 else if (c
== MCKEY_BRACKETED_PASTING_END
)
2124 bracketed_pasting_in_progress
= FALSE
;
2131 /* --------------------------------------------------------------------------------------------- */
2132 /* Returns a key press, mouse events are discarded */
2141 while ((key
= tty_get_event (&ev
, FALSE
, TRUE
)) == EV_NONE
)
2146 /* --------------------------------------------------------------------------------------------- */
2151 /* LEARN_TIMEOUT in ms */
2152 #define LEARN_TIMEOUT 200
2159 buffer
= g_string_sized_new (16);
2161 tty_keypad (FALSE
); /* disable interpreting keys by ncurses */
2162 c
= tty_lowlevel_getch ();
2164 c
= tty_lowlevel_getch (); /* Sanity check, should be unnecessary */
2165 learn_store_key (buffer
, c
);
2167 end_time
= g_get_monotonic_time () + LEARN_TIMEOUT
* MC_USEC_PER_MSEC
;
2172 while ((c
= tty_lowlevel_getch ()) == -1)
2177 time_out
= end_time
- g_get_monotonic_time ();
2181 tv
.tv_sec
= time_out
/ G_USEC_PER_SEC
;
2182 tv
.tv_usec
= time_out
% G_USEC_PER_SEC
;
2183 FD_ZERO (&Read_FD_Set
);
2184 FD_SET (input_fd
, &Read_FD_Set
);
2185 select (input_fd
+ 1, &Read_FD_Set
, NULL
, NULL
, &tv
);
2189 learn_store_key (buffer
, c
);
2192 tty_nodelay (FALSE
);
2194 return g_string_free (buffer
, buffer
->len
== 0);
2195 #undef LEARN_TIMEOUT
2198 /* --------------------------------------------------------------------------------------------- */
2199 /* xterm and linux console only: set keypad to numeric or application
2200 mode. Only in application keypad mode it's possible to distinguish
2201 the '+' key and the '+' on the keypad ('*' and '-' ditto) */
2204 numeric_keypad_mode (void)
2206 if (mc_global
.tty
.console_flag
!= '\0' || mc_global
.tty
.xterm_flag
)
2208 fputs (ESC_STR
">", stdout
);
2213 /* --------------------------------------------------------------------------------------------- */
2216 application_keypad_mode (void)
2218 if (mc_global
.tty
.console_flag
!= '\0' || mc_global
.tty
.xterm_flag
)
2220 fputs (ESC_STR
"=", stdout
);
2225 /* --------------------------------------------------------------------------------------------- */
2228 enable_bracketed_paste (void)
2230 printf (ESC_STR
"[?2004h");
2234 /* --------------------------------------------------------------------------------------------- */
2237 disable_bracketed_paste (void)
2239 printf (ESC_STR
"[?2004l");
2241 bracketed_pasting_in_progress
= FALSE
;
2244 /* --------------------------------------------------------------------------------------------- */