Fixes for extended keys: 1) allow C-x and C-X to be bound separately
authornicm <nicm@openbsd.org>
Wed, 7 Apr 2021 07:30:02 +0000 (07:30 +0000)
committernicm <nicm@openbsd.org>
Wed, 7 Apr 2021 07:30:02 +0000 (07:30 +0000)
since some terminals report them differently 2) use the "backspace"
option to translate backspace 3) map ctrl which are have the ctrl
implied (such as C-x) properly when the terminal reports both the key
and the modifier.

Note that any key bindings for C-X where C-x is meant must now be
changed.

usr.bin/tmux/key-string.c
usr.bin/tmux/tty-keys.c

index 74cdad1..eb72dc0 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: key-string.c,v 1.63 2020/07/06 07:27:39 nicm Exp $ */
+/* $OpenBSD: key-string.c,v 1.64 2021/04/07 07:30:02 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -45,9 +45,9 @@ static const struct {
        { "F11",        KEYC_F11|KEYC_IMPLIED_META },
        { "F12",        KEYC_F12|KEYC_IMPLIED_META },
        { "IC",         KEYC_IC|KEYC_IMPLIED_META },
-       { "Insert",     KEYC_IC|KEYC_IMPLIED_META },
+       { "Insert",     KEYC_IC|KEYC_IMPLIED_META },
        { "DC",         KEYC_DC|KEYC_IMPLIED_META },
-       { "Delete",     KEYC_DC|KEYC_IMPLIED_META },
+       { "Delete",     KEYC_DC|KEYC_IMPLIED_META },
        { "Home",       KEYC_HOME|KEYC_IMPLIED_META },
        { "End",        KEYC_END|KEYC_IMPLIED_META },
        { "NPage",      KEYC_NPAGE|KEYC_IMPLIED_META },
@@ -70,7 +70,7 @@ static const struct {
        { "Right",      KEYC_RIGHT|KEYC_CURSOR|KEYC_IMPLIED_META },
 
        /* Numeric keypad. */
-       { "KP/",        KEYC_KP_SLASH|KEYC_KEYPAD },
+       { "KP/",        KEYC_KP_SLASH|KEYC_KEYPAD },
        { "KP*",        KEYC_KP_STAR|KEYC_KEYPAD },
        { "KP-",        KEYC_KP_MINUS|KEYC_KEYPAD },
        { "KP7",        KEYC_KP_SEVEN|KEYC_KEYPAD },
