From 3a91adabda43376638e0edc80f54181258c98dea Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 12 May 2022 20:19:29 +0800 Subject: refactor: rename keymap.{c,h} to keycodes.{c,h} (#18535) Most code in keymap.h is for keycode definitions, while most code in keymap.c is for the parsing and conversion of keycodes. The name "keymap" may also make people think these two files are for mappings, while in fact keycodes are used even when no mappings are involved, so "keycodes" should be a better file name than "keymap". --- src/nvim/edit.c | 2 +- src/nvim/ex_docmd.c | 2 +- src/nvim/ex_getln.c | 2 +- src/nvim/ex_session.c | 2 +- src/nvim/getchar.c | 2 +- src/nvim/keycodes.c | 1018 ++++++++++++++++++++++++++++++++++++++++++++++++ src/nvim/keycodes.h | 499 ++++++++++++++++++++++++ src/nvim/keymap.c | 1032 ------------------------------------------------- src/nvim/keymap.h | 529 ------------------------- src/nvim/menu.c | 2 +- src/nvim/message.c | 2 +- src/nvim/normal.c | 2 +- src/nvim/option.c | 2 +- src/nvim/os/input.c | 2 +- src/nvim/syntax.c | 2 +- src/nvim/terminal.c | 2 +- src/nvim/vim.h | 2 +- 17 files changed, 1530 insertions(+), 1574 deletions(-) create mode 100644 src/nvim/keycodes.c create mode 100644 src/nvim/keycodes.h delete mode 100644 src/nvim/keymap.c delete mode 100644 src/nvim/keymap.h (limited to 'src') diff --git a/src/nvim/edit.c b/src/nvim/edit.c index f7ce9f4b5f..20bbc23ac4 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -29,7 +29,7 @@ #include "nvim/highlight_group.h" #include "nvim/indent.h" #include "nvim/indent_c.h" -#include "nvim/keymap.h" +#include "nvim/keycodes.h" #include "nvim/main.h" #include "nvim/mark.h" #include "nvim/mbyte.h" diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 0d6af35441..91b8628c33 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -41,7 +41,7 @@ #include "nvim/highlight_group.h" #include "nvim/if_cscope.h" #include "nvim/input.h" -#include "nvim/keymap.h" +#include "nvim/keycodes.h" #include "nvim/lua/executor.h" #include "nvim/main.h" #include "nvim/mark.h" diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index e3e7a5281a..7943a4dadf 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -39,7 +39,7 @@ #include "nvim/highlight_group.h" #include "nvim/if_cscope.h" #include "nvim/indent.h" -#include "nvim/keymap.h" +#include "nvim/keycodes.h" #include "nvim/lib/kvec.h" #include "nvim/log.h" #include "nvim/lua/executor.h" diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c index 1235087500..0d95d7cf28 100644 --- a/src/nvim/ex_session.c +++ b/src/nvim/ex_session.c @@ -27,7 +27,7 @@ #include "nvim/fold.h" #include "nvim/getchar.h" #include "nvim/globals.h" -#include "nvim/keymap.h" +#include "nvim/keycodes.h" #include "nvim/move.h" #include "nvim/option.h" #include "nvim/os/input.h" diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index c50d258b83..f05eeb2fb8 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -31,7 +31,7 @@ #include "nvim/garray.h" #include "nvim/getchar.h" #include "nvim/input.h" -#include "nvim/keymap.h" +#include "nvim/keycodes.h" #include "nvim/lua/executor.h" #include "nvim/main.h" #include "nvim/mbyte.h" diff --git a/src/nvim/keycodes.c b/src/nvim/keycodes.c new file mode 100644 index 0000000000..676ddcf8d4 --- /dev/null +++ b/src/nvim/keycodes.c @@ -0,0 +1,1018 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +#include +#include +#include + +#include "nvim/ascii.h" +#include "nvim/charset.h" +#include "nvim/edit.h" +#include "nvim/eval.h" +#include "nvim/keycodes.h" +#include "nvim/memory.h" +#include "nvim/message.h" +#include "nvim/mouse.h" +#include "nvim/strings.h" +#include "nvim/vim.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "keycodes.c.generated.h" +#endif + +// Some useful tables. + +static const struct modmasktable { + uint16_t mod_mask; ///< Bit-mask for particular key modifier. + uint16_t mod_flag; ///< Bit(s) for particular key modifier. + char_u name; ///< Single letter name of modifier. +} mod_mask_table[] = { + { MOD_MASK_ALT, MOD_MASK_ALT, (char_u)'M' }, + { MOD_MASK_META, MOD_MASK_META, (char_u)'T' }, + { MOD_MASK_CTRL, MOD_MASK_CTRL, (char_u)'C' }, + { MOD_MASK_SHIFT, MOD_MASK_SHIFT, (char_u)'S' }, + { MOD_MASK_MULTI_CLICK, MOD_MASK_2CLICK, (char_u)'2' }, + { MOD_MASK_MULTI_CLICK, MOD_MASK_3CLICK, (char_u)'3' }, + { MOD_MASK_MULTI_CLICK, MOD_MASK_4CLICK, (char_u)'4' }, + { MOD_MASK_CMD, MOD_MASK_CMD, (char_u)'D' }, + // 'A' must be the last one + { MOD_MASK_ALT, MOD_MASK_ALT, (char_u)'A' }, + { 0, 0, NUL } + // NOTE: when adding an entry, update MAX_KEY_NAME_LEN! +}; + +// Shifted key terminal codes and their unshifted equivalent. +// Don't add mouse codes here, they are handled separately! + +#define MOD_KEYS_ENTRY_SIZE 5 + +static char_u modifier_keys_table[] = +{ + // mod mask with modifier without modifier + MOD_MASK_SHIFT, '&', '9', '@', '1', // begin + MOD_MASK_SHIFT, '&', '0', '@', '2', // cancel + MOD_MASK_SHIFT, '*', '1', '@', '4', // command + MOD_MASK_SHIFT, '*', '2', '@', '5', // copy + MOD_MASK_SHIFT, '*', '3', '@', '6', // create + MOD_MASK_SHIFT, '*', '4', 'k', 'D', // delete char + MOD_MASK_SHIFT, '*', '5', 'k', 'L', // delete line + MOD_MASK_SHIFT, '*', '7', '@', '7', // end + MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_END, '@', '7', // end + MOD_MASK_SHIFT, '*', '9', '@', '9', // exit + MOD_MASK_SHIFT, '*', '0', '@', '0', // find + MOD_MASK_SHIFT, '#', '1', '%', '1', // help + MOD_MASK_SHIFT, '#', '2', 'k', 'h', // home + MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_HOME, 'k', 'h', // home + MOD_MASK_SHIFT, '#', '3', 'k', 'I', // insert + MOD_MASK_SHIFT, '#', '4', 'k', 'l', // left arrow + MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_LEFT, 'k', 'l', // left arrow + MOD_MASK_SHIFT, '%', 'a', '%', '3', // message + MOD_MASK_SHIFT, '%', 'b', '%', '4', // move + MOD_MASK_SHIFT, '%', 'c', '%', '5', // next + MOD_MASK_SHIFT, '%', 'd', '%', '7', // options + MOD_MASK_SHIFT, '%', 'e', '%', '8', // previous + MOD_MASK_SHIFT, '%', 'f', '%', '9', // print + MOD_MASK_SHIFT, '%', 'g', '%', '0', // redo + MOD_MASK_SHIFT, '%', 'h', '&', '3', // replace + MOD_MASK_SHIFT, '%', 'i', 'k', 'r', // right arr. + MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_RIGHT, 'k', 'r', // right arr. + MOD_MASK_SHIFT, '%', 'j', '&', '5', // resume + MOD_MASK_SHIFT, '!', '1', '&', '6', // save + MOD_MASK_SHIFT, '!', '2', '&', '7', // suspend + MOD_MASK_SHIFT, '!', '3', '&', '8', // undo + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_UP, 'k', 'u', // up arrow + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_DOWN, 'k', 'd', // down arrow + + // vt100 F1 + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF1, KS_EXTRA, (int)KE_XF1, + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF2, KS_EXTRA, (int)KE_XF2, + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF3, KS_EXTRA, (int)KE_XF3, + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF4, KS_EXTRA, (int)KE_XF4, + + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F1, 'k', '1', // F1 + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F2, 'k', '2', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F3, 'k', '3', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F4, 'k', '4', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F5, 'k', '5', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F6, 'k', '6', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F7, 'k', '7', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F8, 'k', '8', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F9, 'k', '9', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F10, 'k', ';', // F10 + + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F11, 'F', '1', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F12, 'F', '2', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F13, 'F', '3', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F14, 'F', '4', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F15, 'F', '5', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F16, 'F', '6', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F17, 'F', '7', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F18, 'F', '8', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F19, 'F', '9', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F20, 'F', 'A', + + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F21, 'F', 'B', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F22, 'F', 'C', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F23, 'F', 'D', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F24, 'F', 'E', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F25, 'F', 'F', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F26, 'F', 'G', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F27, 'F', 'H', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F28, 'F', 'I', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F29, 'F', 'J', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F30, 'F', 'K', + + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F31, 'F', 'L', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F32, 'F', 'M', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F33, 'F', 'N', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F34, 'F', 'O', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F35, 'F', 'P', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F36, 'F', 'Q', + MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F37, 'F', 'R', + + // TAB pseudo code + MOD_MASK_SHIFT, 'k', 'B', KS_EXTRA, (int)KE_TAB, + + NUL +}; + +static const struct key_name_entry { + int key; // Special key code or ascii value + const char *name; // Name of key +} key_names_table[] = { + { ' ', "Space" }, + { TAB, "Tab" }, + { K_TAB, "Tab" }, + { NL, "NL" }, + { NL, "NewLine" }, // Alternative name + { NL, "LineFeed" }, // Alternative name + { NL, "LF" }, // Alternative name + { CAR, "CR" }, + { CAR, "Return" }, // Alternative name + { CAR, "Enter" }, // Alternative name + { K_BS, "BS" }, + { K_BS, "BackSpace" }, // Alternative name + { ESC, "Esc" }, + { ESC, "Escape" }, // Alternative name + { CSI, "CSI" }, + { '|', "Bar" }, + { '\\', "Bslash" }, + { K_DEL, "Del" }, + { K_DEL, "Delete" }, // Alternative name + { K_KDEL, "kDel" }, + { K_KDEL, "KPPeriod" }, // libtermkey name + { K_UP, "Up" }, + { K_DOWN, "Down" }, + { K_LEFT, "Left" }, + { K_RIGHT, "Right" }, + { K_XUP, "xUp" }, + { K_XDOWN, "xDown" }, + { K_XLEFT, "xLeft" }, + { K_XRIGHT, "xRight" }, + { K_KUP, "kUp" }, + { K_KUP, "KP8" }, + { K_KDOWN, "kDown" }, + { K_KDOWN, "KP2" }, + { K_KLEFT, "kLeft" }, + { K_KLEFT, "KP4" }, + { K_KRIGHT, "kRight" }, + { K_KRIGHT, "KP6" }, + + { K_F1, "F1" }, + { K_F2, "F2" }, + { K_F3, "F3" }, + { K_F4, "F4" }, + { K_F5, "F5" }, + { K_F6, "F6" }, + { K_F7, "F7" }, + { K_F8, "F8" }, + { K_F9, "F9" }, + { K_F10, "F10" }, + + { K_F11, "F11" }, + { K_F12, "F12" }, + { K_F13, "F13" }, + { K_F14, "F14" }, + { K_F15, "F15" }, + { K_F16, "F16" }, + { K_F17, "F17" }, + { K_F18, "F18" }, + { K_F19, "F19" }, + { K_F20, "F20" }, + + { K_F21, "F21" }, + { K_F22, "F22" }, + { K_F23, "F23" }, + { K_F24, "F24" }, + { K_F25, "F25" }, + { K_F26, "F26" }, + { K_F27, "F27" }, + { K_F28, "F28" }, + { K_F29, "F29" }, + { K_F30, "F30" }, + + { K_F31, "F31" }, + { K_F32, "F32" }, + { K_F33, "F33" }, + { K_F34, "F34" }, + { K_F35, "F35" }, + { K_F36, "F36" }, + { K_F37, "F37" }, + { K_F38, "F38" }, + { K_F39, "F39" }, + { K_F40, "F40" }, + + { K_F41, "F41" }, + { K_F42, "F42" }, + { K_F43, "F43" }, + { K_F44, "F44" }, + { K_F45, "F45" }, + { K_F46, "F46" }, + { K_F47, "F47" }, + { K_F48, "F48" }, + { K_F49, "F49" }, + { K_F50, "F50" }, + + { K_F51, "F51" }, + { K_F52, "F52" }, + { K_F53, "F53" }, + { K_F54, "F54" }, + { K_F55, "F55" }, + { K_F56, "F56" }, + { K_F57, "F57" }, + { K_F58, "F58" }, + { K_F59, "F59" }, + { K_F60, "F60" }, + + { K_F61, "F61" }, + { K_F62, "F62" }, + { K_F63, "F63" }, + + { K_XF1, "xF1" }, + { K_XF2, "xF2" }, + { K_XF3, "xF3" }, + { K_XF4, "xF4" }, + + { K_HELP, "Help" }, + { K_UNDO, "Undo" }, + { K_INS, "Insert" }, + { K_INS, "Ins" }, // Alternative name + { K_KINS, "kInsert" }, + { K_KINS, "KP0" }, + { K_HOME, "Home" }, + { K_KHOME, "kHome" }, + { K_KHOME, "KP7" }, + { K_XHOME, "xHome" }, + { K_ZHOME, "zHome" }, + { K_END, "End" }, + { K_KEND, "kEnd" }, + { K_KEND, "KP1" }, + { K_XEND, "xEnd" }, + { K_ZEND, "zEnd" }, + { K_PAGEUP, "PageUp" }, + { K_PAGEDOWN, "PageDown" }, + { K_KPAGEUP, "kPageUp" }, + { K_KPAGEUP, "KP9" }, + { K_KPAGEDOWN, "kPageDown" }, + { K_KPAGEDOWN, "KP3" }, + { K_KORIGIN, "kOrigin" }, + { K_KORIGIN, "KP5" }, + + { K_KPLUS, "kPlus" }, + { K_KPLUS, "KPPlus" }, + { K_KMINUS, "kMinus" }, + { K_KMINUS, "KPMinus" }, + { K_KDIVIDE, "kDivide" }, + { K_KDIVIDE, "KPDiv" }, + { K_KMULTIPLY, "kMultiply" }, + { K_KMULTIPLY, "KPMult" }, + { K_KENTER, "kEnter" }, + { K_KENTER, "KPEnter" }, + { K_KPOINT, "kPoint" }, + { K_KCOMMA, "kComma" }, + { K_KCOMMA, "KPComma" }, + { K_KEQUAL, "kEqual" }, + { K_KEQUAL, "KPEquals" }, + + { K_K0, "k0" }, + { K_K1, "k1" }, + { K_K2, "k2" }, + { K_K3, "k3" }, + { K_K4, "k4" }, + { K_K5, "k5" }, + { K_K6, "k6" }, + { K_K7, "k7" }, + { K_K8, "k8" }, + { K_K9, "k9" }, + + { '<', "lt" }, + + { K_MOUSE, "Mouse" }, + { K_LEFTMOUSE, "LeftMouse" }, + { K_LEFTMOUSE_NM, "LeftMouseNM" }, + { K_LEFTDRAG, "LeftDrag" }, + { K_LEFTRELEASE, "LeftRelease" }, + { K_LEFTRELEASE_NM, "LeftReleaseNM" }, + { K_MOUSEMOVE, "MouseMove" }, + { K_MIDDLEMOUSE, "MiddleMouse" }, + { K_MIDDLEDRAG, "MiddleDrag" }, + { K_MIDDLERELEASE, "MiddleRelease" }, + { K_RIGHTMOUSE, "RightMouse" }, + { K_RIGHTDRAG, "RightDrag" }, + { K_RIGHTRELEASE, "RightRelease" }, + { K_MOUSEDOWN, "ScrollWheelUp" }, + { K_MOUSEUP, "ScrollWheelDown" }, + { K_MOUSELEFT, "ScrollWheelRight" }, + { K_MOUSERIGHT, "ScrollWheelLeft" }, + { K_MOUSEDOWN, "MouseDown" }, // OBSOLETE: Use + { K_MOUSEUP, "MouseUp" }, // ScrollWheelXXX instead + { K_X1MOUSE, "X1Mouse" }, + { K_X1DRAG, "X1Drag" }, + { K_X1RELEASE, "X1Release" }, + { K_X2MOUSE, "X2Mouse" }, + { K_X2DRAG, "X2Drag" }, + { K_X2RELEASE, "X2Release" }, + { K_DROP, "Drop" }, + { K_ZERO, "Nul" }, + { K_SNR, "SNR" }, + { K_PLUG, "Plug" }, + { K_IGNORE, "Ignore" }, + { K_COMMAND, "Cmd" }, + { 0, NULL } + // NOTE: When adding a long name update MAX_KEY_NAME_LEN. +}; + +static struct mousetable { + int pseudo_code; // Code for pseudo mouse event + int button; // Which mouse button is it? + bool is_click; // Is it a mouse button click event? + bool is_drag; // Is it a mouse drag event? +} mouse_table[] = +{ + { (int)KE_LEFTMOUSE, MOUSE_LEFT, true, false }, + { (int)KE_LEFTDRAG, MOUSE_LEFT, false, true }, + { (int)KE_LEFTRELEASE, MOUSE_LEFT, false, false }, + { (int)KE_MIDDLEMOUSE, MOUSE_MIDDLE, true, false }, + { (int)KE_MIDDLEDRAG, MOUSE_MIDDLE, false, true }, + { (int)KE_MIDDLERELEASE, MOUSE_MIDDLE, false, false }, + { (int)KE_RIGHTMOUSE, MOUSE_RIGHT, true, false }, + { (int)KE_RIGHTDRAG, MOUSE_RIGHT, false, true }, + { (int)KE_RIGHTRELEASE, MOUSE_RIGHT, false, false }, + { (int)KE_X1MOUSE, MOUSE_X1, true, false }, + { (int)KE_X1DRAG, MOUSE_X1, false, true }, + { (int)KE_X1RELEASE, MOUSE_X1, false, false }, + { (int)KE_X2MOUSE, MOUSE_X2, true, false }, + { (int)KE_X2DRAG, MOUSE_X2, false, true }, + { (int)KE_X2RELEASE, MOUSE_X2, false, false }, + // DRAG without CLICK + { (int)K_MOUSEMOVE, MOUSE_RELEASE, false, true }, + // RELEASE without CLICK + { (int)KE_IGNORE, MOUSE_RELEASE, false, false }, + { 0, 0, 0, 0 }, +}; + +/// Return the modifier mask bit (#MOD_MASK_*) corresponding to mod name +/// +/// E.g. 'S' for shift, 'C' for ctrl. +int name_to_mod_mask(int c) + FUNC_ATTR_CONST FUNC_ATTR_WARN_UNUSED_RESULT +{ + c = TOUPPER_ASC(c); + for (size_t i = 0; mod_mask_table[i].mod_mask != 0; i++) { + if (c == mod_mask_table[i].name) { + return mod_mask_table[i].mod_flag; + } + } + return 0; +} + +/// Check if there is a special key code for "key" with specified modifiers +/// +/// @param[in] key Initial key code. +/// @param[in,out] modifiers Initial modifiers, is adjusted to have simplified +/// modifiers. +/// +/// @return Simplified key code. +int simplify_key(const int key, int *modifiers) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL +{ + if (*modifiers & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT)) { + // TAB is a special case. + if (key == TAB && (*modifiers & MOD_MASK_SHIFT)) { + *modifiers &= ~MOD_MASK_SHIFT; + return K_S_TAB; + } + const int key0 = KEY2TERMCAP0(key); + const int key1 = KEY2TERMCAP1(key); + for (int i = 0; modifier_keys_table[i] != NUL; i += MOD_KEYS_ENTRY_SIZE) { + if (key0 == modifier_keys_table[i + 3] + && key1 == modifier_keys_table[i + 4] + && (*modifiers & modifier_keys_table[i])) { + *modifiers &= ~modifier_keys_table[i]; + return TERMCAP2KEY(modifier_keys_table[i + 1], + modifier_keys_table[i + 2]); + } + } + } + return key; +} + +/// Change to +int handle_x_keys(const int key) + FUNC_ATTR_CONST FUNC_ATTR_WARN_UNUSED_RESULT +{ + switch (key) { + case K_XUP: + return K_UP; + case K_XDOWN: + return K_DOWN; + case K_XLEFT: + return K_LEFT; + case K_XRIGHT: + return K_RIGHT; + case K_XHOME: + return K_HOME; + case K_ZHOME: + return K_HOME; + case K_XEND: + return K_END; + case K_ZEND: + return K_END; + case K_XF1: + return K_F1; + case K_XF2: + return K_F2; + case K_XF3: + return K_F3; + case K_XF4: + return K_F4; + case K_S_XF1: + return K_S_F1; + case K_S_XF2: + return K_S_F2; + case K_S_XF3: + return K_S_F3; + case K_S_XF4: + return K_S_F4; + } + return key; +} + +/// @return a string which contains the name of the given key when the given modifiers are down. +char_u *get_special_key_name(int c, int modifiers) +{ + static char_u string[MAX_KEY_NAME_LEN + 1]; + + int i, idx; + int table_idx; + char_u *s; + + string[0] = '<'; + idx = 1; + + // Key that stands for a normal character. + if (IS_SPECIAL(c) && KEY2TERMCAP0(c) == KS_KEY) { + c = KEY2TERMCAP1(c); + } + + // Translate shifted special keys into unshifted keys and set modifier. + // Same for CTRL and ALT modifiers. + if (IS_SPECIAL(c)) { + for (i = 0; modifier_keys_table[i] != 0; i += MOD_KEYS_ENTRY_SIZE) { + if (KEY2TERMCAP0(c) == (int)modifier_keys_table[i + 1] + && (int)KEY2TERMCAP1(c) == (int)modifier_keys_table[i + 2]) { + modifiers |= modifier_keys_table[i]; + c = TERMCAP2KEY(modifier_keys_table[i + 3], + modifier_keys_table[i + 4]); + break; + } + } + } + + // try to find the key in the special key table + table_idx = find_special_key_in_table(c); + + // When not a known special key, and not a printable character, try to + // extract modifiers. + if (c > 0 + && utf_char2len(c) == 1) { + if (table_idx < 0 + && (!vim_isprintc(c) || (c & 0x7f) == ' ') + && (c & 0x80)) { + c &= 0x7f; + modifiers |= MOD_MASK_ALT; + // try again, to find the un-alted key in the special key table + table_idx = find_special_key_in_table(c); + } + if (table_idx < 0 && !vim_isprintc(c) && c < ' ') { + c += '@'; + modifiers |= MOD_MASK_CTRL; + } + } + + // translate the modifier into a string + for (i = 0; mod_mask_table[i].name != 'A'; i++) { + if ((modifiers & mod_mask_table[i].mod_mask) + == mod_mask_table[i].mod_flag) { + string[idx++] = mod_mask_table[i].name; + string[idx++] = (char_u)'-'; + } + } + + if (table_idx < 0) { // unknown special key, may output t_xx + if (IS_SPECIAL(c)) { + string[idx++] = 't'; + string[idx++] = '_'; + string[idx++] = (char_u)KEY2TERMCAP0(c); + string[idx++] = KEY2TERMCAP1(c); + } else { + // Not a special key, only modifiers, output directly. + if (utf_char2len(c) > 1) { + idx += utf_char2bytes(c, (char *)string + idx); + } else if (vim_isprintc(c)) { + string[idx++] = (char_u)c; + } else { + s = transchar(c); + while (*s) { + string[idx++] = *s++; + } + } + } + } else { // use name of special key + size_t len = STRLEN(key_names_table[table_idx].name); + + if ((int)len + idx + 2 <= MAX_KEY_NAME_LEN) { + STRCPY(string + idx, key_names_table[table_idx].name); + idx += (int)len; + } + } + string[idx++] = '>'; + string[idx] = NUL; + return string; +} + +/// Try translating a <> name ("keycode"). +/// +/// @param[in,out] srcp Source from which <> are translated. Is advanced to +/// after the <> name if there is a match. +/// @param[in] src_len Length of the srcp. +/// @param[out] dst Location where translation result will be kept. It must +// be at least 19 bytes per "" form. +/// @param[in] flags FSK_ values +/// @param[in] escape_ks escape K_SPECIAL bytes in the character +/// @param[out] did_simplify found , etc. +/// +/// @return Number of characters added to dst, zero for no match. +unsigned int trans_special(const char_u **const srcp, const size_t src_len, char_u *const dst, + const int flags, const bool escape_ks, bool *const did_simplify) + FUNC_ATTR_NONNULL_ARG(1, 3) FUNC_ATTR_WARN_UNUSED_RESULT +{ + int modifiers = 0; + int key = find_special_key(srcp, src_len, &modifiers, flags, did_simplify); + if (key == 0) { + return 0; + } + + return special_to_buf(key, modifiers, escape_ks, dst); +} + +/// Put the character sequence for "key" with "modifiers" into "dst" and return +/// the resulting length. +/// When "escape_ks" is true escape K_SPECIAL bytes in the character. +/// The sequence is not NUL terminated. +/// This is how characters in a string are encoded. +unsigned int special_to_buf(int key, int modifiers, bool escape_ks, char_u *dst) +{ + unsigned int dlen = 0; + + // Put the appropriate modifier in a string. + if (modifiers != 0) { + dst[dlen++] = K_SPECIAL; + dst[dlen++] = KS_MODIFIER; + dst[dlen++] = (char_u)modifiers; + } + + if (IS_SPECIAL(key)) { + dst[dlen++] = K_SPECIAL; + dst[dlen++] = (char_u)KEY2TERMCAP0(key); + dst[dlen++] = KEY2TERMCAP1(key); + } else if (escape_ks) { + char_u *after = add_char2buf(key, dst + dlen); + assert(after >= dst && (uintmax_t)(after - dst) <= UINT_MAX); + dlen = (unsigned int)(after - dst); + } else { + dlen += (unsigned int)utf_char2bytes(key, (char *)dst + dlen); + } + + return dlen; +} + +/// Try translating a <> name +/// +/// @param[in,out] srcp Translated <> name. Is advanced to after the <> name. +/// @param[in] src_len srcp length. +/// @param[out] modp Location where information about modifiers is saved. +/// @param[in] flags FSK_ values +/// @param[out] did_simplify FSK_SIMPLIFY and found , etc. +/// +/// @return Key and modifiers or 0 if there is no match. +int find_special_key(const char_u **const srcp, const size_t src_len, int *const modp, + const int flags, bool *const did_simplify) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1, 3) +{ + const char_u *last_dash; + const char_u *end_of_name; + const char_u *src; + const char_u *bp; + const char_u *const end = *srcp + src_len - 1; + const bool in_string = flags & FSK_IN_STRING; + int modifiers; + int bit; + int key; + uvarnumber_T n; + int l; + + if (src_len == 0) { + return 0; + } + + src = *srcp; + if (src[0] != '<') { + return 0; + } + if (src[1] == '*') { // <*xxx>: do not simplify + src++; + } + + // Find end of modifier list + last_dash = src; + for (bp = src + 1; bp <= end && (*bp == '-' || ascii_isident(*bp)); bp++) { + if (*bp == '-') { + last_dash = bp; + if (bp + 1 <= end) { + l = utfc_ptr2len_len(bp + 1, (int)(end - bp) + 1); + // Anything accepted, like . + // or are not special in strings as " is + // the string delimiter. With a backslash it works: + if (end - bp > l && !(in_string && bp[1] == '"') && bp[l + 1] == '>') { + bp += l; + } else if (end - bp > 2 && in_string && bp[1] == '\\' + && bp[2] == '"' && bp[3] == '>') { + bp += 2; + } + } + } + if (end - bp > 3 && bp[0] == 't' && bp[1] == '_') { + bp += 3; // skip t_xx, xx may be '-' or '>' + } else if (end - bp > 4 && STRNICMP(bp, "char-", 5) == 0) { + vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, true); + if (l == 0) { + emsg(_(e_invarg)); + return 0; + } + bp += l + 5; + break; + } + } + + if (bp <= end && *bp == '>') { // found matching '>' + end_of_name = bp + 1; + + // Which modifiers are given? + modifiers = 0x0; + for (bp = src + 1; bp < last_dash; bp++) { + if (*bp != '-') { + bit = name_to_mod_mask(*bp); + if (bit == 0x0) { + break; // Illegal modifier name + } + modifiers |= bit; + } + } + + // Legal modifier name. + if (bp >= last_dash) { + if (STRNICMP(last_dash + 1, "char-", 5) == 0 + && ascii_isdigit(last_dash[6])) { + // or or + vim_str2nr(last_dash + 6, NULL, &l, STR2NR_ALL, NULL, &n, 0, true); + if (l == 0) { + emsg(_(e_invarg)); + return 0; + } + key = (int)n; + } else { + int off = 1; + + // Modifier with single letter, or special key name. + if (in_string && last_dash[1] == '\\' && last_dash[2] == '"') { + // Special case for a double-quoted string + off = l = 2; + } else { + l = utfc_ptr2len((char *)last_dash + 1); + } + if (modifiers != 0 && last_dash[l + 1] == '>') { + key = utf_ptr2char((char *)last_dash + off); + } else { + key = get_special_key_code(last_dash + off); + if (!(flags & FSK_KEEP_X_KEY)) { + key = handle_x_keys(key); + } + } + } + + // get_special_key_code() may return NUL for invalid + // special key name. + if (key != NUL) { + // Only use a modifier when there is no special key code that + // includes the modifier. + key = simplify_key(key, &modifiers); + + if (!(flags & FSK_KEYCODE)) { + // don't want keycode, use single byte code + if (key == K_BS) { + key = BS; + } else if (key == K_DEL || key == K_KDEL) { + key = DEL; + } + } + + // Normal Key with modifier: + // Try to make a single byte code (except for Alt/Meta modifiers). + if (!IS_SPECIAL(key)) { + key = extract_modifiers(key, &modifiers, flags & FSK_SIMPLIFY, did_simplify); + } + + *modp = modifiers; + *srcp = end_of_name; + return key; + } // else { ELOG("unknown key: '%s'", src); } + } + } + return 0; +} + +/// Try to include modifiers (except alt/meta) in the key. +/// Changes "Shift-a" to 'A', "Ctrl-@" to , etc. +/// @param[in] simplify if false, don't do Ctrl +/// @param[out] did_simplify set when it is not NULL and "simplify" is true and +/// Ctrl is removed from modifiers +static int extract_modifiers(int key, int *modp, const bool simplify, bool *const did_simplify) +{ + int modifiers = *modp; + + // Command-key and ctrl are special + if (!(modifiers & MOD_MASK_CMD) && !(modifiers & MOD_MASK_CTRL)) { + if ((modifiers & MOD_MASK_SHIFT) && ASCII_ISALPHA(key)) { + key = TOUPPER_ASC(key); + modifiers &= ~MOD_MASK_SHIFT; + } + } + // and mean the same thing, always use "H" + if ((modifiers & MOD_MASK_CTRL) && ASCII_ISALPHA(key)) { + key = TOUPPER_ASC(key); + } + if (simplify && (modifiers & MOD_MASK_CTRL) + && ((key >= '?' && key <= '_') || ASCII_ISALPHA(key))) { + key = CTRL_CHR(key); + modifiers &= ~MOD_MASK_CTRL; + if (key == NUL) { // is + key = K_ZERO; + } + if (did_simplify != NULL) { + *did_simplify = true; + } + } + + *modp = modifiers; + return key; +} + +/// Try to find key "c" in the special key table. +/// @return the index when found, -1 when not found. +int find_special_key_in_table(int c) +{ + int i; + + for (i = 0; key_names_table[i].name != NULL; i++) { + if (c == key_names_table[i].key) { + break; + } + } + if (key_names_table[i].name == NULL) { + i = -1; + } + return i; +} + +/// Find the special key with the given name +/// +/// @param[in] name Name of the special. Does not have to end with NUL, it is +/// assumed to end before the first non-idchar. If name starts +/// with "t_" the next two characters are interpreted as +/// a termcap name. +/// +/// @return Key code or 0 if not found. +int get_special_key_code(const char_u *name) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + for (int i = 0; key_names_table[i].name != NULL; i++) { + const char *const table_name = key_names_table[i].name; + int j; + for (j = 0; ascii_isident(name[j]) && table_name[j] != NUL; j++) { + if (TOLOWER_ASC(table_name[j]) != TOLOWER_ASC(name[j])) { + break; + } + } + if (!ascii_isident(name[j]) && table_name[j] == NUL) { + return key_names_table[i].key; + } + } + + return 0; +} + +/// Look up the given mouse code to return the relevant information in the other arguments. +/// @return which button is down or was released. +int get_mouse_button(int code, bool *is_click, bool *is_drag) +{ + int i; + + for (i = 0; mouse_table[i].pseudo_code; i++) { + if (code == mouse_table[i].pseudo_code) { + *is_click = mouse_table[i].is_click; + *is_drag = mouse_table[i].is_drag; + return mouse_table[i].button; + } + } + return 0; // Shouldn't get here +} + +/// Replace any terminal code strings with the equivalent internal representation. +/// +/// Used for the "from" and "to" part of a mapping, and the "to" part of a menu command. +/// Any strings like "" are also replaced, unless `special` is false. +/// K_SPECIAL by itself is replaced by K_SPECIAL KS_SPECIAL KE_FILLER. +/// +/// When "flags" has REPTERM_FROM_PART, trailing is included, otherwise it is removed (to make +/// ":map xx ^V" map xx to nothing). When cpo_flags contains FLAG_CPO_BSLASH, a backslash can be +/// used in place of . All other characters are removed. +/// +/// @param[in] from What characters to replace. +/// @param[in] from_len Length of the "from" argument. +/// @param[out] bufp Location where results were saved in case of success (allocated). +/// Will be set to NULL in case of failure. +/// @param[in] flags REPTERM_FROM_PART see above +/// REPTERM_DO_LT also translate +/// REPTERM_NO_SPECIAL do not accept notation +/// REPTERM_NO_SIMPLIFY do not simplify into 0x08, etc. +/// @param[out] did_simplify set when some code was simplied, unless it is NULL. +/// @param[in] cpo_flags Relevant flags derived from p_cpo, see CPO_TO_CPO_FLAGS. +/// +/// @return Pointer to an allocated memory, which is also saved to "bufp". +char *replace_termcodes(const char *const from, const size_t from_len, char **const bufp, + const int flags, bool *const did_simplify, const int cpo_flags) + FUNC_ATTR_NONNULL_ARG(1, 3) +{ + ssize_t i; + size_t slen; + char_u key; + size_t dlen = 0; + const char_u *src; + const char_u *const end = (char_u *)from + from_len - 1; + char_u *result; // buffer for resulting string + + const bool do_backslash = !(cpo_flags & FLAG_CPO_BSLASH); // backslash is a special character + const bool do_special = !(flags & REPTERM_NO_SPECIAL); + + // Allocate space for the translation. Worst case a single character is + // replaced by 6 bytes (shifted special key), plus a NUL at the end. + const size_t buf_len = from_len * 6 + 1; + result = xmalloc(buf_len); + + src = (char_u *)from; + + // Check for #n at start only: function key n + if ((flags & REPTERM_FROM_PART) && from_len > 1 && src[0] == '#' + && ascii_isdigit(src[1])) { // function key + result[dlen++] = K_SPECIAL; + result[dlen++] = 'k'; + if (src[1] == '0') { + result[dlen++] = ';'; // #0 is F10 is "k;" + } else { + result[dlen++] = src[1]; // #3 is F3 is "k3" + } + src += 2; + } + + // Copy each byte from *from to result[dlen] + while (src <= end) { + // Check for special <> keycodes, like "" + if (do_special && ((flags & REPTERM_DO_LT) || ((end - src) >= 3 + && STRNCMP(src, "", 4) != 0))) { + // Replace by K_SNR _. + // (room: 5 * 6 = 30 bytes; needed: 3 + + 1 <= 14) + if (end - src >= 4 && STRNICMP(src, "", 5) == 0) { + if (current_sctx.sc_sid <= 0) { + emsg(_(e_usingsid)); + } else { + src += 5; + result[dlen++] = K_SPECIAL; + result[dlen++] = (int)KS_EXTRA; + result[dlen++] = (int)KE_SNR; + snprintf((char *)result + dlen, buf_len - dlen, "%" PRId64, + (int64_t)current_sctx.sc_sid); + dlen += STRLEN(result + dlen); + result[dlen++] = '_'; + continue; + } + } + + slen = trans_special(&src, (size_t)(end - src) + 1, result + dlen, + FSK_KEYCODE | ((flags & REPTERM_NO_SIMPLIFY) ? 0 : FSK_SIMPLIFY), + true, did_simplify); + if (slen) { + dlen += slen; + continue; + } + } + + if (do_special) { + char_u *p, *s, len; + + // Replace by the value of "mapleader". + // Replace by the value of "maplocalleader". + // If "mapleader" or "maplocalleader" isn't set use a backslash. + if (end - src >= 7 && STRNICMP(src, "", 8) == 0) { + len = 8; + p = get_var_value("g:mapleader"); + } else if (end - src >= 12 && STRNICMP(src, "", 13) == 0) { + len = 13; + p = get_var_value("g:maplocalleader"); + } else { + len = 0; + p = NULL; + } + + if (len != 0) { + // Allow up to 8 * 6 characters for "mapleader". + if (p == NULL || *p == NUL || STRLEN(p) > 8 * 6) { + s = (char_u *)"\\"; + } else { + s = p; + } + while (*s != NUL) { + result[dlen++] = *s++; + } + src += len; + continue; + } + } + + // Remove CTRL-V and ignore the next character. + // For "from" side the CTRL-V at the end is included, for the "to" + // part it is removed. + // If 'cpoptions' does not contain 'B', also accept a backslash. + key = *src; + if (key == Ctrl_V || (do_backslash && key == '\\')) { + src++; // skip CTRL-V or backslash + if (src > end) { + if (flags & REPTERM_FROM_PART) { + result[dlen++] = key; + } + break; + } + } + + // skip multibyte char correctly + for (i = utfc_ptr2len_len(src, (int)(end - src) + 1); i > 0; i--) { + // If the character is K_SPECIAL, replace it with K_SPECIAL + // KS_SPECIAL KE_FILLER. + if (*src == K_SPECIAL) { + result[dlen++] = K_SPECIAL; + result[dlen++] = KS_SPECIAL; + result[dlen++] = KE_FILLER; + } else { + result[dlen++] = *src; + } + src++; + } + } + result[dlen] = NUL; + + *bufp = xrealloc(result, dlen + 1); + + return *bufp; +} + +/// Logs a single key as a human-readable keycode. +void log_key(int log_level, int key) +{ + if (log_level < MIN_LOG_LEVEL) { + return; + } + char *keyname = key == K_EVENT + ? "K_EVENT" + : (char *)get_special_key_name(key, mod_mask); + LOG(log_level, "input: %s", keyname); +} diff --git a/src/nvim/keycodes.h b/src/nvim/keycodes.h new file mode 100644 index 0000000000..631a9f68d3 --- /dev/null +++ b/src/nvim/keycodes.h @@ -0,0 +1,499 @@ +#ifndef NVIM_KEYCODES_H +#define NVIM_KEYCODES_H + +#include "nvim/strings.h" + +// Keycode definitions for special keys. +// +// Any special key code sequences are replaced by these codes. + +// +// For MS-DOS some keys produce codes larger than 0xff. They are split into two +// chars, the first one is K_NUL. +// +#define K_NUL (0xce) // for MS-DOS: special key follows + +/// K_SPECIAL is the first byte of a special key code and is always followed by +/// two bytes. +/// The second byte can have any value. ASCII is used for normal termcap +/// entries, 0x80 and higher for special keys, see below. +/// The third byte is guaranteed to be between 0x02 and 0x7f. +#define K_SPECIAL (0x80) + +/// Positive characters are "normal" characters. +/// Negative characters are special key codes. Only characters below -0x200 +/// are used to so that the absolute value can't be mistaken for a single-byte +/// character. +#define IS_SPECIAL(c) ((c) < 0) + +/// Characters 0x0100 - 0x01ff have a special meaning for abbreviations. +/// Multi-byte characters also have ABBR_OFF added, thus are above 0x0200. +#define ABBR_OFF 0x100 + +/// NUL cannot be in the input string, therefore it is replaced by +/// K_SPECIAL KS_ZERO KE_FILLER +#define KS_ZERO 255 + +/// K_SPECIAL cannot be in the input string, therefore it is replaced by +/// K_SPECIAL KS_SPECIAL KE_FILLER +#define KS_SPECIAL 254 + +/// KS_EXTRA is used for keys that have no termcap name +/// K_SPECIAL KS_EXTRA KE_xxx +#define KS_EXTRA 253 + +/// KS_MODIFIER is used when a modifier is given for a (special) key +/// K_SPECIAL KS_MODIFIER bitmask +#define KS_MODIFIER 252 + +// These are used for the GUI +// K_SPECIAL KS_xxx KE_FILLER + +#define KS_MOUSE 251 +#define KS_MENU 250 +#define KS_VER_SCROLLBAR 249 +#define KS_HOR_SCROLLBAR 248 + +// Used for switching Select mode back on after a mapping or menu. + +#define KS_SELECT 245 +#define K_SELECT_STRING (char_u *)"\200\365X" + +// Used a termcap entry that produces a normal character. +#define KS_KEY 242 + +// Used for click in a tab pages label. +#define KS_TABLINE 240 + +// Used for menu in a tab pages line. +#define KS_TABMENU 239 + +/// Filler used after KS_SPECIAL and others +#define KE_FILLER ('X') + +// translation of three byte code "K_SPECIAL a b" into int "K_xxx" and back + +#define TERMCAP2KEY(a, b) (-((a) + ((int)(b) << 8))) +#define KEY2TERMCAP0(x) ((-(x)) & 0xff) +#define KEY2TERMCAP1(x) (((unsigned)(-(x)) >> 8) & 0xff) + +// get second or third byte when translating special key code into three bytes + +#define K_SECOND(c) ((c) == K_SPECIAL ? KS_SPECIAL : (c) == \ + NUL ? KS_ZERO : KEY2TERMCAP0(c)) + +#define K_THIRD(c) (((c) == K_SPECIAL || (c) == \ + NUL) ? KE_FILLER : KEY2TERMCAP1(c)) + +/// get single int code from second byte after K_SPECIAL +#define TO_SPECIAL(a, b) ((a) == KS_SPECIAL ? K_SPECIAL : (a) == \ + KS_ZERO ? K_ZERO : TERMCAP2KEY(a, b)) + +// Codes for keys that do not have a termcap name. +// The numbers are fixed to make sure that recorded key sequences remain valid. +// Add new entries at the end, not halfway. +// +// K_SPECIAL KS_EXTRA KE_xxx +// +// Entries must be in the range 0x02-0x7f (see comment at K_SPECIAL). +enum key_extra { + KE_S_UP = 4, // shift-up + KE_S_DOWN = 5, // shift-down + + KE_S_F1 = 6, // shifted function keys + KE_S_F2 = 7, + KE_S_F3 = 8, + KE_S_F4 = 9, + KE_S_F5 = 10, + KE_S_F6 = 11, + KE_S_F7 = 12, + KE_S_F8 = 13, + KE_S_F9 = 14, + KE_S_F10 = 15, + + KE_S_F11 = 16, + KE_S_F12 = 17, + KE_S_F13 = 18, + KE_S_F14 = 19, + KE_S_F15 = 20, + KE_S_F16 = 21, + KE_S_F17 = 22, + KE_S_F18 = 23, + KE_S_F19 = 24, + KE_S_F20 = 25, + + KE_S_F21 = 26, + KE_S_F22 = 27, + KE_S_F23 = 28, + KE_S_F24 = 29, + KE_S_F25 = 30, + KE_S_F26 = 31, + KE_S_F27 = 32, + KE_S_F28 = 33, + KE_S_F29 = 34, + KE_S_F30 = 35, + + KE_S_F31 = 36, + KE_S_F32 = 37, + KE_S_F33 = 38, + KE_S_F34 = 39, + KE_S_F35 = 40, + KE_S_F36 = 41, + KE_S_F37 = 42, + + KE_MOUSE = 43, // mouse event start + + // Symbols for pseudo keys which are translated from the real key symbols + // above. + KE_LEFTMOUSE = 44, // Left mouse button click + KE_LEFTDRAG = 45, // Drag with left mouse button down + KE_LEFTRELEASE = 46, // Left mouse button release + KE_MIDDLEMOUSE = 47, // Middle mouse button click + KE_MIDDLEDRAG = 48, // Drag with middle mouse button down + KE_MIDDLERELEASE = 49, // Middle mouse button release + KE_RIGHTMOUSE = 50, // Right mouse button click + KE_RIGHTDRAG = 51, // Drag with right mouse button down + KE_RIGHTRELEASE = 52, // Right mouse button release + + KE_IGNORE = 53, // Ignored mouse drag/release + + KE_TAB = 54, // unshifted TAB key + KE_S_TAB_OLD = 55, // shifted TAB key (no longer used) + + // , KE_SNIFF_UNUSED = 56 // obsolete + KE_XF1 = 57, // extra vt100 function keys for xterm + KE_XF2 = 58, + KE_XF3 = 59, + KE_XF4 = 60, + KE_XEND = 61, // extra (vt100) end key for xterm + KE_ZEND = 62, // extra (vt100) end key for xterm + KE_XHOME = 63, // extra (vt100) home key for xterm + KE_ZHOME = 64, // extra (vt100) home key for xterm + KE_XUP = 65, // extra vt100 cursor keys for xterm + KE_XDOWN = 66, + KE_XLEFT = 67, + KE_XRIGHT = 68, + + KE_LEFTMOUSE_NM = 69, // non-mappable Left mouse button click + KE_LEFTRELEASE_NM = 70, // non-mappable left mouse button release + + KE_S_XF1 = 71, // vt100 shifted function keys for xterm + KE_S_XF2 = 72, + KE_S_XF3 = 73, + KE_S_XF4 = 74, + + // NOTE: The scroll wheel events are inverted: i.e. UP is the same as + // moving the actual scroll wheel down, LEFT is the same as moving the + // scroll wheel right. + KE_MOUSEDOWN = 75, // scroll wheel pseudo-button Down + KE_MOUSEUP = 76, // scroll wheel pseudo-button Up + KE_MOUSELEFT = 77, // scroll wheel pseudo-button Left + KE_MOUSERIGHT = 78, // scroll wheel pseudo-button Right + + KE_KINS = 79, // keypad Insert key + KE_KDEL = 80, // keypad Delete key + + // KE_CSI = 81, // Nvim doesn't need escaping CSI + KE_SNR = 82, // + KE_PLUG = 83, // + KE_CMDWIN = 84, // open command-line window from Command-line Mode + + KE_C_LEFT = 85, // control-left + KE_C_RIGHT = 86, // control-right + KE_C_HOME = 87, // control-home + KE_C_END = 88, // control-end + + KE_X1MOUSE = 89, // X1/X2 mouse-buttons + KE_X1DRAG = 90, + KE_X1RELEASE = 91, + KE_X2MOUSE = 92, + KE_X2DRAG = 93, + KE_X2RELEASE = 94, + + KE_DROP = 95, // DnD data is available + // , KE_CURSORHOLD = 96 // CursorHold event + KE_NOP = 97, // no-op: does nothing + // , KE_FOCUSGAINED = 98 // focus gained + // , KE_FOCUSLOST = 99 // focus lost + KE_MOUSEMOVE = 100, // mouse moved with no button down + // , KE_CANCEL = 101 // return from vgetc + KE_EVENT = 102, // event + KE_LUA = 103, // lua special key + KE_COMMAND = 104, // special key +}; + +// the three byte codes are replaced with the following int when using vgetc() + +#define K_ZERO TERMCAP2KEY(KS_ZERO, KE_FILLER) + +#define K_UP TERMCAP2KEY('k', 'u') +#define K_KUP TERMCAP2KEY('K', 'u') // keypad up +#define K_DOWN TERMCAP2KEY('k', 'd') +#define K_KDOWN TERMCAP2KEY('K', 'd') // keypad down +#define K_LEFT TERMCAP2KEY('k', 'l') +#define K_KLEFT TERMCAP2KEY('K', 'l') // keypad left +#define K_RIGHT TERMCAP2KEY('k', 'r') +#define K_KRIGHT TERMCAP2KEY('K', 'r') // keypad right +#define K_S_UP TERMCAP2KEY(KS_EXTRA, KE_S_UP) +#define K_S_DOWN TERMCAP2KEY(KS_EXTRA, KE_S_DOWN) +#define K_S_LEFT TERMCAP2KEY('#', '4') +#define K_C_LEFT TERMCAP2KEY(KS_EXTRA, KE_C_LEFT) +#define K_S_RIGHT TERMCAP2KEY('%', 'i') +#define K_C_RIGHT TERMCAP2KEY(KS_EXTRA, KE_C_RIGHT) +#define K_S_HOME TERMCAP2KEY('#', '2') +#define K_C_HOME TERMCAP2KEY(KS_EXTRA, KE_C_HOME) +#define K_S_END TERMCAP2KEY('*', '7') +#define K_C_END TERMCAP2KEY(KS_EXTRA, KE_C_END) +#define K_TAB TERMCAP2KEY(KS_EXTRA, KE_TAB) +#define K_S_TAB TERMCAP2KEY('k', 'B') + +// extra set of function keys F1-F4, for vt100 compatible xterm +#define K_XF1 TERMCAP2KEY(KS_EXTRA, KE_XF1) +#define K_XF2 TERMCAP2KEY(KS_EXTRA, KE_XF2) +#define K_XF3 TERMCAP2KEY(KS_EXTRA, KE_XF3) +#define K_XF4 TERMCAP2KEY(KS_EXTRA, KE_XF4) + +// extra set of cursor keys for vt100 compatible xterm +#define K_XUP TERMCAP2KEY(KS_EXTRA, KE_XUP) +#define K_XDOWN TERMCAP2KEY(KS_EXTRA, KE_XDOWN) +#define K_XLEFT TERMCAP2KEY(KS_EXTRA, KE_XLEFT) +#define K_XRIGHT TERMCAP2KEY(KS_EXTRA, KE_XRIGHT) + +#define K_F1 TERMCAP2KEY('k', '1') // function keys +#define K_F2 TERMCAP2KEY('k', '2') +#define K_F3 TERMCAP2KEY('k', '3') +#define K_F4 TERMCAP2KEY('k', '4') +#define K_F5 TERMCAP2KEY('k', '5') +#define K_F6 TERMCAP2KEY('k', '6') +#define K_F7 TERMCAP2KEY('k', '7') +#define K_F8 TERMCAP2KEY('k', '8') +#define K_F9 TERMCAP2KEY('k', '9') +#define K_F10 TERMCAP2KEY('k', ';') + +#define K_F11 TERMCAP2KEY('F', '1') +#define K_F12 TERMCAP2KEY('F', '2') +#define K_F13 TERMCAP2KEY('F', '3') +#define K_F14 TERMCAP2KEY('F', '4') +#define K_F15 TERMCAP2KEY('F', '5') +#define K_F16 TERMCAP2KEY('F', '6') +#define K_F17 TERMCAP2KEY('F', '7') +#define K_F18 TERMCAP2KEY('F', '8') +#define K_F19 TERMCAP2KEY('F', '9') +#define K_F20 TERMCAP2KEY('F', 'A') + +#define K_F21 TERMCAP2KEY('F', 'B') +#define K_F22 TERMCAP2KEY('F', 'C') +#define K_F23 TERMCAP2KEY('F', 'D') +#define K_F24 TERMCAP2KEY('F', 'E') +#define K_F25 TERMCAP2KEY('F', 'F') +#define K_F26 TERMCAP2KEY('F', 'G') +#define K_F27 TERMCAP2KEY('F', 'H') +#define K_F28 TERMCAP2KEY('F', 'I') +#define K_F29 TERMCAP2KEY('F', 'J') +#define K_F30 TERMCAP2KEY('F', 'K') + +#define K_F31 TERMCAP2KEY('F', 'L') +#define K_F32 TERMCAP2KEY('F', 'M') +#define K_F33 TERMCAP2KEY('F', 'N') +#define K_F34 TERMCAP2KEY('F', 'O') +#define K_F35 TERMCAP2KEY('F', 'P') +#define K_F36 TERMCAP2KEY('F', 'Q') +#define K_F37 TERMCAP2KEY('F', 'R') +#define K_F38 TERMCAP2KEY('F', 'S') +#define K_F39 TERMCAP2KEY('F', 'T') +#define K_F40 TERMCAP2KEY('F', 'U') + +#define K_F41 TERMCAP2KEY('F', 'V') +#define K_F42 TERMCAP2KEY('F', 'W') +#define K_F43 TERMCAP2KEY('F', 'X') +#define K_F44 TERMCAP2KEY('F', 'Y') +#define K_F45 TERMCAP2KEY('F', 'Z') +#define K_F46 TERMCAP2KEY('F', 'a') +#define K_F47 TERMCAP2KEY('F', 'b') +#define K_F48 TERMCAP2KEY('F', 'c') +#define K_F49 TERMCAP2KEY('F', 'd') +#define K_F50 TERMCAP2KEY('F', 'e') + +#define K_F51 TERMCAP2KEY('F', 'f') +#define K_F52 TERMCAP2KEY('F', 'g') +#define K_F53 TERMCAP2KEY('F', 'h') +#define K_F54 TERMCAP2KEY('F', 'i') +#define K_F55 TERMCAP2KEY('F', 'j') +#define K_F56 TERMCAP2KEY('F', 'k') +#define K_F57 TERMCAP2KEY('F', 'l') +#define K_F58 TERMCAP2KEY('F', 'm') +#define K_F59 TERMCAP2KEY('F', 'n') +#define K_F60 TERMCAP2KEY('F', 'o') + +#define K_F61 TERMCAP2KEY('F', 'p') +#define K_F62 TERMCAP2KEY('F', 'q') +#define K_F63 TERMCAP2KEY('F', 'r') + +// extra set of shifted function keys F1-F4, for vt100 compatible xterm +#define K_S_XF1 TERMCAP2KEY(KS_EXTRA, KE_S_XF1) +#define K_S_XF2 TERMCAP2KEY(KS_EXTRA, KE_S_XF2) +#define K_S_XF3 TERMCAP2KEY(KS_EXTRA, KE_S_XF3) +#define K_S_XF4 TERMCAP2KEY(KS_EXTRA, KE_S_XF4) + +#define K_S_F1 TERMCAP2KEY(KS_EXTRA, KE_S_F1) // shifted func. keys +#define K_S_F2 TERMCAP2KEY(KS_EXTRA, KE_S_F2) +#define K_S_F3 TERMCAP2KEY(KS_EXTRA, KE_S_F3) +#define K_S_F4 TERMCAP2KEY(KS_EXTRA, KE_S_F4) +#define K_S_F5 TERMCAP2KEY(KS_EXTRA, KE_S_F5) +#define K_S_F6 TERMCAP2KEY(KS_EXTRA, KE_S_F6) +#define K_S_F7 TERMCAP2KEY(KS_EXTRA, KE_S_F7) +#define K_S_F8 TERMCAP2KEY(KS_EXTRA, KE_S_F8) +#define K_S_F9 TERMCAP2KEY(KS_EXTRA, KE_S_F9) +#define K_S_F10 TERMCAP2KEY(KS_EXTRA, KE_S_F10) + +#define K_S_F11 TERMCAP2KEY(KS_EXTRA, KE_S_F11) +#define K_S_F12 TERMCAP2KEY(KS_EXTRA, KE_S_F12) +// K_S_F13 to K_S_F37 are currently not used + +#define K_HELP TERMCAP2KEY('%', '1') +#define K_UNDO TERMCAP2KEY('&', '8') + +#define K_BS TERMCAP2KEY('k', 'b') + +#define K_INS TERMCAP2KEY('k', 'I') +#define K_KINS TERMCAP2KEY(KS_EXTRA, KE_KINS) +#define K_DEL TERMCAP2KEY('k', 'D') +#define K_KDEL TERMCAP2KEY(KS_EXTRA, KE_KDEL) +#define K_HOME TERMCAP2KEY('k', 'h') +#define K_KHOME TERMCAP2KEY('K', '1') // keypad home (upper left) +#define K_XHOME TERMCAP2KEY(KS_EXTRA, KE_XHOME) +#define K_ZHOME TERMCAP2KEY(KS_EXTRA, KE_ZHOME) +#define K_END TERMCAP2KEY('@', '7') +#define K_KEND TERMCAP2KEY('K', '4') // keypad end (lower left) +#define K_XEND TERMCAP2KEY(KS_EXTRA, KE_XEND) +#define K_ZEND TERMCAP2KEY(KS_EXTRA, KE_ZEND) +#define K_PAGEUP TERMCAP2KEY('k', 'P') +#define K_PAGEDOWN TERMCAP2KEY('k', 'N') +#define K_KPAGEUP TERMCAP2KEY('K', '3') // keypad pageup (upper R.) +#define K_KPAGEDOWN TERMCAP2KEY('K', '5') // keypad pagedown (lower R.) +#define K_KORIGIN TERMCAP2KEY('K', '2') // keypad center + +#define K_KPLUS TERMCAP2KEY('K', '6') // keypad plus +#define K_KMINUS TERMCAP2KEY('K', '7') // keypad minus +#define K_KDIVIDE TERMCAP2KEY('K', '8') // keypad / +#define K_KMULTIPLY TERMCAP2KEY('K', '9') // keypad * +#define K_KENTER TERMCAP2KEY('K', 'A') // keypad Enter +#define K_KPOINT TERMCAP2KEY('K', 'B') // keypad . or , + +#define K_K0 TERMCAP2KEY('K', 'C') // keypad 0 +#define K_K1 TERMCAP2KEY('K', 'D') // keypad 1 +#define K_K2 TERMCAP2KEY('K', 'E') // keypad 2 +#define K_K3 TERMCAP2KEY('K', 'F') // keypad 3 +#define K_K4 TERMCAP2KEY('K', 'G') // keypad 4 +#define K_K5 TERMCAP2KEY('K', 'H') // keypad 5 +#define K_K6 TERMCAP2KEY('K', 'I') // keypad 6 +#define K_K7 TERMCAP2KEY('K', 'J') // keypad 7 +#define K_K8 TERMCAP2KEY('K', 'K') // keypad 8 +#define K_K9 TERMCAP2KEY('K', 'L') // keypad 9 + +#define K_KCOMMA TERMCAP2KEY('K', 'M') // keypad comma +#define K_KEQUAL TERMCAP2KEY('K', 'N') // keypad equal + +#define K_MOUSE TERMCAP2KEY(KS_MOUSE, KE_FILLER) +#define K_MENU TERMCAP2KEY(KS_MENU, KE_FILLER) +#define K_VER_SCROLLBAR TERMCAP2KEY(KS_VER_SCROLLBAR, KE_FILLER) +#define K_HOR_SCROLLBAR TERMCAP2KEY(KS_HOR_SCROLLBAR, KE_FILLER) + +#define K_SELECT TERMCAP2KEY(KS_SELECT, KE_FILLER) + +#define K_TABLINE TERMCAP2KEY(KS_TABLINE, KE_FILLER) +#define K_TABMENU TERMCAP2KEY(KS_TABMENU, KE_FILLER) + +// Symbols for pseudo keys which are translated from the real key symbols +// above. + +#define K_LEFTMOUSE TERMCAP2KEY(KS_EXTRA, KE_LEFTMOUSE) +#define K_LEFTMOUSE_NM TERMCAP2KEY(KS_EXTRA, KE_LEFTMOUSE_NM) +#define K_LEFTDRAG TERMCAP2KEY(KS_EXTRA, KE_LEFTDRAG) +#define K_LEFTRELEASE TERMCAP2KEY(KS_EXTRA, KE_LEFTRELEASE) +#define K_LEFTRELEASE_NM TERMCAP2KEY(KS_EXTRA, KE_LEFTRELEASE_NM) +#define K_MOUSEMOVE TERMCAP2KEY(KS_EXTRA, KE_MOUSEMOVE) +#define K_MIDDLEMOUSE TERMCAP2KEY(KS_EXTRA, KE_MIDDLEMOUSE) +#define K_MIDDLEDRAG TERMCAP2KEY(KS_EXTRA, KE_MIDDLEDRAG) +#define K_MIDDLERELEASE TERMCAP2KEY(KS_EXTRA, KE_MIDDLERELEASE) +#define K_RIGHTMOUSE TERMCAP2KEY(KS_EXTRA, KE_RIGHTMOUSE) +#define K_RIGHTDRAG TERMCAP2KEY(KS_EXTRA, KE_RIGHTDRAG) +#define K_RIGHTRELEASE TERMCAP2KEY(KS_EXTRA, KE_RIGHTRELEASE) +#define K_X1MOUSE TERMCAP2KEY(KS_EXTRA, KE_X1MOUSE) +#define K_X1MOUSE TERMCAP2KEY(KS_EXTRA, KE_X1MOUSE) +#define K_X1DRAG TERMCAP2KEY(KS_EXTRA, KE_X1DRAG) +#define K_X1RELEASE TERMCAP2KEY(KS_EXTRA, KE_X1RELEASE) +#define K_X2MOUSE TERMCAP2KEY(KS_EXTRA, KE_X2MOUSE) +#define K_X2DRAG TERMCAP2KEY(KS_EXTRA, KE_X2DRAG) +#define K_X2RELEASE TERMCAP2KEY(KS_EXTRA, KE_X2RELEASE) + +#define K_IGNORE TERMCAP2KEY(KS_EXTRA, KE_IGNORE) +#define K_NOP TERMCAP2KEY(KS_EXTRA, KE_NOP) + +#define K_MOUSEDOWN TERMCAP2KEY(KS_EXTRA, KE_MOUSEDOWN) +#define K_MOUSEUP TERMCAP2KEY(KS_EXTRA, KE_MOUSEUP) +#define K_MOUSELEFT TERMCAP2KEY(KS_EXTRA, KE_MOUSELEFT) +#define K_MOUSERIGHT TERMCAP2KEY(KS_EXTRA, KE_MOUSERIGHT) + +#define K_SNR TERMCAP2KEY(KS_EXTRA, KE_SNR) +#define K_PLUG TERMCAP2KEY(KS_EXTRA, KE_PLUG) +#define K_CMDWIN TERMCAP2KEY(KS_EXTRA, KE_CMDWIN) + +#define K_DROP TERMCAP2KEY(KS_EXTRA, KE_DROP) + +#define K_EVENT TERMCAP2KEY(KS_EXTRA, KE_EVENT) +#define K_COMMAND TERMCAP2KEY(KS_EXTRA, KE_COMMAND) +#define K_LUA TERMCAP2KEY(KS_EXTRA, KE_LUA) + +// Bits for modifier mask +// 0x01 cannot be used, because the modifier must be 0x02 or higher +#define MOD_MASK_SHIFT 0x02 +#define MOD_MASK_CTRL 0x04 +#define MOD_MASK_ALT 0x08 // aka META +#define MOD_MASK_META 0x10 // META when it's different from ALT +#define MOD_MASK_2CLICK 0x20 // use MOD_MASK_MULTI_CLICK +#define MOD_MASK_3CLICK 0x40 // use MOD_MASK_MULTI_CLICK +#define MOD_MASK_4CLICK 0x60 // use MOD_MASK_MULTI_CLICK +#define MOD_MASK_CMD 0x80 // "super" key (macOS: command-key) + +#define MOD_MASK_MULTI_CLICK (MOD_MASK_2CLICK|MOD_MASK_3CLICK| \ + MOD_MASK_4CLICK) + +/// The length of the longest special key name, including modifiers. +/// Current longest is (length includes '<' and '>'). +#define MAX_KEY_NAME_LEN 32 + +// Maximum length of a special key event as tokens. This includes modifiers. +// The longest event is something like which would be the +// following string of tokens: +// +// bitmask . +// +// This is a total of 6 tokens, and is currently the longest one possible. +#define MAX_KEY_CODE_LEN 6 + +#define FLAG_CPO_BSLASH 0x01 +#define CPO_TO_CPO_FLAGS ((vim_strchr(p_cpo, CPO_BSLASH) == NULL) \ + ? 0 \ + : FLAG_CPO_BSLASH) + +// Flags for replace_termcodes() +enum { + REPTERM_FROM_PART = 1, + REPTERM_DO_LT = 2, + REPTERM_NO_SPECIAL = 4, + REPTERM_NO_SIMPLIFY = 8, +}; + +// Flags for find_special_key() +enum { + FSK_KEYCODE = 0x01, ///< prefer key code, e.g. K_DEL in place of DEL + FSK_KEEP_X_KEY = 0x02, ///< don’t translate xHome to Home key + FSK_IN_STRING = 0x04, ///< in string, double quote is escaped + FSK_SIMPLIFY = 0x08, ///< simplify , etc. +}; + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "keycodes.h.generated.h" +#endif +#endif // NVIM_KEYCODES_H diff --git a/src/nvim/keymap.c b/src/nvim/keymap.c deleted file mode 100644 index b184b42354..0000000000 --- a/src/nvim/keymap.c +++ /dev/null @@ -1,1032 +0,0 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - -#include -#include -#include - -#include "nvim/ascii.h" -#include "nvim/charset.h" -#include "nvim/edit.h" -#include "nvim/eval.h" -#include "nvim/keymap.h" -#include "nvim/memory.h" -#include "nvim/message.h" -#include "nvim/mouse.h" -#include "nvim/strings.h" -#include "nvim/vim.h" - -#ifdef INCLUDE_GENERATED_DECLARATIONS -# include "keymap.c.generated.h" -#endif - -/* - * Some useful tables. - */ - -static const struct modmasktable { - uint16_t mod_mask; ///< Bit-mask for particular key modifier. - uint16_t mod_flag; ///< Bit(s) for particular key modifier. - char_u name; ///< Single letter name of modifier. -} mod_mask_table[] = { - { MOD_MASK_ALT, MOD_MASK_ALT, (char_u)'M' }, - { MOD_MASK_META, MOD_MASK_META, (char_u)'T' }, - { MOD_MASK_CTRL, MOD_MASK_CTRL, (char_u)'C' }, - { MOD_MASK_SHIFT, MOD_MASK_SHIFT, (char_u)'S' }, - { MOD_MASK_MULTI_CLICK, MOD_MASK_2CLICK, (char_u)'2' }, - { MOD_MASK_MULTI_CLICK, MOD_MASK_3CLICK, (char_u)'3' }, - { MOD_MASK_MULTI_CLICK, MOD_MASK_4CLICK, (char_u)'4' }, - { MOD_MASK_CMD, MOD_MASK_CMD, (char_u)'D' }, - // 'A' must be the last one - { MOD_MASK_ALT, MOD_MASK_ALT, (char_u)'A' }, - { 0, 0, NUL } - // NOTE: when adding an entry, update MAX_KEY_NAME_LEN! -}; - -/* - * Shifted key terminal codes and their unshifted equivalent. - * Don't add mouse codes here, they are handled separately! - */ -#define MOD_KEYS_ENTRY_SIZE 5 - -static char_u modifier_keys_table[] = -{ - // mod mask with modifier without modifier - MOD_MASK_SHIFT, '&', '9', '@', '1', // begin - MOD_MASK_SHIFT, '&', '0', '@', '2', // cancel - MOD_MASK_SHIFT, '*', '1', '@', '4', // command - MOD_MASK_SHIFT, '*', '2', '@', '5', // copy - MOD_MASK_SHIFT, '*', '3', '@', '6', // create - MOD_MASK_SHIFT, '*', '4', 'k', 'D', // delete char - MOD_MASK_SHIFT, '*', '5', 'k', 'L', // delete line - MOD_MASK_SHIFT, '*', '7', '@', '7', // end - MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_END, '@', '7', // end - MOD_MASK_SHIFT, '*', '9', '@', '9', // exit - MOD_MASK_SHIFT, '*', '0', '@', '0', // find - MOD_MASK_SHIFT, '#', '1', '%', '1', // help - MOD_MASK_SHIFT, '#', '2', 'k', 'h', // home - MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_HOME, 'k', 'h', // home - MOD_MASK_SHIFT, '#', '3', 'k', 'I', // insert - MOD_MASK_SHIFT, '#', '4', 'k', 'l', // left arrow - MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_LEFT, 'k', 'l', // left arrow - MOD_MASK_SHIFT, '%', 'a', '%', '3', // message - MOD_MASK_SHIFT, '%', 'b', '%', '4', // move - MOD_MASK_SHIFT, '%', 'c', '%', '5', // next - MOD_MASK_SHIFT, '%', 'd', '%', '7', // options - MOD_MASK_SHIFT, '%', 'e', '%', '8', // previous - MOD_MASK_SHIFT, '%', 'f', '%', '9', // print - MOD_MASK_SHIFT, '%', 'g', '%', '0', // redo - MOD_MASK_SHIFT, '%', 'h', '&', '3', // replace - MOD_MASK_SHIFT, '%', 'i', 'k', 'r', // right arr. - MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_RIGHT, 'k', 'r', // right arr. - MOD_MASK_SHIFT, '%', 'j', '&', '5', // resume - MOD_MASK_SHIFT, '!', '1', '&', '6', // save - MOD_MASK_SHIFT, '!', '2', '&', '7', // suspend - MOD_MASK_SHIFT, '!', '3', '&', '8', // undo - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_UP, 'k', 'u', // up arrow - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_DOWN, 'k', 'd', // down arrow - - // vt100 F1 - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF1, KS_EXTRA, (int)KE_XF1, - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF2, KS_EXTRA, (int)KE_XF2, - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF3, KS_EXTRA, (int)KE_XF3, - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF4, KS_EXTRA, (int)KE_XF4, - - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F1, 'k', '1', // F1 - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F2, 'k', '2', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F3, 'k', '3', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F4, 'k', '4', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F5, 'k', '5', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F6, 'k', '6', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F7, 'k', '7', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F8, 'k', '8', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F9, 'k', '9', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F10, 'k', ';', // F10 - - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F11, 'F', '1', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F12, 'F', '2', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F13, 'F', '3', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F14, 'F', '4', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F15, 'F', '5', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F16, 'F', '6', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F17, 'F', '7', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F18, 'F', '8', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F19, 'F', '9', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F20, 'F', 'A', - - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F21, 'F', 'B', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F22, 'F', 'C', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F23, 'F', 'D', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F24, 'F', 'E', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F25, 'F', 'F', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F26, 'F', 'G', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F27, 'F', 'H', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F28, 'F', 'I', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F29, 'F', 'J', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F30, 'F', 'K', - - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F31, 'F', 'L', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F32, 'F', 'M', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F33, 'F', 'N', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F34, 'F', 'O', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F35, 'F', 'P', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F36, 'F', 'Q', - MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F37, 'F', 'R', - - // TAB pseudo code - MOD_MASK_SHIFT, 'k', 'B', KS_EXTRA, (int)KE_TAB, - - NUL -}; - -static const struct key_name_entry { - int key; // Special key code or ascii value - const char *name; // Name of key -} key_names_table[] = { - { ' ', "Space" }, - { TAB, "Tab" }, - { K_TAB, "Tab" }, - { NL, "NL" }, - { NL, "NewLine" }, // Alternative name - { NL, "LineFeed" }, // Alternative name - { NL, "LF" }, // Alternative name - { CAR, "CR" }, - { CAR, "Return" }, // Alternative name - { CAR, "Enter" }, // Alternative name - { K_BS, "BS" }, - { K_BS, "BackSpace" }, // Alternative name - { ESC, "Esc" }, - { ESC, "Escape" }, // Alternative name - { CSI, "CSI" }, - { '|', "Bar" }, - { '\\', "Bslash" }, - { K_DEL, "Del" }, - { K_DEL, "Delete" }, // Alternative name - { K_KDEL, "kDel" }, - { K_KDEL, "KPPeriod" }, // libtermkey name - { K_UP, "Up" }, - { K_DOWN, "Down" }, - { K_LEFT, "Left" }, - { K_RIGHT, "Right" }, - { K_XUP, "xUp" }, - { K_XDOWN, "xDown" }, - { K_XLEFT, "xLeft" }, - { K_XRIGHT, "xRight" }, - { K_KUP, "kUp" }, - { K_KUP, "KP8" }, - { K_KDOWN, "kDown" }, - { K_KDOWN, "KP2" }, - { K_KLEFT, "kLeft" }, - { K_KLEFT, "KP4" }, - { K_KRIGHT, "kRight" }, - { K_KRIGHT, "KP6" }, - - { K_F1, "F1" }, - { K_F2, "F2" }, - { K_F3, "F3" }, - { K_F4, "F4" }, - { K_F5, "F5" }, - { K_F6, "F6" }, - { K_F7, "F7" }, - { K_F8, "F8" }, - { K_F9, "F9" }, - { K_F10, "F10" }, - - { K_F11, "F11" }, - { K_F12, "F12" }, - { K_F13, "F13" }, - { K_F14, "F14" }, - { K_F15, "F15" }, - { K_F16, "F16" }, - { K_F17, "F17" }, - { K_F18, "F18" }, - { K_F19, "F19" }, - { K_F20, "F20" }, - - { K_F21, "F21" }, - { K_F22, "F22" }, - { K_F23, "F23" }, - { K_F24, "F24" }, - { K_F25, "F25" }, - { K_F26, "F26" }, - { K_F27, "F27" }, - { K_F28, "F28" }, - { K_F29, "F29" }, - { K_F30, "F30" }, - - { K_F31, "F31" }, - { K_F32, "F32" }, - { K_F33, "F33" }, - { K_F34, "F34" }, - { K_F35, "F35" }, - { K_F36, "F36" }, - { K_F37, "F37" }, - { K_F38, "F38" }, - { K_F39, "F39" }, - { K_F40, "F40" }, - - { K_F41, "F41" }, - { K_F42, "F42" }, - { K_F43, "F43" }, - { K_F44, "F44" }, - { K_F45, "F45" }, - { K_F46, "F46" }, - { K_F47, "F47" }, - { K_F48, "F48" }, - { K_F49, "F49" }, - { K_F50, "F50" }, - - { K_F51, "F51" }, - { K_F52, "F52" }, - { K_F53, "F53" }, - { K_F54, "F54" }, - { K_F55, "F55" }, - { K_F56, "F56" }, - { K_F57, "F57" }, - { K_F58, "F58" }, - { K_F59, "F59" }, - { K_F60, "F60" }, - - { K_F61, "F61" }, - { K_F62, "F62" }, - { K_F63, "F63" }, - - { K_XF1, "xF1" }, - { K_XF2, "xF2" }, - { K_XF3, "xF3" }, - { K_XF4, "xF4" }, - - { K_HELP, "Help" }, - { K_UNDO, "Undo" }, - { K_INS, "Insert" }, - { K_INS, "Ins" }, // Alternative name - { K_KINS, "kInsert" }, - { K_KINS, "KP0" }, - { K_HOME, "Home" }, - { K_KHOME, "kHome" }, - { K_KHOME, "KP7" }, - { K_XHOME, "xHome" }, - { K_ZHOME, "zHome" }, - { K_END, "End" }, - { K_KEND, "kEnd" }, - { K_KEND, "KP1" }, - { K_XEND, "xEnd" }, - { K_ZEND, "zEnd" }, - { K_PAGEUP, "PageUp" }, - { K_PAGEDOWN, "PageDown" }, - { K_KPAGEUP, "kPageUp" }, - { K_KPAGEUP, "KP9" }, - { K_KPAGEDOWN, "kPageDown" }, - { K_KPAGEDOWN, "KP3" }, - { K_KORIGIN, "kOrigin" }, - { K_KORIGIN, "KP5" }, - - { K_KPLUS, "kPlus" }, - { K_KPLUS, "KPPlus" }, - { K_KMINUS, "kMinus" }, - { K_KMINUS, "KPMinus" }, - { K_KDIVIDE, "kDivide" }, - { K_KDIVIDE, "KPDiv" }, - { K_KMULTIPLY, "kMultiply" }, - { K_KMULTIPLY, "KPMult" }, - { K_KENTER, "kEnter" }, - { K_KENTER, "KPEnter" }, - { K_KPOINT, "kPoint" }, - { K_KCOMMA, "kComma" }, - { K_KCOMMA, "KPComma" }, - { K_KEQUAL, "kEqual" }, - { K_KEQUAL, "KPEquals" }, - - { K_K0, "k0" }, - { K_K1, "k1" }, - { K_K2, "k2" }, - { K_K3, "k3" }, - { K_K4, "k4" }, - { K_K5, "k5" }, - { K_K6, "k6" }, - { K_K7, "k7" }, - { K_K8, "k8" }, - { K_K9, "k9" }, - - { '<', "lt" }, - - { K_MOUSE, "Mouse" }, - { K_LEFTMOUSE, "LeftMouse" }, - { K_LEFTMOUSE_NM, "LeftMouseNM" }, - { K_LEFTDRAG, "LeftDrag" }, - { K_LEFTRELEASE, "LeftRelease" }, - { K_LEFTRELEASE_NM, "LeftReleaseNM" }, - { K_MOUSEMOVE, "MouseMove" }, - { K_MIDDLEMOUSE, "MiddleMouse" }, - { K_MIDDLEDRAG, "MiddleDrag" }, - { K_MIDDLERELEASE, "MiddleRelease" }, - { K_RIGHTMOUSE, "RightMouse" }, - { K_RIGHTDRAG, "RightDrag" }, - { K_RIGHTRELEASE, "RightRelease" }, - { K_MOUSEDOWN, "ScrollWheelUp" }, - { K_MOUSEUP, "ScrollWheelDown" }, - { K_MOUSELEFT, "ScrollWheelRight" }, - { K_MOUSERIGHT, "ScrollWheelLeft" }, - { K_MOUSEDOWN, "MouseDown" }, // OBSOLETE: Use - { K_MOUSEUP, "MouseUp" }, // ScrollWheelXXX instead - { K_X1MOUSE, "X1Mouse" }, - { K_X1DRAG, "X1Drag" }, - { K_X1RELEASE, "X1Release" }, - { K_X2MOUSE, "X2Mouse" }, - { K_X2DRAG, "X2Drag" }, - { K_X2RELEASE, "X2Release" }, - { K_DROP, "Drop" }, - { K_ZERO, "Nul" }, - { K_SNR, "SNR" }, - { K_PLUG, "Plug" }, - { K_IGNORE, "Ignore" }, - { K_COMMAND, "Cmd" }, - { 0, NULL } - // NOTE: When adding a long name update MAX_KEY_NAME_LEN. -}; - -static struct mousetable { - int pseudo_code; // Code for pseudo mouse event - int button; // Which mouse button is it? - bool is_click; // Is it a mouse button click event? - bool is_drag; // Is it a mouse drag event? -} mouse_table[] = -{ - { (int)KE_LEFTMOUSE, MOUSE_LEFT, true, false }, - { (int)KE_LEFTDRAG, MOUSE_LEFT, false, true }, - { (int)KE_LEFTRELEASE, MOUSE_LEFT, false, false }, - { (int)KE_MIDDLEMOUSE, MOUSE_MIDDLE, true, false }, - { (int)KE_MIDDLEDRAG, MOUSE_MIDDLE, false, true }, - { (int)KE_MIDDLERELEASE, MOUSE_MIDDLE, false, false }, - { (int)KE_RIGHTMOUSE, MOUSE_RIGHT, true, false }, - { (int)KE_RIGHTDRAG, MOUSE_RIGHT, false, true }, - { (int)KE_RIGHTRELEASE, MOUSE_RIGHT, false, false }, - { (int)KE_X1MOUSE, MOUSE_X1, true, false }, - { (int)KE_X1DRAG, MOUSE_X1, false, true }, - { (int)KE_X1RELEASE, MOUSE_X1, false, false }, - { (int)KE_X2MOUSE, MOUSE_X2, true, false }, - { (int)KE_X2DRAG, MOUSE_X2, false, true }, - { (int)KE_X2RELEASE, MOUSE_X2, false, false }, - // DRAG without CLICK - { (int)K_MOUSEMOVE, MOUSE_RELEASE, false, true }, - // RELEASE without CLICK - { (int)KE_IGNORE, MOUSE_RELEASE, false, false }, - { 0, 0, 0, 0 }, -}; - -/// Return the modifier mask bit (#MOD_MASK_*) corresponding to mod name -/// -/// E.g. 'S' for shift, 'C' for ctrl. -int name_to_mod_mask(int c) - FUNC_ATTR_CONST FUNC_ATTR_WARN_UNUSED_RESULT -{ - c = TOUPPER_ASC(c); - for (size_t i = 0; mod_mask_table[i].mod_mask != 0; i++) { - if (c == mod_mask_table[i].name) { - return mod_mask_table[i].mod_flag; - } - } - return 0; -} - -/// Check if there is a special key code for "key" with specified modifiers -/// -/// @param[in] key Initial key code. -/// @param[in,out] modifiers Initial modifiers, is adjusted to have simplified -/// modifiers. -/// -/// @return Simplified key code. -int simplify_key(const int key, int *modifiers) - FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL -{ - if (*modifiers & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT)) { - // TAB is a special case. - if (key == TAB && (*modifiers & MOD_MASK_SHIFT)) { - *modifiers &= ~MOD_MASK_SHIFT; - return K_S_TAB; - } - const int key0 = KEY2TERMCAP0(key); - const int key1 = KEY2TERMCAP1(key); - for (int i = 0; modifier_keys_table[i] != NUL; i += MOD_KEYS_ENTRY_SIZE) { - if (key0 == modifier_keys_table[i + 3] - && key1 == modifier_keys_table[i + 4] - && (*modifiers & modifier_keys_table[i])) { - *modifiers &= ~modifier_keys_table[i]; - return TERMCAP2KEY(modifier_keys_table[i + 1], - modifier_keys_table[i + 2]); - } - } - } - return key; -} - -/// Change to -int handle_x_keys(const int key) - FUNC_ATTR_CONST FUNC_ATTR_WARN_UNUSED_RESULT -{ - switch (key) { - case K_XUP: - return K_UP; - case K_XDOWN: - return K_DOWN; - case K_XLEFT: - return K_LEFT; - case K_XRIGHT: - return K_RIGHT; - case K_XHOME: - return K_HOME; - case K_ZHOME: - return K_HOME; - case K_XEND: - return K_END; - case K_ZEND: - return K_END; - case K_XF1: - return K_F1; - case K_XF2: - return K_F2; - case K_XF3: - return K_F3; - case K_XF4: - return K_F4; - case K_S_XF1: - return K_S_F1; - case K_S_XF2: - return K_S_F2; - case K_S_XF3: - return K_S_F3; - case K_S_XF4: - return K_S_F4; - } - return key; -} - -/* - * Return a string which contains the name of the given key when the given - * modifiers are down. - */ -char_u *get_special_key_name(int c, int modifiers) -{ - static char_u string[MAX_KEY_NAME_LEN + 1]; - - int i, idx; - int table_idx; - char_u *s; - - string[0] = '<'; - idx = 1; - - // Key that stands for a normal character. - if (IS_SPECIAL(c) && KEY2TERMCAP0(c) == KS_KEY) { - c = KEY2TERMCAP1(c); - } - - /* - * Translate shifted special keys into unshifted keys and set modifier. - * Same for CTRL and ALT modifiers. - */ - if (IS_SPECIAL(c)) { - for (i = 0; modifier_keys_table[i] != 0; i += MOD_KEYS_ENTRY_SIZE) { - if (KEY2TERMCAP0(c) == (int)modifier_keys_table[i + 1] - && (int)KEY2TERMCAP1(c) == (int)modifier_keys_table[i + 2]) { - modifiers |= modifier_keys_table[i]; - c = TERMCAP2KEY(modifier_keys_table[i + 3], - modifier_keys_table[i + 4]); - break; - } - } - } - - // try to find the key in the special key table - table_idx = find_special_key_in_table(c); - - /* - * When not a known special key, and not a printable character, try to - * extract modifiers. - */ - if (c > 0 - && utf_char2len(c) == 1) { - if (table_idx < 0 - && (!vim_isprintc(c) || (c & 0x7f) == ' ') - && (c & 0x80)) { - c &= 0x7f; - modifiers |= MOD_MASK_ALT; - // try again, to find the un-alted key in the special key table - table_idx = find_special_key_in_table(c); - } - if (table_idx < 0 && !vim_isprintc(c) && c < ' ') { - c += '@'; - modifiers |= MOD_MASK_CTRL; - } - } - - // translate the modifier into a string - for (i = 0; mod_mask_table[i].name != 'A'; i++) { - if ((modifiers & mod_mask_table[i].mod_mask) - == mod_mask_table[i].mod_flag) { - string[idx++] = mod_mask_table[i].name; - string[idx++] = (char_u)'-'; - } - } - - if (table_idx < 0) { // unknown special key, may output t_xx - if (IS_SPECIAL(c)) { - string[idx++] = 't'; - string[idx++] = '_'; - string[idx++] = (char_u)KEY2TERMCAP0(c); - string[idx++] = KEY2TERMCAP1(c); - } else { - // Not a special key, only modifiers, output directly. - if (utf_char2len(c) > 1) { - idx += utf_char2bytes(c, (char *)string + idx); - } else if (vim_isprintc(c)) { - string[idx++] = (char_u)c; - } else { - s = transchar(c); - while (*s) { - string[idx++] = *s++; - } - } - } - } else { // use name of special key - size_t len = STRLEN(key_names_table[table_idx].name); - - if ((int)len + idx + 2 <= MAX_KEY_NAME_LEN) { - STRCPY(string + idx, key_names_table[table_idx].name); - idx += (int)len; - } - } - string[idx++] = '>'; - string[idx] = NUL; - return string; -} - -/// Try translating a <> name ("keycode"). -/// -/// @param[in,out] srcp Source from which <> are translated. Is advanced to -/// after the <> name if there is a match. -/// @param[in] src_len Length of the srcp. -/// @param[out] dst Location where translation result will be kept. It must -// be at least 19 bytes per "" form. -/// @param[in] flags FSK_ values -/// @param[in] escape_ks escape K_SPECIAL bytes in the character -/// @param[out] did_simplify found , etc. -/// -/// @return Number of characters added to dst, zero for no match. -unsigned int trans_special(const char_u **const srcp, const size_t src_len, char_u *const dst, - const int flags, const bool escape_ks, bool *const did_simplify) - FUNC_ATTR_NONNULL_ARG(1, 3) FUNC_ATTR_WARN_UNUSED_RESULT -{ - int modifiers = 0; - int key = find_special_key(srcp, src_len, &modifiers, flags, did_simplify); - if (key == 0) { - return 0; - } - - return special_to_buf(key, modifiers, escape_ks, dst); -} - -/// Put the character sequence for "key" with "modifiers" into "dst" and return -/// the resulting length. -/// When "escape_ks" is true escape K_SPECIAL bytes in the character. -/// The sequence is not NUL terminated. -/// This is how characters in a string are encoded. -unsigned int special_to_buf(int key, int modifiers, bool escape_ks, char_u *dst) -{ - unsigned int dlen = 0; - - // Put the appropriate modifier in a string. - if (modifiers != 0) { - dst[dlen++] = K_SPECIAL; - dst[dlen++] = KS_MODIFIER; - dst[dlen++] = (char_u)modifiers; - } - - if (IS_SPECIAL(key)) { - dst[dlen++] = K_SPECIAL; - dst[dlen++] = (char_u)KEY2TERMCAP0(key); - dst[dlen++] = KEY2TERMCAP1(key); - } else if (escape_ks) { - char_u *after = add_char2buf(key, dst + dlen); - assert(after >= dst && (uintmax_t)(after - dst) <= UINT_MAX); - dlen = (unsigned int)(after - dst); - } else { - dlen += (unsigned int)utf_char2bytes(key, (char *)dst + dlen); - } - - return dlen; -} - -/// Try translating a <> name -/// -/// @param[in,out] srcp Translated <> name. Is advanced to after the <> name. -/// @param[in] src_len srcp length. -/// @param[out] modp Location where information about modifiers is saved. -/// @param[in] flags FSK_ values -/// @param[out] did_simplify FSK_SIMPLIFY and found , etc. -/// -/// @return Key and modifiers or 0 if there is no match. -int find_special_key(const char_u **const srcp, const size_t src_len, int *const modp, - const int flags, bool *const did_simplify) - FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1, 3) -{ - const char_u *last_dash; - const char_u *end_of_name; - const char_u *src; - const char_u *bp; - const char_u *const end = *srcp + src_len - 1; - const bool in_string = flags & FSK_IN_STRING; - int modifiers; - int bit; - int key; - uvarnumber_T n; - int l; - - if (src_len == 0) { - return 0; - } - - src = *srcp; - if (src[0] != '<') { - return 0; - } - if (src[1] == '*') { // <*xxx>: do not simplify - src++; - } - - // Find end of modifier list - last_dash = src; - for (bp = src + 1; bp <= end && (*bp == '-' || ascii_isident(*bp)); bp++) { - if (*bp == '-') { - last_dash = bp; - if (bp + 1 <= end) { - l = utfc_ptr2len_len(bp + 1, (int)(end - bp) + 1); - // Anything accepted, like . - // or are not special in strings as " is - // the string delimiter. With a backslash it works: - if (end - bp > l && !(in_string && bp[1] == '"') && bp[l + 1] == '>') { - bp += l; - } else if (end - bp > 2 && in_string && bp[1] == '\\' - && bp[2] == '"' && bp[3] == '>') { - bp += 2; - } - } - } - if (end - bp > 3 && bp[0] == 't' && bp[1] == '_') { - bp += 3; // skip t_xx, xx may be '-' or '>' - } else if (end - bp > 4 && STRNICMP(bp, "char-", 5) == 0) { - vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, true); - if (l == 0) { - emsg(_(e_invarg)); - return 0; - } - bp += l + 5; - break; - } - } - - if (bp <= end && *bp == '>') { // found matching '>' - end_of_name = bp + 1; - - // Which modifiers are given? - modifiers = 0x0; - for (bp = src + 1; bp < last_dash; bp++) { - if (*bp != '-') { - bit = name_to_mod_mask(*bp); - if (bit == 0x0) { - break; // Illegal modifier name - } - modifiers |= bit; - } - } - - // Legal modifier name. - if (bp >= last_dash) { - if (STRNICMP(last_dash + 1, "char-", 5) == 0 - && ascii_isdigit(last_dash[6])) { - // or or - vim_str2nr(last_dash + 6, NULL, &l, STR2NR_ALL, NULL, &n, 0, true); - if (l == 0) { - emsg(_(e_invarg)); - return 0; - } - key = (int)n; - } else { - int off = 1; - - // Modifier with single letter, or special key name. - if (in_string && last_dash[1] == '\\' && last_dash[2] == '"') { - // Special case for a double-quoted string - off = l = 2; - } else { - l = utfc_ptr2len((char *)last_dash + 1); - } - if (modifiers != 0 && last_dash[l + 1] == '>') { - key = utf_ptr2char((char *)last_dash + off); - } else { - key = get_special_key_code(last_dash + off); - if (!(flags & FSK_KEEP_X_KEY)) { - key = handle_x_keys(key); - } - } - } - - // get_special_key_code() may return NUL for invalid - // special key name. - if (key != NUL) { - // Only use a modifier when there is no special key code that - // includes the modifier. - key = simplify_key(key, &modifiers); - - if (!(flags & FSK_KEYCODE)) { - // don't want keycode, use single byte code - if (key == K_BS) { - key = BS; - } else if (key == K_DEL || key == K_KDEL) { - key = DEL; - } - } - - // Normal Key with modifier: - // Try to make a single byte code (except for Alt/Meta modifiers). - if (!IS_SPECIAL(key)) { - key = extract_modifiers(key, &modifiers, flags & FSK_SIMPLIFY, did_simplify); - } - - *modp = modifiers; - *srcp = end_of_name; - return key; - } // else { ELOG("unknown key: '%s'", src); } - } - } - return 0; -} - -/// Try to include modifiers (except alt/meta) in the key. -/// Changes "Shift-a" to 'A', "Ctrl-@" to , etc. -/// @param[in] simplify if false, don't do Ctrl -/// @param[out] did_simplify set when it is not NULL and "simplify" is true and -/// Ctrl is removed from modifiers -static int extract_modifiers(int key, int *modp, const bool simplify, bool *const did_simplify) -{ - int modifiers = *modp; - - // Command-key and ctrl are special - if (!(modifiers & MOD_MASK_CMD) && !(modifiers & MOD_MASK_CTRL)) { - if ((modifiers & MOD_MASK_SHIFT) && ASCII_ISALPHA(key)) { - key = TOUPPER_ASC(key); - modifiers &= ~MOD_MASK_SHIFT; - } - } - // and mean the same thing, always use "H" - if ((modifiers & MOD_MASK_CTRL) && ASCII_ISALPHA(key)) { - key = TOUPPER_ASC(key); - } - if (simplify && (modifiers & MOD_MASK_CTRL) - && ((key >= '?' && key <= '_') || ASCII_ISALPHA(key))) { - key = CTRL_CHR(key); - modifiers &= ~MOD_MASK_CTRL; - if (key == NUL) { // is - key = K_ZERO; - } - if (did_simplify != NULL) { - *did_simplify = true; - } - } - - *modp = modifiers; - return key; -} - -/* - * Try to find key "c" in the special key table. - * Return the index when found, -1 when not found. - */ -int find_special_key_in_table(int c) -{ - int i; - - for (i = 0; key_names_table[i].name != NULL; i++) { - if (c == key_names_table[i].key) { - break; - } - } - if (key_names_table[i].name == NULL) { - i = -1; - } - return i; -} - -/// Find the special key with the given name -/// -/// @param[in] name Name of the special. Does not have to end with NUL, it is -/// assumed to end before the first non-idchar. If name starts -/// with "t_" the next two characters are interpreted as -/// a termcap name. -/// -/// @return Key code or 0 if not found. -int get_special_key_code(const char_u *name) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT -{ - for (int i = 0; key_names_table[i].name != NULL; i++) { - const char *const table_name = key_names_table[i].name; - int j; - for (j = 0; ascii_isident(name[j]) && table_name[j] != NUL; j++) { - if (TOLOWER_ASC(table_name[j]) != TOLOWER_ASC(name[j])) { - break; - } - } - if (!ascii_isident(name[j]) && table_name[j] == NUL) { - return key_names_table[i].key; - } - } - - return 0; -} - -/* - * Look up the given mouse code to return the relevant information in the other - * arguments. Return which button is down or was released. - */ -int get_mouse_button(int code, bool *is_click, bool *is_drag) -{ - int i; - - for (i = 0; mouse_table[i].pseudo_code; i++) { - if (code == mouse_table[i].pseudo_code) { - *is_click = mouse_table[i].is_click; - *is_drag = mouse_table[i].is_drag; - return mouse_table[i].button; - } - } - return 0; // Shouldn't get here -} - -/// Replace any terminal code strings with the equivalent internal representation. -/// -/// Used for the "from" and "to" part of a mapping, and the "to" part of a menu command. -/// Any strings like "" are also replaced, unless `special` is false. -/// K_SPECIAL by itself is replaced by K_SPECIAL KS_SPECIAL KE_FILLER. -/// -/// When "flags" has REPTERM_FROM_PART, trailing is included, otherwise it is removed (to make -/// ":map xx ^V" map xx to nothing). When cpo_flags contains FLAG_CPO_BSLASH, a backslash can be -/// used in place of . All other characters are removed. -/// -/// @param[in] from What characters to replace. -/// @param[in] from_len Length of the "from" argument. -/// @param[out] bufp Location where results were saved in case of success (allocated). -/// Will be set to NULL in case of failure. -/// @param[in] flags REPTERM_FROM_PART see above -/// REPTERM_DO_LT also translate -/// REPTERM_NO_SPECIAL do not accept notation -/// REPTERM_NO_SIMPLIFY do not simplify into 0x08, etc. -/// @param[out] did_simplify set when some code was simplied, unless it is NULL. -/// @param[in] cpo_flags Relevant flags derived from p_cpo, see CPO_TO_CPO_FLAGS. -/// -/// @return Pointer to an allocated memory, which is also saved to "bufp". -char *replace_termcodes(const char *const from, const size_t from_len, char **const bufp, - const int flags, bool *const did_simplify, const int cpo_flags) - FUNC_ATTR_NONNULL_ARG(1, 3) -{ - ssize_t i; - size_t slen; - char_u key; - size_t dlen = 0; - const char_u *src; - const char_u *const end = (char_u *)from + from_len - 1; - char_u *result; // buffer for resulting string - - const bool do_backslash = !(cpo_flags & FLAG_CPO_BSLASH); // backslash is a special character - const bool do_special = !(flags & REPTERM_NO_SPECIAL); - - // Allocate space for the translation. Worst case a single character is - // replaced by 6 bytes (shifted special key), plus a NUL at the end. - const size_t buf_len = from_len * 6 + 1; - result = xmalloc(buf_len); - - src = (char_u *)from; - - // Check for #n at start only: function key n - if ((flags & REPTERM_FROM_PART) && from_len > 1 && src[0] == '#' - && ascii_isdigit(src[1])) { // function key - result[dlen++] = K_SPECIAL; - result[dlen++] = 'k'; - if (src[1] == '0') { - result[dlen++] = ';'; // #0 is F10 is "k;" - } else { - result[dlen++] = src[1]; // #3 is F3 is "k3" - } - src += 2; - } - - // Copy each byte from *from to result[dlen] - while (src <= end) { - // Check for special <> keycodes, like "" - if (do_special && ((flags & REPTERM_DO_LT) || ((end - src) >= 3 - && STRNCMP(src, "", 4) != 0))) { - // Replace by K_SNR _. - // (room: 5 * 6 = 30 bytes; needed: 3 + + 1 <= 14) - if (end - src >= 4 && STRNICMP(src, "", 5) == 0) { - if (current_sctx.sc_sid <= 0) { - emsg(_(e_usingsid)); - } else { - src += 5; - result[dlen++] = K_SPECIAL; - result[dlen++] = (int)KS_EXTRA; - result[dlen++] = (int)KE_SNR; - snprintf((char *)result + dlen, buf_len - dlen, "%" PRId64, - (int64_t)current_sctx.sc_sid); - dlen += STRLEN(result + dlen); - result[dlen++] = '_'; - continue; - } - } - - slen = trans_special(&src, (size_t)(end - src) + 1, result + dlen, - FSK_KEYCODE | ((flags & REPTERM_NO_SIMPLIFY) ? 0 : FSK_SIMPLIFY), - true, did_simplify); - if (slen) { - dlen += slen; - continue; - } - } - - if (do_special) { - char_u *p, *s, len; - - // Replace by the value of "mapleader". - // Replace by the value of "maplocalleader". - // If "mapleader" or "maplocalleader" isn't set use a backslash. - if (end - src >= 7 && STRNICMP(src, "", 8) == 0) { - len = 8; - p = get_var_value("g:mapleader"); - } else if (end - src >= 12 && STRNICMP(src, "", 13) == 0) { - len = 13; - p = get_var_value("g:maplocalleader"); - } else { - len = 0; - p = NULL; - } - - if (len != 0) { - // Allow up to 8 * 6 characters for "mapleader". - if (p == NULL || *p == NUL || STRLEN(p) > 8 * 6) { - s = (char_u *)"\\"; - } else { - s = p; - } - while (*s != NUL) { - result[dlen++] = *s++; - } - src += len; - continue; - } - } - - // Remove CTRL-V and ignore the next character. - // For "from" side the CTRL-V at the end is included, for the "to" - // part it is removed. - // If 'cpoptions' does not contain 'B', also accept a backslash. - key = *src; - if (key == Ctrl_V || (do_backslash && key == '\\')) { - src++; // skip CTRL-V or backslash - if (src > end) { - if (flags & REPTERM_FROM_PART) { - result[dlen++] = key; - } - break; - } - } - - // skip multibyte char correctly - for (i = utfc_ptr2len_len(src, (int)(end - src) + 1); i > 0; i--) { - // If the character is K_SPECIAL, replace it with K_SPECIAL - // KS_SPECIAL KE_FILLER. - if (*src == K_SPECIAL) { - result[dlen++] = K_SPECIAL; - result[dlen++] = KS_SPECIAL; - result[dlen++] = KE_FILLER; - } else { - result[dlen++] = *src; - } - ++src; - } - } - result[dlen] = NUL; - - *bufp = xrealloc(result, dlen + 1); - - return *bufp; -} - -/// Logs a single key as a human-readable keycode. -void log_key(int log_level, int key) -{ - if (log_level < MIN_LOG_LEVEL) { - return; - } - char *keyname = key == K_EVENT - ? "K_EVENT" - : (char *)get_special_key_name(key, mod_mask); - LOG(log_level, "input: %s", keyname); -} diff --git a/src/nvim/keymap.h b/src/nvim/keymap.h deleted file mode 100644 index 9febd472f9..0000000000 --- a/src/nvim/keymap.h +++ /dev/null @@ -1,529 +0,0 @@ -#ifndef NVIM_KEYMAP_H -#define NVIM_KEYMAP_H - -#include "nvim/strings.h" - -/* - * Keycode definitions for special keys. - * - * Any special key code sequences are replaced by these codes. - */ - -// -// For MS-DOS some keys produce codes larger than 0xff. They are split into two -// chars, the first one is K_NUL. -// -#define K_NUL (0xce) // for MS-DOS: special key follows - -/* - * K_SPECIAL is the first byte of a special key code and is always followed by - * two bytes. - * The second byte can have any value. ASCII is used for normal termcap - * entries, 0x80 and higher for special keys, see below. - * The third byte is guaranteed to be between 0x02 and 0x7f. - */ - -#define K_SPECIAL (0x80) - -/* - * Positive characters are "normal" characters. - * Negative characters are special key codes. Only characters below -0x200 - * are used to so that the absolute value can't be mistaken for a single-byte - * character. - */ -#define IS_SPECIAL(c) ((c) < 0) - -/* - * Characters 0x0100 - 0x01ff have a special meaning for abbreviations. - * Multi-byte characters also have ABBR_OFF added, thus are above 0x0200. - */ -#define ABBR_OFF 0x100 - -/* - * NUL cannot be in the input string, therefore it is replaced by - * K_SPECIAL KS_ZERO KE_FILLER - */ -#define KS_ZERO 255 - -/* - * K_SPECIAL cannot be in the input string, therefore it is replaced by - * K_SPECIAL KS_SPECIAL KE_FILLER - */ -#define KS_SPECIAL 254 - -/* - * KS_EXTRA is used for keys that have no termcap name - * K_SPECIAL KS_EXTRA KE_xxx - */ -#define KS_EXTRA 253 - -/* - * KS_MODIFIER is used when a modifier is given for a (special) key - * K_SPECIAL KS_MODIFIER bitmask - */ -#define KS_MODIFIER 252 - -/* - * These are used for the GUI - * K_SPECIAL KS_xxx KE_FILLER - */ -#define KS_MOUSE 251 -#define KS_MENU 250 -#define KS_VER_SCROLLBAR 249 -#define KS_HOR_SCROLLBAR 248 - -/* - * Used for switching Select mode back on after a mapping or menu. - */ -#define KS_SELECT 245 -#define K_SELECT_STRING (char_u *)"\200\365X" - -// Used a termcap entry that produces a normal character. -#define KS_KEY 242 - -// Used for click in a tab pages label. -#define KS_TABLINE 240 - -// Used for menu in a tab pages line. -#define KS_TABMENU 239 - -/* - * Filler used after KS_SPECIAL and others - */ -#define KE_FILLER ('X') - -/* - * translation of three byte code "K_SPECIAL a b" into int "K_xxx" and back - */ -#define TERMCAP2KEY(a, b) (-((a) + ((int)(b) << 8))) -#define KEY2TERMCAP0(x) ((-(x)) & 0xff) -#define KEY2TERMCAP1(x) (((unsigned)(-(x)) >> 8) & 0xff) - -/* - * get second or third byte when translating special key code into three bytes - */ -#define K_SECOND(c) ((c) == K_SPECIAL ? KS_SPECIAL : (c) == \ - NUL ? KS_ZERO : KEY2TERMCAP0(c)) - -#define K_THIRD(c) (((c) == K_SPECIAL || (c) == \ - NUL) ? KE_FILLER : KEY2TERMCAP1(c)) - -/* - * get single int code from second byte after K_SPECIAL - */ -#define TO_SPECIAL(a, b) ((a) == KS_SPECIAL ? K_SPECIAL : (a) == \ - KS_ZERO ? K_ZERO : TERMCAP2KEY(a, b)) - -// Codes for keys that do not have a termcap name. -// The numbers are fixed to make sure that recorded key sequences remain valid. -// Add new entries at the end, not halfway. -// -// K_SPECIAL KS_EXTRA KE_xxx -// -// Entries must be in the range 0x02-0x7f (see comment at K_SPECIAL). -enum key_extra { - KE_S_UP = 4, // shift-up - KE_S_DOWN = 5, // shift-down - - KE_S_F1 = 6, // shifted function keys - KE_S_F2 = 7, - KE_S_F3 = 8, - KE_S_F4 = 9, - KE_S_F5 = 10, - KE_S_F6 = 11, - KE_S_F7 = 12, - KE_S_F8 = 13, - KE_S_F9 = 14, - KE_S_F10 = 15, - - KE_S_F11 = 16, - KE_S_F12 = 17, - KE_S_F13 = 18, - KE_S_F14 = 19, - KE_S_F15 = 20, - KE_S_F16 = 21, - KE_S_F17 = 22, - KE_S_F18 = 23, - KE_S_F19 = 24, - KE_S_F20 = 25, - - KE_S_F21 = 26, - KE_S_F22 = 27, - KE_S_F23 = 28, - KE_S_F24 = 29, - KE_S_F25 = 30, - KE_S_F26 = 31, - KE_S_F27 = 32, - KE_S_F28 = 33, - KE_S_F29 = 34, - KE_S_F30 = 35, - - KE_S_F31 = 36, - KE_S_F32 = 37, - KE_S_F33 = 38, - KE_S_F34 = 39, - KE_S_F35 = 40, - KE_S_F36 = 41, - KE_S_F37 = 42, - - KE_MOUSE = 43, // mouse event start - - // Symbols for pseudo keys which are translated from the real key symbols - // above. - KE_LEFTMOUSE = 44, // Left mouse button click - KE_LEFTDRAG = 45, // Drag with left mouse button down - KE_LEFTRELEASE = 46, // Left mouse button release - KE_MIDDLEMOUSE = 47, // Middle mouse button click - KE_MIDDLEDRAG = 48, // Drag with middle mouse button down - KE_MIDDLERELEASE = 49, // Middle mouse button release - KE_RIGHTMOUSE = 50, // Right mouse button click - KE_RIGHTDRAG = 51, // Drag with right mouse button down - KE_RIGHTRELEASE = 52, // Right mouse button release - - KE_IGNORE = 53, // Ignored mouse drag/release - - KE_TAB = 54, // unshifted TAB key - KE_S_TAB_OLD = 55, // shifted TAB key (no longer used) - - // , KE_SNIFF_UNUSED = 56 // obsolete - KE_XF1 = 57, // extra vt100 function keys for xterm - KE_XF2 = 58, - KE_XF3 = 59, - KE_XF4 = 60, - KE_XEND = 61, // extra (vt100) end key for xterm - KE_ZEND = 62, // extra (vt100) end key for xterm - KE_XHOME = 63, // extra (vt100) home key for xterm - KE_ZHOME = 64, // extra (vt100) home key for xterm - KE_XUP = 65, // extra vt100 cursor keys for xterm - KE_XDOWN = 66, - KE_XLEFT = 67, - KE_XRIGHT = 68, - - KE_LEFTMOUSE_NM = 69, // non-mappable Left mouse button click - KE_LEFTRELEASE_NM = 70, // non-mappable left mouse button release - - KE_S_XF1 = 71, // vt100 shifted function keys for xterm - KE_S_XF2 = 72, - KE_S_XF3 = 73, - KE_S_XF4 = 74, - - // NOTE: The scroll wheel events are inverted: i.e. UP is the same as - // moving the actual scroll wheel down, LEFT is the same as moving the - // scroll wheel right. - KE_MOUSEDOWN = 75, // scroll wheel pseudo-button Down - KE_MOUSEUP = 76, // scroll wheel pseudo-button Up - KE_MOUSELEFT = 77, // scroll wheel pseudo-button Left - KE_MOUSERIGHT = 78, // scroll wheel pseudo-button Right - - KE_KINS = 79, // keypad Insert key - KE_KDEL = 80, // keypad Delete key - - // KE_CSI = 81, // Nvim doesn't need escaping CSI - KE_SNR = 82, // - KE_PLUG = 83, // - KE_CMDWIN = 84, // open command-line window from Command-line Mode - - KE_C_LEFT = 85, // control-left - KE_C_RIGHT = 86, // control-right - KE_C_HOME = 87, // control-home - KE_C_END = 88, // control-end - - KE_X1MOUSE = 89, // X1/X2 mouse-buttons - KE_X1DRAG = 90, - KE_X1RELEASE = 91, - KE_X2MOUSE = 92, - KE_X2DRAG = 93, - KE_X2RELEASE = 94, - - KE_DROP = 95, // DnD data is available - // , KE_CURSORHOLD = 96 // CursorHold event - KE_NOP = 97, // no-op: does nothing - // , KE_FOCUSGAINED = 98 // focus gained - // , KE_FOCUSLOST = 99 // focus lost - KE_MOUSEMOVE = 100, // mouse moved with no button down - // , KE_CANCEL = 101 // return from vgetc - KE_EVENT = 102, // event - KE_LUA = 103, // lua special key - KE_COMMAND = 104, // special key -}; - -/* - * the three byte codes are replaced with the following int when using vgetc() - */ -#define K_ZERO TERMCAP2KEY(KS_ZERO, KE_FILLER) - -#define K_UP TERMCAP2KEY('k', 'u') -#define K_KUP TERMCAP2KEY('K', 'u') // keypad up -#define K_DOWN TERMCAP2KEY('k', 'd') -#define K_KDOWN TERMCAP2KEY('K', 'd') // keypad down -#define K_LEFT TERMCAP2KEY('k', 'l') -#define K_KLEFT TERMCAP2KEY('K', 'l') // keypad left -#define K_RIGHT TERMCAP2KEY('k', 'r') -#define K_KRIGHT TERMCAP2KEY('K', 'r') // keypad right -#define K_S_UP TERMCAP2KEY(KS_EXTRA, KE_S_UP) -#define K_S_DOWN TERMCAP2KEY(KS_EXTRA, KE_S_DOWN) -#define K_S_LEFT TERMCAP2KEY('#', '4') -#define K_C_LEFT TERMCAP2KEY(KS_EXTRA, KE_C_LEFT) -#define K_S_RIGHT TERMCAP2KEY('%', 'i') -#define K_C_RIGHT TERMCAP2KEY(KS_EXTRA, KE_C_RIGHT) -#define K_S_HOME TERMCAP2KEY('#', '2') -#define K_C_HOME TERMCAP2KEY(KS_EXTRA, KE_C_HOME) -#define K_S_END TERMCAP2KEY('*', '7') -#define K_C_END TERMCAP2KEY(KS_EXTRA, KE_C_END) -#define K_TAB TERMCAP2KEY(KS_EXTRA, KE_TAB) -#define K_S_TAB TERMCAP2KEY('k', 'B') - -// extra set of function keys F1-F4, for vt100 compatible xterm -#define K_XF1 TERMCAP2KEY(KS_EXTRA, KE_XF1) -#define K_XF2 TERMCAP2KEY(KS_EXTRA, KE_XF2) -#define K_XF3 TERMCAP2KEY(KS_EXTRA, KE_XF3) -#define K_XF4 TERMCAP2KEY(KS_EXTRA, KE_XF4) - -// extra set of cursor keys for vt100 compatible xterm -#define K_XUP TERMCAP2KEY(KS_EXTRA, KE_XUP) -#define K_XDOWN TERMCAP2KEY(KS_EXTRA, KE_XDOWN) -#define K_XLEFT TERMCAP2KEY(KS_EXTRA, KE_XLEFT) -#define K_XRIGHT TERMCAP2KEY(KS_EXTRA, KE_XRIGHT) - -#define K_F1 TERMCAP2KEY('k', '1') // function keys -#define K_F2 TERMCAP2KEY('k', '2') -#define K_F3 TERMCAP2KEY('k', '3') -#define K_F4 TERMCAP2KEY('k', '4') -#define K_F5 TERMCAP2KEY('k', '5') -#define K_F6 TERMCAP2KEY('k', '6') -#define K_F7 TERMCAP2KEY('k', '7') -#define K_F8 TERMCAP2KEY('k', '8') -#define K_F9 TERMCAP2KEY('k', '9') -#define K_F10 TERMCAP2KEY('k', ';') - -#define K_F11 TERMCAP2KEY('F', '1') -#define K_F12 TERMCAP2KEY('F', '2') -#define K_F13 TERMCAP2KEY('F', '3') -#define K_F14 TERMCAP2KEY('F', '4') -#define K_F15 TERMCAP2KEY('F', '5') -#define K_F16 TERMCAP2KEY('F', '6') -#define K_F17 TERMCAP2KEY('F', '7') -#define K_F18 TERMCAP2KEY('F', '8') -#define K_F19 TERMCAP2KEY('F', '9') -#define K_F20 TERMCAP2KEY('F', 'A') - -#define K_F21 TERMCAP2KEY('F', 'B') -#define K_F22 TERMCAP2KEY('F', 'C') -#define K_F23 TERMCAP2KEY('F', 'D') -#define K_F24 TERMCAP2KEY('F', 'E') -#define K_F25 TERMCAP2KEY('F', 'F') -#define K_F26 TERMCAP2KEY('F', 'G') -#define K_F27 TERMCAP2KEY('F', 'H') -#define K_F28 TERMCAP2KEY('F', 'I') -#define K_F29 TERMCAP2KEY('F', 'J') -#define K_F30 TERMCAP2KEY('F', 'K') - -#define K_F31 TERMCAP2KEY('F', 'L') -#define K_F32 TERMCAP2KEY('F', 'M') -#define K_F33 TERMCAP2KEY('F', 'N') -#define K_F34 TERMCAP2KEY('F', 'O') -#define K_F35 TERMCAP2KEY('F', 'P') -#define K_F36 TERMCAP2KEY('F', 'Q') -#define K_F37 TERMCAP2KEY('F', 'R') -#define K_F38 TERMCAP2KEY('F', 'S') -#define K_F39 TERMCAP2KEY('F', 'T') -#define K_F40 TERMCAP2KEY('F', 'U') - -#define K_F41 TERMCAP2KEY('F', 'V') -#define K_F42 TERMCAP2KEY('F', 'W') -#define K_F43 TERMCAP2KEY('F', 'X') -#define K_F44 TERMCAP2KEY('F', 'Y') -#define K_F45 TERMCAP2KEY('F', 'Z') -#define K_F46 TERMCAP2KEY('F', 'a') -#define K_F47 TERMCAP2KEY('F', 'b') -#define K_F48 TERMCAP2KEY('F', 'c') -#define K_F49 TERMCAP2KEY('F', 'd') -#define K_F50 TERMCAP2KEY('F', 'e') - -#define K_F51 TERMCAP2KEY('F', 'f') -#define K_F52 TERMCAP2KEY('F', 'g') -#define K_F53 TERMCAP2KEY('F', 'h') -#define K_F54 TERMCAP2KEY('F', 'i') -#define K_F55 TERMCAP2KEY('F', 'j') -#define K_F56 TERMCAP2KEY('F', 'k') -#define K_F57 TERMCAP2KEY('F', 'l') -#define K_F58 TERMCAP2KEY('F', 'm') -#define K_F59 TERMCAP2KEY('F', 'n') -#define K_F60 TERMCAP2KEY('F', 'o') - -#define K_F61 TERMCAP2KEY('F', 'p') -#define K_F62 TERMCAP2KEY('F', 'q') -#define K_F63 TERMCAP2KEY('F', 'r') - -// extra set of shifted function keys F1-F4, for vt100 compatible xterm -#define K_S_XF1 TERMCAP2KEY(KS_EXTRA, KE_S_XF1) -#define K_S_XF2 TERMCAP2KEY(KS_EXTRA, KE_S_XF2) -#define K_S_XF3 TERMCAP2KEY(KS_EXTRA, KE_S_XF3) -#define K_S_XF4 TERMCAP2KEY(KS_EXTRA, KE_S_XF4) - -#define K_S_F1 TERMCAP2KEY(KS_EXTRA, KE_S_F1) // shifted func. keys -#define K_S_F2 TERMCAP2KEY(KS_EXTRA, KE_S_F2) -#define K_S_F3 TERMCAP2KEY(KS_EXTRA, KE_S_F3) -#define K_S_F4 TERMCAP2KEY(KS_EXTRA, KE_S_F4) -#define K_S_F5 TERMCAP2KEY(KS_EXTRA, KE_S_F5) -#define K_S_F6 TERMCAP2KEY(KS_EXTRA, KE_S_F6) -#define K_S_F7 TERMCAP2KEY(KS_EXTRA, KE_S_F7) -#define K_S_F8 TERMCAP2KEY(KS_EXTRA, KE_S_F8) -#define K_S_F9 TERMCAP2KEY(KS_EXTRA, KE_S_F9) -#define K_S_F10 TERMCAP2KEY(KS_EXTRA, KE_S_F10) - -#define K_S_F11 TERMCAP2KEY(KS_EXTRA, KE_S_F11) -#define K_S_F12 TERMCAP2KEY(KS_EXTRA, KE_S_F12) -// K_S_F13 to K_S_F37 are currently not used - -#define K_HELP TERMCAP2KEY('%', '1') -#define K_UNDO TERMCAP2KEY('&', '8') - -#define K_BS TERMCAP2KEY('k', 'b') - -#define K_INS TERMCAP2KEY('k', 'I') -#define K_KINS TERMCAP2KEY(KS_EXTRA, KE_KINS) -#define K_DEL TERMCAP2KEY('k', 'D') -#define K_KDEL TERMCAP2KEY(KS_EXTRA, KE_KDEL) -#define K_HOME TERMCAP2KEY('k', 'h') -#define K_KHOME TERMCAP2KEY('K', '1') // keypad home (upper left) -#define K_XHOME TERMCAP2KEY(KS_EXTRA, KE_XHOME) -#define K_ZHOME TERMCAP2KEY(KS_EXTRA, KE_ZHOME) -#define K_END TERMCAP2KEY('@', '7') -#define K_KEND TERMCAP2KEY('K', '4') // keypad end (lower left) -#define K_XEND TERMCAP2KEY(KS_EXTRA, KE_XEND) -#define K_ZEND TERMCAP2KEY(KS_EXTRA, KE_ZEND) -#define K_PAGEUP TERMCAP2KEY('k', 'P') -#define K_PAGEDOWN TERMCAP2KEY('k', 'N') -#define K_KPAGEUP TERMCAP2KEY('K', '3') // keypad pageup (upper R.) -#define K_KPAGEDOWN TERMCAP2KEY('K', '5') // keypad pagedown (lower R.) -#define K_KORIGIN TERMCAP2KEY('K', '2') // keypad center - -#define K_KPLUS TERMCAP2KEY('K', '6') // keypad plus -#define K_KMINUS TERMCAP2KEY('K', '7') // keypad minus -#define K_KDIVIDE TERMCAP2KEY('K', '8') // keypad / -#define K_KMULTIPLY TERMCAP2KEY('K', '9') // keypad * -#define K_KENTER TERMCAP2KEY('K', 'A') // keypad Enter -#define K_KPOINT TERMCAP2KEY('K', 'B') // keypad . or , - -#define K_K0 TERMCAP2KEY('K', 'C') // keypad 0 -#define K_K1 TERMCAP2KEY('K', 'D') // keypad 1 -#define K_K2 TERMCAP2KEY('K', 'E') // keypad 2 -#define K_K3 TERMCAP2KEY('K', 'F') // keypad 3 -#define K_K4 TERMCAP2KEY('K', 'G') // keypad 4 -#define K_K5 TERMCAP2KEY('K', 'H') // keypad 5 -#define K_K6 TERMCAP2KEY('K', 'I') // keypad 6 -#define K_K7 TERMCAP2KEY('K', 'J') // keypad 7 -#define K_K8 TERMCAP2KEY('K', 'K') // keypad 8 -#define K_K9 TERMCAP2KEY('K', 'L') // keypad 9 - -#define K_KCOMMA TERMCAP2KEY('K', 'M') // keypad comma -#define K_KEQUAL TERMCAP2KEY('K', 'N') // keypad equal - -#define K_MOUSE TERMCAP2KEY(KS_MOUSE, KE_FILLER) -#define K_MENU TERMCAP2KEY(KS_MENU, KE_FILLER) -#define K_VER_SCROLLBAR TERMCAP2KEY(KS_VER_SCROLLBAR, KE_FILLER) -#define K_HOR_SCROLLBAR TERMCAP2KEY(KS_HOR_SCROLLBAR, KE_FILLER) - -#define K_SELECT TERMCAP2KEY(KS_SELECT, KE_FILLER) - -#define K_TABLINE TERMCAP2KEY(KS_TABLINE, KE_FILLER) -#define K_TABMENU TERMCAP2KEY(KS_TABMENU, KE_FILLER) - -/* - * Symbols for pseudo keys which are translated from the real key symbols - * above. - */ -#define K_LEFTMOUSE TERMCAP2KEY(KS_EXTRA, KE_LEFTMOUSE) -#define K_LEFTMOUSE_NM TERMCAP2KEY(KS_EXTRA, KE_LEFTMOUSE_NM) -#define K_LEFTDRAG TERMCAP2KEY(KS_EXTRA, KE_LEFTDRAG) -#define K_LEFTRELEASE TERMCAP2KEY(KS_EXTRA, KE_LEFTRELEASE) -#define K_LEFTRELEASE_NM TERMCAP2KEY(KS_EXTRA, KE_LEFTRELEASE_NM) -#define K_MOUSEMOVE TERMCAP2KEY(KS_EXTRA, KE_MOUSEMOVE) -#define K_MIDDLEMOUSE TERMCAP2KEY(KS_EXTRA, KE_MIDDLEMOUSE) -#define K_MIDDLEDRAG TERMCAP2KEY(KS_EXTRA, KE_MIDDLEDRAG) -#define K_MIDDLERELEASE TERMCAP2KEY(KS_EXTRA, KE_MIDDLERELEASE) -#define K_RIGHTMOUSE TERMCAP2KEY(KS_EXTRA, KE_RIGHTMOUSE) -#define K_RIGHTDRAG TERMCAP2KEY(KS_EXTRA, KE_RIGHTDRAG) -#define K_RIGHTRELEASE TERMCAP2KEY(KS_EXTRA, KE_RIGHTRELEASE) -#define K_X1MOUSE TERMCAP2KEY(KS_EXTRA, KE_X1MOUSE) -#define K_X1MOUSE TERMCAP2KEY(KS_EXTRA, KE_X1MOUSE) -#define K_X1DRAG TERMCAP2KEY(KS_EXTRA, KE_X1DRAG) -#define K_X1RELEASE TERMCAP2KEY(KS_EXTRA, KE_X1RELEASE) -#define K_X2MOUSE TERMCAP2KEY(KS_EXTRA, KE_X2MOUSE) -#define K_X2DRAG TERMCAP2KEY(KS_EXTRA, KE_X2DRAG) -#define K_X2RELEASE TERMCAP2KEY(KS_EXTRA, KE_X2RELEASE) - -#define K_IGNORE TERMCAP2KEY(KS_EXTRA, KE_IGNORE) -#define K_NOP TERMCAP2KEY(KS_EXTRA, KE_NOP) - -#define K_MOUSEDOWN TERMCAP2KEY(KS_EXTRA, KE_MOUSEDOWN) -#define K_MOUSEUP TERMCAP2KEY(KS_EXTRA, KE_MOUSEUP) -#define K_MOUSELEFT TERMCAP2KEY(KS_EXTRA, KE_MOUSELEFT) -#define K_MOUSERIGHT TERMCAP2KEY(KS_EXTRA, KE_MOUSERIGHT) - -#define K_SNR TERMCAP2KEY(KS_EXTRA, KE_SNR) -#define K_PLUG TERMCAP2KEY(KS_EXTRA, KE_PLUG) -#define K_CMDWIN TERMCAP2KEY(KS_EXTRA, KE_CMDWIN) - -#define K_DROP TERMCAP2KEY(KS_EXTRA, KE_DROP) - -#define K_EVENT TERMCAP2KEY(KS_EXTRA, KE_EVENT) -#define K_COMMAND TERMCAP2KEY(KS_EXTRA, KE_COMMAND) -#define K_LUA TERMCAP2KEY(KS_EXTRA, KE_LUA) - -// Bits for modifier mask -// 0x01 cannot be used, because the modifier must be 0x02 or higher -#define MOD_MASK_SHIFT 0x02 -#define MOD_MASK_CTRL 0x04 -#define MOD_MASK_ALT 0x08 // aka META -#define MOD_MASK_META 0x10 // META when it's different from ALT -#define MOD_MASK_2CLICK 0x20 // use MOD_MASK_MULTI_CLICK -#define MOD_MASK_3CLICK 0x40 // use MOD_MASK_MULTI_CLICK -#define MOD_MASK_4CLICK 0x60 // use MOD_MASK_MULTI_CLICK -#define MOD_MASK_CMD 0x80 // "super" key (macOS: command-key) - -#define MOD_MASK_MULTI_CLICK (MOD_MASK_2CLICK|MOD_MASK_3CLICK| \ - MOD_MASK_4CLICK) - -/* - * The length of the longest special key name, including modifiers. - * Current longest is (length includes '<' and - * '>'). - */ -#define MAX_KEY_NAME_LEN 32 - -// Maximum length of a special key event as tokens. This includes modifiers. -// The longest event is something like which would be the -// following string of tokens: -// -// bitmask . -// -// This is a total of 6 tokens, and is currently the longest one possible. -#define MAX_KEY_CODE_LEN 6 - -#define FLAG_CPO_BSLASH 0x01 -#define CPO_TO_CPO_FLAGS ((vim_strchr(p_cpo, CPO_BSLASH) == NULL) \ - ? 0 \ - : FLAG_CPO_BSLASH) - -// Flags for replace_termcodes() -enum { - REPTERM_FROM_PART = 1, - REPTERM_DO_LT = 2, - REPTERM_NO_SPECIAL = 4, - REPTERM_NO_SIMPLIFY = 8, -}; - -// Flags for find_special_key() -enum { - FSK_KEYCODE = 0x01, ///< prefer key code, e.g. K_DEL in place of DEL - FSK_KEEP_X_KEY = 0x02, ///< don’t translate xHome to Home key - FSK_IN_STRING = 0x04, ///< in string, double quote is escaped - FSK_SIMPLIFY = 0x08, ///< simplify , etc. -}; - -#ifdef INCLUDE_GENERATED_DECLARATIONS -# include "keymap.h.generated.h" -#endif -#endif // NVIM_KEYMAP_H diff --git a/src/nvim/menu.c b/src/nvim/menu.c index 887a24d28b..72c129338c 100644 --- a/src/nvim/menu.c +++ b/src/nvim/menu.c @@ -18,7 +18,7 @@ #include "nvim/ex_docmd.h" #include "nvim/garray.h" #include "nvim/getchar.h" -#include "nvim/keymap.h" +#include "nvim/keycodes.h" #include "nvim/memory.h" #include "nvim/menu.h" #include "nvim/message.h" diff --git a/src/nvim/message.c b/src/nvim/message.c index 8f093a12ed..12a3580831 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -24,7 +24,7 @@ #include "nvim/getchar.h" #include "nvim/highlight.h" #include "nvim/input.h" -#include "nvim/keymap.h" +#include "nvim/keycodes.h" #include "nvim/main.h" #include "nvim/mbyte.h" #include "nvim/memory.h" diff --git a/src/nvim/normal.c b/src/nvim/normal.c index c54cc3ed09..a983ff4436 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -33,7 +33,7 @@ #include "nvim/getchar.h" #include "nvim/globals.h" #include "nvim/indent.h" -#include "nvim/keymap.h" +#include "nvim/keycodes.h" #include "nvim/log.h" #include "nvim/main.h" #include "nvim/mark.h" diff --git a/src/nvim/option.c b/src/nvim/option.c index 81b1ab5b2b..b5c9dfee87 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -49,7 +49,7 @@ #include "nvim/highlight.h" #include "nvim/highlight_group.h" #include "nvim/indent_c.h" -#include "nvim/keymap.h" +#include "nvim/keycodes.h" #include "nvim/macros.h" #include "nvim/mbyte.h" #include "nvim/memfile.h" diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index 64e5a7f229..c99d2869da 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -13,7 +13,7 @@ #include "nvim/ex_cmds2.h" #include "nvim/fileio.h" #include "nvim/getchar.h" -#include "nvim/keymap.h" +#include "nvim/keycodes.h" #include "nvim/main.h" #include "nvim/mbyte.h" #include "nvim/memory.h" diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index d8d1b736d2..d64494fd85 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -27,7 +27,7 @@ #include "nvim/highlight.h" #include "nvim/highlight_group.h" #include "nvim/indent_c.h" -#include "nvim/keymap.h" +#include "nvim/keycodes.h" #include "nvim/lua/executor.h" #include "nvim/macros.h" #include "nvim/mbyte.h" diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index f7d33de4fe..9ea847d9fb 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -56,7 +56,7 @@ #include "nvim/getchar.h" #include "nvim/highlight.h" #include "nvim/highlight_group.h" -#include "nvim/keymap.h" +#include "nvim/keycodes.h" #include "nvim/log.h" #include "nvim/macros.h" #include "nvim/main.h" diff --git a/src/nvim/vim.h b/src/nvim/vim.h index 4e269bc9d4..1c05387da3 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -31,7 +31,7 @@ enum { NUMBUFLEN = 65, }; #define ROOT_UID 0 #include "nvim/gettext.h" -#include "nvim/keymap.h" +#include "nvim/keycodes.h" #include "nvim/macros.h" // special attribute addition: Put message in history -- cgit