From 5692f32bcfa049fc2b5555b5a883045b217349b9 Mon Sep 17 00:00:00 2001
From: Přemysl Janouch
Date: Thu, 9 Oct 2014 23:47:24 +0200
Subject: CMake-ify, rename to termkey2 for the time being
---
.gitignore | 2 +
CMakeLists.txt | 151 +++++
Makefile | 178 ------
README | 60 ++
config-version.cmake.in | 10 +
config.cmake.in | 8 +
demo-async.c | 2 +-
demo-glib.c | 2 +-
demo.c | 2 +-
driver-csi.c | 4 +-
driver-ti.c | 6 +-
t/01base.c | 29 -
t/02getkey.c | 92 ---
t/03utf8.c | 188 ------
t/04flags.c | 40 --
t/05read.c | 85 ---
t/06buffer.c | 38 --
t/10keyname.c | 40 --
t/11strfkey.c | 151 -----
t/12strpkey.c | 157 -----
t/13cmpkey.c | 72 ---
t/20canon.c | 74 ---
t/30mouse.c | 174 ------
t/31position.c | 38 --
t/32modereport.c | 45 --
t/39csi.c | 52 --
t/taplib.c | 79 ---
t/taplib.h | 7 -
termkey-internal.h | 115 ----
termkey.c | 1556 -----------------------------------------------
termkey.h.in | 272 ---------
termkey.pc.in | 8 -
termkey2-config.h.in | 8 +
termkey2-internal.h | 115 ++++
termkey2.c | 1556 +++++++++++++++++++++++++++++++++++++++++++++++
termkey2.h | 271 +++++++++
tests/01base.c | 29 +
tests/02getkey.c | 92 +++
tests/03utf8.c | 188 ++++++
tests/04flags.c | 40 ++
tests/05read.c | 85 +++
tests/06buffer.c | 38 ++
tests/10keyname.c | 40 ++
tests/11strfkey.c | 151 +++++
tests/12strpkey.c | 157 +++++
tests/13cmpkey.c | 72 +++
tests/20canon.c | 74 +++
tests/30mouse.c | 174 ++++++
tests/31position.c | 38 ++
tests/32modereport.c | 45 ++
tests/39csi.c | 52 ++
tests/taplib.c | 79 +++
tests/taplib.h | 7 +
53 files changed, 3550 insertions(+), 3498 deletions(-)
create mode 100644 .gitignore
create mode 100644 CMakeLists.txt
delete mode 100644 Makefile
create mode 100644 README
create mode 100644 config-version.cmake.in
create mode 100644 config.cmake.in
delete mode 100644 t/01base.c
delete mode 100644 t/02getkey.c
delete mode 100644 t/03utf8.c
delete mode 100644 t/04flags.c
delete mode 100644 t/05read.c
delete mode 100644 t/06buffer.c
delete mode 100644 t/10keyname.c
delete mode 100644 t/11strfkey.c
delete mode 100644 t/12strpkey.c
delete mode 100644 t/13cmpkey.c
delete mode 100644 t/20canon.c
delete mode 100644 t/30mouse.c
delete mode 100644 t/31position.c
delete mode 100644 t/32modereport.c
delete mode 100644 t/39csi.c
delete mode 100644 t/taplib.c
delete mode 100644 t/taplib.h
delete mode 100644 termkey-internal.h
delete mode 100644 termkey.c
delete mode 100644 termkey.h.in
delete mode 100644 termkey.pc.in
create mode 100644 termkey2-config.h.in
create mode 100644 termkey2-internal.h
create mode 100644 termkey2.c
create mode 100644 termkey2.h
create mode 100644 tests/01base.c
create mode 100644 tests/02getkey.c
create mode 100644 tests/03utf8.c
create mode 100644 tests/04flags.c
create mode 100644 tests/05read.c
create mode 100644 tests/06buffer.c
create mode 100644 tests/10keyname.c
create mode 100644 tests/11strfkey.c
create mode 100644 tests/12strpkey.c
create mode 100644 tests/13cmpkey.c
create mode 100644 tests/20canon.c
create mode 100644 tests/30mouse.c
create mode 100644 tests/31position.c
create mode 100644 tests/32modereport.c
create mode 100644 tests/39csi.c
create mode 100644 tests/taplib.c
create mode 100644 tests/taplib.h
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e5148b8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+# Qt Creator
+/CMakeLists.txt.user*
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..81dbb2c
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,151 @@
+project (termkey2 C)
+cmake_minimum_required (VERSION 2.8.5)
+
+if ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU" OR CMAKE_COMPILER_IS_GNUC)
+ set (CMAKE_C_FLAGS "-std=c99")
+ set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -Wextra")
+endif ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU" OR CMAKE_COMPILER_IS_GNUC)
+
+# Version
+set (project_VERSION_MAJOR 0)
+set (project_VERSION_MINOR 1)
+set (project_VERSION_PATCH 0)
+
+set (project_VERSION ${project_VERSION_MAJOR})
+set (project_VERSION ${project_VERSION}.${project_VERSION_MINOR})
+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")
+
+# Dependecies
+find_package (Curses)
+find_package (PkgConfig REQUIRED)
+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)
+include_directories (${PROJECT_SOURCE_DIR} ${PROJECT_BINARY_DIR})
+
+# Project source files
+set (lib_sources
+ termkey2.c
+ driver-csi.c
+ driver-ti.c)
+set (lib_headers
+ termkey2.h
+ termkey2-internal.h
+ ${PROJECT_BINARY_DIR}/termkey2-config.h)
+
+# Project libraries
+if (unibilium_FOUND)
+ include_directories (${unibilium_INCLUDE_DIRS})
+ set (lib_libraries ${unibilium_LIBRARIES})
+ add_definitions (-DHAVE_UNIBILIUM)
+elseif (CURSES_FOUND)
+ include_directories (${CURSES_INCLUDE_DIR})
+ set (lib_libraries ${CURSES_LIBRARY})
+else (CURSES_FOUND)
+ message (SEND_ERROR "Unibilium not found, Curses not 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
+ 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
+ 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})
+
+add_executable (demo EXCLUDE_FROM_ALL demo.c)
+target_link_libraries (demo termkey2-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})
+ list (APPEND demos demo-glib)
+endif (glib_FOUND)
+
+add_custom_target (demos DEPENDS ${demos})
+
+# The files to be installed
+include (GNUInstallDirs)
+install (TARGETS termkey2 termkey2-static DESTINATION ${CMAKE_INSTALL_LIBDIR})
+install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
+install (FILES termkey2.h ${PROJECT_BINARY_DIR}/termkey2-config.h
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${project_INCLUDE_NAME})
+
+# Configuration for other CMake projects
+configure_file (config.cmake.in
+ ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake @ONLY)
+configure_file (config-version.cmake.in
+ ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake @ONLY)
+
+install (FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
+ ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${project_VERSION})
+
+# Do some unit tests
+option (BUILD_TESTING "Build tests" OFF)
+# TODO: glob, port the tests to CTest
+set (project_tests)
+
+if (BUILD_TESTING)
+ enable_testing ()
+ set (test_common_sources t/taplib.c t/taplib.h)
+
+ foreach (name ${project_tests})
+ add_executable (test-${name} t/${name}.c ${test_common_sources})
+ target_link_libraries (test-${name} ${lib_libraries})
+ add_test (test-${name} test-${name})
+ endforeach (name)
+endif (BUILD_TESTING)
+
+# pkg-config
+file (WRITE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.pc"
+ "Name: ${PROJECT_NAME}\n"
+ "Description: Terminal key input library\n"
+ "Version: ${project_VERSION}\n"
+ "Libs: -L${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} -l${project_LIB_NAME}\n"
+ "Libs.private: ${lib_libraries}\n"
+ "Cflags: -I${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/${project_INCLUDE_NAME}\n")
+install (FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.pc"
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+
+# CPack
+set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "Terminal key input library")
+set (CPACK_PACKAGE_VENDOR "Premysl Janouch")
+set (CPACK_PACKAGE_CONTACT "Přemysl Janouch ")
+set (CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
+set (CPACK_PACKAGE_VERSION_MAJOR ${project_VERSION_MAJOR})
+set (CPACK_PACKAGE_VERSION_MINOR ${project_VERSION_MINOR})
+set (CPACK_PACKAGE_VERSION_PATCH ${project_VERSION_PATCH})
+set (CPACK_GENERATOR "TGZ;ZIP")
+set (CPACK_PACKAGE_FILE_NAME
+ "${CMAKE_PROJECT_NAME}-${project_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
+set (CPACK_PACKAGE_INSTALL_DIRECTORY "${CMAKE_PROJECT_NAME}-${project_VERSION}")
+set (CPACK_SOURCE_GENERATOR "TGZ;ZIP")
+set (CPACK_SOURCE_IGNORE_FILES "/\\\\.git;/build;/CMakeLists.txt.user")
+set (CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${project_VERSION}")
+
+include (CPack)
diff --git a/Makefile b/Makefile
deleted file mode 100644
index b96a1d6..0000000
--- a/Makefile
+++ /dev/null
@@ -1,178 +0,0 @@
-ifeq ($(shell uname),Darwin)
- LIBTOOL ?= glibtool
-else
- LIBTOOL ?= libtool
-endif
-
-ifneq ($(VERBOSE),1)
- LIBTOOL +=--quiet
-endif
-
-CFLAGS +=-Wall -Wextra -std=c99
-
-ifeq ($(DEBUG),1)
- CFLAGS +=-ggdb -DDEBUG
-endif
-
-ifeq ($(PROFILE),1)
- CFLAGS +=-pg
- LDFLAGS+=-pg
-endif
-
-ifeq ($(shell pkg-config --atleast-version=0.1.0 unibilium && echo 1),1)
- CFLAGS +=$(shell pkg-config --cflags unibilium) -DHAVE_UNIBILIUM
- LDFLAGS+=$(shell pkg-config --libs unibilium)
-else ifeq ($(shell pkg-config tinfo && echo 1),1)
- CFLAGS +=$(shell pkg-config --cflags tinfo)
- LDFLAGS+=$(shell pkg-config --libs tinfo)
-else ifeq ($(shell pkg-config ncursesw && echo 1),1)
- CFLAGS +=$(shell pkg-config --cflags ncursesw)
- LDFLAGS+=$(shell pkg-config --libs ncursesw)
-else
- LDFLAGS+=-lncurses
-endif
-
-OBJECTS=termkey.lo driver-csi.lo driver-ti.lo
-LIBRARY=libtermkey.la
-
-DEMOS=demo demo-async
-
-ifeq ($(shell pkg-config glib-2.0 && echo 1),1)
- DEMOS+=demo-glib
-endif
-
-DEMO_OBJECTS=$(DEMOS:=.lo)
-
-TESTSOURCES=$(wildcard t/[0-9]*.c)
-TESTFILES=$(TESTSOURCES:.c=.t)
-
-VERSION_MAJOR=0
-VERSION_MINOR=17
-
-VERSION_CURRENT=12
-VERSION_REVISION=0
-VERSION_AGE=11
-
-PREFIX=/usr/local
-LIBDIR=$(PREFIX)/lib
-INCDIR=$(PREFIX)/include
-MANDIR=$(PREFIX)/share/man
-MAN3DIR=$(MANDIR)/man3
-MAN7DIR=$(MANDIR)/man7
-
-all: $(LIBRARY) $(DEMOS)
-
-%.lo: %.c termkey.h termkey-internal.h
- $(LIBTOOL) --mode=compile --tag=CC $(CC) $(CFLAGS) -o $@ -c $<
-
-$(LIBRARY): $(OBJECTS)
- $(LIBTOOL) --mode=link --tag=CC $(CC) -rpath $(LIBDIR) -version-info $(VERSION_CURRENT):$(VERSION_REVISION):$(VERSION_AGE) $(LDFLAGS) -o $@ $^
-
-demo: $(LIBRARY) demo.lo
- $(LIBTOOL) --mode=link --tag=CC $(CC) -o $@ $^
-
-demo-async: $(LIBRARY) demo-async.lo
- $(LIBTOOL) --mode=link --tag=CC $(CC) -o $@ $^
-
-demo-glib.lo: demo-glib.c termkey.h
- $(LIBTOOL) --mode=compile --tag=CC $(CC) -o $@ -c $< $(shell pkg-config glib-2.0 --cflags)
-
-demo-glib: $(LIBRARY) demo-glib.lo
- $(LIBTOOL) --mode=link --tag=CC $(CC) -o $@ $^ $(shell pkg-config glib-2.0 --libs)
-
-t/%.t: t/%.c $(LIBRARY) t/taplib.lo
- $(LIBTOOL) --mode=link --tag=CC $(CC) -o $@ $^
-
-t/taplib.lo: t/taplib.c
- $(LIBTOOL) --mode=compile --tag=CC $(CC) $(CFLAGS) -o $@ -c $^
-
-.PHONY: test
-test: $(TESTFILES)
- prove -e ""
-
-.PHONY: clean-test
-clean-test:
- $(LIBTOOL) --mode=clean rm -f $(TESTFILES) t/taplib.lo
-
-.PHONY: clean
-clean: clean-test
- $(LIBTOOL) --mode=clean rm -f $(OBJECTS) $(DEMO_OBJECTS)
- $(LIBTOOL) --mode=clean rm -f $(LIBRARY)
- $(LIBTOOL) --mode=clean rm -rf $(DEMOS)
-
-.PHONY: install
-install: install-inc install-lib install-man
- $(LIBTOOL) --mode=finish $(DESTDIR)$(LIBDIR)
-
-install-inc: termkey.h
- install -d $(DESTDIR)$(INCDIR)
- install -m644 termkey.h $(DESTDIR)$(INCDIR)
- install -d $(DESTDIR)$(LIBDIR)/pkgconfig
- sed "s,@LIBDIR@,$(LIBDIR),;s,@INCDIR@,$(INCDIR)," $(DESTDIR)$(LIBDIR)/pkgconfig/termkey.pc
-
-install-lib: $(LIBRARY)
- install -d $(DESTDIR)$(LIBDIR)
- $(LIBTOOL) --mode=install install libtermkey.la $(DESTDIR)$(LIBDIR)/libtermkey.la
-
-install-man:
- install -d $(DESTDIR)$(MAN3DIR)
- install -d $(DESTDIR)$(MAN7DIR)
- for F in man/*.3; do \
- gzip <$$F >$(DESTDIR)$(MAN3DIR)/$${F#man/}.gz; \
- done
- for F in man/*.7; do \
- gzip <$$F >$(DESTDIR)$(MAN7DIR)/$${F#man/}.gz; \
- done
- while read FROM EQ TO; do \
- echo ln -sf $$TO.gz $(DESTDIR)$(MAN3DIR)/$$FROM.gz; \
- done < man/also
-
-# DIST CUT
-
-MANSOURCE=$(wildcard man/*.3.sh)
-BUILTMAN=$(MANSOURCE:.3.sh=.3)
-
-VERSION=$(VERSION_MAJOR).$(VERSION_MINOR)
-
-all: doc
-
-doc: $(BUILTMAN)
-
-%.3: %.3.sh
- sh $< >$@
-
-clean: clean-built
-
-clean-built:
- rm -f $(BUILTMAN) termkey.h
-
-termkey.h: termkey.h.in Makefile
- rm -f $@
- sed -e 's/@@VERSION_MAJOR@@/$(VERSION_MAJOR)/g' \
- -e 's/@@VERSION_MINOR@@/$(VERSION_MINOR)/g' \
- $< >$@
- chmod a-w $@
-
-DISTDIR=libtermkey-$(VERSION)
-
-distdir: all
- mkdir __distdir
- cp *.c *.h LICENSE __distdir
- mkdir __distdir/t
- cp t/*.c t/*.h __distdir/t
- mkdir __distdir/man
- cp man/*.[37] man/also __distdir/man
- sed "s,@VERSION@,$(VERSION)," __distdir/termkey.pc.in
- sed "/^# DIST CUT/Q" __distdir/Makefile
- mv __distdir $(DISTDIR)
-
-TARBALL=$(DISTDIR).tar.gz
-
-dist: distdir
- tar -czf $(TARBALL) $(DISTDIR)
- rm -rf $(DISTDIR)
-
-HTMLDIR=html
-
-htmldocs: $(BUILTMAN)
- perl $(HOME)/src/perl/Parse-Man/examples/man-to-html.pl -O $(HTMLDIR) --file-extension tmpl --link-extension html --template home_lou.tt2 --also man/also man/*.3 man/*.7 --index index.tmpl
diff --git a/README b/README
new file mode 100644
index 0000000..3a1c2ee
--- /dev/null
+++ b/README
@@ -0,0 +1,60 @@
+termkey2
+========
+
+`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
+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
+doesn't aspire to also replace the output part of ncurses, but is rather
+complementary to it. In the end it makes use of its terminfo library.
+
+The API isn't stable yet. Tell me what needs to be done so I can fix it first.
+
+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
+ $ mkdir build
+ $ cd build
+ $ cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local
+
+To install the library, you can do either the usual:
+ $ make install
+
+Or you can try telling CMake to make a package for you. For Debian it is:
+ $ cpack -G DEB
+ # dpkg -i termkey2-*.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:
+
+ $ make demos
+
+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,
+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
+
+Another change worth mentioning is the usage of CMake instead of the problematic
+libtool-based Makefile. Now you can include this project in your other CMake-
+-based projects and simply import the target. No package maintainer action is
+needed for you to enjoy the benefits of proper terminal input.
+
+The rest is just me going silly over formatting and various unimportant stuff.
+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
+, with additional changes made by Přemysl Janouch
+.
+
+You may use the software under the terms of the MIT license, the text of which
+is included within the package, see the file LICENSE.
diff --git a/config-version.cmake.in b/config-version.cmake.in
new file mode 100644
index 0000000..dbd7077
--- /dev/null
+++ b/config-version.cmake.in
@@ -0,0 +1,10 @@
+set (PACKAGE_VERSION "@project_VERSION@")
+
+if ("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
+ set (PACKAGE_VERSION_COMPATIBLE FALSE)
+else ("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
+ set (PACKAGE_VERSION_COMPATIBLE TRUE)
+ if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
+ set (PACKAGE_VERSION_EXACT TRUE)
+ endif ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
+endif ("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
diff --git a/config.cmake.in b/config.cmake.in
new file mode 100644
index 0000000..9a19a6f
--- /dev/null
+++ b/config.cmake.in
@@ -0,0 +1,8 @@
+# - Config file for @project_CMAKE_NAME@
+# It defines the following variables:
+# @project_CMAKE_NAME@_INCLUDE_DIRS
+# @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)
+
diff --git a/demo-async.c b/demo-async.c
index 6efcf28..88d68a5 100644
--- a/demo-async.c
+++ b/demo-async.c
@@ -6,7 +6,7 @@
#include
#include
-#include "termkey.h"
+#include "termkey2.h"
static void
on_key (termkey_t *tk, termkey_key_t *key)
diff --git a/demo-glib.c b/demo-glib.c
index 0162042..dfe5cd4 100644
--- a/demo-glib.c
+++ b/demo-glib.c
@@ -3,7 +3,7 @@
#include
#include
-#include "termkey.h"
+#include "termkey2.h"
static termkey_t *tk;
static int timeout_id;
diff --git a/demo.c b/demo.c
index 1f89ea0..5bb9fc2 100644
--- a/demo.c
+++ b/demo.c
@@ -6,7 +6,7 @@
#include
#include
-#include "termkey.h"
+#include "termkey2.h"
int
main(int argc, char *argv[])
diff --git a/driver-csi.c b/driver-csi.c
index 4e1f275..23f38e7 100644
--- a/driver-csi.c
+++ b/driver-csi.c
@@ -1,5 +1,5 @@
-#include "termkey.h"
-#include "termkey-internal.h"
+#include "termkey2.h"
+#include "termkey2-internal.h"
#include
#include
diff --git a/driver-ti.c b/driver-ti.c
index ed0e9df..93fda30 100644
--- a/driver-ti.c
+++ b/driver-ti.c
@@ -1,8 +1,8 @@
// we want strdup()
#define _XOPEN_SOURCE 600
-#include "termkey.h"
-#include "termkey-internal.h"
+#include "termkey2.h"
+#include "termkey2-internal.h"
#ifdef HAVE_UNIBILIUM
# include
@@ -240,7 +240,7 @@ load_terminfo (termkey_ti_t *ti, const char *term)
if (node && !insert_seq (ti, value, node))
{
- free(node);
+ free (node);
return 0;
}
}
diff --git a/t/01base.c b/t/01base.c
deleted file mode 100644
index 39e0e39..0000000
--- a/t/01base.c
+++ /dev/null
@@ -1,29 +0,0 @@
-#include
-#include "../termkey.h"
-#include "taplib.h"
-
-int
-main (int argc, char *argv[])
-{
- termkey_t *tk;
-
- plan_tests (6);
-
- tk = termkey_new_abstract ("vt100", NULL, 0);
- ok (!!tk, "termkey_new_abstract");
- is_int (termkey_get_buffer_size (tk), 256, "termkey_get_buffer_size");
- ok (termkey_is_started (tk), "termkey_is_started true after construction");
-
- termkey_stop (tk);
- ok (!termkey_is_started (tk),
- "termkey_is_started false after termkey_stop()");
-
- termkey_start (tk);
- ok (termkey_is_started (tk),
- "termkey_is_started true after termkey_start()");
-
- termkey_destroy (tk);
-
- ok (1, "termkey_free");
- return exit_status ();
-}
diff --git a/t/02getkey.c b/t/02getkey.c
deleted file mode 100644
index 8cba991..0000000
--- a/t/02getkey.c
+++ /dev/null
@@ -1,92 +0,0 @@
-#include "../termkey.h"
-#include "taplib.h"
-
-int
-main (int argc, char *argv[])
-{
- termkey_t *tk;
- termkey_key_t key;
-
- plan_tests (31);
-
- tk = termkey_new_abstract ("vt100", NULL, 0);
-
- is_int (termkey_get_buffer_remaining (tk),
- 256, "buffer free initially 256");
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_NONE,
- "getkey yields RES_NONE when empty");
-
- is_int (termkey_push_bytes (tk, "h", 1), 1, "push_bytes returns 1");
-
- is_int (termkey_get_buffer_remaining (tk), 255,
- "buffer free 255 after push_bytes");
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY after h");
-
- is_int (key.type, TERMKEY_TYPE_KEY, "key.type after h");
- is_int (key.code.codepoint, 'h', "key.code.codepoint after h");
- is_int (key.modifiers, 0, "key.modifiers after h");
- is_str (key.multibyte, "h", "key.multibyte after h");
-
- is_int (termkey_get_buffer_remaining (tk), 256,
- "buffer free 256 after getkey");
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_NONE,
- "getkey yields RES_NONE a second time");
-
- termkey_push_bytes (tk, "\x01", 1);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY after C-a");
-
- is_int (key.type, TERMKEY_TYPE_KEY, "key.type after C-a");
- is_int (key.code.codepoint, 'a', "key.code.codepoint after C-a");
- is_int (key.modifiers, TERMKEY_KEYMOD_CTRL, "key.modifiers after C-a");
-
- termkey_push_bytes (tk, "\033OA", 3);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY after Up");
-
- is_int (key.type, TERMKEY_TYPE_KEYSYM, "key.type after Up");
- is_int (key.code.sym, TERMKEY_SYM_UP, "key.code.sym after Up");
- is_int (key.modifiers, 0, "key.modifiers after Up");
-
- is_int (termkey_push_bytes (tk, "\033O", 2), 2, "push_bytes returns 2");
-
- is_int (termkey_get_buffer_remaining (tk), 254,
- "buffer free 254 after partial write");
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_AGAIN,
- "getkey yields RES_AGAIN after partial write");
-
- termkey_push_bytes (tk, "C", 1);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY after Right completion");
-
- is_int (key.type, TERMKEY_TYPE_KEYSYM, "key.type after Right");
- is_int (key.code.sym, TERMKEY_SYM_RIGHT, "key.code.sym after Right");
- is_int (key.modifiers, 0, "key.modifiers after Right");
-
- is_int (termkey_get_buffer_remaining (tk), 256,
- "buffer free 256 after completion");
-
- termkey_push_bytes (tk, "\033[27;5u", 7);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY after Ctrl-Escape");
-
- is_int (key.type, TERMKEY_TYPE_KEYSYM,
- "key.type after Ctrl-Escape");
- is_int (key.code.sym, TERMKEY_SYM_ESCAPE,
- "key.code.sym after Ctrl-Escape");
- is_int (key.modifiers, TERMKEY_KEYMOD_CTRL,
- "key.modifiers after Ctrl-Escape");
-
- termkey_destroy (tk);
-
- return exit_status ();
-}
diff --git a/t/03utf8.c b/t/03utf8.c
deleted file mode 100644
index 9b06e2e..0000000
--- a/t/03utf8.c
+++ /dev/null
@@ -1,188 +0,0 @@
-#include "../termkey.h"
-#include "taplib.h"
-
-int
-main (int argc, char *argv[])
-{
- termkey_t *tk;
- termkey_key_t key;
-
- plan_tests (33 /* 57 */);
-
- tk = termkey_new_abstract ("vt100", "UTF-8", 0);
-
- termkey_push_bytes (tk, "a", 1);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY low ASCII");
- is_int (key.type, TERMKEY_TYPE_KEY, "key.type low ASCII");
- is_int (key.code.codepoint, 'a', "key.code.codepoint low ASCII");
-
- /* 2-byte UTF-8 range is U+0080 to U+07FF (0xDF 0xBF) */
- /* However, we'd best avoid the C1 range, so we'll start at U+00A0 (0xC2 0xA0) */
-
- termkey_push_bytes (tk, "\xC2\xA0", 2);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 2 low");
- is_int (key.type, TERMKEY_TYPE_KEY, "key.type UTF-8 2 low");
- is_int (key.code.codepoint, 0x00A0, "key.code.codepoint UTF-8 2 low");
-
- termkey_push_bytes (tk, "\xDF\xBF", 2);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 2 high");
- is_int (key.type, TERMKEY_TYPE_KEY, "key.type UTF-8 2 high");
- is_int (key.code.codepoint, 0x07FF, "key.code.codepoint UTF-8 2 high");
-
- /* 3-byte UTF-8 range is U+0800 (0xE0 0xA0 0x80) to U+FFFD (0xEF 0xBF 0xBD) */
-
- termkey_push_bytes (tk, "\xE0\xA0\x80", 3);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 3 low");
- is_int (key.type, TERMKEY_TYPE_KEY, "key.type UTF-8 3 low");
- is_int (key.code.codepoint, 0x0800, "key.code.codepoint UTF-8 3 low");
-
- termkey_push_bytes (tk, "\xEF\xBF\xBD", 3);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 3 high");
- is_int (key.type, TERMKEY_TYPE_KEY, "key.type UTF-8 3 high");
- is_int (key.code.codepoint, 0xFFFD, "key.code.codepoint UTF-8 3 high");
-
- /* 4-byte UTF-8 range is U+10000 (0xF0 0x90 0x80 0x80) to U+10FFFF (0xF4 0x8F 0xBF 0xBF) */
-
- termkey_push_bytes (tk, "\xF0\x90\x80\x80", 4);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 4 low");
- is_int (key.type, TERMKEY_TYPE_KEY, "key.type UTF-8 4 low");
- is_int (key.code.codepoint, 0x10000, "key.code.codepoint UTF-8 4 low");
-
- termkey_push_bytes (tk, "\xF4\x8F\xBF\xBF", 4);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 4 high");
- is_int (key.type, TERMKEY_TYPE_KEY, "key.type UTF-8 4 high");
- is_int (key.code.codepoint, 0x10FFFF, "key.code.codepoint UTF-8 4 high");
-
-#if 0
- /* XXX: With the move to iconv, this has changed significantly. */
-
- /* Invalid continuations */
-
- termkey_push_bytes (tk, "\xC2!", 2);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 2 invalid cont");
- is_int (key.code.codepoint, 0xFFFD,
- "key.code.codepoint UTF-8 2 invalid cont");
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 2 invalid after");
- is_int (key.code.codepoint, '!',
- "key.code.codepoint UTF-8 2 invalid after");
-
- termkey_push_bytes (tk, "\xE0!", 2);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 3 invalid cont");
- is_int (key.code.codepoint, 0xFFFD,
- "key.code.codepoint UTF-8 3 invalid cont");
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 3 invalid after");
- is_int (key.code.codepoint, '!',
- "key.code.codepoint UTF-8 3 invalid after");
-
- termkey_push_bytes (tk, "\xE0\xA0!", 3);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 3 invalid cont 2");
- is_int (key.code.codepoint, 0xFFFD,
- "key.code.codepoint UTF-8 3 invalid cont 2");
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 3 invalid after");
- is_int (key.code.codepoint, '!',
- "key.code.codepoint UTF-8 3 invalid after");
-
- termkey_push_bytes (tk, "\xF0!", 2);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 4 invalid cont");
- is_int (key.code.codepoint, 0xFFFD,
- "key.code.codepoint UTF-8 4 invalid cont");
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 4 invalid after");
- is_int (key.code.codepoint, '!',
- "key.code.codepoint UTF-8 4 invalid after");
-
- termkey_push_bytes (tk, "\xF0\x90!", 3);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 4 invalid cont 2");
- is_int (key.code.codepoint, 0xFFFD,
- "key.code.codepoint UTF-8 4 invalid cont 2");
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 4 invalid after");
- is_int (key.code.codepoint, '!',
- "key.code.codepoint UTF-8 4 invalid after");
-
- termkey_push_bytes (tk, "\xF0\x90\x80!", 4);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 4 invalid cont 3");
- is_int (key.code.codepoint, 0xFFFD,
- "key.code.codepoint UTF-8 4 invalid cont 3");
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 4 invalid after");
- is_int (key.code.codepoint, '!',
- "key.code.codepoint UTF-8 4 invalid after");
-#endif
-
- /* Partials */
-
- termkey_push_bytes (tk, "\xC2", 1);
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_AGAIN,
- "getkey yields RES_AGAIN UTF-8 2 partial");
-
- termkey_push_bytes (tk, "\xA0", 1);
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 2 partial");
- is_int (key.code.codepoint, 0x00A0,
- "key.code.codepoint UTF-8 2 partial");
-
- termkey_push_bytes (tk, "\xE0", 1);
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_AGAIN,
- "getkey yields RES_AGAIN UTF-8 3 partial");
-
- termkey_push_bytes (tk, "\xA0", 1);
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_AGAIN,
- "getkey yields RES_AGAIN UTF-8 3 partial");
-
- termkey_push_bytes (tk, "\x80", 1);
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 3 partial");
- is_int (key.code.codepoint, 0x0800,
- "key.code.codepoint UTF-8 3 partial");
-
- termkey_push_bytes (tk, "\xF0", 1);
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_AGAIN,
- "getkey yields RES_AGAIN UTF-8 4 partial");
-
- termkey_push_bytes (tk, "\x90", 1);
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_AGAIN,
- "getkey yields RES_AGAIN UTF-8 4 partial");
-
- termkey_push_bytes (tk, "\x80", 1);
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_AGAIN,
- "getkey yields RES_AGAIN UTF-8 4 partial");
-
- termkey_push_bytes (tk, "\x80", 1);
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY UTF-8 4 partial");
- is_int (key.code.codepoint, 0x10000,
- "key.code.codepoint UTF-8 4 partial");
-
- termkey_destroy (tk);
- return exit_status ();
-}
diff --git a/t/04flags.c b/t/04flags.c
deleted file mode 100644
index eb6e20b..0000000
--- a/t/04flags.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include
-#include "../termkey.h"
-#include "taplib.h"
-
-int
-main (int argc, char *argv[])
-{
- termkey_t *tk;
- termkey_key_t key;
-
- plan_tests (8);
-
- tk = termkey_new_abstract ("vt100", NULL, 0);
-
- termkey_push_bytes (tk, " ", 1);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY after space");
-
- is_int (key.type, TERMKEY_TYPE_KEY, "key.type after space");
- is_int (key.code.codepoint, ' ', "key.code.codepoint after space");
- is_int (key.modifiers, 0, "key.modifiers after space");
-
- termkey_set_flags (tk, TERMKEY_FLAG_SPACESYMBOL);
-
- termkey_push_bytes (tk, " ", 1);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY after space");
-
- is_int (key.type, TERMKEY_TYPE_KEYSYM,
- "key.type after space with FLAG_SPACESYMBOL");
- is_int (key.code.sym, TERMKEY_SYM_SPACE,
- "key.code.sym after space with FLAG_SPACESYMBOL");
- is_int (key.modifiers, 0,
- "key.modifiers after space with FLAG_SPACESYMBOL");
-
- termkey_destroy (tk);
- return exit_status ();
-}
diff --git a/t/05read.c b/t/05read.c
deleted file mode 100644
index 2a5530a..0000000
--- a/t/05read.c
+++ /dev/null
@@ -1,85 +0,0 @@
-#include
-#include
-#include "../termkey.h"
-#include "taplib.h"
-
-int
-main (int argc, char *argv[])
-{
- int fd[2];
- termkey_t *tk;
- termkey_key_t key;
-
- plan_tests (21);
-
- /* We'll need a real filehandle we can write/read.
- * pipe () can make us one */
- pipe (fd);
-
- /* Sanitise this just in case */
- putenv ("TERM=vt100");
-
- tk = termkey_new (fd[0], NULL, TERMKEY_FLAG_NOTERMIOS);
-
- is_int (termkey_get_buffer_remaining (tk), 256,
- "buffer free initially 256");
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_NONE,
- "getkey yields RES_NONE when empty");
-
- write (fd[1], "h", 1);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_NONE,
- "getkey yields RES_NONE before advisereadable");
-
- is_int (termkey_advisereadable (tk), TERMKEY_RES_AGAIN,
- "advisereadable yields RES_AGAIN after h");
-
- is_int (termkey_get_buffer_remaining (tk), 255,
- "buffer free 255 after advisereadable");
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY after h");
-
- is_int (key.type, TERMKEY_TYPE_KEY, "key.type after h");
- is_int (key.code.codepoint, 'h', "key.code.codepoint after h");
- is_int (key.modifiers, 0, "key.modifiers after h");
- is_str (key.multibyte, "h", "key.multibyte after h");
-
- is_int (termkey_get_buffer_remaining (tk), 256,
- "buffer free 256 after getkey");
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_NONE,
- "getkey yields RES_NONE a second time");
-
- write (fd[1], "\033O", 2);
- termkey_advisereadable (tk);
-
- is_int (termkey_get_buffer_remaining (tk), 254,
- "buffer free 254 after partial write");
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_AGAIN,
- "getkey yields RES_AGAIN after partial write");
-
- write (fd[1], "C", 1);
- termkey_advisereadable (tk);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY after Right completion");
-
- is_int (key.type, TERMKEY_TYPE_KEYSYM, "key.type after Right");
- is_int (key.code.sym, TERMKEY_SYM_RIGHT, "key.code.sym after Right");
- is_int (key.modifiers, 0, "key.modifiers after Right");
-
- is_int (termkey_get_buffer_remaining (tk), 256,
- "buffer free 256 after completion");
-
- termkey_stop (tk);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_ERROR,
- "getkey yields RES_ERROR after termkey_stop ()");
- is_int (errno, EINVAL, "getkey error is EINVAL");
-
- termkey_destroy (tk);
- return exit_status ();
-}
diff --git a/t/06buffer.c b/t/06buffer.c
deleted file mode 100644
index af415b6..0000000
--- a/t/06buffer.c
+++ /dev/null
@@ -1,38 +0,0 @@
-#include
-#include "../termkey.h"
-#include "taplib.h"
-
-int main (int argc, char *argv[])
-{
- termkey_t *tk;
- termkey_key_t key;
-
- plan_tests (9);
-
- tk = termkey_new_abstract ("vt100", NULL, 0);
-
- is_int (termkey_get_buffer_remaining (tk), 256,
- "buffer free initially 256");
- is_int (termkey_get_buffer_size (tk), 256,
- "buffer size initially 256");
-
- is_int (termkey_push_bytes (tk, "h", 1), 1, "push_bytes returns 1");
-
- is_int (termkey_get_buffer_remaining (tk), 255,
- "buffer free 255 after push_bytes");
- is_int (termkey_get_buffer_size (tk), 256,
- "buffer size 256 after push_bytes");
-
- ok (!!termkey_set_buffer_size (tk, 512), "buffer set size OK");
-
- is_int (termkey_get_buffer_remaining (tk), 511,
- "buffer free 511 after push_bytes");
- is_int (termkey_get_buffer_size (tk), 512,
- "buffer size 512 after push_bytes");
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "buffered key still useable after resize");
-
- termkey_destroy (tk);
- return exit_status ();
-}
diff --git a/t/10keyname.c b/t/10keyname.c
deleted file mode 100644
index 20ac000..0000000
--- a/t/10keyname.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "../termkey.h"
-#include "taplib.h"
-
-int
-main (int argc, char *argv[])
-{
- termkey_t *tk;
- termkey_sym_t sym;
- const char *end;
-
- plan_tests (10);
-
- tk = termkey_new_abstract ("vt100", NULL, 0);
-
- sym = termkey_keyname2sym (tk, "Space");
- is_int (sym, TERMKEY_SYM_SPACE, "keyname2sym Space");
-
- sym = termkey_keyname2sym (tk, "SomeUnknownKey");
- is_int (sym, TERMKEY_SYM_UNKNOWN, "keyname2sym SomeUnknownKey");
-
- end = termkey_lookup_keyname (tk, "Up", &sym);
- ok (!!end, "termkey_get_keyname Up returns non-NULL");
- is_str (end, "", "termkey_get_keyname Up return points at endofstring");
- is_int (sym, TERMKEY_SYM_UP, "termkey_get_keyname Up yields Up symbol");
-
- end = termkey_lookup_keyname (tk, "DownMore", &sym);
- ok (!!end, "termkey_get_keyname DownMore returns non-NULL");
- is_str (end, "More", "termkey_get_keyname DownMore return points at More");
- is_int (sym, TERMKEY_SYM_DOWN,
- "termkey_get_keyname DownMore yields Down symbol");
-
- end = termkey_lookup_keyname (tk, "SomeUnknownKey", &sym);
- ok (!end, "termkey_get_keyname SomeUnknownKey returns NULL");
-
- is_str (termkey_get_keyname (tk, TERMKEY_SYM_SPACE), "Space",
- "get_keyname SPACE");
-
- termkey_destroy (tk);
- return exit_status ();
-}
diff --git a/t/11strfkey.c b/t/11strfkey.c
deleted file mode 100644
index 4c77bdf..0000000
--- a/t/11strfkey.c
+++ /dev/null
@@ -1,151 +0,0 @@
-#include "../termkey.h"
-#include "taplib.h"
-
-int
-main (int argc, char *argv[])
-{
- termkey_t *tk;
- termkey_key_t key;
- char buffer[16];
- size_t len;
-
- plan_tests (44);
-
- tk = termkey_new_abstract ("vt100", NULL, 0);
-
- key.type = TERMKEY_TYPE_KEY;
- key.code.codepoint = 'A';
- key.modifiers = 0;
- key.multibyte[0] = 0;
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key, 0);
- is_int (len, 1, "length for unicode/A/0");
- is_str (buffer, "A", "buffer for unicode/A/0");
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
- TERMKEY_FORMAT_WRAPBRACKET);
- is_int (len, 1, "length for unicode/A/0 wrapbracket");
- is_str (buffer, "A", "buffer for unicode/A/0 wrapbracket");
-
- key.type = TERMKEY_TYPE_KEY;
- key.code.codepoint = 'b';
- key.modifiers = TERMKEY_KEYMOD_CTRL;
- key.multibyte[0] = 0;
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key, 0);
- is_int (len, 3, "length for unicode/b/CTRL");
- is_str (buffer, "C-b", "buffer for unicode/b/CTRL");
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
- TERMKEY_FORMAT_LONGMOD);
- is_int (len, 6, "length for unicode/b/CTRL longmod");
- is_str (buffer, "Ctrl-b", "buffer for unicode/b/CTRL longmod");
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
- TERMKEY_FORMAT_LONGMOD | TERMKEY_FORMAT_SPACEMOD);
- is_int (len, 6, "length for unicode/b/CTRL longmod|spacemod");
- is_str (buffer, "Ctrl b", "buffer for unicode/b/CTRL longmod|spacemod");
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
- TERMKEY_FORMAT_LONGMOD | TERMKEY_FORMAT_LOWERMOD);
- is_int (len, 6, "length for unicode/b/CTRL longmod|lowermod");
- is_str (buffer, "ctrl-b", "buffer for unicode/b/CTRL longmod|lowermod");
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
- TERMKEY_FORMAT_LONGMOD | TERMKEY_FORMAT_SPACEMOD
- | TERMKEY_FORMAT_LOWERMOD);
- is_int (len, 6, "length for unicode/b/CTRL longmod|spacemod|lowermode");
- is_str (buffer, "ctrl b",
- "buffer for unicode/b/CTRL longmod|spacemod|lowermode");
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
- TERMKEY_FORMAT_CARETCTRL);
- is_int (len, 2, "length for unicode/b/CTRL caretctrl");
- is_str (buffer, "^B", "buffer for unicode/b/CTRL caretctrl");
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
- TERMKEY_FORMAT_WRAPBRACKET);
- is_int (len, 5, "length for unicode/b/CTRL wrapbracket");
- is_str (buffer, "", "buffer for unicode/b/CTRL wrapbracket");
-
- key.type = TERMKEY_TYPE_KEY;
- key.code.codepoint = 'c';
- key.modifiers = TERMKEY_KEYMOD_ALT;
- key.multibyte[0] = 0;
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key, 0);
- is_int (len, 3, "length for unicode/c/ALT");
- is_str (buffer, "A-c", "buffer for unicode/c/ALT");
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
- TERMKEY_FORMAT_LONGMOD);
- is_int (len, 5, "length for unicode/c/ALT longmod");
- is_str (buffer, "Alt-c", "buffer for unicode/c/ALT longmod");
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
- TERMKEY_FORMAT_ALTISMETA);
- is_int (len, 3, "length for unicode/c/ALT altismeta");
- is_str (buffer, "M-c", "buffer for unicode/c/ALT altismeta");
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
- TERMKEY_FORMAT_LONGMOD|TERMKEY_FORMAT_ALTISMETA);
- is_int (len, 6, "length for unicode/c/ALT longmod|altismeta");
- is_str (buffer, "Meta-c", "buffer for unicode/c/ALT longmod|altismeta");
-
- key.type = TERMKEY_TYPE_KEYSYM;
- key.code.sym = TERMKEY_SYM_UP;
- key.modifiers = 0;
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key, 0);
- is_int (len, 2, "length for sym/Up/0");
- is_str (buffer, "Up", "buffer for sym/Up/0");
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
- TERMKEY_FORMAT_WRAPBRACKET);
- is_int (len, 4, "length for sym/Up/0 wrapbracket");
- is_str (buffer, "", "buffer for sym/Up/0 wrapbracket");
-
- key.type = TERMKEY_TYPE_KEYSYM;
- key.code.sym = TERMKEY_SYM_PAGEUP;
- key.modifiers = 0;
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key, 0);
- is_int (len, 6, "length for sym/PageUp/0");
- is_str (buffer, "PageUp", "buffer for sym/PageUp/0");
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
- TERMKEY_FORMAT_LOWERSPACE);
- is_int (len, 7, "length for sym/PageUp/0 lowerspace");
- is_str (buffer, "page up", "buffer for sym/PageUp/0 lowerspace");
-
- /* If size of buffer is too small,
- * strfkey should return something consistent */
- len = termkey_strfkey (tk, buffer, 4, &key, 0);
- is_int (len, 6, "length for sym/PageUp/0");
- is_str (buffer, "Pag", "buffer of len 4 for sym/PageUp/0");
-
- len = termkey_strfkey (tk, buffer, 4, &key, TERMKEY_FORMAT_LOWERSPACE);
- is_int (len, 7, "length for sym/PageUp/0 lowerspace");
- is_str (buffer, "pag", "buffer of len 4 for sym/PageUp/0 lowerspace");
-
- key.type = TERMKEY_TYPE_FUNCTION;
- key.code.number = 5;
- key.modifiers = 0;
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key, 0);
- is_int (len, 2, "length for func/5/0");
- is_str (buffer, "F5", "buffer for func/5/0");
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
- TERMKEY_FORMAT_WRAPBRACKET);
- is_int (len, 4, "length for func/5/0 wrapbracket");
- is_str (buffer, "", "buffer for func/5/0 wrapbracket");
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
- TERMKEY_FORMAT_LOWERSPACE);
- is_int (len, 2, "length for func/5/0 lowerspace");
- is_str (buffer, "f5", "buffer for func/5/0 lowerspace");
-
- termkey_destroy (tk);
- return exit_status ();
-}
diff --git a/t/12strpkey.c b/t/12strpkey.c
deleted file mode 100644
index f67b67a..0000000
--- a/t/12strpkey.c
+++ /dev/null
@@ -1,157 +0,0 @@
-#include "../termkey.h"
-#include "taplib.h"
-
-int
-main (int argc, char *argv[])
-{
- termkey_t *tk;
- termkey_key_t key;
- const char *endp;
-
-#define CLEAR_KEY do { key.type = -1; key.code.codepoint = -1; \
- key.modifiers = -1; key.multibyte[0] = 0; } while (0)
-
- plan_tests (62);
-
- tk = termkey_new_abstract ("vt100", NULL, 0);
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, "A", &key, 0);
- is_int (key.type, TERMKEY_TYPE_KEY, "key.type for unicode/A/0");
- is_int (key.code.codepoint, 'A', "key.code.codepoint for unicode/A/0");
- is_int (key.modifiers, 0, "key.modifiers for unicode/A/0");
- is_str (key.multibyte, "A", "key.multibyte for unicode/A/0");
- is_str (endp, "", "consumed entire input for unicode/A/0");
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, "A and more", &key, 0);
- is_int (key.type, TERMKEY_TYPE_KEY,
- "key.type for unicode/A/0 trailing");
- is_int (key.code.codepoint, 'A',
- "key.code.codepoint for unicode/A/0 trailing");
- is_int (key.modifiers, 0, "key.modifiers for unicode/A/0 trailing");
- is_str (key.multibyte, "A", "key.multibyte for unicode/A/0 trailing");
- is_str (endp, " and more",
- "points at string tail for unicode/A/0 trailing");
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, "C-b", &key, 0);
- is_int (key.type, TERMKEY_TYPE_KEY, "key.type for unicode/b/CTRL");
- is_int (key.code.codepoint, 'b', "key.code.codepoint for unicode/b/CTRL");
- is_int (key.modifiers, TERMKEY_KEYMOD_CTRL,
- "key.modifiers for unicode/b/CTRL");
- is_str (key.multibyte, "b", "key.multibyte for unicode/b/CTRL");
- is_str (endp, "", "consumed entire input for unicode/b/CTRL");
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, "Ctrl-b", &key, TERMKEY_FORMAT_LONGMOD);
- is_int (key.type, TERMKEY_TYPE_KEY,
- "key.type for unicode/b/CTRL longmod");
- is_int (key.code.codepoint, 'b',
- "key.code.codepoint for unicode/b/CTRL longmod");
- is_int (key.modifiers, TERMKEY_KEYMOD_CTRL,
- "key.modifiers for unicode/b/CTRL longmod");
- is_str (key.multibyte, "b", "key.multibyte for unicode/b/CTRL longmod");
- is_str (endp, "", "consumed entire input for unicode/b/CTRL longmod");
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, "^B", &key, TERMKEY_FORMAT_CARETCTRL);
- is_int (key.type, TERMKEY_TYPE_KEY,
- "key.type for unicode/b/CTRL caretctrl");
- is_int (key.code.codepoint, 'b',
- "key.code.codepoint for unicode/b/CTRL caretctrl");
- is_int (key.modifiers, TERMKEY_KEYMOD_CTRL,
- "key.modifiers for unicode/b/CTRL caretctrl");
- is_str (key.multibyte, "b", "key.multibyte for unicode/b/CTRL caretctrl");
- is_str (endp, "", "consumed entire input for unicode/b/CTRL caretctrl");
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, "A-c", &key, 0);
- is_int (key.type, TERMKEY_TYPE_KEY, "key.type for unicode/c/ALT");
- is_int (key.code.codepoint, 'c', "key.code.codepoint for unicode/c/ALT");
- is_int (key.modifiers, TERMKEY_KEYMOD_ALT,
- "key.modifiers for unicode/c/ALT");
- is_str (key.multibyte, "c", "key.multibyte for unicode/c/ALT");
- is_str (endp, "", "consumed entire input for unicode/c/ALT");
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, "Alt-c", &key, TERMKEY_FORMAT_LONGMOD);
- is_int (key.type, TERMKEY_TYPE_KEY,
- "key.type for unicode/c/ALT longmod");
- is_int (key.code.codepoint, 'c',
- "key.code.codepoint for unicode/c/ALT longmod");
- is_int (key.modifiers, TERMKEY_KEYMOD_ALT,
- "key.modifiers for unicode/c/ALT longmod");
- is_str (key.multibyte, "c", "key.multibyte for unicode/c/ALT longmod");
- is_str (endp, "", "consumed entire input for unicode/c/ALT longmod");
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, "M-c", &key, TERMKEY_FORMAT_ALTISMETA);
- is_int (key.type, TERMKEY_TYPE_KEY,
- "key.type for unicode/c/ALT altismeta");
- is_int (key.code.codepoint, 'c',
- "key.code.codepoint for unicode/c/ALT altismeta");
- is_int (key.modifiers, TERMKEY_KEYMOD_ALT,
- "key.modifiers for unicode/c/ALT altismeta");
- is_str (key.multibyte, "c", "key.multibyte for unicode/c/ALT altismeta");
- is_str (endp, "", "consumed entire input for unicode/c/ALT altismeta");
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, "Meta-c", &key,
- TERMKEY_FORMAT_ALTISMETA | TERMKEY_FORMAT_LONGMOD);
- is_int (key.type, TERMKEY_TYPE_KEY,
- "key.type for unicode/c/ALT altismeta+longmod");
- is_int (key.code.codepoint, 'c',
- "key.code.codepoint for unicode/c/ALT altismeta+longmod");
- is_int (key.modifiers, TERMKEY_KEYMOD_ALT,
- "key.modifiers for unicode/c/ALT altismeta+longmod");
- is_str (key.multibyte, "c", "key.multibyte for unicode/c/ALT altismeta+longmod");
- is_str (endp, "",
- "consumed entire input for unicode/c/ALT altismeta+longmod");
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, "meta c", &key,
- TERMKEY_FORMAT_ALTISMETA | TERMKEY_FORMAT_LONGMOD
- | TERMKEY_FORMAT_SPACEMOD | TERMKEY_FORMAT_LOWERMOD);
- is_int (key.type, TERMKEY_TYPE_KEY,
- "key.type for unicode/c/ALT altismeta+long/space+lowermod");
- is_int (key.code.codepoint, 'c',
- "key.code.codepoint for unicode/c/ALT altismeta+long/space+lowermod");
- is_int (key.modifiers, TERMKEY_KEYMOD_ALT,
- "key.modifiers for unicode/c/ALT altismeta+long/space+lowermod");
- is_str (key.multibyte, "c",
- "key.multibyte for unicode/c/ALT altismeta+long/space_lowermod");
- is_str (endp, "",
- "consumed entire input for unicode/c/ALT altismeta+long/space+lowermod");
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, "ctrl alt page up", &key,
- TERMKEY_FORMAT_LONGMOD | TERMKEY_FORMAT_SPACEMOD
- | TERMKEY_FORMAT_LOWERMOD | TERMKEY_FORMAT_LOWERSPACE);
- is_int (key.type, TERMKEY_TYPE_KEYSYM,
- "key.type for sym/PageUp/CTRL+ALT long/space/lowermod+lowerspace");
- is_int (key.code.sym, TERMKEY_SYM_PAGEUP,
- "key.code.codepoint for sym/PageUp/CTRL+ALT long/space/lowermod+lowerspace");
- is_int (key.modifiers, TERMKEY_KEYMOD_ALT | TERMKEY_KEYMOD_CTRL,
- "key.modifiers for sym/PageUp/CTRL+ALT long/space/lowermod+lowerspace");
- is_str (endp, "",
- "consumed entire input for sym/PageUp/CTRL+ALT"
- " long/space/lowermod+lowerspace");
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, "Up", &key, 0);
- is_int (key.type, TERMKEY_TYPE_KEYSYM, "key.type for sym/Up/0");
- is_int (key.code.sym, TERMKEY_SYM_UP, "key.code.codepoint for sym/Up/0");
- is_int (key.modifiers, 0, "key.modifiers for sym/Up/0");
- is_str (endp, "", "consumed entire input for sym/Up/0");
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, "F5", &key, 0);
- is_int (key.type, TERMKEY_TYPE_FUNCTION, "key.type for func/5/0");
- is_int (key.code.number, 5, "key.code.number for func/5/0");
- is_int (key.modifiers, 0, "key.modifiers for func/5/0");
- is_str (endp, "", "consumed entire input for func/5/0");
-
- termkey_destroy (tk);
- return exit_status ();
-}
diff --git a/t/13cmpkey.c b/t/13cmpkey.c
deleted file mode 100644
index 1e12b5c..0000000
--- a/t/13cmpkey.c
+++ /dev/null
@@ -1,72 +0,0 @@
-#include "../termkey.h"
-#include "taplib.h"
-
-int
-main (int argc, char *argv[])
-{
- termkey_t *tk;
- termkey_key_t key1, key2;
-
- plan_tests (12);
-
- tk = termkey_new_abstract ("vt100", NULL, 0);
-
- key1.type = TERMKEY_TYPE_KEY;
- key1.code.codepoint = 'A';
- key1.modifiers = 0;
-
- is_int (termkey_keycmp (tk, &key1, &key1), 0, "cmpkey same structure");
-
- key2.type = TERMKEY_TYPE_KEY;
- key2.code.codepoint = 'A';
- key2.modifiers = 0;
-
- is_int (termkey_keycmp (tk, &key1, &key2), 0, "cmpkey identical structure");
-
- key2.modifiers = TERMKEY_KEYMOD_CTRL;
-
- ok (termkey_keycmp (tk, &key1, &key2) < 0,
- "cmpkey orders CTRL after nomod");
- ok (termkey_keycmp (tk, &key2, &key1) > 0,
- "cmpkey orders nomod before CTRL");
-
- key2.code.codepoint = 'B';
- key2.modifiers = 0;
-
- ok (termkey_keycmp (tk, &key1, &key2) < 0, "cmpkey orders 'B' after 'A'");
- ok (termkey_keycmp (tk, &key2, &key1) > 0, "cmpkey orders 'A' before 'B'");
-
- key1.modifiers = TERMKEY_KEYMOD_CTRL;
-
- ok (termkey_keycmp (tk, &key1, &key2) < 0,
- "cmpkey orders nomod 'B' after CTRL 'A'");
- ok (termkey_keycmp (tk, &key2, &key1) > 0,
- "cmpkey orders CTRL 'A' before nomod 'B'");
-
- key2.type = TERMKEY_TYPE_KEYSYM;
- key2.code.sym = TERMKEY_SYM_UP;
-
- ok (termkey_keycmp (tk, &key1, &key2) < 0,
- "cmpkey orders KEYSYM after KEY");
- ok (termkey_keycmp (tk, &key2, &key1) > 0,
- "cmpkey orders KEY before KEYSYM");
-
- key1.type = TERMKEY_TYPE_KEYSYM;
- key1.code.sym = TERMKEY_SYM_SPACE;
- key1.modifiers = 0;
- key2.type = TERMKEY_TYPE_KEY;
- key2.code.codepoint = ' ';
- key2.modifiers = 0;
-
- is_int (termkey_keycmp (tk, &key1, &key2), 0,
- "cmpkey considers KEYSYM/SPACE and KEY/SP identical");
-
- termkey_set_canonflags (tk,
- termkey_get_canonflags (tk) | TERMKEY_CANON_SPACESYMBOL);
- is_int (termkey_keycmp (tk, &key1, &key2), 0,
- "cmpkey considers KEYSYM/SPACE and KEY/SP"
- " identical under SPACESYMBOL");
-
- termkey_destroy (tk);
- return exit_status ();
-}
diff --git a/t/20canon.c b/t/20canon.c
deleted file mode 100644
index a60c2ef..0000000
--- a/t/20canon.c
+++ /dev/null
@@ -1,74 +0,0 @@
-#include "../termkey.h"
-#include "taplib.h"
-
-int
-main (int argc, char *argv[])
-{
- termkey_t *tk;
- termkey_key_t key;
- const char *endp;
-
-#define CLEAR_KEY do { key.type = -1; key.code.codepoint = -1; \
- key.modifiers = -1; key.multibyte[0] = 0; } while (0)
-
- plan_tests (26);
-
- tk = termkey_new_abstract ("vt100", NULL, 0);
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, " ", &key, 0);
- is_int (key.type, TERMKEY_TYPE_KEY, "key.type for SP/unicode");
- is_int (key.code.codepoint, ' ', "key.code.codepoint for SP/unicode");
- is_int (key.modifiers, 0, "key.modifiers for SP/unicode");
- is_str (key.multibyte, " ", "key.multibyte for SP/unicode");
- is_str (endp, "", "consumed entire input for SP/unicode");
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, "Space", &key, 0);
- is_int (key.type, TERMKEY_TYPE_KEY, "key.type for Space/unicode");
- is_int (key.code.codepoint, ' ', "key.code.codepoint for Space/unicode");
- is_int (key.modifiers, 0, "key.modifiers for Space/unicode");
- is_str (key.multibyte, " ", "key.multibyte for Space/unicode");
- is_str (endp, "", "consumed entire input for Space/unicode");
-
- termkey_set_canonflags (tk,
- termkey_get_canonflags (tk) | TERMKEY_CANON_SPACESYMBOL);
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, " ", &key, 0);
- is_int (key.type, TERMKEY_TYPE_KEYSYM, "key.type for SP/symbol");
- is_int (key.code.sym, TERMKEY_SYM_SPACE,
- "key.code.codepoint for SP/symbol");
- is_int (key.modifiers, 0, "key.modifiers for SP/symbol");
- is_str (endp, "", "consumed entire input for SP/symbol");
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, "Space", &key, 0);
- is_int (key.type, TERMKEY_TYPE_KEYSYM, "key.type for Space/symbol");
- is_int (key.code.sym, TERMKEY_SYM_SPACE,
- "key.code.codepoint for Space/symbol");
- is_int (key.modifiers, 0, "key.modifiers for Space/symbol");
- is_str (endp, "", "consumed entire input for Space/symbol");
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, "DEL", &key, 0);
- is_int (key.type, TERMKEY_TYPE_KEYSYM, "key.type for Del/unconverted");
- is_int (key.code.sym, TERMKEY_SYM_DEL,
- "key.code.codepoint for Del/unconverted");
- is_int (key.modifiers, 0, "key.modifiers for Del/unconverted");
- is_str (endp, "", "consumed entire input for Del/unconverted");
-
- termkey_set_canonflags (tk,
- termkey_get_canonflags (tk) | TERMKEY_CANON_DELBS);
-
- CLEAR_KEY;
- endp = termkey_strpkey (tk, "DEL", &key, 0);
- is_int (key.type, TERMKEY_TYPE_KEYSYM, "key.type for Del/as-backspace");
- is_int (key.code.sym, TERMKEY_SYM_BACKSPACE,
- "key.code.codepoint for Del/as-backspace");
- is_int (key.modifiers, 0, "key.modifiers for Del/as-backspace");
- is_str (endp, "", "consumed entire input for Del/as-backspace");
-
- termkey_destroy (tk);
- return exit_status ();
-}
diff --git a/t/30mouse.c b/t/30mouse.c
deleted file mode 100644
index e4f4b27..0000000
--- a/t/30mouse.c
+++ /dev/null
@@ -1,174 +0,0 @@
-#include "../termkey.h"
-#include "taplib.h"
-
-int
-main (int argc, char *argv[])
-{
- termkey_t *tk;
- termkey_key_t key;
- termkey_mouse_event_t ev;
- int button, line, col;
- char buffer[32];
- size_t len;
-
- plan_tests (60);
-
- tk = termkey_new_abstract ("vt100", NULL, 0);
-
- termkey_push_bytes (tk, "\e[M !!", 6);
-
- key.type = -1;
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY for mouse press");
-
- is_int (key.type, TERMKEY_TYPE_MOUSE, "key.type for mouse press");
-
- ev = -1; button = -1; line = -1; col = -1;
- is_int (termkey_interpret_mouse (tk, &key, &ev, &button, &line, &col),
- TERMKEY_RES_KEY, "interpret_mouse yields RES_KEY");
-
- is_int (ev, TERMKEY_MOUSE_PRESS, "mouse event for press");
- is_int (button, 1, "mouse button for press");
- is_int (line, 1, "mouse line for press");
- is_int (col, 1, "mouse column for press");
- is_int (key.modifiers, 0, "modifiers for press");
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key, 0);
- is_int (len, 13, "string length for press");
- is_str (buffer, "MousePress(1)", "string buffer for press");
-
- len = termkey_strfkey (tk, buffer, sizeof buffer,
- &key, TERMKEY_FORMAT_MOUSE_POS);
- is_int (len, 21, "string length for press");
- is_str (buffer, "MousePress(1) @ (1,1)", "string buffer for press");
-
- termkey_push_bytes (tk, "\e[M@\"!", 6);
-
- key.type = -1;
- ev = -1; button = -1; line = -1; col = -1;
- termkey_getkey (tk, &key);
- is_int (termkey_interpret_mouse (tk, &key, &ev, &button, &line, &col),
- TERMKEY_RES_KEY, "interpret_mouse yields RES_KEY");
-
- is_int (ev, TERMKEY_MOUSE_DRAG, "mouse event for drag");
- is_int (button, 1, "mouse button for drag");
- is_int (line, 1, "mouse line for drag");
- is_int (col, 2, "mouse column for drag");
- is_int (key.modifiers, 0, "modifiers for press");
-
- termkey_push_bytes (tk, "\e[M##!", 6);
-
- key.type = -1;
- ev = -1; button = -1; line = -1; col = -1;
- termkey_getkey (tk, &key);
- is_int (termkey_interpret_mouse (tk, &key, &ev, &button, &line, &col),
- TERMKEY_RES_KEY, "interpret_mouse yields RES_KEY");
-
- is_int (ev, TERMKEY_MOUSE_RELEASE, "mouse event for release");
- is_int (line, 1, "mouse line for release");
- is_int (col, 3, "mouse column for release");
- is_int (key.modifiers, 0, "modifiers for press");
-
- termkey_push_bytes (tk, "\e[M0++", 6);
-
- key.type = -1;
- ev = -1; button = -1; line = -1; col = -1;
- termkey_getkey (tk, &key);
- is_int (termkey_interpret_mouse (tk, &key, &ev, &button, &line, &col),
- TERMKEY_RES_KEY, "interpret_mouse yields RES_KEY");
-
- is_int (ev, TERMKEY_MOUSE_PRESS, "mouse event for Ctrl-press");
- is_int (button, 1, "mouse button for Ctrl-press");
- is_int (line, 11, "mouse line for Ctrl-press");
- is_int (col, 11, "mouse column for Ctrl-press");
- is_int (key.modifiers, TERMKEY_KEYMOD_CTRL, "modifiers for Ctrl-press");
-
- len = termkey_strfkey (tk, buffer, sizeof buffer, &key, 0);
- is_int (len, 15, "string length for Ctrl-press");
- is_str (buffer, "C-MousePress(1)", "string buffer for Ctrl-press");
-
- // rxvt protocol
- termkey_push_bytes (tk, "\e[0;20;20M", 10);
-
- key.type = -1;
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY for mouse press rxvt protocol");
-
- is_int (key.type, TERMKEY_TYPE_MOUSE,
- "key.type for mouse press rxvt protocol");
-
- is_int (termkey_interpret_mouse (tk, &key, &ev, &button, &line, &col),
- TERMKEY_RES_KEY, "interpret_mouse yields RES_KEY");
-
- is_int (ev, TERMKEY_MOUSE_PRESS, "mouse event for press rxvt protocol");
- is_int (button, 1, "mouse button for press rxvt protocol");
- is_int (line, 20, "mouse line for press rxvt protocol");
- is_int (col, 20, "mouse column for press rxvt protocol");
- is_int (key.modifiers, 0, "modifiers for press rxvt protocol");
-
- termkey_push_bytes (tk, "\e[3;20;20M", 10);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY for mouse release rxvt protocol");
-
- is_int (key.type, TERMKEY_TYPE_MOUSE,
- "key.type for mouse release rxvt protocol");
-
- ev = -1; button = -1; line = -1; col = -1;
- is_int (termkey_interpret_mouse (tk, &key, &ev, &button, &line, &col),
- TERMKEY_RES_KEY, "interpret_mouse yields RES_KEY");
-
- is_int (ev, TERMKEY_MOUSE_RELEASE, "mouse event for release rxvt protocol");
- is_int (line, 20, "mouse line for release rxvt protocol");
- is_int (col, 20, "mouse column for release rxvt protocol");
- is_int (key.modifiers, 0, "modifiers for release rxvt protocol");
-
- // SGR protocol
- termkey_push_bytes (tk, "\e[<0;30;30M", 11);
-
- key.type = -1;
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY for mouse press SGR encoding");
-
- is_int (key.type, TERMKEY_TYPE_MOUSE,
- "key.type for mouse press SGR encoding");
-
- ev = -1; button = -1; line = -1; col = -1;
- is_int (termkey_interpret_mouse (tk, &key, &ev, &button, &line, &col),
- TERMKEY_RES_KEY, "interpret_mouse yields RES_KEY");
-
- is_int (ev, TERMKEY_MOUSE_PRESS, "mouse event for press SGR");
- is_int (button, 1, "mouse button for press SGR");
- is_int (line, 30, "mouse line for press SGR");
- is_int (col, 30, "mouse column for press SGR");
- is_int (key.modifiers, 0, "modifiers for press SGR");
-
- termkey_push_bytes (tk, "\e[<0;30;30m", 11);
-
- key.type = -1;
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY for mouse release SGR encoding");
-
- is_int (key.type, TERMKEY_TYPE_MOUSE,
- "key.type for mouse release SGR encoding");
-
- ev = -1; button = -1; line = -1; col = -1;
- is_int (termkey_interpret_mouse (tk, &key, &ev, &button, &line, &col),
- TERMKEY_RES_KEY, "interpret_mouse yields RES_KEY");
-
- is_int (ev, TERMKEY_MOUSE_RELEASE, "mouse event for release SGR");
-
- termkey_push_bytes (tk, "\e[<0;500;300M", 13);
-
- key.type = -1;
- ev = -1; button = -1; line = -1; col = -1;
- termkey_getkey (tk, &key);
- termkey_interpret_mouse (tk, &key, &ev, &button, &line, &col);
-
- is_int (line, 300, "mouse line for press SGR wide");
- is_int (col, 500, "mouse column for press SGR wide");
-
- termkey_destroy (tk);
-
- return exit_status ();
-}
diff --git a/t/31position.c b/t/31position.c
deleted file mode 100644
index a62be7a..0000000
--- a/t/31position.c
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "../termkey.h"
-#include "taplib.h"
-
-int main (int argc, char *argv[])
-{
- termkey_t *tk;
- termkey_key_t key;
- int line, col;
-
- plan_tests (8);
-
- tk = termkey_new_abstract ("vt100", NULL, 0);
-
- termkey_push_bytes (tk, "\e[?15;7R", 8);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY for position report");
-
- is_int (key.type, TERMKEY_TYPE_POSITION, "key.type for position report");
-
- is_int (termkey_interpret_position (tk, &key, &line, &col), TERMKEY_RES_KEY,
- "interpret_position yields RES_KEY");
-
- is_int (line, 15, "line for position report");
- is_int (col, 7, "column for position report");
-
- /* A plain CSI R is likely to be though. This is tricky :/ */
- termkey_push_bytes (tk, "\e[R", 3);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY for ");
-
- is_int (key.type, TERMKEY_TYPE_FUNCTION, "key.type for ");
- is_int (key.code.number, 3, "key.code.number for ");
-
- termkey_destroy (tk);
- return exit_status ();
-}
diff --git a/t/32modereport.c b/t/32modereport.c
deleted file mode 100644
index 5d79725..0000000
--- a/t/32modereport.c
+++ /dev/null
@@ -1,45 +0,0 @@
-#include "../termkey.h"
-#include "taplib.h"
-
-int
-main (int argc, char *argv[])
-{
- termkey_t *tk;
- termkey_key_t key;
- int initial, mode, value;
-
- plan_tests (12);
-
- tk = termkey_new_abstract ("vt100", NULL, 0);
-
- termkey_push_bytes (tk, "\e[?1;2$y", 8);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY for mode report");
-
- is_int (key.type, TERMKEY_TYPE_MODEREPORT, "key.type for mode report");
-
- is_int (termkey_interpret_modereport (tk, &key, &initial, &mode, &value),
- TERMKEY_RES_KEY, "interpret_modereoprt yields RES_KEY");
-
- is_int (initial, '?', "initial indicator from mode report");
- is_int (mode, 1, "mode number from mode report");
- is_int (value, 2, "mode value from mode report");
-
- termkey_push_bytes (tk, "\e[4;1$y", 7);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY for mode report");
-
- is_int (key.type, TERMKEY_TYPE_MODEREPORT, "key.type for mode report");
-
- is_int (termkey_interpret_modereport (tk, &key, &initial, &mode, &value),
- TERMKEY_RES_KEY, "interpret_modereoprt yields RES_KEY");
-
- is_int (initial, 0, "initial indicator from mode report");
- is_int (mode, 4, "mode number from mode report");
- is_int (value, 1, "mode value from mode report");
-
- termkey_destroy (tk);
- return exit_status ();
-}
diff --git a/t/39csi.c b/t/39csi.c
deleted file mode 100644
index 32a15b0..0000000
--- a/t/39csi.c
+++ /dev/null
@@ -1,52 +0,0 @@
-#include "../termkey.h"
-#include "taplib.h"
-
-int
-main (int argc, char *argv[])
-{
- termkey_t *tk;
- termkey_key_t key;
- long args[16];
- size_t nargs = 16;
- unsigned long command;
-
- plan_tests (15);
-
- tk = termkey_new_abstract ("vt100", NULL, 0);
-
- termkey_push_bytes (tk, "\e[5;25v", 7);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY for CSI v");
-
- is_int (key.type, TERMKEY_TYPE_UNKNOWN_CSI, "key.type for unknown CSI");
-
- is_int (termkey_interpret_csi (tk, &key, args, &nargs, &command),
- TERMKEY_RES_KEY, "interpret_csi yields RES_KEY");
-
- is_int (nargs, 2, "nargs for unknown CSI");
- is_int (args[0], 5, "args[0] for unknown CSI");
- is_int (args[1], 25, "args[1] for unknown CSI");
- is_int (command, 'v', "command for unknown CSI");
-
- termkey_push_bytes (tk, "\e[?w", 4);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY for CSI ? w");
- is_int (key.type, TERMKEY_TYPE_UNKNOWN_CSI, "key.type for unknown CSI");
- is_int (termkey_interpret_csi (tk, &key, args, &nargs, &command),
- TERMKEY_RES_KEY, "interpret_csi yields RES_KEY");
- is_int (command, ('?' << 8) | 'w', "command for unknown CSI");
-
- termkey_push_bytes (tk, "\e[?$x", 5);
-
- is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
- "getkey yields RES_KEY for CSI ? $x");
- is_int (key.type, TERMKEY_TYPE_UNKNOWN_CSI, "key.type for unknown CSI");
- is_int (termkey_interpret_csi (tk, &key, args, &nargs, &command),
- TERMKEY_RES_KEY, "interpret_csi yields RES_KEY");
- is_int (command, ('$' << 16) | ('?' << 8) | 'x', "command for unknown CSI");
-
- termkey_destroy (tk);
- return exit_status ();
-}
diff --git a/t/taplib.c b/t/taplib.c
deleted file mode 100644
index bfb70f8..0000000
--- a/t/taplib.c
+++ /dev/null
@@ -1,79 +0,0 @@
-#include "taplib.h"
-
-#include
-#include
-#include
-
-static int g_nexttest = 1;
-static int g_exit_status = 0;
-
-void
-plan_tests (int n)
-{
- printf ("1..%d\n", n);
-}
-
-void
-pass (char *name)
-{
- printf ("ok %d - %s\n", g_nexttest++, name);
-}
-
-void
-fail (char *name)
-{
- printf ("not ok %d - %s\n", g_nexttest++, name);
- g_exit_status = 1;
-}
-
-void
-ok (int cmp, char *name)
-{
- if (cmp)
- pass (name);
- else
- fail (name);
-}
-
-void
-diag (char *fmt, ...)
-{
- va_list args;
- va_start (args, fmt);
-
- fprintf (stderr, "# ");
- vfprintf (stderr, fmt, args);
- fprintf (stderr, "\n");
-
- va_end (args);
-}
-
-void
-is_int (int got, int expect, char *name)
-{
- if (got == expect)
- ok (1, name);
- else
- {
- ok (0, name);
- diag ("got %d expected %d", got, expect);
- }
-}
-
-void
-is_str (const char *got, const char *expect, char *name)
-{
- if (strcmp (got, expect) == 0)
- ok (1, name);
- else
- {
- ok (0, name);
- diag ("got '%s' expected '%s'", got, expect);
- }
-}
-
-int
-exit_status(void)
-{
- return g_exit_status;
-}
diff --git a/t/taplib.h b/t/taplib.h
deleted file mode 100644
index 9045c32..0000000
--- a/t/taplib.h
+++ /dev/null
@@ -1,7 +0,0 @@
-void plan_tests (int n);
-void ok (int cmp, char *name);
-void pass (char *name);
-void fail (char *name);
-void is_int (int got, int expect, char *name);
-void is_str (const char *got, const char *expect, char *name);
-int exit_status (void);
diff --git a/termkey-internal.h b/termkey-internal.h
deleted file mode 100644
index 7282454..0000000
--- a/termkey-internal.h
+++ /dev/null
@@ -1,115 +0,0 @@
-#ifndef TERMKEY_INTERNAL_H
-#define TERMKEY_INTERNAL_H
-
-#include "termkey.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 = (unsigned char) key->code.mouse[1]
- | ((unsigned char) key->code.mouse[3] & 0x0f) << 8;
-
- if (line)
- *line = (unsigned char) key->code.mouse[2]
- | ((unsigned char) key->code.mouse[3] & 0x70) << 4;
-}
-
-static inline void
-termkey_key_set_linecol (termkey_key_t *key, int line, int col)
-{
- if (line > 0xfff)
- line = 0xfff;
-
- if (col > 0x7ff)
- col = 0x7ff;
-
- key->code.mouse[1] = (line & 0x0ff);
- key->code.mouse[2] = (col & 0x0ff);
- key->code.mouse[3] = (line & 0xf00) >> 8 | (col & 0x300) >> 4;
-}
-
-extern termkey_driver_t termkey_driver_csi;
-extern termkey_driver_t termkey_driver_ti;
-
-#endif // ! TERMKEY_INTERNAL_H
-
diff --git a/termkey.c b/termkey.c
deleted file mode 100644
index ad80657..0000000
--- a/termkey.c
+++ /dev/null
@@ -1,1556 +0,0 @@
-#include "termkey.h"
-#include "termkey-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 lowecase 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;
- }
-}
-
-static termkey_result_t
-peekkey_mouse (termkey_t *tk, termkey_key_t *key, size_t *nbytep)
-{
- if (tk->buffcount < 3)
- return TERMKEY_RES_AGAIN;
-
- key->type = TERMKEY_TYPE_MOUSE;
- key->code.mouse[0] = CHARAT (0) - 0x20;
- key->code.mouse[1] = CHARAT (1) - 0x20;
- key->code.mouse[2] = CHARAT (2) - 0x20;
- key->code.mouse[3] = 0;
-
- key->modifiers = (key->code.mouse[0] & 0x1c) >> 2;
- key->code.mouse[0] &= ~0x1c;
-
- *nbytep = 3;
- 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 = strncmp (key1.code.mouse, key2.code.mouse, 4);
- 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/termkey.h.in b/termkey.h.in
deleted file mode 100644
index 2a4fa8d..0000000
--- a/termkey.h.in
+++ /dev/null
@@ -1,272 +0,0 @@
-#ifndef TERMKEY_H
-#define TERMKEY_H
-
-#include
-#include
-#include
-
-#define TERMKEY_VERSION_MAJOR @@VERSION_MAJOR@@
-#define TERMKEY_VERSION_MINOR @@VERSION_MINOR@@
-
-#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 */
- char mouse[4]; /* TERMKEY_TYPE_MOUSE */
- /* opaque, see termkey_interpret_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 // ! TERMKEY_H
-
diff --git a/termkey.pc.in b/termkey.pc.in
deleted file mode 100644
index 31113be..0000000
--- a/termkey.pc.in
+++ /dev/null
@@ -1,8 +0,0 @@
-libdir=@LIBDIR@
-includedir=@INCDIR@
-
-Name: termkey
-Description: Abstract terminal key input library
-Version: @VERSION@
-Libs: -L${libdir} -ltermkey
-Cflags: -I${includedir}
diff --git a/termkey2-config.h.in b/termkey2-config.h.in
new file mode 100644
index 0000000..676a2c0
--- /dev/null
+++ b/termkey2-config.h.in
@@ -0,0 +1,8 @@
+#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
new file mode 100644
index 0000000..b76ba79
--- /dev/null
+++ b/termkey2-internal.h
@@ -0,0 +1,115 @@
+#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 = (unsigned char) key->code.mouse[1]
+ | ((unsigned char) key->code.mouse[3] & 0x0f) << 8;
+
+ if (line)
+ *line = (unsigned char) key->code.mouse[2]
+ | ((unsigned char) key->code.mouse[3] & 0x70) << 4;
+}
+
+static inline void
+termkey_key_set_linecol (termkey_key_t *key, int line, int col)
+{
+ if (line > 0xfff)
+ line = 0xfff;
+
+ if (col > 0x7ff)
+ col = 0x7ff;
+
+ key->code.mouse[1] = (line & 0x0ff);
+ key->code.mouse[2] = (col & 0x0ff);
+ key->code.mouse[3] = (line & 0xf00) >> 8 | (col & 0x300) >> 4;
+}
+
+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
new file mode 100644
index 0000000..e9b574c
--- /dev/null
+++ b/termkey2.c
@@ -0,0 +1,1556 @@
+#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;
+ }
+}
+
+static termkey_result_t
+peekkey_mouse (termkey_t *tk, termkey_key_t *key, size_t *nbytep)
+{
+ if (tk->buffcount < 3)
+ return TERMKEY_RES_AGAIN;
+
+ key->type = TERMKEY_TYPE_MOUSE;
+ key->code.mouse[0] = CHARAT (0) - 0x20;
+ key->code.mouse[1] = CHARAT (1) - 0x20;
+ key->code.mouse[2] = CHARAT (2) - 0x20;
+ key->code.mouse[3] = 0;
+
+ key->modifiers = (key->code.mouse[0] & 0x1c) >> 2;
+ key->code.mouse[0] &= ~0x1c;
+
+ *nbytep = 3;
+ 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 = strncmp (key1.code.mouse, key2.code.mouse, 4);
+ 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
new file mode 100644
index 0000000..9362215
--- /dev/null
+++ b/termkey2.h
@@ -0,0 +1,271 @@
+#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 */
+ char mouse[4]; /* TERMKEY_TYPE_MOUSE */
+ /* opaque, see termkey_interpret_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/tests/01base.c b/tests/01base.c
new file mode 100644
index 0000000..39e0e39
--- /dev/null
+++ b/tests/01base.c
@@ -0,0 +1,29 @@
+#include
+#include "../termkey.h"
+#include "taplib.h"
+
+int
+main (int argc, char *argv[])
+{
+ termkey_t *tk;
+
+ plan_tests (6);
+
+ tk = termkey_new_abstract ("vt100", NULL, 0);
+ ok (!!tk, "termkey_new_abstract");
+ is_int (termkey_get_buffer_size (tk), 256, "termkey_get_buffer_size");
+ ok (termkey_is_started (tk), "termkey_is_started true after construction");
+
+ termkey_stop (tk);
+ ok (!termkey_is_started (tk),
+ "termkey_is_started false after termkey_stop()");
+
+ termkey_start (tk);
+ ok (termkey_is_started (tk),
+ "termkey_is_started true after termkey_start()");
+
+ termkey_destroy (tk);
+
+ ok (1, "termkey_free");
+ return exit_status ();
+}
diff --git a/tests/02getkey.c b/tests/02getkey.c
new file mode 100644
index 0000000..8cba991
--- /dev/null
+++ b/tests/02getkey.c
@@ -0,0 +1,92 @@
+#include "../termkey.h"
+#include "taplib.h"
+
+int
+main (int argc, char *argv[])
+{
+ termkey_t *tk;
+ termkey_key_t key;
+
+ plan_tests (31);
+
+ tk = termkey_new_abstract ("vt100", NULL, 0);
+
+ is_int (termkey_get_buffer_remaining (tk),
+ 256, "buffer free initially 256");
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_NONE,
+ "getkey yields RES_NONE when empty");
+
+ is_int (termkey_push_bytes (tk, "h", 1), 1, "push_bytes returns 1");
+
+ is_int (termkey_get_buffer_remaining (tk), 255,
+ "buffer free 255 after push_bytes");
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY after h");
+
+ is_int (key.type, TERMKEY_TYPE_KEY, "key.type after h");
+ is_int (key.code.codepoint, 'h', "key.code.codepoint after h");
+ is_int (key.modifiers, 0, "key.modifiers after h");
+ is_str (key.multibyte, "h", "key.multibyte after h");
+
+ is_int (termkey_get_buffer_remaining (tk), 256,
+ "buffer free 256 after getkey");
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_NONE,
+ "getkey yields RES_NONE a second time");
+
+ termkey_push_bytes (tk, "\x01", 1);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY after C-a");
+
+ is_int (key.type, TERMKEY_TYPE_KEY, "key.type after C-a");
+ is_int (key.code.codepoint, 'a', "key.code.codepoint after C-a");
+ is_int (key.modifiers, TERMKEY_KEYMOD_CTRL, "key.modifiers after C-a");
+
+ termkey_push_bytes (tk, "\033OA", 3);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY after Up");
+
+ is_int (key.type, TERMKEY_TYPE_KEYSYM, "key.type after Up");
+ is_int (key.code.sym, TERMKEY_SYM_UP, "key.code.sym after Up");
+ is_int (key.modifiers, 0, "key.modifiers after Up");
+
+ is_int (termkey_push_bytes (tk, "\033O", 2), 2, "push_bytes returns 2");
+
+ is_int (termkey_get_buffer_remaining (tk), 254,
+ "buffer free 254 after partial write");
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_AGAIN,
+ "getkey yields RES_AGAIN after partial write");
+
+ termkey_push_bytes (tk, "C", 1);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY after Right completion");
+
+ is_int (key.type, TERMKEY_TYPE_KEYSYM, "key.type after Right");
+ is_int (key.code.sym, TERMKEY_SYM_RIGHT, "key.code.sym after Right");
+ is_int (key.modifiers, 0, "key.modifiers after Right");
+
+ is_int (termkey_get_buffer_remaining (tk), 256,
+ "buffer free 256 after completion");
+
+ termkey_push_bytes (tk, "\033[27;5u", 7);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY after Ctrl-Escape");
+
+ is_int (key.type, TERMKEY_TYPE_KEYSYM,
+ "key.type after Ctrl-Escape");
+ is_int (key.code.sym, TERMKEY_SYM_ESCAPE,
+ "key.code.sym after Ctrl-Escape");
+ is_int (key.modifiers, TERMKEY_KEYMOD_CTRL,
+ "key.modifiers after Ctrl-Escape");
+
+ termkey_destroy (tk);
+
+ return exit_status ();
+}
diff --git a/tests/03utf8.c b/tests/03utf8.c
new file mode 100644
index 0000000..9b06e2e
--- /dev/null
+++ b/tests/03utf8.c
@@ -0,0 +1,188 @@
+#include "../termkey.h"
+#include "taplib.h"
+
+int
+main (int argc, char *argv[])
+{
+ termkey_t *tk;
+ termkey_key_t key;
+
+ plan_tests (33 /* 57 */);
+
+ tk = termkey_new_abstract ("vt100", "UTF-8", 0);
+
+ termkey_push_bytes (tk, "a", 1);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY low ASCII");
+ is_int (key.type, TERMKEY_TYPE_KEY, "key.type low ASCII");
+ is_int (key.code.codepoint, 'a', "key.code.codepoint low ASCII");
+
+ /* 2-byte UTF-8 range is U+0080 to U+07FF (0xDF 0xBF) */
+ /* However, we'd best avoid the C1 range, so we'll start at U+00A0 (0xC2 0xA0) */
+
+ termkey_push_bytes (tk, "\xC2\xA0", 2);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 2 low");
+ is_int (key.type, TERMKEY_TYPE_KEY, "key.type UTF-8 2 low");
+ is_int (key.code.codepoint, 0x00A0, "key.code.codepoint UTF-8 2 low");
+
+ termkey_push_bytes (tk, "\xDF\xBF", 2);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 2 high");
+ is_int (key.type, TERMKEY_TYPE_KEY, "key.type UTF-8 2 high");
+ is_int (key.code.codepoint, 0x07FF, "key.code.codepoint UTF-8 2 high");
+
+ /* 3-byte UTF-8 range is U+0800 (0xE0 0xA0 0x80) to U+FFFD (0xEF 0xBF 0xBD) */
+
+ termkey_push_bytes (tk, "\xE0\xA0\x80", 3);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 3 low");
+ is_int (key.type, TERMKEY_TYPE_KEY, "key.type UTF-8 3 low");
+ is_int (key.code.codepoint, 0x0800, "key.code.codepoint UTF-8 3 low");
+
+ termkey_push_bytes (tk, "\xEF\xBF\xBD", 3);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 3 high");
+ is_int (key.type, TERMKEY_TYPE_KEY, "key.type UTF-8 3 high");
+ is_int (key.code.codepoint, 0xFFFD, "key.code.codepoint UTF-8 3 high");
+
+ /* 4-byte UTF-8 range is U+10000 (0xF0 0x90 0x80 0x80) to U+10FFFF (0xF4 0x8F 0xBF 0xBF) */
+
+ termkey_push_bytes (tk, "\xF0\x90\x80\x80", 4);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 4 low");
+ is_int (key.type, TERMKEY_TYPE_KEY, "key.type UTF-8 4 low");
+ is_int (key.code.codepoint, 0x10000, "key.code.codepoint UTF-8 4 low");
+
+ termkey_push_bytes (tk, "\xF4\x8F\xBF\xBF", 4);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 4 high");
+ is_int (key.type, TERMKEY_TYPE_KEY, "key.type UTF-8 4 high");
+ is_int (key.code.codepoint, 0x10FFFF, "key.code.codepoint UTF-8 4 high");
+
+#if 0
+ /* XXX: With the move to iconv, this has changed significantly. */
+
+ /* Invalid continuations */
+
+ termkey_push_bytes (tk, "\xC2!", 2);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 2 invalid cont");
+ is_int (key.code.codepoint, 0xFFFD,
+ "key.code.codepoint UTF-8 2 invalid cont");
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 2 invalid after");
+ is_int (key.code.codepoint, '!',
+ "key.code.codepoint UTF-8 2 invalid after");
+
+ termkey_push_bytes (tk, "\xE0!", 2);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 3 invalid cont");
+ is_int (key.code.codepoint, 0xFFFD,
+ "key.code.codepoint UTF-8 3 invalid cont");
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 3 invalid after");
+ is_int (key.code.codepoint, '!',
+ "key.code.codepoint UTF-8 3 invalid after");
+
+ termkey_push_bytes (tk, "\xE0\xA0!", 3);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 3 invalid cont 2");
+ is_int (key.code.codepoint, 0xFFFD,
+ "key.code.codepoint UTF-8 3 invalid cont 2");
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 3 invalid after");
+ is_int (key.code.codepoint, '!',
+ "key.code.codepoint UTF-8 3 invalid after");
+
+ termkey_push_bytes (tk, "\xF0!", 2);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 4 invalid cont");
+ is_int (key.code.codepoint, 0xFFFD,
+ "key.code.codepoint UTF-8 4 invalid cont");
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 4 invalid after");
+ is_int (key.code.codepoint, '!',
+ "key.code.codepoint UTF-8 4 invalid after");
+
+ termkey_push_bytes (tk, "\xF0\x90!", 3);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 4 invalid cont 2");
+ is_int (key.code.codepoint, 0xFFFD,
+ "key.code.codepoint UTF-8 4 invalid cont 2");
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 4 invalid after");
+ is_int (key.code.codepoint, '!',
+ "key.code.codepoint UTF-8 4 invalid after");
+
+ termkey_push_bytes (tk, "\xF0\x90\x80!", 4);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 4 invalid cont 3");
+ is_int (key.code.codepoint, 0xFFFD,
+ "key.code.codepoint UTF-8 4 invalid cont 3");
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 4 invalid after");
+ is_int (key.code.codepoint, '!',
+ "key.code.codepoint UTF-8 4 invalid after");
+#endif
+
+ /* Partials */
+
+ termkey_push_bytes (tk, "\xC2", 1);
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_AGAIN,
+ "getkey yields RES_AGAIN UTF-8 2 partial");
+
+ termkey_push_bytes (tk, "\xA0", 1);
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 2 partial");
+ is_int (key.code.codepoint, 0x00A0,
+ "key.code.codepoint UTF-8 2 partial");
+
+ termkey_push_bytes (tk, "\xE0", 1);
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_AGAIN,
+ "getkey yields RES_AGAIN UTF-8 3 partial");
+
+ termkey_push_bytes (tk, "\xA0", 1);
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_AGAIN,
+ "getkey yields RES_AGAIN UTF-8 3 partial");
+
+ termkey_push_bytes (tk, "\x80", 1);
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 3 partial");
+ is_int (key.code.codepoint, 0x0800,
+ "key.code.codepoint UTF-8 3 partial");
+
+ termkey_push_bytes (tk, "\xF0", 1);
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_AGAIN,
+ "getkey yields RES_AGAIN UTF-8 4 partial");
+
+ termkey_push_bytes (tk, "\x90", 1);
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_AGAIN,
+ "getkey yields RES_AGAIN UTF-8 4 partial");
+
+ termkey_push_bytes (tk, "\x80", 1);
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_AGAIN,
+ "getkey yields RES_AGAIN UTF-8 4 partial");
+
+ termkey_push_bytes (tk, "\x80", 1);
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY UTF-8 4 partial");
+ is_int (key.code.codepoint, 0x10000,
+ "key.code.codepoint UTF-8 4 partial");
+
+ termkey_destroy (tk);
+ return exit_status ();
+}
diff --git a/tests/04flags.c b/tests/04flags.c
new file mode 100644
index 0000000..eb6e20b
--- /dev/null
+++ b/tests/04flags.c
@@ -0,0 +1,40 @@
+#include
+#include "../termkey.h"
+#include "taplib.h"
+
+int
+main (int argc, char *argv[])
+{
+ termkey_t *tk;
+ termkey_key_t key;
+
+ plan_tests (8);
+
+ tk = termkey_new_abstract ("vt100", NULL, 0);
+
+ termkey_push_bytes (tk, " ", 1);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY after space");
+
+ is_int (key.type, TERMKEY_TYPE_KEY, "key.type after space");
+ is_int (key.code.codepoint, ' ', "key.code.codepoint after space");
+ is_int (key.modifiers, 0, "key.modifiers after space");
+
+ termkey_set_flags (tk, TERMKEY_FLAG_SPACESYMBOL);
+
+ termkey_push_bytes (tk, " ", 1);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY after space");
+
+ is_int (key.type, TERMKEY_TYPE_KEYSYM,
+ "key.type after space with FLAG_SPACESYMBOL");
+ is_int (key.code.sym, TERMKEY_SYM_SPACE,
+ "key.code.sym after space with FLAG_SPACESYMBOL");
+ is_int (key.modifiers, 0,
+ "key.modifiers after space with FLAG_SPACESYMBOL");
+
+ termkey_destroy (tk);
+ return exit_status ();
+}
diff --git a/tests/05read.c b/tests/05read.c
new file mode 100644
index 0000000..2a5530a
--- /dev/null
+++ b/tests/05read.c
@@ -0,0 +1,85 @@
+#include
+#include
+#include "../termkey.h"
+#include "taplib.h"
+
+int
+main (int argc, char *argv[])
+{
+ int fd[2];
+ termkey_t *tk;
+ termkey_key_t key;
+
+ plan_tests (21);
+
+ /* We'll need a real filehandle we can write/read.
+ * pipe () can make us one */
+ pipe (fd);
+
+ /* Sanitise this just in case */
+ putenv ("TERM=vt100");
+
+ tk = termkey_new (fd[0], NULL, TERMKEY_FLAG_NOTERMIOS);
+
+ is_int (termkey_get_buffer_remaining (tk), 256,
+ "buffer free initially 256");
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_NONE,
+ "getkey yields RES_NONE when empty");
+
+ write (fd[1], "h", 1);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_NONE,
+ "getkey yields RES_NONE before advisereadable");
+
+ is_int (termkey_advisereadable (tk), TERMKEY_RES_AGAIN,
+ "advisereadable yields RES_AGAIN after h");
+
+ is_int (termkey_get_buffer_remaining (tk), 255,
+ "buffer free 255 after advisereadable");
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY after h");
+
+ is_int (key.type, TERMKEY_TYPE_KEY, "key.type after h");
+ is_int (key.code.codepoint, 'h', "key.code.codepoint after h");
+ is_int (key.modifiers, 0, "key.modifiers after h");
+ is_str (key.multibyte, "h", "key.multibyte after h");
+
+ is_int (termkey_get_buffer_remaining (tk), 256,
+ "buffer free 256 after getkey");
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_NONE,
+ "getkey yields RES_NONE a second time");
+
+ write (fd[1], "\033O", 2);
+ termkey_advisereadable (tk);
+
+ is_int (termkey_get_buffer_remaining (tk), 254,
+ "buffer free 254 after partial write");
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_AGAIN,
+ "getkey yields RES_AGAIN after partial write");
+
+ write (fd[1], "C", 1);
+ termkey_advisereadable (tk);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY after Right completion");
+
+ is_int (key.type, TERMKEY_TYPE_KEYSYM, "key.type after Right");
+ is_int (key.code.sym, TERMKEY_SYM_RIGHT, "key.code.sym after Right");
+ is_int (key.modifiers, 0, "key.modifiers after Right");
+
+ is_int (termkey_get_buffer_remaining (tk), 256,
+ "buffer free 256 after completion");
+
+ termkey_stop (tk);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_ERROR,
+ "getkey yields RES_ERROR after termkey_stop ()");
+ is_int (errno, EINVAL, "getkey error is EINVAL");
+
+ termkey_destroy (tk);
+ return exit_status ();
+}
diff --git a/tests/06buffer.c b/tests/06buffer.c
new file mode 100644
index 0000000..af415b6
--- /dev/null
+++ b/tests/06buffer.c
@@ -0,0 +1,38 @@
+#include
+#include "../termkey.h"
+#include "taplib.h"
+
+int main (int argc, char *argv[])
+{
+ termkey_t *tk;
+ termkey_key_t key;
+
+ plan_tests (9);
+
+ tk = termkey_new_abstract ("vt100", NULL, 0);
+
+ is_int (termkey_get_buffer_remaining (tk), 256,
+ "buffer free initially 256");
+ is_int (termkey_get_buffer_size (tk), 256,
+ "buffer size initially 256");
+
+ is_int (termkey_push_bytes (tk, "h", 1), 1, "push_bytes returns 1");
+
+ is_int (termkey_get_buffer_remaining (tk), 255,
+ "buffer free 255 after push_bytes");
+ is_int (termkey_get_buffer_size (tk), 256,
+ "buffer size 256 after push_bytes");
+
+ ok (!!termkey_set_buffer_size (tk, 512), "buffer set size OK");
+
+ is_int (termkey_get_buffer_remaining (tk), 511,
+ "buffer free 511 after push_bytes");
+ is_int (termkey_get_buffer_size (tk), 512,
+ "buffer size 512 after push_bytes");
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "buffered key still useable after resize");
+
+ termkey_destroy (tk);
+ return exit_status ();
+}
diff --git a/tests/10keyname.c b/tests/10keyname.c
new file mode 100644
index 0000000..20ac000
--- /dev/null
+++ b/tests/10keyname.c
@@ -0,0 +1,40 @@
+#include "../termkey.h"
+#include "taplib.h"
+
+int
+main (int argc, char *argv[])
+{
+ termkey_t *tk;
+ termkey_sym_t sym;
+ const char *end;
+
+ plan_tests (10);
+
+ tk = termkey_new_abstract ("vt100", NULL, 0);
+
+ sym = termkey_keyname2sym (tk, "Space");
+ is_int (sym, TERMKEY_SYM_SPACE, "keyname2sym Space");
+
+ sym = termkey_keyname2sym (tk, "SomeUnknownKey");
+ is_int (sym, TERMKEY_SYM_UNKNOWN, "keyname2sym SomeUnknownKey");
+
+ end = termkey_lookup_keyname (tk, "Up", &sym);
+ ok (!!end, "termkey_get_keyname Up returns non-NULL");
+ is_str (end, "", "termkey_get_keyname Up return points at endofstring");
+ is_int (sym, TERMKEY_SYM_UP, "termkey_get_keyname Up yields Up symbol");
+
+ end = termkey_lookup_keyname (tk, "DownMore", &sym);
+ ok (!!end, "termkey_get_keyname DownMore returns non-NULL");
+ is_str (end, "More", "termkey_get_keyname DownMore return points at More");
+ is_int (sym, TERMKEY_SYM_DOWN,
+ "termkey_get_keyname DownMore yields Down symbol");
+
+ end = termkey_lookup_keyname (tk, "SomeUnknownKey", &sym);
+ ok (!end, "termkey_get_keyname SomeUnknownKey returns NULL");
+
+ is_str (termkey_get_keyname (tk, TERMKEY_SYM_SPACE), "Space",
+ "get_keyname SPACE");
+
+ termkey_destroy (tk);
+ return exit_status ();
+}
diff --git a/tests/11strfkey.c b/tests/11strfkey.c
new file mode 100644
index 0000000..4c77bdf
--- /dev/null
+++ b/tests/11strfkey.c
@@ -0,0 +1,151 @@
+#include "../termkey.h"
+#include "taplib.h"
+
+int
+main (int argc, char *argv[])
+{
+ termkey_t *tk;
+ termkey_key_t key;
+ char buffer[16];
+ size_t len;
+
+ plan_tests (44);
+
+ tk = termkey_new_abstract ("vt100", NULL, 0);
+
+ key.type = TERMKEY_TYPE_KEY;
+ key.code.codepoint = 'A';
+ key.modifiers = 0;
+ key.multibyte[0] = 0;
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key, 0);
+ is_int (len, 1, "length for unicode/A/0");
+ is_str (buffer, "A", "buffer for unicode/A/0");
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
+ TERMKEY_FORMAT_WRAPBRACKET);
+ is_int (len, 1, "length for unicode/A/0 wrapbracket");
+ is_str (buffer, "A", "buffer for unicode/A/0 wrapbracket");
+
+ key.type = TERMKEY_TYPE_KEY;
+ key.code.codepoint = 'b';
+ key.modifiers = TERMKEY_KEYMOD_CTRL;
+ key.multibyte[0] = 0;
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key, 0);
+ is_int (len, 3, "length for unicode/b/CTRL");
+ is_str (buffer, "C-b", "buffer for unicode/b/CTRL");
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
+ TERMKEY_FORMAT_LONGMOD);
+ is_int (len, 6, "length for unicode/b/CTRL longmod");
+ is_str (buffer, "Ctrl-b", "buffer for unicode/b/CTRL longmod");
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
+ TERMKEY_FORMAT_LONGMOD | TERMKEY_FORMAT_SPACEMOD);
+ is_int (len, 6, "length for unicode/b/CTRL longmod|spacemod");
+ is_str (buffer, "Ctrl b", "buffer for unicode/b/CTRL longmod|spacemod");
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
+ TERMKEY_FORMAT_LONGMOD | TERMKEY_FORMAT_LOWERMOD);
+ is_int (len, 6, "length for unicode/b/CTRL longmod|lowermod");
+ is_str (buffer, "ctrl-b", "buffer for unicode/b/CTRL longmod|lowermod");
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
+ TERMKEY_FORMAT_LONGMOD | TERMKEY_FORMAT_SPACEMOD
+ | TERMKEY_FORMAT_LOWERMOD);
+ is_int (len, 6, "length for unicode/b/CTRL longmod|spacemod|lowermode");
+ is_str (buffer, "ctrl b",
+ "buffer for unicode/b/CTRL longmod|spacemod|lowermode");
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
+ TERMKEY_FORMAT_CARETCTRL);
+ is_int (len, 2, "length for unicode/b/CTRL caretctrl");
+ is_str (buffer, "^B", "buffer for unicode/b/CTRL caretctrl");
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
+ TERMKEY_FORMAT_WRAPBRACKET);
+ is_int (len, 5, "length for unicode/b/CTRL wrapbracket");
+ is_str (buffer, "", "buffer for unicode/b/CTRL wrapbracket");
+
+ key.type = TERMKEY_TYPE_KEY;
+ key.code.codepoint = 'c';
+ key.modifiers = TERMKEY_KEYMOD_ALT;
+ key.multibyte[0] = 0;
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key, 0);
+ is_int (len, 3, "length for unicode/c/ALT");
+ is_str (buffer, "A-c", "buffer for unicode/c/ALT");
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
+ TERMKEY_FORMAT_LONGMOD);
+ is_int (len, 5, "length for unicode/c/ALT longmod");
+ is_str (buffer, "Alt-c", "buffer for unicode/c/ALT longmod");
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
+ TERMKEY_FORMAT_ALTISMETA);
+ is_int (len, 3, "length for unicode/c/ALT altismeta");
+ is_str (buffer, "M-c", "buffer for unicode/c/ALT altismeta");
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
+ TERMKEY_FORMAT_LONGMOD|TERMKEY_FORMAT_ALTISMETA);
+ is_int (len, 6, "length for unicode/c/ALT longmod|altismeta");
+ is_str (buffer, "Meta-c", "buffer for unicode/c/ALT longmod|altismeta");
+
+ key.type = TERMKEY_TYPE_KEYSYM;
+ key.code.sym = TERMKEY_SYM_UP;
+ key.modifiers = 0;
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key, 0);
+ is_int (len, 2, "length for sym/Up/0");
+ is_str (buffer, "Up", "buffer for sym/Up/0");
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
+ TERMKEY_FORMAT_WRAPBRACKET);
+ is_int (len, 4, "length for sym/Up/0 wrapbracket");
+ is_str (buffer, "", "buffer for sym/Up/0 wrapbracket");
+
+ key.type = TERMKEY_TYPE_KEYSYM;
+ key.code.sym = TERMKEY_SYM_PAGEUP;
+ key.modifiers = 0;
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key, 0);
+ is_int (len, 6, "length for sym/PageUp/0");
+ is_str (buffer, "PageUp", "buffer for sym/PageUp/0");
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
+ TERMKEY_FORMAT_LOWERSPACE);
+ is_int (len, 7, "length for sym/PageUp/0 lowerspace");
+ is_str (buffer, "page up", "buffer for sym/PageUp/0 lowerspace");
+
+ /* If size of buffer is too small,
+ * strfkey should return something consistent */
+ len = termkey_strfkey (tk, buffer, 4, &key, 0);
+ is_int (len, 6, "length for sym/PageUp/0");
+ is_str (buffer, "Pag", "buffer of len 4 for sym/PageUp/0");
+
+ len = termkey_strfkey (tk, buffer, 4, &key, TERMKEY_FORMAT_LOWERSPACE);
+ is_int (len, 7, "length for sym/PageUp/0 lowerspace");
+ is_str (buffer, "pag", "buffer of len 4 for sym/PageUp/0 lowerspace");
+
+ key.type = TERMKEY_TYPE_FUNCTION;
+ key.code.number = 5;
+ key.modifiers = 0;
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key, 0);
+ is_int (len, 2, "length for func/5/0");
+ is_str (buffer, "F5", "buffer for func/5/0");
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
+ TERMKEY_FORMAT_WRAPBRACKET);
+ is_int (len, 4, "length for func/5/0 wrapbracket");
+ is_str (buffer, "", "buffer for func/5/0 wrapbracket");
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key,
+ TERMKEY_FORMAT_LOWERSPACE);
+ is_int (len, 2, "length for func/5/0 lowerspace");
+ is_str (buffer, "f5", "buffer for func/5/0 lowerspace");
+
+ termkey_destroy (tk);
+ return exit_status ();
+}
diff --git a/tests/12strpkey.c b/tests/12strpkey.c
new file mode 100644
index 0000000..f67b67a
--- /dev/null
+++ b/tests/12strpkey.c
@@ -0,0 +1,157 @@
+#include "../termkey.h"
+#include "taplib.h"
+
+int
+main (int argc, char *argv[])
+{
+ termkey_t *tk;
+ termkey_key_t key;
+ const char *endp;
+
+#define CLEAR_KEY do { key.type = -1; key.code.codepoint = -1; \
+ key.modifiers = -1; key.multibyte[0] = 0; } while (0)
+
+ plan_tests (62);
+
+ tk = termkey_new_abstract ("vt100", NULL, 0);
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, "A", &key, 0);
+ is_int (key.type, TERMKEY_TYPE_KEY, "key.type for unicode/A/0");
+ is_int (key.code.codepoint, 'A', "key.code.codepoint for unicode/A/0");
+ is_int (key.modifiers, 0, "key.modifiers for unicode/A/0");
+ is_str (key.multibyte, "A", "key.multibyte for unicode/A/0");
+ is_str (endp, "", "consumed entire input for unicode/A/0");
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, "A and more", &key, 0);
+ is_int (key.type, TERMKEY_TYPE_KEY,
+ "key.type for unicode/A/0 trailing");
+ is_int (key.code.codepoint, 'A',
+ "key.code.codepoint for unicode/A/0 trailing");
+ is_int (key.modifiers, 0, "key.modifiers for unicode/A/0 trailing");
+ is_str (key.multibyte, "A", "key.multibyte for unicode/A/0 trailing");
+ is_str (endp, " and more",
+ "points at string tail for unicode/A/0 trailing");
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, "C-b", &key, 0);
+ is_int (key.type, TERMKEY_TYPE_KEY, "key.type for unicode/b/CTRL");
+ is_int (key.code.codepoint, 'b', "key.code.codepoint for unicode/b/CTRL");
+ is_int (key.modifiers, TERMKEY_KEYMOD_CTRL,
+ "key.modifiers for unicode/b/CTRL");
+ is_str (key.multibyte, "b", "key.multibyte for unicode/b/CTRL");
+ is_str (endp, "", "consumed entire input for unicode/b/CTRL");
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, "Ctrl-b", &key, TERMKEY_FORMAT_LONGMOD);
+ is_int (key.type, TERMKEY_TYPE_KEY,
+ "key.type for unicode/b/CTRL longmod");
+ is_int (key.code.codepoint, 'b',
+ "key.code.codepoint for unicode/b/CTRL longmod");
+ is_int (key.modifiers, TERMKEY_KEYMOD_CTRL,
+ "key.modifiers for unicode/b/CTRL longmod");
+ is_str (key.multibyte, "b", "key.multibyte for unicode/b/CTRL longmod");
+ is_str (endp, "", "consumed entire input for unicode/b/CTRL longmod");
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, "^B", &key, TERMKEY_FORMAT_CARETCTRL);
+ is_int (key.type, TERMKEY_TYPE_KEY,
+ "key.type for unicode/b/CTRL caretctrl");
+ is_int (key.code.codepoint, 'b',
+ "key.code.codepoint for unicode/b/CTRL caretctrl");
+ is_int (key.modifiers, TERMKEY_KEYMOD_CTRL,
+ "key.modifiers for unicode/b/CTRL caretctrl");
+ is_str (key.multibyte, "b", "key.multibyte for unicode/b/CTRL caretctrl");
+ is_str (endp, "", "consumed entire input for unicode/b/CTRL caretctrl");
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, "A-c", &key, 0);
+ is_int (key.type, TERMKEY_TYPE_KEY, "key.type for unicode/c/ALT");
+ is_int (key.code.codepoint, 'c', "key.code.codepoint for unicode/c/ALT");
+ is_int (key.modifiers, TERMKEY_KEYMOD_ALT,
+ "key.modifiers for unicode/c/ALT");
+ is_str (key.multibyte, "c", "key.multibyte for unicode/c/ALT");
+ is_str (endp, "", "consumed entire input for unicode/c/ALT");
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, "Alt-c", &key, TERMKEY_FORMAT_LONGMOD);
+ is_int (key.type, TERMKEY_TYPE_KEY,
+ "key.type for unicode/c/ALT longmod");
+ is_int (key.code.codepoint, 'c',
+ "key.code.codepoint for unicode/c/ALT longmod");
+ is_int (key.modifiers, TERMKEY_KEYMOD_ALT,
+ "key.modifiers for unicode/c/ALT longmod");
+ is_str (key.multibyte, "c", "key.multibyte for unicode/c/ALT longmod");
+ is_str (endp, "", "consumed entire input for unicode/c/ALT longmod");
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, "M-c", &key, TERMKEY_FORMAT_ALTISMETA);
+ is_int (key.type, TERMKEY_TYPE_KEY,
+ "key.type for unicode/c/ALT altismeta");
+ is_int (key.code.codepoint, 'c',
+ "key.code.codepoint for unicode/c/ALT altismeta");
+ is_int (key.modifiers, TERMKEY_KEYMOD_ALT,
+ "key.modifiers for unicode/c/ALT altismeta");
+ is_str (key.multibyte, "c", "key.multibyte for unicode/c/ALT altismeta");
+ is_str (endp, "", "consumed entire input for unicode/c/ALT altismeta");
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, "Meta-c", &key,
+ TERMKEY_FORMAT_ALTISMETA | TERMKEY_FORMAT_LONGMOD);
+ is_int (key.type, TERMKEY_TYPE_KEY,
+ "key.type for unicode/c/ALT altismeta+longmod");
+ is_int (key.code.codepoint, 'c',
+ "key.code.codepoint for unicode/c/ALT altismeta+longmod");
+ is_int (key.modifiers, TERMKEY_KEYMOD_ALT,
+ "key.modifiers for unicode/c/ALT altismeta+longmod");
+ is_str (key.multibyte, "c", "key.multibyte for unicode/c/ALT altismeta+longmod");
+ is_str (endp, "",
+ "consumed entire input for unicode/c/ALT altismeta+longmod");
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, "meta c", &key,
+ TERMKEY_FORMAT_ALTISMETA | TERMKEY_FORMAT_LONGMOD
+ | TERMKEY_FORMAT_SPACEMOD | TERMKEY_FORMAT_LOWERMOD);
+ is_int (key.type, TERMKEY_TYPE_KEY,
+ "key.type for unicode/c/ALT altismeta+long/space+lowermod");
+ is_int (key.code.codepoint, 'c',
+ "key.code.codepoint for unicode/c/ALT altismeta+long/space+lowermod");
+ is_int (key.modifiers, TERMKEY_KEYMOD_ALT,
+ "key.modifiers for unicode/c/ALT altismeta+long/space+lowermod");
+ is_str (key.multibyte, "c",
+ "key.multibyte for unicode/c/ALT altismeta+long/space_lowermod");
+ is_str (endp, "",
+ "consumed entire input for unicode/c/ALT altismeta+long/space+lowermod");
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, "ctrl alt page up", &key,
+ TERMKEY_FORMAT_LONGMOD | TERMKEY_FORMAT_SPACEMOD
+ | TERMKEY_FORMAT_LOWERMOD | TERMKEY_FORMAT_LOWERSPACE);
+ is_int (key.type, TERMKEY_TYPE_KEYSYM,
+ "key.type for sym/PageUp/CTRL+ALT long/space/lowermod+lowerspace");
+ is_int (key.code.sym, TERMKEY_SYM_PAGEUP,
+ "key.code.codepoint for sym/PageUp/CTRL+ALT long/space/lowermod+lowerspace");
+ is_int (key.modifiers, TERMKEY_KEYMOD_ALT | TERMKEY_KEYMOD_CTRL,
+ "key.modifiers for sym/PageUp/CTRL+ALT long/space/lowermod+lowerspace");
+ is_str (endp, "",
+ "consumed entire input for sym/PageUp/CTRL+ALT"
+ " long/space/lowermod+lowerspace");
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, "Up", &key, 0);
+ is_int (key.type, TERMKEY_TYPE_KEYSYM, "key.type for sym/Up/0");
+ is_int (key.code.sym, TERMKEY_SYM_UP, "key.code.codepoint for sym/Up/0");
+ is_int (key.modifiers, 0, "key.modifiers for sym/Up/0");
+ is_str (endp, "", "consumed entire input for sym/Up/0");
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, "F5", &key, 0);
+ is_int (key.type, TERMKEY_TYPE_FUNCTION, "key.type for func/5/0");
+ is_int (key.code.number, 5, "key.code.number for func/5/0");
+ is_int (key.modifiers, 0, "key.modifiers for func/5/0");
+ is_str (endp, "", "consumed entire input for func/5/0");
+
+ termkey_destroy (tk);
+ return exit_status ();
+}
diff --git a/tests/13cmpkey.c b/tests/13cmpkey.c
new file mode 100644
index 0000000..1e12b5c
--- /dev/null
+++ b/tests/13cmpkey.c
@@ -0,0 +1,72 @@
+#include "../termkey.h"
+#include "taplib.h"
+
+int
+main (int argc, char *argv[])
+{
+ termkey_t *tk;
+ termkey_key_t key1, key2;
+
+ plan_tests (12);
+
+ tk = termkey_new_abstract ("vt100", NULL, 0);
+
+ key1.type = TERMKEY_TYPE_KEY;
+ key1.code.codepoint = 'A';
+ key1.modifiers = 0;
+
+ is_int (termkey_keycmp (tk, &key1, &key1), 0, "cmpkey same structure");
+
+ key2.type = TERMKEY_TYPE_KEY;
+ key2.code.codepoint = 'A';
+ key2.modifiers = 0;
+
+ is_int (termkey_keycmp (tk, &key1, &key2), 0, "cmpkey identical structure");
+
+ key2.modifiers = TERMKEY_KEYMOD_CTRL;
+
+ ok (termkey_keycmp (tk, &key1, &key2) < 0,
+ "cmpkey orders CTRL after nomod");
+ ok (termkey_keycmp (tk, &key2, &key1) > 0,
+ "cmpkey orders nomod before CTRL");
+
+ key2.code.codepoint = 'B';
+ key2.modifiers = 0;
+
+ ok (termkey_keycmp (tk, &key1, &key2) < 0, "cmpkey orders 'B' after 'A'");
+ ok (termkey_keycmp (tk, &key2, &key1) > 0, "cmpkey orders 'A' before 'B'");
+
+ key1.modifiers = TERMKEY_KEYMOD_CTRL;
+
+ ok (termkey_keycmp (tk, &key1, &key2) < 0,
+ "cmpkey orders nomod 'B' after CTRL 'A'");
+ ok (termkey_keycmp (tk, &key2, &key1) > 0,
+ "cmpkey orders CTRL 'A' before nomod 'B'");
+
+ key2.type = TERMKEY_TYPE_KEYSYM;
+ key2.code.sym = TERMKEY_SYM_UP;
+
+ ok (termkey_keycmp (tk, &key1, &key2) < 0,
+ "cmpkey orders KEYSYM after KEY");
+ ok (termkey_keycmp (tk, &key2, &key1) > 0,
+ "cmpkey orders KEY before KEYSYM");
+
+ key1.type = TERMKEY_TYPE_KEYSYM;
+ key1.code.sym = TERMKEY_SYM_SPACE;
+ key1.modifiers = 0;
+ key2.type = TERMKEY_TYPE_KEY;
+ key2.code.codepoint = ' ';
+ key2.modifiers = 0;
+
+ is_int (termkey_keycmp (tk, &key1, &key2), 0,
+ "cmpkey considers KEYSYM/SPACE and KEY/SP identical");
+
+ termkey_set_canonflags (tk,
+ termkey_get_canonflags (tk) | TERMKEY_CANON_SPACESYMBOL);
+ is_int (termkey_keycmp (tk, &key1, &key2), 0,
+ "cmpkey considers KEYSYM/SPACE and KEY/SP"
+ " identical under SPACESYMBOL");
+
+ termkey_destroy (tk);
+ return exit_status ();
+}
diff --git a/tests/20canon.c b/tests/20canon.c
new file mode 100644
index 0000000..a60c2ef
--- /dev/null
+++ b/tests/20canon.c
@@ -0,0 +1,74 @@
+#include "../termkey.h"
+#include "taplib.h"
+
+int
+main (int argc, char *argv[])
+{
+ termkey_t *tk;
+ termkey_key_t key;
+ const char *endp;
+
+#define CLEAR_KEY do { key.type = -1; key.code.codepoint = -1; \
+ key.modifiers = -1; key.multibyte[0] = 0; } while (0)
+
+ plan_tests (26);
+
+ tk = termkey_new_abstract ("vt100", NULL, 0);
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, " ", &key, 0);
+ is_int (key.type, TERMKEY_TYPE_KEY, "key.type for SP/unicode");
+ is_int (key.code.codepoint, ' ', "key.code.codepoint for SP/unicode");
+ is_int (key.modifiers, 0, "key.modifiers for SP/unicode");
+ is_str (key.multibyte, " ", "key.multibyte for SP/unicode");
+ is_str (endp, "", "consumed entire input for SP/unicode");
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, "Space", &key, 0);
+ is_int (key.type, TERMKEY_TYPE_KEY, "key.type for Space/unicode");
+ is_int (key.code.codepoint, ' ', "key.code.codepoint for Space/unicode");
+ is_int (key.modifiers, 0, "key.modifiers for Space/unicode");
+ is_str (key.multibyte, " ", "key.multibyte for Space/unicode");
+ is_str (endp, "", "consumed entire input for Space/unicode");
+
+ termkey_set_canonflags (tk,
+ termkey_get_canonflags (tk) | TERMKEY_CANON_SPACESYMBOL);
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, " ", &key, 0);
+ is_int (key.type, TERMKEY_TYPE_KEYSYM, "key.type for SP/symbol");
+ is_int (key.code.sym, TERMKEY_SYM_SPACE,
+ "key.code.codepoint for SP/symbol");
+ is_int (key.modifiers, 0, "key.modifiers for SP/symbol");
+ is_str (endp, "", "consumed entire input for SP/symbol");
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, "Space", &key, 0);
+ is_int (key.type, TERMKEY_TYPE_KEYSYM, "key.type for Space/symbol");
+ is_int (key.code.sym, TERMKEY_SYM_SPACE,
+ "key.code.codepoint for Space/symbol");
+ is_int (key.modifiers, 0, "key.modifiers for Space/symbol");
+ is_str (endp, "", "consumed entire input for Space/symbol");
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, "DEL", &key, 0);
+ is_int (key.type, TERMKEY_TYPE_KEYSYM, "key.type for Del/unconverted");
+ is_int (key.code.sym, TERMKEY_SYM_DEL,
+ "key.code.codepoint for Del/unconverted");
+ is_int (key.modifiers, 0, "key.modifiers for Del/unconverted");
+ is_str (endp, "", "consumed entire input for Del/unconverted");
+
+ termkey_set_canonflags (tk,
+ termkey_get_canonflags (tk) | TERMKEY_CANON_DELBS);
+
+ CLEAR_KEY;
+ endp = termkey_strpkey (tk, "DEL", &key, 0);
+ is_int (key.type, TERMKEY_TYPE_KEYSYM, "key.type for Del/as-backspace");
+ is_int (key.code.sym, TERMKEY_SYM_BACKSPACE,
+ "key.code.codepoint for Del/as-backspace");
+ is_int (key.modifiers, 0, "key.modifiers for Del/as-backspace");
+ is_str (endp, "", "consumed entire input for Del/as-backspace");
+
+ termkey_destroy (tk);
+ return exit_status ();
+}
diff --git a/tests/30mouse.c b/tests/30mouse.c
new file mode 100644
index 0000000..e4f4b27
--- /dev/null
+++ b/tests/30mouse.c
@@ -0,0 +1,174 @@
+#include "../termkey.h"
+#include "taplib.h"
+
+int
+main (int argc, char *argv[])
+{
+ termkey_t *tk;
+ termkey_key_t key;
+ termkey_mouse_event_t ev;
+ int button, line, col;
+ char buffer[32];
+ size_t len;
+
+ plan_tests (60);
+
+ tk = termkey_new_abstract ("vt100", NULL, 0);
+
+ termkey_push_bytes (tk, "\e[M !!", 6);
+
+ key.type = -1;
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY for mouse press");
+
+ is_int (key.type, TERMKEY_TYPE_MOUSE, "key.type for mouse press");
+
+ ev = -1; button = -1; line = -1; col = -1;
+ is_int (termkey_interpret_mouse (tk, &key, &ev, &button, &line, &col),
+ TERMKEY_RES_KEY, "interpret_mouse yields RES_KEY");
+
+ is_int (ev, TERMKEY_MOUSE_PRESS, "mouse event for press");
+ is_int (button, 1, "mouse button for press");
+ is_int (line, 1, "mouse line for press");
+ is_int (col, 1, "mouse column for press");
+ is_int (key.modifiers, 0, "modifiers for press");
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key, 0);
+ is_int (len, 13, "string length for press");
+ is_str (buffer, "MousePress(1)", "string buffer for press");
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer,
+ &key, TERMKEY_FORMAT_MOUSE_POS);
+ is_int (len, 21, "string length for press");
+ is_str (buffer, "MousePress(1) @ (1,1)", "string buffer for press");
+
+ termkey_push_bytes (tk, "\e[M@\"!", 6);
+
+ key.type = -1;
+ ev = -1; button = -1; line = -1; col = -1;
+ termkey_getkey (tk, &key);
+ is_int (termkey_interpret_mouse (tk, &key, &ev, &button, &line, &col),
+ TERMKEY_RES_KEY, "interpret_mouse yields RES_KEY");
+
+ is_int (ev, TERMKEY_MOUSE_DRAG, "mouse event for drag");
+ is_int (button, 1, "mouse button for drag");
+ is_int (line, 1, "mouse line for drag");
+ is_int (col, 2, "mouse column for drag");
+ is_int (key.modifiers, 0, "modifiers for press");
+
+ termkey_push_bytes (tk, "\e[M##!", 6);
+
+ key.type = -1;
+ ev = -1; button = -1; line = -1; col = -1;
+ termkey_getkey (tk, &key);
+ is_int (termkey_interpret_mouse (tk, &key, &ev, &button, &line, &col),
+ TERMKEY_RES_KEY, "interpret_mouse yields RES_KEY");
+
+ is_int (ev, TERMKEY_MOUSE_RELEASE, "mouse event for release");
+ is_int (line, 1, "mouse line for release");
+ is_int (col, 3, "mouse column for release");
+ is_int (key.modifiers, 0, "modifiers for press");
+
+ termkey_push_bytes (tk, "\e[M0++", 6);
+
+ key.type = -1;
+ ev = -1; button = -1; line = -1; col = -1;
+ termkey_getkey (tk, &key);
+ is_int (termkey_interpret_mouse (tk, &key, &ev, &button, &line, &col),
+ TERMKEY_RES_KEY, "interpret_mouse yields RES_KEY");
+
+ is_int (ev, TERMKEY_MOUSE_PRESS, "mouse event for Ctrl-press");
+ is_int (button, 1, "mouse button for Ctrl-press");
+ is_int (line, 11, "mouse line for Ctrl-press");
+ is_int (col, 11, "mouse column for Ctrl-press");
+ is_int (key.modifiers, TERMKEY_KEYMOD_CTRL, "modifiers for Ctrl-press");
+
+ len = termkey_strfkey (tk, buffer, sizeof buffer, &key, 0);
+ is_int (len, 15, "string length for Ctrl-press");
+ is_str (buffer, "C-MousePress(1)", "string buffer for Ctrl-press");
+
+ // rxvt protocol
+ termkey_push_bytes (tk, "\e[0;20;20M", 10);
+
+ key.type = -1;
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY for mouse press rxvt protocol");
+
+ is_int (key.type, TERMKEY_TYPE_MOUSE,
+ "key.type for mouse press rxvt protocol");
+
+ is_int (termkey_interpret_mouse (tk, &key, &ev, &button, &line, &col),
+ TERMKEY_RES_KEY, "interpret_mouse yields RES_KEY");
+
+ is_int (ev, TERMKEY_MOUSE_PRESS, "mouse event for press rxvt protocol");
+ is_int (button, 1, "mouse button for press rxvt protocol");
+ is_int (line, 20, "mouse line for press rxvt protocol");
+ is_int (col, 20, "mouse column for press rxvt protocol");
+ is_int (key.modifiers, 0, "modifiers for press rxvt protocol");
+
+ termkey_push_bytes (tk, "\e[3;20;20M", 10);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY for mouse release rxvt protocol");
+
+ is_int (key.type, TERMKEY_TYPE_MOUSE,
+ "key.type for mouse release rxvt protocol");
+
+ ev = -1; button = -1; line = -1; col = -1;
+ is_int (termkey_interpret_mouse (tk, &key, &ev, &button, &line, &col),
+ TERMKEY_RES_KEY, "interpret_mouse yields RES_KEY");
+
+ is_int (ev, TERMKEY_MOUSE_RELEASE, "mouse event for release rxvt protocol");
+ is_int (line, 20, "mouse line for release rxvt protocol");
+ is_int (col, 20, "mouse column for release rxvt protocol");
+ is_int (key.modifiers, 0, "modifiers for release rxvt protocol");
+
+ // SGR protocol
+ termkey_push_bytes (tk, "\e[<0;30;30M", 11);
+
+ key.type = -1;
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY for mouse press SGR encoding");
+
+ is_int (key.type, TERMKEY_TYPE_MOUSE,
+ "key.type for mouse press SGR encoding");
+
+ ev = -1; button = -1; line = -1; col = -1;
+ is_int (termkey_interpret_mouse (tk, &key, &ev, &button, &line, &col),
+ TERMKEY_RES_KEY, "interpret_mouse yields RES_KEY");
+
+ is_int (ev, TERMKEY_MOUSE_PRESS, "mouse event for press SGR");
+ is_int (button, 1, "mouse button for press SGR");
+ is_int (line, 30, "mouse line for press SGR");
+ is_int (col, 30, "mouse column for press SGR");
+ is_int (key.modifiers, 0, "modifiers for press SGR");
+
+ termkey_push_bytes (tk, "\e[<0;30;30m", 11);
+
+ key.type = -1;
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY for mouse release SGR encoding");
+
+ is_int (key.type, TERMKEY_TYPE_MOUSE,
+ "key.type for mouse release SGR encoding");
+
+ ev = -1; button = -1; line = -1; col = -1;
+ is_int (termkey_interpret_mouse (tk, &key, &ev, &button, &line, &col),
+ TERMKEY_RES_KEY, "interpret_mouse yields RES_KEY");
+
+ is_int (ev, TERMKEY_MOUSE_RELEASE, "mouse event for release SGR");
+
+ termkey_push_bytes (tk, "\e[<0;500;300M", 13);
+
+ key.type = -1;
+ ev = -1; button = -1; line = -1; col = -1;
+ termkey_getkey (tk, &key);
+ termkey_interpret_mouse (tk, &key, &ev, &button, &line, &col);
+
+ is_int (line, 300, "mouse line for press SGR wide");
+ is_int (col, 500, "mouse column for press SGR wide");
+
+ termkey_destroy (tk);
+
+ return exit_status ();
+}
diff --git a/tests/31position.c b/tests/31position.c
new file mode 100644
index 0000000..a62be7a
--- /dev/null
+++ b/tests/31position.c
@@ -0,0 +1,38 @@
+#include "../termkey.h"
+#include "taplib.h"
+
+int main (int argc, char *argv[])
+{
+ termkey_t *tk;
+ termkey_key_t key;
+ int line, col;
+
+ plan_tests (8);
+
+ tk = termkey_new_abstract ("vt100", NULL, 0);
+
+ termkey_push_bytes (tk, "\e[?15;7R", 8);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY for position report");
+
+ is_int (key.type, TERMKEY_TYPE_POSITION, "key.type for position report");
+
+ is_int (termkey_interpret_position (tk, &key, &line, &col), TERMKEY_RES_KEY,
+ "interpret_position yields RES_KEY");
+
+ is_int (line, 15, "line for position report");
+ is_int (col, 7, "column for position report");
+
+ /* A plain CSI R is likely to be though. This is tricky :/ */
+ termkey_push_bytes (tk, "\e[R", 3);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY for ");
+
+ is_int (key.type, TERMKEY_TYPE_FUNCTION, "key.type for ");
+ is_int (key.code.number, 3, "key.code.number for ");
+
+ termkey_destroy (tk);
+ return exit_status ();
+}
diff --git a/tests/32modereport.c b/tests/32modereport.c
new file mode 100644
index 0000000..5d79725
--- /dev/null
+++ b/tests/32modereport.c
@@ -0,0 +1,45 @@
+#include "../termkey.h"
+#include "taplib.h"
+
+int
+main (int argc, char *argv[])
+{
+ termkey_t *tk;
+ termkey_key_t key;
+ int initial, mode, value;
+
+ plan_tests (12);
+
+ tk = termkey_new_abstract ("vt100", NULL, 0);
+
+ termkey_push_bytes (tk, "\e[?1;2$y", 8);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY for mode report");
+
+ is_int (key.type, TERMKEY_TYPE_MODEREPORT, "key.type for mode report");
+
+ is_int (termkey_interpret_modereport (tk, &key, &initial, &mode, &value),
+ TERMKEY_RES_KEY, "interpret_modereoprt yields RES_KEY");
+
+ is_int (initial, '?', "initial indicator from mode report");
+ is_int (mode, 1, "mode number from mode report");
+ is_int (value, 2, "mode value from mode report");
+
+ termkey_push_bytes (tk, "\e[4;1$y", 7);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY for mode report");
+
+ is_int (key.type, TERMKEY_TYPE_MODEREPORT, "key.type for mode report");
+
+ is_int (termkey_interpret_modereport (tk, &key, &initial, &mode, &value),
+ TERMKEY_RES_KEY, "interpret_modereoprt yields RES_KEY");
+
+ is_int (initial, 0, "initial indicator from mode report");
+ is_int (mode, 4, "mode number from mode report");
+ is_int (value, 1, "mode value from mode report");
+
+ termkey_destroy (tk);
+ return exit_status ();
+}
diff --git a/tests/39csi.c b/tests/39csi.c
new file mode 100644
index 0000000..32a15b0
--- /dev/null
+++ b/tests/39csi.c
@@ -0,0 +1,52 @@
+#include "../termkey.h"
+#include "taplib.h"
+
+int
+main (int argc, char *argv[])
+{
+ termkey_t *tk;
+ termkey_key_t key;
+ long args[16];
+ size_t nargs = 16;
+ unsigned long command;
+
+ plan_tests (15);
+
+ tk = termkey_new_abstract ("vt100", NULL, 0);
+
+ termkey_push_bytes (tk, "\e[5;25v", 7);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY for CSI v");
+
+ is_int (key.type, TERMKEY_TYPE_UNKNOWN_CSI, "key.type for unknown CSI");
+
+ is_int (termkey_interpret_csi (tk, &key, args, &nargs, &command),
+ TERMKEY_RES_KEY, "interpret_csi yields RES_KEY");
+
+ is_int (nargs, 2, "nargs for unknown CSI");
+ is_int (args[0], 5, "args[0] for unknown CSI");
+ is_int (args[1], 25, "args[1] for unknown CSI");
+ is_int (command, 'v', "command for unknown CSI");
+
+ termkey_push_bytes (tk, "\e[?w", 4);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY for CSI ? w");
+ is_int (key.type, TERMKEY_TYPE_UNKNOWN_CSI, "key.type for unknown CSI");
+ is_int (termkey_interpret_csi (tk, &key, args, &nargs, &command),
+ TERMKEY_RES_KEY, "interpret_csi yields RES_KEY");
+ is_int (command, ('?' << 8) | 'w', "command for unknown CSI");
+
+ termkey_push_bytes (tk, "\e[?$x", 5);
+
+ is_int (termkey_getkey (tk, &key), TERMKEY_RES_KEY,
+ "getkey yields RES_KEY for CSI ? $x");
+ is_int (key.type, TERMKEY_TYPE_UNKNOWN_CSI, "key.type for unknown CSI");
+ is_int (termkey_interpret_csi (tk, &key, args, &nargs, &command),
+ TERMKEY_RES_KEY, "interpret_csi yields RES_KEY");
+ is_int (command, ('$' << 16) | ('?' << 8) | 'x', "command for unknown CSI");
+
+ termkey_destroy (tk);
+ return exit_status ();
+}
diff --git a/tests/taplib.c b/tests/taplib.c
new file mode 100644
index 0000000..bfb70f8
--- /dev/null
+++ b/tests/taplib.c
@@ -0,0 +1,79 @@
+#include "taplib.h"
+
+#include
+#include
+#include
+
+static int g_nexttest = 1;
+static int g_exit_status = 0;
+
+void
+plan_tests (int n)
+{
+ printf ("1..%d\n", n);
+}
+
+void
+pass (char *name)
+{
+ printf ("ok %d - %s\n", g_nexttest++, name);
+}
+
+void
+fail (char *name)
+{
+ printf ("not ok %d - %s\n", g_nexttest++, name);
+ g_exit_status = 1;
+}
+
+void
+ok (int cmp, char *name)
+{
+ if (cmp)
+ pass (name);
+ else
+ fail (name);
+}
+
+void
+diag (char *fmt, ...)
+{
+ va_list args;
+ va_start (args, fmt);
+
+ fprintf (stderr, "# ");
+ vfprintf (stderr, fmt, args);
+ fprintf (stderr, "\n");
+
+ va_end (args);
+}
+
+void
+is_int (int got, int expect, char *name)
+{
+ if (got == expect)
+ ok (1, name);
+ else
+ {
+ ok (0, name);
+ diag ("got %d expected %d", got, expect);
+ }
+}
+
+void
+is_str (const char *got, const char *expect, char *name)
+{
+ if (strcmp (got, expect) == 0)
+ ok (1, name);
+ else
+ {
+ ok (0, name);
+ diag ("got '%s' expected '%s'", got, expect);
+ }
+}
+
+int
+exit_status(void)
+{
+ return g_exit_status;
+}
diff --git a/tests/taplib.h b/tests/taplib.h
new file mode 100644
index 0000000..9045c32
--- /dev/null
+++ b/tests/taplib.h
@@ -0,0 +1,7 @@
+void plan_tests (int n);
+void ok (int cmp, char *name);
+void pass (char *name);
+void fail (char *name);
+void is_int (int got, int expect, char *name);
+void is_str (const char *got, const char *expect, char *name);
+int exit_status (void);
--
cgit v1.2.3-70-g09d2