Hello community,

here is the log from the commit of package libtermkey for openSUSE:Factory 
checked in at 2020-10-29 09:22:51
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libtermkey (Old)
 and      /work/SRC/openSUSE:Factory/.libtermkey.new.3463 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libtermkey"

Thu Oct 29 09:22:51 2020 rev:4 rq:844623 version:0.22

Changes:
--------
--- /work/SRC/openSUSE:Factory/libtermkey/libtermkey.changes    2018-11-09 
07:54:50.183682492 +0100
+++ /work/SRC/openSUSE:Factory/.libtermkey.new.3463/libtermkey.changes  
2020-10-29 09:22:56.746724543 +0100
@@ -1,0 +2,7 @@
+Thu Oct 22 14:47:38 UTC 2020 - Dirk Stoecker <[email protected]> 0.22
+
+- update to 0.22
+  0.22   - changes: bugfixes for unit tests on BSD platforms
+  0.21.1 - changes: internal bugfixes, valgrind neatness
+
+-------------------------------------------------------------------

Old:
----
  libtermkey-0.20.tar.gz

New:
----
  libtermkey-0.22.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libtermkey.spec ++++++
--- /var/tmp/diff_new_pack.JneClt/_old  2020-10-29 09:22:57.298725072 +0100
+++ /var/tmp/diff_new_pack.JneClt/_new  2020-10-29 09:22:57.302725076 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package libtermkey
 #
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,12 +18,12 @@
 
 %define sover 1
 Name:           libtermkey
-Version:        0.20
+Version:        0.22
 Release:        0
 Summary:        Library for processing of keyboard entry from terminal-based 
programs
 License:        MIT
 Group:          Development/Libraries/C and C++
-Url:            http://www.leonerd.org.uk/code/libtermkey/
+URL:            http://www.leonerd.org.uk/code/libtermkey/
 Source:         
http://www.leonerd.org.uk/code/libtermkey/libtermkey-%{version}.tar.gz
 Patch0:         fix-syntax.patch
 BuildRequires:  gcc
@@ -91,7 +91,7 @@
 
 %files -n %{name}%{sover}
 %defattr(-,root,root)
-%doc LICENSE
+%license LICENSE
 %{_libdir}/libtermkey.so.%{sover}
 %{_libdir}/libtermkey.so.%{sover}.*
 

++++++ libtermkey-0.20.tar.gz -> libtermkey-0.22.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/Makefile new/libtermkey-0.22/Makefile
--- old/libtermkey-0.20/Makefile        2017-03-30 15:17:09.000000000 +0200
+++ new/libtermkey-0.22/Makefile        2019-03-14 14:47:10.000000000 +0100
@@ -49,10 +49,12 @@
 TESTFILES=$(TESTSOURCES:.c=.t)
 
 VERSION_MAJOR=0
-VERSION_MINOR=20
+VERSION_MINOR=22
+
+VERSION=$(VERSION_MAJOR).$(VERSION_MINOR)
 
 VERSION_CURRENT=15
-VERSION_REVISION=0
+VERSION_REVISION=2
 VERSION_AGE=14
 
 PREFIX=/usr/local
@@ -110,7 +112,7 @@
        install -d $(DESTDIR)$(INCDIR)
        install -m644 termkey.h $(DESTDIR)$(INCDIR)
        install -d $(DESTDIR)$(LIBDIR)/pkgconfig
-       sed "s,@LIBDIR@,$(LIBDIR),;s,@INCDIR@,$(INCDIR)," <termkey.pc.in 
>$(DESTDIR)$(LIBDIR)/pkgconfig/termkey.pc
+       LIBDIR=$(LIBDIR) INCDIR=$(INCDIR) VERSION=$(VERSION) sh termkey.pc.sh 
>$(DESTDIR)$(LIBDIR)/pkgconfig/termkey.pc
 
 install-lib: $(LIBRARY)
        install -d $(DESTDIR)$(LIBDIR)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/driver-csi.c 
new/libtermkey-0.22/driver-csi.c
--- old/libtermkey-0.20/driver-csi.c    2017-03-30 15:17:09.000000000 +0200
+++ new/libtermkey-0.22/driver-csi.c    2019-03-14 14:47:10.000000000 +0100
@@ -158,7 +158,7 @@
 }
 
 /*
- * Handler for CSI M / CSI m mouse events in SRG and rxvt encodings
+ * Handler for CSI M / CSI m mouse events in SGR and rxvt encodings
  * Note: This does not handle X10 encoding
  */
 
