billiob pushed a commit to branch master.

http://git.enlightenment.org/apps/terminology.git/commit/?id=671fe7967b613c51b9de670a5955dbc9fe3f3f6f

commit 671fe7967b613c51b9de670a5955dbc9fe3f3f6f
Author: Boris Faure <bill...@gmail.com>
Date:   Sun Sep 21 18:27:23 2014 +0200

    generate tty_keys.h from xterm itself
    
    Script gen_tty_keys.sh is heavily based on the script escapes.sh by Egmont
    Koblinger.
    
    Closes T1564
---
 src/bin/Makefile.am   |    3 +-
 src/bin/keyin.c       |  550 +++++-----------------
 src/bin/keyin.h       |    1 -
 src/bin/tty_keys.h    | 1257 +++++++++++++++++++++++++++++++++++++++++++++++++
 tools/gen_tty_keys.sh |  277 +++++++++++
 5 files changed, 1650 insertions(+), 438 deletions(-)

diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am
index 4baa538..d2024bd 100644
--- a/src/bin/Makefile.am
+++ b/src/bin/Makefile.am
@@ -56,7 +56,8 @@ utils.c utils.h \
 dbus.c dbus.h \
 extns.c extns.h \
 app_server.c app_server.h \
-app_server_eet.c app_server_eet.h
+app_server_eet.c app_server_eet.h \
+tty_keys.h
 
 tybg_SOURCES = \
 tybg.c
diff --git a/src/bin/keyin.c b/src/bin/keyin.c
index 5d045bc..d2f230c 100644
--- a/src/bin/keyin.c
+++ b/src/bin/keyin.c
@@ -8,14 +8,30 @@
 #include "termcmd.h"
 #include "keyin.h"
 
-typedef struct _Keyout Keyout;
+typedef struct _Tty_Key Tty_Key;
+typedef struct _Key_Values Key_Values;
 
-struct _Keyout
+struct _s {
+    char *s;
+    ssize_t len;
+};
+
+struct _Key_Values {
+    struct _s plain;
+    struct _s alt;
+    struct _s ctrl;
+    struct _s ctrl_alt;
+    struct _s shift;
+    struct _s shift_alt;
+    struct _s shift_ctrl;
+    struct _s shift_ctrl_alt;
+};
+struct _Tty_Key
 {
-   const char *in;
-   const char *out;
-   int         inlen;
-   int         outlen;
+    char *key;
+    int key_len;
+    Key_Values default_mode;
+    Key_Values cursor;
 };
 
 typedef struct _Key_Binding Key_Binding;
@@ -36,386 +52,46 @@ static Eina_Hash *_key_bindings = NULL;
 
 /* {{{ Keys to TTY */
 
-#define KEY(in, out) {in, out, sizeof(in) - 1, sizeof(out) - 1}
-
-static const Keyout crlf_keyout[] =
-{
-   KEY("Return",       "\r\n"),
-   
-   KEY(NULL, "END")
-};
-
-static const Keyout nocrlf_keyout[] =
-{
-   KEY("Return",       "\r"),
-   
-   KEY(NULL, "END")
-};
-
-static const Keyout appcur_keyout[] =
-{
-   KEY("Left",         "\033OD"),
-   KEY("Right",        "\033OC"),
-   KEY("Up",           "\033OA"),
-   KEY("Down",         "\033OB"),
-   KEY("Home",         "\033OH"),
-   KEY("End",          "\033OF"),
-//// why did i change these?   
-//   KEY("Home",         "\033[7~"),
-//   KEY("End",          "\033[8~"),
-   KEY("F1",           "\033OP"),
-   KEY("F2",           "\033OQ"),
-   KEY("F3",           "\033OR"),
-   KEY("F4",           "\033OS"),
-   
-   KEY(NULL, "END")
-};
-
-static const Keyout ctrl_keyout[] =
-{
-   KEY("Left",         "\033[1;5D"),
-   KEY("Right",        "\033[1;5C"),
-   KEY("Up",           "\033[1;5A"),
-   KEY("Down",         "\033[1;5B"),
-   KEY("Home",         "\033[1;5H"),
-   KEY("End",          "\033[1;5F"),
-   KEY("Insert",       "\033[2;5~"),
-   KEY("Delete",       "\033[3;5~"),
-   KEY("Prior",        "\033[5;5~"),
-   KEY("Next",         "\033[6;5~"),
-   KEY("F1",           "\033[O5P"),
-   KEY("F2",           "\033[O5Q"),
-   KEY("F3",           "\033[O5R"),
-   KEY("F4",           "\033[O5S"),
-   KEY("F5",           "\033[15;5~"),
-   KEY("F6",           "\033[17;5~"),
-   KEY("F7",           "\033[18;5~"),
-   KEY("F8",           "\033[19;5~"),
-   KEY("F9",           "\033[20;5~"),
-   KEY("F10",          "\033[21;5~"),
-   KEY("F11",          "\033[23;5~"),
-   KEY("F12",          "\033[24;5~"),
-   KEY("F13",          "\033[25;5~"),
-   KEY("F14",          "\033[26;5~"),
-   KEY("F15",          "\033[28;5~"),
-   KEY("F16",          "\033[29;5~"),
-   KEY("F17",          "\033[31;5~"),
-   KEY("F18",          "\033[32;5~"),
-   KEY("F19",          "\033[33;5~"),
-   KEY("F20",          "\033[34;5~"),
-   KEY("F21",          "\033[35;5~"),
-   KEY("F22",          "\033[36;5~"),
-   KEY("F23",          "\033[37;5~"),
-   KEY("F24",          "\033[38;5~"),
-   KEY("F25",          "\033[39;5~"),
-   KEY("F26",          "\033[40;5~"),
-   KEY("F27",          "\033[41;5~"),
-   KEY("F28",          "\033[42;5~"),
-   KEY("F29",          "\033[43;5~"),
-   KEY("F30",          "\033[44;5~"),
-   KEY("F31",          "\033[45;5~"),
-   KEY("F32",          "\033[46;5~"),
-   KEY("F33",          "\033[47;5~"),
-   KEY("F34",          "\033[48;5~"),
-   KEY("F35",          "\033[49;5~"),
-
-   KEY(NULL, "END")
-};
-
-static const Keyout ctrl_shift_keyout[] =
-{
-   KEY("Left",         "\033[1;6D"),
-   KEY("Right",        "\033[1;6C"),
-   KEY("Up",           "\033[1;6A"),
-   KEY("Down",         "\033[1;6B"),
-   KEY("Home",         "\033[1;6H"),
-   KEY("End",          "\033[1;6F"),
-   KEY("Insert",       "\033[2;6~"),
-   KEY("Delete",       "\033[3;6~"),
-   KEY("Prior",        "\033[5;6~"),
-   KEY("Next",         "\033[6;6~"),
-
-   KEY("F1",           "\033[O6P"),
-   KEY("F2",           "\033[O6Q"),
-   KEY("F3",           "\033[O6R"),
-   KEY("F4",           "\033[O6S"),
-   KEY("F5",           "\033[15;6~"),
-   KEY("F6",           "\033[17;6~"),
-   KEY("F7",           "\033[18;6~"),
-   KEY("F8",           "\033[19;6~"),
-   KEY("F9",           "\033[20;6~"),
-   KEY("F10",          "\033[21;6~"),
-   KEY("F11",          "\033[23;6~"),
-   KEY("F12",          "\033[24;6~"),
-   KEY("F13",          "\033[25;6~"),
-   KEY("F14",          "\033[26;6~"),
-   KEY("F15",          "\033[28;6~"),
-   KEY("F16",          "\033[29;6~"),
-   KEY("F17",          "\033[31;6~"),
-   KEY("F18",          "\033[32;6~"),
-   KEY("F19",          "\033[33;6~"),
-   KEY("F20",          "\033[34;6~"),
-   KEY("F21",          "\033[35;6~"),
-   KEY("F22",          "\033[36;6~"),
-   KEY("F23",          "\033[37;6~"),
-   KEY("F24",          "\033[38;6~"),
-   KEY("F25",          "\033[39;6~"),
-   KEY("F26",          "\033[40;6~"),
-   KEY("F27",          "\033[41;6~"),
-   KEY("F28",          "\033[42;6~"),
-   KEY("F29",          "\033[43;6~"),
-   KEY("F30",          "\033[44;6~"),
-   KEY("F31",          "\033[45;6~"),
-   KEY("F32",          "\033[46;6~"),
-   KEY("F33",          "\033[47;6~"),
-   KEY("F34",          "\033[48;6~"),
-   KEY("F35",          "\033[49;6~"),
-
-   KEY(NULL, "END")
-};
-
-static const Keyout shift_keyout[] =
-{
-   KEY("Left",         "\033[1;2D"),
-   KEY("Right",        "\033[1;2C"),
-   KEY("Up",           "\033[1;2A"),
-   KEY("Down",         "\033[1;2B"),
-   KEY("Home",         "\033[1;2H"),
-   KEY("End",          "\033[1;2F"),
-   KEY("Insert",       "\033[2;2~"),
-   KEY("Delete",       "\033[3;2~"),
-   KEY("Prior",        "\033[5;2~"),
-   KEY("Next",         "\033[6;2~"),
-
-   KEY("Tab",          "\033[Z"),
-   KEY("ISO_Left_Tab", "\033[Z"),
-   KEY("F1",           "\033[1;2P"),
-   KEY("F2",           "\033[1;2Q"),
-   KEY("F3",           "\033[1;2R"),
-   KEY("F4",           "\033[1;2S"),
-   KEY("F5",           "\033[15;2~"),
-   KEY("F6",           "\033[17;2~"),
-   KEY("F7",           "\033[18;2~"),
-   KEY("F8",           "\033[19;2~"),
-   KEY("F9",           "\033[20;2~"),
-   KEY("F10",          "\033[21;2~"),
-   KEY("F11",          "\033[23;2~"),
-   KEY("F12",          "\033[24;2~"),
-   KEY("F13",          "\033[25;2~"),
-   KEY("F14",          "\033[26;2~"),
-   KEY("F15",          "\033[28;2~"),
-   KEY("F16",          "\033[29;2~"),
-   KEY("F17",          "\033[31;2~"),
-   KEY("F18",          "\033[32;2~"),
-   KEY("F19",          "\033[33;2~"),
-   KEY("F20",          "\033[34;2~"),
-   KEY("F21",          "\033[35;2~"),
-   KEY("F22",          "\033[36;2~"),
-   KEY("F23",          "\033[37;2~"),
-   KEY("F24",          "\033[38;2~"),
-   KEY("F25",          "\033[39;2~"),
-   KEY("F26",          "\033[40;2~"),
-   KEY("F27",          "\033[41;2~"),
-   KEY("F28",          "\033[42;2~"),
-   KEY("F29",          "\033[43;2~"),
-   KEY("F30",          "\033[44;2~"),
-   KEY("F31",          "\033[45;2~"),
-   KEY("F32",          "\033[46;2~"),
-   KEY("F33",          "\033[47;2~"),
-   KEY("F34",          "\033[48;2~"),
-   KEY("F35",          "\033[49;2~"),
-
-   KEY(NULL, "END")
-};
-
-static const Keyout alt_keyout[] =
-{
-   KEY("Left",         "\033[1;3D"),
-   KEY("Right",        "\033[1;3C"),
-   KEY("Up",           "\033[1;3A"),
-   KEY("Down",         "\033[1;3B"),
-   KEY("End",          "\033[1;3F"),
-   KEY("BackSpace",    "\033\b"),
-   KEY("Return",       "\033\015"),
-   KEY("space",        "\033\040"),
-   KEY("Home",         "\033[1;3H"),
-   KEY("End",          "\033[1;3F"),
-   KEY("Prior",        "\033[5;3~"),
-   KEY("Next",         "\033[6;3~"),
-   KEY("Insert",       "\033[2;3~"),
-   KEY("Delete",       "\033[3;3~"),
-   KEY("Menu",         "\033[29;3~"),
-   KEY("Find",         "\033[1;3~"),
-   KEY("Help",         "\033[28;3~"),
-   KEY("Execute",      "\033[3;3~"),
-   KEY("Select",       "\033[4;3~"),
-   KEY("F1",           "\033[O3P"),
-   KEY("F2",           "\033[O3Q"),
-   KEY("F3",           "\033[O3R"),
-   KEY("F4",           "\033[O3S"),
-   KEY("F5",           "\033[15;3~"),
-   KEY("F6",           "\033[17;3~"),
-   KEY("F7",           "\033[18;3~"),
-   KEY("F8",           "\033[19;3~"),
-   KEY("F9",           "\033[20;3~"),
-   KEY("F10",          "\033[21;3~"),
-   KEY("F11",          "\033[23;3~"),
-   KEY("F12",          "\033[24;3~"),
-   KEY("F13",          "\033[25;3~"),
-   KEY("F14",          "\033[26;3~"),
-   KEY("F15",          "\033[28;3~"),
-   KEY("F16",          "\033[29;3~"),
-   KEY("F17",          "\033[31;3~"),
-   KEY("F18",          "\033[32;3~"),
-   KEY("F19",          "\033[33;3~"),
-   KEY("F20",          "\033[34;3~"),
-   KEY("F21",          "\033[35;3~"),
-   KEY("F22",          "\033[36;3~"),
-   KEY("F23",          "\033[37;3~"),
-   KEY("F24",          "\033[38;3~"),
-   KEY("F25",          "\033[39;3~"),
-   KEY("F26",          "\033[40;3~"),
-   KEY("F27",          "\033[41;3~"),
-   KEY("F28",          "\033[42;3~"),
-   KEY("F29",          "\033[43;3~"),
-   KEY("F30",          "\033[44;3~"),
-   KEY("F31",          "\033[45;3~"),
-   KEY("F32",          "\033[46;3~"),
-   KEY("F33",          "\033[47;3~"),
-   KEY("F34",          "\033[48;3~"),
-   KEY("F35",          "\033[49;3~"),
-
-   KEY(NULL, "END")
-};
-
-static const Keyout keyout[] =
-{
-//   KEY("BackSpace",    "\177"),
-   KEY("BackSpace",    "\b"),
-   KEY("Left",         "\033[D"),
-   KEY("Right",        "\033[C"),
-   KEY("Up",           "\033[A"),
-   KEY("Down",         "\033[B"),
-//   KEY("Tab",          "\t"),
-//   KEY("ISO_Left_Tab", "\t"),
-   KEY("Home",         "\033[H"),
-   KEY("End",          "\033[F"),
-   KEY("Prior",        "\033[5~"),
-   KEY("Next",         "\033[6~"),
-   KEY("Insert",       "\033[2~"),
-   KEY("Delete",       "\033[3~"),
-   KEY("Menu",         "\033[29~"),
-   KEY("Find",         "\033[1~"),
-   KEY("Help",         "\033[28~"),
-   KEY("Execute",      "\033[3~"),
-   KEY("Select",       "\033[4~"),
-   KEY("F1",           "\033OP"),
-   KEY("F2",           "\033OQ"),
-   KEY("F3",           "\033OR"),
-   KEY("F4",           "\033OS"),
-   KEY("F5",           "\033[15~"),
-   KEY("F6",           "\033[17~"),
-   KEY("F7",           "\033[18~"),
-   KEY("F8",           "\033[19~"),
-   KEY("F9",           "\033[20~"),
-   KEY("F10",          "\033[21~"),
-   KEY("F11",          "\033[23~"),
-   KEY("F12",          "\033[24~"),
-   KEY("F13",          "\033[25~"),
-   KEY("F14",          "\033[26~"),
-   KEY("F15",          "\033[28~"),
-   KEY("F16",          "\033[29~"),
-   KEY("F17",          "\033[31~"),
-   KEY("F18",          "\033[32~"),
-   KEY("F19",          "\033[33~"),
-   KEY("F20",          "\033[34~"),
-   KEY("F21",          "\033[35~"),
-   KEY("F22",          "\033[36~"),
-   KEY("F23",          "\033[37~"),
-   KEY("F24",          "\033[38~"),
-   KEY("F25",          "\033[39~"),
-   KEY("F26",          "\033[40~"),
-   KEY("F27",          "\033[41~"),
-   KEY("F28",          "\033[42~"),
-   KEY("F29",          "\033[43~"),
-   KEY("F30",          "\033[44~"),
-   KEY("F31",          "\033[45~"),
-   KEY("F32",          "\033[46~"),
-   KEY("F33",          "\033[47~"),
-   KEY("F34",          "\033[48~"),
-   KEY("F35",          "\033[49~"),
-/*   
-   KEY("KP_F1",        "\033OP"),
-   KEY("KP_F2",        "\033OQ"),
-   KEY("KP_F3",        "\033OR"),
-   KEY("KP_F4",        "\033OS"),
-   KEY("KP_Begin",     "\033Ou"),
-   KEY("KP_Multiply",  "\033Oj"),
-   KEY("KP_Add",       "\033Ok"),
-   KEY("KP_Separator", "\033Ol"),
-   KEY("KP_Subtract",  "\033Om"),
-   KEY("KP_Decimal",   "\033On"),
-   KEY("KP_Divide",    "\033Oo"),
-   KEY("KP_0",         "\033Op"),
-   KEY("KP_1",         "\033Oq"),
-   KEY("KP_2",         "\033Or"),
-   KEY("KP_3",         "\033Os"),
-   KEY("KP_4",         "\033Ot"),
-   KEY("KP_5",         "\033Ou"),
-   KEY("KP_6",         "\033Ov"),
-   KEY("KP_7",         "\033Ow"),
-   KEY("KP_8",         "\033Ox"),
-   KEY("KP_9",         "\033Oy"),
- */
-   KEY(NULL, "END")
-};
-
-static const Keyout kp_keyout[] =
-{
-   KEY("KP_Left",         "\033[D"),
-   KEY("KP_Right",        "\033[C"),
-   KEY("KP_Up",           "\033[A"),
-   KEY("KP_Down",         "\033[B"),
-   KEY("KP_Home",         "\033[H"),
-   KEY("KP_End",          "\033[F"),
-   KEY("KP_Prior",        "\033[5~"),
-   KEY("KP_Next",         "\033[6~"),
-   KEY("KP_Insert",       "\033[2~"),
-   KEY("KP_Delete",       "\033[3~"),
-   KEY("KP_Enter",        "\r"),
-   KEY(NULL, "END")
-};
-
-static const Keyout kps_keyout[] =
-{
-   KEY("KP_Left",         "\033Ot"),
-   KEY("KP_Right",        "\033Ov"),
-   KEY("KP_Up",           "\033Ox"),
-   KEY("KP_Down",         "\033Or"),
-   KEY("KP_Home",         "\033Ow"),
-   KEY("KP_End",          "\033Oq"),
-   KEY("KP_Prior",        "\033Oy"),
-   KEY("KP_Next",         "\033Os"),
-   KEY("KP_Insert",       "\033Op"),
-   KEY("KP_Delete",       "\033On"),
-   KEY("KP_Enter",        "\033OM"),
-   
-   KEY(NULL, "END")
-};
-
 static Eina_Bool
