#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "nvim/macros_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/tui/termkey/driver-csi.h"
#include "nvim/tui/termkey/driver-ti.h"
#include "nvim/tui/termkey/termkey-internal.h"
#include "nvim/tui/termkey/termkey.h"
#include "nvim/tui/termkey/termkey_defs.h"
#ifndef _WIN32
// Include these directly instead of <termios.h> which is system-dependent. #31704
# include <poll.h> // IWYU pragma: keep
# include <strings.h> // IWYU pragma: keep
# include <unistd.h> // IWYU pragma: keep
#else
# include <io.h>
#endif
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "tui/termkey/termkey.c.generated.h"
#endif
#ifdef _MSC_VER
# define strcaseeq(a, b) (_stricmp(a, b) == 0)
#else
# define strcaseeq(a, b) (strcasecmp(a, b) == 0)
#endif
struct TermKeyDriver termkey_driver_ti = {
.name = "terminfo",
.new_driver = new_driver_ti,
.free_driver = free_driver_ti,
.start_driver = start_driver_ti,
.stop_driver = stop_driver_ti,
.peekkey = peekkey_ti,
};
struct TermKeyDriver termkey_driver_csi = {
.name = "CSI",
.new_driver = new_driver_csi,
.free_driver = free_driver_csi,
.peekkey = peekkey_csi,
};
static struct TermKeyDriver *drivers[] = {
&termkey_driver_ti,
&termkey_driver_csi,
NULL,
};
static struct {
TermKeySym sym;
const char *name;
} keynames[] = {
{ TERMKEY_SYM_NONE, "NONE" },
{ TERMKEY_SYM_BACKSPACE, "Backspace" },
{ TERMKEY_SYM_TAB, "Tab" },
{ TERMKEY_SYM_ENTER, "Enter" },
{ TERMKEY_SYM_ESCAPE, "Escape" },
{ TERMKEY_SYM_SPACE, "Space" },
{ TERMKEY_SYM_DEL, "DEL" },
{ TERMKEY_SYM_UP, "Up" },
{ TERMKEY_SYM_DOWN, "Down" },
{ TERMKEY_SYM_LEFT, "Left" },
{ TERMKEY_SYM_RIGHT, "Right" },
{ TERMKEY_SYM_BEGIN, "Begin" },
{ TERMKEY_SYM_FIND, "Find" },
{ TERMKEY_SYM_INSERT, "Insert" },
{ TERMKEY_SYM_DELETE, "Delete" },
{ TERMKEY_SYM_SELECT, "Select" },
{ TERMKEY_SYM_PAGEUP, "PageUp" },
{ TERMKEY_SYM_PAGEDOWN, "PageDown" },
{ TERMKEY_SYM_HOME, "Home" },
{ TERMKEY_SYM_END, "End" },
{ TERMKEY_SYM_CANCEL, "Cancel" },
{ TERMKEY_SYM_CLEAR, "Clear" },
{ TERMKEY_SYM_CLOSE, "Close" },
{ TERMKEY_SYM_COMMAND, "Command" },
{ TERMKEY_SYM_COPY, "Copy" },
{ TERMKEY_SYM_EXIT, "Exit" },
{ TERMKEY_SYM_HELP, "Help" },
{ TERMKEY_SYM_MARK, "Mark" },
{ TERMKEY_SYM_MESSAGE, "Message" },
{ TERMKEY_SYM_MOVE, "Move" },
{ TERMKEY_SYM_OPEN, "Open" },
{ TERMKEY_SYM_OPTIONS, "Options" },
{ TERMKEY_SYM_PRINT, "Print" },
{ TERMKEY_SYM_REDO, "Redo" },
{ TERMKEY_SYM_REFERENCE, "Reference" },
{ TERMKEY_SYM_REFRESH, "Refresh" },
{ TERMKEY_SYM_REPLACE, "Replace" },
{ TERMKEY_SYM_RESTART, "Restart" },
{ TERMKEY_SYM_RESUME, "Resume" },
{ TERMKEY_SYM_SAVE, "Save" },
{ TERMKEY_SYM_SUSPEND, "Suspend" },
{ TERMKEY_SYM_UNDO, "Undo" },
{ TERMKEY_SYM_KP0, "KP0" },
{ TERMKEY_SYM_KP1, "KP1" },
{ TERMKEY_SYM_KP2, "KP2" },
{ TERMKEY_SYM_KP3, "KP3" },
{ TERMKEY_SYM_KP4, "KP4" },
{ TERMKEY_SYM_KP5, "KP5" },
{ TERMKEY_SYM_KP6, "KP6" },
{ TERMKEY_SYM_KP7, "KP7" },
{ TERMKEY_SYM_KP8, "KP8" },
{ TERMKEY_SYM_KP9, "KP9" },
{ TERMKEY_SYM_KPENTER, "KPEnter" },
{ TERMKEY_SYM_KPPLUS, "KPPlus" },
{ TERMKEY_SYM_KPMINUS, "KPMinus" },
{ TERMKEY_SYM_KPMULT, "KPMult" },
{ TERMKEY_SYM_KPDIV, "KPDiv" },
{ TERMKEY_SYM_KPCOMMA, "KPComma" },
{ TERMKEY_SYM_KPPERIOD, "KPPeriod" },
{ TERMKEY_SYM_KPEQUALS, "KPEquals" },
{ 0, NULL },
};
// Mouse event names
static const char *evnames[] = { "Unknown", "Press", "Drag", "Release" };
#define CHARAT(i) (tk->buffer[tk->buffstart + (i)])
#ifdef DEBUG
// Some internal debugging functions
static void print_buffer(TermKey *tk)
{
int i;
for (i = 0; i < tk->buffcount && i < 20; i++) {
fprintf(stderr, "%02x ", CHARAT(i));
}
if (tk->buffcount > 20) {
fprintf(stderr, "...");
}
}
static void print_key(TermKey *tk, TermKeyKey *key)
{
switch (key->type) {
case TERMKEY_TYPE_UNICODE:
fprintf(stderr, "Unicode codepoint=U+<
|