@@ -569,6 +569,9 @@
   if(result == TERMKEY_RES_NONE) {
 #ifdef DEBUG
     switch(args) {
+      case 0:
+        fprintf(stderr, "CSI: Unknown cmd=%c\n", (char)cmd);
+        break;
       case 1:
         fprintf(stderr, "CSI: Unknown arg1=%ld cmd=%c\n", arg[0], (char)cmd);
         break;
@@ -585,6 +588,7 @@
 #endif
     key->type = TERMKEY_TYPE_UNKNOWN_CSI;
     key->code.number = cmd;
+    key->modifiers = 0;
 
     tk->hightide = csi_len - introlen;
     *nbytep = introlen; // Do not yet eat the data bytes
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/driver-ti.c 
new/libtermkey-0.22/driver-ti.c
--- old/libtermkey-0.20/driver-ti.c     2017-03-30 15:17:09.000000000 +0200
+++ new/libtermkey-0.22/driver-ti.c     2019-03-14 14:47:10.000000000 +0100
@@ -10,17 +10,97 @@
 # include <curses.h>
 # include <term.h>
 
-/* curses.h has just poluted our namespace. We want this back */
+/* curses.h has just polluted our namespace. We want this back */
 # undef buttons
 #endif
 
 #include <ctype.h>
+#include <errno.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
-#include <unistd.h>
+#ifndef _WIN32
+# include <unistd.h>
+#endif
 #include <sys/types.h>
 #include <sys/stat.h>
 
+#define streq(a,b) (!strcmp(a,b))
+
+#define MAX_FUNCNAME 9
+
+static struct {
+  const char *funcname;
+  TermKeyType type;
+  TermKeySym sym;
+  int mods;
+} funcs[] =
+{
+  /* THIS LIST MUST REMAIN SORTED! */
+  { "backspace", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BACKSPACE, 0 },
+  { "begin",     TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN,     0 },
+  { "beg",       TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN,     0 },
+  { "btab",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_TAB,       
TERMKEY_KEYMOD_SHIFT },
+  { "cancel",    TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_CANCEL,    0 },
+  { "clear",     TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_CLEAR,     0 },
+  { "close",     TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_CLOSE,     0 },
+  { "command",   TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_COMMAND,   0 },
+  { "copy",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_COPY,      0 },
+  { "dc",        TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DELETE,    0 },
+  { "down",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DOWN,      0 },
+  { "end",       TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_END,       0 },
+  { "enter",     TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_ENTER,     0 },
+  { "exit",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_EXIT,      0 },
+  { "find",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_FIND,      0 },
+  { "help",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HELP,      0 },
+  { "home",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HOME,      0 },
+  { "ic",        TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_INSERT,    0 },
+  { "left",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_LEFT,      0 },
+  { "mark",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MARK,      0 },
+  { "message",   TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MESSAGE,   0 },
+  { "move",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MOVE,      0 },
+  { "next",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN,  0 }, // Not 
quite, but it's the best we can do
+  { "npage",     TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN,  0 },
+  { "open",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_OPEN,      0 },
+  { "options",   TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_OPTIONS,   0 },
+  { "ppage",     TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP,    0 },
+  { "previous",  TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP,    0 }, // Not 
quite, but it's the best we can do
+  { "print",     TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PRINT,     0 },
+  { "redo",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REDO,      0 },
+  { "reference", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REFERENCE, 0 },
+  { "refresh",   TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REFRESH,   0 },
+  { "replace",   TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REPLACE,   0 },
+  { "restart",   TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RESTART,   0 },
+  { "resume",    TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RESUME,    0 },
+  { "right",     TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RIGHT,     0 },
+  { "save",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SAVE,      0 },
+  { "select",    TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SELECT,    0 },
+  { "suspend",   TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SUSPEND,   0 },
+  { "undo",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UNDO,      0 },
+  { "up",        TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UP,        0 },
+  { NULL },
+};
+
+#ifdef HAVE_UNIBILIUM
+static enum unibi_string unibi_lookup_str(const char *name)
+{
+  for(enum unibi_string ret = unibi_string_begin_+1; ret < unibi_string_end_; 
ret++)
+    if(streq(unibi_name_str(ret), name))
+      return ret;
+
+  return -1;
+}
+
+static const char *unibi_get_str_by_name(const unibi_term *ut, const char 
*name)
+{
+  enum unibi_string idx = unibi_lookup_str(name);
+  if(idx == (enum unibi_string)-1)
+    return NULL;
+
+  return unibi_get_str(ut, idx);
+}
+#endif
+
 /* To be efficient at lookups, we store the byte sequence => keyinfo mapping
  * in a trie. This avoids a slow linear search through a flat list of
  * sequences. Because it is likely most nodes will be very sparse, we optimise
@@ -30,7 +110,6 @@
 typedef enum {
   TYPE_KEY,
   TYPE_ARR,
-  TYPE_MOUSE,
 } trie_nodetype;
 
 struct trie_node {
@@ -63,7 +142,6 @@
   char *stop_string;
 } TermKeyTI;
 
-static int funcname2keysym(const char *funcname, TermKeyType *typep, 
TermKeySym *symp, int *modmask, int *modsetp);
 static int insert_seq(TermKeyTI *ti, const char *seq, struct trie_node *node);
 
 static struct trie_node *new_node_key(TermKeyType type, TermKeySym sym, int 
modmask, int modset)
@@ -102,7 +180,6 @@
 {
   switch(n->type) {
   case TYPE_KEY:
-  case TYPE_MOUSE:
     fprintf(stderr, "ABORT: lookup_next within a TYPE_KEY node\n");
     abort();
   case TYPE_ARR:
@@ -121,7 +198,6 @@
 {
   switch(n->type) {
   case TYPE_KEY:
-  case TYPE_MOUSE:
     break;
   case TYPE_ARR:
     {
@@ -144,7 +220,6 @@
 
   switch(n->type) {
   case TYPE_KEY:
-  case TYPE_MOUSE:
     return n;
   case TYPE_ARR:
     {
@@ -152,7 +227,11 @@
       unsigned char min, max;
       // Find the real bounds
       for(min = 0; !nar->arr[min]; min++)
-        ;
+        if(min == 255 && !nar->arr[min]) {
+          free(nar);
+          return new_node_arr(1, 0);
+        }
+
       for(max = 0xff; !nar->arr[max]; max--)
         ;
 
@@ -169,6 +248,30 @@
   return n;
 }
 
+static bool try_load_terminfo_key(TermKeyTI *ti, const char *name, struct 
keyinfo *info)
+{
+  const char *value = NULL;
+
+#ifdef HAVE_UNIBILIUM
+  if(ti->unibi)
+    value = unibi_get_str_by_name(ti->unibi, name);
+#else
+  if(ti->term)
+    value = tigetstr(name);
+#endif
+
+  if(ti->tk->ti_getstr_hook)
+    value = (ti->tk->ti_getstr_hook)(name, value, ti->tk->ti_getstr_hook_data);
+
+  if(!value || value == (char*)-1 || !value[0])
+    return false;
+
+  struct trie_node *node = new_node_key(info->type, info->sym, 
info->modifier_mask, info->modifier_set);
+  insert_seq(ti, value, node);
+
+  return true;
+}
+
 static int load_terminfo(TermKeyTI *ti)
 {
   int i;
@@ -190,70 +293,57 @@
   if(!ti->root)
     return 0;
 
-#ifdef HAVE_UNIBILIUM
-  for(i = unibi_string_begin_+1; i < unibi_string_end_; i++)
-#else
-  for(i = 0; strfnames[i]; i++)
-#endif
-  {
-    // Only care about the key_* constants
-#ifdef HAVE_UNIBILIUM
-    const char *name = unibi_name_str(i);
-#else
-    const char *name = strfnames[i];
-#endif
-    if(strncmp(name, "key_", 4) != 0)
-      continue;
-
-#ifdef HAVE_UNIBILIUM
-    const char *value = unibi_get_str(unibi, i);
-#else
-    const char *value = tigetstr(strnames[i]);
-#endif
-
-    if(ti->tk->ti_getstr_hook)
-      value = (ti->tk->ti_getstr_hook)(name, value, 
ti->tk->ti_getstr_hook_data);
+  /* First the regular key strings
+   */
+  for(i = 0; funcs[i].funcname; i++) {
+    char name[MAX_FUNCNAME + 5 + 1];
 
-    if(!value || value == (char*)-1)
+    sprintf(name, "key_%s", funcs[i].funcname);
+    if(!try_load_terminfo_key(ti, name, &(struct keyinfo){
+          .type = funcs[i].type,
+          .sym  = funcs[i].sym,
+          .modifier_mask = funcs[i].mods,
+          .modifier_set  = funcs[i].mods,
+      }))
       continue;
 
-    struct trie_node *node = NULL;
-
-    if(strcmp(name + 4, "mouse") == 0) {
-      node = malloc(sizeof(*node));
-      if(!node)
-        return 0;
-
-      node->type = TYPE_MOUSE;
-    }
-    else {
-      TermKeyType type;
-      TermKeySym sym;
-      int mask = 0;
-      int set  = 0;
-
-      if(!funcname2keysym(name + 4, &type, &sym, &mask, &set))
-        continue;
-
-      if(sym == TERMKEY_SYM_NONE)
-        continue;
-
-      node = new_node_key(type, sym, mask, set);
-    }
+    /* Maybe it has a shifted version */
+    sprintf(name, "key_s%s", funcs[i].funcname);
+    try_load_terminfo_key(ti, name, &(struct keyinfo){
+        .type = funcs[i].type,
+        .sym  = funcs[i].sym,
+        .modifier_mask = funcs[i].mods | TERMKEY_KEYMOD_SHIFT,
+        .modifier_set  = funcs[i].mods | TERMKEY_KEYMOD_SHIFT,
+    });
+  }
 
-    if(node)
-      if(!insert_seq(ti, value, node)) {
-        free(node);
-        return 0;
-      }
+  /* Now the F<digit> keys
+   */
+  for(i = 1; i < 255; i++) {
+    char name[9];
+    sprintf(name, "key_f%d", i);
+    if(!try_load_terminfo_key(ti, name, &(struct keyinfo){
+          .type = TERMKEY_TYPE_FUNCTION,
+          .sym  = i,
+          .modifier_mask = 0,
+          .modifier_set  = 0,
+      }))
+      break;
   }
 
+  /* Finally mouse mode */
+  try_load_terminfo_key(ti, "key_mouse", &(struct keyinfo){
+      .type = TERMKEY_TYPE_MOUSE,
+  });
+
   /* Take copies of these terminfo strings, in case we build multiple termkey
    * instances for multiple different termtypes, and it's different by the
    * time we want to use it
    */
 #ifdef HAVE_UNIBILIUM
-  const char *keypad_xmit = unibi_get_str(unibi, unibi_keypad_xmit);
+  const char *keypad_xmit = unibi ?
+    unibi_get_str(unibi, unibi_keypad_xmit) :
+    NULL;
 #endif
 
   if(keypad_xmit)
@@ -262,7 +352,9 @@
     ti->start_string = NULL;
 
 #ifdef HAVE_UNIBILIUM
-  const char *keypad_local = unibi_get_str(unibi, unibi_keypad_local);
+  const char *keypad_local = unibi ?
+    unibi_get_str(unibi, unibi_keypad_local) :
+    NULL;
 #endif
 
   if(keypad_local)
@@ -271,9 +363,15 @@
     ti->stop_string = NULL;
 
 #ifdef HAVE_UNIBILIUM
-  unibi_destroy(unibi);
+  if(unibi)
+    unibi_destroy(unibi);
+
+  ti->unibi = NULL;
 #else
-  free(ti->term);
+  if(ti->term)
+    free(ti->term);
+
+  ti->term = NULL;
 #endif
 
   ti->root = compress_trie(ti->root);
@@ -289,30 +387,34 @@
 
   ti->tk = tk;
   ti->root = NULL;
+  ti->start_string = NULL;
+  ti->stop_string = NULL;
 
 #ifdef HAVE_UNIBILIUM
   ti->unibi = unibi_from_term(term);
-  if(!ti->unibi)
-    goto abort_free;
+  int saved_errno = errno;
+  if(!ti->unibi && saved_errno != ENOENT) {
+    free(ti);
+    return NULL;
+  }
+  /* ti->unibi may be NULL if errno == ENOENT. That means the terminal wasn't
+   * known. Lets keep going because if we get getstr hook that might invent
+   * new strings for us
+   */
 #else
   {
     int err;
 
+    ti->term = NULL;
+
     /* Have to cast away the const. But it's OK - we know terminfo won't really
     * modify term */
-    if(setupterm((char*)term, 1, &err) != OK)
-      goto abort_free;
-
-    ti->term = strdup(term);
+    if(setupterm((char*)term, 1, &err) == OK)
+      ti->term = strdup(term);
   }
 #endif
 
   return ti;
-
-abort_free:
-  free(ti);
-
-  return NULL;
 }
 
 static int start_driver(TermKey *tk, void *info)
@@ -338,8 +440,10 @@
   if(fstat(tk->fd, &statbuf) == -1)
     return 0;
 
+#ifndef _WIN32
   if(S_ISFIFO(statbuf.st_mode))
     return 1;
+#endif
 
   // Can't call putp or tputs because they suck and don't give us fd control
   len = strlen(start_string);
@@ -367,8 +471,10 @@
   if(fstat(tk->fd, &statbuf) == -1)
     return 0;
 
+#ifndef _WIN32
   if(S_ISFIFO(statbuf.st_mode))
     return 1;
+#endif
 
   /* The terminfo database will contain keys in application cursor key mode.
    * We may need to enable that mode
@@ -398,6 +504,14 @@
   if(ti->stop_string)
     free(ti->stop_string);
 
+#ifdef HAVE_UNIBILIUM
+  if(ti->unibi)
+    unibi_destroy(ti->unibi);
+#else
+  if(ti->term)
+    free(ti->term);
+#endif
+
   free(ti);
 }
 
@@ -420,15 +534,11 @@
 
     pos++;
 
-    if(p->type == TYPE_KEY) {
-      struct trie_node_key *nk = (struct trie_node_key*)p;
-      key->type      = nk->key.type;
-      key->code.sym  = nk->key.sym;
-      key->modifiers = nk->key.modifier_set;
-      *nbytep = pos;
-      return TERMKEY_RES_KEY;
-    }
-    else if(p->type == TYPE_MOUSE) {
+    if(p->type != TYPE_KEY)
+      continue;
+
+    struct trie_node_key *nk = (struct trie_node_key*)p;
+    if(nk->key.type == TERMKEY_TYPE_MOUSE) {
       tk->buffstart += pos;
       tk->buffcount -= pos;
 
@@ -442,6 +552,12 @@
 
       return mouse_result;
     }
+
+    key->type      = nk->key.type;
+    key->code.sym  = nk->key.sym;
+    key->modifiers = nk->key.modifier_set;
+    *nbytep = pos;
+    return TERMKEY_RES_KEY;
   }
 
   // If p is not NULL then we hadn't walked off the end yet, so we have a
@@ -452,106 +568,6 @@
   return TERMKEY_RES_NONE;
 }
 
-static struct {
-  const char *funcname;
-  TermKeyType type;
-  TermKeySym sym;
-  int mods;
-} funcs[] =
-{
-  /* THIS LIST MUST REMAIN SORTED! */
-  { "backspace", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BACKSPACE, 0 },
-  { "begin",     TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN,     0 },
-  { "beg",       TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN,     0 },
-  { "btab",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_TAB,       
TERMKEY_KEYMOD_SHIFT },
-  { "cancel",    TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_CANCEL,    0 },
-  { "clear",     TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_CLEAR,     0 },
-  { "close",     TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_CLOSE,     0 },
-  { "command",   TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_COMMAND,   0 },
-  { "copy",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_COPY,      0 },
-  { "dc",        TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DELETE,    0 },
-  { "down",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DOWN,      0 },
-  { "end",       TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_END,       0 },
-  { "enter",     TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_ENTER,     0 },
-  { "exit",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_EXIT,      0 },
-  { "find",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_FIND,      0 },
-  { "help",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HELP,      0 },
-  { "home",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HOME,      0 },
-  { "ic",        TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_INSERT,    0 },
-  { "left",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_LEFT,      0 },
-  { "mark",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MARK,      0 },
-  { "message",   TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MESSAGE,   0 },
-  { "mouse",     TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_NONE,      0 },
-  { "move",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MOVE,      0 },
-  { "next",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN,  0 }, // Not 
quite, but it's the best we can do
-  { "npage",     TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN,  0 },
-  { "open",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_OPEN,      0 },
-  { "options",   TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_OPTIONS,   0 },
-  { "ppage",     TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP,    0 },
-  { "previous",  TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP,    0 }, // Not 
quite, but it's the best we can do
-  { "print",     TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PRINT,     0 },
-  { "redo",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REDO,      0 },
-  { "reference", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REFERENCE, 0 },
-  { "refresh",   TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REFRESH,   0 },
-  { "replace",   TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REPLACE,   0 },
-  { "restart",   TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RESTART,   0 },
-  { "resume",    TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RESUME,    0 },
-  { "right",     TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RIGHT,     0 },
-  { "save",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SAVE,      0 },
-  { "select",    TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SELECT,    0 },
-  { "suspend",   TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SUSPEND,   0 },
-  { "undo",      TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UNDO,      0 },
-  { "up",        TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UP,        0 },
-  { NULL },
-};
-
-static int funcname2keysym(const char *funcname, TermKeyType *typep, 
TermKeySym *symp, int *modmaskp, int *modsetp)
-{
-  // Binary search
-
-  int start = 0;
-  int end   = sizeof(funcs)/sizeof(funcs[0]); // is "one past" the end of the 
range
-
-  while(1) {
-    int i = (start+end) / 2;
-    int cmp = strcmp(funcname, funcs[i].funcname);
-
-    if(cmp == 0) {
-      *typep    = funcs[i].type;
-      *symp     = funcs[i].sym;
-      *modmaskp = funcs[i].mods;
-      *modsetp  = funcs[i].mods;
-      return 1;
-    }
-    else if(end == start + 1)
-      // That was our last choice and it wasn't it - not found
-      break;
-    else if(cmp > 0)
-      start = i;
-    else
-      end = i;
-  }
-
-  if(funcname[0] == 'f' && isdigit(funcname[1])) {
-    *typep = TERMKEY_TYPE_FUNCTION;
-    *symp  = atoi(funcname + 1);
-    return 1;
-  }
-
-  // Last-ditch attempt; maybe it's a shift key?
-  if(funcname[0] == 's' && funcname2keysym(funcname + 1, typep, symp, 
modmaskp, modsetp)) {
-    *modmaskp |= TERMKEY_KEYMOD_SHIFT;
-    *modsetp  |= TERMKEY_KEYMOD_SHIFT;
-    return 1;
-  }
-
-#ifdef DEBUG
-  fprintf(stderr, "TODO: Need to convert funcname %s to a type/sym\n", 
funcname);
-#endif
-
-  return 0;
-}
-
 static int insert_seq(TermKeyTI *ti, const char *seq, struct trie_node *node)
 {
   int pos = 0;
@@ -594,7 +610,6 @@
         break;
       }
     case TYPE_KEY:
-    case TYPE_MOUSE:
       fprintf(stderr, "ASSERT FAIL: Tried to insert child node in TYPE_KEY\n");
       abort();
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/man/termkey.7 
new/libtermkey-0.22/man/termkey.7
--- old/libtermkey-0.20/man/termkey.7   2017-03-30 15:17:09.000000000 +0200
+++ new/libtermkey-0.22/man/termkey.7   2019-03-14 14:47:10.000000000 +0100
@@ -72,7 +72,7 @@
 .PP
 A pair of functions are also provided to convert between key events and 
strings. \fBtermkey_strfkey\fP(3) converts a key event into a string, and 
\fBtermkey_strpkey\fP(3) parses a string turning it into a key event.
 .PP
-Key events may be compared for equallity or ordering by using 
\fBtermkey_keycmp\fP(3).
+Key events may be compared for equality or ordering by using 
\fBtermkey_keycmp\fP(3).
 .SS Control Flags
 Details of the behaviour of a \fBtermkey\fP instance are controlled by two 
bitmasks of flags. \fBtermkey_set_flags\fP(3) and \fBtermkey_get_flags\fP(3) 
set or return the flags used to control the general behaviour, and 
\fBtermkey_set_canonflags\fP(3) and \fBtermkey_get_canonflags\fP(3) set or 
return the flags that control the key value canonicalisation behaviour 
performed by \fBtermkey_canonicalise\fP(3).
 .PP
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/man/termkey_advisereadable.3 
new/libtermkey-0.22/man/termkey_advisereadable.3
--- old/libtermkey-0.20/man/termkey_advisereadable.3    2017-03-30 
15:17:09.000000000 +0200
+++ new/libtermkey-0.22/man/termkey_advisereadable.3    2019-03-14 
14:47:10.000000000 +0100
@@ -25,7 +25,7 @@
 No nore bytes were read.
 .TP
 .B TERMKEY_RES_ERROR