-_key_try(Termpty *ty, const Keyout *map, const Evas_Event_Key_Down *ev)
+_key_try(Termpty *ty, const Tty_Key *map, int len, const Evas_Event_Key_Down 
*ev,
+         int alt, int shift, int ctrl)
 {
    int i, inlen;
-   
-   if (!ev->key) return EINA_FALSE;
 
    inlen = strlen(ev->key);
-   for (i = 0; map[i].in; i++)
+   for (i = 0; i < len; i++)
      {
-        if ((inlen == map[i].inlen) && (!memcmp(ev->key, map[i].in, inlen)))
+        if ((inlen == map[i].key_len) && (!memcmp(ev->key, map[i].key, inlen)))
           {
-             termpty_write(ty, map[i].out, map[i].outlen);
+             const struct _s *s;
+             const Key_Values *kv;
+
+             if (!ty->state.appcursor)
+               {
+                  kv = &map[i].default_mode;
+               }
+             else
+               {
+                  kv = &map[i].cursor;
+               }
+             if (!alt && !ctrl && !shift)
+                  s = &kv->plain;
+             else if (alt && !ctrl && !shift)
+                  s = &kv->alt;
+             else if (!alt && ctrl && !shift)
+                  s = &kv->ctrl;
+             else if (alt && ctrl && !shift)
+                  s = &kv->ctrl_alt;
+             else if (!alt && !ctrl && shift)
+                  s = &kv->shift;
+             else if (!alt && !ctrl && shift)
+                  s = &kv->shift_alt;
+             else if (!alt && !ctrl && shift)
+                  s = &kv->shift_ctrl;
+             else if (alt && ctrl && shift)
+                  s = &kv->shift_ctrl_alt;
+
+             termpty_write(ty, s->s, s->len);
              return EINA_TRUE;
           }
      }
@@ -434,21 +110,75 @@ keyin_compose_seq_reset(Keys_Handler *khdl)
    khdl->composing = EINA_FALSE;
 }
 
