1 /* Keyboard support routines.
3 Copyright (C) 1994,1995 the Free Software Foundation.
5 Written by: 1994, 1995 Miguel de Icaza.
6 1994, 1995 Janne Kukonlehto.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
26 #include <sys/types.h>
40 #include "cons.saver.h"
41 #include "../vfs/vfs.h"
43 #ifdef HAVE_TEXTMODE_X11_SUPPORT
48 # if defined(__GLIBC__) && (__GLIBC__ < 2)
49 # include <linux/termios.h> /* This is needed for TIOCLINUX */
53 # include <sys/ioctl.h>
56 #define GET_TIME(tv) (gettimeofday(&tv, (struct timezone *)NULL))
57 #define DIF_TIME(t1,t2) ((t2.tv_sec -t1.tv_sec) *1000+ \
58 (t2.tv_usec-t1.tv_usec)/1000)
60 /* timeout for old_esc_mode in usec */
61 #define ESCMODE_TIMEOUT 1000000
63 /* Linux console keyboard modifiers */
64 #define SHIFT_PRESSED 1
65 #define ALTR_PRESSED 2
66 #define CONTROL_PRESSED 4
67 #define ALTL_PRESSED 8
70 int mou_auto_repeat
= 100;
71 int double_click_speed
= 250;
74 int use_8th_bit_as_meta
= 1;
76 typedef struct key_def
{
77 char ch
; /* Holds the matching char code */
78 int code
; /* The code returned, valid if child == NULL */
80 struct key_def
*child
; /* sequence continuation */
81 int action
; /* optional action to be done. Now used only
82 to mark that we are just after the first
86 /* This holds all the key definitions */
87 static key_def
*keys
= 0;
90 static int disabled_channels
= 0; /* Disable channels checking */
91 static int xgetch_second (void);
92 static int get_modifier (void);
94 /* File descriptor monitoring add/remove routines */
95 typedef struct SelectList
{
99 struct SelectList
*next
;
102 static SelectList
*select_list
= 0;
104 void add_select_channel (int fd
, select_fn callback
, void *info
)
108 new = g_new (SelectList
, 1);
110 new->callback
= callback
;
112 new->next
= select_list
;
116 void delete_select_channel (int fd
)
118 SelectList
*p
= select_list
;
119 SelectList
*p_prev
= 0;
127 p_prev
->next
= p_next
;
129 select_list
= p_next
;
141 inline static int add_selects (fd_set
*select_set
)
146 if (disabled_channels
)
149 for (p
= select_list
; p
; p
= p
->next
){
150 FD_SET (p
->fd
, select_set
);
157 static void check_selects (fd_set
*select_set
)
161 if (disabled_channels
)
164 for (p
= select_list
; p
; p
= p
->next
)
165 if (FD_ISSET (p
->fd
, select_set
))
166 (*p
->callback
)(p
->fd
, p
->info
);
169 void channels_down (void)
171 disabled_channels
++;
174 void channels_up (void)
176 if (!disabled_channels
)
178 "Error: channels_up called with disabled_channels = 0\n");
182 typedef const struct {
188 static key_define_t mc_bindings
[] = {
189 { KEY_END
, ESC_STR
">", MCKEY_NOACTION
},
190 { KEY_HOME
, ESC_STR
"<", MCKEY_NOACTION
},
191 { 0, 0, MCKEY_NOACTION
},
194 /* Broken terminfo and termcap databases on xterminals */
195 static key_define_t xterm_key_defines
[] = {
196 { KEY_F(1), ESC_STR
"OP", MCKEY_NOACTION
},
197 { KEY_F(2), ESC_STR
"OQ", MCKEY_NOACTION
},
198 { KEY_F(3), ESC_STR
"OR", MCKEY_NOACTION
},
199 { KEY_F(4), ESC_STR
"OS", MCKEY_NOACTION
},
200 { KEY_F(1), ESC_STR
"[11~", MCKEY_NOACTION
},
201 { KEY_F(2), ESC_STR
"[12~", MCKEY_NOACTION
},
202 { KEY_F(3), ESC_STR
"[13~", MCKEY_NOACTION
},
203 { KEY_F(4), ESC_STR
"[14~", MCKEY_NOACTION
},
204 { KEY_F(5), ESC_STR
"[15~", MCKEY_NOACTION
},
205 { KEY_F(6), ESC_STR
"[17~", MCKEY_NOACTION
},
206 { KEY_F(7), ESC_STR
"[18~", MCKEY_NOACTION
},
207 { KEY_F(8), ESC_STR
"[19~", MCKEY_NOACTION
},
208 { KEY_F(9), ESC_STR
"[20~", MCKEY_NOACTION
},
209 { KEY_F(10), ESC_STR
"[21~", MCKEY_NOACTION
},
211 /* xterm keys with modifiers */
212 { KEY_M_SHIFT
| KEY_UP
, ESC_STR
"O2A", MCKEY_NOACTION
},
213 { KEY_M_SHIFT
| KEY_DOWN
, ESC_STR
"O2B", MCKEY_NOACTION
},
214 { KEY_M_SHIFT
| KEY_RIGHT
, ESC_STR
"O2C", MCKEY_NOACTION
},
215 { KEY_M_SHIFT
| KEY_LEFT
, ESC_STR
"O2D", MCKEY_NOACTION
},
216 { KEY_M_CTRL
| KEY_PPAGE
, ESC_STR
"[5;5~", MCKEY_NOACTION
},
217 { KEY_M_CTRL
| KEY_NPAGE
, ESC_STR
"[6;5~", MCKEY_NOACTION
},
219 /* rxvt keys with modifiers */
220 { KEY_M_SHIFT
| KEY_UP
, ESC_STR
"[a", MCKEY_NOACTION
},
221 { KEY_M_SHIFT
| KEY_DOWN
, ESC_STR
"[b", MCKEY_NOACTION
},
222 { KEY_M_SHIFT
| KEY_RIGHT
, ESC_STR
"[c", MCKEY_NOACTION
},
223 { KEY_M_SHIFT
| KEY_LEFT
, ESC_STR
"[d", MCKEY_NOACTION
},
224 { KEY_M_CTRL
| KEY_PPAGE
, ESC_STR
"[5^", MCKEY_NOACTION
},
225 { KEY_M_CTRL
| KEY_NPAGE
, ESC_STR
"[6^", MCKEY_NOACTION
},
226 { KEY_M_CTRL
| KEY_HOME
, ESC_STR
"[7^", MCKEY_NOACTION
},
227 { KEY_M_CTRL
| KEY_END
, ESC_STR
"[8^", MCKEY_NOACTION
},
228 { KEY_M_SHIFT
| KEY_HOME
, ESC_STR
"[7$", MCKEY_NOACTION
},
229 { KEY_M_SHIFT
| KEY_END
, ESC_STR
"[8$", MCKEY_NOACTION
},
231 { 0, 0, MCKEY_NOACTION
},
234 static key_define_t mc_default_keys
[] = {
235 { ESC_CHAR
, ESC_STR
, MCKEY_ESCAPE
},
236 { ESC_CHAR
, ESC_STR ESC_STR
, MCKEY_NOACTION
},
237 { 0, 0, MCKEY_NOACTION
},
241 define_sequences (key_define_t
*kd
)
245 for (i
= 0; kd
[i
].code
; i
++)
246 define_sequence(kd
[i
].code
, kd
[i
].seq
, kd
[i
].action
);
249 #ifdef HAVE_TEXTMODE_X11_SUPPORT
250 static Display
*x11_display
;
251 static Window x11_window
;
252 #endif /* HAVE_TEXTMODE_X11_SUPPORT */
254 /* This has to be called before slang_init or whatever routine
255 calls any define_sequence */
258 char *term
= (char *) getenv ("TERM");
260 /* This has to be the first define_sequence */
261 /* So, we can assume that the first keys member has ESC */
262 define_sequences (mc_default_keys
);
264 /* Terminfo on irix does not have some keys */
265 if ((!strncmp (term
, "iris-ansi", 9)) || (!strncmp (term
, "xterm", 5)))
266 define_sequences (xterm_key_defines
);
268 define_sequences (mc_bindings
);
270 /* load some additional keys (e.g. direct Alt-? support) */
271 load_xtra_key_defines();
274 if (strncmp(term
, "qnx", 3) == 0){
275 /* Modify the default value of use_8th_bit_as_meta: we would
276 * like to provide a working mc for a newbie who knows nothing
277 * about [Options|Display bits|Full 8 bits input]...
279 * Don't use 'meta'-bit, when we are dealing with a
280 * 'qnx*'-type terminal: clear the default value!
281 * These terminal types use 0xFF as an escape character,
282 * so use_8th_bit_as_meta==1 must not be enabled!
284 * [mc-4.1.21+,slint.c/getch(): the DEC_8BIT_HACK stuff
285 * is not used now (doesn't even depend on use_8th_bit_as_meta
286 * as in mc-3.1.2)...GREAT!...no additional code is required!]
288 use_8th_bit_as_meta
= 0;
292 #ifdef HAVE_TEXTMODE_X11_SUPPORT
293 x11_display
= XOpenDisplay (0);
295 x11_window
= DefaultRootWindow (x11_display
);
296 #endif /* HAVE_TEXTMODE_X11_SUPPORT */
299 /* This has to be called after SLang_init_tty/slint_init */
300 void init_key_input_fd (void)
303 input_fd
= SLang_TT_Read_FD
;
309 xmouse_get_event (Gpm_Event
*ev
)
312 static struct timeval tv1
= { 0, 0 }; /* Force first click as single */
313 static struct timeval tv2
;
315 static int last_btn
= 0;
317 /* Decode Xterm mouse information to a GPM style event */
319 /* Variable btn has following meaning: */
320 /* 0 = btn1 dn, 1 = btn2 dn, 2 = btn3 dn, 3 = btn up */
323 /* There seems to be no way of knowing which button was released */
324 /* So we assume all the buttons were released */
328 ev
->type
= GPM_UP
| (GPM_SINGLE
<< clicks
);
334 /* Bogus event, maybe mouse wheel */
340 if (tv1
.tv_sec
&& (DIF_TIME (tv1
,tv2
) < double_click_speed
)){
348 ev
->buttons
= GPM_B_LEFT
;
351 ev
->buttons
= GPM_B_MIDDLE
;
354 ev
->buttons
= GPM_B_RIGHT
;
357 ev
->buttons
= GPM_B_UP
;
360 ev
->buttons
= GPM_B_DOWN
;
368 last_btn
= ev
->buttons
;
370 /* Coordinates are 33-based */
371 /* Transform them to 1-based */
372 ev
->x
= getch () - 32;
373 ev
->y
= getch () - 32;
376 static key_def
*create_sequence (char *seq
, int code
, int action
)
378 key_def
*base
, *p
, *attach
;
380 for (base
= attach
= NULL
; *seq
; seq
++){
381 p
= g_new (key_def
, 1);
383 if (attach
) attach
->child
= p
;
387 p
->child
= p
->next
= NULL
;
391 p
->action
= MCKEY_NOACTION
;
397 /* The maximum sequence length (32 + null terminator) */
398 #define SEQ_BUFFER_LEN 33
399 static int seq_buffer
[SEQ_BUFFER_LEN
];
400 static int *seq_append
= 0;
402 static int push_char (int c
)
405 seq_append
= seq_buffer
;
407 if (seq_append
== &(seq_buffer
[SEQ_BUFFER_LEN
-2]))
415 * Return 1 on success, 0 on error.
416 * An error happens if SEQ is a beginning of an existing longer sequence.
418 int define_sequence (int code
, char *seq
, int action
)
422 if (strlen (seq
) > SEQ_BUFFER_LEN
-1)
425 for (base
= keys
; (base
!= 0) && *seq
; ){
426 if (*seq
== base
->ch
){
427 if (base
->child
== 0){
429 base
->child
= create_sequence (seq
+1, code
, action
);
432 /* The sequence matches an existing one. */
434 base
->action
= action
;
445 base
->next
= create_sequence (seq
, code
, action
);
452 /* Attempt to redefine a sequence with a shorter sequence. */
456 keys
= create_sequence (seq
, code
, action
);
460 static int *pending_keys
;
462 /* Apply corrections for the keycode generated in get_key_code() */
464 correct_key_code (int code
)
466 unsigned int c
= code
& ~KEY_M_MASK
; /* code without modifier */
467 unsigned int mod
= code
& KEY_M_MASK
; /* modifier */
470 * Add key modifiers directly from X11 or OS.
471 * Ordinary characters only get modifiers from sequences.
473 if (c
< 32 || c
>= 256) {
474 mod
|= get_modifier ();
477 /* This is needed if the newline is reported as carriage return */
481 /* This is reported to be useful on AIX */
482 if (c
== KEY_SCANCEL
)
485 /* Convert Shift+Tab and Ctrl+Tab to Back Tab */
486 if ((c
== '\t') && (mod
& (KEY_M_SHIFT
| KEY_M_CTRL
))) {
491 /* F0 is the same as F10 for out purposes */
496 * We are not interested if Ctrl was pressed when entering control
497 * characters, so assume that it was. When checking for such keys,
498 * XCTRL macro should be used. In some cases, we are interested,
499 * e.g. to distinguish Ctrl-Enter from Enter.
501 if (c
< 32 && c
!= ESC_CHAR
&& c
!= '\t' && c
!= '\n') {
505 /* Convert Shift+Fn to F(n+10) */
506 if (c
>= KEY_F (1) && c
<= KEY_F (10) && (mod
& KEY_M_SHIFT
)) {
510 /* Remove Shift information from function keys */
511 if (c
>= KEY_F (1) && c
<= KEY_F (20)) {
515 if (!alternate_plus_minus
)
520 case KEY_KP_SUBTRACT
:
523 case KEY_KP_MULTIPLY
:
531 int get_key_code (int no_delay
)
534 static key_def
*this = NULL
, *parent
;
535 static struct timeval esctime
= { -1, -1 };
536 static int lastnodelay
= -1;
538 if (no_delay
!= lastnodelay
) {
540 lastnodelay
= no_delay
;
545 int d
= *pending_keys
++;
551 if (d
== ESC_CHAR
&& pending_keys
){
552 d
= ALT(*pending_keys
++);
555 if ((d
& 0x80) && use_8th_bit_as_meta
)
558 return correct_key_code (d
);
563 nodelay (stdscr
, TRUE
);
566 #if defined(USE_NCURSES) && defined(KEY_RESIZE)
568 goto nodelay_try_again
;
571 nodelay (stdscr
, FALSE
);
573 if (this != NULL
&& parent
!= NULL
&&
574 parent
->action
== MCKEY_ESCAPE
&& old_esc_mode
) {
575 struct timeval current
, timeout
;
577 if (esctime
.tv_sec
== -1)
580 timeout
.tv_sec
= ESCMODE_TIMEOUT
/ 1000000 + esctime
.tv_sec
;
581 timeout
.tv_usec
= ESCMODE_TIMEOUT
% 1000000 + esctime
.tv_usec
;
582 if (timeout
.tv_usec
> 1000000) {
583 timeout
.tv_usec
-= 1000000;
586 if (current
.tv_sec
< timeout
.tv_sec
)
588 if (current
.tv_sec
== timeout
.tv_sec
&&
589 current
.tv_usec
< timeout
.tv_usec
)
592 pending_keys
= seq_append
= NULL
;
598 /* Maybe we got an incomplete match.
599 This we do only in delay mode, since otherwise
600 getch can return -1 at any time. */
602 pending_keys
= seq_buffer
;
609 /* Search the key on the root */
610 if (!no_delay
|| this == NULL
) {
614 if ((c
& 0x80) && use_8th_bit_as_meta
) {
617 /* The first sequence defined starts with esc */
626 pending_keys
= seq_buffer
;
631 if (parent
->action
== MCKEY_ESCAPE
&& old_esc_mode
) {
635 /* Shouldn't happen */
636 fprintf (stderr
, "Internal error\n");
639 goto nodelay_try_again
;
642 c
= xgetch_second ();
644 pending_keys
= seq_append
= NULL
;
650 goto nodelay_try_again
;
654 /* We got a complete match, return and reset search */
657 pending_keys
= seq_append
= NULL
;
660 return correct_key_code (code
);
666 if (parent
!= NULL
&& parent
->action
== MCKEY_ESCAPE
) {
667 /* This is just to save a lot of define_sequences */
669 || (c
== '\n') || (c
== '\t') || (c
== XCTRL('h'))
670 || (c
== KEY_BACKSPACE
) || (c
== '!') || (c
== '\r')
671 || c
== 127 || c
== '+' || c
== '-' || c
== '\\'
678 pending_keys
= seq_append
= NULL
;
680 return correct_key_code (c
);
682 /* Did not find a match or {c} was changed in the if above,
683 so we have to return everything we had skipped
686 pending_keys
= seq_buffer
;
692 return correct_key_code (c
);
695 /* If set timeout is set, then we wait 0.1 seconds, else, we block */
697 try_channels (int set_timeout
)
699 struct timeval timeout
;
700 static fd_set select_set
;
701 struct timeval
*timeptr
;
706 FD_ZERO (&select_set
);
707 FD_SET (input_fd
, &select_set
); /* Add stdin */
708 maxfdp
= max (add_selects (&select_set
), input_fd
);
712 timeout
.tv_usec
= 100000;
717 v
= select (maxfdp
+ 1, &select_set
, NULL
, NULL
, timeptr
);
719 check_selects (&select_set
);
720 if (FD_ISSET (input_fd
, &select_set
))
726 /* Workaround for System V Curses vt100 bug */
727 static int getch_with_delay (void)
731 /* This routine could be used on systems without mouse support,
732 so we need to do the select check :-( */
737 /* Try to get a character */
738 c
= get_key_code (0);
741 /* Failed -> wait 0.1 secs and try again */
744 /* Success -> return the character */
748 /* Returns a character read from stdin with appropriate interpretation */
749 /* Also takes care of generated mouse events */
750 /* Returns EV_MOUSE if it is a mouse event */
751 /* Returns EV_NONE if non-blocking or interrupt set and nothing was done */
753 get_event (Gpm_Event
* event
, int redo_event
, int block
)
756 static int flag
; /* Return value from select */
758 static Gpm_Event ev
; /* Mouse event */
760 struct timeval timeout
;
761 struct timeval
*time_addr
= NULL
;
762 static int dirty
= 3;
764 if ((dirty
== 3) || is_idle ()) {
771 vfs_timeout_handler ();
773 /* Ok, we use (event->x < 0) to signal that the event does not contain
774 a suitable position for the mouse, so we can't use show_mouse_pointer
778 show_mouse_pointer (event
->x
, event
->y
);
783 /* Repeat if using mouse */
784 while (mouse_enabled
&& !pending_keys
) {
788 FD_ZERO (&select_set
);
789 FD_SET (input_fd
, &select_set
);
790 maxfdp
= max (add_selects (&select_set
), input_fd
);
793 if (use_mouse_p
== MOUSE_GPM
) {
795 /* Connection to gpm broken, possibly gpm has died */
797 use_mouse_p
= MOUSE_NONE
;
800 FD_SET (gpm_fd
, &select_set
);
801 maxfdp
= max (maxfdp
, gpm_fd
);
806 timeout
.tv_usec
= mou_auto_repeat
* 1000;
809 time_addr
= &timeout
;
813 if ((seconds
= vfs_timeouts ())) {
814 /* the timeout could be improved and actually be
815 * the number of seconds until the next vfs entry
816 * timeouts in the stamp list.
819 timeout
.tv_sec
= seconds
;
821 time_addr
= &timeout
;
827 time_addr
= &timeout
;
831 enable_interrupt_key ();
832 flag
= select (maxfdp
+ 1, &select_set
, NULL
, NULL
, time_addr
);
833 disable_interrupt_key ();
835 /* select timed out: it could be for any of the following reasons:
836 * redo_event -> it was because of the MOU_REPEAT handler
837 * !block -> we did not block in the select call
838 * else -> 10 second timeout to check the vfs status.
845 vfs_timeout_handler ();
847 if (flag
== -1 && errno
== EINTR
)
850 check_selects (&select_set
);
852 if (FD_ISSET (input_fd
, &select_set
))
855 if (use_mouse_p
== MOUSE_GPM
&& FD_ISSET (gpm_fd
, &select_set
)) {
861 #endif /* !HAVE_LIBGPM */
864 flag
= is_wintouched (stdscr
);
866 #endif /* !HAVE_SLANG */
867 c
= block
? getch_with_delay () : get_key_code (1);
872 #endif /* !HAVE_SLANG */
877 #endif /* KEY_MOUSE */
880 xmouse_get_event (event
);
890 /* Returns a key press, mouse events are discarded */
897 while ((key
= get_event (&ev
, 0, 1)) == EV_NONE
)
902 static int xgetch_second (void)
906 struct timeval timeout
;
908 timeout
.tv_sec
= ESCMODE_TIMEOUT
/ 1000000;
909 timeout
.tv_usec
= ESCMODE_TIMEOUT
% 1000000;
910 nodelay (stdscr
, TRUE
);
911 FD_ZERO (&Read_FD_Set
);
912 FD_SET (input_fd
, &Read_FD_Set
);
913 select (input_fd
+ 1, &Read_FD_Set
, NULL
, NULL
, &timeout
);
915 nodelay (stdscr
, FALSE
);
920 learn_store_key (char *buffer
, char **p
, int c
)
922 if (*p
- buffer
> 253)
927 } else if (c
< ' ') {
929 *(*p
)++ = c
+ 'a' - 1;
930 } else if (c
== '^') {
937 char *learn_key (void)
939 /* LEARN_TIMEOUT in usec */
940 #define LEARN_TIMEOUT 200000
943 struct timeval endtime
;
944 struct timeval timeout
;
949 keypad(stdscr
, FALSE
); /* disable intepreting keys by ncurses */
952 c
= getch (); /* Sanity check, should be unnecessary */
953 learn_store_key (buffer
, &p
, c
);
955 endtime
.tv_usec
+= LEARN_TIMEOUT
;
956 if (endtime
.tv_usec
> 1000000) {
957 endtime
.tv_usec
-= 1000000;
960 nodelay (stdscr
, TRUE
);
962 while ((c
= getch ()) == -1) {
964 timeout
.tv_usec
= endtime
.tv_usec
- timeout
.tv_usec
;
965 if (timeout
.tv_usec
< 0)
967 timeout
.tv_sec
= endtime
.tv_sec
- timeout
.tv_sec
;
968 if (timeout
.tv_sec
>= 0 && timeout
.tv_usec
> 0) {
969 FD_ZERO (&Read_FD_Set
);
970 FD_SET (input_fd
, &Read_FD_Set
);
971 select (input_fd
+ 1, &Read_FD_Set
, NULL
, NULL
, &timeout
);
977 learn_store_key (buffer
, &p
, c
);
979 keypad(stdscr
, TRUE
);
980 nodelay (stdscr
, FALSE
);
982 return g_strdup (buffer
);
985 /* xterm and linux console only: set keypad to numeric or application
986 mode. Only in application keypad mode it's possible to distinguish
987 the '+' key and the '+' on the keypad ('*' and '-' ditto)*/
989 numeric_keypad_mode (void)
991 if (console_flag
|| xterm_flag
) {
992 fprintf (stdout
, "\033>");
998 application_keypad_mode (void)
1000 if (console_flag
|| xterm_flag
) {
1001 fprintf (stdout
, "\033=");
1008 * Check if we are idle, i.e. there are no pending keyboard or mouse
1009 * events. Return 1 is idle, 0 is there are pending events.
1016 struct timeval timeout
;
1018 FD_ZERO (&select_set
);
1019 FD_SET (input_fd
, &select_set
);
1022 if (use_mouse_p
== MOUSE_GPM
&& mouse_enabled
&& gpm_fd
!= -1) {
1023 FD_SET (gpm_fd
, &select_set
);
1024 maxfdp
= max (maxfdp
, gpm_fd
);
1028 timeout
.tv_usec
= 0;
1029 return (select (maxfdp
+ 1, &select_set
, 0, 0, &timeout
) <= 0);
1034 * Get modifier state (shift, alt, ctrl) for the last key pressed.
1035 * We are assuming that the state didn't change since the key press.
1036 * This is only correct if get_modifier() is called very fast after
1037 * the input was received, so that the user didn't release the
1038 * modifier keys yet.
1045 #ifdef HAVE_TEXTMODE_X11_SUPPORT
1052 XQueryPointer (x11_display
, x11_window
, &root
, &child
, &root_x
,
1053 &root_y
, &win_x
, &win_y
, &mask
);
1055 if (mask
& ShiftMask
)
1056 result
|= KEY_M_SHIFT
;
1057 if (mask
& ControlMask
)
1058 result
|= KEY_M_CTRL
;
1064 unsigned char modifiers
= 6;
1066 if (ioctl (0, TIOCLINUX
, &modifiers
) < 0)
1069 /* Translate Linux modifiers into mc modifiers */
1070 if (modifiers
& SHIFT_PRESSED
)
1071 result
|= KEY_M_SHIFT
;
1072 if (modifiers
& (ALTL_PRESSED
| ALTR_PRESSED
))
1073 result
|= KEY_M_ALT
;
1074 if (modifiers
& CONTROL_PRESSED
)
1075 result
|= KEY_M_CTRL
;
1084 static void k_dispose (key_def
*k
)
1088 k_dispose (k
->child
);
1089 k_dispose (k
->next
);
1093 static void s_dispose (SelectList
*sel
)
1098 s_dispose (sel
->next
);
1105 s_dispose (select_list
);
1107 #ifdef HAVE_TEXTMODE_X11_SUPPORT
1109 XCloseDisplay (x11_display
);
1110 #endif /* HAVE_TEXTMODE_X11_SUPPORT */