-An IO error occured. \fIerrno\fP will be preserved. If the error is 
\fBEINTR\fP then this will only be returned if \fBTERMKEY_FLAG_EINTR\fP flag is 
not set; if it is then the IO operation will be retried instead.
+An IO error occurred. \fIerrno\fP will be preserved. If the error is 
\fBEINTR\fP then this will only be returned if \fBTERMKEY_FLAG_EINTR\fP flag is 
not set; if it is then the IO operation will be retried instead.
 .SH "SEE ALSO"
 .BR termkey_getkey (3),
 .BR termkey_waitkey (3),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/man/termkey_set_waittime.3 
new/libtermkey-0.22/man/termkey_set_waittime.3
--- old/libtermkey-0.20/man/termkey_set_waittime.3      2017-03-30 
15:17:09.000000000 +0200
+++ new/libtermkey-0.22/man/termkey_set_waittime.3      2019-03-14 
14:47:10.000000000 +0100
@@ -11,11 +11,11 @@
 .sp
 Link with \fI-ltermkey\fP.
 .SH DESCRIPTION
-\fBtermkey_set_waittime\fP() sets the number of miliseconds that 
\fBtermkey_waitkey\fP(3) will wait for the remaining bytes of a multibyte 
sequence if it detects the start of a partially-complete one.
+\fBtermkey_set_waittime\fP() sets the number of milliseconds that 
\fBtermkey_waitkey\fP(3) will wait for the remaining bytes of a multibyte 
sequence if it detects the start of a partially-complete one.
 .PP
 \fBtermkey_get_waittime\fP() returns the value set by the last call to 
\fBtermkey_set_waittime\fP(), or the default value if a different has not been 
set.
 .SH "RETURN VALUE"
-\fBtermkey_set_waittime\fP() returns no value. \fBtermkey_get_waittime\fP() 
returns the current wait time in miliseconds.
+\fBtermkey_set_waittime\fP() returns no value. \fBtermkey_get_waittime\fP() 
returns the current wait time in milliseconds.
 .SH "SEE ALSO"
 .BR termkey_getkey (3),
 .BR termkey_waitkey (3),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/man/termkey_strfkey.3 
