From e98d9c0fd1a148adc844046d568d40de135fb366 Mon Sep 17 00:00:00 2001
From: Přemysl Janouch
Date: Tue, 14 Oct 2014 00:08:15 +0200
Subject: Rename to termo
---
CMakeLists.txt | 42 +-
README | 18 +-
config.cmake.in | 2 +-
demo-async.c | 34 +-
demo-glib.c | 32 +-
demo.c | 54 +-
driver-csi.c | 408 ++++++-------
driver-ti.c | 164 ++---
termkey2-config.h.in | 8 -
termkey2-internal.h | 112 ----
termkey2.c | 1656 --------------------------------------------------
termkey2.h | 277 ---------
termo-config.h.in | 8 +
termo-internal.h | 112 ++++
termo.c | 1656 ++++++++++++++++++++++++++++++++++++++++++++++++++
termo.h | 277 +++++++++
16 files changed, 2430 insertions(+), 2430 deletions(-)
delete mode 100644 termkey2-config.h.in
delete mode 100644 termkey2-internal.h
delete mode 100644 termkey2.c
delete mode 100644 termkey2.h
create mode 100644 termo-config.h.in
create mode 100644 termo-internal.h
create mode 100644 termo.c
create mode 100644 termo.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 81dbb2c..10665f8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,4 @@
-project (termkey2 C)
+project (termo C)
cmake_minimum_required (VERSION 2.8.5)
if ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU" OR CMAKE_COMPILER_IS_GNUC)
@@ -18,9 +18,9 @@ set (project_VERSION ${project_VERSION}.${project_VERSION_PATCH})
set (project_API_VERSION ${project_VERSION_MAJOR})
# Names
-set (project_LIB_NAME "termkey2-${project_API_VERSION}")
-set (project_INCLUDE_NAME "termkey2-${project_API_VERSION}")
-set (project_CMAKE_NAME "TermKey2")
+set (project_LIB_NAME "termo-${project_API_VERSION}")
+set (project_INCLUDE_NAME "termo-${project_API_VERSION}")
+set (project_CMAKE_NAME "Termo")
# Dependecies
find_package (Curses)
@@ -29,19 +29,19 @@ pkg_check_modules (glib glib-2.0 gio-2.0)
pkg_check_modules (unibilium unibilium>=0.1.0)
# Header files with configuration
-configure_file (${PROJECT_SOURCE_DIR}/termkey2-config.h.in
- ${PROJECT_BINARY_DIR}/termkey2-config.h)
+configure_file (${PROJECT_SOURCE_DIR}/termo-config.h.in
+ ${PROJECT_BINARY_DIR}/termo-config.h)
include_directories (${PROJECT_SOURCE_DIR} ${PROJECT_BINARY_DIR})
# Project source files
set (lib_sources
- termkey2.c
+ termo.c
driver-csi.c
driver-ti.c)
set (lib_headers
- termkey2.h
- termkey2-internal.h
- ${PROJECT_BINARY_DIR}/termkey2-config.h)
+ termo.h
+ termo-internal.h
+ ${PROJECT_BINARY_DIR}/termo-config.h)
# Project libraries
if (unibilium_FOUND)
@@ -56,33 +56,33 @@ else (CURSES_FOUND)
endif (unibilium_FOUND)
# Create the library targets
-add_library (termkey2 SHARED ${lib_sources} ${lib_headers})
-target_link_libraries (termkey2 ${lib_libraries})
-set_target_properties (termkey2 PROPERTIES
+add_library (termo SHARED ${lib_sources} ${lib_headers})
+target_link_libraries (termo ${lib_libraries})
+set_target_properties (termo PROPERTIES
OUTPUT_NAME ${project_LIB_NAME}
VERSION ${project_VERSION}
SOVERSION ${project_API_VERSION})
-add_library (termkey2-static STATIC ${lib_sources} ${lib_headers})
-target_link_libraries (termkey2-static ${lib_libraries})
-set_target_properties (termkey2-static PROPERTIES
+add_library (termo-static STATIC ${lib_sources} ${lib_headers})
+target_link_libraries (termo-static ${lib_libraries})
+set_target_properties (termo-static PROPERTIES
OUTPUT_NAME ${project_LIB_NAME}
VERSION ${project_VERSION}
SOVERSION ${project_API_VERSION})
# Demos
add_executable (demo-async EXCLUDE_FROM_ALL demo-async.c)
-target_link_libraries (demo-async termkey2-static ${lib_libraries})
+target_link_libraries (demo-async termo-static ${lib_libraries})
add_executable (demo EXCLUDE_FROM_ALL demo.c)
-target_link_libraries (demo termkey2-static ${lib_libraries})
+target_link_libraries (demo termo-static ${lib_libraries})
set (demos demo demo-async)
if (glib_FOUND)
include_directories (${glib_INCLUDE_DIRS})
add_executable (demo-glib EXCLUDE_FROM_ALL demo-glib.c)
target_link_libraries (demo
- termkey2-static ${lib_libraries} ${glib_LIBRARIES})
+ termo-static ${lib_libraries} ${glib_LIBRARIES})
list (APPEND demos demo-glib)
endif (glib_FOUND)
@@ -90,9 +90,9 @@ add_custom_target (demos DEPENDS ${demos})
# The files to be installed
include (GNUInstallDirs)
-install (TARGETS termkey2 termkey2-static DESTINATION ${CMAKE_INSTALL_LIBDIR})
+install (TARGETS termo termo-static DESTINATION ${CMAKE_INSTALL_LIBDIR})
install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
-install (FILES termkey2.h ${PROJECT_BINARY_DIR}/termkey2-config.h
+install (FILES termo.h ${PROJECT_BINARY_DIR}/termo-config.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${project_INCLUDE_NAME})
# Configuration for other CMake projects
diff --git a/README b/README
index 3a1c2ee..bb776a5 100644
--- a/README
+++ b/README
@@ -1,9 +1,9 @@
-termkey2
-========
+termo
+=====
-`termkey2' is a library providing an alternative to ncurses' handling of
-terminal input. ncurses does a really terrible job at that, mainly wrt. mouse
-support which seems to be utterly broken. If you can drag things in a terminal
+`termo' is a library providing an alternative to ncurses' handling of terminal
+input. ncurses does a really terrible job at that, mainly wrt. mouse support
+which seems to be utterly broken. If you can drag things in a terminal
application, such as in VIM, I can assure you it's not using ncurses for that.
Since terminal I/O is really complicated and full of special cases, this project
@@ -17,7 +17,7 @@ Building and Installing
Build dependencies: GCC/Clang, pkg-config, cmake >= 2.8.5
Optional dependencies: Unibilium (alternative for curses), GLib (for the demos)
- $ git clone https://github.com/pjanouch/termkey2.git
+ $ git clone https://github.com/pjanouch/termo.git
$ mkdir build
$ cd build
$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local
@@ -27,7 +27,7 @@ To install the library, you can do either the usual:
Or you can try telling CMake to make a package for you. For Debian it is:
$ cpack -G DEB
- # dpkg -i termkey2-*.deb
+ # dpkg -i termo-*.deb
To see the library in action, you can try running the demos, which are
statically linked against the library, and hence they can be run as they are:
@@ -38,7 +38,7 @@ What's Different From the Original termkey?
-------------------------------------------
The main change is throwing away any UTF-8 dependent code, making the library
capable of handling all unibyte and multibyte encodings supported by iconv on
-your system. The characters are still presented as Unicode at the end, however,
+your system. The characters are still presented as Unicode in the end, however,
as the other sensible option is wchar_t and that doesn't really work well, see
http://gnu.org/software/libunistring/manual/libunistring.html#The-wchar_005ft-mess
@@ -52,7 +52,7 @@ Oh, and I've deleted the manpages. It needs more Doxygen. :) TBD
License
-------
-`termkey2' is based on the `termkey' library originally written by Paul Evans
+`termo' is based on the `termkey' library originally written by Paul Evans
, with additional changes made by Přemysl Janouch
.
diff --git a/config.cmake.in b/config.cmake.in
index 9a19a6f..aa0209c 100644
--- a/config.cmake.in
+++ b/config.cmake.in
@@ -4,5 +4,5 @@
# @project_CMAKE_NAME@_LIBRARIES
set (@project_CMAKE_NAME@_INCLUDE_DIRS @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@/@project_INCLUDE_NAME@)
-set (@project_CMAKE_NAME@_LIBRARIES termkey2)
+set (@project_CMAKE_NAME@_LIBRARIES termo)
diff --git a/demo-async.c b/demo-async.c
index 88d68a5..c59b8f6 100644
--- a/demo-async.c
+++ b/demo-async.c
@@ -6,13 +6,13 @@
#include
#include
-#include "termkey2.h"
+#include "termo.h"
static void
-on_key (termkey_t *tk, termkey_key_t *key)
+on_key (termo_t *tk, termo_key_t *key)
{
char buffer[50];
- termkey_strfkey (tk, buffer, sizeof buffer, key, TERMKEY_FORMAT_VIM);
+ termo_strfkey (tk, buffer, sizeof buffer, key, TERMO_FORMAT_VIM);
printf ("%s\n", buffer);
}
@@ -22,23 +22,23 @@ main (int argc, char *argv[])
(void) argc;
(void) argv;
- TERMKEY_CHECK_VERSION;
+ TERMO_CHECK_VERSION;
setlocale (LC_CTYPE, "");
- termkey_t *tk = termkey_new (STDIN_FILENO, NULL, 0);
+ termo_t *tk = termo_new (STDIN_FILENO, NULL, 0);
if (!tk)
{
- fprintf (stderr, "Cannot allocate termkey instance\n");
+ fprintf (stderr, "Cannot allocate termo instance\n");
exit (1);
}
struct pollfd fd;
- fd.fd = STDIN_FILENO; /* the file descriptor we passed to termkey_new() */
+ fd.fd = STDIN_FILENO; /* the file descriptor we passed to termo_new() */
fd.events = POLLIN;
- termkey_result_t ret;
- termkey_key_t key;
+ termo_result_t ret;
+ termo_key_t key;
int running = 1;
int nextwait = -1;
@@ -47,27 +47,27 @@ main (int argc, char *argv[])
{
if (poll (&fd, 1, nextwait) == 0)
// Timed out
- if (termkey_getkey_force (tk, &key) == TERMKEY_RES_KEY)
+ if (termo_getkey_force (tk, &key) == TERMO_RES_KEY)
on_key (tk, &key);
if (fd.revents & (POLLIN | POLLHUP | POLLERR))
- termkey_advisereadable (tk);
+ termo_advisereadable (tk);
- while ((ret = termkey_getkey (tk, &key)) == TERMKEY_RES_KEY)
+ while ((ret = termo_getkey (tk, &key)) == TERMO_RES_KEY)
{
on_key (tk, &key);
- if (key.type == TERMKEY_TYPE_KEY
- && (key.modifiers & TERMKEY_KEYMOD_CTRL)
+ if (key.type == TERMO_TYPE_KEY
+ && (key.modifiers & TERMO_KEYMOD_CTRL)
&& (key.code.codepoint == 'C' || key.code.codepoint == 'c'))
running = 0;
}
- if (ret == TERMKEY_RES_AGAIN)
- nextwait = termkey_get_waittime (tk);
+ if (ret == TERMO_RES_AGAIN)
+ nextwait = termo_get_waittime (tk);
else
nextwait = -1;
}
- termkey_destroy (tk);
+ termo_destroy (tk);
}
diff --git a/demo-glib.c b/demo-glib.c
index dfe5cd4..80f3a7b 100644
--- a/demo-glib.c
+++ b/demo-glib.c
@@ -3,24 +3,24 @@
#include
#include
-#include "termkey2.h"
+#include "termo.h"
-static termkey_t *tk;
+static termo_t *tk;
static int timeout_id;
static void
-on_key (termkey_t *tk, termkey_key_t *key)
+on_key (termo_t *tk, termo_key_t *key)
{
char buffer[50];
- termkey_strfkey (tk, buffer, sizeof buffer, key, TERMKEY_FORMAT_VIM);
+ termo_strfkey (tk, buffer, sizeof buffer, key, TERMO_FORMAT_VIM);
printf ("%s\n", buffer);
}
static gboolean
key_timer (gpointer data)
{
- termkey_key_t key;
- if (termkey_getkey_force (tk, &key) == TERMKEY_RES_KEY)
+ termo_key_t key;
+ if (termo_getkey_force (tk, &key) == TERMO_RES_KEY)
on_key (tk, &key);
return FALSE;
}
@@ -33,16 +33,16 @@ stdin_io (GIOChannel *source, GIOCondition condition, gpointer data)
if (timeout_id)
g_source_remove (timeout_id);
- termkey_advisereadable (tk);
+ termo_advisereadable (tk);
- termkey_result_t ret;
- termkey_key_t key;
- while ((ret = termkey_getkey (tk, &key)) == TERMKEY_RES_KEY)
+ termo_result_t ret;
+ termo_key_t key;
+ while ((ret = termo_getkey (tk, &key)) == TERMO_RES_KEY)
on_key (tk, &key);
- if (ret == TERMKEY_RES_AGAIN)
+ if (ret == TERMO_RES_AGAIN)
timeout_id = g_timeout_add
- (termkey_get_waittime (tk), key_timer, NULL);
+ (termo_get_waittime (tk), key_timer, NULL);
}
return TRUE;
@@ -54,13 +54,13 @@ main (int argc, char *argv[])
(void) argc;
(void) argv;
- TERMKEY_CHECK_VERSION;
+ TERMO_CHECK_VERSION;
setlocale (LC_CTYPE, "");
- tk = termkey_new (STDIN_FILENO, NULL, 0);
+ tk = termo_new (STDIN_FILENO, NULL, 0);
if (!tk)
{
- fprintf (stderr, "Cannot allocate termkey instance\n");
+ fprintf (stderr, "Cannot allocate termo instance\n");
exit (1);
}
@@ -68,5 +68,5 @@ main (int argc, char *argv[])
g_io_add_watch (g_io_channel_unix_new (STDIN_FILENO),
G_IO_IN, stdin_io, NULL);
g_main_loop_run (loop);
- termkey_destroy (tk);
+ termo_destroy (tk);
}
diff --git a/demo.c b/demo.c
index 5bb9fc2..d74892c 100644
--- a/demo.c
+++ b/demo.c
@@ -6,20 +6,20 @@
#include
#include
-#include "termkey2.h"
+#include "termo.h"
int
main(int argc, char *argv[])
{
- TERMKEY_CHECK_VERSION;
+ TERMO_CHECK_VERSION;
setlocale (LC_CTYPE, "");
int mouse = 0;
int mouse_proto = 0;
- termkey_format_t format = TERMKEY_FORMAT_VIM;
+ termo_format_t format = TERMO_FORMAT_VIM;
char buffer[50];
- termkey_t *tk;
+ termo_t *tk;
int opt;
while ((opt = getopt (argc, argv, "m::p:")) != -1)
@@ -43,21 +43,21 @@ main(int argc, char *argv[])
}
}
- tk = termkey_new (STDIN_FILENO, NULL,
- TERMKEY_FLAG_SPACESYMBOL | TERMKEY_FLAG_CTRLC);
+ tk = termo_new (STDIN_FILENO, NULL,
+ TERMO_FLAG_SPACESYMBOL | TERMO_FLAG_CTRLC);
if (!tk)
{
- fprintf (stderr, "Cannot allocate termkey instance\n");
+ fprintf (stderr, "Cannot allocate termo instance\n");
exit (1);
}
- if (termkey_get_flags (tk) & TERMKEY_FLAG_RAW)
+ if (termo_get_flags (tk) & TERMO_FLAG_RAW)
printf ("Termkey in RAW mode\n");
else
printf ("Termkey in multibyte mode\n");
- termkey_result_t ret;
- termkey_key_t key;
+ termo_result_t ret;
+ termo_key_t key;
if (mouse)
{
@@ -66,38 +66,38 @@ main(int argc, char *argv[])
printf ("\033[?%dh", mouse_proto);
}
- while ((ret = termkey_waitkey (tk, &key)) != TERMKEY_RES_EOF)
+ while ((ret = termo_waitkey (tk, &key)) != TERMO_RES_EOF)
{
- if (ret == TERMKEY_RES_KEY)
+ if (ret == TERMO_RES_KEY)
{
- termkey_strfkey (tk, buffer, sizeof buffer, &key, format);
- if (key.type == TERMKEY_TYPE_MOUSE)
+ termo_strfkey (tk, buffer, sizeof buffer, &key, format);
+ if (key.type == TERMO_TYPE_MOUSE)
{
int line, col;
- termkey_interpret_mouse (tk, &key, NULL, NULL, &line, &col);
+ termo_interpret_mouse (tk, &key, NULL, NULL, &line, &col);
printf ("%s at line=%d, col=%d\n", buffer, line, col);
}
- else if (key.type == TERMKEY_TYPE_POSITION)
+ else if (key.type == TERMO_TYPE_POSITION)
{
int line, col;
- termkey_interpret_position (tk, &key, &line, &col);
+ termo_interpret_position (tk, &key, &line, &col);
printf ("Cursor position report at line=%d, col=%d\n",
line, col);
}
- else if (key.type == TERMKEY_TYPE_MODEREPORT)
+ else if (key.type == TERMO_TYPE_MODEREPORT)
{
int initial, mode, value;
- termkey_interpret_modereport
+ termo_interpret_modereport
(tk, &key, &initial, &mode, &value);
printf ("Mode report %s mode %d = %d\n",
initial ? "DEC" : "ANSI", mode, value);
}
- else if (key.type == TERMKEY_TYPE_UNKNOWN_CSI)
+ else if (key.type == TERMO_TYPE_UNKNOWN_CSI)
{
long args[16];
size_t nargs = 16;
unsigned long command;
- termkey_interpret_csi (tk, &key, args, &nargs, &command);
+ termo_interpret_csi (tk, &key, args, &nargs, &command);
printf ("Unrecognised CSI %c %ld;%ld %c%c\n",
(char) (command >> 8), args[0], args[1],
(char) (command >> 16), (char) command);
@@ -105,12 +105,12 @@ main(int argc, char *argv[])
else
printf ("Key %s\n", buffer);
- if (key.type == TERMKEY_TYPE_KEY
- && key.modifiers & TERMKEY_KEYMOD_CTRL
+ if (key.type == TERMO_TYPE_KEY
+ && key.modifiers & TERMO_KEYMOD_CTRL
&& (key.code.codepoint == 'C' || key.code.codepoint == 'c'))
break;
- if (key.type == TERMKEY_TYPE_KEY
+ if (key.type == TERMO_TYPE_KEY
&& key.modifiers == 0
&& key.code.codepoint == '?')
{
@@ -119,11 +119,11 @@ main(int argc, char *argv[])
fflush (stdout);
}
}
- else if (ret == TERMKEY_RES_ERROR)
+ else if (ret == TERMO_RES_ERROR)
{
if (errno != EINTR)
{
- perror ("termkey_waitkey");
+ perror ("termo_waitkey");
break;
}
printf ("Interrupted by signal\n");
@@ -133,5 +133,5 @@ main(int argc, char *argv[])
if (mouse)
printf ("\033[?%dlMouse mode deactivated\n", mouse);
- termkey_destroy (tk);
+ termo_destroy (tk);
}
diff --git a/driver-csi.c b/driver-csi.c
index a7fcc52..4a954fc 100644
--- a/driver-csi.c
+++ b/driver-csi.c
@@ -1,5 +1,5 @@
-#include "termkey2.h"
-#include "termkey2-internal.h"
+#include "termo.h"
+#include "termo-internal.h"
#include
#include
@@ -11,12 +11,12 @@ static char ss3_kpalts[64];
typedef struct
{
- termkey_t *tk;
+ termo_t *tk;
}
-termkey_csi_t;
+termo_csi_t;
-typedef termkey_result_t (*csi_handler_fn)
- (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args);
+typedef termo_result_t (*csi_handler_fn)
+ (termo_t *tk, termo_key_t *key, int cmd, long *arg, int args);
static csi_handler_fn csi_handlers[64];
/*
@@ -25,9 +25,9 @@ static csi_handler_fn csi_handlers[64];
static struct keyinfo csi_ss3s[64];
-static termkey_result_t
-handle_csi_ss3_full (termkey_t *tk,
- termkey_key_t *key, int cmd, long *arg, int args)
+static termo_result_t
+handle_csi_ss3_full (termo_t *tk,
+ termo_key_t *key, int cmd, long *arg, int args)
{
(void) tk;
@@ -41,13 +41,13 @@ handle_csi_ss3_full (termkey_t *tk,
key->modifiers &= ~(csi_ss3s[cmd - 0x40].modifier_mask);
key->modifiers |= csi_ss3s[cmd - 0x40].modifier_set;
- if (key->code.sym == TERMKEY_SYM_UNKNOWN)
- return TERMKEY_RES_NONE;
- return TERMKEY_RES_KEY;
+ if (key->code.sym == TERMO_SYM_UNKNOWN)
+ return TERMO_RES_NONE;
+ return TERMO_RES_KEY;
}
static void
-register_csi_ss3_full (termkey_type_t type, termkey_sym_t sym,
+register_csi_ss3_full (termo_type_t type, termo_sym_t sym,
int modifier_set, int modifier_mask, unsigned char cmd)
{
if (cmd < 0x40 || cmd >= 0x80)
@@ -62,7 +62,7 @@ register_csi_ss3_full (termkey_type_t type, termkey_sym_t sym,
}
static void
-register_csi_ss3 (termkey_type_t type, termkey_sym_t sym, unsigned char cmd)
+register_csi_ss3 (termo_type_t type, termo_sym_t sym, unsigned char cmd)
{
register_csi_ss3_full (type, sym, 0, 0, cmd);
}
@@ -72,7 +72,7 @@ register_csi_ss3 (termkey_type_t type, termkey_sym_t sym, unsigned char cmd)
*/
static void
-register_ss3kpalt (termkey_type_t type, termkey_sym_t sym,
+register_ss3kpalt (termo_type_t type, termo_sym_t sym,
unsigned char cmd, char kpalt)
{
if (cmd < 0x40 || cmd >= 0x80)
@@ -94,8 +94,8 @@ register_ss3kpalt (termkey_type_t type, termkey_sym_t sym,
static struct keyinfo csifuncs[35];
#define NCSIFUNCS ((long) (sizeof csifuncs / sizeof csifuncs[0]))
-static termkey_result_t
-handle_csifunc (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args)
+static termo_result_t
+handle_csifunc (termo_t *tk, termo_key_t *key, int cmd, long *arg, int args)
{
(void) cmd;
@@ -103,7 +103,7 @@ handle_csifunc (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args)
key->modifiers = arg[1] - 1;
else
key->modifiers = 0;
- key->type = TERMKEY_TYPE_KEYSYM;
+ key->type = TERMO_TYPE_KEYSYM;
if (arg[0] == 27)
{
@@ -119,21 +119,21 @@ handle_csifunc (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args)
key->modifiers |= csifuncs[arg[0]].modifier_set;
}
else
- key->code.sym = TERMKEY_SYM_UNKNOWN;
+ key->code.sym = TERMO_SYM_UNKNOWN;
- if (key->code.sym == TERMKEY_SYM_UNKNOWN)
+ if (key->code.sym == TERMO_SYM_UNKNOWN)
{
#ifdef DEBUG
fprintf (stderr, "CSI: Unknown function key %ld\n", arg[0]);
#endif
- return TERMKEY_RES_NONE;
+ return TERMO_RES_NONE;
}
- return TERMKEY_RES_KEY;
+ return TERMO_RES_KEY;
}
static void
-register_csifunc (termkey_type_t type, termkey_sym_t sym, int number)
+register_csifunc (termo_type_t type, termo_sym_t sym, int number)
{
if (number >= NCSIFUNCS)
return;
@@ -150,21 +150,21 @@ register_csifunc (termkey_type_t type, termkey_sym_t sym, int number)
* URxvt seems to emit this instead of ~ when holding Ctrl
*/
-static termkey_result_t
-handle_csi_caret (termkey_t *tk,
- termkey_key_t *key, int cmd, long *arg, int args)
+static termo_result_t
+handle_csi_caret (termo_t *tk,
+ termo_key_t *key, int cmd, long *arg, int args)
{
switch (cmd)
{
case '^':
{
- termkey_result_t res = handle_csifunc (tk, key, cmd, arg, args);
- if (res == TERMKEY_RES_KEY)
- key->modifiers |= TERMKEY_KEYMOD_CTRL;
+ termo_result_t res = handle_csifunc (tk, key, cmd, arg, args);
+ if (res == TERMO_RES_KEY)
+ key->modifiers |= TERMO_KEYMOD_CTRL;
return res;
}
default:
- return TERMKEY_RES_NONE;
+ return TERMO_RES_NONE;
}
}
@@ -172,8 +172,8 @@ handle_csi_caret (termkey_t *tk,
* Handler for CSI u extended Unicode keys
*/
-static termkey_result_t
-handle_csi_u (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args)
+static termo_result_t
+handle_csi_u (termo_t *tk, termo_key_t *key, int cmd, long *arg, int args)
{
switch (cmd)
{
@@ -185,13 +185,13 @@ handle_csi_u (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args)
key->modifiers = 0;
int mod = key->modifiers;
- key->type = TERMKEY_TYPE_KEYSYM;
+ key->type = TERMO_TYPE_KEYSYM;
(*tk->method.emit_codepoint) (tk, arg[0], key);
key->modifiers |= mod;
- return TERMKEY_RES_KEY;
+ return TERMO_RES_KEY;
}
default:
- return TERMKEY_RES_NONE;
+ return TERMO_RES_NONE;
}
}
@@ -200,8 +200,8 @@ handle_csi_u (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args)
* Note: This does not handle X10 encoding
*/
-static termkey_result_t
-handle_csi_m (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args)
+static termo_result_t
+handle_csi_m (termo_t *tk, termo_key_t *key, int cmd, long *arg, int args)
{
(void) tk;
@@ -214,57 +214,57 @@ handle_csi_m (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args)
case 'm':
break;
default:
- return TERMKEY_RES_NONE;
+ return TERMO_RES_NONE;
}
if (!initial && args >= 3)
{
// rxvt protocol
- key->type = TERMKEY_TYPE_MOUSE;
+ key->type = TERMO_TYPE_MOUSE;
key->code.mouse.info = arg[0] - 0x20;
key->modifiers = (key->code.mouse.info & 0x1c) >> 2;
key->code.mouse.info &= ~0x1c;
- termkey_key_set_linecol (key, arg[2] - 1, arg[1] - 1);
- return TERMKEY_RES_KEY;
+ termo_key_set_linecol (key, arg[2] - 1, arg[1] - 1);
+ return TERMO_RES_KEY;
}
if (initial == '<' && args >= 3)
{
// SGR protocol
- key->type = TERMKEY_TYPE_MOUSE;
+ key->type = TERMO_TYPE_MOUSE;
key->code.mouse.info = arg[0];
key->modifiers = (key->code.mouse.info & 0x1c) >> 2;
key->code.mouse.info &= ~0x1c;
- termkey_key_set_linecol (key, arg[2] - 1, arg[1] - 1);
+ termo_key_set_linecol (key, arg[2] - 1, arg[1] - 1);
if (cmd == 'm') // release
key->code.mouse.info |= 0x8000;
- return TERMKEY_RES_KEY;
+ return TERMO_RES_KEY;
}
- return TERMKEY_RES_NONE;
+ return TERMO_RES_NONE;
}
-termkey_result_t
-termkey_interpret_mouse (termkey_t *tk, const termkey_key_t *key,
- termkey_mouse_event_t *event, int *button, int *line, int *col)
+termo_result_t
+termo_interpret_mouse (termo_t *tk, const termo_key_t *key,
+ termo_mouse_event_t *event, int *button, int *line, int *col)
{
(void) tk;
- if (key->type != TERMKEY_TYPE_MOUSE)
- return TERMKEY_RES_NONE;
+ if (key->type != TERMO_TYPE_MOUSE)
+ return TERMO_RES_NONE;
if (button)
*button = 0;
- termkey_key_get_linecol (key, line, col);
+ termo_key_get_linecol (key, line, col);
// XXX: WTF is this logic?
if (!event)
- return TERMKEY_RES_KEY;
+ return TERMO_RES_KEY;
int btn = 0;
int code = key->code.mouse.info;
@@ -276,30 +276,30 @@ termkey_interpret_mouse (termkey_t *tk, const termkey_key_t *key,
case 0:
case 1:
case 2:
- *event = drag ? TERMKEY_MOUSE_DRAG : TERMKEY_MOUSE_PRESS;
+ *event = drag ? TERMO_MOUSE_DRAG : TERMO_MOUSE_PRESS;
btn = code + 1;
break;
case 3:
- *event = TERMKEY_MOUSE_RELEASE;
+ *event = TERMO_MOUSE_RELEASE;
// no button hint
break;
case 64:
case 65:
- *event = drag ? TERMKEY_MOUSE_DRAG : TERMKEY_MOUSE_PRESS;
+ *event = drag ? TERMO_MOUSE_DRAG : TERMO_MOUSE_PRESS;
btn = code + 4 - 64;
break;
default:
- *event = TERMKEY_MOUSE_UNKNOWN;
+ *event = TERMO_MOUSE_UNKNOWN;
}
if (button)
*button = btn;
if (key->code.mouse.info & 0x8000)
- *event = TERMKEY_MOUSE_RELEASE;
- return TERMKEY_RES_KEY;
+ *event = TERMO_MOUSE_RELEASE;
+ return TERMO_RES_KEY;
}
/*
@@ -307,43 +307,43 @@ termkey_interpret_mouse (termkey_t *tk, const termkey_key_t *key,
* A plain CSI R with no arguments is probably actually
*/
-static termkey_result_t
-handle_csi_R (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args)
+static termo_result_t
+handle_csi_R (termo_t *tk, termo_key_t *key, int cmd, long *arg, int args)
{
switch (cmd)
{
case 'R' | '?' << 8:
if (args < 2)
- return TERMKEY_RES_NONE;
+ return TERMO_RES_NONE;
- key->type = TERMKEY_TYPE_POSITION;
- termkey_key_set_linecol (key, arg[1], arg[0]);
- return TERMKEY_RES_KEY;
+ key->type = TERMO_TYPE_POSITION;
+ termo_key_set_linecol (key, arg[1], arg[0]);
+ return TERMO_RES_KEY;
default:
return handle_csi_ss3_full (tk, key, cmd, arg, args);
}
}
-termkey_result_t
-termkey_interpret_position (termkey_t *tk,
- const termkey_key_t *key, int *line, int *col)
+termo_result_t
+termo_interpret_position (termo_t *tk,
+ const termo_key_t *key, int *line, int *col)
{
(void) tk;
- if (key->type != TERMKEY_TYPE_POSITION)
- return TERMKEY_RES_NONE;
+ if (key->type != TERMO_TYPE_POSITION)
+ return TERMO_RES_NONE;
- termkey_key_get_linecol (key, line, col);
- return TERMKEY_RES_KEY;
+ termo_key_get_linecol (key, line, col);
+ return TERMO_RES_KEY;
}
/*
* Handler for CSI $y mode status reports
*/
-static termkey_result_t
-handle_csi_y (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args)
+static termo_result_t
+handle_csi_y (termo_t *tk, termo_key_t *key, int cmd, long *arg, int args)
{
(void) tk;
@@ -352,27 +352,27 @@ handle_csi_y (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args)
case 'y' | '$' << 16:
case 'y' | '$' << 16 | '?' << 8:
if (args < 2)
- return TERMKEY_RES_NONE;
+ return TERMO_RES_NONE;
- key->type = TERMKEY_TYPE_MODEREPORT;
+ key->type = TERMO_TYPE_MODEREPORT;
key->code.mode.initial = (cmd >> 8);
key->code.mode.mode = arg[0];
key->code.mode.value = arg[1];
- return TERMKEY_RES_KEY;
+ return TERMO_RES_KEY;
default:
- return TERMKEY_RES_NONE;
+ return TERMO_RES_NONE;
}
}
-termkey_result_t
-termkey_interpret_modereport (termkey_t *tk,
- const termkey_key_t *key, int *initial, int *mode, int *value)
+termo_result_t
+termo_interpret_modereport (termo_t *tk,
+ const termo_key_t *key, int *initial, int *mode, int *value)
{
(void) tk;
- if (key->type != TERMKEY_TYPE_MODEREPORT)
- return TERMKEY_RES_NONE;
+ if (key->type != TERMO_TYPE_MODEREPORT)
+ return TERMO_RES_NONE;
if (initial)
*initial = key->code.mode.initial;
@@ -380,13 +380,13 @@ termkey_interpret_modereport (termkey_t *tk,
*mode = key->code.mode.mode;
if (value)
*value = key->code.mode.value;
- return TERMKEY_RES_KEY;
+ return TERMO_RES_KEY;
}
#define CHARAT(i) (tk->buffer[tk->buffstart + (i)])
-static termkey_result_t
-parse_csi (termkey_t *tk, size_t introlen, size_t *csi_len,
+static termo_result_t
+parse_csi (termo_t *tk, size_t introlen, size_t *csi_len,
long args[], size_t *nargs, unsigned long *commandp)
{
size_t csi_end = introlen;
@@ -398,7 +398,7 @@ parse_csi (termkey_t *tk, size_t introlen, size_t *csi_len,
}
if (csi_end >= tk->buffcount)
- return TERMKEY_RES_AGAIN;
+ return TERMO_RES_AGAIN;
unsigned char cmd = CHARAT (csi_end);
*commandp = cmd;
@@ -451,17 +451,17 @@ parse_csi (termkey_t *tk, size_t introlen, size_t *csi_len,
*nargs = argi;
*csi_len = csi_end + 1;
- return TERMKEY_RES_KEY;
+ return TERMO_RES_KEY;
}
-termkey_result_t
-termkey_interpret_csi (termkey_t *tk, const termkey_key_t *key,
+termo_result_t
+termo_interpret_csi (termo_t *tk, const termo_key_t *key,
long args[], size_t *nargs, unsigned long *cmd)
{
if (tk->hightide == 0)
- return TERMKEY_RES_NONE;
- if (key->type != TERMKEY_TYPE_UNKNOWN_CSI)
- return TERMKEY_RES_NONE;
+ return TERMO_RES_NONE;
+ if (key->type != TERMO_TYPE_UNKNOWN_CSI)
+ return TERMO_RES_NONE;
size_t dummy;
return parse_csi (tk, 0, &dummy, args, nargs, cmd);
@@ -473,76 +473,76 @@ register_keys (void)
int i;
for (i = 0; i < 64; i++)
{
- csi_ss3s[i].sym = TERMKEY_SYM_UNKNOWN;
- ss3s[i].sym = TERMKEY_SYM_UNKNOWN;
+ csi_ss3s[i].sym = TERMO_SYM_UNKNOWN;
+ ss3s[i].sym = TERMO_SYM_UNKNOWN;
ss3_kpalts[i] = 0;
}
for (i = 0; i < NCSIFUNCS; i++)
- csifuncs[i].sym = TERMKEY_SYM_UNKNOWN;
-
- register_csi_ss3 (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UP, 'A');
- register_csi_ss3 (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DOWN, 'B');
- register_csi_ss3 (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RIGHT, 'C');
- register_csi_ss3 (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_LEFT, 'D');
- register_csi_ss3 (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN, 'E');
- register_csi_ss3 (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_END, 'F');
- register_csi_ss3 (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HOME, 'H');
- register_csi_ss3 (TERMKEY_TYPE_FUNCTION, 1, 'P');
- register_csi_ss3 (TERMKEY_TYPE_FUNCTION, 2, 'Q');
- register_csi_ss3 (TERMKEY_TYPE_FUNCTION, 3, 'R');
- register_csi_ss3 (TERMKEY_TYPE_FUNCTION, 4, 'S');
-
- register_csi_ss3_full (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_TAB,
- TERMKEY_KEYMOD_SHIFT, TERMKEY_KEYMOD_SHIFT, 'Z');
-
- register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPENTER, 'M', 0);
- register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPEQUALS, 'X', '=');
- register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPMULT, 'j', '*');
- register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPPLUS, 'k', '+');
- register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPCOMMA, 'l', ',');
- register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPMINUS, 'm', '-');
- register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPPERIOD, 'n', '.');
- register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPDIV, 'o', '/');
- register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP0, 'p', '0');
- register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP1, 'q', '1');
- register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP2, 'r', '2');
- register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP3, 's', '3');
- register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP4, 't', '4');
- register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP5, 'u', '5');
- register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP6, 'v', '6');
- register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP7, 'w', '7');
- register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP8, 'x', '8');
- register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP9, 'y', '9');
-
- register_csifunc (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_FIND, 1);
- register_csifunc (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_INSERT, 2);
- register_csifunc (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DELETE, 3);
- register_csifunc (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SELECT, 4);
- register_csifunc (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP, 5);
- register_csifunc (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN, 6);
- register_csifunc (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HOME, 7);
- register_csifunc (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_END, 8);
-
- register_csifunc (TERMKEY_TYPE_FUNCTION, 1, 11);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 2, 12);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 3, 13);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 4, 14);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 5, 15);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 6, 17);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 7, 18);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 8, 19);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 9, 20);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 10, 21);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 11, 23);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 12, 24);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 13, 25);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 14, 26);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 15, 28);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 16, 29);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 17, 31);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 18, 32);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 19, 33);
- register_csifunc (TERMKEY_TYPE_FUNCTION, 20, 34);
+ csifuncs[i].sym = TERMO_SYM_UNKNOWN;
+
+ register_csi_ss3 (TERMO_TYPE_KEYSYM, TERMO_SYM_UP, 'A');
+ register_csi_ss3 (TERMO_TYPE_KEYSYM, TERMO_SYM_DOWN, 'B');
+ register_csi_ss3 (TERMO_TYPE_KEYSYM, TERMO_SYM_RIGHT, 'C');
+ register_csi_ss3 (TERMO_TYPE_KEYSYM, TERMO_SYM_LEFT, 'D');
+ register_csi_ss3 (TERMO_TYPE_KEYSYM, TERMO_SYM_BEGIN, 'E');
+ register_csi_ss3 (TERMO_TYPE_KEYSYM, TERMO_SYM_END, 'F');
+ register_csi_ss3 (TERMO_TYPE_KEYSYM, TERMO_SYM_HOME, 'H');
+ register_csi_ss3 (TERMO_TYPE_FUNCTION, 1, 'P');
+ register_csi_ss3 (TERMO_TYPE_FUNCTION, 2, 'Q');
+ register_csi_ss3 (TERMO_TYPE_FUNCTION, 3, 'R');
+ register_csi_ss3 (TERMO_TYPE_FUNCTION, 4, 'S');
+
+ register_csi_ss3_full (TERMO_TYPE_KEYSYM, TERMO_SYM_TAB,
+ TERMO_KEYMOD_SHIFT, TERMO_KEYMOD_SHIFT, 'Z');
+
+ register_ss3kpalt (TERMO_TYPE_KEYSYM, TERMO_SYM_KPENTER, 'M', 0);
+ register_ss3kpalt (TERMO_TYPE_KEYSYM, TERMO_SYM_KPEQUALS, 'X', '=');
+ register_ss3kpalt (TERMO_TYPE_KEYSYM, TERMO_SYM_KPMULT, 'j', '*');
+ register_ss3kpalt (TERMO_TYPE_KEYSYM, TERMO_SYM_KPPLUS, 'k', '+');
+ register_ss3kpalt (TERMO_TYPE_KEYSYM, TERMO_SYM_KPCOMMA, 'l', ',');
+ register_ss3kpalt (TERMO_TYPE_KEYSYM, TERMO_SYM_KPMINUS, 'm', '-');
+ register_ss3kpalt (TERMO_TYPE_KEYSYM, TERMO_SYM_KPPERIOD, 'n', '.');
+ register_ss3kpalt (TERMO_TYPE_KEYSYM, TERMO_SYM_KPDIV, 'o', '/');
+ register_ss3kpalt (TERMO_TYPE_KEYSYM, TERMO_SYM_KP0, 'p', '0');
+ register_ss3kpalt (TERMO_TYPE_KEYSYM, TERMO_SYM_KP1, 'q', '1');
+ register_ss3kpalt (TERMO_TYPE_KEYSYM, TERMO_SYM_KP2, 'r', '2');
+ register_ss3kpalt (TERMO_TYPE_KEYSYM, TERMO_SYM_KP3, 's', '3');
+ register_ss3kpalt (TERMO_TYPE_KEYSYM, TERMO_SYM_KP4, 't', '4');
+ register_ss3kpalt (TERMO_TYPE_KEYSYM, TERMO_SYM_KP5, 'u', '5');
+ register_ss3kpalt (TERMO_TYPE_KEYSYM, TERMO_SYM_KP6, 'v', '6');
+ register_ss3kpalt (TERMO_TYPE_KEYSYM, TERMO_SYM_KP7, 'w', '7');
+ register_ss3kpalt (TERMO_TYPE_KEYSYM, TERMO_SYM_KP8, 'x', '8');
+ register_ss3kpalt (TERMO_TYPE_KEYSYM, TERMO_SYM_KP9, 'y', '9');
+
+ register_csifunc (TERMO_TYPE_KEYSYM, TERMO_SYM_FIND, 1);
+ register_csifunc (TERMO_TYPE_KEYSYM, TERMO_SYM_INSERT, 2);
+ register_csifunc (TERMO_TYPE_KEYSYM, TERMO_SYM_DELETE, 3);
+ register_csifunc (TERMO_TYPE_KEYSYM, TERMO_SYM_SELECT, 4);
+ register_csifunc (TERMO_TYPE_KEYSYM, TERMO_SYM_PAGEUP, 5);
+ register_csifunc (TERMO_TYPE_KEYSYM, TERMO_SYM_PAGEDOWN, 6);
+ register_csifunc (TERMO_TYPE_KEYSYM, TERMO_SYM_HOME, 7);
+ register_csifunc (TERMO_TYPE_KEYSYM, TERMO_SYM_END, 8);
+
+ register_csifunc (TERMO_TYPE_FUNCTION, 1, 11);
+ register_csifunc (TERMO_TYPE_FUNCTION, 2, 12);
+ register_csifunc (TERMO_TYPE_FUNCTION, 3, 13);
+ register_csifunc (TERMO_TYPE_FUNCTION, 4, 14);
+ register_csifunc (TERMO_TYPE_FUNCTION, 5, 15);
+ register_csifunc (TERMO_TYPE_FUNCTION, 6, 17);
+ register_csifunc (TERMO_TYPE_FUNCTION, 7, 18);
+ register_csifunc (TERMO_TYPE_FUNCTION, 8, 19);
+ register_csifunc (TERMO_TYPE_FUNCTION, 9, 20);
+ register_csifunc (TERMO_TYPE_FUNCTION, 10, 21);
+ register_csifunc (TERMO_TYPE_FUNCTION, 11, 23);
+ register_csifunc (TERMO_TYPE_FUNCTION, 12, 24);
+ register_csifunc (TERMO_TYPE_FUNCTION, 13, 25);
+ register_csifunc (TERMO_TYPE_FUNCTION, 14, 26);
+ register_csifunc (TERMO_TYPE_FUNCTION, 15, 28);
+ register_csifunc (TERMO_TYPE_FUNCTION, 16, 29);
+ register_csifunc (TERMO_TYPE_FUNCTION, 17, 31);
+ register_csifunc (TERMO_TYPE_FUNCTION, 18, 32);
+ register_csifunc (TERMO_TYPE_FUNCTION, 19, 33);
+ register_csifunc (TERMO_TYPE_FUNCTION, 20, 34);
csi_handlers['u' - 0x40] = &handle_csi_u;
@@ -554,14 +554,14 @@ register_keys (void)
csi_handlers['y' - 0x40] = &handle_csi_y;
// URxvt
- register_csi_ss3_full (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UP,
- TERMKEY_KEYMOD_CTRL, TERMKEY_KEYMOD_CTRL, 'a');
- register_csi_ss3_full (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DOWN,
- TERMKEY_KEYMOD_CTRL, TERMKEY_KEYMOD_CTRL, 'b');
- register_csi_ss3_full (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RIGHT,
- TERMKEY_KEYMOD_CTRL, TERMKEY_KEYMOD_CTRL, 'c');
- register_csi_ss3_full (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_LEFT,
- TERMKEY_KEYMOD_CTRL, TERMKEY_KEYMOD_CTRL, 'd');
+ register_csi_ss3_full (TERMO_TYPE_KEYSYM, TERMO_SYM_UP,
+ TERMO_KEYMOD_CTRL, TERMO_KEYMOD_CTRL, 'a');
+ register_csi_ss3_full (TERMO_TYPE_KEYSYM, TERMO_SYM_DOWN,
+ TERMO_KEYMOD_CTRL, TERMO_KEYMOD_CTRL, 'b');
+ register_csi_ss3_full (TERMO_TYPE_KEYSYM, TERMO_SYM_RIGHT,
+ TERMO_KEYMOD_CTRL, TERMO_KEYMOD_CTRL, 'c');
+ register_csi_ss3_full (TERMO_TYPE_KEYSYM, TERMO_SYM_LEFT,
+ TERMO_KEYMOD_CTRL, TERMO_KEYMOD_CTRL, 'd');
csi_handlers['^' - 0x40] = &handle_csi_caret;
@@ -570,14 +570,14 @@ register_keys (void)
}
static void *
-new_driver (termkey_t *tk, const char *term)
+new_driver (termo_t *tk, const char *term)
{
(void) term;
if (!keyinfo_initialised && !register_keys ())
return NULL;
- termkey_csi_t *csi = malloc (sizeof *csi);
+ termo_csi_t *csi = malloc (sizeof *csi);
if (!csi)
return NULL;
@@ -588,13 +588,13 @@ new_driver (termkey_t *tk, const char *term)
static void
free_driver (void *info)
{
- termkey_csi_t *csi = info;
+ termo_csi_t *csi = info;
free (csi);
}
-static termkey_result_t
-peekkey_csi (termkey_t *tk, termkey_csi_t *csi,
- size_t introlen, termkey_key_t *key, int force, size_t *nbytep)
+static termo_result_t
+peekkey_csi (termo_t *tk, termo_csi_t *csi,
+ size_t introlen, termo_key_t *key, int force, size_t *nbytep)
{
(void) csi;
@@ -603,16 +603,16 @@ peekkey_csi (termkey_t *tk, termkey_csi_t *csi,
long arg[16];
unsigned long cmd;
- termkey_result_t ret = parse_csi (tk, introlen, &csi_len, arg, &args, &cmd);
- if (ret == TERMKEY_RES_AGAIN)
+ termo_result_t ret = parse_csi (tk, introlen, &csi_len, arg, &args, &cmd);
+ if (ret == TERMO_RES_AGAIN)
{
if (!force)
- return TERMKEY_RES_AGAIN;
+ return TERMO_RES_AGAIN;
(*tk->method.emit_codepoint) (tk, '[', key);
- key->modifiers |= TERMKEY_KEYMOD_ALT;
+ key->modifiers |= TERMO_KEYMOD_ALT;
*nbytep = introlen;
- return TERMKEY_RES_KEY;
+ return TERMO_RES_KEY;
}
// Mouse in X10 encoding consumes the next 3 bytes also (or more with 1005)
@@ -621,24 +621,24 @@ peekkey_csi (termkey_t *tk, termkey_csi_t *csi,
tk->buffstart += csi_len;
tk->buffcount -= csi_len;
- termkey_result_t mouse_result =
+ termo_result_t mouse_result =
(*tk->method.peekkey_mouse) (tk, key, nbytep);
tk->buffstart -= csi_len;
tk->buffcount += csi_len;
- if (mouse_result == TERMKEY_RES_KEY)
+ if (mouse_result == TERMO_RES_KEY)
*nbytep += csi_len;
return mouse_result;
}
- termkey_result_t result = TERMKEY_RES_NONE;
+ termo_result_t result = TERMO_RES_NONE;
// We know from the logic above that cmd must be >= 0x40 and < 0x80
if (csi_handlers[(cmd & 0xff) - 0x40])
result = (*csi_handlers[(cmd & 0xff) - 0x40]) (tk, key, cmd, arg, args);
- if (result == TERMKEY_RES_NONE)
+ if (result == TERMO_RES_NONE)
{
#ifdef DEBUG
switch (args)
@@ -661,49 +661,49 @@ peekkey_csi (termkey_t *tk, termkey_csi_t *csi,
break;
}
#endif
- key->type = TERMKEY_TYPE_UNKNOWN_CSI;
+ key->type = TERMO_TYPE_UNKNOWN_CSI;
key->code.number = cmd;
tk->hightide = csi_len - introlen;
*nbytep = introlen; // Do not yet eat the data bytes
- return TERMKEY_RES_KEY;
+ return TERMO_RES_KEY;
}
*nbytep = csi_len;
return result;
}
-static termkey_result_t
-peekkey_ss3 (termkey_t *tk, termkey_csi_t *csi, size_t introlen,
- termkey_key_t *key, int force, size_t *nbytep)
+static termo_result_t
+peekkey_ss3 (termo_t *tk, termo_csi_t *csi, size_t introlen,
+ termo_key_t *key, int force, size_t *nbytep)
{
(void) csi;
if (tk->buffcount < introlen + 1)
{
if (!force)
- return TERMKEY_RES_AGAIN;
+ return TERMO_RES_AGAIN;
(*tk->method.emit_codepoint) (tk, 'O', key);
- key->modifiers |= TERMKEY_KEYMOD_ALT;
+ key->modifiers |= TERMO_KEYMOD_ALT;
*nbytep = tk->buffcount;
- return TERMKEY_RES_KEY;
+ return TERMO_RES_KEY;
}
unsigned char cmd = CHARAT (introlen);
if (cmd < 0x40 || cmd >= 0x80)
- return TERMKEY_RES_NONE;
+ return TERMO_RES_NONE;
key->type = csi_ss3s[cmd - 0x40].type;
key->code.sym = csi_ss3s[cmd - 0x40].sym;
key->modifiers = csi_ss3s[cmd - 0x40].modifier_set;
- if (key->code.sym == TERMKEY_SYM_UNKNOWN)
+ if (key->code.sym == TERMO_SYM_UNKNOWN)
{
- if (tk->flags & TERMKEY_FLAG_CONVERTKP && ss3_kpalts[cmd - 0x40])
+ if (tk->flags & TERMO_FLAG_CONVERTKP && ss3_kpalts[cmd - 0x40])
{
- key->type = TERMKEY_TYPE_KEY;
+ key->type = TERMO_TYPE_KEY;
key->code.codepoint = ss3_kpalts[cmd - 0x40];
key->modifiers = 0;
@@ -718,26 +718,26 @@ peekkey_ss3 (termkey_t *tk, termkey_csi_t *csi, size_t introlen,
}
}
- if (key->code.sym == TERMKEY_SYM_UNKNOWN)
+ if (key->code.sym == TERMO_SYM_UNKNOWN)
{
#ifdef DEBUG
fprintf (stderr, "CSI: Unknown SS3 %c (0x%02x)\n", (char) cmd, cmd);
#endif
- return TERMKEY_RES_NONE;
+ return TERMO_RES_NONE;
}
*nbytep = introlen + 1;
- return TERMKEY_RES_KEY;
+ return TERMO_RES_KEY;
}
-static termkey_result_t
-peekkey (termkey_t *tk, void *info,
- termkey_key_t *key, int force, size_t *nbytep)
+static termo_result_t
+peekkey (termo_t *tk, void *info,
+ termo_key_t *key, int force, size_t *nbytep)
{
if (tk->buffcount == 0)
- return tk->is_closed ? TERMKEY_RES_EOF : TERMKEY_RES_NONE;
+ return tk->is_closed ? TERMO_RES_EOF : TERMO_RES_NONE;
- termkey_csi_t *csi = info;
+ termo_csi_t *csi = info;
// Now we're sure at least 1 byte is valid
unsigned char b0 = CHARAT (0);
@@ -750,10 +750,10 @@ peekkey (termkey_t *tk, void *info,
return peekkey_ss3 (tk, csi, 1, key, force, nbytep);
if (b0 == 0x9b)
return peekkey_csi (tk, csi, 1, key, force, nbytep);
- return TERMKEY_RES_NONE;
+ return TERMO_RES_NONE;
}
-termkey_driver_t termkey_driver_csi =
+termo_driver_t termo_driver_csi =
{
.name = "CSI",
.new_driver = new_driver,
diff --git a/driver-ti.c b/driver-ti.c
index 1b026fa..80b5d98 100644
--- a/driver-ti.c
+++ b/driver-ti.c
@@ -1,8 +1,8 @@
// we want strdup()
#define _XOPEN_SOURCE 600
-#include "termkey2.h"
-#include "termkey2-internal.h"
+#include "termo.h"
+#include "termo-internal.h"
#ifdef HAVE_UNIBILIUM
# include
@@ -53,7 +53,7 @@ trie_node_array_t;
typedef struct
{
- termkey_t *tk;
+ termo_t *tk;
trie_node_t *root;
char *start_string;
@@ -62,14 +62,14 @@ typedef struct
bool have_mouse;
char *set_mouse_string;
}
-termkey_ti_t;
+termo_ti_t;
-static int funcname2keysym (const char *funcname, termkey_type_t *typep,
- termkey_sym_t *symp, int *modmask, int *modsetp);
-static int insert_seq (termkey_ti_t *ti, const char *seq, trie_node_t *node);
+static int funcname2keysym (const char *funcname, termo_type_t *typep,
+ termo_sym_t *symp, int *modmask, int *modsetp);
+static int insert_seq (termo_ti_t *ti, const char *seq, trie_node_t *node);
static trie_node_t *
-new_node_key (termkey_type_t type, termkey_sym_t sym, int modmask, int modset)
+new_node_key (termo_type_t type, termo_sym_t sym, int modmask, int modset)
{
trie_node_key_t *n = malloc (sizeof *n);
if (!n)
@@ -176,7 +176,7 @@ compress_trie (struct trie_node *n)
}
static bool
-load_terminfo (termkey_ti_t *ti, const char *term)
+load_terminfo (termo_ti_t *ti, const char *term)
{
const char *mouse_report_string = NULL;
@@ -212,15 +212,15 @@ load_terminfo (termkey_ti_t *ti, const char *term)
mouse_report_string = value;
else
{
- termkey_type_t type;
- termkey_sym_t sym;
+ termo_type_t type;
+ termo_sym_t sym;
int mask = 0;
int set = 0;
if (!funcname2keysym (name + 4, &type, &sym, &mask, &set))
continue;
- if (sym == TERMKEY_SYM_NONE)
+ if (sym == TERMO_SYM_NONE)
continue;
node = new_node_key (type, sym, mask, set);
@@ -262,7 +262,7 @@ load_terminfo (termkey_ti_t *ti, const char *term)
}
}
- /* Take copies of these terminfo strings, in case we build multiple termkey
+ /* Take copies of these terminfo strings, in case we build multiple termo
* instances for multiple different termtypes, and it's different by the
* time we want to use it
*/
@@ -292,9 +292,9 @@ load_terminfo (termkey_ti_t *ti, const char *term)
}
static void *
-new_driver (termkey_t *tk, const char *term)
+new_driver (termo_t *tk, const char *term)
{
- termkey_ti_t *ti = calloc (1, sizeof *ti);
+ termo_ti_t *ti = calloc (1, sizeof *ti);
if (!ti)
return NULL;
@@ -318,7 +318,7 @@ abort_free_ti:
}
static bool
-write_string (termkey_t *tk, char *string)
+write_string (termo_t *tk, char *string)
{
if (tk->fd == -1 || !isatty (tk->fd) || !string)
return true;
@@ -340,7 +340,7 @@ write_string (termkey_t *tk, char *string)
}
static bool
-set_mouse (termkey_ti_t *ti, bool enable)
+set_mouse (termo_ti_t *ti, bool enable)
{
#ifdef HAVE_UNIBILIUM
unibi_var_t params[9] = { enable, 0, 0, 0, 0, 0, 0, 0, 0 };
@@ -355,9 +355,9 @@ set_mouse (termkey_ti_t *ti, bool enable)
}
static int
-start_driver (termkey_t *tk, void *info)
+start_driver (termo_t *tk, void *info)
{
- termkey_ti_t *ti = info;
+ termo_ti_t *ti = info;
// TODO: Don't start the mouse automatically, find a nice place to put
// a public function to be called by users.
// TODO: Try to autodetect rxvt and use its protocol instead of mode 1000
@@ -368,9 +368,9 @@ start_driver (termkey_t *tk, void *info)
}
static int
-stop_driver (termkey_t *tk, void *info)
+stop_driver (termo_t *tk, void *info)
{
- termkey_ti_t *ti = info;
+ termo_ti_t *ti = info;
if (ti->have_mouse && !set_mouse (ti, false))
return false;
return write_string (tk, ti->stop_string);
@@ -379,7 +379,7 @@ stop_driver (termkey_t *tk, void *info)
static void
free_driver (void *info)
{
- termkey_ti_t *ti = info;
+ termo_ti_t *ti = info;
free_trie (ti->root);
free (ti->set_mouse_string);
free (ti->start_string);
@@ -389,14 +389,14 @@ free_driver (void *info)
#define CHARAT(i) (tk->buffer[tk->buffstart + (i)])
-static termkey_result_t
-peekkey (termkey_t *tk, void *info,
- termkey_key_t *key, int force, size_t *nbytep)
+static termo_result_t
+peekkey (termo_t *tk, void *info,
+ termo_key_t *key, int force, size_t *nbytep)
{
- termkey_ti_t *ti = info;
+ termo_ti_t *ti = info;
if (tk->buffcount == 0)
- return tk->is_closed ? TERMKEY_RES_EOF : TERMKEY_RES_NONE;
+ return tk->is_closed ? TERMO_RES_EOF : TERMO_RES_NONE;
trie_node_t *p = ti->root;
unsigned int pos = 0;
@@ -415,20 +415,20 @@ peekkey (termkey_t *tk, void *info,
key->code.sym = nk->key.sym;
key->modifiers = nk->key.modifier_set;
*nbytep = pos;
- return TERMKEY_RES_KEY;
+ return TERMO_RES_KEY;
}
else if (p->type == TYPE_MOUSE)
{
tk->buffstart += pos;
tk->buffcount -= pos;
- termkey_result_t mouse_result =
+ termo_result_t mouse_result =
(*tk->method.peekkey_mouse) (tk, key, nbytep);
tk->buffstart -= pos;
tk->buffcount += pos;
- if (mouse_result == TERMKEY_RES_KEY)
+ if (mouse_result == TERMO_RES_KEY)
*nbytep += pos;
return mouse_result;
@@ -438,65 +438,65 @@ peekkey (termkey_t *tk, void *info,
// If p is not NULL then we hadn't walked off the end yet, so we have a
// partial match
if (p && !force)
- return TERMKEY_RES_AGAIN;
+ return TERMO_RES_AGAIN;
- return TERMKEY_RES_NONE;
+ return TERMO_RES_NONE;
}
static struct func
{
const char *funcname;
- termkey_type_t type;
- termkey_sym_t sym;
+ termo_type_t type;
+ termo_sym_t sym;
int mods;
}
funcs[] =
{
/* THIS LIST MUST REMAIN SORTED! */
- { "backspace", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BACKSPACE, 0 },
- { "begin", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN, 0 },
- { "beg", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN, 0 },
- { "btab", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_TAB, TERMKEY_KEYMOD_SHIFT },
- { "cancel", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_CANCEL, 0 },
- { "clear", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_CLEAR, 0 },
- { "close", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_CLOSE, 0 },
- { "command", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_COMMAND, 0 },
- { "copy", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_COPY, 0 },
- { "dc", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DELETE, 0 },
- { "down", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DOWN, 0 },
- { "end", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_END, 0 },
- { "enter", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_ENTER, 0 },
- { "exit", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_EXIT, 0 },
- { "find", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_FIND, 0 },
- { "help", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HELP, 0 },
- { "home", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HOME, 0 },
- { "ic", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_INSERT, 0 },
- { "left", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_LEFT, 0 },
- { "mark", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MARK, 0 },
- { "message", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MESSAGE, 0 },
- { "mouse", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_NONE, 0 },
- { "move", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MOVE, 0 },
+ { "backspace", TERMO_TYPE_KEYSYM, TERMO_SYM_BACKSPACE, 0 },
+ { "begin", TERMO_TYPE_KEYSYM, TERMO_SYM_BEGIN, 0 },
+ { "beg", TERMO_TYPE_KEYSYM, TERMO_SYM_BEGIN, 0 },
+ { "btab", TERMO_TYPE_KEYSYM, TERMO_SYM_TAB, TERMO_KEYMOD_SHIFT },
+ { "cancel", TERMO_TYPE_KEYSYM, TERMO_SYM_CANCEL, 0 },
+ { "clear", TERMO_TYPE_KEYSYM, TERMO_SYM_CLEAR, 0 },
+ { "close", TERMO_TYPE_KEYSYM, TERMO_SYM_CLOSE, 0 },
+ { "command", TERMO_TYPE_KEYSYM, TERMO_SYM_COMMAND, 0 },
+ { "copy", TERMO_TYPE_KEYSYM, TERMO_SYM_COPY, 0 },
+ { "dc", TERMO_TYPE_KEYSYM, TERMO_SYM_DELETE, 0 },
+ { "down", TERMO_TYPE_KEYSYM, TERMO_SYM_DOWN, 0 },
+ { "end", TERMO_TYPE_KEYSYM, TERMO_SYM_END, 0 },
+ { "enter", TERMO_TYPE_KEYSYM, TERMO_SYM_ENTER, 0 },
+ { "exit", TERMO_TYPE_KEYSYM, TERMO_SYM_EXIT, 0 },
+ { "find", TERMO_TYPE_KEYSYM, TERMO_SYM_FIND, 0 },
+ { "help", TERMO_TYPE_KEYSYM, TERMO_SYM_HELP, 0 },
+ { "home", TERMO_TYPE_KEYSYM, TERMO_SYM_HOME, 0 },
+ { "ic", TERMO_TYPE_KEYSYM, TERMO_SYM_INSERT, 0 },
+ { "left", TERMO_TYPE_KEYSYM, TERMO_SYM_LEFT, 0 },
+ { "mark", TERMO_TYPE_KEYSYM, TERMO_SYM_MARK, 0 },
+ { "message", TERMO_TYPE_KEYSYM, TERMO_SYM_MESSAGE, 0 },
+ { "mouse", TERMO_TYPE_KEYSYM, TERMO_SYM_NONE, 0 },
+ { "move", TERMO_TYPE_KEYSYM, TERMO_SYM_MOVE, 0 },
// Not quite, but it's the best we can do
- { "next", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN, 0 },
- { "npage", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN, 0 },
- { "open", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_OPEN, 0 },
- { "options", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_OPTIONS, 0 },
- { "ppage", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP, 0 },
+ { "next", TERMO_TYPE_KEYSYM, TERMO_SYM_PAGEDOWN, 0 },
+ { "npage", TERMO_TYPE_KEYSYM, TERMO_SYM_PAGEDOWN, 0 },
+ { "open", TERMO_TYPE_KEYSYM, TERMO_SYM_OPEN, 0 },
+ { "options", TERMO_TYPE_KEYSYM, TERMO_SYM_OPTIONS, 0 },
+ { "ppage", TERMO_TYPE_KEYSYM, TERMO_SYM_PAGEUP, 0 },
// Not quite, but it's the best we can do
- { "previous", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP, 0 },
- { "print", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PRINT, 0 },
- { "redo", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REDO, 0 },
- { "reference", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REFERENCE, 0 },
- { "refresh", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REFRESH, 0 },
- { "replace", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REPLACE, 0 },
- { "restart", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RESTART, 0 },
- { "resume", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RESUME, 0 },
- { "right", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RIGHT, 0 },
- { "save", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SAVE, 0 },
- { "select", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SELECT, 0 },
- { "suspend", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SUSPEND, 0 },
- { "undo", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UNDO, 0 },
- { "up", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UP, 0 },
+ { "previous", TERMO_TYPE_KEYSYM, TERMO_SYM_PAGEUP, 0 },
+ { "print", TERMO_TYPE_KEYSYM, TERMO_SYM_PRINT, 0 },
+ { "redo", TERMO_TYPE_KEYSYM, TERMO_SYM_REDO, 0 },
+ { "reference", TERMO_TYPE_KEYSYM, TERMO_SYM_REFERENCE, 0 },
+ { "refresh", TERMO_TYPE_KEYSYM, TERMO_SYM_REFRESH, 0 },
+ { "replace", TERMO_TYPE_KEYSYM, TERMO_SYM_REPLACE, 0 },
+ { "restart", TERMO_TYPE_KEYSYM, TERMO_SYM_RESTART, 0 },
+ { "resume", TERMO_TYPE_KEYSYM, TERMO_SYM_RESUME, 0 },
+ { "right", TERMO_TYPE_KEYSYM, TERMO_SYM_RIGHT, 0 },
+ { "save", TERMO_TYPE_KEYSYM, TERMO_SYM_SAVE, 0 },
+ { "select", TERMO_TYPE_KEYSYM, TERMO_SYM_SELECT, 0 },
+ { "suspend", TERMO_TYPE_KEYSYM, TERMO_SYM_SUSPEND, 0 },
+ { "undo", TERMO_TYPE_KEYSYM, TERMO_SYM_UNDO, 0 },
+ { "up", TERMO_TYPE_KEYSYM, TERMO_SYM_UP, 0 },
{ NULL },
};
@@ -508,7 +508,7 @@ func_compare (const void *key, const void *element)
static int
funcname2keysym (const char *funcname,
- termkey_type_t *typep, termkey_sym_t *symp, int *modmaskp, int *modsetp)
+ termo_type_t *typep, termo_sym_t *symp, int *modmaskp, int *modsetp)
{
struct func *func = bsearch (funcname, funcs,
sizeof funcs / sizeof funcs[0], sizeof funcs[0], func_compare);
@@ -523,7 +523,7 @@ funcname2keysym (const char *funcname,
if (funcname[0] == 'f' && isdigit (funcname[1]))
{
- *typep = TERMKEY_TYPE_FUNCTION;
+ *typep = TERMO_TYPE_FUNCTION;
*symp = atoi (funcname + 1);
return 1;
}
@@ -532,8 +532,8 @@ funcname2keysym (const char *funcname,
if (funcname[0] == 's' && funcname2keysym
(funcname + 1, typep, symp, modmaskp, modsetp))
{
- *modmaskp |= TERMKEY_KEYMOD_SHIFT;
- *modsetp |= TERMKEY_KEYMOD_SHIFT;
+ *modmaskp |= TERMO_KEYMOD_SHIFT;
+ *modsetp |= TERMO_KEYMOD_SHIFT;
return 1;
}
@@ -546,7 +546,7 @@ funcname2keysym (const char *funcname,
}
static int
-insert_seq (termkey_ti_t *ti, const char *seq, trie_node_t *node)
+insert_seq (termo_ti_t *ti, const char *seq, trie_node_t *node)
{
int pos = 0;
trie_node_t *p = ti->root;
@@ -603,7 +603,7 @@ insert_seq (termkey_ti_t *ti, const char *seq, trie_node_t *node)
return 1;
}
-termkey_driver_t termkey_driver_ti =
+termo_driver_t termo_driver_ti =
{
.name = "terminfo",
.new_driver = new_driver,
diff --git a/termkey2-config.h.in b/termkey2-config.h.in
deleted file mode 100644
index 676a2c0..0000000
--- a/termkey2-config.h.in
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef TERMKEY2_CONFIG_H
-#define TERMKEY2_CONFIG_H
-
-#define TERMKEY_VERSION_MAJOR @project_VERSION_MAJOR@
-#define TERMKEY_VERSION_MINOR @project_VERSION_MINOR@
-
-#endif // ! TERMKEY2_CONFIG_H
-
diff --git a/termkey2-internal.h b/termkey2-internal.h
deleted file mode 100644
index 5da33ff..0000000
--- a/termkey2-internal.h
+++ /dev/null
@@ -1,112 +0,0 @@
-#ifndef TERMKEY2_INTERNAL_H
-#define TERMKEY2_INTERNAL_H
-
-#include "termkey2.h"
-
-#include
-#include
-#include
-#include
-
-typedef struct termkey_driver termkey_driver_t;
-struct termkey_driver
-{
- const char *name;
- void *(*new_driver) (termkey_t *tk, const char *term);
- void (*free_driver) (void *info);
- int (*start_driver) (termkey_t *tk, void *info);
- int (*stop_driver) (termkey_t *tk, void *info);
- termkey_result_t (*peekkey) (termkey_t *tk,
- void *info, termkey_key_t *key, int force, size_t *nbytes);
-};
-
-typedef struct keyinfo keyinfo_t;
-struct keyinfo
-{
- termkey_type_t type;
- termkey_sym_t sym;
- int modifier_mask;
- int modifier_set;
-};
-
-typedef struct termkey_driver_node termkey_driver_node_t;
-struct termkey_driver_node
-{
- termkey_driver_t *driver;
- void *info;
- termkey_driver_node_t *next;
-};
-
-struct termkey
-{
- int fd;
- int flags;
- int canonflags;
-
- unsigned char *buffer;
- size_t buffstart; // First offset in buffer
- size_t buffcount; // Number of entires valid in buffer
- size_t buffsize; // Total malloc'ed size
-
- // Position beyond buffstart at which peekkey() should next start.
- // Normally 0, but see also termkey_interpret_csi().
- size_t hightide;
-
- struct termios restore_termios;
- bool restore_termios_valid;
-
- int waittime; // In milliseconds
-
- bool is_closed; // We've received EOF
- bool is_started;
-
- int nkeynames;
- const char **keynames;
-
- keyinfo_t c0[32]; // There are 32 C0 codes
- iconv_t to_utf32_conv;
- iconv_t from_utf32_conv;
- termkey_driver_node_t *drivers;
-
- // Now some "protected" methods for the driver to call but which we don't
- // want exported as real symbols in the library
- struct
- {
- void (*emit_codepoint) (termkey_t *tk,
- uint32_t codepoint, termkey_key_t *key);
- termkey_result_t (*peekkey_simple) (termkey_t *tk,
- termkey_key_t *key, int force, size_t *nbytes);
- termkey_result_t (*peekkey_mouse) (termkey_t *tk,
- termkey_key_t *key, size_t *nbytes);
- }
- method;
-};
-
-static inline void
-termkey_key_get_linecol (const termkey_key_t *key, int *line, int *col)
-{
- if (col)
- *col = key->code.mouse.x;
-
- if (line)
- *line = key->code.mouse.y;
-}
-
-static inline void
-termkey_key_set_linecol (termkey_key_t *key, int line, int col)
-{
- if (line > UINT16_MAX)
- line = UINT16_MAX;
-
- if (col > UINT16_MAX)
- col = UINT16_MAX;
-
- key->code.mouse.x = col;
- key->code.mouse.y = line;
-}
-
-extern termkey_driver_t termkey_driver_csi;
-extern termkey_driver_t termkey_driver_ti;
-
-#endif // ! TERMKEY2_INTERNAL_H
-
diff --git a/termkey2.c b/termkey2.c
deleted file mode 100644
index 37831b8..0000000
--- a/termkey2.c
+++ /dev/null
@@ -1,1656 +0,0 @@
-#include "termkey2.h"
-#include "termkey2-internal.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-void
-termkey_check_version (int major, int minor)
-{
- if (major != TERMKEY_VERSION_MAJOR)
- fprintf (stderr, "libtermkey major version mismatch;"
- " %d (wants) != %d (library)\n",
- major, TERMKEY_VERSION_MAJOR);
- else if (minor > TERMKEY_VERSION_MINOR)
- fprintf (stderr, "libtermkey minor version mismatch;"
- " %d (wants) > %d (library)\n",
- minor, TERMKEY_VERSION_MINOR);
- else
- return;
- exit (1);
-}
-
-static termkey_driver_t *drivers[] =
-{
- &termkey_driver_ti,
- &termkey_driver_csi,
- NULL,
-};
-
-// Forwards for the "protected" methods
-static void emit_codepoint (termkey_t *tk, uint32_t codepoint, termkey_key_t *key);
-static termkey_result_t peekkey_simple (termkey_t *tk,
- termkey_key_t *key, int force, size_t *nbytes);
-static termkey_result_t peekkey_mouse (termkey_t *tk,
- termkey_key_t *key, size_t *nbytes);
-
-static termkey_sym_t register_c0 (termkey_t *tk, termkey_sym_t sym,
- unsigned char ctrl, const char *name);
-static termkey_sym_t register_c0_full (termkey_t *tk, termkey_sym_t sym,
- int modifier_set, int modifier_mask, unsigned char ctrl, const char *name);
-
-static struct
-{
- termkey_sym_t 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 },
-};
-
-#define CHARAT(i) (tk->buffer[tk->buffstart + (i)])
-
-#ifdef DEBUG
-/* Some internal deubgging functions */
-
-static void
-print_buffer (termkey_t *tk)
-{
- size_t 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_t *tk, termkey_key_t *key)
-{
- switch (key->type)
- {
- case TERMKEY_TYPE_KEY:
- fprintf (stderr, "Unicode codepoint=U+%04lx multibyte='%s'",
- (long) key->code.codepoint, key->multibyte);
- break;
- case TERMKEY_TYPE_FUNCTION:
- fprintf (stderr, "Function F%d", key->code.number);
- break;
- case TERMKEY_TYPE_KEYSYM:
- fprintf (stderr, "Keysym sym=%d(%s)",
- key->code.sym, termkey_get_keyname (tk, key->code.sym));
- break;
- case TERMKEY_TYPE_MOUSE:
- {
- termkey_mouse_event_t ev;
- int button, line, col;
- termkey_interpret_mouse (tk, key, &ev, &button, &line, &col);
- fprintf (stderr, "Mouse ev=%d button=%d pos=(%d,%d)\n",
- ev, button, line, col);
- break;
- }
- case TERMKEY_TYPE_POSITION:
- {
- int line, col;
- termkey_interpret_position (tk, key, &line, &col);
- fprintf (stderr, "Position report pos=(%d,%d)\n", line, col);
- break;
- }
- case TERMKEY_TYPE_MODEREPORT:
- {
- int initial, mode, value;
- termkey_interpret_modereport (tk, key, &initial, &mode, &value);
- fprintf (stderr, "Mode report mode=%s %d val=%d\n",
- initial == '?' ? "DEC" : "ANSI", mode, value);
- break;
- }
- case TERMKEY_TYPE_UNKNOWN_CSI:
- fprintf (stderr, "unknown CSI\n");
- }
-
- int m = key->modifiers;
- fprintf (stderr, " mod=%s%s%s+%02x",
- (m & TERMKEY_KEYMOD_CTRL ? "C" : ""),
- (m & TERMKEY_KEYMOD_ALT ? "A" : ""),
- (m & TERMKEY_KEYMOD_SHIFT ? "S" : ""),
- m & ~(TERMKEY_KEYMOD_CTRL | TERMKEY_KEYMOD_ALT | TERMKEY_KEYMOD_SHIFT));
-}
-
-static const char *
-res2str (termkey_result_t res)
-{
- static char errorbuffer[256];
-
- switch (res)
- {
- case TERMKEY_RES_KEY:
- return "TERMKEY_RES_KEY";
- case TERMKEY_RES_EOF:
- return "TERMKEY_RES_EOF";
- case TERMKEY_RES_AGAIN:
- return "TERMKEY_RES_AGAIN";
- case TERMKEY_RES_NONE:
- return "TERMKEY_RES_NONE";
- case TERMKEY_RES_ERROR:
- snprintf (errorbuffer, sizeof errorbuffer,
- "TERMKEY_RES_ERROR(errno=%d)\n", errno);
- return (const char*) errorbuffer;
- }
-
- return "unknown";
-}
-#endif
-
-/* Similar to snprintf(str, size, "%s", src) except it turns CamelCase into
- * space separated values
- */
-static int
-snprint_cameltospaces (char *str, size_t size, const char *src)
-{
- int prev_lower = 0;
- size_t l = 0;
- while (*src && l < size - 1)
- {
- if (isupper (*src) && prev_lower)
- {
- if (str)
- str[l++] = ' ';
- if (l >= size - 1)
- break;
- }
- prev_lower = islower (*src);
- str[l++] = tolower (*src++);
- }
- str[l] = 0;
-
- /* For consistency with snprintf, return the number of bytes that would have
- * been written, excluding '\0' */
- for (; *src; src++)
- {
- if (isupper (*src) && prev_lower)
- l++;
- prev_lower = islower (*src);
- l++;
- }
- return l;
-}
-
-/* Similar to strcmp(str, strcamel, n) except that:
- * it compares CamelCase in strcamel with space separated values in str;
- * it takes char**s and updates them
- * n counts bytes of strcamel, not str
- */
-static int
-strpncmp_camel (const char **strp, const char **strcamelp, size_t n)
-{
- const char *str = *strp, *strcamel = *strcamelp;
- int prev_lower = 0;
-
- for (; (*str || *strcamel) && n; n--)
- {
- char b = tolower (*strcamel);
- if (isupper (*strcamel) && prev_lower)
- {
- if (*str != ' ')
- break;
- str++;
- if (*str != b)
- break;
- }
- else if (*str != b)
- break;
-
- prev_lower = islower (*strcamel);
-
- str++;
- strcamel++;
- }
-
- *strp = str;
- *strcamelp = strcamel;
- return *str - *strcamel;
-}
-
-static termkey_t *
-termkey_alloc (void)
-{
- termkey_t *tk = malloc (sizeof *tk);
- if (!tk)
- return NULL;
-
- /* Default all the object fields but don't allocate anything */
-
- tk->fd = -1;
- tk->flags = 0;
- tk->canonflags = 0;
-
- tk->buffer = NULL;
- tk->buffstart = 0;
- tk->buffcount = 0;
- tk->buffsize = 256; /* bytes */
- tk->hightide = 0;
-
- tk->restore_termios_valid = false;
-
- tk->waittime = 50; /* msec */
-
- tk->is_closed = false;
- tk->is_started = false;
-
- tk->nkeynames = 64;
- tk->keynames = NULL;
-
- for (int i = 0; i < 32; i++)
- tk->c0[i].sym = TERMKEY_SYM_NONE;
-
- tk->drivers = NULL;
-
- tk->method.emit_codepoint = &emit_codepoint;
- tk->method.peekkey_simple = &peekkey_simple;
- tk->method.peekkey_mouse = &peekkey_mouse;
- return tk;
-}
-
-static int
-termkey_init (termkey_t *tk, const char *term, const char *encoding)
-{
- if (!encoding)
- encoding = nl_langinfo (CODESET);
-
- static const uint16_t endianity = 0x0102;
- const char *utf32 = (*(uint8_t *) &endianity == 0x01)
- ? "UTF-32BE" : "UTF-32LE";
-
- if ((tk->to_utf32_conv = iconv_open (utf32, encoding)) == (iconv_t) -1)
- return 0;
- if ((tk->from_utf32_conv = iconv_open (encoding, utf32)) == (iconv_t) -1)
- goto abort_free_to_utf32;
-
- tk->buffer = malloc (tk->buffsize);
- if (!tk->buffer)
- goto abort_free_from_utf32;
-
- tk->keynames = malloc (sizeof tk->keynames[0] * tk->nkeynames);
- if (!tk->keynames)
- goto abort_free_buffer;
-
- int i;
- for (i = 0; i < tk->nkeynames; i++)
- tk->keynames[i] = NULL;
- for (i = 0; keynames[i].name; i++)
- if (termkey_register_keyname (tk,
- keynames[i].sym, keynames[i].name) == -1)
- goto abort_free_keynames;
-
- register_c0 (tk, TERMKEY_SYM_BACKSPACE, 0x08, NULL);
- register_c0 (tk, TERMKEY_SYM_TAB, 0x09, NULL);
- register_c0 (tk, TERMKEY_SYM_ENTER, 0x0d, NULL);
- register_c0 (tk, TERMKEY_SYM_ESCAPE, 0x1b, NULL);
-
- termkey_driver_node_t **tail = &tk->drivers;
- for (i = 0; drivers[i]; i++)
- {
- void *info = (*drivers[i]->new_driver) (tk, term);
- if (!info)
- continue;
-
-#ifdef DEBUG
- fprintf (stderr, "Loading the %s driver...\n", drivers[i]->name);
-#endif
-
- termkey_driver_node_t *thisdrv = malloc (sizeof *thisdrv);
- if (!thisdrv)
- goto abort_free_drivers;
-
- thisdrv->driver = drivers[i];
- thisdrv->info = info;
- thisdrv->next = NULL;
-
- *tail = thisdrv;
- tail = &thisdrv->next;
-
-#ifdef DEBUG
- fprintf (stderr, "Loaded %s driver\n", drivers[i]->name);
-#endif
- }
-
- if (!tk->drivers)
- {
- errno = ENOENT;
- goto abort_free_keynames;
- }
- return 1;
-
-abort_free_drivers:
- for (termkey_driver_node_t *p = tk->drivers; p; )
- {
- (*p->driver->free_driver) (p->info);
- termkey_driver_node_t *next = p->next;
- free (p);
- p = next;
- }
-
-abort_free_keynames:
- free (tk->keynames);
-abort_free_buffer:
- free (tk->buffer);
-abort_free_from_utf32:
- iconv_close (tk->from_utf32_conv);
-abort_free_to_utf32:
- iconv_close (tk->to_utf32_conv);
- return 0;
-}
-
-termkey_t *
-termkey_new (int fd, const char *encoding, int flags)
-{
- termkey_t *tk = termkey_alloc ();
- if (!tk)
- return NULL;
-
- tk->fd = fd;
- termkey_set_flags (tk, flags);
-
- const char *term = getenv ("TERM");
- if (termkey_init (tk, term, encoding)
- && termkey_start (tk))
- return tk;
-
- free (tk);
- return NULL;
-}
-
-termkey_t *
-termkey_new_abstract (const char *term, const char *encoding, int flags)
-{
- termkey_t *tk = termkey_alloc ();
- if (!tk)
- return NULL;
-
- tk->fd = -1;
- termkey_set_flags (tk, flags);
-
- if (!termkey_init (tk, term, encoding))
- {
- free (tk);
- return NULL;
- }
-
- termkey_start (tk);
- return tk;
-}
-
-void
-termkey_free (termkey_t *tk)
-{
- free (tk->buffer); tk->buffer = NULL;
- free (tk->keynames); tk->keynames = NULL;
-
- iconv_close (tk->to_utf32_conv);
- tk->to_utf32_conv = (iconv_t) -1;
- iconv_close (tk->from_utf32_conv);
- tk->from_utf32_conv = (iconv_t) -1;
-
- termkey_driver_node_t *p, *next;
- for (p = tk->drivers; p; p = next)
- {
- (*p->driver->free_driver) (p->info);
- next = p->next;
- free (p);
- }
- free (tk);
-}
-
-void
-termkey_destroy (termkey_t *tk)
-{
- if (tk->is_started)
- termkey_stop (tk);
-
- termkey_free (tk);
-}
-
-int
-termkey_start (termkey_t *tk)
-{
- if (tk->is_started)
- return 1;
-
- if (tk->fd != -1 && !(tk->flags & TERMKEY_FLAG_NOTERMIOS))
- {
- struct termios termios;
- if (tcgetattr (tk->fd, &termios) == 0)
- {
- tk->restore_termios = termios;
- tk->restore_termios_valid = true;
-
- termios.c_iflag &= ~(IXON|INLCR|ICRNL);
- termios.c_lflag &= ~(ICANON|ECHO);
- termios.c_cc[VMIN] = 1;
- termios.c_cc[VTIME] = 0;
-
- if (tk->flags & TERMKEY_FLAG_CTRLC)
- /* want no signal keys at all, so just disable ISIG */
- termios.c_lflag &= ~ISIG;
- else
- {
- /* Disable ^\ == VQUIT and ^D == VSUSP but leave ^C as SIGINT */
- termios.c_cc[VQUIT] = _POSIX_VDISABLE;
- termios.c_cc[VSUSP] = _POSIX_VDISABLE;
- /* Some OSes have ^Y == VDSUSP */
-#ifdef VDSUSP
- termios.c_cc[VDSUSP] = _POSIX_VDISABLE;
-#endif
- }
-
-#ifdef DEBUG
- fprintf (stderr, "Setting termios(3) flags\n");
-#endif
- tcsetattr (tk->fd, TCSANOW, &termios);
- }
- }
-
- termkey_driver_node_t *p;
- for (p = tk->drivers; p; p = p->next)
- if (p->driver->start_driver)
- if (!(*p->driver->start_driver) (tk, p->info))
- return 0;
-
-#ifdef DEBUG
- fprintf (stderr, "Drivers started; termkey instance %p is ready\n", tk);
-#endif
-
- tk->is_started = 1;
- return 1;
-}
-
-int
-termkey_stop (termkey_t *tk)
-{
- if (!tk->is_started)
- return 1;
-
- struct termkey_driver_node *p;
- for (p = tk->drivers; p; p = p->next)
- if (p->driver->stop_driver)
- (*p->driver->stop_driver) (tk, p->info);
-
- if (tk->restore_termios_valid)
- tcsetattr (tk->fd, TCSANOW, &tk->restore_termios);
-
- tk->is_started = false;
- return 1;
-}
-
-int
-termkey_is_started (termkey_t *tk)
-{
- return tk->is_started;
-}
-
-int
-termkey_get_fd (termkey_t *tk)
-{
- return tk->fd;
-}
-
-int
-termkey_get_flags (termkey_t *tk)
-{
- return tk->flags;
-}
-
-void
-termkey_set_flags (termkey_t *tk, int newflags)
-{
- tk->flags = newflags;
- if (tk->flags & TERMKEY_FLAG_SPACESYMBOL)
- tk->canonflags |= TERMKEY_CANON_SPACESYMBOL;
- else
- tk->canonflags &= ~TERMKEY_CANON_SPACESYMBOL;
-}
-
-void
-termkey_set_waittime (termkey_t *tk, int msec)
-{
- tk->waittime = msec;
-}
-
-int
-termkey_get_waittime (termkey_t *tk)
-{
- return tk->waittime;
-}
-
-int
-termkey_get_canonflags (termkey_t *tk)
-{
- return tk->canonflags;
-}
-
-void
-termkey_set_canonflags (termkey_t *tk, int flags)
-{
- tk->canonflags = flags;
- if (tk->canonflags & TERMKEY_CANON_SPACESYMBOL)
- tk->flags |= TERMKEY_FLAG_SPACESYMBOL;
- else
- tk->flags &= ~TERMKEY_FLAG_SPACESYMBOL;
-}
-
-size_t
-termkey_get_buffer_size (termkey_t *tk)
-{
- return tk->buffsize;
-}
-
-int
-termkey_set_buffer_size (termkey_t *tk, size_t size)
-{
- unsigned char *buffer = realloc (tk->buffer, size);
- if (!buffer)
- return 0;
-
- tk->buffer = buffer;
- tk->buffsize = size;
- return 1;
-}
-
-size_t
-termkey_get_buffer_remaining (termkey_t *tk)
-{
- /* Return the total number of free bytes in the buffer,
- * because that's what is available to the user. */
- return tk->buffsize - tk->buffcount;
-}
-
-static void
-eat_bytes (termkey_t *tk, size_t count)
-{
- if (count >= tk->buffcount)
- {
- tk->buffstart = 0;
- tk->buffcount = 0;
- return;
- }
-
- tk->buffstart += count;
- tk->buffcount -= count;
-}
-
-#define MULTIBYTE_INVALID '?'
-
-static void
-fill_multibyte (termkey_t *tk, termkey_key_t *key)
-{
- size_t codepoint_len = sizeof key->code.codepoint;
- char *codepoint_ptr = (char *) &key->code.codepoint;
- size_t multibyte_len = sizeof key->multibyte;
- char *multibyte_ptr = (char *) key->multibyte;
-
- size_t result = iconv (tk->from_utf32_conv,
- &codepoint_ptr, &codepoint_len, &multibyte_ptr, &multibyte_len);
- size_t output = sizeof key->multibyte - multibyte_len;
-
- // Something broke
- if (result == (size_t) -1 || output == 0)
- {
- key->multibyte[0] = MULTIBYTE_INVALID;
- key->multibyte[1] = 0;
- return;
- }
-
- // Append a null character, as it wasn't port of the input
- key->multibyte[output] = 0;
-}
-
-static termkey_result_t
-parse_multibyte (termkey_t *tk, const unsigned char *bytes, size_t len,
- uint32_t *cp, size_t *nbytep)
-{
- size_t multibyte_len = len;
- char *multibyte_ptr = (char *) bytes;
- size_t codepoint_len = sizeof *cp;
- char *codepoint_ptr = (char *) cp;
-
- // Fingers crossed...
- errno = 0;
- iconv (tk->to_utf32_conv,
- &multibyte_ptr, &multibyte_len, &codepoint_ptr, &codepoint_len);
-
- // Only one Unicode character could have been processed at maximum,
- // so let's just set the number of processed bytes to the difference
- *nbytep = len - multibyte_len;
-
- // Nothing has been converted, let's examine what happened
- if (codepoint_ptr == (char *) cp)
- {
- if (errno == 0)
- // The input was probably a shift sequence
- return TERMKEY_RES_AGAIN;
- if (errno == EINVAL)
- // Incomplete character or shift sequence
- return TERMKEY_RES_AGAIN;
- if (errno == EILSEQ)
- {
- // Invalid multibyte sequence in the input, let's try going
- // byte after byte in hope we skip it completely
- *cp = MULTIBYTE_INVALID;
- *nbytep = 1;
- return TERMKEY_RES_KEY;
- }
-
- // We can't really get E2BIG so what the fuck is going on here
- abort ();
- }
- return TERMKEY_RES_KEY;
-}
-
-static void
-emit_codepoint (termkey_t *tk, uint32_t codepoint, termkey_key_t *key)
-{
- if (codepoint < 0x20)
- {
- // C0 range
- key->code.codepoint = 0;
- key->modifiers = 0;
-
- if (!(tk->flags & TERMKEY_FLAG_NOINTERPRET)
- && tk->c0[codepoint].sym != TERMKEY_SYM_UNKNOWN)
- {
- key->code.sym = tk->c0[codepoint].sym;
- key->modifiers |= tk->c0[codepoint].modifier_set;
- }
-
- if (!key->code.sym)
- {
- key->type = TERMKEY_TYPE_KEY;
- /* Generically modified Unicode ought not report the SHIFT state,
- * or else we get into complications trying to report Shift-; vs :
- * and so on... In order to be able to represent Ctrl-Shift-A as
- * CTRL modified unicode A, we need to call Ctrl-A simply 'a',
- * lowercase
- */
- if (codepoint + 0x40 >= 'A' && codepoint + 0x40 <= 'Z')
- // It's a letter - use lowercase instead
- key->code.codepoint = codepoint + 0x60;
- else
- key->code.codepoint = codepoint + 0x40;
- key->modifiers = TERMKEY_KEYMOD_CTRL;
- }
- else
- key->type = TERMKEY_TYPE_KEYSYM;
- }
- else if (codepoint == 0x7f && !(tk->flags & TERMKEY_FLAG_NOINTERPRET))
- {
- // ASCII DEL
- key->type = TERMKEY_TYPE_KEYSYM;
- key->code.sym = TERMKEY_SYM_DEL;
- key->modifiers = 0;
- }
- else
- {
- key->type = TERMKEY_TYPE_KEY;
- key->code.codepoint = codepoint;
- key->modifiers = 0;
- }
-
- termkey_canonicalise (tk, key);
-
- if (key->type == TERMKEY_TYPE_KEY)
- fill_multibyte (tk, key);
-}
-
-void
-termkey_canonicalise (termkey_t *tk, termkey_key_t *key)
-{
- int flags = tk->canonflags;
-
- if (flags & TERMKEY_CANON_SPACESYMBOL)
- {
- if (key->type == TERMKEY_TYPE_KEY && key->code.codepoint == 0x20)
- {
- key->type = TERMKEY_TYPE_KEYSYM;
- key->code.sym = TERMKEY_SYM_SPACE;
- }
- }
- else
- {
- if (key->type == TERMKEY_TYPE_KEYSYM
- && key->code.sym == TERMKEY_SYM_SPACE)
- {
- key->type = TERMKEY_TYPE_KEY;
- key->code.codepoint = 0x20;
- fill_multibyte (tk, key);
- }
- }
-
- if (flags & TERMKEY_CANON_DELBS)
- if (key->type == TERMKEY_TYPE_KEYSYM
- && key->code.sym == TERMKEY_SYM_DEL)
- key->code.sym = TERMKEY_SYM_BACKSPACE;
-}
-
-static termkey_result_t
-peekkey (termkey_t *tk, termkey_key_t *key, int force, size_t *nbytep)
-{
- int again = 0;
-
- if (!tk->is_started)
- {
- errno = EINVAL;
- return TERMKEY_RES_ERROR;
- }
-
-#ifdef DEBUG
- fprintf (stderr, "getkey(force=%d): buffer ", force);
- print_buffer (tk);
- fprintf (stderr, "\n");
-#endif
-
- if (tk->hightide)
- {
- tk->buffstart += tk->hightide;
- tk->buffcount -= tk->hightide;
- tk->hightide = 0;
- }
-
- termkey_result_t ret;
- termkey_driver_node_t *p;
- for (p = tk->drivers; p; p = p->next)
- {
- ret = (p->driver->peekkey) (tk, p->info, key, force, nbytep);
-
-#ifdef DEBUG
- fprintf (stderr, "Driver %s yields %s\n",
- p->driver->name, res2str (ret));
-#endif
-
- switch (ret)
- {
- case TERMKEY_RES_KEY:
- {
-#ifdef DEBUG
- print_key (tk, key); fprintf (stderr, "\n");
-#endif
- // Slide the data down to stop it running away
- size_t halfsize = tk->buffsize / 2;
- if (tk->buffstart > halfsize)
- {
- memcpy (tk->buffer, tk->buffer + halfsize, halfsize);
- tk->buffstart -= halfsize;
- }
-
- /* fallthrough */
- }
- case TERMKEY_RES_EOF:
- case TERMKEY_RES_ERROR:
- return ret;
-
- case TERMKEY_RES_AGAIN:
- if (!force)
- again = 1;
- case TERMKEY_RES_NONE:
- break;
- }
- }
-
- if (again)
- return TERMKEY_RES_AGAIN;
-
- ret = peekkey_simple (tk, key, force, nbytep);
-
-#ifdef DEBUG
- fprintf (stderr, "getkey_simple(force=%d) yields %s\n",
- force, res2str (ret));
- if (ret == TERMKEY_RES_KEY)
- {
- print_key (tk, key);
- fprintf (stderr, "\n");
- }
-#endif
-
- return ret;
-}
-
-static termkey_result_t
-peekkey_simple (termkey_t *tk, termkey_key_t *key, int force, size_t *nbytep)
-{
- if (tk->buffcount == 0)
- return tk->is_closed ? TERMKEY_RES_EOF : TERMKEY_RES_NONE;
-
- unsigned char b0 = CHARAT (0);
- if (b0 == 0x1b)
- {
- // Escape-prefixed value? Might therefore be Alt+key
- if (tk->buffcount == 1)
- {
- // This might be an press, or it may want to be part
- // of a longer sequence
- if (!force)
- return TERMKEY_RES_AGAIN;
-
- (*tk->method.emit_codepoint) (tk, b0, key);
- *nbytep = 1;
- return TERMKEY_RES_KEY;
- }
-
- // Try another key there
- tk->buffstart++;
- tk->buffcount--;
-
- // Run the full driver
- termkey_result_t metakey_result = peekkey (tk, key, force, nbytep);
-
- tk->buffstart--;
- tk->buffcount++;
-
- switch (metakey_result)
- {
- case TERMKEY_RES_KEY:
- key->modifiers |= TERMKEY_KEYMOD_ALT;
- (*nbytep)++;
- break;
-
- case TERMKEY_RES_NONE:
- case TERMKEY_RES_EOF:
- case TERMKEY_RES_AGAIN:
- case TERMKEY_RES_ERROR:
- break;
- }
-
- return metakey_result;
- }
- else if (!(tk->flags & TERMKEY_FLAG_RAW))
- {
- uint32_t codepoint;
- termkey_result_t res = parse_multibyte
- (tk, tk->buffer + tk->buffstart, tk->buffcount, &codepoint, nbytep);
-
- if (res == TERMKEY_RES_AGAIN && force)
- {
- /* There weren't enough bytes for a complete character but
- * caller demands an answer. About the best thing we can do here
- * is eat as many bytes as we have, and emit a MULTIBYTE_INVALID.
- * If the remaining bytes arrive later, they'll be invalid too.
- */
- codepoint = MULTIBYTE_INVALID;
- *nbytep = tk->buffcount;
- res = TERMKEY_RES_KEY;
- }
-
- key->type = TERMKEY_TYPE_KEY;
- key->modifiers = 0;
- (*tk->method.emit_codepoint) (tk, codepoint, key);
- return res;
- }
- else
- {
- // Non multibyte case - just report the raw byte
- key->type = TERMKEY_TYPE_KEY;
- key->code.codepoint = b0;
- key->modifiers = 0;
-
- key->multibyte[0] = b0;
- key->multibyte[1] = 0;
-
- *nbytep = 1;
- return TERMKEY_RES_KEY;
- }
-}
-
-// XXX: With the current infrastructure I'm not sure how to properly handle
-// this. peekkey() isn't made for skipping invalid inputs.
-#define INVALID_1005 0x20
-
-static termkey_result_t
-parse_1005_value (const unsigned char **bytes, size_t *len, uint32_t *cp)
-{
- unsigned int nbytes;
- unsigned char b0 = (*bytes)[0];
- if (b0 < 0x80)
- {
- // Single byte ASCII
- *cp = b0;
- nbytes = 1;
- goto end;
- }
- else if (b0 < 0xc0)
- {
- // Starts with a continuation byte - that's not right
- *cp = INVALID_1005;
- nbytes = 1;
- goto end;
- }
- else if (b0 < 0xe0)
- {
- nbytes = 2;
- *cp = b0 & 0x1f;
- }
- else if (b0 < 0xf0)
- {
- nbytes = 3;
- *cp = b0 & 0x0f;
- }
- else if (b0 < 0xf8)
- {
- nbytes = 4;
- *cp = b0 & 0x07;
- }
- else if (b0 < 0xfc)
- {
- nbytes = 5;
- *cp = b0 & 0x03;
- }
- else if (b0 < 0xfe)
- {
- nbytes = 6;
- *cp = b0 & 0x01;
- }
- else
- {
- *cp = INVALID_1005;
- nbytes = 1;
- goto end;
- }
-
- for (unsigned int b = 1; b < nbytes; b++)
- {
- if (b >= *len)
- return TERMKEY_RES_AGAIN;
-
- unsigned char cb = (*bytes)[b];
- if (cb < 0x80 || cb >= 0xc0)
- {
- *cp = INVALID_1005;
- nbytes = b;
- goto end;
- }
- *cp <<= 6;
- *cp |= cb & 0x3f;
- }
-
-end:
- (*bytes) += nbytes;
- (*len) -= nbytes;
- return TERMKEY_RES_KEY;
-}
-
-static termkey_result_t
-peekkey_mouse (termkey_t *tk, termkey_key_t *key, size_t *nbytep)
-{
- uint32_t b, x, y;
-
- // TODO: Add some API to switch on 1005 mode support
- if (false)
- {
- const unsigned char *buff = tk->buffer + tk->buffstart;
- size_t len = tk->buffcount;
-
- if (parse_1005_value (&buff, &len, &b) == TERMKEY_RES_AGAIN
- || parse_1005_value (&buff, &len, &x) == TERMKEY_RES_AGAIN
- || parse_1005_value (&buff, &len, &y) == TERMKEY_RES_AGAIN)
- return TERMKEY_RES_AGAIN;
-
- *nbytep = tk->buffcount - len;
- }
- else
- {
- if (tk->buffcount < 3)
- return TERMKEY_RES_AGAIN;
-
- b = CHARAT (0);
- x = CHARAT (1);
- y = CHARAT (2);
-
- *nbytep = 3;
- }
-
- key->type = TERMKEY_TYPE_MOUSE;
- key->code.mouse.info = b - 0x20;
- key->code.mouse.x = x - 0x20 - 1;
- key->code.mouse.y = y - 0x20 - 1;
-
- key->modifiers = (key->code.mouse.info & 0x1c) >> 2;
- key->code.mouse.info &= ~0x1c;
-
- return TERMKEY_RES_KEY;
-}
-
-termkey_result_t
-termkey_getkey (termkey_t *tk, termkey_key_t *key)
-{
- size_t nbytes = 0;
- termkey_result_t ret = peekkey (tk, key, 0, &nbytes);
-
- if (ret == TERMKEY_RES_KEY)
- eat_bytes (tk, nbytes);
-
- if (ret == TERMKEY_RES_AGAIN)
- /* Call peekkey() again in force mode to obtain whatever it can */
- (void) peekkey (tk, key, 1, &nbytes);
- /* Don't eat it yet though */
-
- return ret;
-}
-
-termkey_result_t
-termkey_getkey_force (termkey_t *tk, termkey_key_t *key)
-{
- size_t nbytes = 0;
- termkey_result_t ret = peekkey (tk, key, 1, &nbytes);
-
- if (ret == TERMKEY_RES_KEY)
- eat_bytes (tk, nbytes);
-
- return ret;
-}
-
-termkey_result_t
-termkey_waitkey (termkey_t *tk, termkey_key_t *key)
-{
- if (tk->fd == -1)
- {
- errno = EBADF;
- return TERMKEY_RES_ERROR;
- }
-
- while (1)
- {
- termkey_result_t ret = termkey_getkey (tk, key);
-
- switch (ret)
- {
- case TERMKEY_RES_KEY:
- case TERMKEY_RES_EOF:
- case TERMKEY_RES_ERROR:
- return ret;
-
- case TERMKEY_RES_NONE:
- ret = termkey_advisereadable (tk);
- if (ret == TERMKEY_RES_ERROR)
- return ret;
- break;
-
- case TERMKEY_RES_AGAIN:
- {
- if (tk->is_closed)
- // We're closed now. Never going to get more bytes
- // so just go with what we have
- return termkey_getkey_force (tk, key);
-
- struct pollfd fd;
-retry:
- fd.fd = tk->fd;
- fd.events = POLLIN;
-
- int pollret = poll (&fd, 1, tk->waittime);
- if (pollret == -1)
- {
- if (errno == EINTR && !(tk->flags & TERMKEY_FLAG_EINTR))
- goto retry;
-
- return TERMKEY_RES_ERROR;
- }
-
- if (fd.revents & (POLLIN | POLLHUP | POLLERR))
- ret = termkey_advisereadable (tk);
- else
- ret = TERMKEY_RES_NONE;
-
- if (ret == TERMKEY_RES_ERROR)
- return ret;
- if (ret == TERMKEY_RES_NONE)
- return termkey_getkey_force (tk, key);
- }
- }
- }
-
- /* UNREACHABLE */
-}
-
-termkey_result_t
-termkey_advisereadable (termkey_t *tk)
-{
- if (tk->fd == -1)
- {
- errno = EBADF;
- return TERMKEY_RES_ERROR;
- }
-
- if (tk->buffstart)
- {
- memmove (tk->buffer, tk->buffer + tk->buffstart, tk->buffcount);
- tk->buffstart = 0;
- }
-
- /* Not expecting it ever to be greater but doesn't hurt to handle that */
- if (tk->buffcount >= tk->buffsize)
- {
- errno = ENOMEM;
- return TERMKEY_RES_ERROR;
- }
-
- ssize_t len;
-retry:
- len = read (tk->fd, tk->buffer + tk->buffcount,
- tk->buffsize - tk->buffcount);
-
- if (len == -1)
- {
- if (errno == EAGAIN)
- return TERMKEY_RES_NONE;
- if (errno == EINTR && !(tk->flags & TERMKEY_FLAG_EINTR))
- goto retry;
- return TERMKEY_RES_ERROR;
- }
- if (len < 1)
- {
- tk->is_closed = true;
- return TERMKEY_RES_NONE;
- }
- tk->buffcount += len;
- return TERMKEY_RES_AGAIN;
-}
-
-size_t
-termkey_push_bytes (termkey_t *tk, const char *bytes, size_t len)
-{
- if (tk->buffstart)
- {
- memmove (tk->buffer, tk->buffer + tk->buffstart, tk->buffcount);
- tk->buffstart = 0;
- }
-
- /* Not expecting it ever to be greater but doesn't hurt to handle that */
- if (tk->buffcount >= tk->buffsize)
- {
- errno = ENOMEM;
- return (size_t)-1;
- }
-
- if (len > tk->buffsize - tk->buffcount)
- len = tk->buffsize - tk->buffcount;
-
- // memcpy(), not strncpy() in case of null bytes in input
- memcpy (tk->buffer + tk->buffcount, bytes, len);
- tk->buffcount += len;
-
- return len;
-}
-
-termkey_sym_t
-termkey_register_keyname (termkey_t *tk, termkey_sym_t sym, const char *name)
-{
- if (!sym)
- sym = tk->nkeynames;
-
- if (sym >= tk->nkeynames)
- {
- const char **new_keynames =
- realloc (tk->keynames, sizeof new_keynames[0] * (sym + 1));
- if (!new_keynames)
- return -1;
-
- tk->keynames = new_keynames;
-
- // Fill in the hole
- for (int i = tk->nkeynames; i < sym; i++)
- tk->keynames[i] = NULL;
-
- tk->nkeynames = sym + 1;
- }
-
- tk->keynames[sym] = name;
- return sym;
-}
-
-const char *
-termkey_get_keyname (termkey_t *tk, termkey_sym_t sym)
-{
- if (sym == TERMKEY_SYM_UNKNOWN)
- return "UNKNOWN";
- if (sym < tk->nkeynames)
- return tk->keynames[sym];
- return "UNKNOWN";
-}
-
-static const char *
-termkey_lookup_keyname_format (termkey_t *tk,
- const char *str, termkey_sym_t *sym, termkey_format_t format)
-{
- /* We store an array, so we can't do better than a linear search. Doesn't
- * matter because user won't be calling this too often */
-
- for (*sym = 0; *sym < tk->nkeynames; (*sym)++)
- {
- const char *thiskey = tk->keynames[*sym];
- if (!thiskey)
- continue;
- size_t len = strlen (thiskey);
- if (format & TERMKEY_FORMAT_LOWERSPACE)
- {
- const char *thisstr = str;
- if (strpncmp_camel (&thisstr, &thiskey, len) == 0)
- return thisstr;
- }
- else if (!strncmp (str, thiskey, len))
- return (char *) str + len;
- }
- return NULL;
-}
-
-const char *
-termkey_lookup_keyname (termkey_t *tk, const char *str, termkey_sym_t *sym)
-{
- return termkey_lookup_keyname_format (tk, str, sym, 0);
-}
-
-termkey_sym_t
-termkey_keyname2sym (termkey_t *tk, const char *keyname)
-{
- termkey_sym_t sym;
- const char *endp = termkey_lookup_keyname (tk, keyname, &sym);
- if (!endp || endp[0])
- return TERMKEY_SYM_UNKNOWN;
- return sym;
-}
-
-static termkey_sym_t
-register_c0 (termkey_t *tk,
- termkey_sym_t sym, unsigned char ctrl, const char *name)
-{
- return register_c0_full (tk, sym, 0, 0, ctrl, name);
-}
-
-static termkey_sym_t
-register_c0_full (termkey_t *tk, termkey_sym_t sym,
- int modifier_set, int modifier_mask, unsigned char ctrl, const char *name)
-{
- if (ctrl >= 0x20)
- {
- errno = EINVAL;
- return -1;
- }
-
- if (name)
- sym = termkey_register_keyname (tk, sym, name);
-
- tk->c0[ctrl].sym = sym;
- tk->c0[ctrl].modifier_set = modifier_set;
- tk->c0[ctrl].modifier_mask = modifier_mask;
- return sym;
-}
-
-static struct modnames
-{
- const char *shift, *alt, *ctrl;
-}
-modnames[] =
-{
- { "S", "A", "C" }, // 0
- { "Shift", "Alt", "Ctrl" }, // LONGMOD
- { "S", "M", "C" }, // ALTISMETA
- { "Shift", "Meta", "Ctrl" }, // ALTISMETA+LONGMOD
- { "s", "a", "c" }, // LOWERMOD
- { "shift", "alt", "ctrl" }, // LOWERMOD+LONGMOD
- { "s", "m", "c" }, // LOWERMOD+ALTISMETA
- { "shift", "meta", "ctrl" }, // LOWERMOD+ALTISMETA+LONGMOD
-};
-
-size_t
-termkey_strfkey (termkey_t *tk, char *buffer, size_t len,
- termkey_key_t *key, termkey_format_t format)
-{
- size_t pos = 0;
- size_t l = 0;
-
- struct modnames *mods = &modnames[
- !!(format & TERMKEY_FORMAT_LONGMOD) +
- !!(format & TERMKEY_FORMAT_ALTISMETA) * 2 +
- !!(format & TERMKEY_FORMAT_LOWERMOD) * 4];
-
- int wrapbracket = (format & TERMKEY_FORMAT_WRAPBRACKET) &&
- (key->type != TERMKEY_TYPE_KEY || key->modifiers != 0);
-
- char sep = (format & TERMKEY_FORMAT_SPACEMOD) ? ' ' : '-';
-
- if (format & TERMKEY_FORMAT_CARETCTRL &&
- key->type == TERMKEY_TYPE_KEY &&
- key->modifiers == TERMKEY_KEYMOD_CTRL)
- {
- uint32_t codepoint = key->code.codepoint;
-
- // Handle some of the special casesfirst
- if (codepoint >= 'a' && codepoint <= 'z')
- {
- l = snprintf (buffer + pos, len - pos,
- wrapbracket ? "<^%c>" : "^%c", (char) codepoint - 0x20);
- if (l <= 0)
- return pos;
- pos += l;
- return pos;
- }
- else if ((codepoint >= '@' && codepoint < 'A') ||
- (codepoint > 'Z' && codepoint <= '_'))
- {
- l = snprintf (buffer + pos, len - pos,
- wrapbracket ? "<^%c>" : "^%c", (char) codepoint);
- if(l <= 0)
- return pos;
- pos += l;
- return pos;
- }
- }
-
- if (wrapbracket)
- {
- l = snprintf (buffer + pos, len - pos, "<");
- if (l <= 0)
- return pos;
- pos += l;
- }
-
- if (key->modifiers & TERMKEY_KEYMOD_ALT)
- {
- l = snprintf (buffer + pos, len - pos, "%s%c", mods->alt, sep);
- if (l <= 0)
- return pos;
- pos += l;
- }
- if (key->modifiers & TERMKEY_KEYMOD_CTRL)
- {
- l = snprintf (buffer + pos, len - pos, "%s%c", mods->ctrl, sep);
- if (l <= 0)
- return pos;
- pos += l;
- }
- if (key->modifiers & TERMKEY_KEYMOD_SHIFT)
- {
- l = snprintf (buffer + pos, len - pos, "%s%c", mods->shift, sep);
- if (l <= 0)
- return pos;
- pos += l;
- }
-
- switch (key->type)
- {
- case TERMKEY_TYPE_KEY:
- if (!key->multibyte[0]) // In case of user-supplied key structures
- fill_multibyte (tk, key);
- l = snprintf (buffer + pos, len - pos, "%s", key->multibyte);
- break;
- case TERMKEY_TYPE_KEYSYM:
- {
- const char *name = termkey_get_keyname (tk, key->code.sym);
- if (format & TERMKEY_FORMAT_LOWERSPACE)
- l = snprint_cameltospaces (buffer + pos, len - pos, name);
- else
- l = snprintf (buffer + pos, len - pos, "%s", name);
- break;
- }
- case TERMKEY_TYPE_FUNCTION:
- l = snprintf (buffer + pos, len - pos, "%c%d",
- (format & TERMKEY_FORMAT_LOWERSPACE ? 'f' : 'F'), key->code.number);
- break;
- case TERMKEY_TYPE_MOUSE:
- {
- termkey_mouse_event_t ev;
- int button;
- int line, col;
- termkey_interpret_mouse (tk, key, &ev, &button, &line, &col);
-
- static const char *evnames[] =
- { "Unknown", "Press", "Drag", "Release" };
- l = snprintf (buffer + pos, len - pos,
- "Mouse%s(%d)", evnames[ev], button);
- if (format & TERMKEY_FORMAT_MOUSE_POS)
- {
- if (l <= 0)
- return pos;
- pos += l;
- l = snprintf (buffer + pos, len - pos, " @ (%u,%u)", col, line);
- }
- break;
- }
- case TERMKEY_TYPE_POSITION:
- l = snprintf (buffer + pos, len - pos, "Position");
- break;
- case TERMKEY_TYPE_MODEREPORT:
- {
- int initial, mode, value;
- termkey_interpret_modereport (tk, key, &initial, &mode, &value);
- if (initial)
- l = snprintf (buffer + pos, len - pos,
- "Mode(%c%d=%d)", initial, mode, value);
- else
- l = snprintf (buffer + pos, len - pos,
- "Mode(%d=%d)", mode, value);
- break;
- }
- case TERMKEY_TYPE_UNKNOWN_CSI:
- l = snprintf (buffer + pos, len - pos,
- "CSI %c", key->code.number & 0xff);
- break;
- }
-
- if (l <= 0)
- return pos;
- pos += l;
-
- if (wrapbracket)
- {
- l = snprintf (buffer + pos, len - pos, ">");
- if (l <= 0)
- return pos;
- pos += l;
- }
- return pos;
-}
-
-const char *
-termkey_strpkey (termkey_t *tk,
- const char *str, termkey_key_t *key, termkey_format_t format)
-{
- struct modnames *mods = &modnames[
- !!(format & TERMKEY_FORMAT_LONGMOD) +
- !!(format & TERMKEY_FORMAT_ALTISMETA) * 2 +
- !!(format & TERMKEY_FORMAT_LOWERMOD) * 4];
-
- key->modifiers = 0;
-
- if ((format & TERMKEY_FORMAT_CARETCTRL) && str[0] == '^' && str[1])
- {
- str = termkey_strpkey (tk,
- str + 1, key, format & ~TERMKEY_FORMAT_CARETCTRL);
-
- if (!str
- || key->type != TERMKEY_TYPE_KEY
- || key->code.codepoint < '@'
- || key->code.codepoint > '_'
- || key->modifiers != 0)
- return NULL;
-
- if (key->code.codepoint >= 'A'
- && key->code.codepoint <= 'Z')
- key->code.codepoint += 0x20;
- key->modifiers = TERMKEY_KEYMOD_CTRL;
- fill_multibyte (tk, key);
- return (char *) str;
- }
-
- const char *sep_at;
- while ((sep_at = strchr (str,
- (format & TERMKEY_FORMAT_SPACEMOD) ? ' ' : '-')))
- {
- size_t n = sep_at - str;
- if (n == strlen (mods->alt) && !strncmp (mods->alt, str, n))
- key->modifiers |= TERMKEY_KEYMOD_ALT;
- else if (n == strlen (mods->ctrl) && !strncmp (mods->ctrl, str, n))
- key->modifiers |= TERMKEY_KEYMOD_CTRL;
- else if (n == strlen (mods->shift) && !strncmp (mods->shift, str, n))
- key->modifiers |= TERMKEY_KEYMOD_SHIFT;
- else
- break;
-
- str = sep_at + 1;
- }
-
- size_t nbytes;
- ssize_t snbytes;
- const char *endstr;
-
- if ((endstr = termkey_lookup_keyname_format
- (tk, str, &key->code.sym, format)))
- {
- key->type = TERMKEY_TYPE_KEYSYM;
- str = endstr;
- }
- else if (sscanf(str, "F%d%zn", &key->code.number, &snbytes) == 1)
- {
- key->type = TERMKEY_TYPE_FUNCTION;
- str += snbytes;
- }
- // Multibyte must be last
- else if (parse_multibyte (tk, (unsigned const char *) str, strlen (str),
- &key->code.codepoint, &nbytes) == TERMKEY_RES_KEY)
- {
- key->type = TERMKEY_TYPE_KEY;
- fill_multibyte (tk, key);
- str += nbytes;
- }
- // TODO: Consider mouse events?
- else
- return NULL;
-
- termkey_canonicalise (tk, key);
- return (char *) str;
-}
-
-int
-termkey_keycmp (termkey_t *tk,
- const termkey_key_t *key1p, const termkey_key_t *key2p)
-{
- /* Copy the key structs since we'll be modifying them */
- termkey_key_t key1 = *key1p, key2 = *key2p;
-
- termkey_canonicalise (tk, &key1);
- termkey_canonicalise (tk, &key2);
-
- if (key1.type != key2.type)
- return key1.type - key2.type;
-
- switch (key1.type)
- {
- case TERMKEY_TYPE_KEY:
- if (key1.code.codepoint != key2.code.codepoint)
- return key1.code.codepoint - key2.code.codepoint;
- break;
- case TERMKEY_TYPE_KEYSYM:
- if (key1.code.sym != key2.code.sym)
- return key1.code.sym - key2.code.sym;
- break;
- case TERMKEY_TYPE_FUNCTION:
- case TERMKEY_TYPE_UNKNOWN_CSI:
- if (key1.code.number != key2.code.number)
- return key1.code.number - key2.code.number;
- break;
- case TERMKEY_TYPE_MOUSE:
- {
- int cmp = memcmp (&key1.code.mouse, &key2.code.mouse,
- sizeof key1.code.mouse);
- if (cmp != 0)
- return cmp;
- break;
- }
- case TERMKEY_TYPE_POSITION:
- {
- int line1, col1, line2, col2;
- termkey_interpret_position (tk, &key1, &line1, &col1);
- termkey_interpret_position (tk, &key2, &line2, &col2);
- if (line1 != line2)
- return line1 - line2;
- return col1 - col2;
- }
- case TERMKEY_TYPE_MODEREPORT:
- {
- int initial1, initial2, mode1, mode2, value1, value2;
- termkey_interpret_modereport (tk, &key1, &initial1, &mode1, &value1);
- termkey_interpret_modereport (tk, &key2, &initial2, &mode2, &value2);
- if (initial1 != initial2)
- return initial1 - initial2;
- if (mode1 != mode2)
- return mode1 - mode2;
- return value1 - value2;
- }
- }
- return key1.modifiers - key2.modifiers;
-}
-
diff --git a/termkey2.h b/termkey2.h
deleted file mode 100644
index 0fa0635..0000000
--- a/termkey2.h
+++ /dev/null
@@ -1,277 +0,0 @@
-#ifndef TERMKEY2_H
-#define TERMKEY2_H
-
-#include
-#include
-#include
-
-#include "termkey2-config.h"
-
-#define TERMKEY_CHECK_VERSION \
- termkey_check_version (TERMKEY_VERSION_MAJOR, TERMKEY_VERSION_MINOR)
-
-typedef enum termkey_sym termkey_sym_t;
-enum termkey_sym
-{
- 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,
-
- TERMKEY_N_SYMS
-};
-
-typedef enum termkey_type termkey_type_t;
-enum termkey_type
-{
- TERMKEY_TYPE_KEY,
- TERMKEY_TYPE_FUNCTION,
- TERMKEY_TYPE_KEYSYM,
- TERMKEY_TYPE_MOUSE,
- TERMKEY_TYPE_POSITION,
- TERMKEY_TYPE_MODEREPORT,
- /* add other recognised types here */
-
- TERMKEY_TYPE_UNKNOWN_CSI = -1
-};
-
-typedef enum termkey_result termkey_result_t;
-enum termkey_result
-{
- TERMKEY_RES_NONE,
- TERMKEY_RES_KEY,
- TERMKEY_RES_EOF,
- TERMKEY_RES_AGAIN,
- TERMKEY_RES_ERROR
-};
-
-typedef enum termkey_mouse_event termkey_mouse_event_t;
-enum termkey_mouse_event
-{
- TERMKEY_MOUSE_UNKNOWN,
- TERMKEY_MOUSE_PRESS,
- TERMKEY_MOUSE_DRAG,
- TERMKEY_MOUSE_RELEASE
-};
-
-enum
-{
- TERMKEY_KEYMOD_SHIFT = 1 << 0,
- TERMKEY_KEYMOD_ALT = 1 << 1,
- TERMKEY_KEYMOD_CTRL = 1 << 2
-};
-
-typedef struct termkey_key termkey_key_t;
-struct termkey_key
-{
- termkey_type_t type;
- union
- {
- uint32_t codepoint; /* TERMKEY_TYPE_KEY */
- int number; /* TERMKEY_TYPE_FUNCTION */
- termkey_sym_t sym; /* TERMKEY_TYPE_KEYSYM */
-
- /* TERMKEY_TYPE_MODEREPORT */
- /* opaque, see termkey_interpret_modereport() */
- struct { char initial; int mode, value; } mode;
-
- /* TERMKEY_TYPE_MOUSE */
- /* opaque, see termkey_interpret_mouse() */
- struct { uint16_t x, y, info; } mouse;
- } code;
-
- int modifiers;
-
- /* The raw multibyte sequence for the key */
- char multibyte[MB_LEN_MAX + 1];
-};
-
-typedef struct termkey termkey_t;
-
-enum
-{
- /* Do not interpret C0//DEL codes if possible */
- TERMKEY_FLAG_NOINTERPRET = 1 << 0,
- /* Convert KP codes to regular keypresses */
- TERMKEY_FLAG_CONVERTKP = 1 << 1,
- /* Don't try to decode the input characters */
- TERMKEY_FLAG_RAW = 1 << 2,
- /* Do not make initial termios calls on construction */
- TERMKEY_FLAG_NOTERMIOS = 1 << 4,
- /* Sets TERMKEY_CANON_SPACESYMBOL */
- TERMKEY_FLAG_SPACESYMBOL = 1 << 5,
- /* Allow Ctrl-C to be read as normal, disabling SIGINT */
- TERMKEY_FLAG_CTRLC = 1 << 6,
- /* Return ERROR on signal (EINTR) rather than retry */
- TERMKEY_FLAG_EINTR = 1 << 7
-};
-
-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_t *termkey_new (int fd, const char *encoding, int flags);
-termkey_t *termkey_new_abstract (const char *term,
- const char *encoding, int flags);
-void termkey_free (termkey_t *tk);
-void termkey_destroy (termkey_t *tk);
-
-int termkey_start (termkey_t *tk);
-int termkey_stop (termkey_t *tk);
-int termkey_is_started (termkey_t *tk);
-
-int termkey_get_fd (termkey_t *tk);
-
-int termkey_get_flags (termkey_t *tk);
-void termkey_set_flags (termkey_t *tk, int newflags);
-
-int termkey_get_waittime (termkey_t *tk);
-void termkey_set_waittime (termkey_t *tk, int msec);
-
-int termkey_get_canonflags (termkey_t *tk);
-void termkey_set_canonflags (termkey_t *tk, int flags);
-
-size_t termkey_get_buffer_size (termkey_t *tk);
-int termkey_set_buffer_size (termkey_t *tk, size_t size);
-
-size_t termkey_get_buffer_remaining (termkey_t *tk);
-
-void termkey_canonicalise (termkey_t *tk, termkey_key_t *key);
-
-termkey_result_t termkey_getkey (termkey_t *tk, termkey_key_t *key);
-termkey_result_t termkey_getkey_force (termkey_t *tk, termkey_key_t *key);
-termkey_result_t termkey_waitkey (termkey_t *tk, termkey_key_t *key);
-
-termkey_result_t termkey_advisereadable (termkey_t *tk);
-
-size_t termkey_push_bytes (termkey_t *tk, const char *bytes, size_t len);
-
-termkey_sym_t termkey_register_keyname (termkey_t *tk,
- termkey_sym_t sym, const char *name);
-const char *termkey_get_keyname (termkey_t *tk, termkey_sym_t sym);
-const char *termkey_lookup_keyname (termkey_t *tk,
- const char *str, termkey_sym_t *sym);
-
-termkey_sym_t termkey_keyname2sym (termkey_t *tk, const char *keyname);
-
-termkey_result_t termkey_interpret_mouse (termkey_t *tk,
- const termkey_key_t *key, termkey_mouse_event_t *event,
- int *button, int *line, int *col);
-termkey_result_t termkey_interpret_position (termkey_t *tk,
- const termkey_key_t *key, int *line, int *col);
-termkey_result_t termkey_interpret_modereport (termkey_t *tk,
- const termkey_key_t *key, int *initial, int *mode, int *value);
-termkey_result_t termkey_interpret_csi (termkey_t *tk,
- const termkey_key_t *key, long args[], size_t *nargs, unsigned long *cmd);
-
-typedef enum termkey_format termkey_format_t;
-enum termkey_format
-{
- /* Shift-... instead of S-... */
- TERMKEY_FORMAT_LONGMOD = 1 << 0,
- /* ^X instead of C-X */
- TERMKEY_FORMAT_CARETCTRL = 1 << 1,
- /* Meta- or M- instead of Alt- or A- */
- TERMKEY_FORMAT_ALTISMETA = 1 << 2,
- /* Wrap special keys in brackets like */
- TERMKEY_FORMAT_WRAPBRACKET = 1 << 3,
- /* M Foo instead of M-Foo */
- TERMKEY_FORMAT_SPACEMOD = 1 << 4,
- /* meta or m instead of Meta or M */
- TERMKEY_FORMAT_LOWERMOD = 1 << 5,
- /* page down instead of PageDown */
- TERMKEY_FORMAT_LOWERSPACE = 1 << 6,
- /* Include mouse position if relevant; @ col,line */
- TERMKEY_FORMAT_MOUSE_POS = 1 << 8
-};
-
-/* Some useful combinations */
-
-#define TERMKEY_FORMAT_VIM (termkey_format_t) \
- (TERMKEY_FORMAT_ALTISMETA | TERMKEY_FORMAT_WRAPBRACKET)
-#define TERMKEY_FORMAT_URWID (termkey_format_t) \
- (TERMKEY_FORMAT_LONGMOD | TERMKEY_FORMAT_ALTISMETA | \
- TERMKEY_FORMAT_LOWERMOD | TERMKEY_FORMAT_SPACEMOD | \
- TERMKEY_FORMAT_LOWERSPACE)
-
-size_t termkey_strfkey (termkey_t *tk, char *buffer, size_t len,
- termkey_key_t *key, termkey_format_t format);
-const char *termkey_strpkey (termkey_t *tk, const char *str,
- termkey_key_t *key, termkey_format_t format);
-
-int termkey_keycmp (termkey_t *tk,
- const termkey_key_t *key1, const termkey_key_t *key2);
-
-#endif // ! TERMKEY2_H
-
diff --git a/termo-config.h.in b/termo-config.h.in
new file mode 100644
index 0000000..780927a
--- /dev/null
+++ b/termo-config.h.in
@@ -0,0 +1,8 @@
+#ifndef TERMO_CONFIG_H
+#define TERMO_CONFIG_H
+
+#define TERMO_VERSION_MAJOR @project_VERSION_MAJOR@
+#define TERMO_VERSION_MINOR @project_VERSION_MINOR@
+
+#endif // ! TERMO_CONFIG_H
+
diff --git a/termo-internal.h b/termo-internal.h
new file mode 100644
index 0000000..b9a27c2
--- /dev/null
+++ b/termo-internal.h
@@ -0,0 +1,112 @@
+#ifndef TERMO_INTERNAL_H
+#define TERMO_INTERNAL_H
+
+#include "termo.h"
+
+#include
+#include
+#include
+#include
+
+typedef struct termo_driver termo_driver_t;
+struct termo_driver
+{
+ const char *name;
+ void *(*new_driver) (termo_t *tk, const char *term);
+ void (*free_driver) (void *info);
+ int (*start_driver) (termo_t *tk, void *info);
+ int (*stop_driver) (termo_t *tk, void *info);
+ termo_result_t (*peekkey) (termo_t *tk,
+ void *info, termo_key_t *key, int force, size_t *nbytes);
+};
+
+typedef struct keyinfo keyinfo_t;
+struct keyinfo
+{
+ termo_type_t type;
+ termo_sym_t sym;
+ int modifier_mask;
+ int modifier_set;
+};
+
+typedef struct termo_driver_node termo_driver_node_t;
+struct termo_driver_node
+{
+ termo_driver_t *driver;
+ void *info;
+ termo_driver_node_t *next;
+};
+
+struct termo
+{
+ int fd;
+ int flags;
+ int canonflags;
+
+ unsigned char *buffer;
+ size_t buffstart; // First offset in buffer
+ size_t buffcount; // Number of entires valid in buffer
+ size_t buffsize; // Total malloc'ed size
+
+ // Position beyond buffstart at which peekkey() should next start.
+ // Normally 0, but see also termo_interpret_csi().
+ size_t hightide;
+
+ struct termios restore_termios;
+ bool restore_termios_valid;
+
+ int waittime; // In milliseconds
+
+ bool is_closed; // We've received EOF
+ bool is_started;
+
+ int nkeynames;
+ const char **keynames;
+
+ keyinfo_t c0[32]; // There are 32 C0 codes
+ iconv_t to_utf32_conv;
+ iconv_t from_utf32_conv;
+ termo_driver_node_t *drivers;
+
+ // Now some "protected" methods for the driver to call but which we don't
+ // want exported as real symbols in the library
+ struct
+ {
+ void (*emit_codepoint) (termo_t *tk,
+ uint32_t codepoint, termo_key_t *key);
+ termo_result_t (*peekkey_simple) (termo_t *tk,
+ termo_key_t *key, int force, size_t *nbytes);
+ termo_result_t (*peekkey_mouse) (termo_t *tk,
+ termo_key_t *key, size_t *nbytes);
+ }
+ method;
+};
+
+static inline void
+termo_key_get_linecol (const termo_key_t *key, int *line, int *col)
+{
+ if (col)
+ *col = key->code.mouse.x;
+
+ if (line)
+ *line = key->code.mouse.y;
+}
+
+static inline void
+termo_key_set_linecol (termo_key_t *key, int line, int col)
+{
+ if (line > UINT16_MAX)
+ line = UINT16_MAX;
+
+ if (col > UINT16_MAX)
+ col = UINT16_MAX;
+
+ key->code.mouse.x = col;
+ key->code.mouse.y = line;
+}
+
+extern termo_driver_t termo_driver_csi;
+extern termo_driver_t termo_driver_ti;
+
+#endif // ! TERMO_INTERNAL_H
+
diff --git a/termo.c b/termo.c
new file mode 100644
index 0000000..9f23158
--- /dev/null
+++ b/termo.c
@@ -0,0 +1,1656 @@
+#include "termo.h"
+#include "termo-internal.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+void
+termo_check_version (int major, int minor)
+{
+ if (major != TERMO_VERSION_MAJOR)
+ fprintf (stderr, "libtermo major version mismatch;"
+ " %d (wants) != %d (library)\n",
+ major, TERMO_VERSION_MAJOR);
+ else if (minor > TERMO_VERSION_MINOR)
+ fprintf (stderr, "libtermo minor version mismatch;"
+ " %d (wants) > %d (library)\n",
+ minor, TERMO_VERSION_MINOR);
+ else
+ return;
+ exit (1);
+}
+
+static termo_driver_t *drivers[] =
+{
+ &termo_driver_ti,
+ &termo_driver_csi,
+ NULL,
+};
+
+// Forwards for the "protected" methods
+static void emit_codepoint (termo_t *tk, uint32_t codepoint, termo_key_t *key);
+static termo_result_t peekkey_simple (termo_t *tk,
+ termo_key_t *key, int force, size_t *nbytes);
+static termo_result_t peekkey_mouse (termo_t *tk,
+ termo_key_t *key, size_t *nbytes);
+
+static termo_sym_t register_c0 (termo_t *tk, termo_sym_t sym,
+ unsigned char ctrl, const char *name);
+static termo_sym_t register_c0_full (termo_t *tk, termo_sym_t sym,
+ int modifier_set, int modifier_mask, unsigned char ctrl, const char *name);
+
+static struct
+{
+ termo_sym_t sym;
+ const char *name;
+}
+keynames[] =
+{
+ { TERMO_SYM_NONE, "NONE" },
+ { TERMO_SYM_BACKSPACE, "Backspace" },
+ { TERMO_SYM_TAB, "Tab" },
+ { TERMO_SYM_ENTER, "Enter" },
+ { TERMO_SYM_ESCAPE, "Escape" },
+ { TERMO_SYM_SPACE, "Space" },
+ { TERMO_SYM_DEL, "DEL" },
+ { TERMO_SYM_UP, "Up" },
+ { TERMO_SYM_DOWN, "Down" },
+ { TERMO_SYM_LEFT, "Left" },
+ { TERMO_SYM_RIGHT, "Right" },
+ { TERMO_SYM_BEGIN, "Begin" },
+ { TERMO_SYM_FIND, "Find" },
+ { TERMO_SYM_INSERT, "Insert" },
+ { TERMO_SYM_DELETE, "Delete" },
+ { TERMO_SYM_SELECT, "Select" },
+ { TERMO_SYM_PAGEUP, "PageUp" },
+ { TERMO_SYM_PAGEDOWN, "PageDown" },
+ { TERMO_SYM_HOME, "Home" },
+ { TERMO_SYM_END, "End" },
+ { TERMO_SYM_CANCEL, "Cancel" },
+ { TERMO_SYM_CLEAR, "Clear" },
+ { TERMO_SYM_CLOSE, "Close" },
+ { TERMO_SYM_COMMAND, "Command" },
+ { TERMO_SYM_COPY, "Copy" },
+ { TERMO_SYM_EXIT, "Exit" },
+ { TERMO_SYM_HELP, "Help" },
+ { TERMO_SYM_MARK, "Mark" },
+ { TERMO_SYM_MESSAGE, "Message" },
+ { TERMO_SYM_MOVE, "Move" },
+ { TERMO_SYM_OPEN, "Open" },
+ { TERMO_SYM_OPTIONS, "Options" },
+ { TERMO_SYM_PRINT, "Print" },
+ { TERMO_SYM_REDO, "Redo" },
+ { TERMO_SYM_REFERENCE, "Reference" },
+ { TERMO_SYM_REFRESH, "Refresh" },
+ { TERMO_SYM_REPLACE, "Replace" },
+ { TERMO_SYM_RESTART, "Restart" },
+ { TERMO_SYM_RESUME, "Resume" },
+ { TERMO_SYM_SAVE, "Save" },
+ { TERMO_SYM_SUSPEND, "Suspend" },
+ { TERMO_SYM_UNDO, "Undo" },
+ { TERMO_SYM_KP0, "KP0" },
+ { TERMO_SYM_KP1, "KP1" },
+ { TERMO_SYM_KP2, "KP2" },
+ { TERMO_SYM_KP3, "KP3" },
+ { TERMO_SYM_KP4, "KP4" },
+ { TERMO_SYM_KP5, "KP5" },
+ { TERMO_SYM_KP6, "KP6" },
+ { TERMO_SYM_KP7, "KP7" },
+ { TERMO_SYM_KP8, "KP8" },
+ { TERMO_SYM_KP9, "KP9" },
+ { TERMO_SYM_KPENTER, "KPEnter" },
+ { TERMO_SYM_KPPLUS, "KPPlus" },
+ { TERMO_SYM_KPMINUS, "KPMinus" },
+ { TERMO_SYM_KPMULT, "KPMult" },
+ { TERMO_SYM_KPDIV, "KPDiv" },
+ { TERMO_SYM_KPCOMMA, "KPComma" },
+ { TERMO_SYM_KPPERIOD, "KPPeriod" },
+ { TERMO_SYM_KPEQUALS, "KPEquals" },
+ { 0, NULL },
+};
+
+#define CHARAT(i) (tk->buffer[tk->buffstart + (i)])
+
+#ifdef DEBUG
+/* Some internal deubgging functions */
+
+static void
+print_buffer (termo_t *tk)
+{
+ size_t 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 (termo_t *tk, termo_key_t *key)
+{
+ switch (key->type)
+ {
+ case TERMO_TYPE_KEY:
+ fprintf (stderr, "Unicode codepoint=U+%04lx multibyte='%s'",
+ (long) key->code.codepoint, key->multibyte);
+ break;
+ case TERMO_TYPE_FUNCTION:
+ fprintf (stderr, "Function F%d", key->code.number);
+ break;
+ case TERMO_TYPE_KEYSYM:
+ fprintf (stderr, "Keysym sym=%d(%s)",
+ key->code.sym, termo_get_keyname (tk, key->code.sym));
+ break;
+ case TERMO_TYPE_MOUSE:
+ {
+ termo_mouse_event_t ev;
+ int button, line, col;
+ termo_interpret_mouse (tk, key, &ev, &button, &line, &col);
+ fprintf (stderr, "Mouse ev=%d button=%d pos=(%d,%d)\n",
+ ev, button, line, col);
+ break;
+ }
+ case TERMO_TYPE_POSITION:
+ {
+ int line, col;
+ termo_interpret_position (tk, key, &line, &col);
+ fprintf (stderr, "Position report pos=(%d,%d)\n", line, col);
+ break;
+ }
+ case TERMO_TYPE_MODEREPORT:
+ {
+ int initial, mode, value;
+ termo_interpret_modereport (tk, key, &initial, &mode, &value);
+ fprintf (stderr, "Mode report mode=%s %d val=%d\n",
+ initial == '?' ? "DEC" : "ANSI", mode, value);
+ break;
+ }
+ case TERMO_TYPE_UNKNOWN_CSI:
+ fprintf (stderr, "unknown CSI\n");
+ }
+
+ int m = key->modifiers;
+ fprintf (stderr, " mod=%s%s%s+%02x",
+ (m & TERMO_KEYMOD_CTRL ? "C" : ""),
+ (m & TERMO_KEYMOD_ALT ? "A" : ""),
+ (m & TERMO_KEYMOD_SHIFT ? "S" : ""),
+ m & ~(TERMO_KEYMOD_CTRL | TERMO_KEYMOD_ALT | TERMO_KEYMOD_SHIFT));
+}
+
+static const char *
+res2str (termo_result_t res)
+{
+ static char errorbuffer[256];
+
+ switch (res)
+ {
+ case TERMO_RES_KEY:
+ return "TERMO_RES_KEY";
+ case TERMO_RES_EOF:
+ return "TERMO_RES_EOF";
+ case TERMO_RES_AGAIN:
+ return "TERMO_RES_AGAIN";
+ case TERMO_RES_NONE:
+ return "TERMO_RES_NONE";
+ case TERMO_RES_ERROR:
+ snprintf (errorbuffer, sizeof errorbuffer,
+ "TERMO_RES_ERROR(errno=%d)\n", errno);
+ return (const char*) errorbuffer;
+ }
+
+ return "unknown";
+}
+#endif
+
+/* Similar to snprintf(str, size, "%s", src) except it turns CamelCase into
+ * space separated values
+ */
+static int
+snprint_cameltospaces (char *str, size_t size, const char *src)
+{
+ int prev_lower = 0;
+ size_t l = 0;
+ while (*src && l < size - 1)
+ {
+ if (isupper (*src) && prev_lower)
+ {
+ if (str)
+ str[l++] = ' ';
+ if (l >= size - 1)
+ break;
+ }
+ prev_lower = islower (*src);
+ str[l++] = tolower (*src++);
+ }
+ str[l] = 0;
+
+ /* For consistency with snprintf, return the number of bytes that would have
+ * been written, excluding '\0' */
+ for (; *src; src++)
+ {
+ if (isupper (*src) && prev_lower)
+ l++;
+ prev_lower = islower (*src);
+ l++;
+ }
+ return l;
+}
+
+/* Similar to strcmp(str, strcamel, n) except that:
+ * it compares CamelCase in strcamel with space separated values in str;
+ * it takes char**s and updates them
+ * n counts bytes of strcamel, not str
+ */
+static int
+strpncmp_camel (const char **strp, const char **strcamelp, size_t n)
+{
+ const char *str = *strp, *strcamel = *strcamelp;
+ int prev_lower = 0;
+
+ for (; (*str || *strcamel) && n; n--)
+ {
+ char b = tolower (*strcamel);
+ if (isupper (*strcamel) && prev_lower)
+ {
+ if (*str != ' ')
+ break;
+ str++;
+ if (*str != b)
+ break;
+ }
+ else if (*str != b)
+ break;
+
+ prev_lower = islower (*strcamel);
+
+ str++;
+ strcamel++;
+ }
+
+ *strp = str;
+ *strcamelp = strcamel;
+ return *str - *strcamel;
+}
+
+static termo_t *
+termo_alloc (void)
+{
+ termo_t *tk = malloc (sizeof *tk);
+ if (!tk)
+ return NULL;
+
+ /* Default all the object fields but don't allocate anything */
+
+ tk->fd = -1;
+ tk->flags = 0;
+ tk->canonflags = 0;
+
+ tk->buffer = NULL;
+ tk->buffstart = 0;
+ tk->buffcount = 0;
+ tk->buffsize = 256; /* bytes */
+ tk->hightide = 0;
+
+ tk->restore_termios_valid = false;
+
+ tk->waittime = 50; /* msec */
+
+ tk->is_closed = false;
+ tk->is_started = false;
+
+ tk->nkeynames = 64;
+ tk->keynames = NULL;
+
+ for (int i = 0; i < 32; i++)
+ tk->c0[i].sym = TERMO_SYM_NONE;
+
+ tk->drivers = NULL;
+
+ tk->method.emit_codepoint = &emit_codepoint;
+ tk->method.peekkey_simple = &peekkey_simple;
+ tk->method.peekkey_mouse = &peekkey_mouse;
+ return tk;
+}
+
+static int
+termo_init (termo_t *tk, const char *term, const char *encoding)
+{
+ if (!encoding)
+ encoding = nl_langinfo (CODESET);
+
+ static const uint16_t endianity = 0x0102;
+ const char *utf32 = (*(uint8_t *) &endianity == 0x01)
+ ? "UTF-32BE" : "UTF-32LE";
+
+ if ((tk->to_utf32_conv = iconv_open (utf32, encoding)) == (iconv_t) -1)
+ return 0;
+ if ((tk->from_utf32_conv = iconv_open (encoding, utf32)) == (iconv_t) -1)
+ goto abort_free_to_utf32;
+
+ tk->buffer = malloc (tk->buffsize);
+ if (!tk->buffer)
+ goto abort_free_from_utf32;
+
+ tk->keynames = malloc (sizeof tk->keynames[0] * tk->nkeynames);
+ if (!tk->keynames)
+ goto abort_free_buffer;
+
+ int i;
+ for (i = 0; i < tk->nkeynames; i++)
+ tk->keynames[i] = NULL;
+ for (i = 0; keynames[i].name; i++)
+ if (termo_register_keyname (tk,
+ keynames[i].sym, keynames[i].name) == -1)
+ goto abort_free_keynames;
+
+ register_c0 (tk, TERMO_SYM_BACKSPACE, 0x08, NULL);
+ register_c0 (tk, TERMO_SYM_TAB, 0x09, NULL);
+ register_c0 (tk, TERMO_SYM_ENTER, 0x0d, NULL);
+ register_c0 (tk, TERMO_SYM_ESCAPE, 0x1b, NULL);
+
+ termo_driver_node_t **tail = &tk->drivers;
+ for (i = 0; drivers[i]; i++)
+ {
+ void *info = (*drivers[i]->new_driver) (tk, term);
+ if (!info)
+ continue;
+
+#ifdef DEBUG
+ fprintf (stderr, "Loading the %s driver...\n", drivers[i]->name);
+#endif
+
+ termo_driver_node_t *thisdrv = malloc (sizeof *thisdrv);
+ if (!thisdrv)
+ goto abort_free_drivers;
+
+ thisdrv->driver = drivers[i];
+ thisdrv->info = info;
+ thisdrv->next = NULL;
+
+ *tail = thisdrv;
+ tail = &thisdrv->next;
+
+#ifdef DEBUG
+ fprintf (stderr, "Loaded %s driver\n", drivers[i]->name);
+#endif
+ }
+
+ if (!tk->drivers)
+ {
+ errno = ENOENT;
+ goto abort_free_keynames;
+ }
+ return 1;
+
+abort_free_drivers:
+ for (termo_driver_node_t *p = tk->drivers; p; )
+ {
+ (*p->driver->free_driver) (p->info);
+ termo_driver_node_t *next = p->next;
+ free (p);
+ p = next;
+ }
+
+abort_free_keynames:
+ free (tk->keynames);
+abort_free_buffer:
+ free (tk->buffer);
+abort_free_from_utf32:
+ iconv_close (tk->from_utf32_conv);
+abort_free_to_utf32:
+ iconv_close (tk->to_utf32_conv);
+ return 0;
+}
+
+termo_t *
+termo_new (int fd, const char *encoding, int flags)
+{
+ termo_t *tk = termo_alloc ();
+ if (!tk)
+ return NULL;
+
+ tk->fd = fd;
+ termo_set_flags (tk, flags);
+
+ const char *term = getenv ("TERM");
+ if (termo_init (tk, term, encoding)
+ && termo_start (tk))
+ return tk;
+
+ free (tk);
+ return NULL;
+}
+
+termo_t *
+termo_new_abstract (const char *term, const char *encoding, int flags)
+{
+ termo_t *tk = termo_alloc ();
+ if (!tk)
+ return NULL;
+
+ tk->fd = -1;
+ termo_set_flags (tk, flags);
+
+ if (!termo_init (tk, term, encoding))
+ {
+ free (tk);
+ return NULL;
+ }
+
+ termo_start (tk);
+ return tk;
+}
+
+void
+termo_free (termo_t *tk)
+{
+ free (tk->buffer); tk->buffer = NULL;
+ free (tk->keynames); tk->keynames = NULL;
+
+ iconv_close (tk->to_utf32_conv);
+ tk->to_utf32_conv = (iconv_t) -1;
+ iconv_close (tk->from_utf32_conv);
+ tk->from_utf32_conv = (iconv_t) -1;
+
+ termo_driver_node_t *p, *next;
+ for (p = tk->drivers; p; p = next)
+ {
+ (*p->driver->free_driver) (p->info);
+ next = p->next;
+ free (p);
+ }
+ free (tk);
+}
+
+void
+termo_destroy (termo_t *tk)
+{
+ if (tk->is_started)
+ termo_stop (tk);
+
+ termo_free (tk);
+}
+
+int
+termo_start (termo_t *tk)
+{
+ if (tk->is_started)
+ return 1;
+
+ if (tk->fd != -1 && !(tk->flags & TERMO_FLAG_NOTERMIOS))
+ {
+ struct termios termios;
+ if (tcgetattr (tk->fd, &termios) == 0)
+ {
+ tk->restore_termios = termios;
+ tk->restore_termios_valid = true;
+
+ termios.c_iflag &= ~(IXON|INLCR|ICRNL);
+ termios.c_lflag &= ~(ICANON|ECHO);
+ termios.c_cc[VMIN] = 1;
+ termios.c_cc[VTIME] = 0;
+
+ if (tk->flags & TERMO_FLAG_CTRLC)
+ /* want no signal keys at all, so just disable ISIG */
+ termios.c_lflag &= ~ISIG;
+ else
+ {
+ /* Disable ^\ == VQUIT and ^D == VSUSP but leave ^C as SIGINT */
+ termios.c_cc[VQUIT] = _POSIX_VDISABLE;
+ termios.c_cc[VSUSP] = _POSIX_VDISABLE;
+ /* Some OSes have ^Y == VDSUSP */
+#ifdef VDSUSP
+ termios.c_cc[VDSUSP] = _POSIX_VDISABLE;
+#endif
+ }
+
+#ifdef DEBUG
+ fprintf (stderr, "Setting termios(3) flags\n");
+#endif
+ tcsetattr (tk->fd, TCSANOW, &termios);
+ }
+ }
+
+ termo_driver_node_t *p;
+ for (p = tk->drivers; p; p = p->next)
+ if (p->driver->start_driver)
+ if (!(*p->driver->start_driver) (tk, p->info))
+ return 0;
+
+#ifdef DEBUG
+ fprintf (stderr, "Drivers started; termo instance %p is ready\n", tk);
+#endif
+
+ tk->is_started = 1;
+ return 1;
+}
+
+int
+termo_stop (termo_t *tk)
+{
+ if (!tk->is_started)
+ return 1;
+
+ struct termo_driver_node *p;
+ for (p = tk->drivers; p; p = p->next)
+ if (p->driver->stop_driver)
+ (*p->driver->stop_driver) (tk, p->info);
+
+ if (tk->restore_termios_valid)
+ tcsetattr (tk->fd, TCSANOW, &tk->restore_termios);
+
+ tk->is_started = false;
+ return 1;
+}
+
+int
+termo_is_started (termo_t *tk)
+{
+ return tk->is_started;
+}
+
+int
+termo_get_fd (termo_t *tk)
+{
+ return tk->fd;
+}
+
+int
+termo_get_flags (termo_t *tk)
+{
+ return tk->flags;
+}
+
+void
+termo_set_flags (termo_t *tk, int newflags)
+{
+ tk->flags = newflags;
+ if (tk->flags & TERMO_FLAG_SPACESYMBOL)
+ tk->canonflags |= TERMO_CANON_SPACESYMBOL;
+ else
+ tk->canonflags &= ~TERMO_CANON_SPACESYMBOL;
+}
+
+void
+termo_set_waittime (termo_t *tk, int msec)
+{
+ tk->waittime = msec;
+}
+
+int
+termo_get_waittime (termo_t *tk)
+{
+ return tk->waittime;
+}
+
+int
+termo_get_canonflags (termo_t *tk)
+{
+ return tk->canonflags;
+}
+
+void
+termo_set_canonflags (termo_t *tk, int flags)
+{
+ tk->canonflags = flags;
+ if (tk->canonflags & TERMO_CANON_SPACESYMBOL)
+ tk->flags |= TERMO_FLAG_SPACESYMBOL;
+ else
+ tk->flags &= ~TERMO_FLAG_SPACESYMBOL;
+}
+
+size_t
+termo_get_buffer_size (termo_t *tk)
+{
+ return tk->buffsize;
+}
+
+int
+termo_set_buffer_size (termo_t *tk, size_t size)
+{
+ unsigned char *buffer = realloc (tk->buffer, size);
+ if (!buffer)
+ return 0;
+
+ tk->buffer = buffer;
+ tk->buffsize = size;
+ return 1;
+}
+
+size_t
+termo_get_buffer_remaining (termo_t *tk)
+{
+ /* Return the total number of free bytes in the buffer,
+ * because that's what is available to the user. */
+ return tk->buffsize - tk->buffcount;
+}
+
+static void
+eat_bytes (termo_t *tk, size_t count)
+{
+ if (count >= tk->buffcount)
+ {
+ tk->buffstart = 0;
+ tk->buffcount = 0;
+ return;
+ }
+
+ tk->buffstart += count;
+ tk->buffcount -= count;
+}
+
+#define MULTIBYTE_INVALID '?'
+
+static void
+fill_multibyte (termo_t *tk, termo_key_t *key)
+{
+ size_t codepoint_len = sizeof key->code.codepoint;
+ char *codepoint_ptr = (char *) &key->code.codepoint;
+ size_t multibyte_len = sizeof key->multibyte;
+ char *multibyte_ptr = (char *) key->multibyte;
+
+ size_t result = iconv (tk->from_utf32_conv,
+ &codepoint_ptr, &codepoint_len, &multibyte_ptr, &multibyte_len);
+ size_t output = sizeof key->multibyte - multibyte_len;
+
+ // Something broke
+ if (result == (size_t) -1 || output == 0)
+ {
+ key->multibyte[0] = MULTIBYTE_INVALID;
+ key->multibyte[1] = 0;
+ return;
+ }
+
+ // Append a null character, as it wasn't port of the input
+ key->multibyte[output] = 0;
+}
+
+static termo_result_t
+parse_multibyte (termo_t *tk, const unsigned char *bytes, size_t len,
+ uint32_t *cp, size_t *nbytep)
+{
+ size_t multibyte_len = len;
+ char *multibyte_ptr = (char *) bytes;
+ size_t codepoint_len = sizeof *cp;
+ char *codepoint_ptr = (char *) cp;
+
+ // Fingers crossed...
+ errno = 0;
+ iconv (tk->to_utf32_conv,
+ &multibyte_ptr, &multibyte_len, &codepoint_ptr, &codepoint_len);
+
+ // Only one Unicode character could have been processed at maximum,
+ // so let's just set the number of processed bytes to the difference
+ *nbytep = len - multibyte_len;
+
+ // Nothing has been converted, let's examine what happened
+ if (codepoint_ptr == (char *) cp)
+ {
+ if (errno == 0)
+ // The input was probably a shift sequence
+ return TERMO_RES_AGAIN;
+ if (errno == EINVAL)
+ // Incomplete character or shift sequence
+ return TERMO_RES_AGAIN;
+ if (errno == EILSEQ)
+ {
+ // Invalid multibyte sequence in the input, let's try going
+ // byte after byte in hope we skip it completely
+ *cp = MULTIBYTE_INVALID;
+ *nbytep = 1;
+ return TERMO_RES_KEY;
+ }
+
+ // We can't really get E2BIG so what the fuck is going on here
+ abort ();
+ }
+ return TERMO_RES_KEY;
+}
+
+static void
+emit_codepoint (termo_t *tk, uint32_t codepoint, termo_key_t *key)
+{
+ if (codepoint < 0x20)
+ {
+ // C0 range
+ key->code.codepoint = 0;
+ key->modifiers = 0;
+
+ if (!(tk->flags & TERMO_FLAG_NOINTERPRET)
+ && tk->c0[codepoint].sym != TERMO_SYM_UNKNOWN)
+ {
+ key->code.sym = tk->c0[codepoint].sym;
+ key->modifiers |= tk->c0[codepoint].modifier_set;
+ }
+
+ if (!key->code.sym)
+ {
+ key->type = TERMO_TYPE_KEY;
+ /* Generically modified Unicode ought not report the SHIFT state,
+ * or else we get into complications trying to report Shift-; vs :
+ * and so on... In order to be able to represent Ctrl-Shift-A as
+ * CTRL modified unicode A, we need to call Ctrl-A simply 'a',
+ * lowercase
+ */
+ if (codepoint + 0x40 >= 'A' && codepoint + 0x40 <= 'Z')
+ // It's a letter - use lowercase instead
+ key->code.codepoint = codepoint + 0x60;
+ else
+ key->code.codepoint = codepoint + 0x40;
+ key->modifiers = TERMO_KEYMOD_CTRL;
+ }
+ else
+ key->type = TERMO_TYPE_KEYSYM;
+ }
+ else if (codepoint == 0x7f && !(tk->flags & TERMO_FLAG_NOINTERPRET))
+ {
+ // ASCII DEL
+ key->type = TERMO_TYPE_KEYSYM;
+ key->code.sym = TERMO_SYM_DEL;
+ key->modifiers = 0;
+ }
+ else
+ {
+ key->type = TERMO_TYPE_KEY;
+ key->code.codepoint = codepoint;
+ key->modifiers = 0;
+ }
+
+ termo_canonicalise (tk, key);
+
+ if (key->type == TERMO_TYPE_KEY)
+ fill_multibyte (tk, key);
+}
+
+void
+termo_canonicalise (termo_t *tk, termo_key_t *key)
+{
+ int flags = tk->canonflags;
+
+ if (flags & TERMO_CANON_SPACESYMBOL)
+ {
+ if (key->type == TERMO_TYPE_KEY && key->code.codepoint == 0x20)
+ {
+ key->type = TERMO_TYPE_KEYSYM;
+ key->code.sym = TERMO_SYM_SPACE;
+ }
+ }
+ else
+ {
+ if (key->type == TERMO_TYPE_KEYSYM
+ && key->code.sym == TERMO_SYM_SPACE)
+ {
+ key->type = TERMO_TYPE_KEY;
+ key->code.codepoint = 0x20;
+ fill_multibyte (tk, key);
+ }
+ }
+
+ if (flags & TERMO_CANON_DELBS)
+ if (key->type == TERMO_TYPE_KEYSYM
+ && key->code.sym == TERMO_SYM_DEL)
+ key->code.sym = TERMO_SYM_BACKSPACE;
+}
+
+static termo_result_t
+peekkey (termo_t *tk, termo_key_t *key, int force, size_t *nbytep)
+{
+ int again = 0;
+
+ if (!tk->is_started)
+ {
+ errno = EINVAL;
+ return TERMO_RES_ERROR;
+ }
+
+#ifdef DEBUG
+ fprintf (stderr, "getkey(force=%d): buffer ", force);
+ print_buffer (tk);
+ fprintf (stderr, "\n");
+#endif
+
+ if (tk->hightide)
+ {
+ tk->buffstart += tk->hightide;
+ tk->buffcount -= tk->hightide;
+ tk->hightide = 0;
+ }
+
+ termo_result_t ret;
+ termo_driver_node_t *p;
+ for (p = tk->drivers; p; p = p->next)
+ {
+ ret = (p->driver->peekkey) (tk, p->info, key, force, nbytep);
+
+#ifdef DEBUG
+ fprintf (stderr, "Driver %s yields %s\n",
+ p->driver->name, res2str (ret));
+#endif
+
+ switch (ret)
+ {
+ case TERMO_RES_KEY:
+ {
+#ifdef DEBUG
+ print_key (tk, key); fprintf (stderr, "\n");
+#endif
+ // Slide the data down to stop it running away
+ size_t halfsize = tk->buffsize / 2;
+ if (tk->buffstart > halfsize)
+ {
+ memcpy (tk->buffer, tk->buffer + halfsize, halfsize);
+ tk->buffstart -= halfsize;
+ }
+
+ /* fallthrough */
+ }
+ case TERMO_RES_EOF:
+ case TERMO_RES_ERROR:
+ return ret;
+
+ case TERMO_RES_AGAIN:
+ if (!force)
+ again = 1;
+ case TERMO_RES_NONE:
+ break;
+ }
+ }
+
+ if (again)
+ return TERMO_RES_AGAIN;
+
+ ret = peekkey_simple (tk, key, force, nbytep);
+
+#ifdef DEBUG
+ fprintf (stderr, "getkey_simple(force=%d) yields %s\n",
+ force, res2str (ret));
+ if (ret == TERMO_RES_KEY)
+ {
+ print_key (tk, key);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+ return ret;
+}
+
+static termo_result_t
+peekkey_simple (termo_t *tk, termo_key_t *key, int force, size_t *nbytep)
+{
+ if (tk->buffcount == 0)
+ return tk->is_closed ? TERMO_RES_EOF : TERMO_RES_NONE;
+
+ unsigned char b0 = CHARAT (0);
+ if (b0 == 0x1b)
+ {
+ // Escape-prefixed value? Might therefore be Alt+key
+ if (tk->buffcount == 1)
+ {
+ // This might be an press, or it may want to be part
+ // of a longer sequence
+ if (!force)
+ return TERMO_RES_AGAIN;
+
+ (*tk->method.emit_codepoint) (tk, b0, key);
+ *nbytep = 1;
+ return TERMO_RES_KEY;
+ }
+
+ // Try another key there
+ tk->buffstart++;
+ tk->buffcount--;
+
+ // Run the full driver
+ termo_result_t metakey_result = peekkey (tk, key, force, nbytep);
+
+ tk->buffstart--;
+ tk->buffcount++;
+
+ switch (metakey_result)
+ {
+ case TERMO_RES_KEY:
+ key->modifiers |= TERMO_KEYMOD_ALT;
+ (*nbytep)++;
+ break;
+
+ case TERMO_RES_NONE:
+ case TERMO_RES_EOF:
+ case TERMO_RES_AGAIN:
+ case TERMO_RES_ERROR:
+ break;
+ }
+
+ return metakey_result;
+ }
+ else if (!(tk->flags & TERMO_FLAG_RAW))
+ {
+ uint32_t codepoint;
+ termo_result_t res = parse_multibyte
+ (tk, tk->buffer + tk->buffstart, tk->buffcount, &codepoint, nbytep);
+
+ if (res == TERMO_RES_AGAIN && force)
+ {
+ /* There weren't enough bytes for a complete character but
+ * caller demands an answer. About the best thing we can do here
+ * is eat as many bytes as we have, and emit a MULTIBYTE_INVALID.
+ * If the remaining bytes arrive later, they'll be invalid too.
+ */
+ codepoint = MULTIBYTE_INVALID;
+ *nbytep = tk->buffcount;
+ res = TERMO_RES_KEY;
+ }
+
+ key->type = TERMO_TYPE_KEY;
+ key->modifiers = 0;
+ (*tk->method.emit_codepoint) (tk, codepoint, key);
+ return res;
+ }
+ else
+ {
+ // Non multibyte case - just report the raw byte
+ key->type = TERMO_TYPE_KEY;
+ key->code.codepoint = b0;
+ key->modifiers = 0;
+
+ key->multibyte[0] = b0;
+ key->multibyte[1] = 0;
+
+ *nbytep = 1;
+ return TERMO_RES_KEY;
+ }
+}
+
+// XXX: With the current infrastructure I'm not sure how to properly handle
+// this. peekkey() isn't made for skipping invalid inputs.
+#define INVALID_1005 0x20
+
+static termo_result_t
+parse_1005_value (const unsigned char **bytes, size_t *len, uint32_t *cp)
+{
+ unsigned int nbytes;
+ unsigned char b0 = (*bytes)[0];
+ if (b0 < 0x80)
+ {
+ // Single byte ASCII
+ *cp = b0;
+ nbytes = 1;
+ goto end;
+ }
+ else if (b0 < 0xc0)
+ {
+ // Starts with a continuation byte - that's not right
+ *cp = INVALID_1005;
+ nbytes = 1;
+ goto end;
+ }
+ else if (b0 < 0xe0)
+ {
+ nbytes = 2;
+ *cp = b0 & 0x1f;
+ }
+ else if (b0 < 0xf0)
+ {
+ nbytes = 3;
+ *cp = b0 & 0x0f;
+ }
+ else if (b0 < 0xf8)
+ {
+ nbytes = 4;
+ *cp = b0 & 0x07;
+ }
+ else if (b0 < 0xfc)
+ {
+ nbytes = 5;
+ *cp = b0 & 0x03;
+ }
+ else if (b0 < 0xfe)
+ {
+ nbytes = 6;
+ *cp = b0 & 0x01;
+ }
+ else
+ {
+ *cp = INVALID_1005;
+ nbytes = 1;
+ goto end;
+ }
+
+ for (unsigned int b = 1; b < nbytes; b++)
+ {
+ if (b >= *len)
+ return TERMO_RES_AGAIN;
+
+ unsigned char cb = (*bytes)[b];
+ if (cb < 0x80 || cb >= 0xc0)
+ {
+ *cp = INVALID_1005;
+ nbytes = b;
+ goto end;
+ }
+ *cp <<= 6;
+ *cp |= cb & 0x3f;
+ }
+
+end:
+ (*bytes) += nbytes;
+ (*len) -= nbytes;
+ return TERMO_RES_KEY;
+}
+
+static termo_result_t
+peekkey_mouse (termo_t *tk, termo_key_t *key, size_t *nbytep)
+{
+ uint32_t b, x, y;
+
+ // TODO: Add some API to switch on 1005 mode support
+ if (false)
+ {
+ const unsigned char *buff = tk->buffer + tk->buffstart;
+ size_t len = tk->buffcount;
+
+ if (parse_1005_value (&buff, &len, &b) == TERMO_RES_AGAIN
+ || parse_1005_value (&buff, &len, &x) == TERMO_RES_AGAIN
+ || parse_1005_value (&buff, &len, &y) == TERMO_RES_AGAIN)
+ return TERMO_RES_AGAIN;
+
+ *nbytep = tk->buffcount - len;
+ }
+ else
+ {
+ if (tk->buffcount < 3)
+ return TERMO_RES_AGAIN;
+
+ b = CHARAT (0);
+ x = CHARAT (1);
+ y = CHARAT (2);
+
+ *nbytep = 3;
+ }
+
+ key->type = TERMO_TYPE_MOUSE;
+ key->code.mouse.info = b - 0x20;
+ key->code.mouse.x = x - 0x20 - 1;
+ key->code.mouse.y = y - 0x20 - 1;
+
+ key->modifiers = (key->code.mouse.info & 0x1c) >> 2;
+ key->code.mouse.info &= ~0x1c;
+
+ return TERMO_RES_KEY;
+}
+
+termo_result_t
+termo_getkey (termo_t *tk, termo_key_t *key)
+{
+ size_t nbytes = 0;
+ termo_result_t ret = peekkey (tk, key, 0, &nbytes);
+
+ if (ret == TERMO_RES_KEY)
+ eat_bytes (tk, nbytes);
+
+ if (ret == TERMO_RES_AGAIN)
+ /* Call peekkey() again in force mode to obtain whatever it can */
+ (void) peekkey (tk, key, 1, &nbytes);
+ /* Don't eat it yet though */
+
+ return ret;
+}
+
+termo_result_t
+termo_getkey_force (termo_t *tk, termo_key_t *key)
+{
+ size_t nbytes = 0;
+ termo_result_t ret = peekkey (tk, key, 1, &nbytes);
+
+ if (ret == TERMO_RES_KEY)
+ eat_bytes (tk, nbytes);
+
+ return ret;
+}
+
+termo_result_t
+termo_waitkey (termo_t *tk, termo_key_t *key)
+{
+ if (tk->fd == -1)
+ {
+ errno = EBADF;
+ return TERMO_RES_ERROR;
+ }
+
+ while (1)
+ {
+ termo_result_t ret = termo_getkey (tk, key);
+
+ switch (ret)
+ {
+ case TERMO_RES_KEY:
+ case TERMO_RES_EOF:
+ case TERMO_RES_ERROR:
+ return ret;
+
+ case TERMO_RES_NONE:
+ ret = termo_advisereadable (tk);
+ if (ret == TERMO_RES_ERROR)
+ return ret;
+ break;
+
+ case TERMO_RES_AGAIN:
+ {
+ if (tk->is_closed)
+ // We're closed now. Never going to get more bytes
+ // so just go with what we have
+ return termo_getkey_force (tk, key);
+
+ struct pollfd fd;
+retry:
+ fd.fd = tk->fd;
+ fd.events = POLLIN;
+
+ int pollret = poll (&fd, 1, tk->waittime);
+ if (pollret == -1)
+ {
+ if (errno == EINTR && !(tk->flags & TERMO_FLAG_EINTR))
+ goto retry;
+
+ return TERMO_RES_ERROR;
+ }
+
+ if (fd.revents & (POLLIN | POLLHUP | POLLERR))
+ ret = termo_advisereadable (tk);
+ else
+ ret = TERMO_RES_NONE;
+
+ if (ret == TERMO_RES_ERROR)
+ return ret;
+ if (ret == TERMO_RES_NONE)
+ return termo_getkey_force (tk, key);
+ }
+ }
+ }
+
+ /* UNREACHABLE */
+}
+
+termo_result_t
+termo_advisereadable (termo_t *tk)
+{
+ if (tk->fd == -1)
+ {
+ errno = EBADF;
+ return TERMO_RES_ERROR;
+ }
+
+ if (tk->buffstart)
+ {
+ memmove (tk->buffer, tk->buffer + tk->buffstart, tk->buffcount);
+ tk->buffstart = 0;
+ }
+
+ /* Not expecting it ever to be greater but doesn't hurt to handle that */
+ if (tk->buffcount >= tk->buffsize)
+ {
+ errno = ENOMEM;
+ return TERMO_RES_ERROR;
+ }
+
+ ssize_t len;
+retry:
+ len = read (tk->fd, tk->buffer + tk->buffcount,
+ tk->buffsize - tk->buffcount);
+
+ if (len == -1)
+ {
+ if (errno == EAGAIN)
+ return TERMO_RES_NONE;
+ if (errno == EINTR && !(tk->flags & TERMO_FLAG_EINTR))
+ goto retry;
+ return TERMO_RES_ERROR;
+ }
+ if (len < 1)
+ {
+ tk->is_closed = true;
+ return TERMO_RES_NONE;
+ }
+ tk->buffcount += len;
+ return TERMO_RES_AGAIN;
+}
+
+size_t
+termo_push_bytes (termo_t *tk, const char *bytes, size_t len)
+{
+ if (tk->buffstart)
+ {
+ memmove (tk->buffer, tk->buffer + tk->buffstart, tk->buffcount);
+ tk->buffstart = 0;
+ }
+
+ /* Not expecting it ever to be greater but doesn't hurt to handle that */
+ if (tk->buffcount >= tk->buffsize)
+ {
+ errno = ENOMEM;
+ return (size_t)-1;
+ }
+
+ if (len > tk->buffsize - tk->buffcount)
+ len = tk->buffsize - tk->buffcount;
+
+ // memcpy(), not strncpy() in case of null bytes in input
+ memcpy (tk->buffer + tk->buffcount, bytes, len);
+ tk->buffcount += len;
+
+ return len;
+}
+
+termo_sym_t
+termo_register_keyname (termo_t *tk, termo_sym_t sym, const char *name)
+{
+ if (!sym)
+ sym = tk->nkeynames;
+
+ if (sym >= tk->nkeynames)
+ {
+ const char **new_keynames =
+ realloc (tk->keynames, sizeof new_keynames[0] * (sym + 1));
+ if (!new_keynames)
+ return -1;
+
+ tk->keynames = new_keynames;
+
+ // Fill in the hole
+ for (int i = tk->nkeynames; i < sym; i++)
+ tk->keynames[i] = NULL;
+
+ tk->nkeynames = sym + 1;
+ }
+
+ tk->keynames[sym] = name;
+ return sym;
+}
+
+const char *
+termo_get_keyname (termo_t *tk, termo_sym_t sym)
+{
+ if (sym == TERMO_SYM_UNKNOWN)
+ return "UNKNOWN";
+ if (sym < tk->nkeynames)
+ return tk->keynames[sym];
+ return "UNKNOWN";
+}
+
+static const char *
+termo_lookup_keyname_format (termo_t *tk,
+ const char *str, termo_sym_t *sym, termo_format_t format)
+{
+ /* We store an array, so we can't do better than a linear search. Doesn't
+ * matter because user won't be calling this too often */
+
+ for (*sym = 0; *sym < tk->nkeynames; (*sym)++)
+ {
+ const char *thiskey = tk->keynames[*sym];
+ if (!thiskey)
+ continue;
+ size_t len = strlen (thiskey);
+ if (format & TERMO_FORMAT_LOWERSPACE)
+ {
+ const char *thisstr = str;
+ if (strpncmp_camel (&thisstr, &thiskey, len) == 0)
+ return thisstr;
+ }
+ else if (!strncmp (str, thiskey, len))
+ return (char *) str + len;
+ }
+ return NULL;
+}
+
+const char *
+termo_lookup_keyname (termo_t *tk, const char *str, termo_sym_t *sym)
+{
+ return termo_lookup_keyname_format (tk, str, sym, 0);
+}
+
+termo_sym_t
+termo_keyname2sym (termo_t *tk, const char *keyname)
+{
+ termo_sym_t sym;
+ const char *endp = termo_lookup_keyname (tk, keyname, &sym);
+ if (!endp || endp[0])
+ return TERMO_SYM_UNKNOWN;
+ return sym;
+}
+
+static termo_sym_t
+register_c0 (termo_t *tk,
+ termo_sym_t sym, unsigned char ctrl, const char *name)
+{
+ return register_c0_full (tk, sym, 0, 0, ctrl, name);
+}
+
+static termo_sym_t
+register_c0_full (termo_t *tk, termo_sym_t sym,
+ int modifier_set, int modifier_mask, unsigned char ctrl, const char *name)
+{
+ if (ctrl >= 0x20)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (name)
+ sym = termo_register_keyname (tk, sym, name);
+
+ tk->c0[ctrl].sym = sym;
+ tk->c0[ctrl].modifier_set = modifier_set;
+ tk->c0[ctrl].modifier_mask = modifier_mask;
+ return sym;
+}
+
+static struct modnames
+{
+ const char *shift, *alt, *ctrl;
+}
+modnames[] =
+{
+ { "S", "A", "C" }, // 0
+ { "Shift", "Alt", "Ctrl" }, // LONGMOD
+ { "S", "M", "C" }, // ALTISMETA
+ { "Shift", "Meta", "Ctrl" }, // ALTISMETA+LONGMOD
+ { "s", "a", "c" }, // LOWERMOD
+ { "shift", "alt", "ctrl" }, // LOWERMOD+LONGMOD
+ { "s", "m", "c" }, // LOWERMOD+ALTISMETA
+ { "shift", "meta", "ctrl" }, // LOWERMOD+ALTISMETA+LONGMOD
+};
+
+size_t
+termo_strfkey (termo_t *tk, char *buffer, size_t len,
+ termo_key_t *key, termo_format_t format)
+{
+ size_t pos = 0;
+ size_t l = 0;
+
+ struct modnames *mods = &modnames[
+ !!(format & TERMO_FORMAT_LONGMOD) +
+ !!(format & TERMO_FORMAT_ALTISMETA) * 2 +
+ !!(format & TERMO_FORMAT_LOWERMOD) * 4];
+
+ int wrapbracket = (format & TERMO_FORMAT_WRAPBRACKET) &&
+ (key->type != TERMO_TYPE_KEY || key->modifiers != 0);
+
+ char sep = (format & TERMO_FORMAT_SPACEMOD) ? ' ' : '-';
+
+ if (format & TERMO_FORMAT_CARETCTRL &&
+ key->type == TERMO_TYPE_KEY &&
+ key->modifiers == TERMO_KEYMOD_CTRL)
+ {
+ uint32_t codepoint = key->code.codepoint;
+
+ // Handle some of the special casesfirst
+ if (codepoint >= 'a' && codepoint <= 'z')
+ {
+ l = snprintf (buffer + pos, len - pos,
+ wrapbracket ? "<^%c>" : "^%c", (char) codepoint - 0x20);
+ if (l <= 0)
+ return pos;
+ pos += l;
+ return pos;
+ }
+ else if ((codepoint >= '@' && codepoint < 'A') ||
+ (codepoint > 'Z' && codepoint <= '_'))
+ {
+ l = snprintf (buffer + pos, len - pos,
+ wrapbracket ? "<^%c>" : "^%c", (char) codepoint);
+ if(l <= 0)
+ return pos;
+ pos += l;
+ return pos;
+ }
+ }
+
+ if (wrapbracket)
+ {
+ l = snprintf (buffer + pos, len - pos, "<");
+ if (l <= 0)
+ return pos;
+ pos += l;
+ }
+
+ if (key->modifiers & TERMO_KEYMOD_ALT)
+ {
+ l = snprintf (buffer + pos, len - pos, "%s%c", mods->alt, sep);
+ if (l <= 0)
+ return pos;
+ pos += l;
+ }
+ if (key->modifiers & TERMO_KEYMOD_CTRL)
+ {
+ l = snprintf (buffer + pos, len - pos, "%s%c", mods->ctrl, sep);
+ if (l <= 0)
+ return pos;
+ pos += l;
+ }
+ if (key->modifiers & TERMO_KEYMOD_SHIFT)
+ {
+ l = snprintf (buffer + pos, len - pos, "%s%c", mods->shift, sep);
+ if (l <= 0)
+ return pos;
+ pos += l;
+ }
+
+ switch (key->type)
+ {
+ case TERMO_TYPE_KEY:
+ if (!key->multibyte[0]) // In case of user-supplied key structures
+ fill_multibyte (tk, key);
+ l = snprintf (buffer + pos, len - pos, "%s", key->multibyte);
+ break;
+ case TERMO_TYPE_KEYSYM:
+ {
+ const char *name = termo_get_keyname (tk, key->code.sym);
+ if (format & TERMO_FORMAT_LOWERSPACE)
+ l = snprint_cameltospaces (buffer + pos, len - pos, name);
+ else
+ l = snprintf (buffer + pos, len - pos, "%s", name);
+ break;
+ }
+ case TERMO_TYPE_FUNCTION:
+ l = snprintf (buffer + pos, len - pos, "%c%d",
+ (format & TERMO_FORMAT_LOWERSPACE ? 'f' : 'F'), key->code.number);
+ break;
+ case TERMO_TYPE_MOUSE:
+ {
+ termo_mouse_event_t ev;
+ int button;
+ int line, col;
+ termo_interpret_mouse (tk, key, &ev, &button, &line, &col);
+
+ static const char *evnames[] =
+ { "Unknown", "Press", "Drag", "Release" };
+ l = snprintf (buffer + pos, len - pos,
+ "Mouse%s(%d)", evnames[ev], button);
+ if (format & TERMO_FORMAT_MOUSE_POS)
+ {
+ if (l <= 0)
+ return pos;
+ pos += l;
+ l = snprintf (buffer + pos, len - pos, " @ (%u,%u)", col, line);
+ }
+ break;
+ }
+ case TERMO_TYPE_POSITION:
+ l = snprintf (buffer + pos, len - pos, "Position");
+ break;
+ case TERMO_TYPE_MODEREPORT:
+ {
+ int initial, mode, value;
+ termo_interpret_modereport (tk, key, &initial, &mode, &value);
+ if (initial)
+ l = snprintf (buffer + pos, len - pos,
+ "Mode(%c%d=%d)", initial, mode, value);
+ else
+ l = snprintf (buffer + pos, len - pos,
+ "Mode(%d=%d)", mode, value);
+ break;
+ }
+ case TERMO_TYPE_UNKNOWN_CSI:
+ l = snprintf (buffer + pos, len - pos,
+ "CSI %c", key->code.number & 0xff);
+ break;
+ }
+
+ if (l <= 0)
+ return pos;
+ pos += l;
+
+ if (wrapbracket)
+ {
+ l = snprintf (buffer + pos, len - pos, ">");
+ if (l <= 0)
+ return pos;
+ pos += l;
+ }
+ return pos;
+}
+
+const char *
+termo_strpkey (termo_t *tk,
+ const char *str, termo_key_t *key, termo_format_t format)
+{
+ struct modnames *mods = &modnames[
+ !!(format & TERMO_FORMAT_LONGMOD) +
+ !!(format & TERMO_FORMAT_ALTISMETA) * 2 +
+ !!(format & TERMO_FORMAT_LOWERMOD) * 4];
+
+ key->modifiers = 0;
+
+ if ((format & TERMO_FORMAT_CARETCTRL) && str[0] == '^' && str[1])
+ {
+ str = termo_strpkey (tk,
+ str + 1, key, format & ~TERMO_FORMAT_CARETCTRL);
+
+ if (!str
+ || key->type != TERMO_TYPE_KEY
+ || key->code.codepoint < '@'
+ || key->code.codepoint > '_'
+ || key->modifiers != 0)
+ return NULL;
+
+ if (key->code.codepoint >= 'A'
+ && key->code.codepoint <= 'Z')
+ key->code.codepoint += 0x20;
+ key->modifiers = TERMO_KEYMOD_CTRL;
+ fill_multibyte (tk, key);
+ return (char *) str;
+ }
+
+ const char *sep_at;
+ while ((sep_at = strchr (str,
+ (format & TERMO_FORMAT_SPACEMOD) ? ' ' : '-')))
+ {
+ size_t n = sep_at - str;
+ if (n == strlen (mods->alt) && !strncmp (mods->alt, str, n))
+ key->modifiers |= TERMO_KEYMOD_ALT;
+ else if (n == strlen (mods->ctrl) && !strncmp (mods->ctrl, str, n))
+ key->modifiers |= TERMO_KEYMOD_CTRL;
+ else if (n == strlen (mods->shift) && !strncmp (mods->shift, str, n))
+ key->modifiers |= TERMO_KEYMOD_SHIFT;
+ else
+ break;
+
+ str = sep_at + 1;
+ }
+
+ size_t nbytes;
+ ssize_t snbytes;
+ const char *endstr;
+
+ if ((endstr = termo_lookup_keyname_format
+ (tk, str, &key->code.sym, format)))
+ {
+ key->type = TERMO_TYPE_KEYSYM;
+ str = endstr;
+ }
+ else if (sscanf(str, "F%d%zn", &key->code.number, &snbytes) == 1)
+ {
+ key->type = TERMO_TYPE_FUNCTION;
+ str += snbytes;
+ }
+ // Multibyte must be last
+ else if (parse_multibyte (tk, (unsigned const char *) str, strlen (str),
+ &key->code.codepoint, &nbytes) == TERMO_RES_KEY)
+ {
+ key->type = TERMO_TYPE_KEY;
+ fill_multibyte (tk, key);
+ str += nbytes;
+ }
+ // TODO: Consider mouse events?
+ else
+ return NULL;
+
+ termo_canonicalise (tk, key);
+ return (char *) str;
+}
+
+int
+termo_keycmp (termo_t *tk,
+ const termo_key_t *key1p, const termo_key_t *key2p)
+{
+ /* Copy the key structs since we'll be modifying them */
+ termo_key_t key1 = *key1p, key2 = *key2p;
+
+ termo_canonicalise (tk, &key1);
+ termo_canonicalise (tk, &key2);
+
+ if (key1.type != key2.type)
+ return key1.type - key2.type;
+
+ switch (key1.type)
+ {
+ case TERMO_TYPE_KEY:
+ if (key1.code.codepoint != key2.code.codepoint)
+ return key1.code.codepoint - key2.code.codepoint;
+ break;
+ case TERMO_TYPE_KEYSYM:
+ if (key1.code.sym != key2.code.sym)
+ return key1.code.sym - key2.code.sym;
+ break;
+ case TERMO_TYPE_FUNCTION:
+ case TERMO_TYPE_UNKNOWN_CSI:
+ if (key1.code.number != key2.code.number)
+ return key1.code.number - key2.code.number;
+ break;
+ case TERMO_TYPE_MOUSE:
+ {
+ int cmp = memcmp (&key1.code.mouse, &key2.code.mouse,
+ sizeof key1.code.mouse);
+ if (cmp != 0)
+ return cmp;
+ break;
+ }
+ case TERMO_TYPE_POSITION:
+ {
+ int line1, col1, line2, col2;
+ termo_interpret_position (tk, &key1, &line1, &col1);
+ termo_interpret_position (tk, &key2, &line2, &col2);
+ if (line1 != line2)
+ return line1 - line2;
+ return col1 - col2;
+ }
+ case TERMO_TYPE_MODEREPORT:
+ {
+ int initial1, initial2, mode1, mode2, value1, value2;
+ termo_interpret_modereport (tk, &key1, &initial1, &mode1, &value1);
+ termo_interpret_modereport (tk, &key2, &initial2, &mode2, &value2);
+ if (initial1 != initial2)
+ return initial1 - initial2;
+ if (mode1 != mode2)
+ return mode1 - mode2;
+ return value1 - value2;
+ }
+ }
+ return key1.modifiers - key2.modifiers;
+}
+
diff --git a/termo.h b/termo.h
new file mode 100644
index 0000000..3bd1a00
--- /dev/null
+++ b/termo.h
@@ -0,0 +1,277 @@
+#ifndef TERMO_H
+#define TERMO_H
+
+#include
+#include
+#include
+
+#include "termo-config.h"
+
+#define TERMO_CHECK_VERSION \
+ termo_check_version (TERMO_VERSION_MAJOR, TERMO_VERSION_MINOR)
+
+typedef enum termo_sym termo_sym_t;
+enum termo_sym
+{
+ TERMO_SYM_UNKNOWN = -1,
+ TERMO_SYM_NONE = 0,
+
+ /* Special names in C0 */
+ TERMO_SYM_BACKSPACE,
+ TERMO_SYM_TAB,
+ TERMO_SYM_ENTER,
+ TERMO_SYM_ESCAPE,
+
+ /* Special names in G0 */
+ TERMO_SYM_SPACE,
+ TERMO_SYM_DEL,
+
+ /* Special keys */
+ TERMO_SYM_UP,
+ TERMO_SYM_DOWN,
+ TERMO_SYM_LEFT,
+ TERMO_SYM_RIGHT,
+ TERMO_SYM_BEGIN,
+ TERMO_SYM_FIND,
+ TERMO_SYM_INSERT,
+ TERMO_SYM_DELETE,
+ TERMO_SYM_SELECT,
+ TERMO_SYM_PAGEUP,
+ TERMO_SYM_PAGEDOWN,
+ TERMO_SYM_HOME,
+ TERMO_SYM_END,
+
+ /* Special keys from terminfo */
+ TERMO_SYM_CANCEL,
+ TERMO_SYM_CLEAR,
+ TERMO_SYM_CLOSE,
+ TERMO_SYM_COMMAND,
+ TERMO_SYM_COPY,
+ TERMO_SYM_EXIT,
+ TERMO_SYM_HELP,
+ TERMO_SYM_MARK,
+ TERMO_SYM_MESSAGE,
+ TERMO_SYM_MOVE,
+ TERMO_SYM_OPEN,
+ TERMO_SYM_OPTIONS,
+ TERMO_SYM_PRINT,
+ TERMO_SYM_REDO,
+ TERMO_SYM_REFERENCE,
+ TERMO_SYM_REFRESH,
+ TERMO_SYM_REPLACE,
+ TERMO_SYM_RESTART,
+ TERMO_SYM_RESUME,
+ TERMO_SYM_SAVE,
+ TERMO_SYM_SUSPEND,
+ TERMO_SYM_UNDO,
+
+ /* Numeric keypad special keys */
+ TERMO_SYM_KP0,
+ TERMO_SYM_KP1,
+ TERMO_SYM_KP2,
+ TERMO_SYM_KP3,
+ TERMO_SYM_KP4,
+ TERMO_SYM_KP5,
+ TERMO_SYM_KP6,
+ TERMO_SYM_KP7,
+ TERMO_SYM_KP8,
+ TERMO_SYM_KP9,
+ TERMO_SYM_KPENTER,
+ TERMO_SYM_KPPLUS,
+ TERMO_SYM_KPMINUS,
+ TERMO_SYM_KPMULT,
+ TERMO_SYM_KPDIV,
+ TERMO_SYM_KPCOMMA,
+ TERMO_SYM_KPPERIOD,
+ TERMO_SYM_KPEQUALS,
+
+ TERMO_N_SYMS
+};
+
+typedef enum termo_type termo_type_t;
+enum termo_type
+{
+ TERMO_TYPE_KEY,
+ TERMO_TYPE_FUNCTION,
+ TERMO_TYPE_KEYSYM,
+ TERMO_TYPE_MOUSE,
+ TERMO_TYPE_POSITION,
+ TERMO_TYPE_MODEREPORT,
+ /* add other recognised types here */
+
+ TERMO_TYPE_UNKNOWN_CSI = -1
+};
+
+typedef enum termo_result termo_result_t;
+enum termo_result
+{
+ TERMO_RES_NONE,
+ TERMO_RES_KEY,
+ TERMO_RES_EOF,
+ TERMO_RES_AGAIN,
+ TERMO_RES_ERROR
+};
+
+typedef enum termo_mouse_event termo_mouse_event_t;
+enum termo_mouse_event
+{
+ TERMO_MOUSE_UNKNOWN,
+ TERMO_MOUSE_PRESS,
+ TERMO_MOUSE_DRAG,
+ TERMO_MOUSE_RELEASE
+};
+
+enum
+{
+ TERMO_KEYMOD_SHIFT = 1 << 0,
+ TERMO_KEYMOD_ALT = 1 << 1,
+ TERMO_KEYMOD_CTRL = 1 << 2
+};
+
+typedef struct termo_key termo_key_t;
+struct termo_key
+{
+ termo_type_t type;
+ union
+ {
+ uint32_t codepoint; /* TERMO_TYPE_KEY */
+ int number; /* TERMO_TYPE_FUNCTION */
+ termo_sym_t sym; /* TERMO_TYPE_KEYSYM */
+
+ /* TERMO_TYPE_MODEREPORT */
+ /* opaque, see termo_interpret_modereport() */
+ struct { char initial; int mode, value; } mode;
+
+ /* TERMO_TYPE_MOUSE */
+ /* opaque, see termo_interpret_mouse() */
+ struct { uint16_t x, y, info; } mouse;
+ } code;
+
+ int modifiers;
+
+ /* The raw multibyte sequence for the key */
+ char multibyte[MB_LEN_MAX + 1];
+};
+
+typedef struct termo termo_t;
+
+enum
+{
+ /* Do not interpret C0//DEL codes if possible */
+ TERMO_FLAG_NOINTERPRET = 1 << 0,
+ /* Convert KP codes to regular keypresses */
+ TERMO_FLAG_CONVERTKP = 1 << 1,
+ /* Don't try to decode the input characters */
+ TERMO_FLAG_RAW = 1 << 2,
+ /* Do not make initial termios calls on construction */
+ TERMO_FLAG_NOTERMIOS = 1 << 4,
+ /* Sets TERMO_CANON_SPACESYMBOL */
+ TERMO_FLAG_SPACESYMBOL = 1 << 5,
+ /* Allow Ctrl-C to be read as normal, disabling SIGINT */
+ TERMO_FLAG_CTRLC = 1 << 6,
+ /* Return ERROR on signal (EINTR) rather than retry */
+ TERMO_FLAG_EINTR = 1 << 7
+};
+
+enum
+{
+ TERMO_CANON_SPACESYMBOL = 1 << 0, /* Space is symbolic rather than Unicode */
+ TERMO_CANON_DELBS = 1 << 1 /* Del is converted to Backspace */
+};
+
+void termo_check_version (int major, int minor);
+
+termo_t *termo_new (int fd, const char *encoding, int flags);
+termo_t *termo_new_abstract (const char *term,
+ const char *encoding, int flags);
+void termo_free (termo_t *tk);
+void termo_destroy (termo_t *tk);
+
+int termo_start (termo_t *tk);
+int termo_stop (termo_t *tk);
+int termo_is_started (termo_t *tk);
+
+int termo_get_fd (termo_t *tk);
+
+int termo_get_flags (termo_t *tk);
+void termo_set_flags (termo_t *tk, int newflags);
+
+int termo_get_waittime (termo_t *tk);
+void termo_set_waittime (termo_t *tk, int msec);
+
+int termo_get_canonflags (termo_t *tk);
+void termo_set_canonflags (termo_t *tk, int flags);
+
+size_t termo_get_buffer_size (termo_t *tk);
+int termo_set_buffer_size (termo_t *tk, size_t size);
+
+size_t termo_get_buffer_remaining (termo_t *tk);
+
+void termo_canonicalise (termo_t *tk, termo_key_t *key);
+
+termo_result_t termo_getkey (termo_t *tk, termo_key_t *key);
+termo_result_t termo_getkey_force (termo_t *tk, termo_key_t *key);
+termo_result_t termo_waitkey (termo_t *tk, termo_key_t *key);
+
+termo_result_t termo_advisereadable (termo_t *tk);
+
+size_t termo_push_bytes (termo_t *tk, const char *bytes, size_t len);
+
+termo_sym_t termo_register_keyname (termo_t *tk,
+ termo_sym_t sym, const char *name);
+const char *termo_get_keyname (termo_t *tk, termo_sym_t sym);
+const char *termo_lookup_keyname (termo_t *tk,
+ const char *str, termo_sym_t *sym);
+
+termo_sym_t termo_keyname2sym (termo_t *tk, const char *keyname);
+
+termo_result_t termo_interpret_mouse (termo_t *tk,
+ const termo_key_t *key, termo_mouse_event_t *event,
+ int *button, int *line, int *col);
+termo_result_t termo_interpret_position (termo_t *tk,
+ const termo_key_t *key, int *line, int *col);
+termo_result_t termo_interpret_modereport (termo_t *tk,
+ const termo_key_t *key, int *initial, int *mode, int *value);
+termo_result_t termo_interpret_csi (termo_t *tk,
+ const termo_key_t *key, long args[], size_t *nargs, unsigned long *cmd);
+
+typedef enum termo_format termo_format_t;
+enum termo_format
+{
+ /* Shift-... instead of S-... */
+ TERMO_FORMAT_LONGMOD = 1 << 0,
+ /* ^X instead of C-X */
+ TERMO_FORMAT_CARETCTRL = 1 << 1,
+ /* Meta- or M- instead of Alt- or A- */
+ TERMO_FORMAT_ALTISMETA = 1 << 2,
+ /* Wrap special keys in brackets like */
+ TERMO_FORMAT_WRAPBRACKET = 1 << 3,
+ /* M Foo instead of M-Foo */
+ TERMO_FORMAT_SPACEMOD = 1 << 4,
+ /* meta or m instead of Meta or M */
+ TERMO_FORMAT_LOWERMOD = 1 << 5,
+ /* page down instead of PageDown */
+ TERMO_FORMAT_LOWERSPACE = 1 << 6,
+ /* Include mouse position if relevant; @ col,line */
+ TERMO_FORMAT_MOUSE_POS = 1 << 8
+};
+
+/* Some useful combinations */
+
+#define TERMO_FORMAT_VIM (termo_format_t) \
+ (TERMO_FORMAT_ALTISMETA | TERMO_FORMAT_WRAPBRACKET)
+#define TERMO_FORMAT_URWID (termo_format_t) \
+ (TERMO_FORMAT_LONGMOD | TERMO_FORMAT_ALTISMETA | \
+ TERMO_FORMAT_LOWERMOD | TERMO_FORMAT_SPACEMOD | \
+ TERMO_FORMAT_LOWERSPACE)
+
+size_t termo_strfkey (termo_t *tk, char *buffer, size_t len,
+ termo_key_t *key, termo_format_t format);
+const char *termo_strpkey (termo_t *tk, const char *str,
+ termo_key_t *key, termo_format_t format);
+
+int termo_keycmp (termo_t *tk,
+ const termo_key_t *key1, const termo_key_t *key2);
+
+#endif // ! TERMO_H
+
--
cgit v1.2.3-70-g09d2