mirror of
https://github.com/neovim/neovim.git
synced 2024-09-17 20:58:20 -04:00
refactor: adopt termkey and eliminate duplicate code
Termkey is abandoned and it's now our code, so there's no reason not to treat it as such. An alternative approach could be to have a proper repo that we maintain such as with unibilium, although with this approach we can make a few assumptions that will allow us to remove more code. Also eliminate duplicate code from both termkey and libvterm.
This commit is contained in:
parent
975aeee537
commit
f9108378b7
@ -160,7 +160,6 @@ These dependencies are "vendored" (inlined), we must update the sources manually
|
|||||||
* Needs to be updated when LPeg is updated.
|
* Needs to be updated when LPeg is updated.
|
||||||
* `src/bit.c`: only for PUC lua: port of `require'bit'` from luajit https://bitop.luajit.org/
|
* `src/bit.c`: only for PUC lua: port of `require'bit'` from luajit https://bitop.luajit.org/
|
||||||
* `runtime/lua/coxpcall.lua`: coxpcall (only needed for PUC lua, builtin to luajit)
|
* `runtime/lua/coxpcall.lua`: coxpcall (only needed for PUC lua, builtin to luajit)
|
||||||
* `src/termkey`: [libtermkey](https://github.com/neovim/libtermkey)
|
|
||||||
|
|
||||||
Other dependencies
|
Other dependencies
|
||||||
--------------------------
|
--------------------------
|
||||||
|
@ -54,8 +54,6 @@ if(ENABLE_WASMTIME)
|
|||||||
target_compile_definitions(nvim_bin PRIVATE HAVE_WASMTIME)
|
target_compile_definitions(nvim_bin PRIVATE HAVE_WASMTIME)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_compile_definitions(main_lib INTERFACE HAVE_UNIBILIUM)
|
|
||||||
|
|
||||||
# The unit test lib requires LuaJIT; it will be skipped if LuaJIT is missing.
|
# The unit test lib requires LuaJIT; it will be skipped if LuaJIT is missing.
|
||||||
option(PREFER_LUA "Prefer Lua over LuaJIT in the nvim executable." OFF)
|
option(PREFER_LUA "Prefer Lua over LuaJIT in the nvim executable." OFF)
|
||||||
if(PREFER_LUA)
|
if(PREFER_LUA)
|
||||||
@ -153,7 +151,7 @@ if(UNIX)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME MATCHES "Windows")
|
if(CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||||
target_compile_definitions(main_lib INTERFACE _WIN32_WINNT=0x0602 MSWIN)
|
target_compile_definitions(main_lib INTERFACE _WIN32_WINNT=0x0602 MSWIN WIN32_LEAN_AND_MEAN)
|
||||||
target_link_libraries(main_lib INTERFACE netapi32)
|
target_link_libraries(main_lib INTERFACE netapi32)
|
||||||
elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||||
target_link_libraries(nvim_bin PRIVATE "-framework CoreServices")
|
target_link_libraries(nvim_bin PRIVATE "-framework CoreServices")
|
||||||
@ -366,8 +364,8 @@ file(MAKE_DIRECTORY ${TOUCHES_DIR} ${GENERATED_DIR} ${GENERATED_INCLUDES_DIR})
|
|||||||
|
|
||||||
file(GLOB NVIM_SOURCES CONFIGURE_DEPENDS *.c)
|
file(GLOB NVIM_SOURCES CONFIGURE_DEPENDS *.c)
|
||||||
file(GLOB NVIM_HEADERS CONFIGURE_DEPENDS *.h)
|
file(GLOB NVIM_HEADERS CONFIGURE_DEPENDS *.h)
|
||||||
file(GLOB EXTERNAL_SOURCES CONFIGURE_DEPENDS ../xdiff/*.c ../mpack/*.c ../cjson/*.c ../klib/*.c ../termkey/*.c ../vterm/*.c)
|
file(GLOB EXTERNAL_SOURCES CONFIGURE_DEPENDS ../xdiff/*.c ../mpack/*.c ../cjson/*.c ../klib/*.c ../vterm/*.c)
|
||||||
file(GLOB EXTERNAL_HEADERS CONFIGURE_DEPENDS ../xdiff/*.h ../mpack/*.h ../cjson/*.h ../klib/*.h ../termkey/*.h ../vterm/*.h)
|
file(GLOB EXTERNAL_HEADERS CONFIGURE_DEPENDS ../xdiff/*.h ../mpack/*.h ../cjson/*.h ../klib/*.h ../vterm/*.h)
|
||||||
|
|
||||||
file(GLOB NLUA0_SOURCES CONFIGURE_DEPENDS ../mpack/*.c)
|
file(GLOB NLUA0_SOURCES CONFIGURE_DEPENDS ../mpack/*.c)
|
||||||
|
|
||||||
@ -378,6 +376,15 @@ if(PREFER_LUA)
|
|||||||
target_compile_definitions(main_lib INTERFACE NVIM_VENDOR_BIT)
|
target_compile_definitions(main_lib INTERFACE NVIM_VENDOR_BIT)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Inlined external projects, we don't maintain it. #9306
|
||||||
|
if(MSVC)
|
||||||
|
set_source_files_properties(
|
||||||
|
${EXTERNAL_SOURCES} PROPERTIES COMPILE_OPTIONS "-wd4090;-wd4244;-wd4267")
|
||||||
|
else()
|
||||||
|
set_source_files_properties(
|
||||||
|
${EXTERNAL_SOURCES} PROPERTIES COMPILE_OPTIONS "-Wno-conversion;-Wno-missing-noreturn;-Wno-missing-format-attribute;-Wno-double-promotion;-Wno-strict-prototypes;-Wno-misleading-indentation;-Wno-sign-compare;-Wno-implicit-fallthrough;-Wno-missing-prototypes;-Wno-missing-field-initializers")
|
||||||
|
endif()
|
||||||
|
|
||||||
list(APPEND NLUA0_SOURCES ${PROJECT_SOURCE_DIR}/src/nlua0.c)
|
list(APPEND NLUA0_SOURCES ${PROJECT_SOURCE_DIR}/src/nlua0.c)
|
||||||
|
|
||||||
foreach(subdir
|
foreach(subdir
|
||||||
@ -386,6 +393,7 @@ foreach(subdir
|
|||||||
api/private
|
api/private
|
||||||
msgpack_rpc
|
msgpack_rpc
|
||||||
tui
|
tui
|
||||||
|
tui/termkey
|
||||||
event
|
event
|
||||||
eval
|
eval
|
||||||
lua
|
lua
|
||||||
@ -407,49 +415,36 @@ endforeach()
|
|||||||
list(SORT NVIM_SOURCES)
|
list(SORT NVIM_SOURCES)
|
||||||
list(SORT NVIM_HEADERS)
|
list(SORT NVIM_HEADERS)
|
||||||
|
|
||||||
list(APPEND LINT_NVIM_SOURCES ${NVIM_SOURCES} ${NVIM_HEADERS})
|
|
||||||
|
|
||||||
foreach(sfile ${NVIM_SOURCES})
|
foreach(sfile ${NVIM_SOURCES})
|
||||||
get_filename_component(f ${sfile} NAME)
|
get_filename_component(f ${sfile} NAME)
|
||||||
if(WIN32 AND ${f} MATCHES "^(pty_process_unix.c)$")
|
if(WIN32 AND ${f} MATCHES "^(pty_process_unix.c)$")
|
||||||
list(APPEND to_remove ${sfile})
|
list(REMOVE_ITEM NVIM_SOURCES ${sfile})
|
||||||
endif()
|
endif()
|
||||||
if(NOT WIN32 AND ${f} MATCHES "^(pty_process_win.c)$")
|
if(NOT WIN32 AND ${f} MATCHES "^(pty_process_win.c)$")
|
||||||
list(APPEND to_remove ${sfile})
|
list(REMOVE_ITEM NVIM_SOURCES ${sfile})
|
||||||
endif()
|
endif()
|
||||||
if(NOT WIN32 AND ${f} MATCHES "^(pty_conpty_win.c)$")
|
if(NOT WIN32 AND ${f} MATCHES "^(pty_conpty_win.c)$")
|
||||||
list(APPEND to_remove ${sfile})
|
list(REMOVE_ITEM NVIM_SOURCES ${sfile})
|
||||||
endif()
|
endif()
|
||||||
if(NOT WIN32 AND ${f} MATCHES "^(os_win_console.c)$")
|
if(NOT WIN32 AND ${f} MATCHES "^(os_win_console.c)$")
|
||||||
list(APPEND to_remove ${sfile})
|
list(REMOVE_ITEM NVIM_SOURCES ${sfile})
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
list(REMOVE_ITEM NVIM_SOURCES ${to_remove})
|
|
||||||
|
|
||||||
foreach(hfile ${NVIM_HEADERS})
|
foreach(hfile ${NVIM_HEADERS})
|
||||||
get_filename_component(f ${hfile} NAME)
|
get_filename_component(f ${hfile} NAME)
|
||||||
if(WIN32 AND ${f} MATCHES "^(unix_defs.h)$")
|
if(WIN32 AND ${f} MATCHES "^(unix_defs.h)$")
|
||||||
list(APPEND to_remove_h ${hfile})
|
list(REMOVE_ITEM NVIM_HEADERS ${hfile})
|
||||||
endif()
|
endif()
|
||||||
if(WIN32 AND ${f} MATCHES "^(pty_process_unix.h)$")
|
if(WIN32 AND ${f} MATCHES "^(pty_process_unix.h)$")
|
||||||
list(APPEND to_remove_h ${hfile})
|
list(REMOVE_ITEM NVIM_HEADERS ${hfile})
|
||||||
endif()
|
endif()
|
||||||
if(NOT WIN32 AND ${f} MATCHES "^(win_defs.h)$")
|
if(NOT WIN32 AND ${f} MATCHES "^(win_defs.h)$")
|
||||||
list(APPEND to_remove_h ${hfile})
|
list(REMOVE_ITEM NVIM_HEADERS ${hfile})
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
list(REMOVE_ITEM NVIM_HEADERS ${to_remove_h})
|
list(APPEND LINT_NVIM_SOURCES ${NVIM_SOURCES} ${NVIM_HEADERS})
|
||||||
|
|
||||||
# xdiff, mpack, lua-cjson, termkey: inlined external project, we don't maintain it. #9306
|
|
||||||
if(MSVC)
|
|
||||||
set_source_files_properties(
|
|
||||||
${EXTERNAL_SOURCES} PROPERTIES COMPILE_OPTIONS "-wd4090;-wd4244;-wd4267")
|
|
||||||
else()
|
|
||||||
set_source_files_properties(
|
|
||||||
${EXTERNAL_SOURCES} PROPERTIES COMPILE_OPTIONS "-Wno-conversion;-Wno-missing-noreturn;-Wno-missing-format-attribute;-Wno-double-promotion;-Wno-strict-prototypes;-Wno-misleading-indentation;-Wno-sign-compare;-Wno-implicit-fallthrough;-Wno-missing-prototypes;-Wno-missing-field-initializers")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Log level (NVIM_LOG_DEBUG in log.h)
|
# Log level (NVIM_LOG_DEBUG in log.h)
|
||||||
if(CI_BUILD)
|
if(CI_BUILD)
|
||||||
@ -849,7 +844,7 @@ endif()
|
|||||||
add_glob_target(
|
add_glob_target(
|
||||||
TARGET lintc-clang-tidy
|
TARGET lintc-clang-tidy
|
||||||
COMMAND ${CLANG_TIDY_PRG}
|
COMMAND ${CLANG_TIDY_PRG}
|
||||||
FILES ${NVIM_SOURCES} ${NVIM_HEADERS}
|
FILES ${LINT_NVIM_SOURCES}
|
||||||
FLAGS --quiet
|
FLAGS --quiet
|
||||||
EXCLUDE ${EXCLUDE_CLANG_TIDY})
|
EXCLUDE ${EXCLUDE_CLANG_TIDY})
|
||||||
|
|
||||||
@ -862,7 +857,7 @@ endif()
|
|||||||
add_glob_target(
|
add_glob_target(
|
||||||
TARGET clang-analyzer
|
TARGET clang-analyzer
|
||||||
COMMAND ${CLANG_TIDY_PRG}
|
COMMAND ${CLANG_TIDY_PRG}
|
||||||
FILES ${NVIM_SOURCES} ${NVIM_HEADERS}
|
FILES ${LINT_NVIM_SOURCES}
|
||||||
FLAGS --quiet
|
FLAGS --quiet
|
||||||
--checks='
|
--checks='
|
||||||
-*,
|
-*,
|
||||||
@ -905,13 +900,13 @@ add_glob_target(
|
|||||||
TARGET lintc-uncrustify
|
TARGET lintc-uncrustify
|
||||||
COMMAND ${UNCRUSTIFY_PRG}
|
COMMAND ${UNCRUSTIFY_PRG}
|
||||||
FLAGS -c ${UNCRUSTIFY_CONFIG} -q --check
|
FLAGS -c ${UNCRUSTIFY_CONFIG} -q --check
|
||||||
FILES ${LINT_NVIM_SOURCES})
|
FILES ${NVIM_SOURCES} ${NVIM_HEADERS})
|
||||||
|
|
||||||
add_glob_target(
|
add_glob_target(
|
||||||
TARGET formatc
|
TARGET formatc
|
||||||
COMMAND ${UNCRUSTIFY_PRG}
|
COMMAND ${UNCRUSTIFY_PRG}
|
||||||
FLAGS -c ${UNCRUSTIFY_CONFIG} --replace --no-backup
|
FLAGS -c ${UNCRUSTIFY_CONFIG} --replace --no-backup
|
||||||
FILES ${LINT_NVIM_SOURCES})
|
FILES ${NVIM_SOURCES} ${NVIM_HEADERS})
|
||||||
|
|
||||||
add_dependencies(lintc-uncrustify uncrustify_update_config)
|
add_dependencies(lintc-uncrustify uncrustify_update_config)
|
||||||
add_dependencies(formatc uncrustify_update_config)
|
add_dependencies(formatc uncrustify_update_config)
|
||||||
|
@ -16,9 +16,6 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
// vterm.h defines an `unsigned int small` in a struct, triggering error C2632
|
|
||||||
#undef small
|
|
||||||
|
|
||||||
// Windows does not have S_IFLNK but libuv defines it
|
// Windows does not have S_IFLNK but libuv defines it
|
||||||
// and sets the flag for us when calling uv_fs_stat.
|
// and sets the flag for us when calling uv_fs_stat.
|
||||||
#include <uv.h>
|
#include <uv.h>
|
||||||
|
@ -7,24 +7,27 @@
|
|||||||
#include "nvim/api/private/defs.h"
|
#include "nvim/api/private/defs.h"
|
||||||
#include "nvim/api/private/helpers.h"
|
#include "nvim/api/private/helpers.h"
|
||||||
#include "nvim/event/loop.h"
|
#include "nvim/event/loop.h"
|
||||||
|
#include "nvim/event/rstream.h"
|
||||||
#include "nvim/event/stream.h"
|
#include "nvim/event/stream.h"
|
||||||
#include "nvim/macros_defs.h"
|
#include "nvim/macros_defs.h"
|
||||||
#include "nvim/main.h"
|
#include "nvim/main.h"
|
||||||
#include "nvim/map_defs.h"
|
#include "nvim/map_defs.h"
|
||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
|
#include "nvim/msgpack_rpc/channel.h"
|
||||||
#include "nvim/option_vars.h"
|
#include "nvim/option_vars.h"
|
||||||
#include "nvim/os/os.h"
|
#include "nvim/os/os.h"
|
||||||
#include "nvim/os/os_defs.h"
|
#include "nvim/os/os_defs.h"
|
||||||
#include "nvim/strings.h"
|
#include "nvim/strings.h"
|
||||||
#include "nvim/tui/input.h"
|
#include "nvim/tui/input.h"
|
||||||
#include "nvim/tui/input_defs.h"
|
#include "nvim/tui/input_defs.h"
|
||||||
|
#include "nvim/tui/termkey/driver-csi.h"
|
||||||
|
#include "nvim/tui/termkey/termkey.h"
|
||||||
#include "nvim/tui/tui.h"
|
#include "nvim/tui/tui.h"
|
||||||
#include "nvim/ui_client.h"
|
#include "nvim/ui_client.h"
|
||||||
|
|
||||||
#ifdef MSWIN
|
#ifdef MSWIN
|
||||||
# include "nvim/os/os_win_console.h"
|
# include "nvim/os/os_win_console.h"
|
||||||
#endif
|
#endif
|
||||||
#include "nvim/event/rstream.h"
|
|
||||||
#include "nvim/msgpack_rpc/channel.h"
|
|
||||||
|
|
||||||
#define READ_STREAM_SIZE 0xfff
|
#define READ_STREAM_SIZE 0xfff
|
||||||
|
|
||||||
@ -261,7 +264,7 @@ static size_t handle_more_modifiers(TermKeyKey *key, char *buf, size_t buflen)
|
|||||||
|
|
||||||
static void handle_kitty_key_protocol(TermInput *input, TermKeyKey *key)
|
static void handle_kitty_key_protocol(TermInput *input, TermKeyKey *key)
|
||||||
{
|
{
|
||||||
const char *name = pmap_get(int)(&kitty_key_map, (int)key->code.codepoint);
|
const char *name = pmap_get(int)(&kitty_key_map, key->code.codepoint);
|
||||||
if (name) {
|
if (name) {
|
||||||
char buf[64];
|
char buf[64];
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
@ -598,7 +601,7 @@ static void handle_unknown_csi(TermInput *input, const TermKeyKey *key)
|
|||||||
// contain, so just allocate enough space for a large upper bound
|
// contain, so just allocate enough space for a large upper bound
|
||||||
TermKeyCsiParam params[16];
|
TermKeyCsiParam params[16];
|
||||||
size_t nparams = 16;
|
size_t nparams = 16;
|
||||||
unsigned long cmd;
|
unsigned cmd;
|
||||||
if (termkey_interpret_csi(input->tk, key, params, &nparams, &cmd) != TERMKEY_RES_KEY) {
|
if (termkey_interpret_csi(input->tk, key, params, &nparams, &cmd) != TERMKEY_RES_KEY) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -641,7 +644,7 @@ static void handle_unknown_csi(TermInput *input, const TermKeyKey *key)
|
|||||||
case 't':
|
case 't':
|
||||||
if (nparams == 5) {
|
if (nparams == 5) {
|
||||||
// We only care about the first 3 parameters, and we ignore subparameters
|
// We only care about the first 3 parameters, and we ignore subparameters
|
||||||
long args[3];
|
int args[3];
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(args); i++) {
|
for (size_t i = 0; i < ARRAY_SIZE(args); i++) {
|
||||||
if (termkey_interpret_csi_param(params[i], &args[i], NULL, NULL) != TERMKEY_RES_KEY) {
|
if (termkey_interpret_csi_param(params[i], &args[i], NULL, NULL) != TERMKEY_RES_KEY) {
|
||||||
return;
|
return;
|
||||||
@ -650,8 +653,8 @@ static void handle_unknown_csi(TermInput *input, const TermKeyKey *key)
|
|||||||
|
|
||||||
if (args[0] == 48) {
|
if (args[0] == 48) {
|
||||||
// In-band resize event (DEC private mode 2048)
|
// In-band resize event (DEC private mode 2048)
|
||||||
int height_chars = (int)args[1];
|
int height_chars = args[1];
|
||||||
int width_chars = (int)args[2];
|
int width_chars = args[2];
|
||||||
tui_set_size(input->tui_data, width_chars, height_chars);
|
tui_set_size(input->tui_data, width_chars, height_chars);
|
||||||
ui_client_set_size(width_chars, height_chars);
|
ui_client_set_size(width_chars, height_chars);
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
|
|
||||||
#include "nvim/event/defs.h"
|
#include "nvim/event/defs.h"
|
||||||
#include "nvim/tui/input_defs.h" // IWYU pragma: keep
|
#include "nvim/tui/input_defs.h" // IWYU pragma: keep
|
||||||
|
#include "nvim/tui/termkey/termkey_defs.h"
|
||||||
#include "nvim/tui/tui_defs.h"
|
#include "nvim/tui/tui_defs.h"
|
||||||
#include "nvim/types_defs.h"
|
#include "nvim/types_defs.h"
|
||||||
#include "termkey/termkey.h"
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
kKeyEncodingLegacy, ///< Legacy key encoding
|
kKeyEncodingLegacy, ///< Legacy key encoding
|
||||||
|
1
src/nvim/tui/termkey/README
Normal file
1
src/nvim/tui/termkey/README
Normal file
@ -0,0 +1 @@
|
|||||||
|
// Adapted from libtermkey: https://github.com/neovim/libtermkey
|
File diff suppressed because it is too large
Load Diff
7
src/nvim/tui/termkey/driver-csi.h
Normal file
7
src/nvim/tui/termkey/driver-csi.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "nvim/tui/termkey/termkey_defs.h"
|
||||||
|
|
||||||
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
|
# include "tui/termkey/driver-csi.h.generated.h"
|
||||||
|
#endif
|
@ -1,33 +1,28 @@
|
|||||||
// we want strdup()
|
|
||||||
#define _XOPEN_SOURCE 600
|
|
||||||
|
|
||||||
#include "termkey.h"
|
|
||||||
#include "termkey-internal.h"
|
|
||||||
|
|
||||||
#ifdef HAVE_UNIBILIUM
|
|
||||||
# include <unibilium.h>
|
|
||||||
#else
|
|
||||||
# include <curses.h>
|
|
||||||
# include <term.h>
|
|
||||||
|
|
||||||
/* curses.h has just polluted our namespace. We want this back */
|
|
||||||
# undef buttons
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unibilium.h>
|
||||||
|
|
||||||
|
#include "nvim/memory.h"
|
||||||
|
#include "nvim/tui/termkey/driver-ti.h"
|
||||||
|
#include "nvim/tui/termkey/termkey-internal.h"
|
||||||
|
#include "nvim/tui/termkey/termkey.h"
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#else
|
#else
|
||||||
# include <io.h>
|
# include <io.h>
|
||||||
#endif
|
#endif
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#define streq(a,b) (!strcmp(a,b))
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
|
# include "tui/termkey/driver-ti.c.generated.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define streq(a, b) (!strcmp(a, b))
|
||||||
|
|
||||||
#define MAX_FUNCNAME 9
|
#define MAX_FUNCNAME 9
|
||||||
|
|
||||||
@ -36,9 +31,8 @@ static struct {
|
|||||||
TermKeyType type;
|
TermKeyType type;
|
||||||
TermKeySym sym;
|
TermKeySym sym;
|
||||||
int mods;
|
int mods;
|
||||||
} funcs[] =
|
} funcs[] = {
|
||||||
{
|
// THIS LIST MUST REMAIN SORTED!
|
||||||
/* THIS LIST MUST REMAIN SORTED! */
|
|
||||||
{ "backspace", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BACKSPACE, 0 },
|
{ "backspace", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BACKSPACE, 0 },
|
||||||
{ "begin", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN, 0 },
|
{ "begin", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN, 0 },
|
||||||
{ "beg", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN, 0 },
|
{ "beg", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN, 0 },
|
||||||
@ -61,12 +55,12 @@ static struct {
|
|||||||
{ "mark", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MARK, 0 },
|
{ "mark", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MARK, 0 },
|
||||||
{ "message", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MESSAGE, 0 },
|
{ "message", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MESSAGE, 0 },
|
||||||
{ "move", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MOVE, 0 },
|
{ "move", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MOVE, 0 },
|
||||||
{ "next", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN, 0 }, // Not quite, but it's the best we can do
|
{ "next", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN, 0 }, // Not quite, but it's the best we can do
|
||||||
{ "npage", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN, 0 },
|
{ "npage", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN, 0 },
|
||||||
{ "open", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_OPEN, 0 },
|
{ "open", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_OPEN, 0 },
|
||||||
{ "options", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_OPTIONS, 0 },
|
{ "options", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_OPTIONS, 0 },
|
||||||
{ "ppage", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP, 0 },
|
{ "ppage", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP, 0 },
|
||||||
{ "previous", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP, 0 }, // Not quite, but it's the best we can do
|
{ "previous", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP, 0 }, // Not quite, but it's the best we can do
|
||||||
{ "print", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PRINT, 0 },
|
{ "print", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PRINT, 0 },
|
||||||
{ "redo", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REDO, 0 },
|
{ "redo", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REDO, 0 },
|
||||||
{ "reference", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REFERENCE, 0 },
|
{ "reference", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REFERENCE, 0 },
|
||||||
@ -80,34 +74,34 @@ static struct {
|
|||||||
{ "suspend", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SUSPEND, 0 },
|
{ "suspend", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SUSPEND, 0 },
|
||||||
{ "undo", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UNDO, 0 },
|
{ "undo", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UNDO, 0 },
|
||||||
{ "up", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UP, 0 },
|
{ "up", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UP, 0 },
|
||||||
{ NULL },
|
{ NULL, 0, 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef HAVE_UNIBILIUM
|
|
||||||
static enum unibi_string unibi_lookup_str(const char *name)
|
static enum unibi_string unibi_lookup_str(const char *name)
|
||||||
{
|
{
|
||||||
for(enum unibi_string ret = unibi_string_begin_+1; ret < unibi_string_end_; ret++)
|
for (enum unibi_string ret = unibi_string_begin_ + 1; ret < unibi_string_end_; ret++) {
|
||||||
if(streq(unibi_name_str(ret), name))
|
if (streq(unibi_name_str(ret), name)) {
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
return (enum unibi_string)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *unibi_get_str_by_name(const unibi_term *ut, const char *name)
|
static const char *unibi_get_str_by_name(const unibi_term *ut, const char *name)
|
||||||
{
|
{
|
||||||
enum unibi_string idx = unibi_lookup_str(name);
|
enum unibi_string idx = unibi_lookup_str(name);
|
||||||
if(idx == (enum unibi_string)-1)
|
if (idx == (enum unibi_string)-1) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return unibi_get_str(ut, idx);
|
return unibi_get_str(ut, idx);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* To be efficient at lookups, we store the byte sequence => keyinfo mapping
|
// To be efficient at lookups, we store the byte sequence => keyinfo mapping
|
||||||
* in a trie. This avoids a slow linear search through a flat list of
|
// in a trie. This avoids a slow linear search through a flat list of
|
||||||
* sequences. Because it is likely most nodes will be very sparse, we optimise
|
// sequences. Because it is likely most nodes will be very sparse, we optimise
|
||||||
* vector to store an extent map after the database is loaded.
|
// vector to store an extent map after the database is loaded.
|
||||||
*/
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TYPE_KEY,
|
TYPE_KEY,
|
||||||
@ -125,126 +119,110 @@ struct trie_node_key {
|
|||||||
|
|
||||||
struct trie_node_arr {
|
struct trie_node_arr {
|
||||||
trie_nodetype type;
|
trie_nodetype type;
|
||||||
unsigned char min, max; /* INCLUSIVE endpoints of the extent range */
|
unsigned char min, max; // INCLUSIVE endpoints of the extent range
|
||||||
struct trie_node *arr[]; /* dynamic size at allocation time */
|
struct trie_node *arr[]; // dynamic size at allocation time
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
TermKey *tk;
|
|
||||||
|
|
||||||
#ifdef HAVE_UNIBILIUM
|
|
||||||
unibi_term *unibi; /* only valid until first 'start' call */
|
|
||||||
#else
|
|
||||||
char *term; /* only valid until first 'start' call */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct trie_node *root;
|
|
||||||
|
|
||||||
char *start_string;
|
|
||||||
char *stop_string;
|
|
||||||
} TermKeyTI;
|
|
||||||
|
|
||||||
static int insert_seq(TermKeyTI *ti, const char *seq, struct trie_node *node);
|
static int insert_seq(TermKeyTI *ti, const char *seq, struct trie_node *node);
|
||||||
|
|
||||||
static struct trie_node *new_node_key(TermKeyType type, TermKeySym sym, int modmask, int modset)
|
static struct trie_node *new_node_key(TermKeyType type, TermKeySym sym, int modmask, int modset)
|
||||||
{
|
{
|
||||||
struct trie_node_key *n = malloc(sizeof(*n));
|
struct trie_node_key *n = xmalloc(sizeof(*n));
|
||||||
if(!n)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
n->type = TYPE_KEY;
|
n->type = TYPE_KEY;
|
||||||
|
|
||||||
n->key.type = type;
|
n->key.type = type;
|
||||||
n->key.sym = sym;
|
n->key.sym = sym;
|
||||||
n->key.modifier_mask = modmask;
|
n->key.modifier_mask = modmask;
|
||||||
n->key.modifier_set = modset;
|
n->key.modifier_set = modset;
|
||||||
|
|
||||||
return (struct trie_node*)n;
|
return (struct trie_node *)n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct trie_node *new_node_arr(unsigned char min, unsigned char max)
|
static struct trie_node *new_node_arr(unsigned char min, unsigned char max)
|
||||||
{
|
{
|
||||||
struct trie_node_arr *n = malloc(sizeof(*n) + ((int)max-min+1) * sizeof(n->arr[0]));
|
struct trie_node_arr *n = xmalloc(sizeof(*n) + (max - min + 1) * sizeof(n->arr[0]));
|
||||||
if(!n)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
n->type = TYPE_ARR;
|
n->type = TYPE_ARR;
|
||||||
n->min = min; n->max = max;
|
n->min = min; n->max = max;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for(i = min; i <= max; i++)
|
for (i = min; i <= max; i++) {
|
||||||
n->arr[i-min] = NULL;
|
n->arr[i - min] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return (struct trie_node*)n;
|
return (struct trie_node *)n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct trie_node *lookup_next(struct trie_node *n, unsigned char b)
|
static struct trie_node *lookup_next(struct trie_node *n, unsigned char b)
|
||||||
{
|
{
|
||||||
switch(n->type) {
|
switch (n->type) {
|
||||||
case TYPE_KEY:
|
case TYPE_KEY:
|
||||||
fprintf(stderr, "ABORT: lookup_next within a TYPE_KEY node\n");
|
fprintf(stderr, "ABORT: lookup_next within a TYPE_KEY node\n");
|
||||||
abort();
|
abort();
|
||||||
case TYPE_ARR:
|
case TYPE_ARR: {
|
||||||
{
|
struct trie_node_arr *nar = (struct trie_node_arr *)n;
|
||||||
struct trie_node_arr *nar = (struct trie_node_arr*)n;
|
if (b < nar->min || b > nar->max) {
|
||||||
if(b < nar->min || b > nar->max)
|
return NULL;
|
||||||
return NULL;
|
|
||||||
return nar->arr[b - nar->min];
|
|
||||||
}
|
}
|
||||||
|
return nar->arr[b - nar->min];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL; // Never reached but keeps compiler happy
|
return NULL; // Never reached but keeps compiler happy
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_trie(struct trie_node *n)
|
static void free_trie(struct trie_node *n)
|
||||||
{
|
{
|
||||||
switch(n->type) {
|
switch (n->type) {
|
||||||
case TYPE_KEY:
|
case TYPE_KEY:
|
||||||
break;
|
break;
|
||||||
case TYPE_ARR:
|
case TYPE_ARR: {
|
||||||
{
|
struct trie_node_arr *nar = (struct trie_node_arr *)n;
|
||||||
struct trie_node_arr *nar = (struct trie_node_arr*)n;
|
int i;
|
||||||
int i;
|
for (i = nar->min; i <= nar->max; i++) {
|
||||||
for(i = nar->min; i <= nar->max; i++)
|
if (nar->arr[i - nar->min]) {
|
||||||
if(nar->arr[i - nar->min])
|
free_trie(nar->arr[i - nar->min]);
|
||||||
free_trie(nar->arr[i - nar->min]);
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(n);
|
xfree(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct trie_node *compress_trie(struct trie_node *n)
|
static struct trie_node *compress_trie(struct trie_node *n)
|
||||||
{
|
{
|
||||||
if(!n)
|
if (!n) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
switch(n->type) {
|
switch (n->type) {
|
||||||
case TYPE_KEY:
|
case TYPE_KEY:
|
||||||
return n;
|
return n;
|
||||||
case TYPE_ARR:
|
case TYPE_ARR: {
|
||||||
{
|
struct trie_node_arr *nar = (struct trie_node_arr *)n;
|
||||||
struct trie_node_arr *nar = (struct trie_node_arr*)n;
|
unsigned char min, max;
|
||||||
unsigned char min, max;
|
// Find the real bounds
|
||||||
// Find the real bounds
|
for (min = 0; !nar->arr[min]; min++) {
|
||||||
for(min = 0; !nar->arr[min]; min++)
|
if (min == 255 && !nar->arr[min]) {
|
||||||
if(min == 255 && !nar->arr[min]) {
|
xfree(nar);
|
||||||
free(nar);
|
return new_node_arr(1, 0);
|
||||||
return new_node_arr(1, 0);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for(max = 0xff; !nar->arr[max]; max--)
|
|
||||||
;
|
|
||||||
|
|
||||||
struct trie_node_arr *new = (struct trie_node_arr*)new_node_arr(min, max);
|
|
||||||
int i;
|
|
||||||
for(i = min; i <= max; i++)
|
|
||||||
new->arr[i - min] = compress_trie(nar->arr[i]);
|
|
||||||
|
|
||||||
free(nar);
|
|
||||||
return (struct trie_node*)new;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (max = 0xff; !nar->arr[max]; max--) {}
|
||||||
|
|
||||||
|
struct trie_node_arr *new = (struct trie_node_arr *)new_node_arr(min, max);
|
||||||
|
int i;
|
||||||
|
for (i = min; i <= max; i++) {
|
||||||
|
new->arr[i - min] = compress_trie(nar->arr[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
xfree(nar);
|
||||||
|
return (struct trie_node *)new;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
@ -254,21 +232,20 @@ static bool try_load_terminfo_key(TermKeyTI *ti, const char *name, struct keyinf
|
|||||||
{
|
{
|
||||||
const char *value = NULL;
|
const char *value = NULL;
|
||||||
|
|
||||||
#ifdef HAVE_UNIBILIUM
|
if (ti->unibi) {
|
||||||
if(ti->unibi)
|
|
||||||
value = unibi_get_str_by_name(ti->unibi, name);
|
value = unibi_get_str_by_name(ti->unibi, name);
|
||||||
#else
|
}
|
||||||
if(ti->term)
|
|
||||||
value = tigetstr(name);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(ti->tk->ti_getstr_hook)
|
if (ti->tk->ti_getstr_hook) {
|
||||||
value = (ti->tk->ti_getstr_hook)(name, value, ti->tk->ti_getstr_hook_data);
|
value = (ti->tk->ti_getstr_hook)(name, value, ti->tk->ti_getstr_hook_data);
|
||||||
|
}
|
||||||
|
|
||||||
if(!value || value == (char*)-1 || !value[0])
|
if (!value || value == (char *)-1 || !value[0]) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
struct trie_node *node = new_node_key(info->type, info->sym, info->modifier_mask, info->modifier_set);
|
struct trie_node *node = new_node_key(info->type, info->sym, info->modifier_mask,
|
||||||
|
info->modifier_set);
|
||||||
insert_seq(ti, value, node);
|
insert_seq(ti, value, node);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -278,288 +255,257 @@ static int load_terminfo(TermKeyTI *ti)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#ifdef HAVE_UNIBILIUM
|
|
||||||
unibi_term *unibi = ti->unibi;
|
unibi_term *unibi = ti->unibi;
|
||||||
#else
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
|
|
||||||
/* Have to cast away the const. But it's OK - we know terminfo won't really
|
|
||||||
* modify term */
|
|
||||||
if(setupterm((char*)ti->term, 1, &err) != OK)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ti->root = new_node_arr(0, 0xff);
|
ti->root = new_node_arr(0, 0xff);
|
||||||
if(!ti->root)
|
if (!ti->root) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* First the regular key strings
|
// First the regular key strings
|
||||||
*/
|
for (i = 0; funcs[i].funcname; i++) {
|
||||||
for(i = 0; funcs[i].funcname; i++) {
|
|
||||||
char name[MAX_FUNCNAME + 5 + 1];
|
char name[MAX_FUNCNAME + 5 + 1];
|
||||||
|
|
||||||
sprintf(name, "key_%s", funcs[i].funcname);
|
sprintf(name, "key_%s", funcs[i].funcname); // NOLINT(runtime/printf)
|
||||||
if(!try_load_terminfo_key(ti, name, &(struct keyinfo){
|
if (!try_load_terminfo_key(ti, name, &(struct keyinfo){
|
||||||
.type = funcs[i].type,
|
.type = funcs[i].type,
|
||||||
.sym = funcs[i].sym,
|
.sym = funcs[i].sym,
|
||||||
.modifier_mask = funcs[i].mods,
|
.modifier_mask = funcs[i].mods,
|
||||||
.modifier_set = funcs[i].mods,
|
.modifier_set = funcs[i].mods,
|
||||||
}))
|
})) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Maybe it has a shifted version */
|
// Maybe it has a shifted version
|
||||||
sprintf(name, "key_s%s", funcs[i].funcname);
|
sprintf(name, "key_s%s", funcs[i].funcname); // NOLINT(runtime/printf)
|
||||||
try_load_terminfo_key(ti, name, &(struct keyinfo){
|
try_load_terminfo_key(ti, name, &(struct keyinfo){
|
||||||
.type = funcs[i].type,
|
.type = funcs[i].type,
|
||||||
.sym = funcs[i].sym,
|
.sym = funcs[i].sym,
|
||||||
.modifier_mask = funcs[i].mods | TERMKEY_KEYMOD_SHIFT,
|
.modifier_mask = funcs[i].mods | TERMKEY_KEYMOD_SHIFT,
|
||||||
.modifier_set = funcs[i].mods | TERMKEY_KEYMOD_SHIFT,
|
.modifier_set = funcs[i].mods | TERMKEY_KEYMOD_SHIFT,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now the F<digit> keys
|
// Now the F<digit> keys
|
||||||
*/
|
for (i = 1; i < 255; i++) {
|
||||||
for(i = 1; i < 255; i++) {
|
|
||||||
char name[9];
|
char name[9];
|
||||||
sprintf(name, "key_f%d", i);
|
sprintf(name, "key_f%d", i); // NOLINT(runtime/printf)
|
||||||
if(!try_load_terminfo_key(ti, name, &(struct keyinfo){
|
if (!try_load_terminfo_key(ti, name, &(struct keyinfo){
|
||||||
.type = TERMKEY_TYPE_FUNCTION,
|
.type = TERMKEY_TYPE_FUNCTION,
|
||||||
.sym = i,
|
.sym = i,
|
||||||
.modifier_mask = 0,
|
.modifier_mask = 0,
|
||||||
.modifier_set = 0,
|
.modifier_set = 0,
|
||||||
}))
|
})) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally mouse mode */
|
// Finally mouse mode
|
||||||
{
|
{
|
||||||
const char *value = NULL;
|
const char *value = NULL;
|
||||||
|
|
||||||
#ifdef HAVE_UNIBILIUM
|
if (ti->unibi) {
|
||||||
if(ti->unibi)
|
|
||||||
value = unibi_get_str_by_name(ti->unibi, "key_mouse");
|
value = unibi_get_str_by_name(ti->unibi, "key_mouse");
|
||||||
#else
|
}
|
||||||
if(ti->term)
|
|
||||||
value = tigetstr("key_mouse");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(ti->tk->ti_getstr_hook)
|
if (ti->tk->ti_getstr_hook) {
|
||||||
value = (ti->tk->ti_getstr_hook)("key_mouse", value, ti->tk->ti_getstr_hook_data);
|
value = (ti->tk->ti_getstr_hook)("key_mouse", value, ti->tk->ti_getstr_hook_data);
|
||||||
|
}
|
||||||
|
|
||||||
/* Some terminfos (e.g. xterm-1006) claim a different key_mouse that won't
|
// Some terminfos (e.g. xterm-1006) claim a different key_mouse that won't
|
||||||
* give X10 encoding. We'll only accept this if it's exactly "\e[M"
|
// give X10 encoding. We'll only accept this if it's exactly "\e[M"
|
||||||
*/
|
if (value && streq(value, "\x1b[M")) {
|
||||||
if(value && streq(value, "\x1b[M")) {
|
|
||||||
struct trie_node *node = new_node_key(TERMKEY_TYPE_MOUSE, 0, 0, 0);
|
struct trie_node *node = new_node_key(TERMKEY_TYPE_MOUSE, 0, 0, 0);
|
||||||
insert_seq(ti, value, node);
|
insert_seq(ti, value, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Take copies of these terminfo strings, in case we build multiple termkey
|
// Take copies of these terminfo strings, in case we build multiple termkey
|
||||||
* instances for multiple different termtypes, and it's different by the
|
// instances for multiple different termtypes, and it's different by the
|
||||||
* time we want to use it
|
// time we want to use it
|
||||||
*/
|
const char *keypad_xmit = unibi
|
||||||
#ifdef HAVE_UNIBILIUM
|
? unibi_get_str(unibi, unibi_keypad_xmit)
|
||||||
const char *keypad_xmit = unibi ?
|
: NULL;
|
||||||
unibi_get_str(unibi, unibi_keypad_xmit) :
|
|
||||||
NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(keypad_xmit)
|
if (keypad_xmit) {
|
||||||
ti->start_string = strdup(keypad_xmit);
|
ti->start_string = xstrdup(keypad_xmit);
|
||||||
else
|
} else {
|
||||||
ti->start_string = NULL;
|
ti->start_string = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_UNIBILIUM
|
const char *keypad_local = unibi
|
||||||
const char *keypad_local = unibi ?
|
? unibi_get_str(unibi, unibi_keypad_local)
|
||||||
unibi_get_str(unibi, unibi_keypad_local) :
|
: NULL;
|
||||||
NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(keypad_local)
|
if (keypad_local) {
|
||||||
ti->stop_string = strdup(keypad_local);
|
ti->stop_string = xstrdup(keypad_local);
|
||||||
else
|
} else {
|
||||||
ti->stop_string = NULL;
|
ti->stop_string = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_UNIBILIUM
|
if (unibi) {
|
||||||
if(unibi)
|
|
||||||
unibi_destroy(unibi);
|
unibi_destroy(unibi);
|
||||||
|
}
|
||||||
|
|
||||||
ti->unibi = NULL;
|
ti->unibi = NULL;
|
||||||
#else
|
|
||||||
if(ti->term)
|
|
||||||
free(ti->term);
|
|
||||||
|
|
||||||
ti->term = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ti->root = compress_trie(ti->root);
|
ti->root = compress_trie(ti->root);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *new_driver(TermKey *tk, const char *term)
|
void *new_driver_ti(TermKey *tk, const char *term)
|
||||||
{
|
{
|
||||||
TermKeyTI *ti = malloc(sizeof *ti);
|
TermKeyTI *ti = xmalloc(sizeof *ti);
|
||||||
if(!ti)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ti->tk = tk;
|
ti->tk = tk;
|
||||||
ti->root = NULL;
|
ti->root = NULL;
|
||||||
ti->start_string = NULL;
|
ti->start_string = NULL;
|
||||||
ti->stop_string = NULL;
|
ti->stop_string = NULL;
|
||||||
|
|
||||||
#ifdef HAVE_UNIBILIUM
|
|
||||||
ti->unibi = unibi_from_term(term);
|
ti->unibi = unibi_from_term(term);
|
||||||
int saved_errno = errno;
|
int saved_errno = errno;
|
||||||
if(!ti->unibi && saved_errno != ENOENT) {
|
if (!ti->unibi && saved_errno != ENOENT) {
|
||||||
free(ti);
|
xfree(ti);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* ti->unibi may be NULL if errno == ENOENT. That means the terminal wasn't
|
// ti->unibi may be NULL if errno == ENOENT. That means the terminal wasn't
|
||||||
* known. Lets keep going because if we get getstr hook that might invent
|
// known. Lets keep going because if we get getstr hook that might invent
|
||||||
* new strings for us
|
// new strings for us
|
||||||
*/
|
|
||||||
#else
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
|
|
||||||
ti->term = NULL;
|
|
||||||
|
|
||||||
/* Have to cast away the const. But it's OK - we know terminfo won't really
|
|
||||||
* modify term */
|
|
||||||
if(setupterm((char*)term, 1, &err) == OK)
|
|
||||||
ti->term = strdup(term);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return ti;
|
return ti;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int start_driver(TermKey *tk, void *info)
|
int start_driver_ti(TermKey *tk, void *info)
|
||||||
{
|
{
|
||||||
TermKeyTI *ti = info;
|
TermKeyTI *ti = info;
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
char *start_string;
|
char *start_string;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
if(!ti->root)
|
if (!ti->root) {
|
||||||
load_terminfo(ti);
|
load_terminfo(ti);
|
||||||
|
}
|
||||||
|
|
||||||
start_string = ti->start_string;
|
start_string = ti->start_string;
|
||||||
|
|
||||||
if(tk->fd == -1 || !start_string)
|
if (tk->fd == -1 || !start_string) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* The terminfo database will contain keys in application cursor key mode.
|
// The terminfo database will contain keys in application cursor key mode.
|
||||||
* We may need to enable that mode
|
// We may need to enable that mode
|
||||||
*/
|
|
||||||
|
|
||||||
/* There's no point trying to write() to a pipe */
|
// There's no point trying to write() to a pipe
|
||||||
if(fstat(tk->fd, &statbuf) == -1)
|
if (fstat(tk->fd, &statbuf) == -1) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
if(S_ISFIFO(statbuf.st_mode))
|
if (S_ISFIFO(statbuf.st_mode)) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Can't call putp or tputs because they suck and don't give us fd control
|
// Can't call putp or tputs because they suck and don't give us fd control
|
||||||
len = strlen(start_string);
|
len = strlen(start_string);
|
||||||
while(len) {
|
while (len) {
|
||||||
size_t written = write(tk->fd, start_string, len);
|
size_t written = (size_t)write(tk->fd, start_string, (unsigned)len);
|
||||||
if(written == -1)
|
if (written == (size_t)-1) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
start_string += written;
|
start_string += written;
|
||||||
len -= written;
|
len -= written;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stop_driver(TermKey *tk, void *info)
|
int stop_driver_ti(TermKey *tk, void *info)
|
||||||
{
|
{
|
||||||
TermKeyTI *ti = info;
|
TermKeyTI *ti = info;
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
char *stop_string = ti->stop_string;
|
char *stop_string = ti->stop_string;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
if(tk->fd == -1 || !stop_string)
|
if (tk->fd == -1 || !stop_string) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* There's no point trying to write() to a pipe */
|
// There's no point trying to write() to a pipe
|
||||||
if(fstat(tk->fd, &statbuf) == -1)
|
if (fstat(tk->fd, &statbuf) == -1) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
if(S_ISFIFO(statbuf.st_mode))
|
if (S_ISFIFO(statbuf.st_mode)) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The terminfo database will contain keys in application cursor key mode.
|
// The terminfo database will contain keys in application cursor key mode.
|
||||||
* We may need to enable that mode
|
// We may need to enable that mode
|
||||||
*/
|
|
||||||
|
|
||||||
// Can't call putp or tputs because they suck and don't give us fd control
|
// Can't call putp or tputs because they suck and don't give us fd control
|
||||||
len = strlen(stop_string);
|
len = strlen(stop_string);
|
||||||
while(len) {
|
while (len) {
|
||||||
size_t written = write(tk->fd, stop_string, len);
|
size_t written = (size_t)write(tk->fd, stop_string, (unsigned)len);
|
||||||
if(written == -1)
|
if (written == (size_t)-1) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
stop_string += written;
|
stop_string += written;
|
||||||
len -= written;
|
len -= written;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_driver(void *info)
|
void free_driver_ti(void *info)
|
||||||
{
|
{
|
||||||
TermKeyTI *ti = info;
|
TermKeyTI *ti = info;
|
||||||
|
|
||||||
free_trie(ti->root);
|
free_trie(ti->root);
|
||||||
|
|
||||||
if(ti->start_string)
|
if (ti->start_string) {
|
||||||
free(ti->start_string);
|
xfree(ti->start_string);
|
||||||
|
}
|
||||||
|
|
||||||
if(ti->stop_string)
|
if (ti->stop_string) {
|
||||||
free(ti->stop_string);
|
xfree(ti->stop_string);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_UNIBILIUM
|
if (ti->unibi) {
|
||||||
if(ti->unibi)
|
|
||||||
unibi_destroy(ti->unibi);
|
unibi_destroy(ti->unibi);
|
||||||
#else
|
}
|
||||||
if(ti->term)
|
|
||||||
free(ti->term);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
free(ti);
|
xfree(ti);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHARAT(i) (tk->buffer[tk->buffstart + (i)])
|
#define CHARAT(i) (tk->buffer[tk->buffstart + (i)])
|
||||||
|
|
||||||
static TermKeyResult peekkey(TermKey *tk, void *info, TermKeyKey *key, int force, size_t *nbytep)
|
TermKeyResult peekkey_ti(TermKey *tk, void *info, TermKeyKey *key, int force, size_t *nbytep)
|
||||||
{
|
{
|
||||||
TermKeyTI *ti = info;
|
TermKeyTI *ti = info;
|
||||||
|
|
||||||
if(tk->buffcount == 0)
|
if (tk->buffcount == 0) {
|
||||||
return tk->is_closed ? TERMKEY_RES_EOF : TERMKEY_RES_NONE;
|
return tk->is_closed ? TERMKEY_RES_EOF : TERMKEY_RES_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
struct trie_node *p = ti->root;
|
struct trie_node *p = ti->root;
|
||||||
|
|
||||||
unsigned int pos = 0;
|
unsigned pos = 0;
|
||||||
while(pos < tk->buffcount) {
|
while (pos < tk->buffcount) {
|
||||||
p = lookup_next(p, CHARAT(pos));
|
p = lookup_next(p, CHARAT(pos));
|
||||||
if(!p)
|
if (!p) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
pos++;
|
pos++;
|
||||||
|
|
||||||
if(p->type != TYPE_KEY)
|
if (p->type != TYPE_KEY) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
struct trie_node_key *nk = (struct trie_node_key*)p;
|
struct trie_node_key *nk = (struct trie_node_key *)p;
|
||||||
if(nk->key.type == TERMKEY_TYPE_MOUSE) {
|
if (nk->key.type == TERMKEY_TYPE_MOUSE) {
|
||||||
tk->buffstart += pos;
|
tk->buffstart += pos;
|
||||||
tk->buffcount -= pos;
|
tk->buffcount -= pos;
|
||||||
|
|
||||||
@ -568,14 +514,15 @@ static TermKeyResult peekkey(TermKey *tk, void *info, TermKeyKey *key, int force
|
|||||||
tk->buffstart -= pos;
|
tk->buffstart -= pos;
|
||||||
tk->buffcount += pos;
|
tk->buffcount += pos;
|
||||||
|
|
||||||
if(mouse_result == TERMKEY_RES_KEY)
|
if (mouse_result == TERMKEY_RES_KEY) {
|
||||||
*nbytep += pos;
|
*nbytep += pos;
|
||||||
|
}
|
||||||
|
|
||||||
return mouse_result;
|
return mouse_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
key->type = nk->key.type;
|
key->type = nk->key.type;
|
||||||
key->code.sym = nk->key.sym;
|
key->code.sym = nk->key.sym;
|
||||||
key->modifiers = nk->key.modifier_set;
|
key->modifiers = nk->key.modifier_set;
|
||||||
*nbytep = pos;
|
*nbytep = pos;
|
||||||
return TERMKEY_RES_KEY;
|
return TERMKEY_RES_KEY;
|
||||||
@ -583,8 +530,9 @@ static TermKeyResult peekkey(TermKey *tk, void *info, TermKeyKey *key, int force
|
|||||||
|
|
||||||
// If p is not NULL then we hadn't walked off the end yet, so we have a
|
// If p is not NULL then we hadn't walked off the end yet, so we have a
|
||||||
// partial match
|
// partial match
|
||||||
if(p && !force)
|
if (p && !force) {
|
||||||
return TERMKEY_RES_AGAIN;
|
return TERMKEY_RES_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
return TERMKEY_RES_NONE;
|
return TERMKEY_RES_NONE;
|
||||||
}
|
}
|
||||||
@ -597,39 +545,42 @@ static int insert_seq(TermKeyTI *ti, const char *seq, struct trie_node *node)
|
|||||||
// Unsigned because we'll be using it as an array subscript
|
// Unsigned because we'll be using it as an array subscript
|
||||||
unsigned char b;
|
unsigned char b;
|
||||||
|
|
||||||
while((b = seq[pos])) {
|
while ((b = (unsigned char)seq[pos])) {
|
||||||
struct trie_node *next = lookup_next(p, b);
|
struct trie_node *next = lookup_next(p, b);
|
||||||
if(!next)
|
if (!next) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
p = next;
|
p = next;
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
while((b = seq[pos])) {
|
while ((b = (unsigned char)seq[pos])) {
|
||||||
struct trie_node *next;
|
struct trie_node *next;
|
||||||
if(seq[pos+1])
|
if (seq[pos + 1]) {
|
||||||
// Intermediate node
|
// Intermediate node
|
||||||
next = new_node_arr(0, 0xff);
|
next = new_node_arr(0, 0xff);
|
||||||
else
|
} else {
|
||||||
// Final key node
|
// Final key node
|
||||||
next = node;
|
next = node;
|
||||||
|
}
|
||||||
|
|
||||||
if(!next)
|
if (!next) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
switch(p->type) {
|
switch (p->type) {
|
||||||
case TYPE_ARR:
|
case TYPE_ARR: {
|
||||||
{
|
struct trie_node_arr *nar = (struct trie_node_arr *)p;
|
||||||
struct trie_node_arr *nar = (struct trie_node_arr*)p;
|
if (b < nar->min || b > nar->max) {
|
||||||
if(b < nar->min || b > nar->max) {
|
fprintf(stderr,
|
||||||
fprintf(stderr, "ASSERT FAIL: Trie insert at 0x%02x is outside of extent bounds (0x%02x..0x%02x)\n",
|
"ASSERT FAIL: Trie insert at 0x%02x is outside of extent bounds (0x%02x..0x%02x)\n",
|
||||||
b, nar->min, nar->max);
|
b, nar->min, nar->max);
|
||||||
abort();
|
abort();
|
||||||
}
|
|
||||||
nar->arr[b - nar->min] = next;
|
|
||||||
p = next;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
nar->arr[b - nar->min] = next;
|
||||||
|
p = next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case TYPE_KEY:
|
case TYPE_KEY:
|
||||||
fprintf(stderr, "ASSERT FAIL: Tried to insert child node in TYPE_KEY\n");
|
fprintf(stderr, "ASSERT FAIL: Tried to insert child node in TYPE_KEY\n");
|
||||||
abort();
|
abort();
|
||||||
@ -640,15 +591,3 @@ static int insert_seq(TermKeyTI *ti, const char *seq, struct trie_node *node)
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TermKeyDriver termkey_driver_ti = {
|
|
||||||
.name = "terminfo",
|
|
||||||
|
|
||||||
.new_driver = new_driver,
|
|
||||||
.free_driver = free_driver,
|
|
||||||
|
|
||||||
.start_driver = start_driver,
|
|
||||||
.stop_driver = stop_driver,
|
|
||||||
|
|
||||||
.peekkey = peekkey,
|
|
||||||
};
|
|
7
src/nvim/tui/termkey/driver-ti.h
Normal file
7
src/nvim/tui/termkey/driver-ti.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "nvim/tui/termkey/termkey_defs.h"
|
||||||
|
|
||||||
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
|
# include "tui/termkey/driver-ti.h.generated.h"
|
||||||
|
#endif
|
@ -1,31 +1,29 @@
|
|||||||
#ifndef GUARD_TERMKEY_INTERNAL_H_
|
#pragma once
|
||||||
#define GUARD_TERMKEY_INTERNAL_H_
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "nvim/tui/termkey/termkey_defs.h"
|
||||||
|
|
||||||
#define HAVE_TERMIOS
|
#define HAVE_TERMIOS
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# undef HAVE_TERMIOS
|
# undef HAVE_TERMIOS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "termkey.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#ifdef HAVE_TERMIOS
|
#ifdef HAVE_TERMIOS
|
||||||
# include <termios.h>
|
# include <termios.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#include <BaseTsd.h>
|
# include <BaseTsd.h>
|
||||||
typedef SSIZE_T ssize_t;
|
typedef SSIZE_T ssize_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct TermKeyDriver
|
struct TermKeyDriver {
|
||||||
{
|
const char *name;
|
||||||
const char *name;
|
void *(*new_driver)(TermKey *tk, const char *term);
|
||||||
void *(*new_driver)(TermKey *tk, const char *term);
|
void (*free_driver)(void *info);
|
||||||
void (*free_driver)(void *info);
|
int (*start_driver)(TermKey *tk, void *info);
|
||||||
int (*start_driver)(TermKey *tk, void *info);
|
int (*stop_driver)(TermKey *tk, void *info);
|
||||||
int (*stop_driver)(TermKey *tk, void *info);
|
|
||||||
TermKeyResult (*peekkey)(TermKey *tk, void *info, TermKeyKey *key, int force, size_t *nbytes);
|
TermKeyResult (*peekkey)(TermKey *tk, void *info, TermKeyKey *key, int force, size_t *nbytes);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -38,21 +36,21 @@ struct keyinfo {
|
|||||||
|
|
||||||
struct TermKeyDriverNode;
|
struct TermKeyDriverNode;
|
||||||
struct TermKeyDriverNode {
|
struct TermKeyDriverNode {
|
||||||
struct TermKeyDriver *driver;
|
struct TermKeyDriver *driver;
|
||||||
void *info;
|
void *info;
|
||||||
struct TermKeyDriverNode *next;
|
struct TermKeyDriverNode *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TermKey {
|
struct TermKey {
|
||||||
int fd;
|
int fd;
|
||||||
int flags;
|
int flags;
|
||||||
int canonflags;
|
int canonflags;
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
size_t buffstart; // First offset in buffer
|
size_t buffstart; // First offset in buffer
|
||||||
size_t buffcount; // NUMBER of entires valid in buffer
|
size_t buffcount; // NUMBER of entires valid in buffer
|
||||||
size_t buffsize; // Total malloc'ed size
|
size_t buffsize; // Total malloc'ed size
|
||||||
size_t hightide; /* Position beyond buffstart at which peekkey() should next start
|
size_t hightide; // Position beyond buffstart at which peekkey() should next start
|
||||||
* normally 0, but see also termkey_interpret_csi */
|
// normally 0, but see also termkey_interpret_csi
|
||||||
|
|
||||||
#ifdef HAVE_TERMIOS
|
#ifdef HAVE_TERMIOS
|
||||||
struct termios restore_termios;
|
struct termios restore_termios;
|
||||||
@ -62,12 +60,12 @@ struct TermKey {
|
|||||||
TermKey_Terminfo_Getstr_Hook *ti_getstr_hook;
|
TermKey_Terminfo_Getstr_Hook *ti_getstr_hook;
|
||||||
void *ti_getstr_hook_data;
|
void *ti_getstr_hook_data;
|
||||||
|
|
||||||
int waittime; // msec
|
int waittime; // msec
|
||||||
|
|
||||||
char is_closed;
|
char is_closed;
|
||||||
char is_started;
|
char is_started;
|
||||||
|
|
||||||
int nkeynames;
|
int nkeynames;
|
||||||
const char **keynames;
|
const char **keynames;
|
||||||
|
|
||||||
// There are 32 C0 codes
|
// There are 32 C0 codes
|
||||||
@ -78,7 +76,7 @@ struct TermKey {
|
|||||||
// Now some "protected" methods for the driver to call but which we don't
|
// Now some "protected" methods for the driver to call but which we don't
|
||||||
// want exported as real symbols in the library
|
// want exported as real symbols in the library
|
||||||
struct {
|
struct {
|
||||||
void (*emit_codepoint)(TermKey *tk, long codepoint, TermKeyKey *key);
|
void (*emit_codepoint)(TermKey *tk, int codepoint, TermKeyKey *key);
|
||||||
TermKeyResult (*peekkey_simple)(TermKey *tk, TermKeyKey *key, int force, size_t *nbytes);
|
TermKeyResult (*peekkey_simple)(TermKey *tk, TermKeyKey *key, int force, size_t *nbytes);
|
||||||
TermKeyResult (*peekkey_mouse)(TermKey *tk, TermKeyKey *key, size_t *nbytes);
|
TermKeyResult (*peekkey_mouse)(TermKey *tk, TermKeyKey *key, size_t *nbytes);
|
||||||
} method;
|
} method;
|
||||||
@ -86,27 +84,26 @@ struct TermKey {
|
|||||||
|
|
||||||
static inline void termkey_key_get_linecol(const TermKeyKey *key, int *line, int *col)
|
static inline void termkey_key_get_linecol(const TermKeyKey *key, int *line, int *col)
|
||||||
{
|
{
|
||||||
if(col)
|
if (col) {
|
||||||
*col = (unsigned char)key->code.mouse[1] | ((unsigned char)key->code.mouse[3] & 0x0f) << 8;
|
*col = (unsigned char)key->code.mouse[1] | ((unsigned char)key->code.mouse[3] & 0x0f) << 8;
|
||||||
|
}
|
||||||
|
|
||||||
if(line)
|
if (line) {
|
||||||
*line = (unsigned char)key->code.mouse[2] | ((unsigned char)key->code.mouse[3] & 0x70) << 4;
|
*line = (unsigned char)key->code.mouse[2] | ((unsigned char)key->code.mouse[3] & 0x70) << 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void termkey_key_set_linecol(TermKeyKey *key, int line, int col)
|
static inline void termkey_key_set_linecol(TermKeyKey *key, int line, int col)
|
||||||
{
|
{
|
||||||
if(line > 0xfff)
|
if (line > 0xfff) {
|
||||||
line = 0xfff;
|
line = 0xfff;
|
||||||
|
}
|
||||||
|
|
||||||
if(col > 0x7ff)
|
if (col > 0x7ff) {
|
||||||
col = 0x7ff;
|
col = 0x7ff;
|
||||||
|
}
|
||||||
|
|
||||||
key->code.mouse[1] = (line & 0x0ff);
|
key->code.mouse[1] = (char)(line & 0x0ff);
|
||||||
key->code.mouse[2] = (col & 0x0ff);
|
key->code.mouse[2] = (char)(col & 0x0ff);
|
||||||
key->code.mouse[3] = (line & 0xf00) >> 8 | (col & 0x300) >> 4;
|
key->code.mouse[3] = (line & 0xf00) >> 8 | (col & 0x300) >> 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern struct TermKeyDriver termkey_driver_csi;
|
|
||||||
extern struct TermKeyDriver termkey_driver_ti;
|
|
||||||
|
|
||||||
#endif
|
|
1315
src/nvim/tui/termkey/termkey.c
Normal file
1315
src/nvim/tui/termkey/termkey.c
Normal file
File diff suppressed because it is too large
Load Diff
10
src/nvim/tui/termkey/termkey.h
Normal file
10
src/nvim/tui/termkey/termkey.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "nvim/tui/termkey/termkey_defs.h"
|
||||||
|
|
||||||
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
|
# include "tui/termkey/termkey.h.generated.h"
|
||||||
|
#endif
|
199
src/nvim/tui/termkey/termkey_defs.h
Normal file
199
src/nvim/tui/termkey/termkey_defs.h
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unibilium.h>
|
||||||
|
#include <uv.h>
|
||||||
|
|
||||||
|
#include "nvim/event/defs.h"
|
||||||
|
#include "nvim/tui/tui_defs.h"
|
||||||
|
#include "nvim/types_defs.h"
|
||||||
|
|
||||||
|
typedef struct TermKey TermKey;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
TermKey *tk;
|
||||||
|
int saved_string_id;
|
||||||
|
char *saved_string;
|
||||||
|
} TermKeyCsi;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TERMKEY_RES_NONE,
|
||||||
|
TERMKEY_RES_KEY,
|
||||||
|
TERMKEY_RES_EOF,
|
||||||
|
TERMKEY_RES_AGAIN,
|
||||||
|
TERMKEY_RES_ERROR,
|
||||||
|
} TermKeyResult;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TERMKEY_SYM_UNKNOWN = -1,
|
||||||
|
TERMKEY_SYM_NONE = 0,
|
||||||
|
|
||||||
|
// Special names in C0
|
||||||
|
TERMKEY_SYM_BACKSPACE,
|
||||||
|
TERMKEY_SYM_TAB,
|
||||||
|
TERMKEY_SYM_ENTER,
|
||||||
|
TERMKEY_SYM_ESCAPE,
|
||||||
|
|
||||||
|
// Special names in G0
|
||||||
|
TERMKEY_SYM_SPACE,
|
||||||
|
TERMKEY_SYM_DEL,
|
||||||
|
|
||||||
|
// Special keys
|
||||||
|
TERMKEY_SYM_UP,
|
||||||
|
TERMKEY_SYM_DOWN,
|
||||||
|
TERMKEY_SYM_LEFT,
|
||||||
|
TERMKEY_SYM_RIGHT,
|
||||||
|
TERMKEY_SYM_BEGIN,
|
||||||
|
TERMKEY_SYM_FIND,
|
||||||
|
TERMKEY_SYM_INSERT,
|
||||||
|
TERMKEY_SYM_DELETE,
|
||||||
|
TERMKEY_SYM_SELECT,
|
||||||
|
TERMKEY_SYM_PAGEUP,
|
||||||
|
TERMKEY_SYM_PAGEDOWN,
|
||||||
|
TERMKEY_SYM_HOME,
|
||||||
|
TERMKEY_SYM_END,
|
||||||
|
|
||||||
|
// Special keys from terminfo
|
||||||
|
TERMKEY_SYM_CANCEL,
|
||||||
|
TERMKEY_SYM_CLEAR,
|
||||||
|
TERMKEY_SYM_CLOSE,
|
||||||
|
TERMKEY_SYM_COMMAND,
|
||||||
|
TERMKEY_SYM_COPY,
|
||||||
|
TERMKEY_SYM_EXIT,
|
||||||
|
TERMKEY_SYM_HELP,
|
||||||
|
TERMKEY_SYM_MARK,
|
||||||
|
TERMKEY_SYM_MESSAGE,
|
||||||
|
TERMKEY_SYM_MOVE,
|
||||||
|
TERMKEY_SYM_OPEN,
|
||||||
|
TERMKEY_SYM_OPTIONS,
|
||||||
|
TERMKEY_SYM_PRINT,
|
||||||
|
TERMKEY_SYM_REDO,
|
||||||
|
TERMKEY_SYM_REFERENCE,
|
||||||
|
TERMKEY_SYM_REFRESH,
|
||||||
|
TERMKEY_SYM_REPLACE,
|
||||||
|
TERMKEY_SYM_RESTART,
|
||||||
|
TERMKEY_SYM_RESUME,
|
||||||
|
TERMKEY_SYM_SAVE,
|
||||||
|
TERMKEY_SYM_SUSPEND,
|
||||||
|
TERMKEY_SYM_UNDO,
|
||||||
|
|
||||||
|
// Numeric keypad special keys
|
||||||
|
TERMKEY_SYM_KP0,
|
||||||
|
TERMKEY_SYM_KP1,
|
||||||
|
TERMKEY_SYM_KP2,
|
||||||
|
TERMKEY_SYM_KP3,
|
||||||
|
TERMKEY_SYM_KP4,
|
||||||
|
TERMKEY_SYM_KP5,
|
||||||
|
TERMKEY_SYM_KP6,
|
||||||
|
TERMKEY_SYM_KP7,
|
||||||
|
TERMKEY_SYM_KP8,
|
||||||
|
TERMKEY_SYM_KP9,
|
||||||
|
TERMKEY_SYM_KPENTER,
|
||||||
|
TERMKEY_SYM_KPPLUS,
|
||||||
|
TERMKEY_SYM_KPMINUS,
|
||||||
|
TERMKEY_SYM_KPMULT,
|
||||||
|
TERMKEY_SYM_KPDIV,
|
||||||
|
TERMKEY_SYM_KPCOMMA,
|
||||||
|
TERMKEY_SYM_KPPERIOD,
|
||||||
|
TERMKEY_SYM_KPEQUALS,
|
||||||
|
|
||||||
|
// et cetera ad nauseum
|
||||||
|
TERMKEY_N_SYMS,
|
||||||
|
} TermKeySym;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TERMKEY_TYPE_UNICODE,
|
||||||
|
TERMKEY_TYPE_FUNCTION,
|
||||||
|
TERMKEY_TYPE_KEYSYM,
|
||||||
|
TERMKEY_TYPE_MOUSE,
|
||||||
|
TERMKEY_TYPE_POSITION,
|
||||||
|
TERMKEY_TYPE_MODEREPORT,
|
||||||
|
TERMKEY_TYPE_DCS,
|
||||||
|
TERMKEY_TYPE_OSC,
|
||||||
|
// add other recognised types here
|
||||||
|
|
||||||
|
TERMKEY_TYPE_UNKNOWN_CSI = -1,
|
||||||
|
} TermKeyType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TERMKEY_MOUSE_UNKNOWN,
|
||||||
|
TERMKEY_MOUSE_PRESS,
|
||||||
|
TERMKEY_MOUSE_DRAG,
|
||||||
|
TERMKEY_MOUSE_RELEASE,
|
||||||
|
} TermKeyMouseEvent;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TERMKEY_KEYMOD_SHIFT = 1 << 0,
|
||||||
|
TERMKEY_KEYMOD_ALT = 1 << 1,
|
||||||
|
TERMKEY_KEYMOD_CTRL = 1 << 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const unsigned char *param;
|
||||||
|
size_t length;
|
||||||
|
} TermKeyCsiParam;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TERMKEY_FLAG_NOINTERPRET = 1 << 0, // Do not interpret C0//DEL codes if possible
|
||||||
|
TERMKEY_FLAG_CONVERTKP = 1 << 1, // Convert KP codes to regular keypresses
|
||||||
|
TERMKEY_FLAG_RAW = 1 << 2, // Input is raw bytes, not UTF-8
|
||||||
|
TERMKEY_FLAG_UTF8 = 1 << 3, // Input is definitely UTF-8
|
||||||
|
TERMKEY_FLAG_NOTERMIOS = 1 << 4, // Do not make initial termios calls on construction
|
||||||
|
TERMKEY_FLAG_SPACESYMBOL = 1 << 5, // Sets TERMKEY_CANON_SPACESYMBOL
|
||||||
|
TERMKEY_FLAG_CTRLC = 1 << 6, // Allow Ctrl-C to be read as normal, disabling SIGINT
|
||||||
|
TERMKEY_FLAG_EINTR = 1 << 7, // Return ERROR on signal (EINTR) rather than retry
|
||||||
|
TERMKEY_FLAG_NOSTART = 1 << 8, // Do not call termkey_start() in constructor
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TERMKEY_CANON_SPACESYMBOL = 1 << 0, // Space is symbolic rather than Unicode
|
||||||
|
TERMKEY_CANON_DELBS = 1 << 1, // Del is converted to Backspace
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
TermKeyType type;
|
||||||
|
union {
|
||||||
|
int codepoint; // TERMKEY_TYPE_UNICODE
|
||||||
|
int number; // TERMKEY_TYPE_FUNCTION
|
||||||
|
TermKeySym sym; // TERMKEY_TYPE_KEYSYM
|
||||||
|
char mouse[4]; // TERMKEY_TYPE_MOUSE
|
||||||
|
// opaque. see termkey_interpret_mouse
|
||||||
|
} code;
|
||||||
|
|
||||||
|
int modifiers;
|
||||||
|
|
||||||
|
// Any Unicode character can be UTF-8 encoded in no more than 6 bytes, plus
|
||||||
|
// terminating NUL
|
||||||
|
char utf8[7];
|
||||||
|
} TermKeyKey;
|
||||||
|
|
||||||
|
// Mostly-undocumented hooks for doing evil evil things
|
||||||
|
typedef const char *TermKey_Terminfo_Getstr_Hook(const char *name, const char *value, void *data);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TERMKEY_FORMAT_LONGMOD = 1 << 0, // Shift-... instead of S-...
|
||||||
|
TERMKEY_FORMAT_CARETCTRL = 1 << 1, // ^X instead of C-X
|
||||||
|
TERMKEY_FORMAT_ALTISMETA = 1 << 2, // Meta- or M- instead of Alt- or A-
|
||||||
|
TERMKEY_FORMAT_WRAPBRACKET = 1 << 3, // Wrap special keys in brackets like <Escape>
|
||||||
|
TERMKEY_FORMAT_SPACEMOD = 1 << 4, // M Foo instead of M-Foo
|
||||||
|
TERMKEY_FORMAT_LOWERMOD = 1 << 5, // meta or m instead of Meta or M
|
||||||
|
TERMKEY_FORMAT_LOWERSPACE = 1 << 6, // page down instead of PageDown
|
||||||
|
|
||||||
|
TERMKEY_FORMAT_MOUSE_POS = 1 << 8, // Include mouse position if relevant; @ col,line
|
||||||
|
} TermKeyFormat;
|
||||||
|
|
||||||
|
// Some useful combinations
|
||||||
|
|
||||||
|
#define TERMKEY_FORMAT_VIM (TermKeyFormat)(TERMKEY_FORMAT_ALTISMETA|TERMKEY_FORMAT_WRAPBRACKET)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
TermKey *tk;
|
||||||
|
|
||||||
|
unibi_term *unibi; // only valid until first 'start' call
|
||||||
|
|
||||||
|
struct trie_node *root;
|
||||||
|
|
||||||
|
char *start_string;
|
||||||
|
char *stop_string;
|
||||||
|
} TermKeyTI;
|
File diff suppressed because it is too large
Load Diff
@ -1,256 +0,0 @@
|
|||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef GUARD_TERMKEY_H_
|
|
||||||
#define GUARD_TERMKEY_H_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#define TERMKEY_VERSION_MAJOR 0
|
|
||||||
#define TERMKEY_VERSION_MINOR 22
|
|
||||||
|
|
||||||
#define TERMKEY_CHECK_VERSION \
|
|
||||||
termkey_check_version(TERMKEY_VERSION_MAJOR, TERMKEY_VERSION_MINOR)
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TERMKEY_SYM_UNKNOWN = -1,
|
|
||||||
TERMKEY_SYM_NONE = 0,
|
|
||||||
|
|
||||||
/* Special names in C0 */
|
|
||||||
TERMKEY_SYM_BACKSPACE,
|
|
||||||
TERMKEY_SYM_TAB,
|
|
||||||
TERMKEY_SYM_ENTER,
|
|
||||||
TERMKEY_SYM_ESCAPE,
|
|
||||||
|
|
||||||
/* Special names in G0 */
|
|
||||||
TERMKEY_SYM_SPACE,
|
|
||||||
TERMKEY_SYM_DEL,
|
|
||||||
|
|
||||||
/* Special keys */
|
|
||||||
TERMKEY_SYM_UP,
|
|
||||||
TERMKEY_SYM_DOWN,
|
|
||||||
TERMKEY_SYM_LEFT,
|
|
||||||
TERMKEY_SYM_RIGHT,
|
|
||||||
TERMKEY_SYM_BEGIN,
|
|
||||||
TERMKEY_SYM_FIND,
|
|
||||||
TERMKEY_SYM_INSERT,
|
|
||||||
TERMKEY_SYM_DELETE,
|
|
||||||
TERMKEY_SYM_SELECT,
|
|
||||||
TERMKEY_SYM_PAGEUP,
|
|
||||||
TERMKEY_SYM_PAGEDOWN,
|
|
||||||
TERMKEY_SYM_HOME,
|
|
||||||
TERMKEY_SYM_END,
|
|
||||||
|
|
||||||
/* Special keys from terminfo */
|
|
||||||
TERMKEY_SYM_CANCEL,
|
|
||||||
TERMKEY_SYM_CLEAR,
|
|
||||||
TERMKEY_SYM_CLOSE,
|
|
||||||
TERMKEY_SYM_COMMAND,
|
|
||||||
TERMKEY_SYM_COPY,
|
|
||||||
TERMKEY_SYM_EXIT,
|
|
||||||
TERMKEY_SYM_HELP,
|
|
||||||
TERMKEY_SYM_MARK,
|
|
||||||
TERMKEY_SYM_MESSAGE,
|
|
||||||
TERMKEY_SYM_MOVE,
|
|
||||||
TERMKEY_SYM_OPEN,
|
|
||||||
TERMKEY_SYM_OPTIONS,
|
|
||||||
TERMKEY_SYM_PRINT,
|
|
||||||
TERMKEY_SYM_REDO,
|
|
||||||
TERMKEY_SYM_REFERENCE,
|
|
||||||
TERMKEY_SYM_REFRESH,
|
|
||||||
TERMKEY_SYM_REPLACE,
|
|
||||||
TERMKEY_SYM_RESTART,
|
|
||||||
TERMKEY_SYM_RESUME,
|
|
||||||
TERMKEY_SYM_SAVE,
|
|
||||||
TERMKEY_SYM_SUSPEND,
|
|
||||||
TERMKEY_SYM_UNDO,
|
|
||||||
|
|
||||||
/* Numeric keypad special keys */
|
|
||||||
TERMKEY_SYM_KP0,
|
|
||||||
TERMKEY_SYM_KP1,
|
|
||||||
TERMKEY_SYM_KP2,
|
|
||||||
TERMKEY_SYM_KP3,
|
|
||||||
TERMKEY_SYM_KP4,
|
|
||||||
TERMKEY_SYM_KP5,
|
|
||||||
TERMKEY_SYM_KP6,
|
|
||||||
TERMKEY_SYM_KP7,
|
|
||||||
TERMKEY_SYM_KP8,
|
|
||||||
TERMKEY_SYM_KP9,
|
|
||||||
TERMKEY_SYM_KPENTER,
|
|
||||||
TERMKEY_SYM_KPPLUS,
|
|
||||||
TERMKEY_SYM_KPMINUS,
|
|
||||||
TERMKEY_SYM_KPMULT,
|
|
||||||
TERMKEY_SYM_KPDIV,
|
|
||||||
TERMKEY_SYM_KPCOMMA,
|
|
||||||
TERMKEY_SYM_KPPERIOD,
|
|
||||||
TERMKEY_SYM_KPEQUALS,
|
|
||||||
|
|
||||||
/* et cetera ad nauseum */
|
|
||||||
TERMKEY_N_SYMS
|
|
||||||
} TermKeySym;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TERMKEY_TYPE_UNICODE,
|
|
||||||
TERMKEY_TYPE_FUNCTION,
|
|
||||||
TERMKEY_TYPE_KEYSYM,
|
|
||||||
TERMKEY_TYPE_MOUSE,
|
|
||||||
TERMKEY_TYPE_POSITION,
|
|
||||||
TERMKEY_TYPE_MODEREPORT,
|
|
||||||
TERMKEY_TYPE_DCS,
|
|
||||||
TERMKEY_TYPE_OSC,
|
|
||||||
/* add other recognised types here */
|
|
||||||
|
|
||||||
TERMKEY_TYPE_UNKNOWN_CSI = -1
|
|
||||||
} TermKeyType;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TERMKEY_RES_NONE,
|
|
||||||
TERMKEY_RES_KEY,
|
|
||||||
TERMKEY_RES_EOF,
|
|
||||||
TERMKEY_RES_AGAIN,
|
|
||||||
TERMKEY_RES_ERROR
|
|
||||||
} TermKeyResult;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TERMKEY_MOUSE_UNKNOWN,
|
|
||||||
TERMKEY_MOUSE_PRESS,
|
|
||||||
TERMKEY_MOUSE_DRAG,
|
|
||||||
TERMKEY_MOUSE_RELEASE
|
|
||||||
} TermKeyMouseEvent;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
TERMKEY_KEYMOD_SHIFT = 1 << 0,
|
|
||||||
TERMKEY_KEYMOD_ALT = 1 << 1,
|
|
||||||
TERMKEY_KEYMOD_CTRL = 1 << 2
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
TermKeyType type;
|
|
||||||
union {
|
|
||||||
long codepoint; /* TERMKEY_TYPE_UNICODE */
|
|
||||||
int number; /* TERMKEY_TYPE_FUNCTION */
|
|
||||||
TermKeySym sym; /* TERMKEY_TYPE_KEYSYM */
|
|
||||||
char mouse[4]; /* TERMKEY_TYPE_MOUSE */
|
|
||||||
/* opaque. see termkey_interpret_mouse */
|
|
||||||
} code;
|
|
||||||
|
|
||||||
int modifiers;
|
|
||||||
|
|
||||||
/* Any Unicode character can be UTF-8 encoded in no more than 6 bytes, plus
|
|
||||||
* terminating NUL */
|
|
||||||
char utf8[7];
|
|
||||||
} TermKeyKey;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const unsigned char *param;
|
|
||||||
size_t length;
|
|
||||||
} TermKeyCsiParam;
|
|
||||||
|
|
||||||
typedef struct TermKey TermKey;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
TERMKEY_FLAG_NOINTERPRET = 1 << 0, /* Do not interpret C0//DEL codes if possible */
|
|
||||||
TERMKEY_FLAG_CONVERTKP = 1 << 1, /* Convert KP codes to regular keypresses */
|
|
||||||
TERMKEY_FLAG_RAW = 1 << 2, /* Input is raw bytes, not UTF-8 */
|
|
||||||
TERMKEY_FLAG_UTF8 = 1 << 3, /* Input is definitely UTF-8 */
|
|
||||||
TERMKEY_FLAG_NOTERMIOS = 1 << 4, /* Do not make initial termios calls on construction */
|
|
||||||
TERMKEY_FLAG_SPACESYMBOL = 1 << 5, /* Sets TERMKEY_CANON_SPACESYMBOL */
|
|
||||||
TERMKEY_FLAG_CTRLC = 1 << 6, /* Allow Ctrl-C to be read as normal, disabling SIGINT */
|
|
||||||
TERMKEY_FLAG_EINTR = 1 << 7, /* Return ERROR on signal (EINTR) rather than retry */
|
|
||||||
TERMKEY_FLAG_NOSTART = 1 << 8 /* Do not call termkey_start() in constructor */
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
TERMKEY_CANON_SPACESYMBOL = 1 << 0, /* Space is symbolic rather than Unicode */
|
|
||||||
TERMKEY_CANON_DELBS = 1 << 1 /* Del is converted to Backspace */
|
|
||||||
};
|
|
||||||
|
|
||||||
void termkey_check_version(int major, int minor);
|
|
||||||
|
|
||||||
TermKey *termkey_new(int fd, int flags);
|
|
||||||
TermKey *termkey_new_abstract(const char *term, int flags);
|
|
||||||
void termkey_free(TermKey *tk);
|
|
||||||
void termkey_destroy(TermKey *tk);
|
|
||||||
|
|
||||||
/* Mostly-undocumented hooks for doing evil evil things */
|
|
||||||
typedef const char *TermKey_Terminfo_Getstr_Hook(const char *name, const char *value, void *data);
|
|
||||||
void termkey_hook_terminfo_getstr(TermKey *tk, TermKey_Terminfo_Getstr_Hook *hookfn, void *data);
|
|
||||||
|
|
||||||
int termkey_start(TermKey *tk);
|
|
||||||
int termkey_stop(TermKey *tk);
|
|
||||||
int termkey_is_started(TermKey *tk);
|
|
||||||
|
|
||||||
int termkey_get_fd(TermKey *tk);
|
|
||||||
|
|
||||||
int termkey_get_flags(TermKey *tk);
|
|
||||||
void termkey_set_flags(TermKey *tk, int newflags);
|
|
||||||
|
|
||||||
int termkey_get_waittime(TermKey *tk);
|
|
||||||
void termkey_set_waittime(TermKey *tk, int msec);
|
|
||||||
|
|
||||||
int termkey_get_canonflags(TermKey *tk);
|
|
||||||
void termkey_set_canonflags(TermKey *tk, int);
|
|
||||||
|
|
||||||
size_t termkey_get_buffer_size(TermKey *tk);
|
|
||||||
int termkey_set_buffer_size(TermKey *tk, size_t size);
|
|
||||||
|
|
||||||
size_t termkey_get_buffer_remaining(TermKey *tk);
|
|
||||||
|
|
||||||
void termkey_canonicalise(TermKey *tk, TermKeyKey *key);
|
|
||||||
|
|
||||||
TermKeyResult termkey_getkey(TermKey *tk, TermKeyKey *key);
|
|
||||||
TermKeyResult termkey_getkey_force(TermKey *tk, TermKeyKey *key);
|
|
||||||
TermKeyResult termkey_waitkey(TermKey *tk, TermKeyKey *key);
|
|
||||||
|
|
||||||
TermKeyResult termkey_advisereadable(TermKey *tk);
|
|
||||||
|
|
||||||
size_t termkey_push_bytes(TermKey *tk, const char *bytes, size_t len);
|
|
||||||
|
|
||||||
TermKeySym termkey_register_keyname(TermKey *tk, TermKeySym sym, const char *name);
|
|
||||||
const char *termkey_get_keyname(TermKey *tk, TermKeySym sym);
|
|
||||||
const char *termkey_lookup_keyname(TermKey *tk, const char *str, TermKeySym *sym);
|
|
||||||
|
|
||||||
TermKeySym termkey_keyname2sym(TermKey *tk, const char *keyname);
|
|
||||||
|
|
||||||
TermKeyResult termkey_interpret_mouse(TermKey *tk, const TermKeyKey *key, TermKeyMouseEvent *event, int *button, int *line, int *col);
|
|
||||||
|
|
||||||
TermKeyResult termkey_interpret_position(TermKey *tk, const TermKeyKey *key, int *line, int *col);
|
|
||||||
|
|
||||||
TermKeyResult termkey_interpret_modereport(TermKey *tk, const TermKeyKey *key, int *initial, int *mode, int *value);
|
|
||||||
|
|
||||||
TermKeyResult termkey_interpret_csi(TermKey *tk, const TermKeyKey *key, TermKeyCsiParam params[], size_t *nparams, unsigned long *cmd);
|
|
||||||
|
|
||||||
TermKeyResult termkey_interpret_csi_param(TermKeyCsiParam param, long *paramp, long subparams[], size_t *nsubparams);
|
|
||||||
|
|
||||||
TermKeyResult termkey_interpret_string(TermKey *tk, const TermKeyKey *key, const char **strp);
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TERMKEY_FORMAT_LONGMOD = 1 << 0, /* Shift-... instead of S-... */
|
|
||||||
TERMKEY_FORMAT_CARETCTRL = 1 << 1, /* ^X instead of C-X */
|
|
||||||
TERMKEY_FORMAT_ALTISMETA = 1 << 2, /* Meta- or M- instead of Alt- or A- */
|
|
||||||
TERMKEY_FORMAT_WRAPBRACKET = 1 << 3, /* Wrap special keys in brackets like <Escape> */
|
|
||||||
TERMKEY_FORMAT_SPACEMOD = 1 << 4, /* M Foo instead of M-Foo */
|
|
||||||
TERMKEY_FORMAT_LOWERMOD = 1 << 5, /* meta or m instead of Meta or M */
|
|
||||||
TERMKEY_FORMAT_LOWERSPACE = 1 << 6, /* page down instead of PageDown */
|
|
||||||
|
|
||||||
TERMKEY_FORMAT_MOUSE_POS = 1 << 8 /* Include mouse position if relevant; @ col,line */
|
|
||||||
} TermKeyFormat;
|
|
||||||
|
|
||||||
/* Some useful combinations */
|
|
||||||
|
|
||||||
#define TERMKEY_FORMAT_VIM (TermKeyFormat)(TERMKEY_FORMAT_ALTISMETA|TERMKEY_FORMAT_WRAPBRACKET)
|
|
||||||
#define TERMKEY_FORMAT_URWID (TermKeyFormat)(TERMKEY_FORMAT_LONGMOD|TERMKEY_FORMAT_ALTISMETA| \
|
|
||||||
TERMKEY_FORMAT_LOWERMOD|TERMKEY_FORMAT_SPACEMOD|TERMKEY_FORMAT_LOWERSPACE)
|
|
||||||
|
|
||||||
size_t termkey_strfkey(TermKey *tk, char *buffer, size_t len, TermKeyKey *key, TermKeyFormat format);
|
|
||||||
const char *termkey_strpkey(TermKey *tk, const char *str, TermKeyKey *key, TermKeyFormat format);
|
|
||||||
|
|
||||||
int termkey_keycmp(TermKey *tk, const TermKeyKey *key1, const TermKeyKey *key2);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,8 +1,7 @@
|
|||||||
#include "vterm_internal.h"
|
#include "vterm_internal.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "utf8.h"
|
#include "nvim/tui/termkey/termkey.h"
|
||||||
|
|
||||||
void vterm_keyboard_unichar(VTerm *vt, uint32_t c, VTermModifier mod)
|
void vterm_keyboard_unichar(VTerm *vt, uint32_t c, VTermModifier mod)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "vterm_internal.h"
|
#include "vterm_internal.h"
|
||||||
|
|
||||||
#include "utf8.h"
|
#include "nvim/tui/termkey/termkey.h"
|
||||||
|
|
||||||
static void output_mouse(VTermState *state, int code, int pressed, int modifiers, int col, int row)
|
static void output_mouse(VTermState *state, int code, int pressed, int modifiers, int col, int row)
|
||||||
{
|
{
|
||||||
|
@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "nvim/mbyte.h"
|
||||||
|
#include "nvim/tui/termkey/termkey.h"
|
||||||
|
|
||||||
#include "rect.h"
|
#include "rect.h"
|
||||||
#include "utf8.h"
|
|
||||||
|
|
||||||
#define UNICODE_SPACE 0x20
|
#define UNICODE_SPACE 0x20
|
||||||
#define UNICODE_LINEFEED 0x0a
|
#define UNICODE_LINEFEED 0x0a
|
||||||
@ -922,7 +923,7 @@ static size_t _get_chars(const VTermScreen *screen, const int utf8, void *buffer
|
|||||||
|
|
||||||
#define PUT(c) \
|
#define PUT(c) \
|
||||||
if(utf8) { \
|
if(utf8) { \
|
||||||
size_t thislen = utf8_seqlen(c); \
|
size_t thislen = utf_char2len(c); \
|
||||||
if(buffer && outpos + thislen <= len) \
|
if(buffer && outpos + thislen <= len) \
|
||||||
outpos += fill_utf8((c), (char *)buffer + outpos); \
|
outpos += fill_utf8((c), (char *)buffer + outpos); \
|
||||||
else \
|
else \
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
/* The following functions copied and adapted from libtermkey
|
|
||||||
*
|
|
||||||
* http://www.leonerd.org.uk/code/libtermkey/
|
|
||||||
*/
|
|
||||||
static inline unsigned int utf8_seqlen(long codepoint)
|
|
||||||
{
|
|
||||||
if(codepoint < 0x0000080) return 1;
|
|
||||||
if(codepoint < 0x0000800) return 2;
|
|
||||||
if(codepoint < 0x0010000) return 3;
|
|
||||||
if(codepoint < 0x0200000) return 4;
|
|
||||||
if(codepoint < 0x4000000) return 5;
|
|
||||||
return 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Does NOT NUL-terminate the buffer */
|
|
||||||
static int fill_utf8(long codepoint, char *str)
|
|
||||||
{
|
|
||||||
int nbytes = utf8_seqlen(codepoint);
|
|
||||||
|
|
||||||
// This is easier done backwards
|
|
||||||
int b = nbytes;
|
|
||||||
while(b > 1) {
|
|
||||||
b--;
|
|
||||||
str[b] = 0x80 | (codepoint & 0x3f);
|
|
||||||
codepoint >>= 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(nbytes) {
|
|
||||||
case 1: str[0] = (codepoint & 0x7f); break;
|
|
||||||
case 2: str[0] = 0xc0 | (codepoint & 0x1f); break;
|
|
||||||
case 3: str[0] = 0xe0 | (codepoint & 0x0f); break;
|
|
||||||
case 4: str[0] = 0xf0 | (codepoint & 0x07); break;
|
|
||||||
case 5: str[0] = 0xf8 | (codepoint & 0x03); break;
|
|
||||||
case 6: str[0] = 0xfc | (codepoint & 0x01); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nbytes;
|
|
||||||
}
|
|
||||||
/* end copy */
|
|
Loading…
Reference in New Issue
Block a user