new/libtermkey-0.22/man/termkey_strfkey.3
--- old/libtermkey-0.20/man/termkey_strfkey.3   2017-03-30 15:17:09.000000000 
+0200
+++ new/libtermkey-0.22/man/termkey_strfkey.3   2019-03-14 14:47:10.000000000 
+0100
@@ -47,7 +47,7 @@
 .B TERMKEY_FORMAT_URWID
 Shortcut to set \fBALTISMETA\fP, \fBLONGMOD\fP, \fBLOWERMOD\fP, \fBSPACEMOD\fP 
and \fBLOWERSPACE\fP, to give an output close to the format the \fIurwid\fP 
python library uses.
 .PP
-When formatting a \fBTERMKEY_TYPE_UNICODE\fP key structure, this function uses 
the \fIutf8\fP member. If this member contains an empty string (i.e. its first 
character is 0) then this member will be prefilled by the function from the 
\fIcode.number\fP member. This can be convenient when the key structure is 
being constructed programatically by user code.
+When formatting a \fBTERMKEY_TYPE_UNICODE\fP key structure, this function uses 
the \fIutf8\fP member. If this member contains an empty string (i.e. its first 
character is 0) then this member will be prefilled by the function from the 
\fIcode.number\fP member. This can be convenient when the key structure is 
being constructed programmatically by user code.
 .SH "RETURN VALUE"
 \fBtermkey_strfkey\fP() returns the number of characters written to 
\fIbuffer\fP.
 .SH "SEE ALSO"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/man/termkey_strpkey.3 
new/libtermkey-0.22/man/termkey_strpkey.3
--- old/libtermkey-0.20/man/termkey_strpkey.3   2017-03-30 15:17:09.000000000 
+0200
+++ new/libtermkey-0.22/man/termkey_strpkey.3   2019-03-14 14:47:10.000000000 
+0100
@@ -25,17 +25,20 @@
 Expect the name "\f(CWMeta\fP" or the letter "\f(CWM\fP" instead of 
"\f(CWAlt\fP" or "\f(CWA\fP".
 .TP
 .B TERMKEY_FORMAT_SPACEMOD
-Expect spaces instead of hyphens to separate the modifer name(s) from the base 
key name.
+Expect spaces instead of hyphens to separate the modifier name(s) from the 
base key name.
 .TP
 .B TERMKEY_FORMAT_LOWERMOD
 Expect lowercase for the modifier name.
 .TP
 .B TERMKEY_FORMAT_LOWERSPACE
 Expect lowercase with spaces in for the key name instead of camelCase (for 
example "\f(CWpage down\fP" instead of "\f(CWPageDown\fP").
+.TP
+.B TERMKEY_FORMAT_MOUSE_POS
+Expect a mouse event to be followed by its position rendered as "\f(CW@ 
(col,line)\fP".
 .PP
 Before returning, this function canonicalises the \fIkey\fP structure 
according to the rules given for \fBtermkey_canonicalise\fP(3).
 .PP
-The \fBTERMKEY_FORMAT_WRAPBRACKET\fP and \fBTERMKEY_FORMAT_MOUSE_POS\fP 
options are currently not supported by \fBtermkey_strpkey\fP(). When returning 
a \fBTERMKEY_TYPE_UNICODE\fP key structure, this function will fill in the 
\fIutf8\fP member.
+The \fBTERMKEY_FORMAT_WRAPBRACKET\fP option is currently not supported by 
\fBtermkey_strpkey\fP(). When returning a \fBTERMKEY_TYPE_UNICODE\fP key 
structure, this function will fill in the \fIutf8\fP member.
 .SH "RETURN VALUE"
 After a successful parse, \fBtermkey_strpkey\fP() returns a pointer to the 
first character of the input it did not consume. If the input string contains 
more characters then this will point at the first character beyond. If the 
entire input string was consumed, then this will point at a null byte. If 
\fBtermkey_strpkey\fP() fails to parse, it returns \fBNULL\fP. After a failed 
parse, the \fIkey\fP structure may contain partial or invalid results. The 
structure will only be valid if the function returns a non-\fBNULL\fP result.
 .SH "SEE ALSO"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/man/termkey_waitkey.3 
new/libtermkey-0.22/man/termkey_waitkey.3
--- old/libtermkey-0.20/man/termkey_waitkey.3   2017-03-30 15:17:09.000000000 
+0200
+++ new/libtermkey-0.22/man/termkey_waitkey.3   2019-03-14 14:47:10.000000000 
+0100
@@ -25,7 +25,7 @@
 No key events are ready and the terminal has been closed, so no more will 
arrive.
 .TP
 .B TERMKEY_RES_ERROR
-An IO error occured. \fIerrno\fP will be preserved. If the error is 
\fBEINTR\fP then this will only be returned if \fBTERMKEY_FLAG_EINTR\fP flag is 
not set; if it is then the IO operation will be retried instead. If this is 
called with terminal IO stopped, due to \fBtermkey_stop\fP(3) then \fIerrno\fP 
will be set to \fBEINVAL\fP.
+An IO error occurred. \fIerrno\fP will be preserved. If the error is 
\fBEINTR\fP then this will only be returned if \fBTERMKEY_FLAG_EINTR\fP flag is 
not set; if it is then the IO operation will be retried instead. If this is 
called with terminal IO stopped, due to \fBtermkey_stop\fP(3) then \fIerrno\fP 
will be set to \fBEINVAL\fP.
 .SH EXAMPLE
 The following example program prints details of every keypress until the user 
presses \fICtrl-C\fP.
 .PP
@@ -151,6 +151,8 @@
 }
 .in
 .fi
+.SH COMPATIBILITY
+This function is not available on Windows.
 .SH "SEE ALSO"
 .BR termkey_getkey (3),
 .BR termkey_set_waittime (3),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/t/12strpkey.c 
new/libtermkey-0.22/t/12strpkey.c
--- old/libtermkey-0.20/t/12strpkey.c   2017-03-30 15:17:09.000000000 +0200
+++ new/libtermkey-0.22/t/12strpkey.c   2019-03-14 14:47:10.000000000 +0100
@@ -5,11 +5,14 @@
 {
   TermKey      *tk;
   TermKeyKey    key;
+  TermKeyMouseEvent mouse;
+  int button, line, col;
   const char   *endp;
 
 #define CLEAR_KEY do { key.type = -1; key.code.codepoint = -1; key.modifiers = 
-1; key.utf8[0] = 0; } while(0)
+#define CLEAR_MOUSE do { CLEAR_KEY; mouse = -1; button = -1, line = -1; col = 
-1; } while(0)
 
-  plan_tests(62);
+  plan_tests(84);
 
   tk = termkey_new_abstract("vt100", 0);
 
@@ -115,6 +118,48 @@
   is_int(key.modifiers,   0,                     "key.modifiers for func/5/0");
   is_str(endp, "", "consumed entire input for func/5/0");
 