@@ -164,7 +164,7 @@ key_string_get_modifiers(const char **string)
 key_code
 key_string_lookup_string(const char *string)
 {
-       static const char       *other = "!#()+,-.0123456789:;<=>'\r\t";
+       static const char       *other = "!#()+,-.0123456789:;<=>'\r\t\177";
        key_code                 key, modifiers;
        u_int                    u, i;
        struct utf8_data         ud, *udp;
@@ -181,8 +181,8 @@ key_string_lookup_string(const char *string)
 
        /* Is this a hexadecimal value? */
        if (string[0] == '0' && string[1] == 'x') {
-               if (sscanf(string + 2, "%x", &u) != 1)
-                       return (KEYC_UNKNOWN);
+               if (sscanf(string + 2, "%x", &u) != 1)
+                       return (KEYC_UNKNOWN);
                mlen = wctomb(m, u);
                if (mlen <= 0 || mlen > MB_LEN_MAX)
                        return (KEYC_UNKNOWN);
@@ -238,11 +238,11 @@ key_string_lookup_string(const char *string)
        }
 
        /* Convert the standard control keys. */
-       if (key < KEYC_BASE && (modifiers & KEYC_CTRL) && !strchr(other, key)) {
+       if (key < KEYC_BASE && (modifiers & KEYC_CTRL) &&
+           strchr(other, key) == NULL &&
+           (key < 64 || key > 95)) {
                if (key >= 97 && key <= 122)
                        key -= 96;
-               else if (key >= 64 && key <= 95)
-                       key -= 64;
                else if (key == 32)
                        key = 0;
                else if (key == 63)
index bf56cc2..d3db07e 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tty-keys.c,v 1.142 2020/09/23 14:57:33 nicm Exp $ */
+/* $OpenBSD: tty-keys.c,v 1.143 2021/04/07 07:30:02 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -61,7 +61,7 @@ static int    tty_keys_extended_device_attributes(struct tty *, const char *,
 /* Default raw keys. */
 struct tty_default_key_raw {
        const char             *string;
-       key_code                key;
+       key_code                key;
 };
 static const struct tty_default_key_raw tty_default_raw_keys[] = {
        /* Application escape. */
@@ -262,7 +262,7 @@ static const key_code tty_default_xterm_modifiers[] = {
  */
 struct tty_default_key_code {
        enum tty_code_code      code;
-       key_code                key;
+       key_code                key;
 };
 static const struct tty_default_key_code tty_default_code_keys[] = {
        /* Function keys. */
@@ -420,7 +420,7 @@ tty_keys_add(struct tty *tty, const char *s, key_code key)
 {
        struct tty_key  *tk;
        size_t           size;
-       const char      *keystr;
+       const char      *keystr;
 
        keystr = key_string_lookup_key(key, 1);
        if ((tk = tty_keys_find(tty, s, strlen(s), &size)) == NULL) {
@@ -477,7 +477,7 @@ tty_keys_build(struct tty *tty)
        const struct tty_default_key_raw        *tdkr;
        const struct tty_default_key_xterm      *tdkx;
        const struct tty_default_key_code       *tdkc;
-       u_int                                    i, j;
+       u_int                                    i, j;
        const char                              *s;
        struct options_entry                    *o;
        struct options_array_item               *a;
@@ -869,6 +869,8 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
        size_t           end;
        u_int            number, modifiers;
        char             tmp[64];
+       cc_t             bspace;
+       key_code         nkey;
 
        *size = 0;
 
@@ -911,38 +913,61 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
        }
        *size = end + 1;
 
-       /* Store the key and modifiers. */
-       *key = number;
+       /* Store the key. */
+       bspace = tty->tio.c_cc[VERASE];
+       if (bspace != _POSIX_VDISABLE && number == bspace)
+               nkey = KEYC_BSPACE;
+       else
+               nkey = number;
+
+       /* Update the modifiers. */
        switch (modifiers) {
        case 2:
-               (*key) |= KEYC_SHIFT;
+               nkey |= KEYC_SHIFT;
                break;
        case 3:
-               (*key) |= (KEYC_META|KEYC_IMPLIED_META);
+               nkey |= (KEYC_META|KEYC_IMPLIED_META);
                break;
        case 4:
-               (*key) |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META);
+               nkey |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META);
                break;
        case 5:
-               (*key) |= KEYC_CTRL;
+               nkey |= KEYC_CTRL;
                break;
        case 6:
-               (*key) |= (KEYC_SHIFT|KEYC_CTRL);
+               nkey |= (KEYC_SHIFT|KEYC_CTRL);
                break;
        case 7:
-               (*key) |= (KEYC_META|KEYC_CTRL);
+               nkey |= (KEYC_META|KEYC_CTRL);
                break;
        case 8:
-               (*key) |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL);
+               nkey |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL);
                break;
        default:
                *key = KEYC_NONE;
                break;
        }
+
+    /* Don't allow both KEYC_CTRL and implied. */
+       if ((nkey & KEYC_CTRL) && (nkey & KEYC_MASK_KEY) < 32)
+               nkey &= ~KEYC_CTRL;
+       if ((nkey & KEYC_MASK_MODIFIERS) == KEYC_CTRL) {
+               nkey &= KEYC_MASK_KEY;
+               if (nkey >= 97 && nkey <= 122)
+                       nkey -= 96;
+               else if (nkey == 32)
+                       nkey = 0;
+               else if (nkey == 63)
+                       nkey = 127;
+               else
+                       nkey |= KEYC_CTRL;
+       }
+
        if (log_get_level() != 0) {
                log_debug("%s: extended key %.*s is %llx (%s)", c->name,
-                   (int)*size, buf, *key, key_string_lookup_key(*key, 1));
+                   (int)*size, buf, nkey, key_string_lookup_key(nkey, 1));
        }
+       *key = nkey;
        return (0);
 }