+#include "tty_keys.h"
+
 static void
 _handle_key_to_pty(Termpty *ty, const Evas_Event_Key_Down *ev,
-             int alt, int shift, int ctrl)
+                   int alt, int shift, int ctrl)
 {
-   if (!alt)
+   if (!ev->key)
+     return;
+
+   if (!strcmp(ev->key, "BackSpace"))
+     {
+        if (ty->state.send_bs)
+          {
+             termpty_write(ty, "\b", 1);
+             return;
+          }
+        else
+          {
+             Config *cfg = termpty_config_get(ty);
+
+             if (cfg->erase_is_del)
+               {
+                  termpty_write(ty, "\177", sizeof("\177") - 1);
+               }
+             else
+               {
+                  termpty_write(ty, "\b", sizeof("\b") - 1);
+               }
+             return;
+        }
+     }
+   if (!strcmp(ev->key, "Return"))
      {
       if (ty->state.crlf)
         {
-           if (_key_try(ty, crlf_keyout, ev)) return;
+           termpty_write(ty, "\r\n", sizeof("\r\n") - 1);
+           return;
         }
       else
         {
-           if (_key_try(ty, nocrlf_keyout, ev)) return;
+           termpty_write(ty, "\r", sizeof("\r") - 1);
+           return;
         }
      }
+   if (ev->key && ev->key[0] == 'K' && ev->key[1] == 'k')
+     {
+        if (!evas_key_lock_is_set(ev->locks, "Num_Lock"))
+          {
+             if (ty->state.alt_kp)
+               {
+                  if (_key_try(ty, tty_keys,
+                               
sizeof(tty_keys_kp_app)/sizeof(tty_keys_kp_app[0]),
+                               ev, alt, shift, ctrl))
+                    return;
+               }
+             else
+               {
+                  if (_key_try(ty, tty_keys,
+                               
sizeof(tty_keys_kp_plain)/sizeof(tty_keys_kp_plain[0]),
+                               ev, alt, shift, ctrl))
+                    return;
+               }
+          }
+     }
+   else
+     if (_key_try(ty, tty_keys, sizeof(tty_keys)/sizeof(tty_keys[0]), ev,
+                  alt, shift, ctrl))
+       return;
+#if 0
    if (
        ((ty->state.alt_kp) && (shift))
 //       || ((!ty->state.alt_kp) &&
@@ -485,60 +215,8 @@ _handle_key_to_pty(Termpty *ty, const Evas_Event_Key_Down 
*ev,
              if (_key_try(ty, ctrl_shift_keyout, ev)) return;
           }
      }
-   else if (shift)
-     {
-        if (_key_try(ty, shift_keyout, ev)) return;
-     }
-
-   else if (alt)
-     {
-        if (_key_try(ty, alt_keyout, ev)) return;
-        if (ev->key[0] > 0 && ev->key[1] == '\0')
-          {
-             char echo[2];
-             /* xterm and rxvt differ here about their default options: */
-             /* xterm, altSendsEscape off
-
-             echo[0] = ev->key[0] | 0x80;
-             termpty_write(ty, echo, 1);
-             */
-
-             /* rxvt, with meta8 off, chose it because of utf-8 */
-             echo[0] = 033;
-             echo[1] = ev->key[0];
-             termpty_write(ty, echo, 2);
-             return;
-          }
-     }
-
-   if (ty->state.appcursor)
-     {
-        if (_key_try(ty, appcur_keyout, ev)) return;
-     }
-
-   if (!strcmp(ev->key, "BackSpace"))
-     {
-        if (ty->state.send_bs)
-          {
-             termpty_write(ty, "\b", 1);
-             return;
-          }
-        else
-          {
-             Config *cfg = termpty_config_get(ty);
+#endif
 
-             if (cfg->erase_is_del)
-               {
-                  termpty_write(ty, "\177", sizeof("\177") - 1);
-               }
-             else
-               {
-                  termpty_write(ty, "\b", sizeof("\b") - 1);
-               }
-             return;
-        }
-     }
-   if (_key_try(ty, keyout, ev)) return;
    if (ev->string)
      {
         if ((ev->string[0]) && (!ev->string[1]))
diff --git a/src/bin/keyin.h b/src/bin/keyin.h
index e7b8aea..bf5ba6e 100644
--- a/src/bin/keyin.h
+++ b/src/bin/keyin.h
@@ -36,5 +36,4 @@ int keyin_add_config(Config_Keys *cfg_key);
 int keyin_remove_config(Config_Keys *cfg_key);
 void key_bindings_shutdown(void);
 
-
 #endif
diff --git a/src/bin/tty_keys.h b/src/bin/tty_keys.h
new file mode 100644
index 0000000..08b3b5f
--- /dev/null
+++ b/src/bin/tty_keys.h
@@ -0,0 +1,1257 @@
+/* /!\\ This file was heavily generated by gen_tty_keys.sh */
+#define KH(in) { in, sizeof(in) - 1 }
+static const Tty_Key tty_keys[] = {
+{
+  "F1",
+  sizeof("F1") - 1,
+  {
+    KH("\033OP"), // default F1
+    KH("\033[O3P"), // default Alt+F1
+    KH("\033[1;5P"), // default Ctrl+F1
+    KH("\033[1;7P"), // default Ctrl+Alt+F1
+    KH("\033[1;2P"), // default Shift+F1
+    KH("\033[1;4P"), // default Shift+Alt+F1
+    KH("\033[1;6P"), // default Shift+Ctrl+F1
+    KH("\033[1;8P"), // default Shift+Ctrl+Alt+F1
+  },
+  {
+    KH("\033OP"), // cursor F1
+    KH("\033[O3P"), // cursor Alt+F1
+    KH("\033[1;5P"), // cursor Ctrl+F1
+    KH("\033[1;7P"), // cursor Ctrl+Alt+F1
+    KH("\033[1;2P"), // cursor Shift+F1
+    KH("\033[1;4P"), // cursor Shift+Alt+F1
+    KH("\033[1;6P"), // cursor Shift+Ctrl+F1
+    KH("\033[1;8P"), // cursor Shift+Ctrl+Alt+F1
+  },
+},
+{
+  "F2",
+  sizeof("F2") - 1,
+  {
+    KH("\033OQ"), // default F2
+    KH("\033[O3Q"), // default Alt+F2
+    KH("\033[1;5Q"), // default Ctrl+F2
+    KH("\033[1;7Q"), // default Ctrl+Alt+F2
+    KH("\033[1;2Q"), // default Shift+F2
+    KH("\033[1;4Q"), // default Shift+Alt+F2
+    KH("\033[1;6Q"), // default Shift+Ctrl+F2
+    KH("\033[1;8Q"), // default Shift+Ctrl+Alt+F2
+  },
+  {
+    KH("\033OQ"), // cursor F2
+    KH("\033[O3Q"), // cursor Alt+F2
+    KH("\033[1;5Q"), // cursor Ctrl+F2
+    KH("\033[1;7Q"), // cursor Ctrl+Alt+F2
+    KH("\033[1;2Q"), // cursor Shift+F2
+    KH("\033[1;4Q"), // cursor Shift+Alt+F2
+    KH("\033[1;6Q"), // cursor Shift+Ctrl+F2
+    KH("\033[1;8Q"), // cursor Shift+Ctrl+Alt+F2
+  },
+},
+{
+  "F3",
+  sizeof("F3") - 1,
+  {
+    KH("\033OR"), // default F3
+    KH("\033[O3R"), // default Alt+F3
+    KH("\033[1;5R"), // default Ctrl+F3
+    KH("\033[1;7R"), // default Ctrl+Alt+F3
+    KH("\033[1;2R"), // default Shift+F3
+    KH("\033[1;4R"), // default Shift+Alt+F3
+    KH("\033[1;6R"), // default Shift+Ctrl+F3
+    KH("\033[1;8R"), // default Shift+Ctrl+Alt+F3
+  },
+  {
+    KH("\033OR"), // cursor F3
+    KH("\033[O3R"), // cursor Alt+F3
+    KH("\033[1;5R"), // cursor Ctrl+F3
+    KH("\033[1;7R"), // cursor Ctrl+Alt+F3
+    KH("\033[1;2R"), // cursor Shift+F3
+    KH("\033[1;4R"), // cursor Shift+Alt+F3
+    KH("\033[1;6R"), // cursor Shift+Ctrl+F3
+    KH("\033[1;8R"), // cursor Shift+Ctrl+Alt+F3
+  },
+},
+{
+  "F4",
+  sizeof("F4") - 1,
+  {
+    KH("\033OS"), // default F4
+    KH("\033[O3S"), // default Alt+F4
+    KH("\033[1;5S"), // default Ctrl+F4
+    KH("\033[1;7S"), // default Ctrl+Alt+F4
+    KH("\033[1;2S"), // default Shift+F4
+    KH("\033[1;4S"), // default Shift+Alt+F4
+    KH("\033[1;6S"), // default Shift+Ctrl+F4
+    KH("\033[1;8S"), // default Shift+Ctrl+Alt+F4
+  },
+  {
+    KH("\033OS"), // cursor F4
+    KH("\033[O3S"), // cursor Alt+F4
+    KH("\033[1;5S"), // cursor Ctrl+F4
+    KH("\033[1;7S"), // cursor Ctrl+Alt+F4
+    KH("\033[1;2S"), // cursor Shift+F4
+    KH("\033[1;4S"), // cursor Shift+Alt+F4
+    KH("\033[1;6S"), // cursor Shift+Ctrl+F4
+    KH("\033[1;8S"), // cursor Shift+Ctrl+Alt+F4
+  },
+},
+{
+  "F5",
+  sizeof("F5") - 1,
+  {
+    KH("\033[15~"), // default F5
+    KH("\033[15;3~"), // default Alt+F5
+    KH("\033[15;5~"), // default Ctrl+F5
+    KH("\033[15;7~"), // default Ctrl+Alt+F5
+    KH("\033[15;2~"), // default Shift+F5
+    KH("\033[15;4~"), // default Shift+Alt+F5
+    KH("\033[15;6~"), // default Shift+Ctrl+F5
+    KH("\033[15;8~"), // default Shift+Ctrl+Alt+F5
+  },
+  {
+    KH("\033[15~"), // cursor F5
+    KH("\033[15;3~"), // cursor Alt+F5
+    KH("\033[15;5~"), // cursor Ctrl+F5
+    KH("\033[15;7~"), // cursor Ctrl+Alt+F5
+    KH("\033[15;2~"), // cursor Shift+F5
+    KH("\033[15;4~"), // cursor Shift+Alt+F5
+    KH("\033[15;6~"), // cursor Shift+Ctrl+F5
+    KH("\033[15;8~"), // cursor Shift+Ctrl+Alt+F5
+  },
+},
+{
+  "F6",
+  sizeof("F6") - 1,
+  {
+    KH("\033[17~"), // default F6
+    KH("\033[17;3~"), // default Alt+F6
+    KH("\033[17;5~"), // default Ctrl+F6
+    KH("\033[17;7~"), // default Ctrl+Alt+F6
+    KH("\033[17;2~"), // default Shift+F6
+    KH("\033[17;4~"), // default Shift+Alt+F6
+    KH("\033[17;6~"), // default Shift+Ctrl+F6
+    KH("\033[17;8~"), // default Shift+Ctrl+Alt+F6
+  },
+  {
+    KH("\033[17~"), // cursor F6
+    KH("\033[17;3~"), // cursor Alt+F6
+    KH("\033[17;5~"), // cursor Ctrl+F6
+    KH("\033[17;7~"), // cursor Ctrl+Alt+F6
+    KH("\033[17;2~"), // cursor Shift+F6
+    KH("\033[17;4~"), // cursor Shift+Alt+F6
+    KH("\033[17;6~"), // cursor Shift+Ctrl+F6
+    KH("\033[17;8~"), // cursor Shift+Ctrl+Alt+F6
+  },
+},
+{
+  "F7",
+  sizeof("F7") - 1,
+  {
+    KH("\033[18~"), // default F7
+    KH("\033[18;3~"), // default Alt+F7
+    KH("\033[18;5~"), // default Ctrl+F7
+    KH("\033[18;7~"), // default Ctrl+Alt+F7
+    KH("\033[18;2~"), // default Shift+F7
+    KH("\033[18;4~"), // default Shift+Alt+F7
+    KH("\033[18;6~"), // default Shift+Ctrl+F7
+    KH("\033[18;8~"), // default Shift+Ctrl+Alt+F7
+  },
+  {
+    KH("\033[18~"), // cursor F7
+    KH("\033[18;3~"), // cursor Alt+F7
+    KH("\033[18;5~"), // cursor Ctrl+F7
+    KH("\033[18;7~"), // cursor Ctrl+Alt+F7
+    KH("\033[18;2~"), // cursor Shift+F7
+    KH("\033[18;4~"), // cursor Shift+Alt+F7
+    KH("\033[18;6~"), // cursor Shift+Ctrl+F7
+    KH("\033[18;8~"), // cursor Shift+Ctrl+Alt+F7
+  },
+},
+{
+  "F8",
+  sizeof("F8") - 1,
+  {
+    KH("\033[19~"), // default F8
+    KH("\033[19;3~"), // default Alt+F8
+    KH("\033[19;5~"), // default Ctrl+F8
+    KH("\033[19;7~"), // default Ctrl+Alt+F8
+    KH("\033[19;2~"), // default Shift+F8
+    KH("\033[19;4~"), // default Shift+Alt+F8
+    KH("\033[19;6~"), // default Shift+Ctrl+F8
+    KH("\033[19;8~"), // default Shift+Ctrl+Alt+F8
+  },
+  {
+    KH("\033[19~"), // cursor F8
+    KH("\033[19;3~"), // cursor Alt+F8
+    KH("\033[19;5~"), // cursor Ctrl+F8
+    KH("\033[19;7~"), // cursor Ctrl+Alt+F8
+    KH("\033[19;2~"), // cursor Shift+F8
+    KH("\033[19;4~"), // cursor Shift+Alt+F8
+    KH("\033[19;6~"), // cursor Shift+Ctrl+F8
+    KH("\033[19;8~"), // cursor Shift+Ctrl+Alt+F8
+  },
+},
+{
+  "F9",
+  sizeof("F9") - 1,
+  {
+    KH("\033[20~"), // default F9
+    KH("\033[20;3~"), // default Alt+F9
+    KH("\033[20;5~"), // default Ctrl+F9
+    KH("\033[20;7~"), // default Ctrl+Alt+F9
+    KH("\033[20;2~"), // default Shift+F9
+    KH("\033[20;4~"), // default Shift+Alt+F9
+    KH("\033[20;6~"), // default Shift+Ctrl+F9
+    KH("\033[20;8~"), // default Shift+Ctrl+Alt+F9
+  },
+  {
+    KH("\033[20~"), // cursor F9
+    KH("\033[20;3~"), // cursor Alt+F9
+    KH("\033[20;5~"), // cursor Ctrl+F9
+    KH("\033[20;7~"), // cursor Ctrl+Alt+F9
+    KH("\033[20;2~"), // cursor Shift+F9
+    KH("\033[20;4~"), // cursor Shift+Alt+F9
+    KH("\033[20;6~"), // cursor Shift+Ctrl+F9
+    KH("\033[20;8~"), // cursor Shift+Ctrl+Alt+F9
+  },
+},
+{
+  "F10",
+  sizeof("F10") - 1,
+  {
+    KH("\033[21~"), // default F10
+    KH("\033[21;3~"), // default Alt+F10
+    KH("\033[21;5~"), // default Ctrl+F10
+    KH("\033[21;7~"), // default Ctrl+Alt+F10
+    KH("\033[21;2~"), // default Shift+F10
+    KH("\033[21;4~"), // default Shift+Alt+F10
+    KH("\033[21;6~"), // default Shift+Ctrl+F10
+    KH("\033[21;8~"), // default Shift+Ctrl+Alt+F10
+  },
+  {
+    KH("\033[21~"), // cursor F10
+    KH("\033[21;3~"), // cursor Alt+F10
+    KH("\033[21;5~"), // cursor Ctrl+F10
+    KH("\033[21;7~"), // cursor Ctrl+Alt+F10
+    KH("\033[21;2~"), // cursor Shift+F10
+    KH("\033[21;4~"), // cursor Shift+Alt+F10
+    KH("\033[21;6~"), // cursor Shift+Ctrl+F10
+    KH("\033[21;8~"), // cursor Shift+Ctrl+Alt+F10
+  },
+},
+{
+  "F11",
+  sizeof("F11") - 1,
+  {
+    KH("\033[23~"), // default F11
+    KH("\033[23;3~"), // default Alt+F11
+    KH("\033[23;5~"), // default Ctrl+F11
+    KH("\033[23;7~"), // default Ctrl+Alt+F11
+    KH("\033[23;2~"), // default Shift+F11
+    KH("\033[23;4~"), // default Shift+Alt+F11
+    KH("\033[23;6~"), // default Shift+Ctrl+F11
+    KH("\033[23;8~"), // default Shift+Ctrl+Alt+F11
+  },
+  {
+    KH("\033[23~"), // cursor F11
+    KH("\033[23;3~"), // cursor Alt+F11
+    KH("\033[23;5~"), // cursor Ctrl+F11
+    KH("\033[23;7~"), // cursor Ctrl+Alt+F11
+    KH("\033[23;2~"), // cursor Shift+F11
+    KH("\033[23;4~"), // cursor Shift+Alt+F11
+    KH("\033[23;6~"), // cursor Shift+Ctrl+F11
+    KH("\033[23;8~"), // cursor Shift+Ctrl+Alt+F11
+  },
+},
+{
+  "F12",
+  sizeof("F12") - 1,
+  {
+    KH("\033[24~"), // default F12
+    KH("\033[24;3~"), // default Alt+F12
+    KH("\033[24;5~"), // default Ctrl+F12
+    KH("\033[24;7~"), // default Ctrl+Alt+F12
+    KH("\033[24;2~"), // default Shift+F12
+    KH("\033[24;4~"), // default Shift+Alt+F12
+    KH("\033[24;6~"), // default Shift+Ctrl+F12
+    KH("\033[24;8~"), // default Shift+Ctrl+Alt+F12
+  },
+  {
+    KH("\033[24~"), // cursor F12
+    KH("\033[24;3~"), // cursor Alt+F12
+    KH("\033[24;5~"), // cursor Ctrl+F12
+    KH("\033[24;7~"), // cursor Ctrl+Alt+F12
+    KH("\033[24;2~"), // cursor Shift+F12
+    KH("\033[24;4~"), // cursor Shift+Alt+F12
+    KH("\033[24;6~"), // cursor Shift+Ctrl+F12
+    KH("\033[24;8~"), // cursor Shift+Ctrl+Alt+F12
+  },
+},
+{
+  "Left",
+  sizeof("Left") - 1,
+  {
+    KH("\033[D"), // default Left
+    KH("\033[1;3D"), // default Alt+Left
+    KH("\033[1;5D"), // default Ctrl+Left
+    KH("\033[1;7D"), // default Ctrl+Alt+Left
+    KH("\033[1;2D"), // default Shift+Left
+    KH("\033[1;4D"), // default Shift+Alt+Left
+    KH("\033[1;6D"), // default Shift+Ctrl+Left
+    KH("\033[1;8D"), // default Shift+Ctrl+Alt+Left
+  },
+  {
+    KH("\033OD"), // cursor Left
+    KH("\033[1;3D"), // cursor Alt+Left
+    KH("\033[1;5D"), // cursor Ctrl+Left
+    KH("\033[1;7D"), // cursor Ctrl+Alt+Left
+    KH("\033[1;2D"), // cursor Shift+Left
+    KH("\033[1;4D"), // cursor Shift+Alt+Left
+    KH("\033[1;6D"), // cursor Shift+Ctrl+Left
+    KH("\033[1;8D"), // cursor Shift+Ctrl+Alt+Left
+  },
+},
+{
+  "Right",
+  sizeof("Right") - 1,
+  {
+    KH("\033[C"), // default Right
+    KH("\033[1;3C"), // default Alt+Right
+    KH("\033[1;5C"), // default Ctrl+Right
+    KH("\033[1;7C"), // default Ctrl+Alt+Right
+    KH("\033[1;2C"), // default Shift+Right
+    KH("\033[1;4C"), // default Shift+Alt+Right
+    KH("\033[1;6C"), // default Shift+Ctrl+Right
+    KH("\033[1;8C"), // default Shift+Ctrl+Alt+Right
+  },
+  {
+    KH("\033OC"), // cursor Right
+    KH("\033[1;3C"), // cursor Alt+Right
+    KH("\033[1;5C"), // cursor Ctrl+Right
+    KH("\033[1;7C"), // cursor Ctrl+Alt+Right
+    KH("\033[1;2C"), // cursor Shift+Right
+    KH("\033[1;4C"), // cursor Shift+Alt+Right
+    KH("\033[1;6C"), // cursor Shift+Ctrl+Right
+    KH("\033[1;8C"), // cursor Shift+Ctrl+Alt+Right
+  },
+},
+{
+  "Up",
+  sizeof("Up") - 1,
+  {
+    KH("\033[A"), // default Up
+    KH("\033[1;3A"), // default Alt+Up
+    KH("\033[1;5A"), // default Ctrl+Up
+    KH("\033[1;7A"), // default Ctrl+Alt+Up
+    KH("\033[1;2A"), // default Shift+Up
+    KH("\033[1;4A"), // default Shift+Alt+Up
+    {NULL, 0}, // default Shift+Ctrl+Up
+    {NULL, 0}, // default Shift+Ctrl+Alt+Up
+  },
+  {
+    KH("\033OA"), // cursor Up
+    KH("\033[1;3A"), // cursor Alt+Up
+    KH("\033[1;5A"), // cursor Ctrl+Up
+    KH("\033[1;7A"), // cursor Ctrl+Alt+Up
+    KH("\033[1;2A"), // cursor Shift+Up
+    KH("\033[1;4A"), // cursor Shift+Alt+Up
+    {NULL, 0}, // cursor Shift+Ctrl+Up
+    {NULL, 0}, // cursor Shift+Ctrl+Alt+Up
+  },
+},
+{
+  "Down",
+  sizeof("Down") - 1,
+  {
+    KH("\033[B"), // default Down
+    KH("\033[1;3B"), // default Alt+Down
+    KH("\033[1;5B"), // default Ctrl+Down
+    KH("\033[1;7B"), // default Ctrl+Alt+Down
+    KH("\033[1;2B"), // default Shift+Down
+    KH("\033[1;4B"), // default Shift+Alt+Down
+    KH("\033[1;6B"), // default Shift+Ctrl+Down
+    KH("\033[1;8B"), // default Shift+Ctrl+Alt+Down
+  },
+  {
+    KH("\033OB"), // cursor Down
+    KH("\033[1;3B"), // cursor Alt+Down
+    KH("\033[1;5B"), // cursor Ctrl+Down
+    KH("\033[1;7B"), // cursor Ctrl+Alt+Down
+    KH("\033[1;2B"), // cursor Shift+Down
+    KH("\033[1;4B"), // cursor Shift+Alt+Down
+    KH("\033[1;6B"), // cursor Shift+Ctrl+Down
+    KH("\033[1;8B"), // cursor Shift+Ctrl+Alt+Down
+  },
+},
+{
+  "Home",
+  sizeof("Home") - 1,
+  {
+    KH("\033[H"), // default Home
+    KH("\033[1;3H"), // default Alt+Home
+    KH("\033[1;5H"), // default Ctrl+Home
+    KH("\033[1;7H"), // default Ctrl+Alt+Home
+    KH("\033[1;2H"), // default Shift+Home
+    KH("\033[1;4H"), // default Shift+Alt+Home
+    KH("\033[1;6H"), // default Shift+Ctrl+Home
+    KH("\033[1;8H"), // default Shift+Ctrl+Alt+Home
+  },
+  {
+    KH("\033OH"), // cursor Home
+    KH("\033[1;3H"), // cursor Alt+Home
+    KH("\033[1;5H"), // cursor Ctrl+Home
+    KH("\033[1;7H"), // cursor Ctrl+Alt+Home
+    KH("\033[1;2H"), // cursor Shift+Home
+    KH("\033[1;4H"), // cursor Shift+Alt+Home
+    KH("\033[1;6H"), // cursor Shift+Ctrl+Home
+    KH("\033[1;8H"), // cursor Shift+Ctrl+Alt+Home
+  },
+},
+{
+  "End",
+  sizeof("End") - 1,
+  {
+    KH("\033[F"), // default End
+    KH("\033[1;3F"), // default Alt+End
+    KH("\033[1;5F"), // default Ctrl+End
+    KH("\033[1;7F"), // default Ctrl+Alt+End
+    KH("\033[1;2F"), // default Shift+End
+    KH("\033[1;4F"), // default Shift+Alt+End
+    KH("\033[1;6F"), // default Shift+Ctrl+End
+    KH("\033[1;8F"), // default Shift+Ctrl+Alt+End
+  },
+  {
+    KH("\033OF"), // cursor End
+    KH("\033[1;3F"), // cursor Alt+End
+    KH("\033[1;5F"), // cursor Ctrl+End
+    KH("\033[1;7F"), // cursor Ctrl+Alt+End
+    KH("\033[1;2F"), // cursor Shift+End
+    KH("\033[1;4F"), // cursor Shift+Alt+End
+    KH("\033[1;6F"), // cursor Shift+Ctrl+End
+    KH("\033[1;8F"), // cursor Shift+Ctrl+Alt+End
+  },
+},
+{
+  "Insert",
+  sizeof("Insert") - 1,
+  {
+    KH("\033[2~"), // default Insert
+    KH("\033[2;3~"), // default Alt+Insert
+    KH("\033[2;5~"), // default Ctrl+Insert
+    KH("\033[2;7~"), // default Ctrl+Alt+Insert
+    KH("\033[2;2~"), // default Shift+Insert
+    KH("\033[2;4~"), // default Shift+Alt+Insert
+    KH("\033[2;6~"), // default Shift+Ctrl+Insert
+    KH("\033[2;8~"), // default Shift+Ctrl+Alt+Insert
+  },
+  {
+    KH("\033[2~"), // cursor Insert
+    KH("\033[2;3~"), // cursor Alt+Insert
+    KH("\033[2;5~"), // cursor Ctrl+Insert
+    KH("\033[2;7~"), // cursor Ctrl+Alt+Insert
+    KH("\033[2;2~"), // cursor Shift+Insert
+    KH("\033[2;4~"), // cursor Shift+Alt+Insert
+    KH("\033[2;6~"), // cursor Shift+Ctrl+Insert
+    KH("\033[2;8~"), // cursor Shift+Ctrl+Alt+Insert
+  },
+},
+{
+  "Delete",
+  sizeof("Delete") - 1,
+  {
+    KH("\033[3~"), // default Delete
+    KH("\033[3;3~"), // default Alt+Delete
+    KH("\033[3;5~"), // default Ctrl+Delete
+    KH("\033[3;7~"), // default Ctrl+Alt+Delete
+    KH("\033[3;2~"), // default Shift+Delete
+    KH("\033[3;4~"), // default Shift+Alt+Delete
+    KH("\033[3;6~"), // default Shift+Ctrl+Delete
+    KH("\033[3;8~"), // default Shift+Ctrl+Alt+Delete
+  },
+  {
+    KH("\033[3~"), // cursor Delete
+    KH("\033[3;3~"), // cursor Alt+Delete
+    KH("\033[3;5~"), // cursor Ctrl+Delete
+    KH("\033[3;7~"), // cursor Ctrl+Alt+Delete
+    KH("\033[3;2~"), // cursor Shift+Delete
+    KH("\033[3;4~"), // cursor Shift+Alt+Delete
+    KH("\033[3;6~"), // cursor Shift+Ctrl+Delete
+    KH("\033[3;8~"), // cursor Shift+Ctrl+Alt+Delete
+  },
+},
+{
+  "Prior",
+  sizeof("Prior") - 1,
+  {
+    KH("\033[5~"), // default Prior
+    KH("\033[5;3~"), // default Alt+Prior
+    KH("\033[5;5~"), // default Ctrl+Prior
+    KH("\033[5;7~"), // default Ctrl+Alt+Prior
+    KH("\033[5;2~"), // default Shift+Prior
+    KH("\033[5;4~"), // default Shift+Alt+Prior
+    KH("\033[5;6~"), // default Shift+Ctrl+Prior
+    KH("\033[5;8~"), // default Shift+Ctrl+Alt+Prior
+  },
+  {
+    KH("\033[5~"), // cursor Prior
+    KH("\033[5;3~"), // cursor Alt+Prior
+    KH("\033[5;5~"), // cursor Ctrl+Prior
+    KH("\033[5;7~"), // cursor Ctrl+Alt+Prior
+    KH("\033[5;2~"), // cursor Shift+Prior
+    KH("\033[5;4~"), // cursor Shift+Alt+Prior
+    KH("\033[5;6~"), // cursor Shift+Ctrl+Prior
+    KH("\033[5;8~"), // cursor Shift+Ctrl+Alt+Prior
+  },
+},
+{
+  "Next",
+  sizeof("Next") - 1,
+  {
+    KH("\033[6~"), // default Next
+    KH("\033[6;3~"), // default Alt+Next
+    KH("\033[6;5~"), // default Ctrl+Next
+    KH("\033[6;7~"), // default Ctrl+Alt+Next
+    KH("\033[6;2~"), // default Shift+Next
+    KH("\033[6;4~"), // default Shift+Alt+Next
+    KH("\033[6;6~"), // default Shift+Ctrl+Next
+    KH("\033[6;8~"), // default Shift+Ctrl+Alt+Next
+  },
+  {
+    KH("\033[6~"), // cursor Next
+    KH("\033[6;3~"), // cursor Alt+Next
+    KH("\033[6;5~"), // cursor Ctrl+Next
+    KH("\033[6;7~"), // cursor Ctrl+Alt+Next
+    KH("\033[6;2~"), // cursor Shift+Next
+    KH("\033[6;4~"), // cursor Shift+Alt+Next
+    KH("\033[6;6~"), // cursor Shift+Ctrl+Next
+    KH("\033[6;8~"), // cursor Shift+Ctrl+Alt+Next
+  },
+},
+{
+  "Tab",
+  sizeof("Tab") - 1,
+  {
+    KH("\t"), // default Tab
+    KH("\x89"), // default Alt+Tab
+    KH("\t"), // default Ctrl+Tab
+    KH("\x89"), // default Ctrl+Alt+Tab
+    KH("\033[Z"), // default Shift+Tab
+    KH("\033[Z"), // default Shift+Alt+Tab
+    KH("\033[Z"), // default Shift+Ctrl+Tab
+    KH("\033[Z"), // default Shift+Ctrl+Alt+Tab
+  },
+  {
+    KH("\t"), // cursor Tab
+    KH("\x89"), // cursor Alt+Tab
+    KH("\t"), // cursor Ctrl+Tab
+    KH("\x89"), // cursor Ctrl+Alt+Tab
+    KH("\033[Z"), // cursor Shift+Tab
+    KH("\033[Z"), // cursor Shift+Alt+Tab
+    KH("\033[Z"), // cursor Shift+Ctrl+Tab
+    KH("\033[Z"), // cursor Shift+Ctrl+Alt+Tab
+  },
+},
+{
+  "minus",
+  sizeof("minus") - 1,
+  {
+    KH("-"), // default minus
+    KH("­"), // default Alt+minus
+    KH("-"), // default Ctrl+minus
+    KH("­"), // default Ctrl+Alt+minus
+    KH("_"), // default Shift+minus
+    KH("\xdf"), // default Shift+Alt+minus
+    KH("\x1f"), // default Shift+Ctrl+minus
+    KH("\x9f"), // default Shift+Ctrl+Alt+minus
+  },
+  {
+    KH("-"), // cursor minus
+    KH("­"), // cursor Alt+minus
+    KH("-"), // cursor Ctrl+minus
+    KH("­"), // cursor Ctrl+Alt+minus
+    KH("_"), // cursor Shift+minus
+    KH("\xdf"), // cursor Shift+Alt+minus
+    KH("\037"), // cursor Shift+Ctrl+minus
+    KH("\x9f"), // cursor Shift+Ctrl+Alt+minus
+  },
+},
+{
+  "space",
+  sizeof("space") - 1,
+  {
+    KH(" "), // default space
+    KH("\xa0"), // default Alt+space
+    KH("\0"), // default Ctrl+space
+    KH("\x80"), // default Ctrl+Alt+space
+    KH(" "), // default Shift+space
+    KH("\xa0"), // default Shift+Alt+space
+    KH("\0"), // default Shift+Ctrl+space
+    KH("\x80"), // default Shift+Ctrl+Alt+space
+  },
+  {
+    KH(" "), // cursor space
+    KH("\xa0"), // cursor Alt+space
+    KH("\0"), // cursor Ctrl+space
+    KH("\x80"), // cursor Ctrl+Alt+space
+    KH(" "), // cursor Shift+space
+    KH("\xa0"), // cursor Shift+Alt+space
+    KH("\0"), // cursor Shift+Ctrl+space
+    KH("\x80"), // cursor Shift+Ctrl+Alt+space
+  },
+},
+{
+  "Menu",
+  sizeof("Menu") - 1,
+  {
+    KH("\033[29~"), // default Menu
+    KH("\033[29;3~"), // default Alt+Menu
+    KH("\033[29;5~"), // default Ctrl+Menu
+    KH("\033[29;7~"), // default Ctrl+Alt+Menu
+    KH("\033[29;2~"), // default Shift+Menu
+    KH("\033[29;4~"), // default Shift+Alt+Menu
+    KH("\033[29;6~"), // default Shift+Ctrl+Menu
+    KH("\033[29;8~"), // default Shift+Ctrl+Alt+Menu
+  },
+  {
+    KH("\033[29~"), // cursor Menu
+    KH("\033[29;3~"), // cursor Alt+Menu
+    KH("\033[29;5~"), // cursor Ctrl+Menu
+    KH("\033[29;7~"), // cursor Ctrl+Alt+Menu
+    KH("\033[29;2~"), // cursor Shift+Menu
+    KH("\033[29;4~"), // cursor Shift+Alt+Menu
+    KH("\033[29;6~"), // cursor Shift+Ctrl+Menu
+    KH("\033[29;8~"), // cursor Shift+Ctrl+Alt+Menu
+  },
+},
+{
+  "Find",
+  sizeof("Find") - 1,
+  {
+    KH("\033[1~"), // default Find
+    KH("\033[1;3~"), // default Alt+Find
+    KH("\033[1;5~"), // default Ctrl+Find
+    KH("\033[1;7~"), // default Ctrl+Alt+Find
+    KH("\033[1;2~"), // default Shift+Find
+    KH("\033[1;4~"), // default Shift+Alt+Find
+    KH("\033[1;6~"), // default Shift+Ctrl+Find
+    KH("\033[1;8~"), // default Shift+Ctrl+Alt+Find
+  },
+  {
+    KH("\033[1~"), // cursor Find
+    KH("\033[1;3~"), // cursor Alt+Find
+    KH("\033[1;5~"), // cursor Ctrl+Find
+    KH("\033[1;7~"), // cursor Ctrl+Alt+Find
+    KH("\033[1;2~"), // cursor Shift+Find
+    KH("\033[1;4~"), // cursor Shift+Alt+Find
+    KH("\033[1;6~"), // cursor Shift+Ctrl+Find
+    KH("\033[1;8~"), // cursor Shift+Ctrl+Alt+Find
+  },
+},
+{
+  "Help",
+  sizeof("Help") - 1,
+  {
+    KH("\033[28~"), // cursor Help
+    KH("\033[28;3~"), // default Alt+Help
+    KH("\033[28;5~"), // default Ctrl+Help
+    KH("\033[28;7~"), // default Ctrl+Alt+Help
+    KH("\033[28;2~"), // default Shift+Help
+    KH("\033[28;4~"), // default Shift+Alt+Help
+    KH("\033[28;6~"), // default Shift+Ctrl+Help
+    KH("\033[28;8~"), // default Shift+Ctrl+Alt+Help
+  },
+  {
+    KH("\033[28~"), // cursor Help
+    KH("\033[28;3~"), // cursor Alt+Help
+    KH("\033[28;5~"), // cursor Ctrl+Help
+    KH("\033[28;7~"), // cursor Ctrl+Alt+Help
+    KH("\033[28;2~"), // cursor Shift+Help
+    KH("\033[28;4~"), // cursor Shift+Alt+Help
+    KH("\033[28;6~"), // cursor Shift+Ctrl+Help
+    KH("\033[28;8~"), // cursor Shift+Ctrl+Alt+Help
+  },
+},
+{
+  "Execute",
+  sizeof("Execute") - 1,
+  {
+    KH("\033[3~"), // default Execute
+    KH("\033[3;3~"), // default Alt+Execute
+    KH("\033[3;5~"), // default Ctrl+Execute
+    KH("\033[3;7~"), // default Ctrl+Alt+Execute
+    KH("\033[3;2~"), // default Shift+Execute
+    KH("\033[3;4~"), // default Shift+Alt+Execute
+    KH("\033[3;6~"), // default Shift+Ctrl+Execute
+    KH("\033[3;8~"), // default Shift+Ctrl+Alt+Execute
+  },
+  {
+    KH("\033[3~"), // cursor Execute
+    KH("\033[3;3~"), // cursor Alt+Execute
+    KH("\033[3;5~"), // cursor Ctrl+Execute
+    KH("\033[3;7~"), // cursor Ctrl+Alt+Execute
+    KH("\033[3;2~"), // cursor Shift+Execute
+    KH("\033[3;4~"), // cursor Shift+Alt+Execute
+    KH("\033[3;6~"), // cursor Shift+Ctrl+Execute
+    KH("\033[3;8~"), // cursor Shift+Ctrl+Alt+Execute
+  },
+},
+{
+  "Select",
+  sizeof("Select") - 1,
+  {
+    KH("\033[4~"), // default Select
+    KH("\033[4;3~"), // default Alt+Select
+    KH("\033[4;5~"), // default Ctrl+Select
+    KH("\033[4;7~"), // default Ctrl+Alt+Select
+    KH("\033[4;2~"), // default Shift+Select
+    KH("\033[4;4~"), // default Shift+Alt+Select
+    KH("\033[4;6~"), // default Shift+Ctrl+Select
+    KH("\033[4;8~"), // default Shift+Ctrl+Alt+Select
+  },
+  {
+    KH("\033[4~"), // cursor Select
+    KH("\033[4;3~"), // cursor Alt+Select
+    KH("\033[4;5~"), // cursor Ctrl+Select
+    KH("\033[4;7~"), // cursor Ctrl+Alt+Select
+    KH("\033[4;2~"), // cursor Shift+Select
+    KH("\033[4;4~"), // cursor Shift+Alt+Select
+    KH("\033[4;6~"), // cursor Shift+Ctrl+Select
+    KH("\033[4;8~"), // cursor Shift+Ctrl+Alt+Select
+  },
+},
+};
+static const Tty_Key tty_keys_kp_plain[] = {
+{
+  "KP_Up",
+  sizeof("KP_Up") - 1,
+  {
+    KH("\033[A"), // default KP_Up
+    KH("\033[A"), // default Alt+KP_Up
+    KH("\033[A"), // default Ctrl+KP_Up
+    KH("\033[A"), // default Ctrl+Alt+KP_Up
+    KH("8"), // default Shift+KP_Up
+    KH("8"), // default Shift+Alt+KP_Up
+    KH("8"), // default Shift+Ctrl+KP_Up
+    KH("8"), // default Shift+Ctrl+Alt+KP_Up
+  },
+  {
+    KH("\033OA"), // cursor KP_Up
+    KH("\033OA"), // cursor Alt+KP_Up
+    KH("\033OA"), // cursor Ctrl+KP_Up
+    KH("\033OA"), // cursor Ctrl+Alt+KP_Up
+    KH("8"), // cursor Shift+KP_Up
+    KH("8"), // cursor Shift+Alt+KP_Up
+    KH("8"), // cursor Shift+Ctrl+KP_Up
+    KH("8"), // cursor Shift+Ctrl+Alt+KP_Up
+  },
+},
+{
+  "KP_Down",
+  sizeof("KP_Down") - 1,
+  {
+    KH("\033[B"), // default KP_Down
+    KH("\033[B"), // default Alt+KP_Down
+    KH("\033[B"), // default Ctrl+KP_Down
+    KH("\033[B"), // default Ctrl+Alt+KP_Down
+    KH("2"), // default Shift+KP_Down
+    KH("2"), // default Shift+Alt+KP_Down
+    KH("2"), // default Shift+Ctrl+KP_Down
+    KH("2"), // default Shift+Ctrl+Alt+KP_Down
+  },
+  {
+    KH("\033OB"), // cursor KP_Down
+    KH("\033OB"), // cursor Alt+KP_Down
+    KH("\033OB"), // cursor Ctrl+KP_Down
+    KH("\033OB"), // cursor Ctrl+Alt+KP_Down
+    KH("2"), // cursor Shift+KP_Down
+    KH("2"), // cursor Shift+Alt+KP_Down
+    KH("2"), // cursor Shift+Ctrl+KP_Down
+    KH("2"), // cursor Shift+Ctrl+Alt+KP_Down
+  },
+},
+{
+  "KP_Right",
+  sizeof("KP_Right") - 1,
+  {
+    KH("\033[C"), // default KP_Right
+    KH("\033[C"), // default Alt+KP_Right
+    KH("\033[C"), // default Ctrl+KP_Right
+    KH("\033[C"), // default Ctrl+Alt+KP_Right
+    KH("6"), // default Shift+KP_Right
+    KH("6"), // default Shift+Alt+KP_Right
+    KH("6"), // default Shift+Ctrl+KP_Right
+    KH("6"), // default Shift+Ctrl+Alt+KP_Right
+  },
+  {
+    KH("\033OC"), // cursor KP_Right
+    KH("\033OC"), // cursor Alt+KP_Right
+    KH("\033OC"), // cursor Ctrl+KP_Right
+    KH("\033OC"), // cursor Ctrl+Alt+KP_Right
+    KH("6"), // cursor Shift+KP_Right
+    KH("6"), // cursor Shift+Alt+KP_Right
+    KH("6"), // cursor Shift+Ctrl+KP_Right
+    KH("6"), // cursor Shift+Ctrl+Alt+KP_Right
+  },
+},
+{
+  "KP_Left",
+  sizeof("KP_Left") - 1,
+  {
+    KH("\033[D"), // default KP_Left
+    KH("\033[D"), // default Alt+KP_Left
+    KH("\033[D"), // default Ctrl+KP_Left
+    KH("\033[D"), // default Ctrl+Alt+KP_Left
+    KH("4"), // default Shift+KP_Left
+    KH("4"), // default Shift+Alt+KP_Left
+    KH("4"), // default Shift+Ctrl+KP_Left
+    KH("4"), // default Shift+Ctrl+Alt+KP_Left
+  },
+  {
+    KH("\033OD"), // cursor KP_Left
+    KH("\033OD"), // cursor Alt+KP_Left
+    KH("\033OD"), // cursor Ctrl+KP_Left
+    KH("\033OD"), // cursor Ctrl+Alt+KP_Left
+    KH("4"), // cursor Shift+KP_Left
+    KH("4"), // cursor Shift+Alt+KP_Left
+    KH("4"), // cursor Shift+Ctrl+KP_Left
+    KH("4"), // cursor Shift+Ctrl+Alt+KP_Left
+  },
+},
+{
+  "KP_Insert",
+  sizeof("KP_Insert") - 1,
+  {
+    KH("\033[2~"), // default KP_Insert
+    KH("\033[2;3~"), // default Alt+KP_Insert
+    KH("\033[2;5~"), // default Ctrl+KP_Insert
+    KH("\033[2;7~"), // default Ctrl+Alt+KP_Insert
+    KH("\033[2;2~"), // default Shift+KP_Insert
+    KH("\033[2;4~"), // default Shift+Alt+KP_Insert
+    KH("\033[2;6~"), // default Shift+Ctrl+KP_Insert
+    KH("\033[2;8~"), // default Shift+Ctrl+Alt+KP_Insert
+  },
+  {
+    KH("\033[2~"), // cursor KP_Insert
+    KH("\033[2;3~"), // cursor Alt+KP_Insert
+    KH("\033[2;5~"), // cursor Ctrl+KP_Insert
+    KH("\033[2;7~"), // cursor Ctrl+Alt+KP_Insert
+    KH("\033[2;2~"), // cursor Shift+KP_Insert
+    KH("\033[2;4~"), // cursor Shift+Alt+KP_Insert
+    KH("\033[2;6~"), // cursor Shift+Ctrl+KP_Insert
+    KH("\033[2;8~"), // cursor Shift+Ctrl+Alt+KP_Insert
+  },
+},
+{
+  "KP_Delete",
+  sizeof("KP_Delete") - 1,
+  {
+    KH("\033[3~"), // default KP_Delete
+    KH("\033[3;3~"), // default Alt+KP_Delete
+    KH("\033[3;5~"), // default Ctrl+KP_Delete
+    KH("\033[3;7~"), // default Ctrl+Alt+KP_Delete
+    KH("."), // default Shift+KP_Delete
+    KH("."), // default Shift+Alt+KP_Delete
+    KH("."), // default Shift+Ctrl+KP_Delete
+    KH("."), // default Shift+Ctrl+Alt+KP_Delete
+  },
+  {
+    KH("\033[3~"), // cursor KP_Delete
+    KH("\033[3;3~"), // cursor Alt+KP_Delete
+    KH("\033[3;5~"), // cursor Ctrl+KP_Delete
+    KH("\033[3;7~"), // cursor Ctrl+Alt+KP_Delete
+    KH("."), // cursor Shift+KP_Delete
+    KH("."), // cursor Shift+Alt+KP_Delete
+    KH("."), // cursor Shift+Ctrl+KP_Delete
+    KH("."), // cursor Shift+Ctrl+Alt+KP_Delete
+  },
+},
+{
+  "KP_Home",
+  sizeof("KP_Home") - 1,
+  {
+    KH("\033[H"), // default KP_Home
+    KH("\033[H"), // default Alt+KP_Home
+    KH("\033[H"), // default Ctrl+KP_Home
+    KH("\033[H"), // default Ctrl+Alt+KP_Home
+    KH("\033[H"), // default Shift+KP_Home
+    KH("\033[H"), // default Shift+Alt+KP_Home
+    KH("\033[H"), // default Shift+Ctrl+KP_Home
+    KH("\033[H"), // default Shift+Ctrl+Alt+KP_Home
+  },
+  {
+    KH("\033OH"), // cursor KP_Home
+    KH("\033OH"), // cursor Alt+KP_Home
+    KH("\033OH"), // cursor Ctrl+KP_Home
+    KH("\033OH"), // cursor Ctrl+Alt+KP_Home
+    KH("\033OH"), // cursor Shift+KP_Home
+    KH("\033OH"), // cursor Shift+Alt+KP_Home
+    KH("\033OH"), // cursor Shift+Ctrl+KP_Home
+    KH("\033OH"), // cursor Shift+Ctrl+Alt+KP_Home
+  },
+},
+{
+  "KP_Prior",
+  sizeof("KP_Prior") - 1,
+  {
+    KH("\033[5~"), // default KP_Prior
+    KH("\033[5~"), // default Alt+KP_Prior
+    KH("\033[5~"), // default Ctrl+KP_Prior
+    KH("\033[5~"), // default Ctrl+Alt+KP_Prior
+    KH("\033[5~"), // default Shift+KP_Prior
+    KH("\033[5~"), // default Shift+Alt+KP_Prior
+    KH("\033[5~"), // default Shift+Ctrl+KP_Prior
+    KH("\033[5~"), // default Shift+Ctrl+Alt+KP_Prior
+  },
+  {
+    KH("\033[5~"), // cursor KP_Prior
+    KH("\033[5~"), // cursor Alt+KP_Prior
+    KH("\033[5~"), // cursor Ctrl+KP_Prior
+    KH("\033[5~"), // cursor Ctrl+Alt+KP_Prior
+    KH("\033[5~"), // cursor Shift+KP_Prior
+    KH("\033[5~"), // cursor Shift+Alt+KP_Prior
+    KH("\033[5~"), // cursor Shift+Ctrl+KP_Prior
+    KH("\033[5~"), // cursor Shift+Ctrl+Alt+KP_Prior
+  },
+},
+{
+  "KP_Next",
+  sizeof("KP_Next") - 1,
+  {
+    KH("\033[6~"), // default KP_Next
+    KH("\033[6~"), // default Alt+KP_Next
+    KH("\033[6~"), // default Ctrl+KP_Next
+    KH("\033[6~"), // default Ctrl+Alt+KP_Next
+    KH("\033[6~"), // default Shift+KP_Next
+    KH("\033[6~"), // default Shift+Alt+KP_Next
+    KH("\033[6~"), // default Shift+Ctrl+KP_Next
+    KH("\033[6~"), // default Shift+Ctrl+Alt+KP_Next
+  },
+  {
+    KH("\033[6~"), // cursor KP_Next
+    KH("\033[6~"), // cursor Alt+KP_Next
+    KH("\033[6~"), // cursor Ctrl+KP_Next
+    KH("\033[6~"), // cursor Ctrl+Alt+KP_Next
+    KH("\033[6~"), // cursor Shift+KP_Next
+    KH("\033[6~"), // cursor Shift+Alt+KP_Next
+    KH("\033[6~"), // cursor Shift+Ctrl+KP_Next
+    KH("\033[6~"), // cursor Shift+Ctrl+Alt+KP_Next
+  },
+},
+{
+  "KP_Begin",
+  sizeof("KP_Begin") - 1,
+  {
+    KH("\033[E"), // default KP_Begin
+    KH("\033[E"), // default Alt+KP_Begin
+    KH("\033[E"), // default Ctrl+KP_Begin
+    KH("\033[E"), // default Ctrl+Alt+KP_Begin
+    KH("5"), // default Shift+KP_Begin
+    KH("5"), // default Shift+Alt+KP_Begin
+    KH("5"), // default Shift+Ctrl+KP_Begin
+    KH("5"), // default Shift+Ctrl+Alt+KP_Begin
+  },
+  {
+    KH("\033OE"), // cursor KP_Begin
+    KH("\033OE"), // cursor Alt+KP_Begin
+    KH("\033OE"), // cursor Ctrl+KP_Begin
+    KH("\033OE"), // cursor Ctrl+Alt+KP_Begin
+    KH("5"), // cursor Shift+KP_Begin
+    KH("5"), // cursor Shift+Alt+KP_Begin
+    KH("5"), // cursor Shift+Ctrl+KP_Begin
+    KH("5"), // cursor Shift+Ctrl+Alt+KP_Begin
+  },
+},
+{
+  "KP_End",
+  sizeof("KP_End") - 1,
+  {
+    KH("\033[F"), // default KP_End
+    KH("\033[F"), // default Alt+KP_End
+    KH("\033[F"), // default Ctrl+KP_End
+    KH("\033[F"), // default Ctrl+Alt+KP_End
+    KH("\033[F"), // default Shift+KP_End
+    KH("\033[F"), // default Shift+Alt+KP_End
+    KH("\033[F"), // default Shift+Ctrl+KP_End
+    KH("\033[F"), // default Shift+Ctrl+Alt+KP_End
+  },
+  {
+    KH("\033OF"), // cursor KP_End
+    KH("\033OF"), // cursor Alt+KP_End
+    KH("\033OF"), // cursor Ctrl+KP_End
+    KH("\033OF"), // cursor Ctrl+Alt+KP_End
+    KH("\033OF"), // cursor Shift+KP_End
+    KH("\033OF"), // cursor Shift+Alt+KP_End
+    KH("\033OF"), // cursor Shift+Ctrl+KP_End
+    KH("\033OF"), // cursor Shift+Ctrl+Alt+KP_End
+  },
+},
+};
+static const Tty_Key tty_keys_kp_app[] = {
+{
+  "KP_Up",
+  sizeof("KP_Up") - 1,
+  {
+    KH("\033[A"), // default KP_Up
+    KH("\033[1;3A"), // default Alt+KP_Up
+    KH("\033[1;5A"), // default Ctrl+KP_Up
+    KH("\033[1;7A"), // default Ctrl+Alt+KP_Up
+    KH("\033O2x"), // default Shift+KP_Up
+    KH("\033O4x"), // default Shift+Alt+KP_Up
+    KH("\033O6x"), // default Shift+Ctrl+KP_Up
+    KH("\033O8x"), // default Shift+Ctrl+Alt+KP_Up
+  },
+  {
+    KH("\033OA"), // cursor KP_Up
+    KH("\033[1;3A"), // cursor Alt+KP_Up
+    KH("\033[1;5A"), // cursor Ctrl+KP_Up
+    KH("\033[1;7A"), // cursor Ctrl+Alt+KP_Up
+    KH("\033O2x"), // cursor Shift+KP_Up
+    KH("\033O4x"), // cursor Shift+Alt+KP_Up
+    KH("\033O6x"), // cursor Shift+Ctrl+KP_Up
+    KH("\033O8x"), // cursor Shift+Ctrl+Alt+KP_Up
+  },
+},
+{
+  "KP_Down",
+  sizeof("KP_Down") - 1,
+  {
+    KH("\033[B"), // default KP_Down
+    KH("\033[1;3B"), // default Alt+KP_Down
+    KH("\033[1;5B"), // default Ctrl+KP_Down
+    KH("\033[1;7B"), // default Ctrl+Alt+KP_Down
+    KH("\033O2r"), // default Shift+KP_Down
+    KH("\033O4r"), // default Shift+Alt+KP_Down
+    KH("\033O6r"), // default Shift+Ctrl+KP_Down
+    KH("\033O8r"), // default Shift+Ctrl+Alt+KP_Down
+  },
+  {
+    KH("\033OB"), // cursor KP_Down
+    KH("\033[1;3B"), // cursor Alt+KP_Down
+    KH("\033[1;5B"), // cursor Ctrl+KP_Down
+    KH("\033[1;7B"), // cursor Ctrl+Alt+KP_Down
+    KH("\033O2r"), // cursor Shift+KP_Down
+    KH("\033O4r"), // cursor Shift+Alt+KP_Down
+    KH("\033O6r"), // cursor Shift+Ctrl+KP_Down
+    KH("\033O8r"), // cursor Shift+Ctrl+Alt+KP_Down
+  },
+},
+{
+  "KP_Right",
+  sizeof("KP_Right") - 1,
+  {
+    KH("\033[C"), // default KP_Right
+    KH("\033[1;3C"), // default Alt+KP_Right
+    KH("\033[1;5C"), // default Ctrl+KP_Right
+    KH("\033[1;7C"), // default Ctrl+Alt+KP_Right
+    KH("\033O2v"), // default Shift+KP_Right
+    KH("\033O4v"), // default Shift+Alt+KP_Right
+    KH("\033O6v"), // default Shift+Ctrl+KP_Right
+    KH("\033O8v"), // default Shift+Ctrl+Alt+KP_Right
+  },
+  {
+    KH("\033OC"), // cursor KP_Right
+    KH("\033[1;3C"), // cursor Alt+KP_Right
+    KH("\033[1;5C"), // cursor Ctrl+KP_Right
+    KH("\033[1;7C"), // cursor Ctrl+Alt+KP_Right
+    KH("\033O2v"), // cursor Shift+KP_Right
+    KH("\033O4v"), // cursor Shift+Alt+KP_Right
+    KH("\033O6v"), // cursor Shift+Ctrl+KP_Right
+    KH("\033O8v"), // cursor Shift+Ctrl+Alt+KP_Right
+  },
+},
+{
+  "KP_Left",
+  sizeof("KP_Left") - 1,
+  {
+    KH("\033[D"), // default KP_Left
+    KH("\033[1;3D"), // default Alt+KP_Left
+    KH("\033[1;5D"), // default Ctrl+KP_Left
+    KH("\033[1;7D"), // default Ctrl+Alt+KP_Left
+    KH("\033O2t"), // default Shift+KP_Left
+    KH("\033O4t"), // default Shift+Alt+KP_Left
+    KH("\033O6t"), // default Shift+Ctrl+KP_Left
+    KH("\033O8t"), // default Shift+Ctrl+Alt+KP_Left
+  },
+  {
+    KH("\033OD"), // cursor KP_Left
+    KH("\033[1;3D"), // cursor Alt+KP_Left
+    KH("\033[1;5D"), // cursor Ctrl+KP_Left
+    KH("\033[1;7D"), // cursor Ctrl+Alt+KP_Left
+    KH("\033O2t"), // cursor Shift+KP_Left
+    KH("\033O4t"), // cursor Shift+Alt+KP_Left
+    KH("\033O6t"), // cursor Shift+Ctrl+KP_Left
+    KH("\033O8t"), // cursor Shift+Ctrl+Alt+KP_Left
+  },
+},
+{
+  "KP_Insert",
+  sizeof("KP_Insert") - 1,
+  {
+    KH("\033[2~"), // default KP_Insert
+    KH("\033[2;3~"), // default Alt+KP_Insert
+    KH("\033[2;5~"), // default Ctrl+KP_Insert
+    KH("\033[2;7~"), // default Ctrl+Alt+KP_Insert
+    KH("\033[2;2~"), // default Shift+KP_Insert
+    KH("\033[2;4~"), // default Shift+Alt+KP_Insert
+    KH("\033[2;6~"), // default Shift+Ctrl+KP_Insert
+    KH("\033[2;8~"), // default Shift+Ctrl+Alt+KP_Insert
+  },
+  {
+    KH("\033[2~"), // cursor KP_Insert
+    KH("\033[2;3~"), // cursor Alt+KP_Insert
+    KH("\033[2;5~"), // cursor Ctrl+KP_Insert
+    KH("\033[2;7~"), // cursor Ctrl+Alt+KP_Insert
+    KH("\033[2;2~"), // cursor Shift+KP_Insert
+    KH("\033[2;4~"), // cursor Shift+Alt+KP_Insert
+    KH("\033[2;6~"), // cursor Shift+Ctrl+KP_Insert
+    KH("\033[2;8~"), // cursor Shift+Ctrl+Alt+KP_Insert
+  },
+},
+{
+  "KP_Delete",
+  sizeof("KP_Delete") - 1,
+  {
+    KH("\033[3~"), // default KP_Delete
+    KH("\033[3;3~"), // default Alt+KP_Delete
+    KH("\033[3;5~"), // default Ctrl+KP_Delete
+    KH("\033[3;7~"), // default Ctrl+Alt+KP_Delete
+    KH("\033O2n"), // default Shift+KP_Delete
+    KH("\033O4n"), // default Shift+Alt+KP_Delete
+    KH("\033O6n"), // default Shift+Ctrl+KP_Delete
+    KH("\033O8n"), // default Shift+Ctrl+Alt+KP_Delete
+  },
+  {
+    KH("\033[3~"), // cursor KP_Delete
+    KH("\033[3;3~"), // cursor Alt+KP_Delete
+    KH("\033[3;5~"), // cursor Ctrl+KP_Delete
+    KH("\033[3;7~"), // cursor Ctrl+Alt+KP_Delete
+    KH("\033O2n"), // cursor Shift+KP_Delete
+    KH("\033O4n"), // cursor Shift+Alt+KP_Delete
+    KH("\033O6n"), // cursor Shift+Ctrl+KP_Delete
+    KH("\033O8n"), // cursor Shift+Ctrl+Alt+KP_Delete
+  },
+},
+{
+  "KP_Home",
+  sizeof("KP_Home") - 1,
+  {
+    KH("\033[H"), // default KP_Home
+    KH("\033[1;3H"), // default Alt+KP_Home
+    KH("\033[1;5H"), // default Ctrl+KP_Home
+    KH("\033[1;7H"), // default Ctrl+Alt+KP_Home
+    KH("\033[1;2H"), // default Shift+KP_Home
+    KH("\033[1;4H"), // default Shift+Alt+KP_Home
+    KH("\033[1;6H"), // default Shift+Ctrl+KP_Home
+    KH("\033[1;8H"), // default Shift+Ctrl+Alt+KP_Home
+  },
+  {
+    KH("\033OH"), // cursor KP_Home
+    KH("\033[1;3H"), // cursor Alt+KP_Home
+    KH("\033[1;5H"), // cursor Ctrl+KP_Home
+    KH("\033[1;7H"), // cursor Ctrl+Alt+KP_Home
+    KH("\033[1;2H"), // cursor Shift+KP_Home
+    KH("\033[1;4H"), // cursor Shift+Alt+KP_Home
+    KH("\033[1;6H"), // cursor Shift+Ctrl+KP_Home
+    KH("\033[1;8H"), // cursor Shift+Ctrl+Alt+KP_Home
+  },
+},
+{
+  "KP_Prior",
+  sizeof("KP_Prior") - 1,
+  {
+    KH("\033[5~"), // default KP_Prior
+    KH("\033[5;3~"), // default Alt+KP_Prior
+    KH("\033[5;5~"), // default Ctrl+KP_Prior
+    KH("\033[5;7~"), // default Ctrl+Alt+KP_Prior
+    KH("\033[5;2~"), // default Shift+KP_Prior
+    KH("\033[5;4~"), // default Shift+Alt+KP_Prior
+    KH("\033[5;6~"), // default Shift+Ctrl+KP_Prior
+    KH("\033[5;8~"), // default Shift+Ctrl+Alt+KP_Prior
+  },
+  {
+    KH("\033[5~"), // cursor KP_Prior
+    KH("\033[5;3~"), // cursor Alt+KP_Prior
+    KH("\033[5;5~"), // cursor Ctrl+KP_Prior
+    KH("\033[5;7~"), // cursor Ctrl+Alt+KP_Prior
+    KH("\033[5;2~"), // cursor Shift+KP_Prior
+    KH("\033[5;4~"), // cursor Shift+Alt+KP_Prior
+    KH("\033[5;6~"), // cursor Shift+Ctrl+KP_Prior
+    KH("\033[5;8~"), // cursor Shift+Ctrl+Alt+KP_Prior
+  },
+},
+{
+  "KP_Next",
+  sizeof("KP_Next") - 1,
+  {
+    KH("\033[6~"), // default KP_Next
+    KH("\033[6;3~"), // default Alt+KP_Next
+    KH("\033[6;5~"), // default Ctrl+KP_Next
+    KH("\033[6;7~"), // default Ctrl+Alt+KP_Next
+    KH("\033[6;2~"), // default Shift+KP_Next
+    KH("\033[6;4~"), // default Shift+Alt+KP_Next
+    KH("\033[6;6~"), // default Shift+Ctrl+KP_Next
+    KH("\033[6;8~"), // default Shift+Ctrl+Alt+KP_Next
+  },
+  {
+    KH("\033[6~"), // cursor KP_Next
+    KH("\033[6;3~"), // cursor Alt+KP_Next
+    KH("\033[6;5~"), // cursor Ctrl+KP_Next
+    KH("\033[6;7~"), // cursor Ctrl+Alt+KP_Next
+    KH("\033[6;2~"), // cursor Shift+KP_Next
+    KH("\033[6;4~"), // cursor Shift+Alt+KP_Next
+    KH("\033[6;6~"), // cursor Shift+Ctrl+KP_Next
+    KH("\033[6;8~"), // cursor Shift+Ctrl+Alt+KP_Next
+  },
+},
+{
+  "KP_Begin",
+  sizeof("KP_Begin") - 1,
+  {
+    KH("\033[E"), // default KP_Begin
+    KH("\033[1;3E"), // default Alt+KP_Begin
+    KH("\033[1;5E"), // default Ctrl+KP_Begin
+    KH("\033[1;7E"), // default Ctrl+Alt+KP_Begin
+    KH("\033O2u"), // default Shift+KP_Begin
+    KH("\033O4u"), // default Shift+Alt+KP_Begin
+    KH("\033O6u"), // default Shift+Ctrl+KP_Begin
+    KH("\033O8u"), // default Shift+Ctrl+Alt+KP_Begin
+  },
+  {
+    KH("\033OE"), // cursor KP_Begin
+    KH("\033[1;3E"), // cursor Alt+KP_Begin
+    KH("\033[1;5E"), // cursor Ctrl+KP_Begin
+    KH("\033[1;7E"), // cursor Ctrl+Alt+KP_Begin
+    KH("\033O2u"), // cursor Shift+KP_Begin
+    KH("\033O4u"), // cursor Shift+Alt+KP_Begin
+    KH("\033O6u"), // cursor Shift+Ctrl+KP_Begin
+    KH("\033O8u"), // cursor Shift+Ctrl+Alt+KP_Begin
+  },
+},
+{
+  "KP_End",
+  sizeof("KP_End") - 1,
+  {
+    KH("\033[F"), // default KP_End
+    KH("\033[1;3F"), // default Alt+KP_End
+    KH("\033[1;5F"), // default Ctrl+KP_End
+    KH("\033[1;7F"), // default Ctrl+Alt+KP_End
+    KH("\033[1;2F"), // default Shift+KP_End
+    KH("\033[1;4F"), // default Shift+Alt+KP_End
+    KH("\033[1;6F"), // default Shift+Ctrl+KP_End
+    KH("\033[1;8F"), // default Shift+Ctrl+Alt+KP_End
+  },
+  {
+    KH("\033OF"), // cursor KP_End
+    KH("\033[1;3F"), // cursor Alt+KP_End
+    KH("\033[1;5F"), // cursor Ctrl+KP_End
+    KH("\033[1;7F"), // cursor Ctrl+Alt+KP_End
+    KH("\033[1;2F"), // cursor Shift+KP_End
+    KH("\033[1;4F"), // cursor Shift+Alt+KP_End
+    KH("\033[1;6F"), // cursor Shift+Ctrl+KP_End
+    KH("\033[1;8F"), // cursor Shift+Ctrl+Alt+KP_End
+  },
+},
+};
+#undef KH
diff --git a/tools/gen_tty_keys.sh b/tools/gen_tty_keys.sh
new file mode 100755
index 0000000..e12db8b
--- /dev/null
+++ b/tools/gen_tty_keys.sh
@@ -0,0 +1,277 @@
+#!/bin/bash
+
+if [ -z "$(type -p xdotool)" ]; then
+       echo 'Install xdotool!' >&2
+       exit 1
+fi
+
+if [ -z "$(type -p numlockx)" ]; then
+       echo 'Install numlockx!' >&2
+       exit 1
+fi
+
+if [ -t 1 ]; then
+       echo 'Redirect the output to a file!' >&2
+       exit 1
+fi
+
+function do_reset {
+       echo -ne '\e[?1050l' >&2
+       echo -ne '\e[?1051l' >&2
+       echo -ne '\e[?1052l' >&2
+       echo -ne '\e[?1053l' >&2
+       echo -ne '\e[?1060l' >&2
+       echo -ne '\e[?1061l' >&2
+       echo -ne '\e[?1l' >&2  # normal cursor mode
+       echo -ne '\e>' >&2     # normal keypad mode
+}
+
+do_key() {
+   local key="$1"
+   local shift="$2"
+   local ctrl="$3"
+   local alt="$4"
+   local kind="$5"
+
+   local mod=""
+   local numlock=0
+
+   if [ "$shift" = "1" ]; then
+      mod="${mod}Shift+"
+   fi
+   if [ "$ctrl" = "1" ]; then
+      mod="${mod}Ctrl+"
+   fi
+   if [ "$alt" = "1" ]; then
+      mod="${mod}Alt+"
+   fi
+   if [ "$numlock" = "1" ]; then
+      numlockx on
+   else
+      numlockx off
+   fi
+
+   skip=0
+   if [[ $key =~ F && $alt = 1 ]]; then
+      # Alt+Fx are usually window manager actions
+      skip=1
+   elif [[ $key =~ Insert && ( $shift = 1 || $ctrl = 1 ) ]]; then
+      # {Shift,Ctrl}+Insert is about mouse selection
+      skip=1
+   elif [[ ( $key =~ Home || $key =~ End || $key =~ Page ) && $shift = 1 ]]; 
then
+      # Shift+{PgUp,PgDn,Home,End} effect the scrollbar
+      skip=1
+   elif [[ ( $key =~ Up || $key =~ Down ) && $shift = 1 && $ctrl = 1 ]]; then
+      # Ctrl+Shift+{Up,Dn} also effect the scrollbar
+      skip=1
+   elif [[ ( $key =~ Add || $key =~ Sub ) && ( $shift = 1) ]]; then
+      # Shift+{+,-} changes window size in xterm
+      skip=1
+   fi
+
+   echo "$kind $mod$key" >&2
+   if [ $skip = 0 ]; then
+      xdotool key $mod$key Return
+      if [ $? -eq 0 ]; then
+         IFS='' read -r esc
+         esc="${esc/$'\033'/\\033}"
+      else
+         echo "SEGV: $mod$key" >&2
+         skip=1
+      fi
+   else
+      skip=1
+   fi
+   if [ $skip = 0 ]; then
+      echo "    KH(\"$esc\"), // $kind $mod$key"
+   else
+      echo "    {NULL, 0}, // $kind $mod$key"
+   fi
+
+   sleep 0.1
+   # a bit of healthy paranoia
+   xdotool key at Return
+   IFS='' read -r esc
+   if [ "$esc" != '@' ]; then
+      echo 'Sync error!' >&2
+      exit 1
+   fi
+}
+
+do_keys_mode() {
+
+
+   local keys='F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 Left Right Up Down Home 
End Insert Delete Prior Next Tab minus space Menu Find Help Select '
+
+   echo "#define KH(in) { in, sizeof(in) - 1 }"
+
+   echo "static const Tty_Key tty_keys[] = {"
+   for k in $keys; do
+      echo "{"
+      echo "  \"$k\","
+      echo "  sizeof(\"$k\") - 1,"
+      #default
+      echo "  {"
+      do_reset
+      do_key $k 0 0 0 "default"
+      do_key $k 0 0 1 "default"
+      do_key $k 0 1 0 "default"
+      do_key $k 0 1 1 "default"
+      do_key $k 1 0 0 "default"
+      do_key $k 1 0 1 "default"
+      do_key $k 1 1 0 "default"
+      do_key $k 1 1 1 "default"
+      echo "  },"
+
+      #cursor
+      echo "  {"
+      do_reset
+      echo -ne '\e[?1h' >&2  # application cursor mode
+      do_key $k 0 0 0 "cursor"
+      do_key $k 0 0 1 "cursor"
+      do_key $k 0 1 0 "cursor"
+      do_key $k 0 1 1 "cursor"
+      do_key $k 1 0 0 "cursor"
+      do_key $k 1 0 1 "cursor"
+      do_key $k 1 1 0 "cursor"
+      do_key $k 1 1 1 "cursor"
+      echo "  },"
+      echo "},"
+   done
+   echo "};"
+
+
+   # Kp_*
+
+   keys='KP_Up KP_Down KP_Right KP_Left KP_Insert KP_Delete KP_Home KP_Prior 
KP_Next KP_Begin KP_End'
+
+   echo "static const Tty_Key tty_keys_kp_plain[] = {"
+   for k in $keys; do
+      echo "{"
+      echo "  \"$k\","
+      echo "  sizeof(\"$k\") - 1,"
+      #default
+      echo "  {"
+      do_reset
+      do_key $k 0 0 0 "default"
+      do_key $k 0 0 1 "default"
+      do_key $k 0 1 0 "default"
+      do_key $k 0 1 1 "default"
+      do_key $k 1 0 0 "default"
+      do_key $k 1 0 1 "default"
+      do_key $k 1 1 0 "default"
+      do_key $k 1 1 1 "default"
+      echo "  },"
+
+      #cursor
+      echo "  {"
+      do_reset
+      echo -ne '\e[?1h' >&2  # application cursor mode
+      do_key $k 0 0 0 "cursor"
+      do_key $k 0 0 1 "cursor"
+      do_key $k 0 1 0 "cursor"
+      do_key $k 0 1 1 "cursor"
+      do_key $k 1 0 0 "cursor"
+      do_key $k 1 0 1 "cursor"
+      do_key $k 1 1 0 "cursor"
+      do_key $k 1 1 1 "cursor"
+      echo "  },"
+      echo "},"
+   done
+   echo "};"
+   echo "static const Tty_Key tty_keys_kp_app[] = {"
+   for k in $keys; do
+      echo "{"
+      echo "  \"$k\","
+      echo "  sizeof(\"$k\") - 1,"
+      #default
+      echo "  {"
+      do_reset
+      echo -ne '\e[?1l' >&2  # normal cursor mode
+      echo -ne '\e=' >&2     # application keypad
+      do_key $k 0 0 0 "default"
+      do_key $k 0 0 1 "default"
+      do_key $k 0 1 0 "default"
+      do_key $k 0 1 1 "default"
+      do_key $k 1 0 0 "default"
+      do_key $k 1 0 1 "default"
+      do_key $k 1 1 0 "default"
+      do_key $k 1 1 1 "default"
+      echo "  },"
+
+      #cursor
+      echo "  {"
+      do_reset
+      echo -ne '\e[?1h' >&2  # application cursor mode
+      echo -ne '\e=' >&2     # application keypad
+      do_key $k 0 0 0 "cursor"
+      do_key $k 0 0 1 "cursor"
+      do_key $k 0 1 0 "cursor"
+      do_key $k 0 1 1 "cursor"
+      do_key $k 1 0 0 "cursor"
+      do_key $k 1 0 1 "cursor"
+      do_key $k 1 1 0 "cursor"
+      do_key $k 1 1 1 "cursor"
+      echo "  },"
+      echo "},"
+   done
+   echo "};"
+   #
+   #echo '  normal'
+   #echo '###   normal' >&2
+   #do_one_cursor_and_keypad_mode
+
+   #echo -ne '\e[?1h' >&2  # application cursor mode
+   #echo '  cursor'
+   #echo '###   cursor' >&2
+   #do_one_cursor_and_keypad_mode
+
+   #echo -ne '\e[?1l' >&2  # normal cursor mode
+   #echo -ne '\e=' >&2     # application keypad
+   #echo '  keypad'
+   #echo '###   keypad' >&2
+   #do_one_cursor_and_keypad_mode
+
+   #echo -ne '\e[?1h' >&2  # application cursor mode
+   #echo '  cursor+keypad'
+   #echo '###   cursor+keypad' >&2
+   #do_one_cursor_and_keypad_mode
+
+   echo "#undef KH"
+}
+
+cat <<END >&2
+
+Don't do anything!
+Don't touch your keyboard!  Not even modifiers or numlock!
+Don't change window focus!
+Just leave it running!
+
+Make sure to have English keyboard layout.
+
+Press Ctrl+C if you really need to abort.
+
+END
+
+# Sometimes the first run of xdotool produces some garbage, no clue why.
+xdotool key T e s t space 1 Return
+read x
+xdotool key T e s t space 2 Return
+read x
+if [ "$x" != 'Test 2' ]; then
+       echo "Oops, xdotool doesn't seem to work!" >&2
+       exit 1
+fi
+
+# Let's go!
+
+trap 'do_reset; echo >&2; echo >&2; echo "If your keyboard is stuck, press and 
release the modifiers one by one" >&2' EXIT
+
+do_keys_mode DEFAULT 0
+
+do_reset
+
+echo >&2
+echo "Ready." >&2
+
+trap EXIT

-- 


Reply via email to