+  CLEAR_MOUSE;
+  endp = termkey_strpkey(tk, "MousePress(1)", &key, 0);
+  termkey_interpret_mouse(tk, &key, &mouse, &button, &line, &col);
+  is_int(key.type,        TERMKEY_TYPE_MOUSE,    "key.type for mouse");
+  is_int(mouse,           TERMKEY_MOUSE_PRESS,   "mouse press event");
+  is_int(button,          1,                     "mouse button 1");
+  is_str(endp, "", "consumed entire input for MousePress(1)");
+
+  CLEAR_MOUSE;
+  endp = termkey_strpkey(tk, "MousePress(2) @ (3, 5)", &key, 
TERMKEY_FORMAT_MOUSE_POS);
+  termkey_interpret_mouse(tk, &key, &mouse, &button, &line, &col);
+  is_int(key.type,        TERMKEY_TYPE_MOUSE,    "key.type for mouse");
+  is_int(mouse,           TERMKEY_MOUSE_PRESS,   "mouse press event");
+  is_int(button,          2,                     "mouse button 2");
+  is_int(col,             3,                     "mouse column 3");
+  is_int(line,            5,                     "mouse line 5");
+  is_str(endp, "", "consumed entire input for MousePress(2) @ (3, 5)");
+
+  CLEAR_MOUSE;
+  endp = termkey_strpkey(tk, "MouseRelease(1)", &key, 0);
+  termkey_interpret_mouse(tk, &key, &mouse, &button, &line, &col);
+  is_int(key.type,        TERMKEY_TYPE_MOUSE,    "key.type for mouse");
+  is_int(mouse,           TERMKEY_MOUSE_RELEASE, "mouse release event");
+  is_int(button,          0,                     "mouse button 1 lost"); // 
TODO: can we recover it?
+  is_str(endp, "", "consumed entire input for MouseRelease(1)");
+
+  CLEAR_MOUSE;
+  endp = termkey_strpkey(tk, "MouseDrag(1)", &key, 0);
+  termkey_interpret_mouse(tk, &key, &mouse, &button, &line, &col);
+  is_int(key.type,        TERMKEY_TYPE_MOUSE,    "key.type for mouse");
+  is_int(mouse,           TERMKEY_MOUSE_DRAG,    "mouse drap event");
+  is_int(button,          1,                     "mouse button 1");
+  is_str(endp, "", "consumed entire input for MouseDrag(1)");
+
+  CLEAR_MOUSE;
+  endp = termkey_strpkey(tk, "MouseUnknown(1)", &key, 0);
+  termkey_interpret_mouse(tk, &key, &mouse, &button, &line, &col);
+  is_int(key.type,        TERMKEY_TYPE_MOUSE,    "key.type for mouse");
+  is_int(mouse,           TERMKEY_MOUSE_UNKNOWN, "mouse unknown event");
+  is_int(button,          0,                     "mouse button 1 lost");
+  is_str(endp, "", "consumed entire input for MouseUnknown(1)");
+
   termkey_destroy(tk);
 
   return exit_status();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/t/30mouse.c 
new/libtermkey-0.22/t/30mouse.c
--- old/libtermkey-0.20/t/30mouse.c     2017-03-30 15:17:09.000000000 +0200
+++ new/libtermkey-0.22/t/30mouse.c     2019-03-14 14:47:10.000000000 +0100
@@ -14,7 +14,7 @@
 
   tk = termkey_new_abstract("vt100", 0);
 
-  termkey_push_bytes(tk, "\e[M !!", 6);
+  termkey_push_bytes(tk, "\x1b[M !!", 6);
 
   key.type = -1;
   is_int(termkey_getkey(tk, &key), TERMKEY_RES_KEY, "getkey yields RES_KEY for 
mouse press");
@@ -38,7 +38,7 @@
   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);
+  termkey_push_bytes(tk, "\x1b[M@\"!", 6);
 
   key.type = -1;
   ev = -1; button = -1; line = -1; col = -1;
@@ -51,7 +51,7 @@
   is_int(col,    2,                   "mouse column for drag");
   is_int(key.modifiers, 0,            "modifiers for press");
 
-  termkey_push_bytes(tk, "\e[M##!", 6);
+  termkey_push_bytes(tk, "\x1b[M##!", 6);
 
   key.type = -1;
   ev = -1; button = -1; line = -1; col = -1;
@@ -63,7 +63,7 @@
   is_int(col,    3,                     "mouse column for release");
   is_int(key.modifiers, 0,            "modifiers for press");
 
-  termkey_push_bytes(tk, "\e[M0++", 6);
+  termkey_push_bytes(tk, "\x1b[M0++", 6);
 
   key.type = -1;
   ev = -1; button = -1; line = -1; col = -1;
@@ -81,7 +81,7 @@
   is_str(buffer, "C-MousePress(1)", "string buffer for Ctrl-press");
 
   // rxvt protocol
-  termkey_push_bytes(tk, "\e[0;20;20M", 10);
+  termkey_push_bytes(tk, "\x1b[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");
@@ -96,7 +96,7 @@
   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);
+  termkey_push_bytes(tk, "\x1b[3;20;20M", 10);
 
   is_int(termkey_getkey(tk, &key), TERMKEY_RES_KEY, "getkey yields RES_KEY for 
mouse release rxvt protocol");
 
@@ -111,7 +111,7 @@
   is_int(key.modifiers, 0,            "modifiers for release rxvt protocol");
 
   // SGR protocol
-  termkey_push_bytes(tk, "\e[<0;30;30M", 11);
+  termkey_push_bytes(tk, "\x1b[<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");
@@ -127,7 +127,7 @@
   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);
+  termkey_push_bytes(tk, "\x1b[<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");
@@ -139,7 +139,7 @@
 
   is_int(ev,     TERMKEY_MOUSE_RELEASE, "mouse event for release SGR");
 
-  termkey_push_bytes(tk, "\e[<0;500;300M", 13);
+  termkey_push_bytes(tk, "\x1b[<0;500;300M", 13);
 
   key.type = -1;
   ev = -1; button = -1; line = -1; col = -1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/t/31position.c 
new/libtermkey-0.22/t/31position.c
--- old/libtermkey-0.20/t/31position.c  2017-03-30 15:17:09.000000000 +0200
+++ new/libtermkey-0.22/t/31position.c  2019-03-14 14:47:10.000000000 +0100
@@ -11,7 +11,7 @@
 
   tk = termkey_new_abstract("vt100", 0);
 
