2011-10-15 14:56:47 +04:00
|
|
|
/*
|
|
|
|
Keyboard support routines.
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2023-01-03 11:30:57 +03:00
|
|
|
Copyright (C) 1994-2023
|
2014-02-12 10:33:10 +04:00
|
|
|
Free Software Foundation, Inc.
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2011-10-15 14:56:47 +04:00
|
|
|
Written by:
|
|
|
|
Miguel de Icaza, 1994, 1995
|
|
|
|
Janne Kukonlehto, 1994, 1995
|
|
|
|
Jakub Jelinek, 1995
|
|
|
|
Norbert Warmuth, 1997
|
2013-05-20 16:34:21 +04:00
|
|
|
Denys Vlasenko <vda.linux@googlemail.com>, 2013
|
|
|
|
Slava Zanko <slavazanko@gmail.com>, 2013
|
2013-10-01 13:31:13 +04:00
|
|
|
Egmont Koblinger <egmont@gmail.com>, 2013
|
2006-01-07 15:49:08 +03:00
|
|
|
|
2011-10-15 14:56:47 +04:00
|
|
|
This file is part of the Midnight Commander.
|
2006-01-07 15:49:08 +03:00
|
|
|
|
2011-10-15 14:56:47 +04:00
|
|
|
The Midnight Commander is free software: you can redistribute it
|
|
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
|
|
published by the Free Software Foundation, either version 3 of the License,
|
|
|
|
or (at your option) any later version.
|
|
|
|
|
|
|
|
The Midnight Commander is distributed in the hope that it will be useful,
|
1998-02-27 07:54:42 +03:00
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
2011-10-15 14:56:47 +04:00
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2009-02-05 21:28:18 +03:00
|
|
|
/** \file key.c
|
|
|
|
* \brief Source: keyboard support routines
|
|
|
|
*/
|
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
#include <config.h>
|
2005-02-08 12:04:03 +03:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
#include <ctype.h>
|
|
|
|
#include <errno.h>
|
2005-02-08 12:04:03 +03:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2019-09-22 17:29:50 +03:00
|
|
|
#ifdef HAVE_SYS_SELECT_H
|
|
|
|
#include <sys/select.h>
|
|
|
|
#else
|
2009-02-06 02:30:45 +03:00
|
|
|
#include <sys/time.h>
|
2005-02-08 12:04:03 +03:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
2019-09-22 17:29:50 +03:00
|
|
|
#endif
|
2001-09-07 21:52:19 +04:00
|
|
|
|
2010-01-20 18:11:52 +03:00
|
|
|
#include "lib/global.h"
|
2010-01-21 15:17:26 +03:00
|
|
|
|
2011-02-15 16:44:17 +03:00
|
|
|
#include "lib/vfs/vfs.h"
|
2010-01-21 15:17:26 +03:00
|
|
|
|
2010-01-07 02:57:27 +03:00
|
|
|
#include "tty.h"
|
2010-11-08 13:21:45 +03:00
|
|
|
#include "tty-internal.h" /* mouse_enabled */
|
2010-01-07 02:57:27 +03:00
|
|
|
#include "mouse.h"
|
|
|
|
#include "key.h"
|
2009-05-08 14:01:05 +04:00
|
|
|
|
2011-02-18 14:30:15 +03:00
|
|
|
#include "lib/widget.h" /* mc_refresh() */
|
2003-11-08 02:50:18 +03:00
|
|
|
|
2001-06-05 20:41:44 +04:00
|
|
|
#ifdef HAVE_TEXTMODE_X11_SUPPORT
|
2010-01-07 02:57:27 +03:00
|
|
|
#include "x11conn.h"
|
1999-04-21 23:18:31 +04:00
|
|
|
#endif
|
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
#ifdef __linux__
|
2009-07-04 14:48:39 +04:00
|
|
|
#if defined(__GLIBC__) && (__GLIBC__ < 2)
|
2010-11-08 13:21:45 +03:00
|
|
|
#include <linux/termios.h> /* TIOCLINUX */
|
2010-01-02 12:00:26 +03:00
|
|
|
#else
|
2010-11-08 13:21:45 +03:00
|
|
|
#include <termios.h>
|
2009-07-04 14:48:39 +04:00
|
|
|
#endif
|
2012-10-16 14:09:17 +04:00
|
|
|
#ifdef HAVE_SYS_IOCTL_H
|
2009-07-04 14:48:39 +04:00
|
|
|
#include <sys/ioctl.h>
|
2012-10-16 14:09:17 +04:00
|
|
|
#endif
|
2009-09-17 02:07:04 +04:00
|
|
|
#endif /* __linux__ */
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2004-09-14 21:18:25 +04:00
|
|
|
#ifdef __CYGWIN__
|
2009-07-04 14:48:39 +04:00
|
|
|
#include <termios.h>
|
2012-10-16 14:09:17 +04:00
|
|
|
#ifdef HAVE_SYS_IOCTL_H
|
2009-07-04 14:48:39 +04:00
|
|
|
#include <sys/ioctl.h>
|
2012-10-16 14:09:17 +04:00
|
|
|
#endif
|
2009-09-17 02:07:04 +04:00
|
|
|
#endif /* __CYGWIN__ */
|
2004-09-14 21:18:25 +04:00
|
|
|
|
2003-02-23 08:36:49 +03:00
|
|
|
#ifdef __QNXNTO__
|
2009-07-04 14:48:39 +04:00
|
|
|
#include <dlfcn.h>
|
|
|
|
#include <Ph.h>
|
|
|
|
#include <sys/dcmd_chr.h>
|
2009-09-17 02:07:04 +04:00
|
|
|
#endif /* __QNXNTO__ */
|
2006-01-07 15:49:08 +03:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/*** global variables ****************************************************************************/
|
2002-12-21 11:43:15 +03:00
|
|
|
|
2021-10-02 13:09:34 +03:00
|
|
|
int mou_auto_repeat = 100; /* ms */
|
|
|
|
int double_click_speed = 250; /* ms */
|
2016-11-25 09:17:03 +03:00
|
|
|
gboolean old_esc_mode = TRUE;
|
2011-11-25 12:54:21 +04:00
|
|
|
/* timeout for old_esc_mode in usec */
|
2021-10-02 13:09:34 +03:00
|
|
|
int old_esc_mode_timeout = G_USEC_PER_SEC; /* us, settable via env */
|
2016-11-25 09:17:03 +03:00
|
|
|
gboolean use_8th_bit_as_meta = FALSE;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2013-10-01 13:31:13 +04:00
|
|
|
gboolean bracketed_pasting_in_progress = FALSE;
|
|
|
|
|
2009-10-09 15:46:08 +04:00
|
|
|
/* This table is a mapping between names and the constants we use
|
|
|
|
* We use this to allow users to define alternate definitions for
|
|
|
|
* certain keys that may be missing from the terminal database
|
2009-07-04 14:48:39 +04:00
|
|
|
*/
|
2009-11-03 19:39:16 +03:00
|
|
|
const key_code_name_t key_name_conv_tab[] = {
|
2014-01-04 10:47:46 +04:00
|
|
|
{ESC_CHAR, "escape", N_("Escape"), "Esc"},
|
2009-10-09 15:46:08 +04:00
|
|
|
/* KEY_F(0) is not here, since we are mapping it to f10, so there is no reason
|
2010-11-08 13:21:45 +03:00
|
|
|
to define f0 as well. Also, it makes Learn keys a bunch of problems :( */
|
|
|
|
{KEY_F (1), "f1", N_("Function key 1"), "F1"},
|
|
|
|
{KEY_F (2), "f2", N_("Function key 2"), "F2"},
|
|
|
|
{KEY_F (3), "f3", N_("Function key 3"), "F3"},
|
|
|
|
{KEY_F (4), "f4", N_("Function key 4"), "F4"},
|
|
|
|
{KEY_F (5), "f5", N_("Function key 5"), "F5"},
|
|
|
|
{KEY_F (6), "f6", N_("Function key 6"), "F6"},
|
|
|
|
{KEY_F (7), "f7", N_("Function key 7"), "F7"},
|
|
|
|
{KEY_F (8), "f8", N_("Function key 8"), "F8"},
|
|
|
|
{KEY_F (9), "f9", N_("Function key 9"), "F9"},
|
|
|
|
{KEY_F (10), "f10", N_("Function key 10"), "F10"},
|
|
|
|
{KEY_F (11), "f11", N_("Function key 11"), "F11"},
|
|
|
|
{KEY_F (12), "f12", N_("Function key 12"), "F12"},
|
|
|
|
{KEY_F (13), "f13", N_("Function key 13"), "F13"},
|
|
|
|
{KEY_F (14), "f14", N_("Function key 14"), "F14"},
|
|
|
|
{KEY_F (15), "f15", N_("Function key 15"), "F15"},
|
|
|
|
{KEY_F (16), "f16", N_("Function key 16"), "F16"},
|
|
|
|
{KEY_F (17), "f17", N_("Function key 17"), "F17"},
|
|
|
|
{KEY_F (18), "f18", N_("Function key 18"), "F18"},
|
|
|
|
{KEY_F (19), "f19", N_("Function key 19"), "F19"},
|
|
|
|
{KEY_F (20), "f20", N_("Function key 20"), "F20"},
|
|
|
|
{ALT ('\t'), "complete", N_("Completion/M-tab"), "Meta-Tab"},
|
2014-01-04 10:47:46 +04:00
|
|
|
{KEY_BTAB, "backtab", N_("BackTab/S-tab"), "Shift-Tab"},
|
|
|
|
{KEY_BACKSPACE, "backspace", N_("Backspace"), "Backspace"},
|
|
|
|
{KEY_UP, "up", N_("Up arrow"), "Up"},
|
|
|
|
{KEY_DOWN, "down", N_("Down arrow"), "Down"},
|
|
|
|
{KEY_LEFT, "left", N_("Left arrow"), "Left"},
|
|
|
|
{KEY_RIGHT, "right", N_("Right arrow"), "Right"},
|
|
|
|
{KEY_IC, "insert", N_("Insert"), "Ins"},
|
|
|
|
{KEY_DC, "delete", N_("Delete"), "Del"},
|
|
|
|
{KEY_HOME, "home", N_("Home"), "Home"},
|
|
|
|
{KEY_END, "end", N_("End key"), "End"},
|
|
|
|
{KEY_PPAGE, "pgup", N_("Page Up"), "PgUp"},
|
|
|
|
{KEY_NPAGE, "pgdn", N_("Page Down"), "PgDn"},
|
|
|
|
{(int) '/', "kpslash", N_("/ on keypad"), "/"},
|
2010-11-08 13:21:45 +03:00
|
|
|
{KEY_KP_MULTIPLY, "kpasterisk", N_("* on keypad"), "*"},
|
2014-01-04 10:47:46 +04:00
|
|
|
{KEY_KP_SUBTRACT, "kpminus", N_("- on keypad"), "-"},
|
|
|
|
{KEY_KP_ADD, "kpplus", N_("+ on keypad"), "+"},
|
2009-10-09 15:46:08 +04:00
|
|
|
|
|
|
|
/* From here on, these won't be shown in Learn keys (no space) */
|
2010-11-08 13:21:45 +03:00
|
|
|
{KEY_LEFT, "kpleft", N_("Left arrow keypad"), "Left"},
|
|
|
|
{KEY_RIGHT, "kpright", N_("Right arrow keypad"), "Right"},
|
|
|
|
{KEY_UP, "kpup", N_("Up arrow keypad"), "Up"},
|
|
|
|
{KEY_DOWN, "kpdown", N_("Down arrow keypad"), "Down"},
|
|
|
|
{KEY_HOME, "kphome", N_("Home on keypad"), "Home"},
|
|
|
|
{KEY_END, "kpend", N_("End on keypad"), "End"},
|
|
|
|
{KEY_NPAGE, "kpnpage", N_("Page Down keypad"), "PgDn"},
|
|
|
|
{KEY_PPAGE, "kpppage", N_("Page Up keypad"), "PgUp"},
|
|
|
|
{KEY_IC, "kpinsert", N_("Insert on keypad"), "Ins"},
|
|
|
|
{KEY_DC, "kpdelete", N_("Delete on keypad"), "Del"},
|
|
|
|
{(int) '\n', "kpenter", N_("Enter on keypad"), "Enter"},
|
|
|
|
{KEY_F (21), "f21", N_("Function key 21"), "F21"},
|
|
|
|
{KEY_F (22), "f22", N_("Function key 22"), "F22"},
|
|
|
|
{KEY_F (23), "f23", N_("Function key 23"), "F23"},
|
|
|
|
{KEY_F (24), "f24", N_("Function key 24"), "F24"},
|
|
|
|
{KEY_A1, "a1", N_("A1 key"), "A1"},
|
|
|
|
{KEY_C1, "c1", N_("C1 key"), "C1"},
|
2009-10-09 15:46:08 +04:00
|
|
|
|
|
|
|
/* Alternative label */
|
2014-01-04 10:47:46 +04:00
|
|
|
{ESC_CHAR, "esc", N_("Escape"), "Esc"},
|
|
|
|
{KEY_BACKSPACE, "bs", N_("Backspace"), "Bakspace"},
|
|
|
|
{KEY_IC, "ins", N_("Insert"), "Ins"},
|
|
|
|
{KEY_DC, "del", N_("Delete"), "Del"},
|
2010-11-08 13:21:45 +03:00
|
|
|
{(int) '*', "asterisk", N_("Asterisk"), "*"},
|
2014-01-04 10:47:46 +04:00
|
|
|
{(int) '-', "minus", N_("Minus"), "-"},
|
|
|
|
{(int) '+', "plus", N_("Plus"), "+"},
|
2010-11-08 13:21:45 +03:00
|
|
|
{(int) '.', "dot", N_("Dot"), "."},
|
|
|
|
{(int) '<', "lt", N_("Less than"), "<"},
|
|
|
|
{(int) '>', "gt", N_("Great than"), ">"},
|
|
|
|
{(int) '=', "equal", N_("Equal"), "="},
|
|
|
|
{(int) ',', "comma", N_("Comma"), ","},
|
|
|
|
{(int) '\'', "apostrophe", N_("Apostrophe"), "\'"},
|
|
|
|
{(int) ':', "colon", N_("Colon"), ":"},
|
2014-09-04 11:35:36 +04:00
|
|
|
{(int) ';', "semicolon", N_("Semicolon"), ";"},
|
2010-11-08 13:21:45 +03:00
|
|
|
{(int) '!', "exclamation", N_("Exclamation mark"), "!"},
|
|
|
|
{(int) '?', "question", N_("Question mark"), "?"},
|
|
|
|
{(int) '&', "ampersand", N_("Ampersand"), "&"},
|
|
|
|
{(int) '$', "dollar", N_("Dollar sign"), "$"},
|
|
|
|
{(int) '"', "quota", N_("Quotation mark"), "\""},
|
2011-10-09 11:07:00 +04:00
|
|
|
{(int) '%', "percent", N_("Percent sign"), "%"},
|
2010-11-08 13:21:45 +03:00
|
|
|
{(int) '^', "caret", N_("Caret"), "^"},
|
|
|
|
{(int) '~', "tilda", N_("Tilda"), "~"},
|
|
|
|
{(int) '`', "prime", N_("Prime"), "`"},
|
|
|
|
{(int) '_', "underline", N_("Underline"), "_"},
|
|
|
|
{(int) '_', "understrike", N_("Understrike"), "_"},
|
|
|
|
{(int) '|', "pipe", N_("Pipe"), "|"},
|
|
|
|
{(int) '(', "lparenthesis", N_("Left parenthesis"), "("},
|
|
|
|
{(int) ')', "rparenthesis", N_("Right parenthesis"), ")"},
|
|
|
|
{(int) '[', "lbracket", N_("Left bracket"), "["},
|
|
|
|
{(int) ']', "rbracket", N_("Right bracket"), "]"},
|
|
|
|
{(int) '{', "lbrace", N_("Left brace"), "{"},
|
|
|
|
{(int) '}', "rbrace", N_("Right brace"), "}"},
|
|
|
|
{(int) '\n', "enter", N_("Enter"), "Enter"},
|
|
|
|
{(int) '\t', "tab", N_("Tab key"), "Tab"},
|
|
|
|
{(int) ' ', "space", N_("Space key"), "Space"},
|
|
|
|
{(int) '/', "slash", N_("Slash key"), "/"},
|
|
|
|
{(int) '\\', "backslash", N_("Backslash key"), "\\"},
|
|
|
|
{(int) '#', "number", N_("Number sign #"), "#"},
|
|
|
|
{(int) '#', "hash", N_("Number sign #"), "#"},
|
2010-11-02 13:34:08 +03:00
|
|
|
/* TRANSLATORS: Please translate as in "at sign" (@). */
|
2010-11-08 13:21:45 +03:00
|
|
|
{(int) '@', "at", N_("At sign"), "@"},
|
2009-10-09 15:46:08 +04:00
|
|
|
|
|
|
|
/* meta keys */
|
2010-11-08 13:21:45 +03:00
|
|
|
{KEY_M_CTRL, "control", N_("Ctrl"), "C"},
|
|
|
|
{KEY_M_CTRL, "ctrl", N_("Ctrl"), "C"},
|
|
|
|
{KEY_M_ALT, "meta", N_("Alt"), "M"},
|
|
|
|
{KEY_M_ALT, "alt", N_("Alt"), "M"},
|
|
|
|
{KEY_M_ALT, "ralt", N_("Alt"), "M"},
|
|
|
|
{KEY_M_SHIFT, "shift", N_("Shift"), "S"},
|
|
|
|
|
|
|
|
{0, NULL, NULL, NULL}
|
2009-07-04 14:48:39 +04:00
|
|
|
};
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/*** file scope macro definitions ****************************************************************/
|
2009-07-04 14:48:39 +04:00
|
|
|
|
2021-10-02 13:09:34 +03:00
|
|
|
#define MC_USEC_PER_MSEC 1000
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
/* The maximum sequence length (32 + null terminator) */
|
|
|
|
#define SEQ_BUFFER_LEN 33
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/*** file scope type declarations ****************************************************************/
|
2009-07-04 14:48:39 +04:00
|
|
|
|
|
|
|
/* Linux console keyboard modifiers */
|
2010-11-08 13:21:45 +03:00
|
|
|
typedef enum
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
SHIFT_PRESSED = (1 << 0),
|
|
|
|
ALTR_PRESSED = (1 << 1),
|
|
|
|
CONTROL_PRESSED = (1 << 2),
|
|
|
|
ALTL_PRESSED = (1 << 3)
|
2009-07-04 14:48:39 +04:00
|
|
|
} mod_pressed_t;
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
typedef struct key_def
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
char ch; /* Holds the matching char code */
|
|
|
|
int code; /* The code returned, valid if child == NULL */
|
1998-02-27 07:54:42 +03:00
|
|
|
struct key_def *next;
|
2009-09-17 02:07:04 +04:00
|
|
|
struct key_def *child; /* sequence continuation */
|
|
|
|
int action; /* optional action to be done. Now used only
|
|
|
|
to mark that we are just after the first
|
|
|
|
Escape */
|
1998-02-27 07:54:42 +03:00
|
|
|
} key_def;
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
typedef struct
|
|
|
|
{
|
2009-07-04 14:48:39 +04:00
|
|
|
int code;
|
|
|
|
const char *seq;
|
|
|
|
int action;
|
|
|
|
} key_define_t;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
/* File descriptor monitoring add/remove routines */
|
2019-04-09 13:56:57 +03:00
|
|
|
typedef struct
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
1998-02-27 07:54:42 +03:00
|
|
|
int fd;
|
|
|
|
select_fn callback;
|
|
|
|
void *info;
|
2019-04-09 13:56:57 +03:00
|
|
|
} select_t;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2011-01-22 00:36:29 +03:00
|
|
|
typedef enum KeySortType
|
|
|
|
{
|
|
|
|
KEY_NOSORT = 0,
|
|
|
|
KEY_SORTBYNAME,
|
|
|
|
KEY_SORTBYCODE
|
|
|
|
} KeySortType;
|
|
|
|
|
2003-03-10 11:47:37 +03:00
|
|
|
#ifdef __QNXNTO__
|
2009-07-04 14:48:39 +04:00
|
|
|
typedef int (*ph_dv_f) (void *, void *);
|
|
|
|
typedef int (*ph_ov_f) (void *);
|
|
|
|
typedef int (*ph_pqc_f) (unsigned short, PhCursorInfo_t *);
|
2003-03-10 11:47:37 +03:00
|
|
|
#endif
|
|
|
|
|
Update template for .c files.
Add section for forward declarations of local functions. This section is
located before file scope variables because functions can be used in
strucutres (see find.c for example):
/*** forward declarations (file scope functions) *************************************************/
/* button callbacks */
static int start_stop (WButton * button, int action);
static int find_do_view_file (WButton * button, int action);
static int find_do_edit_file (WButton * button, int action);
/*** file scope variables ************************************************************************/
static struct
{
...
bcback_fn callback;
} fbuts[] =
{
...
{ B_STOP, NORMAL_BUTTON, N_("S&uspend"), 0, 0, NULL, start_stop },
...
{ B_VIEW, NORMAL_BUTTON, N_("&View - F3"), 0, 0, NULL, find_do_view_file },
{ B_VIEW, NORMAL_BUTTON, N_("&Edit - F4"), 0, 0, NULL, find_do_edit_file }
};
Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
2023-02-24 09:27:11 +03:00
|
|
|
/*** forward declarations (file scope functions) *************************************************/
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/*** file scope variables ************************************************************************/
|
2009-05-24 13:39:14 +04:00
|
|
|
|
2009-09-17 02:07:04 +04:00
|
|
|
static key_define_t mc_default_keys[] = {
|
|
|
|
{ESC_CHAR, ESC_STR, MCKEY_ESCAPE},
|
|
|
|
{ESC_CHAR, ESC_STR ESC_STR, MCKEY_NOACTION},
|
2013-10-01 13:31:13 +04:00
|
|
|
{MCKEY_BRACKETED_PASTING_START, ESC_STR "[200~", MCKEY_NOACTION},
|
|
|
|
{MCKEY_BRACKETED_PASTING_END, ESC_STR "[201~", MCKEY_NOACTION},
|
2009-09-17 02:07:04 +04:00
|
|
|
{0, NULL, MCKEY_NOACTION},
|
2009-07-04 14:48:39 +04:00
|
|
|
};
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
/* Broken terminfo and termcap databases on xterminals */
|
2009-09-17 02:07:04 +04:00
|
|
|
static key_define_t xterm_key_defines[] = {
|
|
|
|
{KEY_F (1), ESC_STR "OP", MCKEY_NOACTION},
|
|
|
|
{KEY_F (2), ESC_STR "OQ", MCKEY_NOACTION},
|
|
|
|
{KEY_F (3), ESC_STR "OR", MCKEY_NOACTION},
|
|
|
|
{KEY_F (4), ESC_STR "OS", MCKEY_NOACTION},
|
|
|
|
{KEY_F (1), ESC_STR "[11~", MCKEY_NOACTION},
|
|
|
|
{KEY_F (2), ESC_STR "[12~", MCKEY_NOACTION},
|
|
|
|
{KEY_F (3), ESC_STR "[13~", MCKEY_NOACTION},
|
|
|
|
{KEY_F (4), ESC_STR "[14~", MCKEY_NOACTION},
|
|
|
|
{KEY_F (5), ESC_STR "[15~", MCKEY_NOACTION},
|
|
|
|
{KEY_F (6), ESC_STR "[17~", MCKEY_NOACTION},
|
|
|
|
{KEY_F (7), ESC_STR "[18~", MCKEY_NOACTION},
|
|
|
|
{KEY_F (8), ESC_STR "[19~", MCKEY_NOACTION},
|
|
|
|
{KEY_F (9), ESC_STR "[20~", MCKEY_NOACTION},
|
|
|
|
{KEY_F (10), ESC_STR "[21~", MCKEY_NOACTION},
|
2002-12-21 10:34:49 +03:00
|
|
|
|
2003-09-23 10:58:34 +04:00
|
|
|
/* old xterm Shift-arrows */
|
2009-09-17 02:07:04 +04:00
|
|
|
{KEY_M_SHIFT | KEY_UP, ESC_STR "O2A", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_DOWN, ESC_STR "O2B", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_RIGHT, ESC_STR "O2C", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_LEFT, ESC_STR "O2D", MCKEY_NOACTION},
|
2003-07-23 09:44:25 +04:00
|
|
|
|
2003-09-23 10:58:34 +04:00
|
|
|
/* new xterm Shift-arrows */
|
2009-09-17 02:07:04 +04:00
|
|
|
{KEY_M_SHIFT | KEY_UP, ESC_STR "[1;2A", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_DOWN, ESC_STR "[1;2B", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_RIGHT, ESC_STR "[1;2C", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_LEFT, ESC_STR "[1;2D", MCKEY_NOACTION},
|
2003-09-23 10:58:34 +04:00
|
|
|
|
|
|
|
/* more xterm keys with modifiers */
|
2009-09-17 02:07:04 +04:00
|
|
|
{KEY_M_CTRL | KEY_PPAGE, ESC_STR "[5;5~", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_NPAGE, ESC_STR "[6;5~", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_IC, ESC_STR "[2;5~", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_DC, ESC_STR "[3;5~", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_HOME, ESC_STR "[1;5H", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_END, ESC_STR "[1;5F", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_HOME, ESC_STR "[1;2H", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_END, ESC_STR "[1;2F", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_UP, ESC_STR "[1;5A", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_DOWN, ESC_STR "[1;5B", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_RIGHT, ESC_STR "[1;5C", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_LEFT, ESC_STR "[1;5D", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_IC, ESC_STR "[2;2~", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_DC, ESC_STR "[3;2~", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_M_CTRL | KEY_UP, ESC_STR "[1;6A", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_M_CTRL | KEY_DOWN, ESC_STR "[1;6B", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_M_CTRL | KEY_RIGHT, ESC_STR "[1;6C", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_M_CTRL | KEY_LEFT, ESC_STR "[1;6D", MCKEY_NOACTION},
|
Handle newline and tab with shift/ctrl modifiers correctly.
MC already has its own half-ready trick: when pasting with Shift-Insert,
using the X11 extension, the newline ("Enter" as mc calls it) with the
Shift modifier pressed gets converted to a "Return", and in the editor
the Return character inserts a non-indenting newline. This makes pasting
better in terminals not supporting bracketed paste, however, it has some
problems that this commit addresses:
* Shift+newline gets this special treatment, but Ctrl+newline gets
dropped. Hence e.g. when pasting in Gnome-terminal with Ctrl+Shift+V
all the newlines will be missing. This commit adds the same
non-indenting newline behavior to Ctrl+Newline and Ctrl+Shift+Newline.
* The code forgets about Tab that also needs special treatment:
- Most terminals send \e[Z on Shift+Tab, this is not handled by MC
at all, moreover it causes a hang for about a second. This commit
teaches this sequence to MC. This is especially useful when no X11
is available, because there Ctrl+Tab is identical to Tab, so the
backwards tab feature is not available. With this commit Shift+Tab
becomes a backwards tab too on all terminals that emit \e[Z.
- When pasting to the editor, Shift+Tab, Ctrl+Tab and Ctrl+Shift+Tab
should all insert a tab for the same reason mentioned at the newline.
- It would look inconsistent in the keymap files to have logical code
such as "backtab" instead of "shift-tab" and friends, hence get rid
of KEY_BTAB and use KEY_M_SHIFT | '\t' instead.
Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
2013-10-01 14:09:14 +04:00
|
|
|
{KEY_M_SHIFT | '\t', ESC_STR "[Z", MCKEY_NOACTION},
|
2002-12-21 10:34:49 +03:00
|
|
|
|
2009-03-26 00:32:25 +03:00
|
|
|
/* putty */
|
2009-09-17 02:07:04 +04:00
|
|
|
{KEY_M_SHIFT | KEY_M_CTRL | KEY_UP, ESC_STR "[[1;6A", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_M_CTRL | KEY_DOWN, ESC_STR "[[1;6B", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_M_CTRL | KEY_RIGHT, ESC_STR "[[1;6C", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_M_CTRL | KEY_LEFT, ESC_STR "[[1;6D", MCKEY_NOACTION},
|
2009-03-26 00:32:25 +03:00
|
|
|
|
2009-06-12 16:54:52 +04:00
|
|
|
/* putty alt-arrow keys */
|
2009-06-18 14:41:21 +04:00
|
|
|
/* removed as source esc esc esc trouble */
|
|
|
|
/*
|
2009-09-17 02:07:04 +04:00
|
|
|
{ KEY_M_ALT | KEY_UP, ESC_STR ESC_STR "OA", MCKEY_NOACTION },
|
|
|
|
{ KEY_M_ALT | KEY_DOWN, ESC_STR ESC_STR "OB", MCKEY_NOACTION },
|
|
|
|
{ KEY_M_ALT | KEY_RIGHT, ESC_STR ESC_STR "OC", MCKEY_NOACTION },
|
|
|
|
{ KEY_M_ALT | KEY_LEFT, ESC_STR ESC_STR "OD", MCKEY_NOACTION },
|
|
|
|
{ KEY_M_ALT | KEY_PPAGE, ESC_STR ESC_STR "[5~", MCKEY_NOACTION },
|
|
|
|
{ KEY_M_ALT | KEY_NPAGE, ESC_STR ESC_STR "[6~", MCKEY_NOACTION },
|
|
|
|
{ KEY_M_ALT | KEY_HOME, ESC_STR ESC_STR "[1~", MCKEY_NOACTION },
|
|
|
|
{ KEY_M_ALT | KEY_END, ESC_STR ESC_STR "[4~", MCKEY_NOACTION },
|
|
|
|
|
|
|
|
{ KEY_M_CTRL | KEY_M_ALT | KEY_UP, ESC_STR ESC_STR "[1;2A", MCKEY_NOACTION },
|
|
|
|
{ KEY_M_CTRL | KEY_M_ALT | KEY_DOWN, ESC_STR ESC_STR "[1;2B", MCKEY_NOACTION },
|
|
|
|
{ KEY_M_CTRL | KEY_M_ALT | KEY_RIGHT, ESC_STR ESC_STR "[1;2C", MCKEY_NOACTION },
|
|
|
|
{ KEY_M_CTRL | KEY_M_ALT | KEY_LEFT, ESC_STR ESC_STR "[1;2D", MCKEY_NOACTION },
|
|
|
|
|
|
|
|
{ KEY_M_CTRL | KEY_M_ALT | KEY_PPAGE, ESC_STR ESC_STR "[[5;5~", MCKEY_NOACTION },
|
|
|
|
{ KEY_M_CTRL | KEY_M_ALT | KEY_NPAGE, ESC_STR ESC_STR "[[6;5~", MCKEY_NOACTION },
|
|
|
|
{ KEY_M_CTRL | KEY_M_ALT | KEY_HOME, ESC_STR ESC_STR "[1;5H", MCKEY_NOACTION },
|
|
|
|
{ KEY_M_CTRL | KEY_M_ALT | KEY_END, ESC_STR ESC_STR "[1;5F", MCKEY_NOACTION },
|
|
|
|
*/
|
2009-06-12 16:54:52 +04:00
|
|
|
/* xterm alt-arrow keys */
|
2009-09-17 02:07:04 +04:00
|
|
|
{KEY_M_ALT | KEY_UP, ESC_STR "[1;3A", MCKEY_NOACTION},
|
|
|
|
{KEY_M_ALT | KEY_DOWN, ESC_STR "[1;3B", MCKEY_NOACTION},
|
|
|
|
{KEY_M_ALT | KEY_RIGHT, ESC_STR "[1;3C", MCKEY_NOACTION},
|
|
|
|
{KEY_M_ALT | KEY_LEFT, ESC_STR "[1;3D", MCKEY_NOACTION},
|
|
|
|
{KEY_M_ALT | KEY_PPAGE, ESC_STR "[5;3~", MCKEY_NOACTION},
|
|
|
|
{KEY_M_ALT | KEY_NPAGE, ESC_STR "[6;3~", MCKEY_NOACTION},
|
|
|
|
{KEY_M_ALT | KEY_HOME, ESC_STR "[1~", MCKEY_NOACTION},
|
|
|
|
{KEY_M_ALT | KEY_END, ESC_STR "[4~", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_M_ALT | KEY_UP, ESC_STR "[1;7A", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_M_ALT | KEY_DOWN, ESC_STR "[1;7B", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_M_ALT | KEY_RIGHT, ESC_STR "[1;7C", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_M_ALT | KEY_LEFT, ESC_STR "[1;7D", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_M_ALT | KEY_PPAGE, ESC_STR "[5;7~", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_M_ALT | KEY_NPAGE, ESC_STR "[6;7~", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_M_ALT | KEY_HOME, ESC_STR "OH", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_M_ALT | KEY_END, ESC_STR "OF", MCKEY_NOACTION},
|
2009-06-12 16:54:52 +04:00
|
|
|
|
2021-11-13 19:24:59 +03:00
|
|
|
{KEY_M_SHIFT | KEY_M_ALT | KEY_UP, ESC_STR "[1;4A", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_M_ALT | KEY_DOWN, ESC_STR "[1;4B", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_M_ALT | KEY_RIGHT, ESC_STR "[1;4C", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_M_ALT | KEY_LEFT, ESC_STR "[1;4D", MCKEY_NOACTION},
|
|
|
|
|
2002-12-21 10:34:49 +03:00
|
|
|
/* rxvt keys with modifiers */
|
2009-09-17 02:07:04 +04:00
|
|
|
{KEY_M_SHIFT | KEY_UP, ESC_STR "[a", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_DOWN, ESC_STR "[b", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_RIGHT, ESC_STR "[c", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_LEFT, ESC_STR "[d", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_UP, ESC_STR "Oa", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_DOWN, ESC_STR "Ob", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_RIGHT, ESC_STR "Oc", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_LEFT, ESC_STR "Od", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_PPAGE, ESC_STR "[5^", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_NPAGE, ESC_STR "[6^", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_HOME, ESC_STR "[7^", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_END, ESC_STR "[8^", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_HOME, ESC_STR "[7$", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_END, ESC_STR "[8$", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_IC, ESC_STR "[2^", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_DC, ESC_STR "[3^", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_DC, ESC_STR "[3$", MCKEY_NOACTION},
|
2003-03-14 19:52:33 +03:00
|
|
|
|
|
|
|
/* konsole keys with modifiers */
|
2009-09-17 02:07:04 +04:00
|
|
|
{KEY_M_SHIFT | KEY_HOME, ESC_STR "O2H", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_END, ESC_STR "O2F", MCKEY_NOACTION},
|
2002-12-21 10:34:49 +03:00
|
|
|
|
2003-09-23 10:58:34 +04:00
|
|
|
/* gnome-terminal */
|
2009-09-17 02:07:04 +04:00
|
|
|
{KEY_M_SHIFT | KEY_UP, ESC_STR "[2A", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_DOWN, ESC_STR "[2B", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_RIGHT, ESC_STR "[2C", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_LEFT, ESC_STR "[2D", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_UP, ESC_STR "[5A", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_DOWN, ESC_STR "[5B", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_RIGHT, ESC_STR "[5C", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_LEFT, ESC_STR "[5D", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_M_CTRL | KEY_UP, ESC_STR "[6A", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_M_CTRL | KEY_DOWN, ESC_STR "[6B", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_M_CTRL | KEY_RIGHT, ESC_STR "[6C", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_M_CTRL | KEY_LEFT, ESC_STR "[6D", MCKEY_NOACTION},
|
2003-09-23 10:58:34 +04:00
|
|
|
|
2003-09-24 11:06:08 +04:00
|
|
|
/* gnome-terminal - application mode */
|
2009-09-17 02:07:04 +04:00
|
|
|
{KEY_M_CTRL | KEY_UP, ESC_STR "O5A", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_DOWN, ESC_STR "O5B", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_RIGHT, ESC_STR "O5C", MCKEY_NOACTION},
|
|
|
|
{KEY_M_CTRL | KEY_LEFT, ESC_STR "O5D", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_M_CTRL | KEY_UP, ESC_STR "O6A", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_M_CTRL | KEY_DOWN, ESC_STR "O6B", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_M_CTRL | KEY_RIGHT, ESC_STR "O6C", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_M_CTRL | KEY_LEFT, ESC_STR "O6D", MCKEY_NOACTION},
|
2003-09-24 07:32:23 +04:00
|
|
|
|
2006-02-05 18:27:49 +03:00
|
|
|
/* iTerm */
|
2009-09-17 02:07:04 +04:00
|
|
|
{KEY_M_SHIFT | KEY_PPAGE, ESC_STR "[5;2~", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_NPAGE, ESC_STR "[6;2~", MCKEY_NOACTION},
|
2006-02-05 18:27:49 +03:00
|
|
|
|
2009-03-26 00:32:25 +03:00
|
|
|
/* putty */
|
2009-09-17 02:07:04 +04:00
|
|
|
{KEY_M_SHIFT | KEY_PPAGE, ESC_STR "[[5;53~", MCKEY_NOACTION},
|
|
|
|
{KEY_M_SHIFT | KEY_NPAGE, ESC_STR "[[6;53~", MCKEY_NOACTION},
|
2009-03-26 00:32:25 +03:00
|
|
|
|
2003-09-09 20:30:14 +04:00
|
|
|
/* keypad keys */
|
2009-09-17 02:07:04 +04:00
|
|
|
{KEY_IC, ESC_STR "Op", MCKEY_NOACTION},
|
|
|
|
{KEY_DC, ESC_STR "On", MCKEY_NOACTION},
|
|
|
|
{'/', ESC_STR "Oo", MCKEY_NOACTION},
|
|
|
|
{'\n', ESC_STR "OM", MCKEY_NOACTION},
|
2003-09-09 20:30:14 +04:00
|
|
|
|
2009-09-17 02:07:04 +04:00
|
|
|
{0, NULL, MCKEY_NOACTION},
|
1998-02-27 07:54:42 +03:00
|
|
|
};
|
|
|
|
|
Fix various typos in the source code (closes MidnightCommander/mc#177).
Found via `codespell -S
po,doc,./misc/syntax,./src/vfs/extfs/helpers/README.it -L
parm,rouge,sav,ect,vie,te,dum,clen,wee,dynamc,childs,ths,fo,nin,unx,nd,iif,iterm,ser,makrs,wil`
Co-authored-by: Yury V. Zaytsev <yury@shurup.com>
Signed-off-by: Kian-Meng Ang <kianmeng@cpan.org>
Signed-off-by: Yury V. Zaytsev <yury@shurup.com>
2023-01-10 06:02:52 +03:00
|
|
|
/* qansi-m terminals have a much more key combinations,
|
2004-09-26 04:58:47 +04:00
|
|
|
which are undefined in termcap/terminfo */
|
2009-09-17 02:07:04 +04:00
|
|
|
static key_define_t qansi_key_defines[] = {
|
2004-09-26 04:58:47 +04:00
|
|
|
/* qansi-m terminal */
|
2009-09-17 02:07:04 +04:00
|
|
|
{KEY_M_CTRL | KEY_NPAGE, ESC_STR "[u", MCKEY_NOACTION}, /* Ctrl-PgDown */
|
|
|
|
{KEY_M_CTRL | KEY_PPAGE, ESC_STR "[v", MCKEY_NOACTION}, /* Ctrl-PgUp */
|
|
|
|
{KEY_M_CTRL | KEY_HOME, ESC_STR "[h", MCKEY_NOACTION}, /* Ctrl-Home */
|
|
|
|
{KEY_M_CTRL | KEY_END, ESC_STR "[y", MCKEY_NOACTION}, /* Ctrl-End */
|
|
|
|
{KEY_M_CTRL | KEY_IC, ESC_STR "[`", MCKEY_NOACTION}, /* Ctrl-Insert */
|
|
|
|
{KEY_M_CTRL | KEY_DC, ESC_STR "[p", MCKEY_NOACTION}, /* Ctrl-Delete */
|
|
|
|
{KEY_M_CTRL | KEY_LEFT, ESC_STR "[d", MCKEY_NOACTION}, /* Ctrl-Left */
|
|
|
|
{KEY_M_CTRL | KEY_RIGHT, ESC_STR "[c", MCKEY_NOACTION}, /* Ctrl-Right */
|
|
|
|
{KEY_M_CTRL | KEY_DOWN, ESC_STR "[b", MCKEY_NOACTION}, /* Ctrl-Down */
|
|
|
|
{KEY_M_CTRL | KEY_UP, ESC_STR "[a", MCKEY_NOACTION}, /* Ctrl-Up */
|
|
|
|
{KEY_M_CTRL | KEY_KP_ADD, ESC_STR "[s", MCKEY_NOACTION}, /* Ctrl-Gr-Plus */
|
|
|
|
{KEY_M_CTRL | KEY_KP_SUBTRACT, ESC_STR "[t", MCKEY_NOACTION}, /* Ctrl-Gr-Minus */
|
|
|
|
{KEY_M_CTRL | '\t', ESC_STR "[z", MCKEY_NOACTION}, /* Ctrl-Tab */
|
|
|
|
{KEY_M_SHIFT | '\t', ESC_STR "[Z", MCKEY_NOACTION}, /* Shift-Tab */
|
|
|
|
{KEY_M_CTRL | KEY_F (1), ESC_STR "[1~", MCKEY_NOACTION}, /* Ctrl-F1 */
|
|
|
|
{KEY_M_CTRL | KEY_F (2), ESC_STR "[2~", MCKEY_NOACTION}, /* Ctrl-F2 */
|
|
|
|
{KEY_M_CTRL | KEY_F (3), ESC_STR "[3~", MCKEY_NOACTION}, /* Ctrl-F3 */
|
|
|
|
{KEY_M_CTRL | KEY_F (4), ESC_STR "[4~", MCKEY_NOACTION}, /* Ctrl-F4 */
|
|
|
|
{KEY_M_CTRL | KEY_F (5), ESC_STR "[5~", MCKEY_NOACTION}, /* Ctrl-F5 */
|
|
|
|
{KEY_M_CTRL | KEY_F (6), ESC_STR "[6~", MCKEY_NOACTION}, /* Ctrl-F6 */
|
|
|
|
{KEY_M_CTRL | KEY_F (7), ESC_STR "[7~", MCKEY_NOACTION}, /* Ctrl-F7 */
|
|
|
|
{KEY_M_CTRL | KEY_F (8), ESC_STR "[8~", MCKEY_NOACTION}, /* Ctrl-F8 */
|
|
|
|
{KEY_M_CTRL | KEY_F (9), ESC_STR "[9~", MCKEY_NOACTION}, /* Ctrl-F9 */
|
|
|
|
{KEY_M_CTRL | KEY_F (10), ESC_STR "[10~", MCKEY_NOACTION}, /* Ctrl-F10 */
|
|
|
|
{KEY_M_CTRL | KEY_F (11), ESC_STR "[11~", MCKEY_NOACTION}, /* Ctrl-F11 */
|
|
|
|
{KEY_M_CTRL | KEY_F (12), ESC_STR "[12~", MCKEY_NOACTION}, /* Ctrl-F12 */
|
|
|
|
{KEY_M_ALT | KEY_F (1), ESC_STR "[17~", MCKEY_NOACTION}, /* Alt-F1 */
|
|
|
|
{KEY_M_ALT | KEY_F (2), ESC_STR "[18~", MCKEY_NOACTION}, /* Alt-F2 */
|
|
|
|
{KEY_M_ALT | KEY_F (3), ESC_STR "[19~", MCKEY_NOACTION}, /* Alt-F3 */
|
|
|
|
{KEY_M_ALT | KEY_F (4), ESC_STR "[20~", MCKEY_NOACTION}, /* Alt-F4 */
|
|
|
|
{KEY_M_ALT | KEY_F (5), ESC_STR "[21~", MCKEY_NOACTION}, /* Alt-F5 */
|
|
|
|
{KEY_M_ALT | KEY_F (6), ESC_STR "[22~", MCKEY_NOACTION}, /* Alt-F6 */
|
|
|
|
{KEY_M_ALT | KEY_F (7), ESC_STR "[23~", MCKEY_NOACTION}, /* Alt-F7 */
|
|
|
|
{KEY_M_ALT | KEY_F (8), ESC_STR "[24~", MCKEY_NOACTION}, /* Alt-F8 */
|
|
|
|
{KEY_M_ALT | KEY_F (9), ESC_STR "[25~", MCKEY_NOACTION}, /* Alt-F9 */
|
|
|
|
{KEY_M_ALT | KEY_F (10), ESC_STR "[26~", MCKEY_NOACTION}, /* Alt-F10 */
|
|
|
|
{KEY_M_ALT | KEY_F (11), ESC_STR "[27~", MCKEY_NOACTION}, /* Alt-F11 */
|
|
|
|
{KEY_M_ALT | KEY_F (12), ESC_STR "[28~", MCKEY_NOACTION}, /* Alt-F12 */
|
|
|
|
{KEY_M_ALT | 'a', ESC_STR "Na", MCKEY_NOACTION}, /* Alt-a */
|
|
|
|
{KEY_M_ALT | 'b', ESC_STR "Nb", MCKEY_NOACTION}, /* Alt-b */
|
|
|
|
{KEY_M_ALT | 'c', ESC_STR "Nc", MCKEY_NOACTION}, /* Alt-c */
|
|
|
|
{KEY_M_ALT | 'd', ESC_STR "Nd", MCKEY_NOACTION}, /* Alt-d */
|
|
|
|
{KEY_M_ALT | 'e', ESC_STR "Ne", MCKEY_NOACTION}, /* Alt-e */
|
|
|
|
{KEY_M_ALT | 'f', ESC_STR "Nf", MCKEY_NOACTION}, /* Alt-f */
|
|
|
|
{KEY_M_ALT | 'g', ESC_STR "Ng", MCKEY_NOACTION}, /* Alt-g */
|
2009-11-08 09:20:59 +03:00
|
|
|
{KEY_M_ALT | 'h', ESC_STR "Nh", MCKEY_NOACTION}, /* Alt-h */
|
2009-09-17 02:07:04 +04:00
|
|
|
{KEY_M_ALT | 'i', ESC_STR "Ni", MCKEY_NOACTION}, /* Alt-i */
|
|
|
|
{KEY_M_ALT | 'j', ESC_STR "Nj", MCKEY_NOACTION}, /* Alt-j */
|
|
|
|
{KEY_M_ALT | 'k', ESC_STR "Nk", MCKEY_NOACTION}, /* Alt-k */
|
|
|
|
{KEY_M_ALT | 'l', ESC_STR "Nl", MCKEY_NOACTION}, /* Alt-l */
|
|
|
|
{KEY_M_ALT | 'm', ESC_STR "Nm", MCKEY_NOACTION}, /* Alt-m */
|
|
|
|
{KEY_M_ALT | 'n', ESC_STR "Nn", MCKEY_NOACTION}, /* Alt-n */
|
|
|
|
{KEY_M_ALT | 'o', ESC_STR "No", MCKEY_NOACTION}, /* Alt-o */
|
|
|
|
{KEY_M_ALT | 'p', ESC_STR "Np", MCKEY_NOACTION}, /* Alt-p */
|
2009-11-08 09:20:59 +03:00
|
|
|
{KEY_M_ALT | 'q', ESC_STR "Nq", MCKEY_NOACTION}, /* Alt-q */
|
|
|
|
{KEY_M_ALT | 'r', ESC_STR "Nr", MCKEY_NOACTION}, /* Alt-r */
|
2009-09-17 02:07:04 +04:00
|
|
|
{KEY_M_ALT | 's', ESC_STR "Ns", MCKEY_NOACTION}, /* Alt-s */
|
|
|
|
{KEY_M_ALT | 't', ESC_STR "Nt", MCKEY_NOACTION}, /* Alt-t */
|
|
|
|
{KEY_M_ALT | 'u', ESC_STR "Nu", MCKEY_NOACTION}, /* Alt-u */
|
|
|
|
{KEY_M_ALT | 'v', ESC_STR "Nv", MCKEY_NOACTION}, /* Alt-v */
|
|
|
|
{KEY_M_ALT | 'w', ESC_STR "Nw", MCKEY_NOACTION}, /* Alt-w */
|
|
|
|
{KEY_M_ALT | 'x', ESC_STR "Nx", MCKEY_NOACTION}, /* Alt-x */
|
|
|
|
{KEY_M_ALT | 'y', ESC_STR "Ny", MCKEY_NOACTION}, /* Alt-y */
|
|
|
|
{KEY_M_ALT | 'z', ESC_STR "Nz", MCKEY_NOACTION}, /* Alt-z */
|
|
|
|
{KEY_KP_SUBTRACT, ESC_STR "[S", MCKEY_NOACTION}, /* Gr-Minus */
|
|
|
|
{KEY_KP_ADD, ESC_STR "[T", MCKEY_NOACTION}, /* Gr-Plus */
|
2006-01-07 15:49:08 +03:00
|
|
|
{0, NULL, MCKEY_NOACTION},
|
2004-09-26 04:58:47 +04:00
|
|
|
};
|
|
|
|
|
2009-07-18 18:30:06 +04:00
|
|
|
/* This holds all the key definitions */
|
|
|
|
static key_def *keys = NULL;
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
static int input_fd;
|
2009-09-17 02:07:04 +04:00
|
|
|
static int disabled_channels = 0; /* Disable channels checking */
|
2009-05-24 13:39:14 +04:00
|
|
|
|
2019-04-09 13:56:57 +03:00
|
|
|
static GSList *select_list = NULL;
|
2009-05-24 13:39:14 +04:00
|
|
|
|
2009-09-17 02:07:04 +04:00
|
|
|
static int seq_buffer[SEQ_BUFFER_LEN];
|
2009-07-04 14:48:39 +04:00
|
|
|
static int *seq_append = NULL;
|
2009-05-24 13:39:14 +04:00
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
static int *pending_keys = NULL;
|
2009-05-24 13:39:14 +04:00
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
#ifdef __QNXNTO__
|
|
|
|
ph_dv_f ph_attach;
|
|
|
|
ph_ov_f ph_input_group;
|
|
|
|
ph_pqc_f ph_query_cursor;
|
|
|
|
#endif
|
2009-05-24 13:39:14 +04:00
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
#ifdef HAVE_TEXTMODE_X11_SUPPORT
|
|
|
|
static Display *x11_display;
|
|
|
|
static Window x11_window;
|
2009-09-17 02:07:04 +04:00
|
|
|
#endif /* HAVE_TEXTMODE_X11_SUPPORT */
|
2009-05-24 13:39:14 +04:00
|
|
|
|
2011-01-22 00:36:29 +03:00
|
|
|
static KeySortType has_been_sorted = KEY_NOSORT;
|
|
|
|
|
2011-09-06 14:35:42 +04:00
|
|
|
/* *INDENT-OFF* */
|
2011-01-22 00:36:29 +03:00
|
|
|
static const size_t key_conv_tab_size = G_N_ELEMENTS (key_name_conv_tab) - 1;
|
2011-09-06 14:35:42 +04:00
|
|
|
/* *INDENT-ON* */
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2011-01-22 00:36:29 +03:00
|
|
|
static const key_code_name_t *key_conv_tab_sorted[G_N_ELEMENTS (key_name_conv_tab) - 1];
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2019-04-09 13:56:57 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2010-11-08 13:21:45 +03:00
|
|
|
/*** file scope functions ************************************************************************/
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2009-07-04 14:48:39 +04:00
|
|
|
|
2019-04-09 13:56:57 +03:00
|
|
|
static int
|
|
|
|
select_cmp_by_fd_set (gconstpointer a, gconstpointer b)
|
|
|
|
{
|
|
|
|
const select_t *s = (const select_t *) a;
|
|
|
|
const fd_set *f = (const fd_set *) b;
|
|
|
|
|
|
|
|
return (FD_ISSET (s->fd, f) ? 0 : 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static int
|
|
|
|
select_cmp_by_fd (gconstpointer a, gconstpointer b)
|
|
|
|
{
|
|
|
|
const select_t *s = (const select_t *) a;
|
|
|
|
const int fd = GPOINTER_TO_INT (b);
|
|
|
|
|
|
|
|
return (s->fd == fd ? 0 : 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-08-31 05:54:10 +04:00
|
|
|
static int
|
2009-09-17 02:07:04 +04:00
|
|
|
add_selects (fd_set * select_set)
|
2009-07-04 14:48:39 +04:00
|
|
|
{
|
|
|
|
int top_fd = 0;
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
if (disabled_channels == 0)
|
|
|
|
{
|
2019-04-09 13:56:57 +03:00
|
|
|
GSList *s;
|
2009-07-04 14:48:39 +04:00
|
|
|
|
2019-04-09 13:56:57 +03:00
|
|
|
for (s = select_list; s != NULL; s = g_slist_next (s))
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2019-04-09 13:56:57 +03:00
|
|
|
select_t *p = (select_t *) s->data;
|
|
|
|
|
2009-09-17 02:07:04 +04:00
|
|
|
FD_SET (p->fd, select_set);
|
|
|
|
if (p->fd > top_fd)
|
|
|
|
top_fd = p->fd;
|
|
|
|
}
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return top_fd;
|
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
static void
|
2009-09-17 02:07:04 +04:00
|
|
|
check_selects (fd_set * select_set)
|
2009-07-04 14:48:39 +04:00
|
|
|
{
|
2019-04-09 13:56:57 +03:00
|
|
|
while (disabled_channels == 0)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2019-04-09 13:56:57 +03:00
|
|
|
GSList *s;
|
|
|
|
select_t *p;
|
2009-09-17 02:07:04 +04:00
|
|
|
|
2019-04-09 13:56:57 +03:00
|
|
|
s = g_slist_find_custom (select_list, select_set, select_cmp_by_fd_set);
|
|
|
|
if (s == NULL)
|
|
|
|
break;
|
2009-09-17 02:07:04 +04:00
|
|
|
|
2019-04-09 13:56:57 +03:00
|
|
|
p = (select_t *) s->data;
|
|
|
|
FD_CLR (p->fd, select_set);
|
|
|
|
p->callback (p->fd, p->info);
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2009-07-04 14:48:39 +04:00
|
|
|
/* If set timeout is set, then we wait 0.1 seconds, else, we block */
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
static void
|
2019-04-13 13:28:09 +03:00
|
|
|
try_channels (gboolean set_timeout)
|
2009-07-04 14:48:39 +04:00
|
|
|
{
|
2010-02-02 13:48:08 +03:00
|
|
|
struct timeval time_out;
|
2009-07-04 14:48:39 +04:00
|
|
|
static fd_set select_set;
|
|
|
|
|
2019-04-13 13:28:09 +03:00
|
|
|
while (TRUE)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2013-10-15 10:34:04 +04:00
|
|
|
struct timeval *timeptr = NULL;
|
|
|
|
int maxfdp, v;
|
|
|
|
|
2009-09-17 02:07:04 +04:00
|
|
|
FD_ZERO (&select_set);
|
|
|
|
FD_SET (input_fd, &select_set); /* Add stdin */
|
2016-04-07 10:52:04 +03:00
|
|
|
maxfdp = MAX (add_selects (&select_set), input_fd);
|
2009-09-17 02:07:04 +04:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
if (set_timeout)
|
|
|
|
{
|
2010-02-02 13:48:08 +03:00
|
|
|
time_out.tv_sec = 0;
|
2021-10-02 13:09:34 +03:00
|
|
|
time_out.tv_usec = 100 * MC_USEC_PER_MSEC;
|
2010-02-02 13:48:08 +03:00
|
|
|
timeptr = &time_out;
|
2009-10-09 15:46:08 +04:00
|
|
|
}
|
2009-09-17 02:07:04 +04:00
|
|
|
|
|
|
|
v = select (maxfdp + 1, &select_set, NULL, NULL, timeptr);
|
2010-11-08 13:21:45 +03:00
|
|
|
if (v > 0)
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
check_selects (&select_set);
|
|
|
|
if (FD_ISSET (input_fd, &select_set))
|
2009-10-09 15:46:08 +04:00
|
|
|
break;
|
2009-09-17 02:07:04 +04:00
|
|
|
}
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
static key_def *
|
|
|
|
create_sequence (const char *seq, int code, int action)
|
|
|
|
{
|
|
|
|
key_def *base, *p, *attach;
|
|
|
|
|
2019-04-13 13:28:09 +03:00
|
|
|
for (base = attach = NULL; *seq != '\0'; seq++)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
p = g_new (key_def, 1);
|
|
|
|
if (base == NULL)
|
|
|
|
base = p;
|
|
|
|
if (attach != NULL)
|
|
|
|
attach->child = p;
|
|
|
|
|
|
|
|
p->ch = *seq;
|
|
|
|
p->code = code;
|
|
|
|
p->child = p->next = NULL;
|
|
|
|
if (seq[1] == '\0')
|
|
|
|
p->action = action;
|
|
|
|
else
|
|
|
|
p->action = MCKEY_NOACTION;
|
|
|
|
attach = p;
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
|
|
|
return base;
|
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
static void
|
2009-09-17 02:07:04 +04:00
|
|
|
define_sequences (const key_define_t * kd)
|
2009-05-24 13:39:14 +04:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
for (i = 0; kd[i].code != 0; i++)
|
2009-09-17 02:07:04 +04:00
|
|
|
define_sequence (kd[i].code, kd[i].seq, kd[i].action);
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
2009-05-24 13:39:14 +04:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2012-10-30 13:07:46 +04:00
|
|
|
#ifdef HAVE_TEXTMODE_X11_SUPPORT
|
2009-07-04 14:48:39 +04:00
|
|
|
static void
|
|
|
|
init_key_x11 (void)
|
|
|
|
{
|
2011-10-28 16:09:44 +04:00
|
|
|
if (getenv ("DISPLAY") != NULL && !mc_global.tty.disable_x11)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
x11_display = mc_XOpenDisplay (0);
|
2009-07-04 14:48:39 +04:00
|
|
|
|
2009-09-17 02:07:04 +04:00
|
|
|
if (x11_display != NULL)
|
|
|
|
x11_window = DefaultRootWindow (x11_display);
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
|
|
|
}
|
2012-10-30 13:07:46 +04:00
|
|
|
#endif /* HAVE_TEXTMODE_X11_SUPPORT */
|
2009-07-04 14:48:39 +04:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2009-07-04 14:48:39 +04:00
|
|
|
/* Workaround for System V Curses vt100 bug */
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
static int
|
|
|
|
getch_with_delay (void)
|
|
|
|
{
|
|
|
|
int c;
|
|
|
|
|
|
|
|
/* This routine could be used on systems without mouse support,
|
|
|
|
so we need to do the select check :-( */
|
2019-04-13 13:28:09 +03:00
|
|
|
while (TRUE)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
if (pending_keys == NULL)
|
2019-04-13 13:28:09 +03:00
|
|
|
try_channels (FALSE);
|
2009-09-17 02:07:04 +04:00
|
|
|
|
|
|
|
/* Try to get a character */
|
|
|
|
c = get_key_code (0);
|
|
|
|
if (c != -1)
|
|
|
|
break;
|
2019-04-13 13:28:09 +03:00
|
|
|
|
2009-09-17 02:07:04 +04:00
|
|
|
/* Failed -> wait 0.1 secs and try again */
|
2019-04-13 13:28:09 +03:00
|
|
|
try_channels (TRUE);
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
2019-04-13 13:28:09 +03:00
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
/* Success -> return the character */
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
static void
|
2013-02-13 13:37:50 +04:00
|
|
|
xmouse_get_event (Gpm_Event * ev, gboolean extended)
|
2009-07-04 14:48:39 +04:00
|
|
|
{
|
2021-10-02 12:47:26 +03:00
|
|
|
static gint64 tv1 = 0; /* Force first click as single */
|
2009-07-04 14:48:39 +04:00
|
|
|
static int clicks = 0;
|
|
|
|
static int last_btn = 0;
|
2013-02-13 13:37:50 +04:00
|
|
|
int btn;
|
2009-07-04 14:48:39 +04:00
|
|
|
|
|
|
|
/* Decode Xterm mouse information to a GPM style event */
|
|
|
|
|
2013-02-13 13:37:50 +04:00
|
|
|
if (!extended)
|
|
|
|
{
|
|
|
|
/* Variable btn has following meaning: */
|
|
|
|
/* 0 = btn1 dn, 1 = btn2 dn, 2 = btn3 dn, 3 = btn up */
|
|
|
|
btn = tty_lowlevel_getch () - 32;
|
|
|
|
/* Coordinates are 33-based */
|
|
|
|
/* Transform them to 1-based */
|
|
|
|
ev->x = tty_lowlevel_getch () - 32;
|
|
|
|
ev->y = tty_lowlevel_getch () - 32;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* SGR 1006 extension (e.g. "\e[<0;12;300M"):
|
|
|
|
- Numbers are encoded in decimal to make it ASCII-safe
|
|
|
|
and to overcome the limit of 223 columns/rows.
|
|
|
|
- Mouse release is encoded by trailing 'm' rather than 'M'
|
|
|
|
so that the released button can be reported.
|
|
|
|
- Numbers are no longer offset by 32. */
|
|
|
|
char c;
|
2019-04-13 13:28:09 +03:00
|
|
|
|
2013-02-13 13:37:50 +04:00
|
|
|
btn = ev->x = ev->y = 0;
|
|
|
|
ev->type = 0; /* In case we return on an invalid sequence */
|
2019-04-13 13:28:09 +03:00
|
|
|
|
2013-02-13 13:37:50 +04:00
|
|
|
while ((c = tty_lowlevel_getch ()) != ';')
|
|
|
|
{
|
|
|
|
if (c < '0' || c > '9')
|
|
|
|
return;
|
|
|
|
btn = 10 * btn + (c - '0');
|
|
|
|
}
|
|
|
|
while ((c = tty_lowlevel_getch ()) != ';')
|
|
|
|
{
|
|
|
|
if (c < '0' || c > '9')
|
|
|
|
return;
|
|
|
|
ev->x = 10 * ev->x + (c - '0');
|
|
|
|
}
|
|
|
|
while ((c = tty_lowlevel_getch ()) != 'M' && c != 'm')
|
|
|
|
{
|
|
|
|
if (c < '0' || c > '9')
|
|
|
|
return;
|
|
|
|
ev->y = 10 * ev->y + (c - '0');
|
|
|
|
}
|
|
|
|
/* Legacy mouse protocol doesn't tell which button was released,
|
|
|
|
conveniently all of mc's widgets are written not to rely on this
|
|
|
|
information. With the SGR extension the released button becomes
|
|
|
|
known, but for the sake of simplicity we just ignore it. */
|
|
|
|
if (c == 'm')
|
|
|
|
btn = 3;
|
|
|
|
}
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
/* There seems to be no way of knowing which button was released */
|
|
|
|
/* So we assume all the buttons were released */
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
if (btn == 3)
|
|
|
|
{
|
|
|
|
if (last_btn != 0)
|
|
|
|
{
|
|
|
|
if ((last_btn & (GPM_B_UP | GPM_B_DOWN)) != 0)
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
/* FIXME: DIRTY HACK */
|
|
|
|
/* don't generate GPM_UP after mouse wheel */
|
|
|
|
/* need for menu event handling */
|
|
|
|
ev->type = 0;
|
2021-10-02 12:47:26 +03:00
|
|
|
tv1 = 0;
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
ev->type = GPM_UP | (GPM_SINGLE << clicks);
|
2021-10-03 17:12:42 +03:00
|
|
|
tv1 = g_get_monotonic_time ();
|
2009-09-17 02:07:04 +04:00
|
|
|
}
|
|
|
|
ev->buttons = 0;
|
|
|
|
last_btn = 0;
|
|
|
|
clicks = 0;
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
/* Bogus event, maybe mouse wheel */
|
|
|
|
ev->type = 0;
|
|
|
|
}
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-02 12:47:26 +03:00
|
|
|
gint64 tv2;
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
if (btn >= 32 && btn <= 34)
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
btn -= 32;
|
|
|
|
ev->type = GPM_DRAG;
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
else
|
2009-09-17 02:07:04 +04:00
|
|
|
ev->type = GPM_DOWN;
|
|
|
|
|
2021-10-03 17:12:42 +03:00
|
|
|
tv2 = g_get_monotonic_time ();
|
2021-10-02 12:47:26 +03:00
|
|
|
if (tv1 != 0 && tv2 - tv1 < (gint64) double_click_speed * MC_USEC_PER_MSEC)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
clicks++;
|
|
|
|
clicks %= 3;
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
else
|
2009-09-17 02:07:04 +04:00
|
|
|
clicks = 0;
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
switch (btn)
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
case 0:
|
|
|
|
ev->buttons = GPM_B_LEFT;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
ev->buttons = GPM_B_MIDDLE;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
ev->buttons = GPM_B_RIGHT;
|
|
|
|
break;
|
|
|
|
case 64:
|
|
|
|
ev->buttons = GPM_B_UP;
|
|
|
|
clicks = 0;
|
|
|
|
break;
|
|
|
|
case 65:
|
|
|
|
ev->buttons = GPM_B_DOWN;
|
|
|
|
clicks = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Nothing */
|
|
|
|
ev->type = 0;
|
|
|
|
ev->buttons = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
last_btn = ev->buttons;
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
2009-07-04 14:48:39 +04:00
|
|
|
* Get modifier state (shift, alt, ctrl) for the last key pressed.
|
|
|
|
* We are assuming that the state didn't change since the key press.
|
|
|
|
* This is only correct if get_modifier() is called very fast after
|
|
|
|
* the input was received, so that the user didn't release the
|
|
|
|
* modifier keys yet.
|
|
|
|
*/
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
static int
|
|
|
|
get_modifier (void)
|
|
|
|
{
|
|
|
|
int result = 0;
|
|
|
|
#ifdef __QNXNTO__
|
|
|
|
static int in_photon = 0;
|
|
|
|
static int ph_ig = 0;
|
2009-09-17 02:07:04 +04:00
|
|
|
#endif /* __QNXNTO__ */
|
2009-07-04 14:48:39 +04:00
|
|
|
|
|
|
|
#ifdef HAVE_TEXTMODE_X11_SUPPORT
|
2010-11-08 13:21:45 +03:00
|
|
|
if (x11_window != 0)
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
Window root, child;
|
|
|
|
int root_x, root_y;
|
|
|
|
int win_x, win_y;
|
|
|
|
unsigned int mask;
|
|
|
|
|
|
|
|
mc_XQueryPointer (x11_display, x11_window, &root, &child, &root_x,
|
|
|
|
&root_y, &win_x, &win_y, &mask);
|
|
|
|
|
2019-04-13 13:28:09 +03:00
|
|
|
if ((mask & ShiftMask) != 0)
|
2009-09-17 02:07:04 +04:00
|
|
|
result |= KEY_M_SHIFT;
|
2019-04-13 13:28:09 +03:00
|
|
|
if ((mask & ControlMask) != 0)
|
2009-09-17 02:07:04 +04:00
|
|
|
result |= KEY_M_CTRL;
|
|
|
|
return result;
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
2009-09-17 02:07:04 +04:00
|
|
|
#endif /* HAVE_TEXTMODE_X11_SUPPORT */
|
2009-07-04 14:48:39 +04:00
|
|
|
|
2019-04-13 13:28:09 +03:00
|
|
|
#ifdef __QNXNTO__
|
2010-11-08 13:21:45 +03:00
|
|
|
if (in_photon == 0)
|
|
|
|
{
|
2019-04-13 13:28:09 +03:00
|
|
|
/* First time here, let's load Photon library and attach to Photon */
|
2009-09-17 02:07:04 +04:00
|
|
|
in_photon = -1;
|
2019-04-13 13:28:09 +03:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
if (getenv ("PHOTON2_PATH") != NULL)
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
/* QNX 6.x has no support for RTLD_LAZY */
|
2019-04-13 13:28:09 +03:00
|
|
|
void *ph_handle;
|
|
|
|
|
|
|
|
ph_handle = dlopen ("/usr/lib/libph.so", RTLD_NOW);
|
2010-11-08 13:21:45 +03:00
|
|
|
if (ph_handle != NULL)
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
ph_attach = (ph_dv_f) dlsym (ph_handle, "PhAttach");
|
|
|
|
ph_input_group = (ph_ov_f) dlsym (ph_handle, "PhInputGroup");
|
|
|
|
ph_query_cursor = (ph_pqc_f) dlsym (ph_handle, "PhQueryCursor");
|
2019-04-13 13:28:09 +03:00
|
|
|
if ((ph_attach != NULL) && (ph_input_group != NULL) && (ph_query_cursor != NULL)
|
|
|
|
&& (*ph_attach) (0, 0) != NULL)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2019-04-13 13:28:09 +03:00
|
|
|
/* Attached */
|
|
|
|
ph_ig = (*ph_input_group) (0);
|
|
|
|
in_photon = 1;
|
2009-09-17 02:07:04 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
2019-04-13 13:28:09 +03:00
|
|
|
/* We do not have Photon running. Assume we are in text console or xterm */
|
2010-11-08 13:21:45 +03:00
|
|
|
if (in_photon == -1)
|
|
|
|
{
|
2019-04-13 13:28:09 +03:00
|
|
|
int mod_status;
|
2013-10-15 10:34:04 +04:00
|
|
|
int shift_ext_status;
|
|
|
|
|
2016-01-01 11:23:17 +03:00
|
|
|
if (devctl (fileno (stdin), DCMD_CHR_LINESTATUS, &mod_status, sizeof (mod_status), NULL) ==
|
|
|
|
-1)
|
2009-09-17 02:07:04 +04:00
|
|
|
return 0;
|
2016-01-01 11:23:17 +03:00
|
|
|
|
2009-09-17 02:07:04 +04:00
|
|
|
shift_ext_status = mod_status & 0xffffff00UL;
|
|
|
|
mod_status &= 0x7f;
|
2019-04-13 13:28:09 +03:00
|
|
|
if ((mod_status & _LINESTATUS_CON_ALT) != 0)
|
2009-09-17 02:07:04 +04:00
|
|
|
result |= KEY_M_ALT;
|
2019-04-13 13:28:09 +03:00
|
|
|
if ((mod_status & _LINESTATUS_CON_CTRL) != 0)
|
2009-09-17 02:07:04 +04:00
|
|
|
result |= KEY_M_CTRL;
|
2019-04-13 13:28:09 +03:00
|
|
|
if ((mod_status & _LINESTATUS_CON_SHIFT) != 0 || (shift_ext_status & 0x00000800UL) != 0)
|
2009-09-17 02:07:04 +04:00
|
|
|
result |= KEY_M_SHIFT;
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-04-13 13:28:09 +03:00
|
|
|
PhCursorInfo_t cursor_info;
|
|
|
|
|
2009-09-17 02:07:04 +04:00
|
|
|
(*ph_query_cursor) (ph_ig, &cursor_info);
|
2019-04-13 13:28:09 +03:00
|
|
|
if ((cursor_info.key_mods & 0x04) != 0)
|
2009-09-17 02:07:04 +04:00
|
|
|
result |= KEY_M_ALT;
|
2019-04-13 13:28:09 +03:00
|
|
|
if ((cursor_info.key_mods & 0x02) != 0)
|
2009-09-17 02:07:04 +04:00
|
|
|
result |= KEY_M_CTRL;
|
2019-04-13 13:28:09 +03:00
|
|
|
if ((cursor_info.key_mods & 0x01) != 0)
|
2009-09-17 02:07:04 +04:00
|
|
|
result |= KEY_M_SHIFT;
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
|
|
|
#endif /* __QNXNTO__ */
|
|
|
|
|
|
|
|
#if defined __linux__ || (defined __CYGWIN__ && defined TIOCLINUX)
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
unsigned char modifiers = 6;
|
|
|
|
|
|
|
|
if (ioctl (0, TIOCLINUX, &modifiers) < 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Translate Linux modifiers into mc modifiers */
|
2019-04-13 13:28:09 +03:00
|
|
|
if ((modifiers & SHIFT_PRESSED) != 0)
|
2009-09-17 02:07:04 +04:00
|
|
|
result |= KEY_M_SHIFT;
|
2019-04-13 13:28:09 +03:00
|
|
|
if ((modifiers & (ALTL_PRESSED | ALTR_PRESSED)) != 0)
|
2009-09-17 02:07:04 +04:00
|
|
|
result |= KEY_M_ALT;
|
2019-04-13 13:28:09 +03:00
|
|
|
if ((modifiers & CONTROL_PRESSED) != 0)
|
2009-09-17 02:07:04 +04:00
|
|
|
result |= KEY_M_CTRL;
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
2009-09-17 02:07:04 +04:00
|
|
|
#endif /* !__linux__ */
|
2019-04-13 13:28:09 +03:00
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
static gboolean
|
|
|
|
push_char (int c)
|
|
|
|
{
|
|
|
|
gboolean ret = FALSE;
|
|
|
|
|
|
|
|
if (seq_append == NULL)
|
2009-09-17 02:07:04 +04:00
|
|
|
seq_append = seq_buffer;
|
2009-07-04 14:48:39 +04:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
if (seq_append != &(seq_buffer[SEQ_BUFFER_LEN - 2]))
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
*(seq_append++) = c;
|
2019-04-13 13:28:09 +03:00
|
|
|
*seq_append = '\0';
|
2009-09-17 02:07:04 +04:00
|
|
|
ret = TRUE;
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2009-07-04 14:48:39 +04:00
|
|
|
/* Apply corrections for the keycode generated in get_key_code() */
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
static int
|
|
|
|
correct_key_code (int code)
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
unsigned int c = code & ~KEY_M_MASK; /* code without modifier */
|
|
|
|
unsigned int mod = code & KEY_M_MASK; /* modifier */
|
|
|
|
#ifdef __QNXNTO__
|
|
|
|
unsigned int qmod; /* bunch of the QNX console
|
|
|
|
modifiers needs unchanged */
|
|
|
|
#endif /* __QNXNTO__ */
|
2009-07-04 14:48:39 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Add key modifiers directly from X11 or OS.
|
|
|
|
* Ordinary characters only get modifiers from sequences.
|
|
|
|
*/
|
2010-11-08 13:21:45 +03:00
|
|
|
if (c < 32 || c >= 256)
|
2009-09-17 02:07:04 +04:00
|
|
|
mod |= get_modifier ();
|
2009-07-04 14:48:39 +04:00
|
|
|
|
|
|
|
/* This is needed if the newline is reported as carriage return */
|
|
|
|
if (c == '\r')
|
2009-09-17 02:07:04 +04:00
|
|
|
c = '\n';
|
2009-07-04 14:48:39 +04:00
|
|
|
|
|
|
|
/* This is reported to be useful on AIX */
|
|
|
|
if (c == KEY_SCANCEL)
|
2009-09-17 02:07:04 +04:00
|
|
|
c = '\t';
|
2009-07-04 14:48:39 +04:00
|
|
|
|
Handle newline and tab with shift/ctrl modifiers correctly.
MC already has its own half-ready trick: when pasting with Shift-Insert,
using the X11 extension, the newline ("Enter" as mc calls it) with the
Shift modifier pressed gets converted to a "Return", and in the editor
the Return character inserts a non-indenting newline. This makes pasting
better in terminals not supporting bracketed paste, however, it has some
problems that this commit addresses:
* Shift+newline gets this special treatment, but Ctrl+newline gets
dropped. Hence e.g. when pasting in Gnome-terminal with Ctrl+Shift+V
all the newlines will be missing. This commit adds the same
non-indenting newline behavior to Ctrl+Newline and Ctrl+Shift+Newline.
* The code forgets about Tab that also needs special treatment:
- Most terminals send \e[Z on Shift+Tab, this is not handled by MC
at all, moreover it causes a hang for about a second. This commit
teaches this sequence to MC. This is especially useful when no X11
is available, because there Ctrl+Tab is identical to Tab, so the
backwards tab feature is not available. With this commit Shift+Tab
becomes a backwards tab too on all terminals that emit \e[Z.
- When pasting to the editor, Shift+Tab, Ctrl+Tab and Ctrl+Shift+Tab
should all insert a tab for the same reason mentioned at the newline.
- It would look inconsistent in the keymap files to have logical code
such as "backtab" instead of "shift-tab" and friends, hence get rid
of KEY_BTAB and use KEY_M_SHIFT | '\t' instead.
Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
2013-10-01 14:09:14 +04:00
|
|
|
/* Convert Back Tab to Shift+Tab */
|
|
|
|
if (c == KEY_BTAB)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
Handle newline and tab with shift/ctrl modifiers correctly.
MC already has its own half-ready trick: when pasting with Shift-Insert,
using the X11 extension, the newline ("Enter" as mc calls it) with the
Shift modifier pressed gets converted to a "Return", and in the editor
the Return character inserts a non-indenting newline. This makes pasting
better in terminals not supporting bracketed paste, however, it has some
problems that this commit addresses:
* Shift+newline gets this special treatment, but Ctrl+newline gets
dropped. Hence e.g. when pasting in Gnome-terminal with Ctrl+Shift+V
all the newlines will be missing. This commit adds the same
non-indenting newline behavior to Ctrl+Newline and Ctrl+Shift+Newline.
* The code forgets about Tab that also needs special treatment:
- Most terminals send \e[Z on Shift+Tab, this is not handled by MC
at all, moreover it causes a hang for about a second. This commit
teaches this sequence to MC. This is especially useful when no X11
is available, because there Ctrl+Tab is identical to Tab, so the
backwards tab feature is not available. With this commit Shift+Tab
becomes a backwards tab too on all terminals that emit \e[Z.
- When pasting to the editor, Shift+Tab, Ctrl+Tab and Ctrl+Shift+Tab
should all insert a tab for the same reason mentioned at the newline.
- It would look inconsistent in the keymap files to have logical code
such as "backtab" instead of "shift-tab" and friends, hence get rid
of KEY_BTAB and use KEY_M_SHIFT | '\t' instead.
Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
2013-10-01 14:09:14 +04:00
|
|
|
c = '\t';
|
|
|
|
mod = KEY_M_SHIFT;
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* F0 is the same as F10 for out purposes */
|
|
|
|
if (c == KEY_F (0))
|
2009-09-17 02:07:04 +04:00
|
|
|
c = KEY_F (10);
|
2009-07-04 14:48:39 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We are not interested if Ctrl was pressed when entering control
|
|
|
|
* characters, so assume that it was. When checking for such keys,
|
|
|
|
* XCTRL macro should be used. In some cases, we are interested,
|
|
|
|
* e.g. to distinguish Ctrl-Enter from Enter.
|
|
|
|
*/
|
2010-12-30 10:25:56 +03:00
|
|
|
if (c == '\b')
|
|
|
|
{
|
|
|
|
/* Special case for backspase ('\b' < 32) */
|
|
|
|
c = KEY_BACKSPACE;
|
|
|
|
mod &= ~KEY_M_CTRL;
|
|
|
|
}
|
|
|
|
else if (c < 32 && c != ESC_CHAR && c != '\t' && c != '\n')
|
2009-09-17 02:07:04 +04:00
|
|
|
mod |= KEY_M_CTRL;
|
2010-12-30 10:25:56 +03:00
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
#ifdef __QNXNTO__
|
|
|
|
qmod = get_modifier ();
|
|
|
|
|
2019-04-13 13:28:09 +03:00
|
|
|
if (c == 127 && mod == 0)
|
|
|
|
{
|
|
|
|
/* Add Ctrl/Alt/Shift-BackSpace */
|
2009-09-17 02:07:04 +04:00
|
|
|
mod |= get_modifier ();
|
|
|
|
c = KEY_BACKSPACE;
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
|
|
|
|
2019-04-13 13:28:09 +03:00
|
|
|
if (c == '0' && mod == 0 && (qmod & KEY_M_SHIFT) == KEY_M_SHIFT)
|
|
|
|
{
|
|
|
|
/* Add Shift-Insert on key pad */
|
|
|
|
mod = KEY_M_SHIFT;
|
|
|
|
c = KEY_IC;
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
2009-05-24 13:39:14 +04:00
|
|
|
|
2019-04-13 13:28:09 +03:00
|
|
|
if (c == '.' && mod == 0 && (qmod & KEY_M_SHIFT) == KEY_M_SHIFT)
|
|
|
|
{
|
|
|
|
/* Add Shift-Del on key pad */
|
|
|
|
mod = KEY_M_SHIFT;
|
|
|
|
c = KEY_DC;
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
|
|
|
#endif /* __QNXNTO__ */
|
2009-05-24 13:39:14 +04:00
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
/* Unrecognized 0177 is delete (preserve Ctrl) */
|
2010-11-08 13:21:45 +03:00
|
|
|
if (c == 0177)
|
2009-09-17 02:07:04 +04:00
|
|
|
c = KEY_BACKSPACE;
|
2009-05-24 13:39:14 +04:00
|
|
|
|
2010-11-18 14:15:20 +03:00
|
|
|
#if 0
|
2009-07-04 14:48:39 +04:00
|
|
|
/* Unrecognized Ctrl-d is delete */
|
2019-04-13 13:28:09 +03:00
|
|
|
if (c == 'd' & 31)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
c = KEY_DC;
|
|
|
|
mod &= ~KEY_M_CTRL;
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
2009-05-24 13:39:14 +04:00
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
/* Unrecognized Ctrl-h is backspace */
|
2019-04-13 13:28:09 +03:00
|
|
|
if (c == 'h' & 31)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
c = KEY_BACKSPACE;
|
|
|
|
mod &= ~KEY_M_CTRL;
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
2010-11-18 14:15:20 +03:00
|
|
|
#endif
|
2009-05-24 13:39:14 +04:00
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
/* Shift+BackSpace is backspace */
|
2019-04-13 13:28:09 +03:00
|
|
|
if (c == KEY_BACKSPACE && (mod & KEY_M_SHIFT) != 0)
|
2009-09-17 02:07:04 +04:00
|
|
|
mod &= ~KEY_M_SHIFT;
|
2009-05-24 13:39:14 +04:00
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
/* Convert Shift+Fn to F(n+10) */
|
2019-04-13 13:28:09 +03:00
|
|
|
if (c >= KEY_F (1) && c <= KEY_F (10) && (mod & KEY_M_SHIFT) != 0)
|
2009-09-17 02:07:04 +04:00
|
|
|
c += 10;
|
2009-05-24 13:39:14 +04:00
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
/* Remove Shift information from function keys */
|
2010-11-08 13:21:45 +03:00
|
|
|
if (c >= KEY_F (1) && c <= KEY_F (20))
|
2009-09-17 02:07:04 +04:00
|
|
|
mod &= ~KEY_M_SHIFT;
|
2009-05-24 13:39:14 +04:00
|
|
|
|
2011-09-14 02:07:31 +04:00
|
|
|
if (!mc_global.tty.alternate_plus_minus)
|
2010-11-08 13:21:45 +03:00
|
|
|
switch (c)
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
case KEY_KP_ADD:
|
|
|
|
c = '+';
|
|
|
|
break;
|
|
|
|
case KEY_KP_SUBTRACT:
|
|
|
|
c = '-';
|
|
|
|
break;
|
|
|
|
case KEY_KP_MULTIPLY:
|
|
|
|
c = '*';
|
|
|
|
break;
|
2015-04-19 13:57:38 +03:00
|
|
|
default:
|
|
|
|
break;
|
2009-09-17 02:07:04 +04:00
|
|
|
}
|
2006-01-07 15:49:08 +03:00
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
return (mod | c);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
static int
|
2013-05-21 16:35:54 +04:00
|
|
|
getch_with_timeout (unsigned int delay_us)
|
2009-07-04 14:48:39 +04:00
|
|
|
{
|
|
|
|
fd_set Read_FD_Set;
|
|
|
|
int c;
|
2010-02-02 13:48:08 +03:00
|
|
|
struct timeval time_out;
|
2003-02-23 08:05:49 +03:00
|
|
|
|
2021-10-02 13:09:34 +03:00
|
|
|
time_out.tv_sec = delay_us / G_USEC_PER_SEC;
|
|
|
|
time_out.tv_usec = delay_us % G_USEC_PER_SEC;
|
2009-07-04 14:48:39 +04:00
|
|
|
tty_nodelay (TRUE);
|
|
|
|
FD_ZERO (&Read_FD_Set);
|
|
|
|
FD_SET (input_fd, &Read_FD_Set);
|
2010-02-02 13:48:08 +03:00
|
|
|
select (input_fd + 1, &Read_FD_Set, NULL, NULL, &time_out);
|
2009-07-04 14:48:39 +04:00
|
|
|
c = tty_lowlevel_getch ();
|
|
|
|
tty_nodelay (FALSE);
|
|
|
|
return c;
|
|
|
|
}
|
2003-02-23 08:05:49 +03:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2003-02-23 08:05:49 +03:00
|
|
|
static void
|
2009-07-04 14:48:39 +04:00
|
|
|
learn_store_key (char *buffer, char **p, int c)
|
2003-02-23 08:05:49 +03:00
|
|
|
{
|
2009-07-04 14:48:39 +04:00
|
|
|
if (*p - buffer > 253)
|
2009-09-17 02:07:04 +04:00
|
|
|
return;
|
2019-04-13 13:28:09 +03:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
if (c == ESC_CHAR)
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
*(*p)++ = '\\';
|
|
|
|
*(*p)++ = 'e';
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
else if (c < ' ')
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
*(*p)++ = '^';
|
|
|
|
*(*p)++ = c + 'a' - 1;
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
else if (c == '^')
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
*(*p)++ = '^';
|
|
|
|
*(*p)++ = '^';
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
else
|
2009-09-17 02:07:04 +04:00
|
|
|
*(*p)++ = (char) c;
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
2003-02-23 08:23:04 +03:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
static void
|
2009-09-17 02:07:04 +04:00
|
|
|
k_dispose (key_def * k)
|
2009-07-04 14:48:39 +04:00
|
|
|
{
|
2010-11-08 13:21:45 +03:00
|
|
|
if (k != NULL)
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
k_dispose (k->child);
|
|
|
|
k_dispose (k->next);
|
|
|
|
g_free (k);
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
|
|
|
}
|
2003-02-23 08:05:49 +03:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static int
|
2011-01-22 00:36:29 +03:00
|
|
|
key_code_comparator_by_name (const void *p1, const void *p2)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2016-02-20 12:54:31 +03:00
|
|
|
const key_code_name_t *n1 = *(const key_code_name_t * const *) p1;
|
|
|
|
const key_code_name_t *n2 = *(const key_code_name_t * const *) p2;
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2011-10-21 20:11:22 +04:00
|
|
|
return g_ascii_strcasecmp (n1->name, n2->name);
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2011-01-22 00:36:29 +03:00
|
|
|
static int
|
|
|
|
key_code_comparator_by_code (const void *p1, const void *p2)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2016-02-20 12:54:31 +03:00
|
|
|
const key_code_name_t *n1 = *(const key_code_name_t * const *) p1;
|
|
|
|
const key_code_name_t *n2 = *(const key_code_name_t * const *) p2;
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2011-01-22 00:36:29 +03:00
|
|
|
return n1->code - n2->code;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
sort_key_conv_tab (enum KeySortType type_sort)
|
|
|
|
{
|
|
|
|
if (has_been_sorted != type_sort)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
|
|
|
size_t i;
|
2019-04-13 13:28:09 +03:00
|
|
|
|
2011-01-22 00:36:29 +03:00
|
|
|
for (i = 0; i < key_conv_tab_size; i++)
|
|
|
|
key_conv_tab_sorted[i] = &key_name_conv_tab[i];
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2011-01-22 00:36:29 +03:00
|
|
|
if (type_sort == KEY_SORTBYNAME)
|
|
|
|
qsort (key_conv_tab_sorted, key_conv_tab_size, sizeof (key_conv_tab_sorted[0]),
|
|
|
|
&key_code_comparator_by_name);
|
|
|
|
else if (type_sort == KEY_SORTBYCODE)
|
|
|
|
qsort (key_conv_tab_sorted, key_conv_tab_size, sizeof (key_conv_tab_sorted[0]),
|
|
|
|
&key_code_comparator_by_code);
|
2019-04-13 13:28:09 +03:00
|
|
|
|
2011-01-22 00:36:29 +03:00
|
|
|
has_been_sorted = type_sort;
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static int
|
|
|
|
lookup_keyname (const char *name, int *idx)
|
|
|
|
{
|
|
|
|
if (name[0] != '\0')
|
|
|
|
{
|
|
|
|
const key_code_name_t key = { 0, name, NULL, NULL };
|
|
|
|
const key_code_name_t *keyp = &key;
|
2016-02-20 12:54:31 +03:00
|
|
|
const key_code_name_t **res;
|
2010-11-08 13:21:45 +03:00
|
|
|
|
|
|
|
if (name[1] == '\0')
|
|
|
|
{
|
|
|
|
*idx = -1;
|
|
|
|
return (int) name[0];
|
|
|
|
}
|
|
|
|
|
2011-01-22 00:36:29 +03:00
|
|
|
sort_key_conv_tab (KEY_SORTBYNAME);
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2011-01-22 00:36:29 +03:00
|
|
|
res = bsearch (&keyp, key_conv_tab_sorted, key_conv_tab_size,
|
|
|
|
sizeof (key_conv_tab_sorted[0]), key_code_comparator_by_name);
|
2010-11-08 13:21:45 +03:00
|
|
|
|
|
|
|
if (res != NULL)
|
|
|
|
{
|
2016-02-20 12:54:31 +03:00
|
|
|
*idx = (int) (res - key_conv_tab_sorted);
|
2010-11-08 13:21:45 +03:00
|
|
|
return (*res)->code;
|
|
|
|
}
|
|
|
|
}
|
1999-04-21 23:18:31 +04:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
*idx = -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-01-22 00:36:29 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
lookup_keycode (const long code, int *idx)
|
|
|
|
{
|
|
|
|
if (code != 0)
|
|
|
|
{
|
|
|
|
const key_code_name_t key = { code, NULL, NULL, NULL };
|
|
|
|
const key_code_name_t *keyp = &key;
|
2016-02-20 12:54:31 +03:00
|
|
|
const key_code_name_t **res;
|
2011-01-22 00:36:29 +03:00
|
|
|
|
|
|
|
sort_key_conv_tab (KEY_SORTBYCODE);
|
|
|
|
|
|
|
|
res = bsearch (&keyp, key_conv_tab_sorted, key_conv_tab_size,
|
|
|
|
sizeof (key_conv_tab_sorted[0]), key_code_comparator_by_code);
|
|
|
|
|
|
|
|
if (res != NULL)
|
|
|
|
{
|
2016-02-20 12:54:31 +03:00
|
|
|
*idx = (int) (res - key_conv_tab_sorted);
|
2011-01-22 00:36:29 +03:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*idx = -1;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/*** public functions ****************************************************************************/
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2009-05-13 17:05:55 +04:00
|
|
|
/* This has to be called before init_slang or whatever routine
|
1998-02-27 07:54:42 +03:00
|
|
|
calls any define_sequence */
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2005-03-21 23:27:55 +03:00
|
|
|
void
|
|
|
|
init_key (void)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2019-04-13 13:28:09 +03:00
|
|
|
const char *term;
|
|
|
|
|
|
|
|
term = getenv ("TERM");
|
2005-03-21 23:27:55 +03:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
/* This has to be the first define_sequence */
|
|
|
|
/* So, we can assume that the first keys member has ESC */
|
|
|
|
define_sequences (mc_default_keys);
|
2003-05-30 23:56:43 +04:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Terminfo on irix does not have some keys */
|
2011-09-06 14:35:42 +04:00
|
|
|
if (mc_global.tty.xterm_flag
|
2009-09-17 02:07:04 +04:00
|
|
|
|| (term != NULL
|
|
|
|
&& (strncmp (term, "iris-ansi", 9) == 0
|
|
|
|
|| strncmp (term, "xterm", 5) == 0
|
2013-05-29 16:41:37 +04:00
|
|
|
|| strncmp (term, "rxvt", 4) == 0 || strncmp (term, "screen", 6) == 0)))
|
2009-09-17 02:07:04 +04:00
|
|
|
define_sequences (xterm_key_defines);
|
2003-05-30 23:56:43 +04:00
|
|
|
|
1998-05-20 06:19:17 +04:00
|
|
|
/* load some additional keys (e.g. direct Alt-? support) */
|
2005-03-21 23:27:55 +03:00
|
|
|
load_xtra_key_defines ();
|
|
|
|
|
1998-05-20 06:19:17 +04:00
|
|
|
#ifdef __QNX__
|
2010-11-08 13:21:45 +03:00
|
|
|
if ((term != NULL) && (strncmp (term, "qnx", 3) == 0))
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
/* Modify the default value of use_8th_bit_as_meta: we would
|
|
|
|
* like to provide a working mc for a newbie who knows nothing
|
|
|
|
* about [Options|Display bits|Full 8 bits input]...
|
|
|
|
*
|
|
|
|
* Don't use 'meta'-bit, when we are dealing with a
|
|
|
|
* 'qnx*'-type terminal: clear the default value!
|
|
|
|
* These terminal types use 0xFF as an escape character,
|
|
|
|
* so use_8th_bit_as_meta==1 must not be enabled!
|
|
|
|
*
|
|
|
|
* [mc-4.1.21+,slint.c/getch(): the DEC_8BIT_HACK stuff
|
|
|
|
* is not used now (doesn't even depend on use_8th_bit_as_meta
|
|
|
|
* as in mc-3.1.2)...GREAT!...no additional code is required!]
|
|
|
|
*/
|
2016-11-25 09:17:03 +03:00
|
|
|
use_8th_bit_as_meta = FALSE;
|
1998-05-20 06:19:17 +04:00
|
|
|
}
|
2009-09-17 02:07:04 +04:00
|
|
|
#endif /* __QNX__ */
|
2001-06-06 02:08:31 +04:00
|
|
|
|
2012-10-30 13:07:46 +04:00
|
|
|
#ifdef HAVE_TEXTMODE_X11_SUPPORT
|
2003-02-23 08:05:49 +03:00
|
|
|
init_key_x11 ();
|
2012-10-30 13:07:46 +04:00
|
|
|
#endif
|
2004-09-26 04:58:47 +04:00
|
|
|
|
2006-01-07 15:49:08 +03:00
|
|
|
/* Load the qansi-m key definitions
|
2004-09-26 04:58:47 +04:00
|
|
|
if we are running under the qansi-m terminal */
|
2009-07-04 14:48:39 +04:00
|
|
|
if (term != NULL && (strncmp (term, "qansi-m", 7) == 0))
|
2009-09-17 02:07:04 +04:00
|
|
|
define_sequences (qansi_key_defines);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* This has to be called after SLang_init_tty/slint_init
|
|
|
|
*/
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
void
|
|
|
|
init_key_input_fd (void)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
#ifdef HAVE_SLANG
|
|
|
|
input_fd = SLang_TT_Read_FD;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
void
|
|
|
|
done_key (void)
|
|
|
|
{
|
|
|
|
k_dispose (keys);
|
2019-04-09 13:56:57 +03:00
|
|
|
g_slist_free_full (select_list, g_free);
|
2009-07-04 14:48:39 +04:00
|
|
|
|
|
|
|
#ifdef HAVE_TEXTMODE_X11_SUPPORT
|
|
|
|
if (x11_display)
|
2009-09-17 02:07:04 +04:00
|
|
|
mc_XCloseDisplay (x11_display);
|
2009-07-04 14:48:39 +04:00
|
|
|
#endif
|
|
|
|
}
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
void
|
|
|
|
add_select_channel (int fd, select_fn callback, void *info)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2019-04-09 13:56:57 +03:00
|
|
|
select_t *new;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2019-04-09 13:56:57 +03:00
|
|
|
new = g_new (select_t, 1);
|
2009-07-04 14:48:39 +04:00
|
|
|
new->fd = fd;
|
|
|
|
new->callback = callback;
|
|
|
|
new->info = info;
|
2019-04-09 13:56:57 +03:00
|
|
|
|
|
|
|
select_list = g_slist_prepend (select_list, new);
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
void
|
|
|
|
delete_select_channel (int fd)
|
|
|
|
{
|
2019-04-09 13:56:57 +03:00
|
|
|
GSList *p;
|
2009-09-17 02:07:04 +04:00
|
|
|
|
2019-04-09 13:56:57 +03:00
|
|
|
p = g_slist_find_custom (select_list, GINT_TO_POINTER (fd), select_cmp_by_fd);
|
|
|
|
if (p != NULL)
|
|
|
|
select_list = g_slist_delete_link (select_list, p);
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
void
|
|
|
|
channels_up (void)
|
|
|
|
{
|
|
|
|
if (disabled_channels == 0)
|
2009-09-17 02:07:04 +04:00
|
|
|
fputs ("Error: channels_up called with disabled_channels = 0\n", stderr);
|
2009-07-04 14:48:39 +04:00
|
|
|
disabled_channels--;
|
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
void
|
|
|
|
channels_down (void)
|
|
|
|
{
|
|
|
|
disabled_channels++;
|
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Return the code associated with the symbolic name keyname
|
|
|
|
*/
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2009-11-06 14:41:54 +03:00
|
|
|
long
|
2023-04-15 15:19:05 +03:00
|
|
|
tty_keyname_to_keycode (const char *name, char **label)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2009-10-30 04:12:04 +03:00
|
|
|
char **lc_keys, **p;
|
2016-02-20 12:54:31 +03:00
|
|
|
char *cname;
|
2009-07-04 14:48:39 +04:00
|
|
|
int k = -1;
|
|
|
|
int key = 0;
|
2009-10-30 04:12:04 +03:00
|
|
|
int lc_index = -1;
|
2009-10-09 15:46:08 +04:00
|
|
|
|
|
|
|
int use_meta = -1;
|
|
|
|
int use_ctrl = -1;
|
|
|
|
int use_shift = -1;
|
2009-07-04 14:48:39 +04:00
|
|
|
|
2010-02-02 13:48:08 +03:00
|
|
|
if (name == NULL)
|
2010-11-08 13:21:45 +03:00
|
|
|
return 0;
|
2009-10-09 15:46:08 +04:00
|
|
|
|
2016-02-20 12:54:31 +03:00
|
|
|
cname = g_strstrip (g_strdup (name));
|
|
|
|
lc_keys = g_strsplit_set (cname, "-+ ", -1);
|
|
|
|
g_free (cname);
|
2009-10-09 15:46:08 +04:00
|
|
|
|
2013-08-07 13:48:54 +04:00
|
|
|
for (p = lc_keys; p != NULL && *p != NULL; p++)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
|
|
|
if ((*p)[0] != '\0')
|
|
|
|
{
|
|
|
|
int idx;
|
|
|
|
|
|
|
|
key = lookup_keyname (g_strstrip (*p), &idx);
|
|
|
|
|
|
|
|
if (key == KEY_M_ALT)
|
|
|
|
use_meta = idx;
|
|
|
|
else if (key == KEY_M_CTRL)
|
|
|
|
use_ctrl = idx;
|
|
|
|
else if (key == KEY_M_SHIFT)
|
|
|
|
use_shift = idx;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
k = key;
|
|
|
|
lc_index = idx;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
2009-10-09 15:46:08 +04:00
|
|
|
|
2009-10-30 04:12:04 +03:00
|
|
|
g_strfreev (lc_keys);
|
2009-10-09 15:46:08 +04:00
|
|
|
|
|
|
|
/* output */
|
|
|
|
if (k <= 0)
|
2010-11-08 13:21:45 +03:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (label != NULL)
|
|
|
|
{
|
|
|
|
GString *s;
|
|
|
|
|
|
|
|
s = g_string_new ("");
|
|
|
|
|
|
|
|
if (use_meta != -1)
|
|
|
|
{
|
2011-01-22 00:36:29 +03:00
|
|
|
g_string_append (s, key_conv_tab_sorted[use_meta]->shortcut);
|
2010-11-08 13:21:45 +03:00
|
|
|
g_string_append_c (s, '-');
|
|
|
|
}
|
|
|
|
if (use_ctrl != -1)
|
|
|
|
{
|
2011-01-22 00:36:29 +03:00
|
|
|
g_string_append (s, key_conv_tab_sorted[use_ctrl]->shortcut);
|
2010-11-08 13:21:45 +03:00
|
|
|
g_string_append_c (s, '-');
|
|
|
|
}
|
|
|
|
if (use_shift != -1)
|
|
|
|
{
|
|
|
|
if (k < 127)
|
|
|
|
g_string_append_c (s, (gchar) g_ascii_toupper ((gchar) k));
|
|
|
|
else
|
|
|
|
{
|
2011-01-22 00:36:29 +03:00
|
|
|
g_string_append (s, key_conv_tab_sorted[use_shift]->shortcut);
|
2010-11-08 13:21:45 +03:00
|
|
|
g_string_append_c (s, '-');
|
2011-01-22 00:36:29 +03:00
|
|
|
g_string_append (s, key_conv_tab_sorted[lc_index]->shortcut);
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (k < 128)
|
|
|
|
{
|
2011-09-06 14:35:42 +04:00
|
|
|
if ((k >= 'A') || (lc_index < 0) || (key_conv_tab_sorted[lc_index]->shortcut == NULL))
|
2010-11-08 13:21:45 +03:00
|
|
|
g_string_append_c (s, (gchar) g_ascii_tolower ((gchar) k));
|
|
|
|
else
|
2011-01-22 00:36:29 +03:00
|
|
|
g_string_append (s, key_conv_tab_sorted[lc_index]->shortcut);
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
2011-01-22 00:36:29 +03:00
|
|
|
else if ((lc_index != -1) && (key_conv_tab_sorted[lc_index]->shortcut != NULL))
|
|
|
|
g_string_append (s, key_conv_tab_sorted[lc_index]->shortcut);
|
2010-11-08 13:21:45 +03:00
|
|
|
else
|
|
|
|
g_string_append_c (s, (gchar) g_ascii_tolower ((gchar) key));
|
|
|
|
|
|
|
|
*label = g_string_free (s, FALSE);
|
2009-10-09 15:46:08 +04:00
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
if (use_shift != -1)
|
|
|
|
{
|
|
|
|
if (k < 127 && k > 31)
|
|
|
|
k = g_ascii_toupper ((gchar) k);
|
|
|
|
else
|
|
|
|
k |= KEY_M_SHIFT;
|
2009-10-09 15:46:08 +04:00
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
if (use_ctrl != -1)
|
|
|
|
{
|
2009-10-09 15:46:08 +04:00
|
|
|
if (k < 256)
|
|
|
|
k = XCTRL (k);
|
|
|
|
else
|
|
|
|
k |= KEY_M_CTRL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (use_meta != -1)
|
|
|
|
k = ALT (k);
|
2006-01-07 15:49:08 +03:00
|
|
|
|
2009-11-06 14:41:54 +03:00
|
|
|
return (long) k;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2011-01-22 00:36:29 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
char *
|
2023-04-15 15:19:05 +03:00
|
|
|
tty_keycode_to_keyname (const int keycode)
|
2011-01-22 00:36:29 +03:00
|
|
|
{
|
|
|
|
/* code without modifier */
|
|
|
|
unsigned int k = keycode & ~KEY_M_MASK;
|
|
|
|
/* modifier */
|
|
|
|
unsigned int mod = keycode & KEY_M_MASK;
|
|
|
|
|
|
|
|
int key_idx = -1;
|
|
|
|
|
|
|
|
GString *s;
|
|
|
|
int idx;
|
|
|
|
|
|
|
|
s = g_string_sized_new (8);
|
|
|
|
|
|
|
|
if (lookup_keycode (k, &key_idx) || (k > 0 && k < 256))
|
|
|
|
{
|
2019-04-13 13:28:09 +03:00
|
|
|
if ((mod & KEY_M_ALT) != 0 && lookup_keycode (KEY_M_ALT, &idx))
|
2011-01-22 00:36:29 +03:00
|
|
|
{
|
2019-04-13 13:28:09 +03:00
|
|
|
g_string_append (s, key_conv_tab_sorted[idx]->name);
|
|
|
|
g_string_append_c (s, '-');
|
2011-01-22 00:36:29 +03:00
|
|
|
}
|
2019-04-13 13:28:09 +03:00
|
|
|
|
|
|
|
if ((mod & KEY_M_CTRL) != 0)
|
2011-01-22 00:36:29 +03:00
|
|
|
{
|
|
|
|
/* non printeble chars like a CTRL-[A..Z] */
|
|
|
|
if (k < 32)
|
|
|
|
k += 64;
|
|
|
|
|
|
|
|
if (lookup_keycode (KEY_M_CTRL, &idx))
|
|
|
|
{
|
2013-10-10 16:21:26 +04:00
|
|
|
g_string_append (s, key_conv_tab_sorted[idx]->name);
|
2011-01-22 00:36:29 +03:00
|
|
|
g_string_append_c (s, '-');
|
|
|
|
}
|
|
|
|
}
|
2019-04-13 13:28:09 +03:00
|
|
|
|
|
|
|
if ((mod & KEY_M_SHIFT) != 0)
|
2011-01-22 00:36:29 +03:00
|
|
|
{
|
|
|
|
if (lookup_keycode (KEY_M_ALT, &idx))
|
|
|
|
{
|
|
|
|
if (k < 127)
|
|
|
|
g_string_append_c (s, (gchar) g_ascii_toupper ((gchar) k));
|
|
|
|
else
|
|
|
|
{
|
2013-10-10 16:21:26 +04:00
|
|
|
g_string_append (s, key_conv_tab_sorted[idx]->name);
|
2011-01-22 00:36:29 +03:00
|
|
|
g_string_append_c (s, '-');
|
|
|
|
g_string_append (s, key_conv_tab_sorted[key_idx]->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (k < 128)
|
|
|
|
{
|
2011-09-06 14:35:42 +04:00
|
|
|
if ((k >= 'A') || (key_idx < 0) || (key_conv_tab_sorted[key_idx]->name == NULL))
|
2011-01-22 00:36:29 +03:00
|
|
|
g_string_append_c (s, (gchar) k);
|
|
|
|
else
|
|
|
|
g_string_append (s, key_conv_tab_sorted[key_idx]->name);
|
|
|
|
}
|
|
|
|
else if ((key_idx != -1) && (key_conv_tab_sorted[key_idx]->name != NULL))
|
|
|
|
g_string_append (s, key_conv_tab_sorted[key_idx]->name);
|
|
|
|
else
|
|
|
|
g_string_append_c (s, (gchar) keycode);
|
|
|
|
}
|
|
|
|
|
|
|
|
return g_string_free (s, s->len == 0);
|
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
2009-07-04 14:48:39 +04:00
|
|
|
* Return TRUE on success, FALSE on error.
|
2001-08-14 08:48:26 +04:00
|
|
|
* An error happens if SEQ is a beginning of an existing longer sequence.
|
|
|
|
*/
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
gboolean
|
|
|
|
define_sequence (int code, const char *seq, int action)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
key_def *base;
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
if (strlen (seq) > SEQ_BUFFER_LEN - 1)
|
2009-09-17 02:07:04 +04:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
for (base = keys; (base != NULL) && (*seq != '\0');)
|
2010-11-08 13:21:45 +03:00
|
|
|
if (*seq == base->ch)
|
|
|
|
{
|
2019-04-13 13:28:09 +03:00
|
|
|
if (base->child == NULL)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
if (*(seq + 1) != '\0')
|
|
|
|
base->child = create_sequence (seq + 1, code, action);
|
2010-11-08 13:21:45 +03:00
|
|
|
else
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
/* The sequence matches an existing one. */
|
|
|
|
base->code = code;
|
|
|
|
base->action = action;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
base = base->child;
|
|
|
|
seq++;
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-04-13 13:28:09 +03:00
|
|
|
if (base->next != NULL)
|
2009-09-17 02:07:04 +04:00
|
|
|
base = base->next;
|
2010-11-08 13:21:45 +03:00
|
|
|
else
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
base->next = create_sequence (seq, code, action);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
2001-08-14 08:48:26 +04:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
if (*seq == '\0')
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
/* Attempt to redefine a sequence with a shorter sequence. */
|
|
|
|
return FALSE;
|
2001-08-14 08:48:26 +04:00
|
|
|
}
|
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
keys = create_sequence (seq, code, action);
|
2009-07-04 14:48:39 +04:00
|
|
|
return TRUE;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
2009-07-04 14:48:39 +04:00
|
|
|
* Check if we are idle, i.e. there are no pending keyboard or mouse
|
|
|
|
* events. Return 1 is idle, 0 is there are pending events.
|
|
|
|
*/
|
|
|
|
gboolean
|
|
|
|
is_idle (void)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2013-05-29 16:41:37 +04:00
|
|
|
int nfd;
|
2009-07-04 14:48:39 +04:00
|
|
|
fd_set select_set;
|
2010-02-02 13:48:08 +03:00
|
|
|
struct timeval time_out;
|
2002-12-23 12:46:28 +03:00
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
FD_ZERO (&select_set);
|
|
|
|
FD_SET (input_fd, &select_set);
|
2016-04-07 10:52:04 +03:00
|
|
|
nfd = MAX (0, input_fd) + 1;
|
2013-05-29 16:41:37 +04:00
|
|
|
time_out.tv_sec = 0;
|
|
|
|
time_out.tv_usec = 0;
|
2009-07-04 14:48:39 +04:00
|
|
|
#ifdef HAVE_LIBGPM
|
2013-05-29 16:41:37 +04:00
|
|
|
if (mouse_enabled && use_mouse_p == MOUSE_GPM)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2013-05-29 16:41:37 +04:00
|
|
|
if (gpm_fd >= 0)
|
|
|
|
{
|
|
|
|
FD_SET (gpm_fd, &select_set);
|
2016-04-07 10:52:04 +03:00
|
|
|
nfd = MAX (nfd, gpm_fd + 1);
|
2013-05-29 16:41:37 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (mouse_fd >= 0) /* error indicative */
|
|
|
|
{
|
|
|
|
if (FD_ISSET (mouse_fd, &select_set))
|
|
|
|
FD_CLR (mouse_fd, &select_set);
|
|
|
|
mouse_fd = gpm_fd;
|
|
|
|
}
|
|
|
|
/* gpm_fd == -2 means under some X terminal */
|
|
|
|
if (gpm_fd == -1)
|
|
|
|
{
|
|
|
|
mouse_enabled = FALSE;
|
|
|
|
use_mouse_p = MOUSE_NONE;
|
|
|
|
}
|
|
|
|
}
|
2009-07-04 14:48:39 +04:00
|
|
|
}
|
|
|
|
#endif
|
2013-05-29 16:41:37 +04:00
|
|
|
return (select (nfd, &select_set, 0, 0, &time_out) <= 0);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
int
|
|
|
|
get_key_code (int no_delay)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
int c;
|
|
|
|
static key_def *this = NULL, *parent;
|
2021-10-02 13:26:07 +03:00
|
|
|
static gint64 esc_time = -1;
|
1998-02-27 07:54:42 +03:00
|
|
|
static int lastnodelay = -1;
|
2006-01-07 15:49:08 +03:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
if (no_delay != lastnodelay)
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
this = NULL;
|
|
|
|
lastnodelay = no_delay;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2009-09-17 02:07:04 +04:00
|
|
|
pend_send:
|
2010-11-08 13:21:45 +03:00
|
|
|
if (pending_keys != NULL)
|
|
|
|
{
|
2013-05-21 15:47:30 +04:00
|
|
|
gboolean bad_seq;
|
2013-02-13 13:50:18 +04:00
|
|
|
|
2020-02-22 11:04:55 +03:00
|
|
|
c = *pending_keys++;
|
|
|
|
while (c == ESC_CHAR)
|
|
|
|
c = ALT (*pending_keys++);
|
2013-02-13 13:50:18 +04:00
|
|
|
|
2020-02-22 10:57:40 +03:00
|
|
|
bad_seq = (*pending_keys != ESC_CHAR && *pending_keys != '\0');
|
2013-05-21 15:47:30 +04:00
|
|
|
if (*pending_keys == '\0' || bad_seq)
|
2013-02-13 13:50:18 +04:00
|
|
|
pending_keys = seq_append = NULL;
|
|
|
|
|
2013-05-21 15:47:30 +04:00
|
|
|
if (bad_seq)
|
2013-05-21 16:35:54 +04:00
|
|
|
{
|
|
|
|
/* This is an unknown ESC sequence.
|
|
|
|
* To prevent interpreting its tail as a random garbage,
|
|
|
|
* eat and discard all buffered and quickly following chars.
|
|
|
|
* Small, but non-zero timeout is needed to reconnect
|
|
|
|
* escape sequence split up by e.g. a serial line.
|
|
|
|
*/
|
|
|
|
int paranoia = 20;
|
|
|
|
|
|
|
|
while (getch_with_timeout (old_esc_mode_timeout) >= 0 && --paranoia != 0)
|
|
|
|
;
|
|
|
|
}
|
2020-02-22 11:39:35 +03:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (c > 127 && c < 256 && use_8th_bit_as_meta)
|
|
|
|
c = ALT (c & 0x7f);
|
2013-05-21 15:47:30 +04:00
|
|
|
|
2020-02-22 11:39:35 +03:00
|
|
|
goto done;
|
|
|
|
}
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2009-09-17 02:07:04 +04:00
|
|
|
nodelay_try_again:
|
2019-04-13 13:28:09 +03:00
|
|
|
if (no_delay != 0)
|
2009-09-17 02:07:04 +04:00
|
|
|
tty_nodelay (TRUE);
|
2009-07-04 14:48:39 +04:00
|
|
|
|
2009-06-19 21:33:41 +04:00
|
|
|
c = tty_lowlevel_getch ();
|
2008-12-29 03:01:53 +03:00
|
|
|
#if (defined(USE_NCURSES) || defined(USE_NCURSESW)) && defined(KEY_RESIZE)
|
2002-02-06 08:23:50 +03:00
|
|
|
if (c == KEY_RESIZE)
|
2009-09-17 02:07:04 +04:00
|
|
|
goto nodelay_try_again;
|
2002-02-06 08:23:50 +03:00
|
|
|
#endif
|
2019-04-13 13:28:09 +03:00
|
|
|
|
|
|
|
if (no_delay != 0)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
tty_nodelay (FALSE);
|
2010-11-08 13:21:45 +03:00
|
|
|
if (c == -1)
|
|
|
|
{
|
2020-02-22 11:39:35 +03:00
|
|
|
if (this == NULL || parent == NULL || parent->action != MCKEY_ESCAPE || !old_esc_mode ||
|
2021-10-03 17:12:42 +03:00
|
|
|
esc_time == -1 || g_get_monotonic_time () < esc_time + old_esc_mode_timeout)
|
2020-02-22 11:39:35 +03:00
|
|
|
return -1;
|
2019-04-13 13:28:09 +03:00
|
|
|
|
2020-02-22 11:39:35 +03:00
|
|
|
this = NULL;
|
|
|
|
pending_keys = seq_append = NULL;
|
|
|
|
return ESC_CHAR;
|
2009-09-17 02:07:04 +04:00
|
|
|
}
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
else if (c == -1)
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
/* Maybe we got an incomplete match.
|
|
|
|
This we do only in delay mode, since otherwise
|
|
|
|
tty_lowlevel_getch can return -1 at any time. */
|
2020-02-22 11:39:35 +03:00
|
|
|
if (seq_append == NULL)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2020-02-22 11:39:35 +03:00
|
|
|
this = NULL;
|
|
|
|
return -1;
|
2009-09-17 02:07:04 +04:00
|
|
|
}
|
2020-02-22 11:39:35 +03:00
|
|
|
|
|
|
|
pending_keys = seq_buffer;
|
|
|
|
goto pend_send;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
2006-01-07 15:49:08 +03:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Search the key on the root */
|
2019-04-13 13:28:09 +03:00
|
|
|
if (no_delay == 0 || this == NULL)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
this = keys;
|
|
|
|
parent = NULL;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2019-04-13 13:28:09 +03:00
|
|
|
if (c > 127 && c < 256 && use_8th_bit_as_meta)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
c &= 0x7f;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2009-09-17 02:07:04 +04:00
|
|
|
/* The first sequence defined starts with esc */
|
|
|
|
parent = keys;
|
|
|
|
this = keys->child;
|
|
|
|
}
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
2013-05-20 16:34:21 +04:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
while (this != NULL)
|
|
|
|
{
|
|
|
|
if (c == this->ch)
|
|
|
|
{
|
2013-05-21 15:47:30 +04:00
|
|
|
if (this->child == NULL)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
/* We got a complete match, return and reset search */
|
|
|
|
pending_keys = seq_append = NULL;
|
2020-02-22 11:04:55 +03:00
|
|
|
c = this->code;
|
|
|
|
goto done;
|
2009-09-17 02:07:04 +04:00
|
|
|
}
|
2019-04-13 13:28:09 +03:00
|
|
|
|
2013-05-20 16:34:21 +04:00
|
|
|
/* No match yet, but it may be a prefix for a valid seq */
|
|
|
|
if (!push_char (c))
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2013-05-20 16:34:21 +04:00
|
|
|
pending_keys = seq_buffer;
|
|
|
|
goto pend_send;
|
|
|
|
}
|
2019-04-13 13:28:09 +03:00
|
|
|
|
2013-05-20 16:34:21 +04:00
|
|
|
parent = this;
|
|
|
|
this = this->child;
|
|
|
|
if (parent->action == MCKEY_ESCAPE && old_esc_mode)
|
|
|
|
{
|
2019-04-13 13:28:09 +03:00
|
|
|
if (no_delay != 0)
|
2013-05-20 16:34:21 +04:00
|
|
|
{
|
2021-10-03 17:12:42 +03:00
|
|
|
esc_time = g_get_monotonic_time ();
|
2013-05-20 16:34:21 +04:00
|
|
|
goto nodelay_try_again;
|
|
|
|
}
|
2019-04-13 13:28:09 +03:00
|
|
|
|
2021-10-02 13:26:07 +03:00
|
|
|
esc_time = -1;
|
2013-05-21 16:35:54 +04:00
|
|
|
c = getch_with_timeout (old_esc_mode_timeout);
|
2020-02-22 11:39:35 +03:00
|
|
|
if (c != -1)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
pending_keys = seq_append = NULL;
|
|
|
|
this = NULL;
|
|
|
|
return ESC_CHAR;
|
2009-09-17 02:07:04 +04:00
|
|
|
}
|
2019-04-13 13:28:09 +03:00
|
|
|
|
|
|
|
if (no_delay != 0)
|
2013-05-20 16:34:21 +04:00
|
|
|
goto nodelay_try_again;
|
|
|
|
c = tty_lowlevel_getch ();
|
|
|
|
continue;
|
2009-09-17 02:07:04 +04:00
|
|
|
}
|
2013-05-20 16:34:21 +04:00
|
|
|
|
|
|
|
/* c != this->ch. Try other keys with this prefix */
|
|
|
|
if (this->next != NULL)
|
|
|
|
{
|
|
|
|
this = this->next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No match found. Is it one of our ESC <key> specials? */
|
|
|
|
if ((parent != NULL) && (parent->action == MCKEY_ESCAPE))
|
|
|
|
{
|
|
|
|
/* Convert escape-digits to F-keys */
|
|
|
|
if (g_ascii_isdigit (c))
|
|
|
|
c = KEY_F (c - '0');
|
|
|
|
else if (c == ' ')
|
|
|
|
c = ESC_CHAR;
|
|
|
|
else
|
|
|
|
c = ALT (c);
|
|
|
|
|
|
|
|
pending_keys = seq_append = NULL;
|
2020-02-22 11:04:55 +03:00
|
|
|
goto done;
|
2013-05-20 16:34:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Unknown sequence. Maybe a prefix of a longer one. Save it. */
|
|
|
|
push_char (c);
|
|
|
|
pending_keys = seq_buffer;
|
|
|
|
goto pend_send;
|
|
|
|
} /* while (this != NULL) */
|
|
|
|
|
2020-02-22 11:04:55 +03:00
|
|
|
done:
|
1998-02-27 07:54:42 +03:00
|
|
|
this = NULL;
|
|
|
|
return correct_key_code (c);
|
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Returns a character read from stdin with appropriate interpretation */
|
|
|
|
/* Also takes care of generated mouse events */
|
|
|
|
/* Returns EV_MOUSE if it is a mouse event */
|
|
|
|
/* Returns EV_NONE if non-blocking or interrupt set and nothing was done */
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2002-08-31 10:40:47 +04:00
|
|
|
int
|
2009-06-19 21:33:41 +04:00
|
|
|
tty_get_event (struct Gpm_Event *event, gboolean redo_event, gboolean block)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
int c;
|
2013-12-02 16:42:01 +04:00
|
|
|
int flag = 0; /* Return value from select */
|
1998-02-27 07:54:42 +03:00
|
|
|
#ifdef HAVE_LIBGPM
|
2009-09-17 02:07:04 +04:00
|
|
|
static struct Gpm_Event ev; /* Mouse event */
|
1998-02-27 07:54:42 +03:00
|
|
|
#endif
|
2010-02-02 13:48:08 +03:00
|
|
|
struct timeval time_out;
|
1998-02-27 07:54:42 +03:00
|
|
|
struct timeval *time_addr = NULL;
|
|
|
|
static int dirty = 3;
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
if ((dirty == 3) || is_idle ())
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
mc_refresh ();
|
|
|
|
dirty = 1;
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
else
|
2009-09-17 02:07:04 +04:00
|
|
|
dirty++;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
vfs_timeout_handler ();
|
2002-08-31 10:40:47 +04:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Ok, we use (event->x < 0) to signal that the event does not contain
|
|
|
|
a suitable position for the mouse, so we can't use show_mouse_pointer
|
|
|
|
on it.
|
2002-08-31 10:40:47 +04:00
|
|
|
*/
|
2010-11-08 13:21:45 +03:00
|
|
|
if (event->x > 0)
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
show_mouse_pointer (event->x, event->y);
|
|
|
|
if (!redo_event)
|
|
|
|
event->x = -1;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Repeat if using mouse */
|
2010-11-08 13:21:45 +03:00
|
|
|
while (pending_keys == NULL)
|
|
|
|
{
|
2013-05-29 16:41:37 +04:00
|
|
|
int nfd;
|
2009-09-17 02:07:04 +04:00
|
|
|
fd_set select_set;
|
2002-08-31 10:40:47 +04:00
|
|
|
|
2009-09-17 02:07:04 +04:00
|
|
|
FD_ZERO (&select_set);
|
|
|
|
FD_SET (input_fd, &select_set);
|
2016-04-07 10:52:04 +03:00
|
|
|
nfd = MAX (add_selects (&select_set), MAX (0, input_fd)) + 1;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
#ifdef HAVE_LIBGPM
|
2010-11-08 13:21:45 +03:00
|
|
|
if (mouse_enabled && (use_mouse_p == MOUSE_GPM))
|
|
|
|
{
|
2013-05-29 16:41:37 +04:00
|
|
|
if (gpm_fd >= 0)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2013-05-29 16:41:37 +04:00
|
|
|
FD_SET (gpm_fd, &select_set);
|
2016-04-07 10:52:04 +03:00
|
|
|
nfd = MAX (nfd, gpm_fd + 1);
|
2013-05-29 16:41:37 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (mouse_fd >= 0) /* error indicative */
|
|
|
|
{
|
|
|
|
if (FD_ISSET (mouse_fd, &select_set))
|
|
|
|
FD_CLR (mouse_fd, &select_set);
|
|
|
|
mouse_fd = gpm_fd;
|
|
|
|
}
|
|
|
|
/* gpm_fd == -2 means under some X terminal */
|
|
|
|
if (gpm_fd == -1)
|
|
|
|
{
|
|
|
|
mouse_enabled = FALSE;
|
|
|
|
use_mouse_p = MOUSE_NONE;
|
|
|
|
}
|
2009-09-17 02:07:04 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1998-02-27 07:54:42 +03:00
|
|
|
#endif
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
if (redo_event)
|
|
|
|
{
|
2021-10-02 13:09:34 +03:00
|
|
|
time_out.tv_usec = mou_auto_repeat * MC_USEC_PER_MSEC;
|
2010-02-02 13:48:08 +03:00
|
|
|
time_out.tv_sec = 0;
|
2009-09-17 02:07:04 +04:00
|
|
|
|
2010-02-02 13:48:08 +03:00
|
|
|
time_addr = &time_out;
|
2010-11-08 13:21:45 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
int seconds;
|
|
|
|
|
|
|
|
seconds = vfs_timeouts ();
|
|
|
|
time_addr = NULL;
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
if (seconds != 0)
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
/* the timeout could be improved and actually be
|
|
|
|
* the number of seconds until the next vfs entry
|
|
|
|
* timeouts in the stamp list.
|
|
|
|
*/
|
|
|
|
|
2010-02-02 13:48:08 +03:00
|
|
|
time_out.tv_sec = seconds;
|
|
|
|
time_out.tv_usec = 0;
|
|
|
|
time_addr = &time_out;
|
2009-09-17 02:07:04 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-17 17:55:50 +03:00
|
|
|
if (!block || tty_got_winch ())
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2010-02-02 13:48:08 +03:00
|
|
|
time_addr = &time_out;
|
|
|
|
time_out.tv_sec = 0;
|
|
|
|
time_out.tv_usec = 0;
|
2009-09-17 02:07:04 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
tty_enable_interrupt_key ();
|
2013-05-29 16:41:37 +04:00
|
|
|
flag = select (nfd, &select_set, NULL, NULL, time_addr);
|
2009-09-17 02:07:04 +04:00
|
|
|
tty_disable_interrupt_key ();
|
|
|
|
|
|
|
|
/* select timed out: it could be for any of the following reasons:
|
|
|
|
* redo_event -> it was because of the MOU_REPEAT handler
|
|
|
|
* !block -> we did not block in the select call
|
|
|
|
* else -> 10 second timeout to check the vfs status.
|
|
|
|
*/
|
2010-11-08 13:21:45 +03:00
|
|
|
if (flag == 0)
|
|
|
|
{
|
2009-09-17 02:07:04 +04:00
|
|
|
if (redo_event)
|
|
|
|
return EV_MOUSE;
|
2019-08-17 17:55:50 +03:00
|
|
|
if (!block || tty_got_winch ())
|
2009-09-17 02:07:04 +04:00
|
|
|
return EV_NONE;
|
|
|
|
vfs_timeout_handler ();
|
|
|
|
}
|
|
|
|
if (flag == -1 && errno == EINTR)
|
|
|
|
return EV_NONE;
|
|
|
|
|
|
|
|
check_selects (&select_set);
|
|
|
|
|
|
|
|
if (FD_ISSET (input_fd, &select_set))
|
|
|
|
break;
|
2019-04-13 13:28:09 +03:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
#ifdef HAVE_LIBGPM
|
2013-05-29 16:41:37 +04:00
|
|
|
if (mouse_enabled && use_mouse_p == MOUSE_GPM)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2013-05-29 16:41:37 +04:00
|
|
|
if (gpm_fd >= 0)
|
|
|
|
{
|
|
|
|
if (FD_ISSET (gpm_fd, &select_set))
|
|
|
|
{
|
|
|
|
int status;
|
|
|
|
|
|
|
|
status = Gpm_GetEvent (&ev);
|
|
|
|
if (status == 1) /* success */
|
|
|
|
{
|
|
|
|
Gpm_FitEvent (&ev);
|
|
|
|
*event = ev;
|
|
|
|
return EV_MOUSE;
|
|
|
|
}
|
2019-04-13 13:28:09 +03:00
|
|
|
if (status <= 0) /* connection closed; -1 == error */
|
2013-05-29 16:41:37 +04:00
|
|
|
{
|
|
|
|
if (mouse_fd >= 0 && FD_ISSET (mouse_fd, &select_set))
|
|
|
|
FD_CLR (mouse_fd, &select_set);
|
|
|
|
|
|
|
|
disable_mouse ();
|
2019-03-02 14:26:30 +03:00
|
|
|
return EV_NONE;
|
2013-05-29 16:41:37 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (mouse_fd >= 0) /* error indicative */
|
|
|
|
{
|
|
|
|
if (FD_ISSET (mouse_fd, &select_set))
|
|
|
|
FD_CLR (mouse_fd, &select_set);
|
|
|
|
mouse_fd = gpm_fd;
|
|
|
|
}
|
|
|
|
/* gpm_fd == -2 means under some X terminal */
|
|
|
|
if (gpm_fd == -1)
|
|
|
|
{
|
|
|
|
mouse_enabled = FALSE;
|
|
|
|
use_mouse_p = MOUSE_NONE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2009-09-17 02:07:04 +04:00
|
|
|
}
|
|
|
|
#endif /* !HAVE_LIBGPM */
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
2009-08-17 16:01:05 +04:00
|
|
|
|
2001-09-15 05:18:11 +04:00
|
|
|
#ifndef HAVE_SLANG
|
2002-08-31 10:40:47 +04:00
|
|
|
flag = is_wintouched (stdscr);
|
1998-02-27 07:54:42 +03:00
|
|
|
untouchwin (stdscr);
|
2009-09-17 02:07:04 +04:00
|
|
|
#endif /* !HAVE_SLANG */
|
2002-08-31 10:40:47 +04:00
|
|
|
c = block ? getch_with_delay () : get_key_code (1);
|
1998-12-02 08:18:20 +03:00
|
|
|
|
2001-09-15 05:18:11 +04:00
|
|
|
#ifndef HAVE_SLANG
|
2009-08-17 16:01:05 +04:00
|
|
|
if (flag > 0)
|
2009-09-17 02:07:04 +04:00
|
|
|
tty_touch_screen ();
|
|
|
|
#endif /* !HAVE_SLANG */
|
2002-08-31 10:40:47 +04:00
|
|
|
|
2009-08-17 16:01:05 +04:00
|
|
|
if (mouse_enabled && (c == MCKEY_MOUSE
|
2001-09-15 05:18:11 +04:00
|
|
|
#ifdef KEY_MOUSE
|
2009-09-17 02:07:04 +04:00
|
|
|
|| c == KEY_MOUSE
|
|
|
|
#endif /* KEY_MOUSE */
|
2011-12-08 14:25:03 +04:00
|
|
|
|| c == MCKEY_EXTENDED_MOUSE))
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2020-02-15 00:14:19 +03:00
|
|
|
/* Mouse event. See tickets 2956 and 3954 for extended mode detection. */
|
|
|
|
gboolean extended = c == MCKEY_EXTENDED_MOUSE;
|
|
|
|
|
|
|
|
#ifdef KEY_MOUSE
|
|
|
|
extended = extended || (c == KEY_MOUSE && xmouse_seq == NULL
|
|
|
|
&& xmouse_extended_seq != NULL);
|
|
|
|
#endif /* KEY_MOUSE */
|
|
|
|
|
|
|
|
xmouse_get_event (event, extended);
|
2013-10-01 13:31:13 +04:00
|
|
|
c = (event->type != 0) ? EV_MOUSE : EV_NONE;
|
|
|
|
}
|
|
|
|
else if (c == MCKEY_BRACKETED_PASTING_START)
|
|
|
|
{
|
|
|
|
bracketed_pasting_in_progress = TRUE;
|
|
|
|
c = EV_NONE;
|
|
|
|
}
|
|
|
|
else if (c == MCKEY_BRACKETED_PASTING_END)
|
|
|
|
{
|
|
|
|
bracketed_pasting_in_progress = FALSE;
|
|
|
|
c = EV_NONE;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return c;
|
1998-12-02 08:18:20 +03:00
|
|
|
}
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Returns a key press, mouse events are discarded */
|
2010-11-08 13:21:45 +03:00
|
|
|
|
2009-06-19 21:33:41 +04:00
|
|
|
int
|
2009-07-04 14:48:39 +04:00
|
|
|
tty_getch (void)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
Gpm_Event ev;
|
2009-07-04 14:48:39 +04:00
|
|
|
int key;
|
1998-04-15 10:05:34 +04:00
|
|
|
|
1998-04-15 10:15:42 +04:00
|
|
|
ev.x = -1;
|
2019-04-13 13:28:09 +03:00
|
|
|
while ((key = tty_get_event (&ev, FALSE, TRUE)) == EV_NONE)
|
|
|
|
;
|
1998-02-27 07:54:42 +03:00
|
|
|
return key;
|
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-07-04 14:48:39 +04:00
|
|
|
char *
|
|
|
|
learn_key (void)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2021-10-02 13:54:45 +03:00
|
|
|
/* LEARN_TIMEOUT in ms */
|
|
|
|
#define LEARN_TIMEOUT 200
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
fd_set Read_FD_Set;
|
2021-10-02 13:54:45 +03:00
|
|
|
gint64 end_time;
|
2001-08-28 01:24:29 +04:00
|
|
|
int c;
|
2009-09-17 02:07:04 +04:00
|
|
|
char buffer[256];
|
1998-02-27 07:54:42 +03:00
|
|
|
char *p = buffer;
|
2006-01-07 15:49:08 +03:00
|
|
|
|
Fix various typos in the source code (closes MidnightCommander/mc#177).
Found via `codespell -S
po,doc,./misc/syntax,./src/vfs/extfs/helpers/README.it -L
parm,rouge,sav,ect,vie,te,dum,clen,wee,dynamc,childs,ths,fo,nin,unx,nd,iif,iterm,ser,makrs,wil`
Co-authored-by: Yury V. Zaytsev <yury@shurup.com>
Signed-off-by: Kian-Meng Ang <kianmeng@cpan.org>
Signed-off-by: Yury V. Zaytsev <yury@shurup.com>
2023-01-10 06:02:52 +03:00
|
|
|
tty_keypad (FALSE); /* disable interpreting keys by ncurses */
|
2009-06-19 21:33:41 +04:00
|
|
|
c = tty_lowlevel_getch ();
|
2002-11-06 09:08:11 +03:00
|
|
|
while (c == -1)
|
2009-09-17 02:07:04 +04:00
|
|
|
c = tty_lowlevel_getch (); /* Sanity check, should be unnecessary */
|
1998-02-27 07:54:42 +03:00
|
|
|
learn_store_key (buffer, &p, c);
|
2019-04-13 13:28:09 +03:00
|
|
|
|
2021-10-03 17:12:42 +03:00
|
|
|
end_time = g_get_monotonic_time () + LEARN_TIMEOUT * MC_USEC_PER_MSEC;
|
2019-04-13 13:28:09 +03:00
|
|
|
|
2009-05-31 16:23:10 +04:00
|
|
|
tty_nodelay (TRUE);
|
2012-10-21 18:16:44 +04:00
|
|
|
while (TRUE)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
|
|
|
while ((c = tty_lowlevel_getch ()) == -1)
|
|
|
|
{
|
2021-10-02 13:54:45 +03:00
|
|
|
gint64 time_out;
|
|
|
|
struct timeval tv;
|
|
|
|
|
2021-10-03 17:12:42 +03:00
|
|
|
time_out = end_time - g_get_monotonic_time ();
|
2021-10-02 13:54:45 +03:00
|
|
|
if (time_out <= 0)
|
2009-09-17 02:07:04 +04:00
|
|
|
break;
|
2021-10-02 13:54:45 +03:00
|
|
|
|
|
|
|
tv.tv_sec = time_out / G_USEC_PER_SEC;
|
|
|
|
tv.tv_usec = time_out % G_USEC_PER_SEC;
|
|
|
|
FD_ZERO (&Read_FD_Set);
|
|
|
|
FD_SET (input_fd, &Read_FD_Set);
|
|
|
|
select (input_fd + 1, &Read_FD_Set, NULL, NULL, &tv);
|
2009-09-17 02:07:04 +04:00
|
|
|
}
|
|
|
|
if (c == -1)
|
|
|
|
break;
|
|
|
|
learn_store_key (buffer, &p, c);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
2009-05-31 16:23:10 +04:00
|
|
|
tty_keypad (TRUE);
|
|
|
|
tty_nodelay (FALSE);
|
2009-07-04 14:48:39 +04:00
|
|
|
*p = '\0';
|
2021-10-02 14:00:32 +03:00
|
|
|
return (buffer[0] != '\0' ? g_strdup (buffer) : NULL);
|
2009-07-04 14:48:39 +04:00
|
|
|
#undef LEARN_TIMEOUT
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
1998-04-01 02:36:24 +04:00
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
1998-04-01 02:36:24 +04:00
|
|
|
/* xterm and linux console only: set keypad to numeric or application
|
|
|
|
mode. Only in application keypad mode it's possible to distinguish
|
2010-11-08 13:21:45 +03:00
|
|
|
the '+' key and the '+' on the keypad ('*' and '-' ditto) */
|
|
|
|
|
1998-04-01 02:36:24 +04:00
|
|
|
void
|
|
|
|
numeric_keypad_mode (void)
|
|
|
|
{
|
2011-09-14 02:07:31 +04:00
|
|
|
if (mc_global.tty.console_flag != '\0' || mc_global.tty.xterm_flag)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2011-08-26 11:27:41 +04:00
|
|
|
fputs (ESC_STR ">", stdout);
|
2009-09-17 02:07:04 +04:00
|
|
|
fflush (stdout);
|
1998-04-01 02:36:24 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-08 13:21:45 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
1998-04-01 02:36:24 +04:00
|
|
|
void
|
|
|
|
application_keypad_mode (void)
|
|
|
|
{
|
2011-09-14 02:07:31 +04:00
|
|
|
if (mc_global.tty.console_flag != '\0' || mc_global.tty.xterm_flag)
|
2010-11-08 13:21:45 +03:00
|
|
|
{
|
2011-08-26 11:27:41 +04:00
|
|
|
fputs (ESC_STR "=", stdout);
|
2009-09-17 02:07:04 +04:00
|
|
|
fflush (stdout);
|
1998-04-01 02:36:24 +04:00
|
|
|
}
|
|
|
|
}
|
2010-11-08 13:21:45 +03:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2013-10-01 13:31:13 +04:00
|
|
|
|
|
|
|
void
|
|
|
|
enable_bracketed_paste (void)
|
|
|
|
{
|
|
|
|
printf (ESC_STR "[?2004h");
|
|
|
|
fflush (stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
void
|
|
|
|
disable_bracketed_paste (void)
|
|
|
|
{
|
|
|
|
printf (ESC_STR "[?2004l");
|
|
|
|
fflush (stdout);
|
|
|
|
bracketed_pasting_in_progress = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|