2 Keyboard support routines.
4 Copyright (C) 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
5 2005, 2006, 2007, 2009, 2010, 2011
6 The Free Software Foundation, Inc.
9 Miguel de Icaza, 1994, 1995
10 Janne Kukonlehto, 1994, 1995
14 This file is part of the Midnight Commander.
16 The Midnight Commander is free software: you can redistribute it
17 and/or modify it under the terms of the GNU General Public License as
18 published by the Free Software Foundation, either version 3 of the License,
19 or (at your option) any later version.
21 The Midnight Commander is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program. If not, see <http://www.gnu.org/licenses/>.
31 * \brief Source: keyboard support routines
42 #include <sys/types.h>
45 #include "lib/global.h"
47 #include "lib/vfs/vfs.h"
50 #include "tty-internal.h" /* mouse_enabled */
54 #include "lib/widget.h" /* mc_refresh() */
56 #ifdef HAVE_TEXTMODE_X11_SUPPORT
61 #if defined(__GLIBC__) && (__GLIBC__ < 2)
62 #include <linux/termios.h> /* TIOCLINUX */
66 #ifdef HAVE_SYS_IOCTL_H
67 #include <sys/ioctl.h>
69 #endif /* __linux__ */
73 #ifdef HAVE_SYS_IOCTL_H
74 #include <sys/ioctl.h>
76 #endif /* __CYGWIN__ */
81 #include <sys/dcmd_chr.h>
82 #endif /* __QNXNTO__ */
84 /*** global variables ****************************************************************************/
86 int mou_auto_repeat
= 100;
87 int double_click_speed
= 250;
89 /* timeout for old_esc_mode in usec */
90 int old_esc_mode_timeout
= 1000000; /* settable via env */
91 int use_8th_bit_as_meta
= 0;
93 /* This table is a mapping between names and the constants we use
94 * We use this to allow users to define alternate definitions for
95 * certain keys that may be missing from the terminal database
97 const key_code_name_t key_name_conv_tab
[] = {
98 /* KEY_F(0) is not here, since we are mapping it to f10, so there is no reason
99 to define f0 as well. Also, it makes Learn keys a bunch of problems :( */
100 {KEY_F (1), "f1", N_("Function key 1"), "F1"},
101 {KEY_F (2), "f2", N_("Function key 2"), "F2"},
102 {KEY_F (3), "f3", N_("Function key 3"), "F3"},
103 {KEY_F (4), "f4", N_("Function key 4"), "F4"},
104 {KEY_F (5), "f5", N_("Function key 5"), "F5"},
105 {KEY_F (6), "f6", N_("Function key 6"), "F6"},
106 {KEY_F (7), "f7", N_("Function key 7"), "F7"},
107 {KEY_F (8), "f8", N_("Function key 8"), "F8"},
108 {KEY_F (9), "f9", N_("Function key 9"), "F9"},
109 {KEY_F (10), "f10", N_("Function key 10"), "F10"},
110 {KEY_F (11), "f11", N_("Function key 11"), "F11"},
111 {KEY_F (12), "f12", N_("Function key 12"), "F12"},
112 {KEY_F (13), "f13", N_("Function key 13"), "F13"},
113 {KEY_F (14), "f14", N_("Function key 14"), "F14"},
114 {KEY_F (15), "f15", N_("Function key 15"), "F15"},
115 {KEY_F (16), "f16", N_("Function key 16"), "F16"},
116 {KEY_F (17), "f17", N_("Function key 17"), "F17"},
117 {KEY_F (18), "f18", N_("Function key 18"), "F18"},
118 {KEY_F (19), "f19", N_("Function key 19"), "F19"},
119 {KEY_F (20), "f20", N_("Function key 20"), "F20"},
120 {KEY_BACKSPACE
, "backspace", N_("Backspace key"), "Backspace"},
121 {KEY_END
, "end", N_("End key"), "End"},
122 {KEY_UP
, "up", N_("Up arrow key"), "Up"},
123 {KEY_DOWN
, "down", N_("Down arrow key"), "Down"},
124 {KEY_LEFT
, "left", N_("Left arrow key"), "Left"},
125 {KEY_RIGHT
, "right", N_("Right arrow key"), "Right"},
126 {KEY_HOME
, "home", N_("Home key"), "Home"},
127 {KEY_NPAGE
, "pgdn", N_("Page Down key"), "PgDn"},
128 {KEY_PPAGE
, "pgup", N_("Page Up key"), "PgUp"},
129 {KEY_IC
, "insert", N_("Insert key"), "Ins"},
130 {KEY_DC
, "delete", N_("Delete key"), "Del"},
131 {ALT ('\t'), "complete", N_("Completion/M-tab"), "Meta-Tab"},
132 {KEY_BTAB
, "backtab", N_("Back Tabulation S-tab"), "Shift-Tab"},
133 {KEY_KP_ADD
, "kpplus", N_("+ on keypad"), "+"},
134 {KEY_KP_SUBTRACT
, "kpminus", N_("- on keypad"), "-"},
135 {(int) '/', "kpslash", N_("Slash on keypad"), "/"},
136 {KEY_KP_MULTIPLY
, "kpasterisk", N_("* on keypad"), "*"},
138 /* From here on, these won't be shown in Learn keys (no space) */
139 {ESC_CHAR
, "escape", N_("Escape key"), "Esc"},
140 {KEY_LEFT
, "kpleft", N_("Left arrow keypad"), "Left"},
141 {KEY_RIGHT
, "kpright", N_("Right arrow keypad"), "Right"},
142 {KEY_UP
, "kpup", N_("Up arrow keypad"), "Up"},
143 {KEY_DOWN
, "kpdown", N_("Down arrow keypad"), "Down"},
144 {KEY_HOME
, "kphome", N_("Home on keypad"), "Home"},
145 {KEY_END
, "kpend", N_("End on keypad"), "End"},
146 {KEY_NPAGE
, "kpnpage", N_("Page Down keypad"), "PgDn"},
147 {KEY_PPAGE
, "kpppage", N_("Page Up keypad"), "PgUp"},
148 {KEY_IC
, "kpinsert", N_("Insert on keypad"), "Ins"},
149 {KEY_DC
, "kpdelete", N_("Delete on keypad"), "Del"},
150 {(int) '\n', "kpenter", N_("Enter on keypad"), "Enter"},
151 {KEY_F (21), "f21", N_("Function key 21"), "F21"},
152 {KEY_F (22), "f22", N_("Function key 22"), "F22"},
153 {KEY_F (23), "f23", N_("Function key 23"), "F23"},
154 {KEY_F (24), "f24", N_("Function key 24"), "F24"},
155 {KEY_A1
, "a1", N_("A1 key"), "A1"},
156 {KEY_C1
, "c1", N_("C1 key"), "C1"},
158 /* Alternative label */
159 {ESC_CHAR
, "esc", N_("Escape key"), "Esc"},
160 {KEY_BACKSPACE
, "bs", N_("Backspace key"), "Bakspace"},
161 {KEY_IC
, "ins", N_("Insert key"), "Ins"},
162 {KEY_DC
, "del", N_("Delete key"), "Del"},
163 {(int) '+', "plus", N_("Plus"), "+"},
164 {(int) '-', "minus", N_("Minus"), "-"},
165 {(int) '*', "asterisk", N_("Asterisk"), "*"},
166 {(int) '.', "dot", N_("Dot"), "."},
167 {(int) '<', "lt", N_("Less than"), "<"},
168 {(int) '>', "gt", N_("Great than"), ">"},
169 {(int) '=', "equal", N_("Equal"), "="},
170 {(int) ',', "comma", N_("Comma"), ","},
171 {(int) '\'', "apostrophe", N_("Apostrophe"), "\'"},
172 {(int) ':', "colon", N_("Colon"), ":"},
173 {(int) '!', "exclamation", N_("Exclamation mark"), "!"},
174 {(int) '?', "question", N_("Question mark"), "?"},
175 {(int) '&', "ampersand", N_("Ampersand"), "&"},
176 {(int) '$', "dollar", N_("Dollar sign"), "$"},
177 {(int) '"', "quota", N_("Quotation mark"), "\""},
178 {(int) '%', "percent", N_("Percent sign"), "%"},
179 {(int) '^', "caret", N_("Caret"), "^"},
180 {(int) '~', "tilda", N_("Tilda"), "~"},
181 {(int) '`', "prime", N_("Prime"), "`"},
182 {(int) '_', "underline", N_("Underline"), "_"},
183 {(int) '_', "understrike", N_("Understrike"), "_"},
184 {(int) '|', "pipe", N_("Pipe"), "|"},
185 {(int) '(', "lparenthesis", N_("Left parenthesis"), "("},
186 {(int) ')', "rparenthesis", N_("Right parenthesis"), ")"},
187 {(int) '[', "lbracket", N_("Left bracket"), "["},
188 {(int) ']', "rbracket", N_("Right bracket"), "]"},
189 {(int) '{', "lbrace", N_("Left brace"), "{"},
190 {(int) '}', "rbrace", N_("Right brace"), "}"},
191 {(int) '\n', "enter", N_("Enter"), "Enter"},
192 {(int) '\t', "tab", N_("Tab key"), "Tab"},
193 {(int) ' ', "space", N_("Space key"), "Space"},
194 {(int) '/', "slash", N_("Slash key"), "/"},
195 {(int) '\\', "backslash", N_("Backslash key"), "\\"},
196 {(int) '#', "number", N_("Number sign #"), "#"},
197 {(int) '#', "hash", N_("Number sign #"), "#"},
198 /* TRANSLATORS: Please translate as in "at sign" (@). */
199 {(int) '@', "at", N_("At sign"), "@"},
202 {KEY_M_CTRL
, "control", N_("Ctrl"), "C"},
203 {KEY_M_CTRL
, "ctrl", N_("Ctrl"), "C"},
204 {KEY_M_ALT
, "meta", N_("Alt"), "M"},
205 {KEY_M_ALT
, "alt", N_("Alt"), "M"},
206 {KEY_M_ALT
, "ralt", N_("Alt"), "M"},
207 {KEY_M_SHIFT
, "shift", N_("Shift"), "S"},
209 {0, NULL
, NULL
, NULL
}
212 /*** file scope macro definitions ****************************************************************/
214 #define GET_TIME(tv) (gettimeofday(&tv, (struct timezone *) NULL))
215 #define DIF_TIME(t1, t2) ((t2.tv_sec - t1.tv_sec) * 1000 + (t2.tv_usec - t1.tv_usec)/1000)
217 /* The maximum sequence length (32 + null terminator) */
218 #define SEQ_BUFFER_LEN 33
220 /*** file scope type declarations ****************************************************************/
222 /* Linux console keyboard modifiers */
225 SHIFT_PRESSED
= (1 << 0),
226 ALTR_PRESSED
= (1 << 1),
227 CONTROL_PRESSED
= (1 << 2),
228 ALTL_PRESSED
= (1 << 3)
231 typedef struct key_def
233 char ch
; /* Holds the matching char code */
234 int code
; /* The code returned, valid if child == NULL */
235 struct key_def
*next
;
236 struct key_def
*child
; /* sequence continuation */
237 int action
; /* optional action to be done. Now used only
238 to mark that we are just after the first
249 /* File descriptor monitoring add/remove routines */
250 typedef struct SelectList
255 struct SelectList
*next
;
258 typedef enum KeySortType
266 typedef int (*ph_dv_f
) (void *, void *);
267 typedef int (*ph_ov_f
) (void *);
268 typedef int (*ph_pqc_f
) (unsigned short, PhCursorInfo_t
*);
271 /*** file scope variables ************************************************************************/
273 static key_define_t mc_default_keys
[] = {
274 {ESC_CHAR
, ESC_STR
, MCKEY_ESCAPE
},
275 {ESC_CHAR
, ESC_STR ESC_STR
, MCKEY_NOACTION
},
276 {0, NULL
, MCKEY_NOACTION
},
279 /* Broken terminfo and termcap databases on xterminals */
280 static key_define_t xterm_key_defines
[] = {
281 {KEY_F (1), ESC_STR
"OP", MCKEY_NOACTION
},
282 {KEY_F (2), ESC_STR
"OQ", MCKEY_NOACTION
},
283 {KEY_F (3), ESC_STR
"OR", MCKEY_NOACTION
},
284 {KEY_F (4), ESC_STR
"OS", MCKEY_NOACTION
},
285 {KEY_F (1), ESC_STR
"[11~", MCKEY_NOACTION
},
286 {KEY_F (2), ESC_STR
"[12~", MCKEY_NOACTION
},
287 {KEY_F (3), ESC_STR
"[13~", MCKEY_NOACTION
},
288 {KEY_F (4), ESC_STR
"[14~", MCKEY_NOACTION
},
289 {KEY_F (5), ESC_STR
"[15~", MCKEY_NOACTION
},
290 {KEY_F (6), ESC_STR
"[17~", MCKEY_NOACTION
},
291 {KEY_F (7), ESC_STR
"[18~", MCKEY_NOACTION
},
292 {KEY_F (8), ESC_STR
"[19~", MCKEY_NOACTION
},
293 {KEY_F (9), ESC_STR
"[20~", MCKEY_NOACTION
},
294 {KEY_F (10), ESC_STR
"[21~", MCKEY_NOACTION
},
296 /* old xterm Shift-arrows */
297 {KEY_M_SHIFT
| KEY_UP
, ESC_STR
"O2A", MCKEY_NOACTION
},
298 {KEY_M_SHIFT
| KEY_DOWN
, ESC_STR
"O2B", MCKEY_NOACTION
},
299 {KEY_M_SHIFT
| KEY_RIGHT
, ESC_STR
"O2C", MCKEY_NOACTION
},
300 {KEY_M_SHIFT
| KEY_LEFT
, ESC_STR
"O2D", MCKEY_NOACTION
},
302 /* new xterm Shift-arrows */
303 {KEY_M_SHIFT
| KEY_UP
, ESC_STR
"[1;2A", MCKEY_NOACTION
},
304 {KEY_M_SHIFT
| KEY_DOWN
, ESC_STR
"[1;2B", MCKEY_NOACTION
},
305 {KEY_M_SHIFT
| KEY_RIGHT
, ESC_STR
"[1;2C", MCKEY_NOACTION
},
306 {KEY_M_SHIFT
| KEY_LEFT
, ESC_STR
"[1;2D", MCKEY_NOACTION
},
308 /* more xterm keys with modifiers */
309 {KEY_M_CTRL
| KEY_PPAGE
, ESC_STR
"[5;5~", MCKEY_NOACTION
},
310 {KEY_M_CTRL
| KEY_NPAGE
, ESC_STR
"[6;5~", MCKEY_NOACTION
},
311 {KEY_M_CTRL
| KEY_IC
, ESC_STR
"[2;5~", MCKEY_NOACTION
},
312 {KEY_M_CTRL
| KEY_DC
, ESC_STR
"[3;5~", MCKEY_NOACTION
},
313 {KEY_M_CTRL
| KEY_HOME
, ESC_STR
"[1;5H", MCKEY_NOACTION
},
314 {KEY_M_CTRL
| KEY_END
, ESC_STR
"[1;5F", MCKEY_NOACTION
},
315 {KEY_M_SHIFT
| KEY_HOME
, ESC_STR
"[1;2H", MCKEY_NOACTION
},
316 {KEY_M_SHIFT
| KEY_END
, ESC_STR
"[1;2F", MCKEY_NOACTION
},
317 {KEY_M_CTRL
| KEY_UP
, ESC_STR
"[1;5A", MCKEY_NOACTION
},
318 {KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"[1;5B", MCKEY_NOACTION
},
319 {KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"[1;5C", MCKEY_NOACTION
},
320 {KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"[1;5D", MCKEY_NOACTION
},
321 {KEY_M_SHIFT
| KEY_IC
, ESC_STR
"[2;2~", MCKEY_NOACTION
},
322 {KEY_M_SHIFT
| KEY_DC
, ESC_STR
"[3;2~", MCKEY_NOACTION
},
323 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_UP
, ESC_STR
"[1;6A", MCKEY_NOACTION
},
324 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"[1;6B", MCKEY_NOACTION
},
325 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"[1;6C", MCKEY_NOACTION
},
326 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"[1;6D", MCKEY_NOACTION
},
329 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_UP
, ESC_STR
"[[1;6A", MCKEY_NOACTION
},
330 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"[[1;6B", MCKEY_NOACTION
},
331 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"[[1;6C", MCKEY_NOACTION
},
332 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"[[1;6D", MCKEY_NOACTION
},
334 /* putty alt-arrow keys */
335 /* removed as source esc esc esc trouble */
337 { KEY_M_ALT | KEY_UP, ESC_STR ESC_STR "OA", MCKEY_NOACTION },
338 { KEY_M_ALT | KEY_DOWN, ESC_STR ESC_STR "OB", MCKEY_NOACTION },
339 { KEY_M_ALT | KEY_RIGHT, ESC_STR ESC_STR "OC", MCKEY_NOACTION },
340 { KEY_M_ALT | KEY_LEFT, ESC_STR ESC_STR "OD", MCKEY_NOACTION },
341 { KEY_M_ALT | KEY_PPAGE, ESC_STR ESC_STR "[5~", MCKEY_NOACTION },
342 { KEY_M_ALT | KEY_NPAGE, ESC_STR ESC_STR "[6~", MCKEY_NOACTION },
343 { KEY_M_ALT | KEY_HOME, ESC_STR ESC_STR "[1~", MCKEY_NOACTION },
344 { KEY_M_ALT | KEY_END, ESC_STR ESC_STR "[4~", MCKEY_NOACTION },
346 { KEY_M_CTRL | KEY_M_ALT | KEY_UP, ESC_STR ESC_STR "[1;2A", MCKEY_NOACTION },
347 { KEY_M_CTRL | KEY_M_ALT | KEY_DOWN, ESC_STR ESC_STR "[1;2B", MCKEY_NOACTION },
348 { KEY_M_CTRL | KEY_M_ALT | KEY_RIGHT, ESC_STR ESC_STR "[1;2C", MCKEY_NOACTION },
349 { KEY_M_CTRL | KEY_M_ALT | KEY_LEFT, ESC_STR ESC_STR "[1;2D", MCKEY_NOACTION },
351 { KEY_M_CTRL | KEY_M_ALT | KEY_PPAGE, ESC_STR ESC_STR "[[5;5~", MCKEY_NOACTION },
352 { KEY_M_CTRL | KEY_M_ALT | KEY_NPAGE, ESC_STR ESC_STR "[[6;5~", MCKEY_NOACTION },
353 { KEY_M_CTRL | KEY_M_ALT | KEY_HOME, ESC_STR ESC_STR "[1;5H", MCKEY_NOACTION },
354 { KEY_M_CTRL | KEY_M_ALT | KEY_END, ESC_STR ESC_STR "[1;5F", MCKEY_NOACTION },
356 /* xterm alt-arrow keys */
357 {KEY_M_ALT
| KEY_UP
, ESC_STR
"[1;3A", MCKEY_NOACTION
},
358 {KEY_M_ALT
| KEY_DOWN
, ESC_STR
"[1;3B", MCKEY_NOACTION
},
359 {KEY_M_ALT
| KEY_RIGHT
, ESC_STR
"[1;3C", MCKEY_NOACTION
},
360 {KEY_M_ALT
| KEY_LEFT
, ESC_STR
"[1;3D", MCKEY_NOACTION
},
361 {KEY_M_ALT
| KEY_PPAGE
, ESC_STR
"[5;3~", MCKEY_NOACTION
},
362 {KEY_M_ALT
| KEY_NPAGE
, ESC_STR
"[6;3~", MCKEY_NOACTION
},
363 {KEY_M_ALT
| KEY_HOME
, ESC_STR
"[1~", MCKEY_NOACTION
},
364 {KEY_M_ALT
| KEY_END
, ESC_STR
"[4~", MCKEY_NOACTION
},
365 {KEY_M_CTRL
| KEY_M_ALT
| KEY_UP
, ESC_STR
"[1;7A", MCKEY_NOACTION
},
366 {KEY_M_CTRL
| KEY_M_ALT
| KEY_DOWN
, ESC_STR
"[1;7B", MCKEY_NOACTION
},
367 {KEY_M_CTRL
| KEY_M_ALT
| KEY_RIGHT
, ESC_STR
"[1;7C", MCKEY_NOACTION
},
368 {KEY_M_CTRL
| KEY_M_ALT
| KEY_LEFT
, ESC_STR
"[1;7D", MCKEY_NOACTION
},
369 {KEY_M_CTRL
| KEY_M_ALT
| KEY_PPAGE
, ESC_STR
"[5;7~", MCKEY_NOACTION
},
370 {KEY_M_CTRL
| KEY_M_ALT
| KEY_NPAGE
, ESC_STR
"[6;7~", MCKEY_NOACTION
},
371 {KEY_M_CTRL
| KEY_M_ALT
| KEY_HOME
, ESC_STR
"OH", MCKEY_NOACTION
},
372 {KEY_M_CTRL
| KEY_M_ALT
| KEY_END
, ESC_STR
"OF", MCKEY_NOACTION
},
374 /* rxvt keys with modifiers */
375 {KEY_M_SHIFT
| KEY_UP
, ESC_STR
"[a", MCKEY_NOACTION
},
376 {KEY_M_SHIFT
| KEY_DOWN
, ESC_STR
"[b", MCKEY_NOACTION
},
377 {KEY_M_SHIFT
| KEY_RIGHT
, ESC_STR
"[c", MCKEY_NOACTION
},
378 {KEY_M_SHIFT
| KEY_LEFT
, ESC_STR
"[d", MCKEY_NOACTION
},
379 {KEY_M_CTRL
| KEY_UP
, ESC_STR
"Oa", MCKEY_NOACTION
},
380 {KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"Ob", MCKEY_NOACTION
},
381 {KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"Oc", MCKEY_NOACTION
},
382 {KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"Od", MCKEY_NOACTION
},
383 {KEY_M_CTRL
| KEY_PPAGE
, ESC_STR
"[5^", MCKEY_NOACTION
},
384 {KEY_M_CTRL
| KEY_NPAGE
, ESC_STR
"[6^", MCKEY_NOACTION
},
385 {KEY_M_CTRL
| KEY_HOME
, ESC_STR
"[7^", MCKEY_NOACTION
},
386 {KEY_M_CTRL
| KEY_END
, ESC_STR
"[8^", MCKEY_NOACTION
},
387 {KEY_M_SHIFT
| KEY_HOME
, ESC_STR
"[7$", MCKEY_NOACTION
},
388 {KEY_M_SHIFT
| KEY_END
, ESC_STR
"[8$", MCKEY_NOACTION
},
389 {KEY_M_CTRL
| KEY_IC
, ESC_STR
"[2^", MCKEY_NOACTION
},
390 {KEY_M_CTRL
| KEY_DC
, ESC_STR
"[3^", MCKEY_NOACTION
},
391 {KEY_M_SHIFT
| KEY_DC
, ESC_STR
"[3$", MCKEY_NOACTION
},
393 /* konsole keys with modifiers */
394 {KEY_M_SHIFT
| KEY_HOME
, ESC_STR
"O2H", MCKEY_NOACTION
},
395 {KEY_M_SHIFT
| KEY_END
, ESC_STR
"O2F", MCKEY_NOACTION
},
398 {KEY_M_SHIFT
| KEY_UP
, ESC_STR
"[2A", MCKEY_NOACTION
},
399 {KEY_M_SHIFT
| KEY_DOWN
, ESC_STR
"[2B", MCKEY_NOACTION
},
400 {KEY_M_SHIFT
| KEY_RIGHT
, ESC_STR
"[2C", MCKEY_NOACTION
},
401 {KEY_M_SHIFT
| KEY_LEFT
, ESC_STR
"[2D", MCKEY_NOACTION
},
402 {KEY_M_CTRL
| KEY_UP
, ESC_STR
"[5A", MCKEY_NOACTION
},
403 {KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"[5B", MCKEY_NOACTION
},
404 {KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"[5C", MCKEY_NOACTION
},
405 {KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"[5D", MCKEY_NOACTION
},
406 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_UP
, ESC_STR
"[6A", MCKEY_NOACTION
},
407 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"[6B", MCKEY_NOACTION
},
408 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"[6C", MCKEY_NOACTION
},
409 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"[6D", MCKEY_NOACTION
},
411 /* gnome-terminal - application mode */
412 {KEY_M_CTRL
| KEY_UP
, ESC_STR
"O5A", MCKEY_NOACTION
},
413 {KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"O5B", MCKEY_NOACTION
},
414 {KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"O5C", MCKEY_NOACTION
},
415 {KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"O5D", MCKEY_NOACTION
},
416 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_UP
, ESC_STR
"O6A", MCKEY_NOACTION
},
417 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"O6B", MCKEY_NOACTION
},
418 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"O6C", MCKEY_NOACTION
},
419 {KEY_M_SHIFT
| KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"O6D", MCKEY_NOACTION
},
422 {KEY_M_SHIFT
| KEY_PPAGE
, ESC_STR
"[5;2~", MCKEY_NOACTION
},
423 {KEY_M_SHIFT
| KEY_NPAGE
, ESC_STR
"[6;2~", MCKEY_NOACTION
},
426 {KEY_M_SHIFT
| KEY_PPAGE
, ESC_STR
"[[5;53~", MCKEY_NOACTION
},
427 {KEY_M_SHIFT
| KEY_NPAGE
, ESC_STR
"[[6;53~", MCKEY_NOACTION
},
430 {KEY_IC
, ESC_STR
"Op", MCKEY_NOACTION
},
431 {KEY_DC
, ESC_STR
"On", MCKEY_NOACTION
},
432 {'/', ESC_STR
"Oo", MCKEY_NOACTION
},
433 {'\n', ESC_STR
"OM", MCKEY_NOACTION
},
435 {0, NULL
, MCKEY_NOACTION
},
438 /* qansi-m terminals have a much more key combinatios,
439 which are undefined in termcap/terminfo */
440 static key_define_t qansi_key_defines
[] = {
441 /* qansi-m terminal */
442 {KEY_M_CTRL
| KEY_NPAGE
, ESC_STR
"[u", MCKEY_NOACTION
}, /* Ctrl-PgDown */
443 {KEY_M_CTRL
| KEY_PPAGE
, ESC_STR
"[v", MCKEY_NOACTION
}, /* Ctrl-PgUp */
444 {KEY_M_CTRL
| KEY_HOME
, ESC_STR
"[h", MCKEY_NOACTION
}, /* Ctrl-Home */
445 {KEY_M_CTRL
| KEY_END
, ESC_STR
"[y", MCKEY_NOACTION
}, /* Ctrl-End */
446 {KEY_M_CTRL
| KEY_IC
, ESC_STR
"[`", MCKEY_NOACTION
}, /* Ctrl-Insert */
447 {KEY_M_CTRL
| KEY_DC
, ESC_STR
"[p", MCKEY_NOACTION
}, /* Ctrl-Delete */
448 {KEY_M_CTRL
| KEY_LEFT
, ESC_STR
"[d", MCKEY_NOACTION
}, /* Ctrl-Left */
449 {KEY_M_CTRL
| KEY_RIGHT
, ESC_STR
"[c", MCKEY_NOACTION
}, /* Ctrl-Right */
450 {KEY_M_CTRL
| KEY_DOWN
, ESC_STR
"[b", MCKEY_NOACTION
}, /* Ctrl-Down */
451 {KEY_M_CTRL
| KEY_UP
, ESC_STR
"[a", MCKEY_NOACTION
}, /* Ctrl-Up */
452 {KEY_M_CTRL
| KEY_KP_ADD
, ESC_STR
"[s", MCKEY_NOACTION
}, /* Ctrl-Gr-Plus */
453 {KEY_M_CTRL
| KEY_KP_SUBTRACT
, ESC_STR
"[t", MCKEY_NOACTION
}, /* Ctrl-Gr-Minus */
454 {KEY_M_CTRL
| '\t', ESC_STR
"[z", MCKEY_NOACTION
}, /* Ctrl-Tab */
455 {KEY_M_SHIFT
| '\t', ESC_STR
"[Z", MCKEY_NOACTION
}, /* Shift-Tab */
456 {KEY_M_CTRL
| KEY_F (1), ESC_STR
"[1~", MCKEY_NOACTION
}, /* Ctrl-F1 */
457 {KEY_M_CTRL
| KEY_F (2), ESC_STR
"[2~", MCKEY_NOACTION
}, /* Ctrl-F2 */
458 {KEY_M_CTRL
| KEY_F (3), ESC_STR
"[3~", MCKEY_NOACTION
}, /* Ctrl-F3 */
459 {KEY_M_CTRL
| KEY_F (4), ESC_STR
"[4~", MCKEY_NOACTION
}, /* Ctrl-F4 */
460 {KEY_M_CTRL
| KEY_F (5), ESC_STR
"[5~", MCKEY_NOACTION
}, /* Ctrl-F5 */
461 {KEY_M_CTRL
| KEY_F (6), ESC_STR
"[6~", MCKEY_NOACTION
}, /* Ctrl-F6 */
462 {KEY_M_CTRL
| KEY_F (7), ESC_STR
"[7~", MCKEY_NOACTION
}, /* Ctrl-F7 */
463 {KEY_M_CTRL
| KEY_F (8), ESC_STR
"[8~", MCKEY_NOACTION
}, /* Ctrl-F8 */
464 {KEY_M_CTRL
| KEY_F (9), ESC_STR
"[9~", MCKEY_NOACTION
}, /* Ctrl-F9 */
465 {KEY_M_CTRL
| KEY_F (10), ESC_STR
"[10~", MCKEY_NOACTION
}, /* Ctrl-F10 */
466 {KEY_M_CTRL
| KEY_F (11), ESC_STR
"[11~", MCKEY_NOACTION
}, /* Ctrl-F11 */
467 {KEY_M_CTRL
| KEY_F (12), ESC_STR
"[12~", MCKEY_NOACTION
}, /* Ctrl-F12 */
468 {KEY_M_ALT
| KEY_F (1), ESC_STR
"[17~", MCKEY_NOACTION
}, /* Alt-F1 */
469 {KEY_M_ALT
| KEY_F (2), ESC_STR
"[18~", MCKEY_NOACTION
}, /* Alt-F2 */
470 {KEY_M_ALT
| KEY_F (3), ESC_STR
"[19~", MCKEY_NOACTION
}, /* Alt-F3 */
471 {KEY_M_ALT
| KEY_F (4), ESC_STR
"[20~", MCKEY_NOACTION
}, /* Alt-F4 */
472 {KEY_M_ALT
| KEY_F (5), ESC_STR
"[21~", MCKEY_NOACTION
}, /* Alt-F5 */
473 {KEY_M_ALT
| KEY_F (6), ESC_STR
"[22~", MCKEY_NOACTION
}, /* Alt-F6 */
474 {KEY_M_ALT
| KEY_F (7), ESC_STR
"[23~", MCKEY_NOACTION
}, /* Alt-F7 */
475 {KEY_M_ALT
| KEY_F (8), ESC_STR
"[24~", MCKEY_NOACTION
}, /* Alt-F8 */
476 {KEY_M_ALT
| KEY_F (9), ESC_STR
"[25~", MCKEY_NOACTION
}, /* Alt-F9 */
477 {KEY_M_ALT
| KEY_F (10), ESC_STR
"[26~", MCKEY_NOACTION
}, /* Alt-F10 */
478 {KEY_M_ALT
| KEY_F (11), ESC_STR
"[27~", MCKEY_NOACTION
}, /* Alt-F11 */
479 {KEY_M_ALT
| KEY_F (12), ESC_STR
"[28~", MCKEY_NOACTION
}, /* Alt-F12 */
480 {KEY_M_ALT
| 'a', ESC_STR
"Na", MCKEY_NOACTION
}, /* Alt-a */
481 {KEY_M_ALT
| 'b', ESC_STR
"Nb", MCKEY_NOACTION
}, /* Alt-b */
482 {KEY_M_ALT
| 'c', ESC_STR
"Nc", MCKEY_NOACTION
}, /* Alt-c */
483 {KEY_M_ALT
| 'd', ESC_STR
"Nd", MCKEY_NOACTION
}, /* Alt-d */
484 {KEY_M_ALT
| 'e', ESC_STR
"Ne", MCKEY_NOACTION
}, /* Alt-e */
485 {KEY_M_ALT
| 'f', ESC_STR
"Nf", MCKEY_NOACTION
}, /* Alt-f */
486 {KEY_M_ALT
| 'g', ESC_STR
"Ng", MCKEY_NOACTION
}, /* Alt-g */
487 {KEY_M_ALT
| 'h', ESC_STR
"Nh", MCKEY_NOACTION
}, /* Alt-h */
488 {KEY_M_ALT
| 'i', ESC_STR
"Ni", MCKEY_NOACTION
}, /* Alt-i */
489 {KEY_M_ALT
| 'j', ESC_STR
"Nj", MCKEY_NOACTION
}, /* Alt-j */
490 {KEY_M_ALT
| 'k', ESC_STR
"Nk", MCKEY_NOACTION
}, /* Alt-k */
491 {KEY_M_ALT
| 'l', ESC_STR
"Nl", MCKEY_NOACTION
}, /* Alt-l */
492 {KEY_M_ALT
| 'm', ESC_STR
"Nm", MCKEY_NOACTION
}, /* Alt-m */
493 {KEY_M_ALT
| 'n', ESC_STR
"Nn", MCKEY_NOACTION
}, /* Alt-n */
494 {KEY_M_ALT
| 'o', ESC_STR
"No", MCKEY_NOACTION
}, /* Alt-o */
495 {KEY_M_ALT
| 'p', ESC_STR
"Np", MCKEY_NOACTION
}, /* Alt-p */
496 {KEY_M_ALT
| 'q', ESC_STR
"Nq", MCKEY_NOACTION
}, /* Alt-q */
497 {KEY_M_ALT
| 'r', ESC_STR
"Nr", MCKEY_NOACTION
}, /* Alt-r */
498 {KEY_M_ALT
| 's', ESC_STR
"Ns", MCKEY_NOACTION
}, /* Alt-s */
499 {KEY_M_ALT
| 't', ESC_STR
"Nt", MCKEY_NOACTION
}, /* Alt-t */
500 {KEY_M_ALT
| 'u', ESC_STR
"Nu", MCKEY_NOACTION
}, /* Alt-u */
501 {KEY_M_ALT
| 'v', ESC_STR
"Nv", MCKEY_NOACTION
}, /* Alt-v */
502 {KEY_M_ALT
| 'w', ESC_STR
"Nw", MCKEY_NOACTION
}, /* Alt-w */
503 {KEY_M_ALT
| 'x', ESC_STR
"Nx", MCKEY_NOACTION
}, /* Alt-x */
504 {KEY_M_ALT
| 'y', ESC_STR
"Ny", MCKEY_NOACTION
}, /* Alt-y */
505 {KEY_M_ALT
| 'z', ESC_STR
"Nz", MCKEY_NOACTION
}, /* Alt-z */
506 {KEY_KP_SUBTRACT
, ESC_STR
"[S", MCKEY_NOACTION
}, /* Gr-Minus */
507 {KEY_KP_ADD
, ESC_STR
"[T", MCKEY_NOACTION
}, /* Gr-Plus */
508 {0, NULL
, MCKEY_NOACTION
},
511 /* This holds all the key definitions */
512 static key_def
*keys
= NULL
;
515 static int disabled_channels
= 0; /* Disable channels checking */
517 static SelectList
*select_list
= NULL
;
519 static int seq_buffer
[SEQ_BUFFER_LEN
];
520 static int *seq_append
= NULL
;
522 static int *pending_keys
= NULL
;
526 ph_ov_f ph_input_group
;
527 ph_pqc_f ph_query_cursor
;
530 #ifdef HAVE_TEXTMODE_X11_SUPPORT
531 static Display
*x11_display
;
532 static Window x11_window
;
533 #endif /* HAVE_TEXTMODE_X11_SUPPORT */
535 static KeySortType has_been_sorted
= KEY_NOSORT
;
538 static const size_t key_conv_tab_size
= G_N_ELEMENTS (key_name_conv_tab
) - 1;
541 static const key_code_name_t
*key_conv_tab_sorted
[G_N_ELEMENTS (key_name_conv_tab
) - 1];
543 /*** file scope functions ************************************************************************/
544 /* --------------------------------------------------------------------------------------------- */
547 add_selects (fd_set
* select_set
)
551 if (disabled_channels
== 0)
555 for (p
= select_list
; p
!= NULL
; p
= p
->next
)
557 FD_SET (p
->fd
, select_set
);
566 /* --------------------------------------------------------------------------------------------- */
569 check_selects (fd_set
* select_set
)
571 if (disabled_channels
== 0)
580 for (p
= select_list
; p
; p
= p
->next
)
581 if (FD_ISSET (p
->fd
, select_set
))
583 FD_CLR (p
->fd
, select_set
);
584 (*p
->callback
) (p
->fd
, p
->info
);
593 /* --------------------------------------------------------------------------------------------- */
594 /* If set timeout is set, then we wait 0.1 seconds, else, we block */
597 try_channels (int set_timeout
)
599 struct timeval time_out
;
600 static fd_set select_set
;
601 struct timeval
*timeptr
;
607 FD_ZERO (&select_set
);
608 FD_SET (input_fd
, &select_set
); /* Add stdin */
609 maxfdp
= max (add_selects (&select_set
), input_fd
);
615 time_out
.tv_usec
= 100000;
619 v
= select (maxfdp
+ 1, &select_set
, NULL
, NULL
, timeptr
);
622 check_selects (&select_set
);
623 if (FD_ISSET (input_fd
, &select_set
))
629 /* --------------------------------------------------------------------------------------------- */
632 create_sequence (const char *seq
, int code
, int action
)
634 key_def
*base
, *p
, *attach
;
636 for (base
= attach
= NULL
; *seq
; seq
++)
638 p
= g_new (key_def
, 1);
646 p
->child
= p
->next
= NULL
;
650 p
->action
= MCKEY_NOACTION
;
656 /* --------------------------------------------------------------------------------------------- */
659 define_sequences (const key_define_t
* kd
)
663 for (i
= 0; kd
[i
].code
!= 0; i
++)
664 define_sequence (kd
[i
].code
, kd
[i
].seq
, kd
[i
].action
);
667 /* --------------------------------------------------------------------------------------------- */
669 #ifdef HAVE_TEXTMODE_X11_SUPPORT
673 if (getenv ("DISPLAY") != NULL
&& !mc_global
.tty
.disable_x11
)
675 x11_display
= mc_XOpenDisplay (0);
677 if (x11_display
!= NULL
)
678 x11_window
= DefaultRootWindow (x11_display
);
681 #endif /* HAVE_TEXTMODE_X11_SUPPORT */
683 /* --------------------------------------------------------------------------------------------- */
684 /* Workaround for System V Curses vt100 bug */
687 getch_with_delay (void)
691 /* This routine could be used on systems without mouse support,
692 so we need to do the select check :-( */
695 if (pending_keys
== NULL
)
698 /* Try to get a character */
699 c
= get_key_code (0);
702 /* Failed -> wait 0.1 secs and try again */
705 /* Success -> return the character */
709 /* --------------------------------------------------------------------------------------------- */
712 xmouse_get_event (Gpm_Event
* ev
, gboolean extended
)
714 static struct timeval tv1
= { 0, 0 }; /* Force first click as single */
715 static struct timeval tv2
;
716 static int clicks
= 0;
717 static int last_btn
= 0;
720 /* Decode Xterm mouse information to a GPM style event */
724 /* Variable btn has following meaning: */
725 /* 0 = btn1 dn, 1 = btn2 dn, 2 = btn3 dn, 3 = btn up */
726 btn
= tty_lowlevel_getch () - 32;
727 /* Coordinates are 33-based */
728 /* Transform them to 1-based */
729 ev
->x
= tty_lowlevel_getch () - 32;
730 ev
->y
= tty_lowlevel_getch () - 32;
734 /* SGR 1006 extension (e.g. "\e[<0;12;300M"):
735 - Numbers are encoded in decimal to make it ASCII-safe
736 and to overcome the limit of 223 columns/rows.
737 - Mouse release is encoded by trailing 'm' rather than 'M'
738 so that the released button can be reported.
739 - Numbers are no longer offset by 32. */
741 btn
= ev
->x
= ev
->y
= 0;
742 ev
->type
= 0; /* In case we return on an invalid sequence */
743 while ((c
= tty_lowlevel_getch ()) != ';')
745 if (c
< '0' || c
> '9')
747 btn
= 10 * btn
+ (c
- '0');
749 while ((c
= tty_lowlevel_getch ()) != ';')
751 if (c
< '0' || c
> '9')
753 ev
->x
= 10 * ev
->x
+ (c
- '0');
755 while ((c
= tty_lowlevel_getch ()) != 'M' && c
!= 'm')
757 if (c
< '0' || c
> '9')
759 ev
->y
= 10 * ev
->y
+ (c
- '0');
761 /* Legacy mouse protocol doesn't tell which button was released,
762 conveniently all of mc's widgets are written not to rely on this
763 information. With the SGR extension the released button becomes
764 known, but for the sake of simplicity we just ignore it. */
769 /* There seems to be no way of knowing which button was released */
770 /* So we assume all the buttons were released */
776 if ((last_btn
& (GPM_B_UP
| GPM_B_DOWN
)) != 0)
778 /* FIXME: DIRTY HACK */
779 /* don't generate GPM_UP after mouse wheel */
780 /* need for menu event handling */
787 ev
->type
= GPM_UP
| (GPM_SINGLE
<< clicks
);
796 /* Bogus event, maybe mouse wheel */
802 if (btn
>= 32 && btn
<= 34)
811 if (tv1
.tv_sec
&& (DIF_TIME (tv1
, tv2
) < double_click_speed
))
822 ev
->buttons
= GPM_B_LEFT
;
825 ev
->buttons
= GPM_B_MIDDLE
;
828 ev
->buttons
= GPM_B_RIGHT
;
831 ev
->buttons
= GPM_B_UP
;
835 ev
->buttons
= GPM_B_DOWN
;
844 last_btn
= ev
->buttons
;
848 /* --------------------------------------------------------------------------------------------- */
850 * Get modifier state (shift, alt, ctrl) for the last key pressed.
851 * We are assuming that the state didn't change since the key press.
852 * This is only correct if get_modifier() is called very fast after
853 * the input was received, so that the user didn't release the
862 int mod_status
, shift_ext_status
;
863 static int in_photon
= 0;
864 static int ph_ig
= 0;
865 PhCursorInfo_t cursor_info
;
866 #endif /* __QNXNTO__ */
868 #ifdef HAVE_TEXTMODE_X11_SUPPORT
876 mc_XQueryPointer (x11_display
, x11_window
, &root
, &child
, &root_x
,
877 &root_y
, &win_x
, &win_y
, &mask
);
879 if (mask
& ShiftMask
)
880 result
|= KEY_M_SHIFT
;
881 if (mask
& ControlMask
)
882 result
|= KEY_M_CTRL
;
885 #endif /* HAVE_TEXTMODE_X11_SUPPORT */
890 /* First time here, let's load Photon library and attach
893 if (getenv ("PHOTON2_PATH") != NULL
)
895 /* QNX 6.x has no support for RTLD_LAZY */
896 void *ph_handle
= dlopen ("/usr/lib/libph.so", RTLD_NOW
);
897 if (ph_handle
!= NULL
)
899 ph_attach
= (ph_dv_f
) dlsym (ph_handle
, "PhAttach");
900 ph_input_group
= (ph_ov_f
) dlsym (ph_handle
, "PhInputGroup");
901 ph_query_cursor
= (ph_pqc_f
) dlsym (ph_handle
, "PhQueryCursor");
902 if ((ph_attach
!= NULL
) && (ph_input_group
!= NULL
) && (ph_query_cursor
!= NULL
))
904 if ((*ph_attach
) (0, 0))
906 ph_ig
= (*ph_input_group
) (0);
913 /* We do not have Photon running. Assume we are in text
917 if (devctl (fileno (stdin
), DCMD_CHR_LINESTATUS
, &mod_status
, sizeof (int), NULL
) == -1)
919 shift_ext_status
= mod_status
& 0xffffff00UL
;
921 if (mod_status
& _LINESTATUS_CON_ALT
)
923 if (mod_status
& _LINESTATUS_CON_CTRL
)
924 result
|= KEY_M_CTRL
;
925 if ((mod_status
& _LINESTATUS_CON_SHIFT
) || (shift_ext_status
& 0x00000800UL
))
926 result
|= KEY_M_SHIFT
;
930 (*ph_query_cursor
) (ph_ig
, &cursor_info
);
931 if (cursor_info
.key_mods
& 0x04)
933 if (cursor_info
.key_mods
& 0x02)
934 result
|= KEY_M_CTRL
;
935 if (cursor_info
.key_mods
& 0x01)
936 result
|= KEY_M_SHIFT
;
938 #endif /* __QNXNTO__ */
940 #if defined __linux__ || (defined __CYGWIN__ && defined TIOCLINUX)
942 unsigned char modifiers
= 6;
944 if (ioctl (0, TIOCLINUX
, &modifiers
) < 0)
947 /* Translate Linux modifiers into mc modifiers */
948 if (modifiers
& SHIFT_PRESSED
)
949 result
|= KEY_M_SHIFT
;
950 if (modifiers
& (ALTL_PRESSED
| ALTR_PRESSED
))
952 if (modifiers
& CONTROL_PRESSED
)
953 result
|= KEY_M_CTRL
;
955 #endif /* !__linux__ */
959 /* --------------------------------------------------------------------------------------------- */
964 gboolean ret
= FALSE
;
966 if (seq_append
== NULL
)
967 seq_append
= seq_buffer
;
969 if (seq_append
!= &(seq_buffer
[SEQ_BUFFER_LEN
- 2]))
979 /* --------------------------------------------------------------------------------------------- */
980 /* Apply corrections for the keycode generated in get_key_code() */
983 correct_key_code (int code
)
985 unsigned int c
= code
& ~KEY_M_MASK
; /* code without modifier */
986 unsigned int mod
= code
& KEY_M_MASK
; /* modifier */
988 unsigned int qmod
; /* bunch of the QNX console
989 modifiers needs unchanged */
990 #endif /* __QNXNTO__ */
993 * Add key modifiers directly from X11 or OS.
994 * Ordinary characters only get modifiers from sequences.
996 if (c
< 32 || c
>= 256)
998 mod
|= get_modifier ();
1001 /* This is needed if the newline is reported as carriage return */
1005 /* This is reported to be useful on AIX */
1006 if (c
== KEY_SCANCEL
)
1009 /* Convert Shift+Tab and Ctrl+Tab to Back Tab
1010 * only if modifiers directly from X11
1012 #ifdef HAVE_TEXTMODE_X11_SUPPORT
1013 if (x11_window
!= 0)
1014 #endif /* HAVE_TEXTMODE_X11_SUPPORT */
1016 if ((c
== '\t') && (mod
& (KEY_M_SHIFT
| KEY_M_CTRL
)))
1023 /* F0 is the same as F10 for out purposes */
1028 * We are not interested if Ctrl was pressed when entering control
1029 * characters, so assume that it was. When checking for such keys,
1030 * XCTRL macro should be used. In some cases, we are interested,
1031 * e.g. to distinguish Ctrl-Enter from Enter.
1035 /* Special case for backspase ('\b' < 32) */
1039 else if (c
< 32 && c
!= ESC_CHAR
&& c
!= '\t' && c
!= '\n')
1045 qmod
= get_modifier ();
1047 if ((c
== 127) && (mod
== 0))
1048 { /* Add Ctrl/Alt/Shift-BackSpace */
1049 mod
|= get_modifier ();
1053 if ((c
== '0') && (mod
== 0))
1054 { /* Add Shift-Insert on key pad */
1055 if ((qmod
& KEY_M_SHIFT
) == KEY_M_SHIFT
)
1062 if ((c
== '.') && (mod
== 0))
1063 { /* Add Shift-Del on key pad */
1064 if ((qmod
& KEY_M_SHIFT
) == KEY_M_SHIFT
)
1070 #endif /* __QNXNTO__ */
1072 /* Unrecognized 0177 is delete (preserve Ctrl) */
1079 /* Unrecognized Ctrl-d is delete */
1080 if (c
== (31 & 'd'))
1086 /* Unrecognized Ctrl-h is backspace */
1087 if (c
== (31 & 'h'))
1094 /* Shift+BackSpace is backspace */
1095 if (c
== KEY_BACKSPACE
&& (mod
& KEY_M_SHIFT
))
1097 mod
&= ~KEY_M_SHIFT
;
1100 /* Convert Shift+Fn to F(n+10) */
1101 if (c
>= KEY_F (1) && c
<= KEY_F (10) && (mod
& KEY_M_SHIFT
))
1106 /* Remove Shift information from function keys */
1107 if (c
>= KEY_F (1) && c
<= KEY_F (20))
1109 mod
&= ~KEY_M_SHIFT
;
1112 if (!mc_global
.tty
.alternate_plus_minus
)
1118 case KEY_KP_SUBTRACT
:
1121 case KEY_KP_MULTIPLY
:
1129 /* --------------------------------------------------------------------------------------------- */
1132 xgetch_second (void)
1136 struct timeval time_out
;
1138 time_out
.tv_sec
= old_esc_mode_timeout
/ 1000000;
1139 time_out
.tv_usec
= old_esc_mode_timeout
% 1000000;
1141 FD_ZERO (&Read_FD_Set
);
1142 FD_SET (input_fd
, &Read_FD_Set
);
1143 select (input_fd
+ 1, &Read_FD_Set
, NULL
, NULL
, &time_out
);
1144 c
= tty_lowlevel_getch ();
1145 tty_nodelay (FALSE
);
1149 /* --------------------------------------------------------------------------------------------- */
1152 learn_store_key (char *buffer
, char **p
, int c
)
1154 if (*p
- buffer
> 253)
1164 *(*p
)++ = c
+ 'a' - 1;
1175 /* --------------------------------------------------------------------------------------------- */
1178 k_dispose (key_def
* k
)
1182 k_dispose (k
->child
);
1183 k_dispose (k
->next
);
1188 /* --------------------------------------------------------------------------------------------- */
1191 s_dispose (SelectList
* sel
)
1195 s_dispose (sel
->next
);
1200 /* --------------------------------------------------------------------------------------------- */
1203 key_code_comparator_by_name (const void *p1
, const void *p2
)
1205 const key_code_name_t
*n1
= *(const key_code_name_t
**) p1
;
1206 const key_code_name_t
*n2
= *(const key_code_name_t
**) p2
;
1208 return g_ascii_strcasecmp (n1
->name
, n2
->name
);
1211 /* --------------------------------------------------------------------------------------------- */
1214 key_code_comparator_by_code (const void *p1
, const void *p2
)
1216 const key_code_name_t
*n1
= *(const key_code_name_t
**) p1
;
1217 const key_code_name_t
*n2
= *(const key_code_name_t
**) p2
;
1219 return n1
->code
- n2
->code
;
1222 /* --------------------------------------------------------------------------------------------- */
1225 sort_key_conv_tab (enum KeySortType type_sort
)
1227 if (has_been_sorted
!= type_sort
)
1230 for (i
= 0; i
< key_conv_tab_size
; i
++)
1231 key_conv_tab_sorted
[i
] = &key_name_conv_tab
[i
];
1233 if (type_sort
== KEY_SORTBYNAME
)
1235 qsort (key_conv_tab_sorted
, key_conv_tab_size
, sizeof (key_conv_tab_sorted
[0]),
1236 &key_code_comparator_by_name
);
1238 else if (type_sort
== KEY_SORTBYCODE
)
1240 qsort (key_conv_tab_sorted
, key_conv_tab_size
, sizeof (key_conv_tab_sorted
[0]),
1241 &key_code_comparator_by_code
);
1243 has_been_sorted
= type_sort
;
1247 /* --------------------------------------------------------------------------------------------- */
1250 lookup_keyname (const char *name
, int *idx
)
1252 if (name
[0] != '\0')
1254 const key_code_name_t key
= { 0, name
, NULL
, NULL
};
1255 const key_code_name_t
*keyp
= &key
;
1256 key_code_name_t
**res
;
1258 if (name
[1] == '\0')
1261 return (int) name
[0];
1264 sort_key_conv_tab (KEY_SORTBYNAME
);
1266 res
= bsearch (&keyp
, key_conv_tab_sorted
, key_conv_tab_size
,
1267 sizeof (key_conv_tab_sorted
[0]), key_code_comparator_by_name
);
1271 *idx
= (int) (res
- (key_code_name_t
**) key_conv_tab_sorted
);
1272 return (*res
)->code
;
1280 /* --------------------------------------------------------------------------------------------- */
1283 lookup_keycode (const long code
, int *idx
)
1287 const key_code_name_t key
= { code
, NULL
, NULL
, NULL
};
1288 const key_code_name_t
*keyp
= &key
;
1289 key_code_name_t
**res
;
1291 sort_key_conv_tab (KEY_SORTBYCODE
);
1293 res
= bsearch (&keyp
, key_conv_tab_sorted
, key_conv_tab_size
,
1294 sizeof (key_conv_tab_sorted
[0]), key_code_comparator_by_code
);
1298 *idx
= (int) (res
- (key_code_name_t
**) key_conv_tab_sorted
);
1307 /* --------------------------------------------------------------------------------------------- */
1308 /*** public functions ****************************************************************************/
1309 /* --------------------------------------------------------------------------------------------- */
1310 /* This has to be called before init_slang or whatever routine
1311 calls any define_sequence */
1316 const char *term
= getenv ("TERM");
1318 /* This has to be the first define_sequence */
1319 /* So, we can assume that the first keys member has ESC */
1320 define_sequences (mc_default_keys
);
1322 /* Terminfo on irix does not have some keys */
1323 if (mc_global
.tty
.xterm_flag
1325 && (strncmp (term
, "iris-ansi", 9) == 0
1326 || strncmp (term
, "xterm", 5) == 0
1327 || strncmp (term
, "rxvt", 4) == 0 || strcmp (term
, "screen") == 0)))
1328 define_sequences (xterm_key_defines
);
1330 /* load some additional keys (e.g. direct Alt-? support) */
1331 load_xtra_key_defines ();
1334 if ((term
!= NULL
) && (strncmp (term
, "qnx", 3) == 0))
1336 /* Modify the default value of use_8th_bit_as_meta: we would
1337 * like to provide a working mc for a newbie who knows nothing
1338 * about [Options|Display bits|Full 8 bits input]...
1340 * Don't use 'meta'-bit, when we are dealing with a
1341 * 'qnx*'-type terminal: clear the default value!
1342 * These terminal types use 0xFF as an escape character,
1343 * so use_8th_bit_as_meta==1 must not be enabled!
1345 * [mc-4.1.21+,slint.c/getch(): the DEC_8BIT_HACK stuff
1346 * is not used now (doesn't even depend on use_8th_bit_as_meta
1347 * as in mc-3.1.2)...GREAT!...no additional code is required!]
1349 use_8th_bit_as_meta
= 0;
1351 #endif /* __QNX__ */
1353 #ifdef HAVE_TEXTMODE_X11_SUPPORT
1357 /* Load the qansi-m key definitions
1358 if we are running under the qansi-m terminal */
1359 if (term
!= NULL
&& (strncmp (term
, "qansi-m", 7) == 0))
1360 define_sequences (qansi_key_defines
);
1363 /* --------------------------------------------------------------------------------------------- */
1365 * This has to be called after SLang_init_tty/slint_init
1369 init_key_input_fd (void)
1372 input_fd
= SLang_TT_Read_FD
;
1376 /* --------------------------------------------------------------------------------------------- */
1382 s_dispose (select_list
);
1384 #ifdef HAVE_TEXTMODE_X11_SUPPORT
1386 mc_XCloseDisplay (x11_display
);
1390 /* --------------------------------------------------------------------------------------------- */
1393 add_select_channel (int fd
, select_fn callback
, void *info
)
1397 new = g_new (SelectList
, 1);
1399 new->callback
= callback
;
1401 new->next
= select_list
;
1405 /* --------------------------------------------------------------------------------------------- */
1408 delete_select_channel (int fd
)
1410 SelectList
*p
= select_list
;
1411 SelectList
*p_prev
= NULL
;
1420 p_prev
->next
= p_next
;
1422 select_list
= p_next
;
1434 /* --------------------------------------------------------------------------------------------- */
1439 if (disabled_channels
== 0)
1440 fputs ("Error: channels_up called with disabled_channels = 0\n", stderr
);
1441 disabled_channels
--;
1444 /* --------------------------------------------------------------------------------------------- */
1447 channels_down (void)
1449 disabled_channels
++;
1452 /* --------------------------------------------------------------------------------------------- */
1454 * Return the code associated with the symbolic name keyname
1458 lookup_key (const char *name
, char **label
)
1460 char **lc_keys
, **p
;
1472 name
= g_strstrip (g_strdup (name
));
1473 p
= lc_keys
= g_strsplit_set (name
, "-+ ", -1);
1474 g_free ((char *) name
);
1476 while ((p
!= NULL
) && (*p
!= NULL
))
1478 if ((*p
)[0] != '\0')
1482 key
= lookup_keyname (g_strstrip (*p
), &idx
);
1484 if (key
== KEY_M_ALT
)
1486 else if (key
== KEY_M_CTRL
)
1488 else if (key
== KEY_M_SHIFT
)
1501 g_strfreev (lc_keys
);
1512 s
= g_string_new ("");
1516 g_string_append (s
, key_conv_tab_sorted
[use_meta
]->shortcut
);
1517 g_string_append_c (s
, '-');
1521 g_string_append (s
, key_conv_tab_sorted
[use_ctrl
]->shortcut
);
1522 g_string_append_c (s
, '-');
1524 if (use_shift
!= -1)
1527 g_string_append_c (s
, (gchar
) g_ascii_toupper ((gchar
) k
));
1530 g_string_append (s
, key_conv_tab_sorted
[use_shift
]->shortcut
);
1531 g_string_append_c (s
, '-');
1532 g_string_append (s
, key_conv_tab_sorted
[lc_index
]->shortcut
);
1537 if ((k
>= 'A') || (lc_index
< 0) || (key_conv_tab_sorted
[lc_index
]->shortcut
== NULL
))
1538 g_string_append_c (s
, (gchar
) g_ascii_tolower ((gchar
) k
));
1540 g_string_append (s
, key_conv_tab_sorted
[lc_index
]->shortcut
);
1542 else if ((lc_index
!= -1) && (key_conv_tab_sorted
[lc_index
]->shortcut
!= NULL
))
1543 g_string_append (s
, key_conv_tab_sorted
[lc_index
]->shortcut
);
1545 g_string_append_c (s
, (gchar
) g_ascii_tolower ((gchar
) key
));
1547 *label
= g_string_free (s
, FALSE
);
1550 if (use_shift
!= -1)
1552 if (k
< 127 && k
> 31)
1553 k
= g_ascii_toupper ((gchar
) k
);
1572 /* --------------------------------------------------------------------------------------------- */
1575 lookup_key_by_code (const int keycode
)
1577 /* code without modifier */
1578 unsigned int k
= keycode
& ~KEY_M_MASK
;
1580 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
))
1599 g_string_append (s
, key_conv_tab_sorted
[use_meta
]->name
);
1600 g_string_append_c (s
, '-');
1603 if (mod
& KEY_M_CTRL
)
1605 /* non printeble chars like a CTRL-[A..Z] */
1609 if (lookup_keycode (KEY_M_CTRL
, &idx
))
1612 g_string_append (s
, key_conv_tab_sorted
[use_ctrl
]->name
);
1613 g_string_append_c (s
, '-');
1616 if (mod
& KEY_M_SHIFT
)
1618 if (lookup_keycode (KEY_M_ALT
, &idx
))
1622 g_string_append_c (s
, (gchar
) g_ascii_toupper ((gchar
) k
));
1625 g_string_append (s
, key_conv_tab_sorted
[use_shift
]->name
);
1626 g_string_append_c (s
, '-');
1627 g_string_append (s
, key_conv_tab_sorted
[key_idx
]->name
);
1633 if ((k
>= 'A') || (key_idx
< 0) || (key_conv_tab_sorted
[key_idx
]->name
== NULL
))
1634 g_string_append_c (s
, (gchar
) k
);
1636 g_string_append (s
, key_conv_tab_sorted
[key_idx
]->name
);
1638 else if ((key_idx
!= -1) && (key_conv_tab_sorted
[key_idx
]->name
!= NULL
))
1639 g_string_append (s
, key_conv_tab_sorted
[key_idx
]->name
);
1641 g_string_append_c (s
, (gchar
) keycode
);
1644 return g_string_free (s
, s
->len
== 0);
1647 /* --------------------------------------------------------------------------------------------- */
1649 * Return TRUE on success, FALSE on error.
1650 * An error happens if SEQ is a beginning of an existing longer sequence.
1654 define_sequence (int code
, const char *seq
, int action
)
1658 if (strlen (seq
) > SEQ_BUFFER_LEN
- 1)
1661 for (base
= keys
; (base
!= NULL
) && (*seq
!= '\0');)
1662 if (*seq
== base
->ch
)
1664 if (base
->child
== 0)
1666 if (*(seq
+ 1) != '\0')
1667 base
->child
= create_sequence (seq
+ 1, code
, action
);
1670 /* The sequence matches an existing one. */
1672 base
->action
= action
;
1686 base
->next
= create_sequence (seq
, code
, action
);
1693 /* Attempt to redefine a sequence with a shorter sequence. */
1697 keys
= create_sequence (seq
, code
, action
);
1701 /* --------------------------------------------------------------------------------------------- */
1703 * Check if we are idle, i.e. there are no pending keyboard or mouse
1704 * events. Return 1 is idle, 0 is there are pending events.
1711 struct timeval time_out
;
1713 FD_ZERO (&select_set
);
1714 FD_SET (input_fd
, &select_set
);
1717 if (mouse_enabled
&& (use_mouse_p
== MOUSE_GPM
) && (gpm_fd
> 0))
1719 FD_SET (gpm_fd
, &select_set
);
1720 maxfdp
= max (maxfdp
, gpm_fd
);
1723 time_out
.tv_sec
= 0;
1724 time_out
.tv_usec
= 0;
1725 return (select (maxfdp
+ 1, &select_set
, 0, 0, &time_out
) <= 0);
1728 /* --------------------------------------------------------------------------------------------- */
1731 get_key_code (int no_delay
)
1734 static key_def
*this = NULL
, *parent
;
1735 static struct timeval esctime
= { -1, -1 };
1736 static int lastnodelay
= -1;
1738 if (no_delay
!= lastnodelay
)
1741 lastnodelay
= no_delay
;
1745 if (pending_keys
!= NULL
)
1749 d
= *pending_keys
++;
1750 while (d
== ESC_CHAR
&& *pending_keys
!= '\0')
1751 d
= ALT (*pending_keys
++);
1753 if (*pending_keys
== '\0')
1754 pending_keys
= seq_append
= NULL
;
1756 if (d
> 127 && d
< 256 && use_8th_bit_as_meta
)
1760 return correct_key_code (d
);
1767 c
= tty_lowlevel_getch ();
1768 #if (defined(USE_NCURSES) || defined(USE_NCURSESW)) && defined(KEY_RESIZE)
1769 if (c
== KEY_RESIZE
)
1770 goto nodelay_try_again
;
1774 tty_nodelay (FALSE
);
1777 if (this != NULL
&& parent
!= NULL
&& parent
->action
== MCKEY_ESCAPE
&& old_esc_mode
)
1779 struct timeval current
, time_out
;
1781 if (esctime
.tv_sec
== -1)
1784 time_out
.tv_sec
= old_esc_mode_timeout
/ 1000000 + esctime
.tv_sec
;
1785 time_out
.tv_usec
= old_esc_mode_timeout
% 1000000 + esctime
.tv_usec
;
1786 if (time_out
.tv_usec
> 1000000)
1788 time_out
.tv_usec
-= 1000000;
1791 if (current
.tv_sec
< time_out
.tv_sec
)
1793 if (current
.tv_sec
== time_out
.tv_sec
&& current
.tv_usec
< time_out
.tv_usec
)
1796 pending_keys
= seq_append
= NULL
;
1804 /* Maybe we got an incomplete match.
1805 This we do only in delay mode, since otherwise
1806 tty_lowlevel_getch can return -1 at any time. */
1807 if (seq_append
!= NULL
)
1809 pending_keys
= seq_buffer
;
1816 /* Search the key on the root */
1817 if (!no_delay
|| this == NULL
)
1822 if ((c
> 127 && c
< 256) && use_8th_bit_as_meta
)
1826 /* The first sequence defined starts with esc */
1831 while (this != NULL
)
1839 pending_keys
= seq_buffer
;
1844 if (parent
->action
== MCKEY_ESCAPE
&& old_esc_mode
)
1851 /* Shouldn't happen */
1852 fputs ("Internal error\n", stderr
);
1853 exit (EXIT_FAILURE
);
1855 goto nodelay_try_again
;
1857 esctime
.tv_sec
= -1;
1858 c
= xgetch_second ();
1861 pending_keys
= seq_append
= NULL
;
1869 goto nodelay_try_again
;
1870 c
= tty_lowlevel_getch ();
1875 /* We got a complete match, return and reset search */
1878 pending_keys
= seq_append
= NULL
;
1881 return correct_key_code (code
);
1886 if (this->next
!= NULL
)
1890 if ((parent
!= NULL
) && (parent
->action
== MCKEY_ESCAPE
))
1892 /* Convert escape-digits to F-keys */
1893 if (g_ascii_isdigit (c
))
1894 c
= KEY_F (c
- '0');
1900 pending_keys
= seq_append
= NULL
;
1902 return correct_key_code (c
);
1904 /* Did not find a match or {c} was changed in the if above,
1905 so we have to return everything we had skipped
1908 pending_keys
= seq_buffer
;
1914 return correct_key_code (c
);
1917 /* --------------------------------------------------------------------------------------------- */
1918 /* Returns a character read from stdin with appropriate interpretation */
1919 /* Also takes care of generated mouse events */
1920 /* Returns EV_MOUSE if it is a mouse event */
1921 /* Returns EV_NONE if non-blocking or interrupt set and nothing was done */
1924 tty_get_event (struct Gpm_Event
*event
, gboolean redo_event
, gboolean block
)
1927 static int flag
= 0; /* Return value from select */
1929 static struct Gpm_Event ev
; /* Mouse event */
1931 struct timeval time_out
;
1932 struct timeval
*time_addr
= NULL
;
1933 static int dirty
= 3;
1935 if ((dirty
== 3) || is_idle ())
1943 vfs_timeout_handler ();
1945 /* Ok, we use (event->x < 0) to signal that the event does not contain
1946 a suitable position for the mouse, so we can't use show_mouse_pointer
1951 show_mouse_pointer (event
->x
, event
->y
);
1956 /* Repeat if using mouse */
1957 while (pending_keys
== NULL
)
1962 FD_ZERO (&select_set
);
1963 FD_SET (input_fd
, &select_set
);
1964 maxfdp
= max (add_selects (&select_set
), input_fd
);
1967 if (mouse_enabled
&& (use_mouse_p
== MOUSE_GPM
))
1971 /* Connection to gpm broken, possibly gpm has died */
1972 mouse_enabled
= FALSE
;
1973 use_mouse_p
= MOUSE_NONE
;
1977 FD_SET (gpm_fd
, &select_set
);
1978 maxfdp
= max (maxfdp
, gpm_fd
);
1984 time_out
.tv_usec
= mou_auto_repeat
* 1000;
1985 time_out
.tv_sec
= 0;
1987 time_addr
= &time_out
;
1993 seconds
= vfs_timeouts ();
1998 /* the timeout could be improved and actually be
1999 * the number of seconds until the next vfs entry
2000 * timeouts in the stamp list.
2003 time_out
.tv_sec
= seconds
;
2004 time_out
.tv_usec
= 0;
2005 time_addr
= &time_out
;
2009 if (!block
|| mc_global
.tty
.winch_flag
!= 0)
2011 time_addr
= &time_out
;
2012 time_out
.tv_sec
= 0;
2013 time_out
.tv_usec
= 0;
2016 tty_enable_interrupt_key ();
2017 flag
= select (maxfdp
+ 1, &select_set
, NULL
, NULL
, time_addr
);
2018 tty_disable_interrupt_key ();
2020 /* select timed out: it could be for any of the following reasons:
2021 * redo_event -> it was because of the MOU_REPEAT handler
2022 * !block -> we did not block in the select call
2023 * else -> 10 second timeout to check the vfs status.
2029 if (!block
|| mc_global
.tty
.winch_flag
!= 0)
2031 vfs_timeout_handler ();
2033 if (flag
== -1 && errno
== EINTR
)
2036 check_selects (&select_set
);
2038 if (FD_ISSET (input_fd
, &select_set
))
2041 if (mouse_enabled
&& use_mouse_p
== MOUSE_GPM
2042 && gpm_fd
> 0 && FD_ISSET (gpm_fd
, &select_set
))
2049 #endif /* !HAVE_LIBGPM */
2053 flag
= is_wintouched (stdscr
);
2054 untouchwin (stdscr
);
2055 #endif /* !HAVE_SLANG */
2056 c
= block
? getch_with_delay () : get_key_code (1);
2060 tty_touch_screen ();
2061 #endif /* !HAVE_SLANG */
2063 if (mouse_enabled
&& (c
== MCKEY_MOUSE
2066 #endif /* KEY_MOUSE */
2067 || c
== MCKEY_EXTENDED_MOUSE
))
2070 xmouse_get_event (event
, c
== MCKEY_EXTENDED_MOUSE
);
2071 return (event
->type
!= 0) ? EV_MOUSE
: EV_NONE
;
2077 /* --------------------------------------------------------------------------------------------- */
2078 /* Returns a key press, mouse events are discarded */
2087 while ((key
= tty_get_event (&ev
, FALSE
, TRUE
)) == EV_NONE
);
2091 /* --------------------------------------------------------------------------------------------- */
2096 /* LEARN_TIMEOUT in usec */
2097 #define LEARN_TIMEOUT 200000
2100 struct timeval endtime
;
2101 struct timeval time_out
;
2106 tty_keypad (FALSE
); /* disable intepreting keys by ncurses */
2107 c
= tty_lowlevel_getch ();
2109 c
= tty_lowlevel_getch (); /* Sanity check, should be unnecessary */
2110 learn_store_key (buffer
, &p
, c
);
2112 endtime
.tv_usec
+= LEARN_TIMEOUT
;
2113 if (endtime
.tv_usec
> 1000000)
2115 endtime
.tv_usec
-= 1000000;
2121 while ((c
= tty_lowlevel_getch ()) == -1)
2123 GET_TIME (time_out
);
2124 time_out
.tv_usec
= endtime
.tv_usec
- time_out
.tv_usec
;
2125 if (time_out
.tv_usec
< 0)
2127 time_out
.tv_sec
= endtime
.tv_sec
- time_out
.tv_sec
;
2128 if (time_out
.tv_sec
>= 0 && time_out
.tv_usec
> 0)
2130 FD_ZERO (&Read_FD_Set
);
2131 FD_SET (input_fd
, &Read_FD_Set
);
2132 select (input_fd
+ 1, &Read_FD_Set
, NULL
, NULL
, &time_out
);
2139 learn_store_key (buffer
, &p
, c
);
2142 tty_nodelay (FALSE
);
2144 return g_strdup (buffer
);
2145 #undef LEARN_TIMEOUT
2148 /* --------------------------------------------------------------------------------------------- */
2149 /* xterm and linux console only: set keypad to numeric or application
2150 mode. Only in application keypad mode it's possible to distinguish
2151 the '+' key and the '+' on the keypad ('*' and '-' ditto) */
2154 numeric_keypad_mode (void)
2156 if (mc_global
.tty
.console_flag
!= '\0' || mc_global
.tty
.xterm_flag
)
2158 fputs (ESC_STR
">", stdout
);
2163 /* --------------------------------------------------------------------------------------------- */
2166 application_keypad_mode (void)
2168 if (mc_global
.tty
.console_flag
!= '\0' || mc_global
.tty
.xterm_flag
)
2170 fputs (ESC_STR
"=", stdout
);
2175 /* --------------------------------------------------------------------------------------------- */