aboutsummaryrefslogtreecommitdiff
path: root/tty-keys.c
diff options
context:
space:
mode:
authorJosh Rahm <rahm@google.com>2023-01-27 23:04:47 +0000
committerJosh Rahm <rahm@google.com>2023-01-27 23:04:47 +0000
commite64dc03ff7b867826c7fc76d6fff210ad3382e33 (patch)
tree9cf71b02a7ee8f6d39ae1207201dc0745bdb8be5 /tty-keys.c
parentfb15fd116097b98c1b839cfdc76a7d84e206e6d5 (diff)
parentf5af3cfb211c12897b15e3b5a3b29c4bbb0493a8 (diff)
downloadrtmux-e64dc03ff7b867826c7fc76d6fff210ad3382e33.tar.gz
rtmux-e64dc03ff7b867826c7fc76d6fff210ad3382e33.tar.bz2
rtmux-e64dc03ff7b867826c7fc76d6fff210ad3382e33.zip
Merge remote-tracking branch 'upstream/master' into rahm
Diffstat (limited to 'tty-keys.c')
-rw-r--r--tty-keys.c218
1 files changed, 193 insertions, 25 deletions
diff --git a/tty-keys.c b/tty-keys.c
index bb9ec231..5677f133 100644
--- a/tty-keys.c
+++ b/tty-keys.c
@@ -55,8 +55,11 @@ static int tty_keys_clipboard(struct tty *, const char *, size_t,
size_t *);
static int tty_keys_device_attributes(struct tty *, const char *, size_t,
size_t *);
+static int tty_keys_device_attributes2(struct tty *, const char *, size_t,
+ size_t *);
static int tty_keys_extended_device_attributes(struct tty *, const char *,
size_t, size_t *);
+static int tty_keys_colours(struct tty *, const char *, size_t, size_t *);
/* A key tree entry. */
struct tty_key {
@@ -208,6 +211,9 @@ static const struct tty_default_key_raw tty_default_raw_keys[] = {
/* Paste keys. */
{ "\033[200~", KEYC_PASTE_START },
{ "\033[201~", KEYC_PASTE_END },
+
+ /* Extended keys. */
+ { "\033[1;5Z", '\011'|KEYC_CTRL|KEYC_SHIFT },
};
/* Default xterm keys. */
@@ -681,7 +687,7 @@ tty_keys_next(struct tty *tty)
goto partial_key;
}
- /* Is this a device attributes response? */
+ /* Is this a primary device attributes response? */
switch (tty_keys_device_attributes(tty, buf, len, &size)) {
case 0: /* yes */
key = KEYC_UNKNOWN;
@@ -692,6 +698,17 @@ tty_keys_next(struct tty *tty)
goto partial_key;
}
+ /* Is this a secondary device attributes response? */
+ switch (tty_keys_device_attributes2(tty, buf, len, &size)) {
+ case 0: /* yes */
+ key = KEYC_UNKNOWN;
+ goto complete_key;
+ case -1: /* no, or not valid */
+ break;
+ case 1: /* partial */
+ goto partial_key;
+ }
+
/* Is this an extended device attributes response? */
switch (tty_keys_extended_device_attributes(tty, buf, len, &size)) {
case 0: /* yes */
@@ -703,6 +720,17 @@ tty_keys_next(struct tty *tty)
goto partial_key;
}
+ /* Is this a colours response? */
+ switch (tty_keys_colours(tty, buf, len, &size)) {
+ case 0: /* yes */
+ key = KEYC_UNKNOWN;
+ goto complete_key;
+ case -1: /* no, or not valid */
+ break;
+ case 1: /* partial */
+ goto partial_key;
+ }
+
/* Is this a mouse key press? */
switch (tty_keys_mouse(tty, buf, len, &size, &m)) {
case 0: /* yes */
@@ -1232,7 +1260,7 @@ tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size)
}
/*
- * Handle secondary device attributes input. Returns 0 for success, -1 for
+ * Handle primary device attributes input. Returns 0 for success, -1 for
* failure, 1 for partial.
*/
static int
@@ -1240,17 +1268,15 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len,
size_t *size)
{
struct client *c = tty->client;
+ int *features = &c->term_features;
u_int i, n = 0;
- char tmp[64], *endptr, p[32] = { 0 }, *cp, *next;
+ char tmp[128], *endptr, p[32] = { 0 }, *cp, *next;
*size = 0;
if (tty->flags & TTY_HAVEDA)
return (-1);
- /*
- * First three bytes are always \033[>. Some older Terminal.app
- * versions respond as for DA (\033[?) so accept and ignore that.
- */
+ /* First three bytes are always \033[?. */
if (buf[0] != '\033')
return (-1);
if (len == 1)
@@ -1259,27 +1285,97 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len,
return (-1);
if (len == 2)
return (1);
- if (buf[2] != '>' && buf[2] != '?')
+ if (buf[2] != '?')
return (-1);
if (len == 3)
return (1);
- /* Copy the rest up to a 'c'. */
- for (i = 0; i < (sizeof tmp) - 1; i++) {
+ /* Copy the rest up to a c. */
+ for (i = 0; i < (sizeof tmp); i++) {
if (3 + i == len)
return (1);
if (buf[3 + i] == 'c')
break;
tmp[i] = buf[3 + i];
}
- if (i == (sizeof tmp) - 1)
+ if (i == (sizeof tmp))
return (-1);
tmp[i] = '\0';
*size = 4 + i;
- /* Ignore DA response. */
- if (buf[2] == '?')
- return (0);
+ /* Convert all arguments to numbers. */
+ cp = tmp;
+ while ((next = strsep(&cp, ";")) != NULL) {
+ p[n] = strtoul(next, &endptr, 10);
+ if (*endptr != '\0')
+ p[n] = 0;
+ if (++n == nitems(p))
+ break;
+ }
+
+ /* Add terminal features. */
+ switch (p[0]) {
+ case 62: /* VT220 */
+ case 63: /* VT320 */
+ case 64: /* VT420 */
+ for (i = 1; i < n; i++) {
+ log_debug("%s: DA feature: %d", c->name, p[i]);
+ if (p[i] == 4)
+ tty_add_features(features, "sixel", ",");
+ }
+ break;
+ }
+ log_debug("%s: received primary DA %.*s", c->name, (int)*size, buf);
+
+ tty_update_features(tty);
+ tty->flags |= TTY_HAVEDA;
+
+ return (0);
+}
+
+/*
+ * Handle secondary device attributes input. Returns 0 for success, -1 for
+ * failure, 1 for partial.
+ */
+static int
+tty_keys_device_attributes2(struct tty *tty, const char *buf, size_t len,
+ size_t *size)
+{
+ struct client *c = tty->client;
+ int *features = &c->term_features;
+ u_int i, n = 0;
+ char tmp[128], *endptr, p[32] = { 0 }, *cp, *next;
+
+ *size = 0;
+ if (tty->flags & TTY_HAVEDA2)
+ return (-1);
+
+ /* First three bytes are always \033[>. */
+ if (buf[0] != '\033')
+ return (-1);
+ if (len == 1)
+ return (1);
+ if (buf[1] != '[')
+ return (-1);
+ if (len == 2)
+ return (1);
+ if (buf[2] != '>')
+ return (-1);
+ if (len == 3)
+ return (1);
+
+ /* Copy the rest up to a c. */
+ for (i = 0; i < (sizeof tmp); i++) {
+ if (3 + i == len)
+ return (1);
+ if (buf[3 + i] == 'c')
+ break;
+ tmp[i] = buf[3 + i];
+ }
+ if (i == (sizeof tmp))
+ return (-1);
+ tmp[i] = '\0';
+ *size = 4 + i;
/* Convert all arguments to numbers. */
cp = tmp;
@@ -1287,28 +1383,29 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len,
p[n] = strtoul(next, &endptr, 10);
if (*endptr != '\0')
p[n] = 0;
- n++;
+ if (++n == nitems(p))
+ break;
}
/* Add terminal features. */
switch (p[0]) {
case 41: /* VT420 */
- tty_add_features(&c->term_features, "margins,rectfill", ",");
+ tty_add_features(features, "margins,rectfill", ",");
break;
case 'M': /* mintty */
- tty_default_features(&c->term_features, "mintty", 0);
+ tty_default_features(features, "mintty", 0);
break;
case 'T': /* tmux */
- tty_default_features(&c->term_features, "tmux", 0);
+ tty_default_features(features, "tmux", 0);
break;
case 'U': /* rxvt-unicode */
- tty_default_features(&c->term_features, "rxvt-unicode", 0);
+ tty_default_features(features, "rxvt-unicode", 0);
break;
}
log_debug("%s: received secondary DA %.*s", c->name, (int)*size, buf);
tty_update_features(tty);
- tty->flags |= TTY_HAVEDA;
+ tty->flags |= TTY_HAVEDA2;
return (0);
}
@@ -1322,6 +1419,7 @@ tty_keys_extended_device_attributes(struct tty *tty, const char *buf,
size_t len, size_t *size)
{
struct client *c = tty->client;
+ int *features = &c->term_features;
u_int i;
char tmp[128];
@@ -1347,7 +1445,7 @@ tty_keys_extended_device_attributes(struct tty *tty, const char *buf,
if (len == 4)
return (1);
- /* Copy the rest up to a '\033\\'. */
+ /* Copy the rest up to \033\. */
for (i = 0; i < (sizeof tmp) - 1; i++) {
if (4 + i == len)
return (1);
@@ -1362,13 +1460,13 @@ tty_keys_extended_device_attributes(struct tty *tty, const char *buf,
/* Add terminal features. */
if (strncmp(tmp, "iTerm2 ", 7) == 0)
- tty_default_features(&c->term_features, "iTerm2", 0);
+ tty_default_features(features, "iTerm2", 0);
else if (strncmp(tmp, "tmux ", 5) == 0)
- tty_default_features(&c->term_features, "tmux", 0);
+ tty_default_features(features, "tmux", 0);
else if (strncmp(tmp, "XTerm(", 6) == 0)
- tty_default_features(&c->term_features, "XTerm", 0);
+ tty_default_features(features, "XTerm", 0);
else if (strncmp(tmp, "mintty ", 7) == 0)
- tty_default_features(&c->term_features, "mintty", 0);
+ tty_default_features(features, "mintty", 0);
log_debug("%s: received extended DA %.*s", c->name, (int)*size, buf);
free(c->term_type);
@@ -1379,3 +1477,73 @@ tty_keys_extended_device_attributes(struct tty *tty, const char *buf,
return (0);
}
+
+/*
+ * Handle foreground or background input. Returns 0 for success, -1 for
+ * failure, 1 for partial.
+ */
+static int
+tty_keys_colours(struct tty *tty, const char *buf, size_t len, size_t *size)
+{
+ struct client *c = tty->client;
+ u_int i;
+ char tmp[128];
+ int n;
+
+ *size = 0;
+ if ((tty->flags & TTY_HAVEFG) && (tty->flags & TTY_HAVEBG))
+ return (-1);
+
+ /* First four bytes are always \033]1 and 0 or 1 and ;. */
+ if (buf[0] != '\033')
+ return (-1);
+ if (len == 1)
+ return (1);
+ if (buf[1] != ']')
+ return (-1);
+ if (len == 2)
+ return (1);
+ if (buf[2] != '1')
+ return (-1);
+ if (len == 3)
+ return (1);
+ if (buf[3] != '0' && buf[3] != '1')
+ return (-1);
+ if (len == 4)
+ return (1);
+ if (buf[4] != ';')
+ return (-1);
+ if (len == 5)
+ return (1);
+
+ /* Copy the rest up to \033\ or \007. */
+ for (i = 0; i < (sizeof tmp) - 1; i++) {
+ if (5 + i == len)
+ return (1);
+ if (buf[5 + i - 1] == '\033' && buf[5 + i] == '\\')
+ break;
+ if (buf[5 + i] == '\007')
+ break;
+ tmp[i] = buf[5 + i];
+ }
+ if (i == (sizeof tmp) - 1)
+ return (-1);
+ if (tmp[i - 1] == '\033')
+ tmp[i - 1] = '\0';
+ else
+ tmp[i] = '\0';
+ *size = 6 + i;
+
+ n = colour_parseX11(tmp);
+ if (n != -1 && buf[3] == '0') {
+ log_debug("%s: foreground is %s", c->name, colour_tostring(n));
+ tty->fg = n;
+ tty->flags |= TTY_HAVEFG;
+ } else if (n != -1) {
+ log_debug("%s: background is %s", c->name, colour_tostring(n));
+ tty->bg = n;
+ tty->flags |= TTY_HAVEBG;
+ }
+
+ return (0);
+}