-  termkey_push_bytes(tk, "\e[?15;7R", 8);
+  termkey_push_bytes(tk, "\x1b[?15;7R", 8);
 
   is_int(termkey_getkey(tk, &key), TERMKEY_RES_KEY, "getkey yields RES_KEY for 
position report");
 
@@ -25,7 +25,7 @@
   /* A plain CSI R is likely to be <F3> though.
    * This is tricky :/
    */
-  termkey_push_bytes(tk, "\e[R", 3);
+  termkey_push_bytes(tk, "\x1b[R", 3);
 
   is_int(termkey_getkey(tk, &key), TERMKEY_RES_KEY, "getkey yields RES_KEY for 
<F3>");
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/t/32modereport.c 
new/libtermkey-0.22/t/32modereport.c
--- old/libtermkey-0.20/t/32modereport.c        2017-03-30 15:17:09.000000000 
+0200
+++ new/libtermkey-0.22/t/32modereport.c        2019-03-14 14:47:10.000000000 
+0100
@@ -11,7 +11,7 @@
 
   tk = termkey_new_abstract("vt100", 0);
 
-  termkey_push_bytes(tk, "\e[?1;2$y", 8);
+  termkey_push_bytes(tk, "\x1b[?1;2$y", 8);
 
   is_int(termkey_getkey(tk, &key), TERMKEY_RES_KEY, "getkey yields RES_KEY for 
mode report");
 
@@ -23,7 +23,7 @@
   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);
+  termkey_push_bytes(tk, "\x1b[4;1$y", 7);
 
   is_int(termkey_getkey(tk, &key), TERMKEY_RES_KEY, "getkey yields RES_KEY for 
mode report");
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/t/38csi.c 
new/libtermkey-0.22/t/38csi.c
--- old/libtermkey-0.20/t/38csi.c       2017-03-30 15:17:09.000000000 +0200
+++ new/libtermkey-0.22/t/38csi.c       2019-03-14 14:47:10.000000000 +0100
@@ -13,7 +13,7 @@
 
   tk = termkey_new_abstract("vt100", 0);
 
-  termkey_push_bytes(tk, "\e[5;25v", 7);
+  termkey_push_bytes(tk, "\x1b[5;25v", 7);
 
   is_int(termkey_getkey(tk, &key), TERMKEY_RES_KEY, "getkey yields RES_KEY for 
CSI v");
 
@@ -26,14 +26,14 @@
   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);
+  termkey_push_bytes(tk, "\x1b[?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);
+  termkey_push_bytes(tk, "\x1b[?$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");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/t/39dcs.c 
new/libtermkey-0.22/t/39dcs.c
--- old/libtermkey-0.20/t/39dcs.c       2017-03-30 15:17:09.000000000 +0200
+++ new/libtermkey-0.22/t/39dcs.c       2019-03-14 14:47:10.000000000 +0100
@@ -12,7 +12,7 @@
   tk = termkey_new_abstract("xterm", 0);
 
   // 7bit DCS
-  termkey_push_bytes(tk, "\eP1$r1 q\e\\", 10);
+  termkey_push_bytes(tk, "\x1bP1$r1 q\x1b\\", 10);
 
   is_int(termkey_getkey(tk, &key), TERMKEY_RES_KEY, "getkey yields RES_KEY for 
DCS");
 
@@ -38,7 +38,7 @@
   is_int(termkey_getkey(tk, &key), TERMKEY_RES_NONE, "getkey again yields 
RES_NONE");
 
   // 7bit OSC
-  termkey_push_bytes(tk, "\e]15;abc\e\\", 10);
+  termkey_push_bytes(tk, "\x1b]15;abc\x1b\\", 10);
 
   is_int(termkey_getkey(tk, &key), TERMKEY_RES_KEY, "getkey yields RES_KEY for 
OSC");
 
@@ -51,11 +51,11 @@
   is_int(termkey_getkey(tk, &key), TERMKEY_RES_NONE, "getkey again yields 
RES_NONE");
 
   // False alarm
-  termkey_push_bytes(tk, "\eP", 2);
+  termkey_push_bytes(tk, "\x1bP", 2);
 
   is_int(termkey_getkey(tk, &key), TERMKEY_RES_AGAIN, "getkey yields RES_AGAIN 
for false alarm");
 
-  is_int(termkey_getkey_force(tk, &key), TERMKEY_RES_KEY, "getkey_forvce 
yields RES_KEY for false alarm");
+  is_int(termkey_getkey_force(tk, &key), TERMKEY_RES_KEY, "getkey_force yields 
RES_KEY for false alarm");
 
   is_int(key.type,           TERMKEY_TYPE_UNICODE, "key.type for false alarm");
   is_int(key.code.codepoint, 'P',                  "key.code.codepoint for 
false alarm");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/t/40ti-override.c 
new/libtermkey-0.22/t/40ti-override.c
--- old/libtermkey-0.20/t/40ti-override.c       2017-03-30 15:17:09.000000000 
+0200
+++ new/libtermkey-0.22/t/40ti-override.c       2019-03-14 14:47:10.000000000 
+0100
@@ -22,7 +22,11 @@
 
   plan_tests(3);
 
-  tk = termkey_new_abstract("vt100", TERMKEY_FLAG_NOSTART);
+  /* There was never a VT750. We've just made this string up.
+   * This test ensures that the hooked function can invent TI strings for new
+   * terminal types that don't exist in the TI database yet.
+   */
+  tk = termkey_new_abstract("vt750", TERMKEY_FLAG_NOSTART);
   termkey_hook_terminfo_getstr(tk, &backspace_is_X, NULL);
   termkey_start(tk);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/termkey-internal.h 
new/libtermkey-0.22/termkey-internal.h
--- old/libtermkey-0.20/termkey-internal.h      2017-03-30 15:17:09.000000000 
+0200
+++ new/libtermkey-0.22/termkey-internal.h      2019-03-14 14:47:10.000000000 
+0100
@@ -1,10 +1,23 @@
 #ifndef GUARD_TERMKEY_INTERNAL_H_
 #define GUARD_TERMKEY_INTERNAL_H_
 
+#define HAVE_TERMIOS
+
+#ifdef _WIN32
+# undef HAVE_TERMIOS
+#endif
+
 #include "termkey.h"
 
 #include <stdint.h>
-#include <termios.h>
+#ifdef HAVE_TERMIOS
+# include <termios.h>
+#endif
+
+#ifdef _MSC_VER
+#include <BaseTsd.h>
+typedef SSIZE_T ssize_t;
+#endif
 
 struct TermKeyDriver
 {
@@ -41,8 +54,10 @@
   size_t hightide; /* Position beyond buffstart at which peekkey() should next 
start
                     * normally 0, but see also termkey_interpret_csi */
 
+#ifdef HAVE_TERMIOS
   struct termios restore_termios;
   char restore_termios_valid;
+#endif
 
   TermKey_Terminfo_Getstr_Hook *ti_getstr_hook;
   void *ti_getstr_hook_data;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/termkey.c 
new/libtermkey-0.22/termkey.c
--- old/libtermkey-0.20/termkey.c       2017-03-30 15:17:09.000000000 +0200
+++ new/libtermkey-0.22/termkey.c       2019-03-14 14:47:10.000000000 +0100
@@ -3,14 +3,20 @@
 
 #include <ctype.h>
 #include <errno.h>
-#include <poll.h>
-#include <unistd.h>
+#ifndef _WIN32
+# include <poll.h>
+# include <unistd.h>
+# include <strings.h>
+#endif
 #include <string.h>
-#include <strings.h>
 
 #include <stdio.h>
 
-#define strcaseeq(a,b) (strcasecmp(a,b) == 0)
+#ifdef _MSC_VER
+# define strcaseeq(a,b) (_stricmp(a,b) == 0)
+#else
+# define strcaseeq(a,b) (strcasecmp(a,b) == 0)
+#endif
 
 void termkey_check_version(int major, int minor)
 {
@@ -111,10 +117,13 @@
   { 0, NULL },
 };
 
+// Mouse event names
+static const char *evnames[] = { "Unknown", "Press", "Drag", "Release" };
+
 #define CHARAT(i) (tk->buffer[tk->buffstart + (i)])
 
 #ifdef DEBUG
-/* Some internal deubgging functions */
+/* Some internal debugging functions */
 
 static void print_buffer(TermKey *tk)
 {
@@ -282,7 +291,9 @@
   tk->buffsize  = 256; /* bytes */
   tk->hightide  = 0;
 
+#ifdef HAVE_TERMIOS
   tk->restore_termios_valid = 0;
+#endif
 
   tk->ti_getstr_hook = NULL;
   tk->ti_getstr_hook_data = NULL;
@@ -483,6 +494,7 @@
   if(tk->is_started)
     return 1;
 
+#ifdef HAVE_TERMIOS
   if(tk->fd != -1 && !(tk->flags & TERMKEY_FLAG_NOTERMIOS)) {
     struct termios termios;
     if(tcgetattr(tk->fd, &termios) == 0) {
@@ -517,6 +529,7 @@
       tcsetattr(tk->fd, TCSANOW, &termios);
     }
   }
+#endif
 
   struct TermKeyDriverNode *p;
   for(p = tk->drivers; p; p = p->next)
@@ -542,8 +555,10 @@
     if(p->driver->stop_driver)
       (*p->driver->stop_driver)(tk, p->info);
 
+#ifdef HAVE_TERMIOS
   if(tk->restore_termios_valid)
     tcsetattr(tk->fd, TCSANOW, &tk->restore_termios);
+#endif
 
   tk->is_started = 0;
 
@@ -768,12 +783,12 @@
     if(!key->code.sym) {
       key->type = TERMKEY_TYPE_UNICODE;
       /* Generically modified Unicode ought not report the SHIFT state, or else
-       * we get into complicationg trying to report Shift-; vs : and so on...
+       * 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
+        // it's a letter - use lowercase instead
         key->code.codepoint = codepoint + 0x60;
       else
         key->code.codepoint = codepoint + 0x40;
@@ -1046,6 +1061,7 @@
   return ret;
 }
 
+#ifndef _WIN32
 TermKeyResult termkey_waitkey(TermKey *tk, TermKeyKey *key)
 {
   if(tk->fd == -1) {
@@ -1105,6 +1121,7 @@
 
   /* UNREACHABLE */
 }
+#endif
 
 TermKeyResult termkey_advisereadable(TermKey *tk)
 {
@@ -1307,7 +1324,7 @@
      key->modifiers == TERMKEY_KEYMOD_CTRL) {
     long codepoint = key->code.codepoint;
 
-    // Handle some of the special casesfirst
+    // Handle some of the special cases first
     if(codepoint >= 'a' && codepoint <= 'z') {
       l = snprintf(buffer + pos, len - pos, wrapbracket ? "<^%c>" : "^%c", 
(char)codepoint - 0x20);
       if(l <= 0) return pos;
@@ -1373,8 +1390,6 @@
       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);
 
@@ -1466,6 +1481,8 @@
   size_t nbytes;
   ssize_t snbytes;
   const char *endstr;
+  int button;
+  char event_name[32];
 
   if((endstr = termkey_lookup_keyname_format(tk, str, &key->code.sym, 
format))) {
     key->type = TERMKEY_TYPE_KEYSYM;
@@ -1475,13 +1492,48 @@
     key->type = TERMKEY_TYPE_FUNCTION;
     str += snbytes;
   }
+  else if(sscanf(str, "Mouse%31[^(](%d)%zn", event_name, &button, &snbytes) == 
2) {
+    str += snbytes;
+    key->type = TERMKEY_TYPE_MOUSE;
+
+    TermKeyMouseEvent ev = TERMKEY_MOUSE_UNKNOWN;
+    for(size_t i = 0; i < sizeof(evnames)/sizeof(evnames[0]); i++) {
+      if(strcmp(evnames[i], event_name) == 0) {
+        ev = TERMKEY_MOUSE_UNKNOWN + i;
+        break;
+      }
+    }
+
+    int code;
+    switch(ev) {
+    case TERMKEY_MOUSE_PRESS:
+    case TERMKEY_MOUSE_DRAG:
+      code = button - 1;
+      if(ev == TERMKEY_MOUSE_DRAG) {
+        code |= 0x20;
+      }
+      break;
+    case TERMKEY_MOUSE_RELEASE:
+      code = 3;
+      break;
+    default:
+      code = 128;
+      break;
+    }
+    key->code.mouse[0] = code;
+
+    unsigned int line = 0, col = 0;
+    if((format & TERMKEY_FORMAT_MOUSE_POS) && sscanf(str, " @ (%u,%u)%zn", 
&col, &line, &snbytes) == 2) {
+      str += snbytes;
+    }
+    termkey_key_set_linecol(key, col, line);
+  }
   // Unicode must be last
   else if(parse_utf8((unsigned const char *)str, strlen(str), 
&key->code.codepoint, &nbytes) == TERMKEY_RES_KEY) {
     key->type = TERMKEY_TYPE_UNICODE;
     fill_utf8(key);
     str += nbytes;
   }
-  // TODO: Consider mouse events?
   else
     return NULL;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/termkey.h 
new/libtermkey-0.22/termkey.h
--- old/libtermkey-0.20/termkey.h       2017-03-30 15:17:09.000000000 +0200
+++ new/libtermkey-0.22/termkey.h       2019-03-14 14:47:10.000000000 +0100
@@ -9,7 +9,7 @@
 #include <stdlib.h>
 
 #define TERMKEY_VERSION_MAJOR 0
-#define TERMKEY_VERSION_MINOR 20
+#define TERMKEY_VERSION_MINOR 22
 
 #define TERMKEY_CHECK_VERSION \
         termkey_check_version(TERMKEY_VERSION_MAJOR, TERMKEY_VERSION_MINOR)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/termkey.pc.in 
new/libtermkey-0.22/termkey.pc.in
--- old/libtermkey-0.20/termkey.pc.in   2017-03-30 15:17:09.000000000 +0200
+++ new/libtermkey-0.22/termkey.pc.in   1970-01-01 01:00:00.000000000 +0100
@@ -1,8 +0,0 @@
-libdir=@LIBDIR@
-includedir=@INCDIR@
-
-Name: termkey
-Description: Abstract terminal key input library
-Version: 0.20
-Libs: -L${libdir} -ltermkey
-Cflags: -I${includedir}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtermkey-0.20/termkey.pc.sh 
new/libtermkey-0.22/termkey.pc.sh
--- old/libtermkey-0.20/termkey.pc.sh   1970-01-01 01:00:00.000000000 +0100
+++ new/libtermkey-0.22/termkey.pc.sh   2019-03-14 14:47:10.000000000 +0100
@@ -0,0 +1,10 @@
+cat <<EOF
+libdir=$LIBDIR
+includedir=$INCDIR
+
+Name: termkey
+Description: Abstract terminal key input library
+Version: $VERSION
+Libs: -L\${libdir} -ltermkey
+Cflags: -I\${includedir}
+EOF


Reply via email to