Merge branch 'master' into sixel

This commit is contained in:
Nicholas Marriott
2021-10-07 13:19:48 +01:00
189 changed files with 30660 additions and 10187 deletions

View File

@@ -21,6 +21,7 @@
#include <netinet/in.h>
#include <ctype.h>
#include <limits.h>
#include <resolv.h>
#include <stdlib.h>
@@ -46,61 +47,98 @@ static struct tty_key *tty_keys_find(struct tty *, const char *, size_t,
static int tty_keys_next1(struct tty *, const char *, size_t, key_code *,
size_t *, int);
static void tty_keys_callback(int, short, void *);
static int tty_keys_extended_key(struct tty *, const char *, size_t,
size_t *, key_code *);
static int tty_keys_mouse(struct tty *, const char *, size_t, size_t *,
struct mouse_event *);
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_status_report(struct tty *, const char *,
static int tty_keys_extended_device_attributes(struct tty *, const char *,
size_t, size_t *);
/* A key tree entry. */
struct tty_key {
char ch;
key_code key;
struct tty_key *left;
struct tty_key *right;
struct tty_key *next;
};
/* 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. */
{ "\033O[", '\033' },
/*
* Numeric keypad. Just use the vt100 escape sequences here and always
* put the terminal into keypad_xmit mode. Translation of numbers
* mode/applications mode is done in input-keys.c.
*/
{ "\033Oo", KEYC_KP_SLASH },
{ "\033Oj", KEYC_KP_STAR },
{ "\033Om", KEYC_KP_MINUS },
{ "\033Ow", KEYC_KP_SEVEN },
{ "\033Ox", KEYC_KP_EIGHT },
{ "\033Oy", KEYC_KP_NINE },
{ "\033Ok", KEYC_KP_PLUS },
{ "\033Ot", KEYC_KP_FOUR },
{ "\033Ou", KEYC_KP_FIVE },
{ "\033Ov", KEYC_KP_SIX },
{ "\033Oq", KEYC_KP_ONE },
{ "\033Or", KEYC_KP_TWO },
{ "\033Os", KEYC_KP_THREE },
{ "\033OM", KEYC_KP_ENTER },
{ "\033Op", KEYC_KP_ZERO },
{ "\033On", KEYC_KP_PERIOD },
{ "\033Oo", KEYC_KP_SLASH|KEYC_KEYPAD },
{ "\033Oj", KEYC_KP_STAR|KEYC_KEYPAD },
{ "\033Om", KEYC_KP_MINUS|KEYC_KEYPAD },
{ "\033Ow", KEYC_KP_SEVEN|KEYC_KEYPAD },
{ "\033Ox", KEYC_KP_EIGHT|KEYC_KEYPAD },
{ "\033Oy", KEYC_KP_NINE|KEYC_KEYPAD },
{ "\033Ok", KEYC_KP_PLUS|KEYC_KEYPAD },
{ "\033Ot", KEYC_KP_FOUR|KEYC_KEYPAD },
{ "\033Ou", KEYC_KP_FIVE|KEYC_KEYPAD },
{ "\033Ov", KEYC_KP_SIX|KEYC_KEYPAD },
{ "\033Oq", KEYC_KP_ONE|KEYC_KEYPAD },
{ "\033Or", KEYC_KP_TWO|KEYC_KEYPAD },
{ "\033Os", KEYC_KP_THREE|KEYC_KEYPAD },
{ "\033OM", KEYC_KP_ENTER|KEYC_KEYPAD },
{ "\033Op", KEYC_KP_ZERO|KEYC_KEYPAD },
{ "\033On", KEYC_KP_PERIOD|KEYC_KEYPAD },
/* Arrow keys. */
{ "\033OA", KEYC_UP },
{ "\033OB", KEYC_DOWN },
{ "\033OC", KEYC_RIGHT },
{ "\033OD", KEYC_LEFT },
{ "\033OA", KEYC_UP|KEYC_CURSOR },
{ "\033OB", KEYC_DOWN|KEYC_CURSOR },
{ "\033OC", KEYC_RIGHT|KEYC_CURSOR },
{ "\033OD", KEYC_LEFT|KEYC_CURSOR },
{ "\033[A", KEYC_UP },
{ "\033[B", KEYC_DOWN },
{ "\033[C", KEYC_RIGHT },
{ "\033[D", KEYC_LEFT },
{ "\033[A", KEYC_UP|KEYC_CURSOR },
{ "\033[B", KEYC_DOWN|KEYC_CURSOR },
{ "\033[C", KEYC_RIGHT|KEYC_CURSOR },
{ "\033[D", KEYC_LEFT|KEYC_CURSOR },
/*
* Meta arrow keys. These do not get the IMPLIED_META flag so they
* don't match the xterm-style meta keys in the output tree - Escape+Up
* should stay as Escape+Up and not become M-Up.
*/
{ "\033\033OA", KEYC_UP|KEYC_CURSOR|KEYC_META },
{ "\033\033OB", KEYC_DOWN|KEYC_CURSOR|KEYC_META },
{ "\033\033OC", KEYC_RIGHT|KEYC_CURSOR|KEYC_META },
{ "\033\033OD", KEYC_LEFT|KEYC_CURSOR|KEYC_META },
{ "\033\033[A", KEYC_UP|KEYC_CURSOR|KEYC_META },
{ "\033\033[B", KEYC_DOWN|KEYC_CURSOR|KEYC_META },
{ "\033\033[C", KEYC_RIGHT|KEYC_CURSOR|KEYC_META },
{ "\033\033[D", KEYC_LEFT|KEYC_CURSOR|KEYC_META },
/* Other (xterm) "cursor" keys. */
{ "\033OH", KEYC_HOME },
{ "\033OF", KEYC_END },
{ "\033\033OH", KEYC_HOME|KEYC_META|KEYC_IMPLIED_META },
{ "\033\033OF", KEYC_END|KEYC_META|KEYC_IMPLIED_META },
{ "\033[H", KEYC_HOME },
{ "\033[F", KEYC_END },
{ "\033\033[H", KEYC_HOME|KEYC_META|KEYC_IMPLIED_META },
{ "\033\033[F", KEYC_END|KEYC_META|KEYC_IMPLIED_META },
/* rxvt-style arrow + modifier keys. */
{ "\033Oa", KEYC_UP|KEYC_CTRL },
{ "\033Ob", KEYC_DOWN|KEYC_CTRL },
@@ -179,15 +217,64 @@ static const struct tty_default_key_raw tty_default_raw_keys[] = {
{ "\033[201~", KEYC_PASTE_END },
};
/* Default xterm keys. */
struct tty_default_key_xterm {
const char *template;
key_code key;
};
static const struct tty_default_key_xterm tty_default_xterm_keys[] = {
{ "\033[1;_P", KEYC_F1 },
{ "\033O1;_P", KEYC_F1 },
{ "\033O_P", KEYC_F1 },
{ "\033[1;_Q", KEYC_F2 },
{ "\033O1;_Q", KEYC_F2 },
{ "\033O_Q", KEYC_F2 },
{ "\033[1;_R", KEYC_F3 },
{ "\033O1;_R", KEYC_F3 },
{ "\033O_R", KEYC_F3 },
{ "\033[1;_S", KEYC_F4 },
{ "\033O1;_S", KEYC_F4 },
{ "\033O_S", KEYC_F4 },
{ "\033[15;_~", KEYC_F5 },
{ "\033[17;_~", KEYC_F6 },
{ "\033[18;_~", KEYC_F7 },
{ "\033[19;_~", KEYC_F8 },
{ "\033[20;_~", KEYC_F9 },
{ "\033[21;_~", KEYC_F10 },
{ "\033[23;_~", KEYC_F11 },
{ "\033[24;_~", KEYC_F12 },
{ "\033[1;_A", KEYC_UP },
{ "\033[1;_B", KEYC_DOWN },
{ "\033[1;_C", KEYC_RIGHT },
{ "\033[1;_D", KEYC_LEFT },
{ "\033[1;_H", KEYC_HOME },
{ "\033[1;_F", KEYC_END },
{ "\033[5;_~", KEYC_PPAGE },
{ "\033[6;_~", KEYC_NPAGE },
{ "\033[2;_~", KEYC_IC },
{ "\033[3;_~", KEYC_DC },
};
static const key_code tty_default_xterm_modifiers[] = {
0,
0,
KEYC_SHIFT,
KEYC_META|KEYC_IMPLIED_META,
KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META,
KEYC_CTRL,
KEYC_SHIFT|KEYC_CTRL,
KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL,
KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL,
KEYC_META|KEYC_IMPLIED_META
};
/*
* Default terminfo(5) keys. Any keys that have builtin modifiers
* (that is, where the key itself contains the modifiers) has the
* KEYC_XTERM flag set so a leading escape is not treated as meta (and
* probably removed).
* Default terminfo(5) keys. Any keys that have builtin modifiers (that is,
* where the key itself contains the modifiers) has the KEYC_XTERM flag set so
* a leading escape is not treated as meta (and probably removed).
*/
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. */
@@ -204,61 +291,61 @@ static const struct tty_default_key_code tty_default_code_keys[] = {
{ TTYC_KF11, KEYC_F11 },
{ TTYC_KF12, KEYC_F12 },
{ TTYC_KF13, KEYC_F1|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KF14, KEYC_F2|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KF15, KEYC_F3|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KF16, KEYC_F4|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KF17, KEYC_F5|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KF18, KEYC_F6|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KF19, KEYC_F7|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KF20, KEYC_F8|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KF21, KEYC_F9|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KF22, KEYC_F10|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KF23, KEYC_F11|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KF24, KEYC_F12|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KF13, KEYC_F1|KEYC_SHIFT },
{ TTYC_KF14, KEYC_F2|KEYC_SHIFT },
{ TTYC_KF15, KEYC_F3|KEYC_SHIFT },
{ TTYC_KF16, KEYC_F4|KEYC_SHIFT },
{ TTYC_KF17, KEYC_F5|KEYC_SHIFT },
{ TTYC_KF18, KEYC_F6|KEYC_SHIFT },
{ TTYC_KF19, KEYC_F7|KEYC_SHIFT },
{ TTYC_KF20, KEYC_F8|KEYC_SHIFT },
{ TTYC_KF21, KEYC_F9|KEYC_SHIFT },
{ TTYC_KF22, KEYC_F10|KEYC_SHIFT },
{ TTYC_KF23, KEYC_F11|KEYC_SHIFT },
{ TTYC_KF24, KEYC_F12|KEYC_SHIFT },
{ TTYC_KF25, KEYC_F1|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF26, KEYC_F2|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF27, KEYC_F3|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF28, KEYC_F4|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF29, KEYC_F5|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF30, KEYC_F6|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF31, KEYC_F7|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF32, KEYC_F8|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF33, KEYC_F9|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF34, KEYC_F10|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF35, KEYC_F11|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF36, KEYC_F12|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF25, KEYC_F1|KEYC_CTRL },
{ TTYC_KF26, KEYC_F2|KEYC_CTRL },
{ TTYC_KF27, KEYC_F3|KEYC_CTRL },
{ TTYC_KF28, KEYC_F4|KEYC_CTRL },
{ TTYC_KF29, KEYC_F5|KEYC_CTRL },
{ TTYC_KF30, KEYC_F6|KEYC_CTRL },
{ TTYC_KF31, KEYC_F7|KEYC_CTRL },
{ TTYC_KF32, KEYC_F8|KEYC_CTRL },
{ TTYC_KF33, KEYC_F9|KEYC_CTRL },
{ TTYC_KF34, KEYC_F10|KEYC_CTRL },
{ TTYC_KF35, KEYC_F11|KEYC_CTRL },
{ TTYC_KF36, KEYC_F12|KEYC_CTRL },
{ TTYC_KF37, KEYC_F1|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF38, KEYC_F2|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF39, KEYC_F3|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF40, KEYC_F4|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF41, KEYC_F5|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF42, KEYC_F6|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF43, KEYC_F7|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF44, KEYC_F8|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF45, KEYC_F9|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF46, KEYC_F10|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF47, KEYC_F11|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF48, KEYC_F12|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KF37, KEYC_F1|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KF38, KEYC_F2|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KF39, KEYC_F3|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KF40, KEYC_F4|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KF41, KEYC_F5|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KF42, KEYC_F6|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KF43, KEYC_F7|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KF44, KEYC_F8|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KF45, KEYC_F9|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KF46, KEYC_F10|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KF47, KEYC_F11|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KF48, KEYC_F12|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KF49, KEYC_F1|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KF50, KEYC_F2|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KF51, KEYC_F3|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KF52, KEYC_F4|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KF53, KEYC_F5|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KF54, KEYC_F6|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KF55, KEYC_F7|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KF56, KEYC_F8|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KF57, KEYC_F9|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KF58, KEYC_F10|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KF59, KEYC_F11|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KF60, KEYC_F12|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KF49, KEYC_F1|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KF50, KEYC_F2|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KF51, KEYC_F3|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KF52, KEYC_F4|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KF53, KEYC_F5|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KF54, KEYC_F6|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KF55, KEYC_F7|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KF56, KEYC_F8|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KF57, KEYC_F9|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KF58, KEYC_F10|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KF59, KEYC_F11|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KF60, KEYC_F12|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KF61, KEYC_F1|KEYC_ESCAPE|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KF62, KEYC_F2|KEYC_ESCAPE|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KF63, KEYC_F3|KEYC_ESCAPE|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KF61, KEYC_F1|KEYC_META|KEYC_IMPLIED_META|KEYC_SHIFT },
{ TTYC_KF62, KEYC_F2|KEYC_META|KEYC_IMPLIED_META|KEYC_SHIFT },
{ TTYC_KF63, KEYC_F3|KEYC_META|KEYC_IMPLIED_META|KEYC_SHIFT },
{ TTYC_KICH1, KEYC_IC },
{ TTYC_KDCH1, KEYC_DC },
@@ -269,74 +356,74 @@ static const struct tty_default_key_code tty_default_code_keys[] = {
{ TTYC_KCBT, KEYC_BTAB },
/* Arrow keys from terminfo. */
{ TTYC_KCUU1, KEYC_UP },
{ TTYC_KCUD1, KEYC_DOWN },
{ TTYC_KCUB1, KEYC_LEFT },
{ TTYC_KCUF1, KEYC_RIGHT },
{ TTYC_KCUU1, KEYC_UP|KEYC_CURSOR },
{ TTYC_KCUD1, KEYC_DOWN|KEYC_CURSOR },
{ TTYC_KCUB1, KEYC_LEFT|KEYC_CURSOR },
{ TTYC_KCUF1, KEYC_RIGHT|KEYC_CURSOR },
/* Key and modifier capabilities. */
{ TTYC_KDC2, KEYC_DC|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KDC3, KEYC_DC|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KDC4, KEYC_DC|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KDC5, KEYC_DC|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KDC6, KEYC_DC|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KDC7, KEYC_DC|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KIND, KEYC_DOWN|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KDN2, KEYC_DOWN|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KDN3, KEYC_DOWN|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KDN4, KEYC_DOWN|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KDN5, KEYC_DOWN|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KDN6, KEYC_DOWN|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KDN7, KEYC_DOWN|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KEND2, KEYC_END|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KEND3, KEYC_END|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KEND4, KEYC_END|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KEND5, KEYC_END|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KEND6, KEYC_END|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KEND7, KEYC_END|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KHOM2, KEYC_HOME|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KHOM3, KEYC_HOME|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KHOM4, KEYC_HOME|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KHOM5, KEYC_HOME|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KHOM6, KEYC_HOME|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KHOM7, KEYC_HOME|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KIC2, KEYC_IC|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KIC3, KEYC_IC|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KIC4, KEYC_IC|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KIC5, KEYC_IC|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KIC6, KEYC_IC|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KIC7, KEYC_IC|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KLFT2, KEYC_LEFT|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KLFT3, KEYC_LEFT|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KLFT4, KEYC_LEFT|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KLFT5, KEYC_LEFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KLFT6, KEYC_LEFT|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KLFT7, KEYC_LEFT|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KNXT2, KEYC_NPAGE|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KNXT3, KEYC_NPAGE|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KNXT4, KEYC_NPAGE|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KNXT5, KEYC_NPAGE|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KNXT6, KEYC_NPAGE|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KNXT7, KEYC_NPAGE|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KPRV2, KEYC_PPAGE|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KPRV3, KEYC_PPAGE|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KPRV4, KEYC_PPAGE|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KPRV5, KEYC_PPAGE|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KPRV6, KEYC_PPAGE|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KPRV7, KEYC_PPAGE|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KRIT2, KEYC_RIGHT|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KRIT3, KEYC_RIGHT|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KRIT4, KEYC_RIGHT|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KRIT5, KEYC_RIGHT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KRIT6, KEYC_RIGHT|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KRIT7, KEYC_RIGHT|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KRI, KEYC_UP|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KUP2, KEYC_UP|KEYC_SHIFT|KEYC_XTERM },
{ TTYC_KUP3, KEYC_UP|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KUP4, KEYC_UP|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
{ TTYC_KUP5, KEYC_UP|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KUP6, KEYC_UP|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KUP7, KEYC_UP|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM },
{ TTYC_KDC2, KEYC_DC|KEYC_SHIFT },
{ TTYC_KDC3, KEYC_DC|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KDC4, KEYC_DC|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KDC5, KEYC_DC|KEYC_CTRL },
{ TTYC_KDC6, KEYC_DC|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KDC7, KEYC_DC|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
{ TTYC_KIND, KEYC_DOWN|KEYC_SHIFT },
{ TTYC_KDN2, KEYC_DOWN|KEYC_SHIFT },
{ TTYC_KDN3, KEYC_DOWN|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KDN4, KEYC_DOWN|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KDN5, KEYC_DOWN|KEYC_CTRL },
{ TTYC_KDN6, KEYC_DOWN|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KDN7, KEYC_DOWN|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
{ TTYC_KEND2, KEYC_END|KEYC_SHIFT },
{ TTYC_KEND3, KEYC_END|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KEND4, KEYC_END|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KEND5, KEYC_END|KEYC_CTRL },
{ TTYC_KEND6, KEYC_END|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KEND7, KEYC_END|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
{ TTYC_KHOM2, KEYC_HOME|KEYC_SHIFT },
{ TTYC_KHOM3, KEYC_HOME|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KHOM4, KEYC_HOME|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KHOM5, KEYC_HOME|KEYC_CTRL },
{ TTYC_KHOM6, KEYC_HOME|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KHOM7, KEYC_HOME|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
{ TTYC_KIC2, KEYC_IC|KEYC_SHIFT },
{ TTYC_KIC3, KEYC_IC|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KIC4, KEYC_IC|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KIC5, KEYC_IC|KEYC_CTRL },
{ TTYC_KIC6, KEYC_IC|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KIC7, KEYC_IC|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
{ TTYC_KLFT2, KEYC_LEFT|KEYC_SHIFT },
{ TTYC_KLFT3, KEYC_LEFT|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KLFT4, KEYC_LEFT|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KLFT5, KEYC_LEFT|KEYC_CTRL },
{ TTYC_KLFT6, KEYC_LEFT|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KLFT7, KEYC_LEFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
{ TTYC_KNXT2, KEYC_NPAGE|KEYC_SHIFT },
{ TTYC_KNXT3, KEYC_NPAGE|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KNXT4, KEYC_NPAGE|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KNXT5, KEYC_NPAGE|KEYC_CTRL },
{ TTYC_KNXT6, KEYC_NPAGE|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KNXT7, KEYC_NPAGE|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
{ TTYC_KPRV2, KEYC_PPAGE|KEYC_SHIFT },
{ TTYC_KPRV3, KEYC_PPAGE|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KPRV4, KEYC_PPAGE|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KPRV5, KEYC_PPAGE|KEYC_CTRL },
{ TTYC_KPRV6, KEYC_PPAGE|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KPRV7, KEYC_PPAGE|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
{ TTYC_KRIT2, KEYC_RIGHT|KEYC_SHIFT },
{ TTYC_KRIT3, KEYC_RIGHT|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KRIT4, KEYC_RIGHT|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KRIT5, KEYC_RIGHT|KEYC_CTRL },
{ TTYC_KRIT6, KEYC_RIGHT|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KRIT7, KEYC_RIGHT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
{ TTYC_KRI, KEYC_UP|KEYC_SHIFT },
{ TTYC_KUP2, KEYC_UP|KEYC_SHIFT },
{ TTYC_KUP3, KEYC_UP|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KUP4, KEYC_UP|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
{ TTYC_KUP5, KEYC_UP|KEYC_CTRL },
{ TTYC_KUP6, KEYC_UP|KEYC_SHIFT|KEYC_CTRL },
{ TTYC_KUP7, KEYC_UP|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
};
/* Add key to tree. */
@@ -345,9 +432,9 @@ 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);
keystr = key_string_lookup_key(key, 1);
if ((tk = tty_keys_find(tty, s, strlen(s), &size)) == NULL) {
log_debug("new key %s: 0x%llx (%s)", s, key, keystr);
tty_keys_add1(&tty->key_tree, s, key);
@@ -400,17 +487,30 @@ void
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;
u_int i, j;
const char *s;
struct options_entry *o;
struct options_array_item *a;
union options_value *ov;
char copy[16];
key_code key;
if (tty->key_tree != NULL)
tty_keys_free(tty);
tty->key_tree = NULL;
for (i = 0; i < nitems(tty_default_xterm_keys); i++) {
tdkx = &tty_default_xterm_keys[i];
for (j = 2; j < nitems(tty_default_xterm_modifiers); j++) {
strlcpy(copy, tdkx->template, sizeof copy);
copy[strcspn(copy, "_")] = '0' + j;
key = tdkx->key|tty_default_xterm_modifiers[j];
tty_keys_add(tty, copy, key);
}
}
for (i = 0; i < nitems(tty_default_raw_keys); i++) {
tdkr = &tty_default_raw_keys[i];
@@ -511,9 +611,8 @@ tty_keys_next1(struct tty *tty, const char *buf, size_t len, key_code *key,
struct tty_key *tk, *tk1;
struct utf8_data ud;
enum utf8_state more;
utf8_char uc;
u_int i;
wchar_t wc;
int n;
log_debug("%s: next key is %zu (%.*s) (expired=%d)", c->name, len,
(int)len, buf, expired);
@@ -531,13 +630,6 @@ tty_keys_next1(struct tty *tty, const char *buf, size_t len, key_code *key,
return (0);
}
/* Is this an an xterm(1) key? */
n = xterm_keys_find(buf, len, size, key);
if (n == 0)
return (0);
if (n == 1 && !expired)
return (1);
/* Is this valid UTF-8? */
more = utf8_open(&ud, (u_char)*buf);
if (more == UTF8_MORE) {
@@ -552,12 +644,12 @@ tty_keys_next1(struct tty *tty, const char *buf, size_t len, key_code *key,
if (more != UTF8_DONE)
return (-1);
if (utf8_combine(&ud, &wc) != UTF8_DONE)
if (utf8_from_data(&ud, &uc) != UTF8_DONE)
return (-1);
*key = wc;
*key = uc;
log_debug("%s: UTF-8 key %.*s %#llx", c->name, (int)ud.size,
buf, *key);
ud.data, *key);
return (0);
}
@@ -578,8 +670,6 @@ tty_keys_next(struct tty *tty)
struct mouse_event m = { 0 };
struct key_event *event;
gettimeofday(&tv, NULL);
/* Get key buffer. */
buf = EVBUFFER_DATA(tty->in);
len = EVBUFFER_LENGTH(tty->in);
@@ -609,8 +699,8 @@ tty_keys_next(struct tty *tty)
goto partial_key;
}
/* Is this a device status report response? */
switch (tty_keys_device_status_report(tty, buf, len, &size)) {
/* Is this an extended device attributes response? */
switch (tty_keys_extended_device_attributes(tty, buf, len, &size)) {
case 0: /* yes */
key = KEYC_UNKNOWN;
goto complete_key;
@@ -634,6 +724,16 @@ tty_keys_next(struct tty *tty)
goto partial_key;
}
/* Is this an extended key press? */
switch (tty_keys_extended_key(tty, buf, len, &size, &key)) {
case 0: /* yes */
goto complete_key;
case -1: /* no, or not valid */
break;
case 1: /* partial */
goto partial_key;
}
first_key:
/* Try to lookup complete key. */
n = tty_keys_next1(tty, buf, len, &key, &size, expired);
@@ -650,7 +750,7 @@ first_key:
/* Look for a key without the escape. */
n = tty_keys_next1(tty, buf + 1, len - 1, &key, &size, expired);
if (n == 0) { /* found */
if (key & KEYC_XTERM) {
if (key & KEYC_IMPLIED_META) {
/*
* We want the escape key as well as the xterm
* key, because the xterm sequence implicitly
@@ -662,7 +762,7 @@ first_key:
size = 1;
goto complete_key;
}
key |= KEYC_ESCAPE;
key |= KEYC_META;
size++;
goto complete_key;
}
@@ -675,7 +775,7 @@ first_key:
* escape). So pass it through even if the timer has not expired.
*/
if (*buf == '\033' && len >= 2) {
key = (u_char)buf[1] | KEYC_ESCAPE;
key = (u_char)buf[1] | KEYC_META;
size = 2;
} else {
key = (u_char)buf[0];
@@ -720,7 +820,7 @@ complete_key:
*/
bspace = tty->tio.c_cc[VERASE];
if (bspace != _POSIX_VDISABLE && (key & KEYC_MASK_KEY) == bspace)
key = (key & KEYC_MASK_MOD) | KEYC_BSPACE;
key = (key & KEYC_MASK_MODIFIERS)|KEYC_BSPACE;
/* Remove data from buffer. */
evbuffer_drain(tty->in, size);
@@ -732,11 +832,13 @@ complete_key:
/* Check for focus events. */
if (key == KEYC_FOCUS_OUT) {
tty->client->flags &= ~CLIENT_FOCUSED;
return (1);
c->flags &= ~CLIENT_FOCUSED;
window_update_focus(c->session->curw->window);
notify_client("client-focus-out", c);
} else if (key == KEYC_FOCUS_IN) {
tty->client->flags |= CLIENT_FOCUSED;
return (1);
c->flags |= CLIENT_FOCUSED;
notify_client("client-focus-in", c);
window_update_focus(c->session->curw->window);
}
/* Fire the key. */
@@ -771,6 +873,134 @@ tty_keys_callback(__unused int fd, __unused short events, void *data)
}
}
/*
* Handle extended key input. This has two forms: \033[27;m;k~ and \033[k;mu,
* where k is key as a number and m is a modifier. Returns 0 for success, -1
* for failure, 1 for partial;
*/
static int
tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
size_t *size, key_code *key)
{
struct client *c = tty->client;
size_t end;
u_int number, modifiers;
char tmp[64];
cc_t bspace;
key_code nkey;
key_code onlykey;
*size = 0;
/* First two 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);
/*
* Look for a terminator. Stop at either '~' or anything that isn't a
* number or ';'.
*/
for (end = 2; end < len && end != sizeof tmp; end++) {
if (buf[end] == '~')
break;
if (!isdigit((u_char)buf[end]) && buf[end] != ';')
break;
}
if (end == len)
return (1);
if (end == sizeof tmp || (buf[end] != '~' && buf[end] != 'u'))
return (-1);
/* Copy to the buffer. */
memcpy(tmp, buf + 2, end);
tmp[end] = '\0';
/* Try to parse either form of key. */
if (buf[end] == '~') {
if (sscanf(tmp, "27;%u;%u", &modifiers, &number) != 2)
return (-1);
} else {
if (sscanf(tmp ,"%u;%u", &number, &modifiers) != 2)
return (-1);
}
*size = end + 1;
/* 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:
nkey |= KEYC_SHIFT;
break;
case 3:
nkey |= (KEYC_META|KEYC_IMPLIED_META);
break;
case 4:
nkey |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META);
break;
case 5:
nkey |= KEYC_CTRL;
break;
case 6:
nkey |= (KEYC_SHIFT|KEYC_CTRL);
break;
case 7:
nkey |= (KEYC_META|KEYC_CTRL);
break;
case 8:
nkey |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL);
break;
case 9:
nkey |= (KEYC_META|KEYC_IMPLIED_META);
break;
default:
*key = KEYC_NONE;
break;
}
/*
* Don't allow both KEYC_CTRL and as an implied modifier. Also convert
* C-X into C-x and so on.
*/
if (nkey & KEYC_CTRL) {
onlykey = (nkey & KEYC_MASK_KEY);
if (onlykey < 32 &&
onlykey != 9 &&
onlykey != 13 &&
onlykey != 27)
/* nothing */;
else if (onlykey >= 97 && onlykey <= 122)
onlykey -= 96;
else if (onlykey >= 64 && onlykey <= 95)
onlykey -= 64;
else if (onlykey == 32)
onlykey = 0;
else if (onlykey == 63)
onlykey = 127;
else
onlykey |= KEYC_CTRL;
nkey = onlykey|((nkey & KEYC_MASK_MODIFIERS) & ~KEYC_CTRL);
}
if (log_get_level() != 0) {
log_debug("%s: extended key %.*s is %llx (%s)", c->name,
(int)*size, buf, nkey, key_string_lookup_key(nkey, 1));
}
*key = nkey;
return (0);
}
/*
* Handle mouse key input. Returns 0 for success, -1 for failure, 1 for partial
* (probably a mouse sequence but need more data).
@@ -933,7 +1163,7 @@ tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len,
*size = 0;
/* First three bytes are always \033]52;. */
/* First five bytes are always \033]52;. */
if (buf[0] != '\033')
return (-1);
if (len == 1)
@@ -1006,9 +1236,16 @@ tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len,
return (0);
}
//XXX primary DA
// for (i = 1; i < n; i++) {
// log_debug("%s: DA feature: %d", c->name, p[i]);
// if (p[i] == 4)
// flags |= TERM_SIXEL;
// }
/*
* Handle device attributes input. Returns 0 for success, -1 for failure, 1 for
* partial.
* Handle secondary device attributes input. Returns 0 for success, -1 for
* failure, 1 for partial.
*/
static int
tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len,
@@ -1017,13 +1254,15 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len,
struct client *c = tty->client;
u_int i, n = 0;
char tmp[64], *endptr, p[32] = { 0 }, *cp, *next;
int flags = 0;
*size = 0;
if (tty->flags & TTY_HAVEDA)
return (-1);
/* First three bytes are always \033[?. */
/*
* First three bytes are always \033[>. Some older Terminal.app
* versions respond as for DA (\033[?) so accept and ignore that.
*/
if (buf[0] != '\033')
return (-1);
if (len == 1)
@@ -1032,15 +1271,17 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len,
return (-1);
if (len == 2)
return (1);
if (buf[2] != '?')
if (buf[2] != '>' && buf[2] != '?')
return (-1);
if (len == 3)
return (1);
/* Copy the rest up to a 'c'. */
for (i = 0; i < (sizeof tmp) - 1 && buf[3 + i] != 'c'; i++) {
for (i = 0; i < (sizeof tmp) - 1; i++) {
if (3 + i == len)
return (1);
if (buf[3 + i] == 'c')
break;
tmp[i] = buf[3 + i];
}
if (i == (sizeof tmp) - 1)
@@ -1048,7 +1289,11 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len,
tmp[i] = '\0';
*size = 4 + i;
/* Convert version numbers. */
/* 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);
@@ -1057,75 +1302,92 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len,
n++;
}
/* Set terminal flags. */
/* Add terminal features. */
switch (p[0]) {
case 64: /* VT420 */
flags |= (TERM_DECFRA|TERM_DECSLRM);
case 41: /* VT420 */
tty_add_features(&c->term_features, "margins,rectfill", ",");
break;
case 'M': /* mintty */
tty_default_features(&c->term_features, "mintty", 0);
break;
case 'T': /* tmux */
tty_default_features(&c->term_features, "tmux", 0);
break;
case 'U': /* rxvt-unicode */
tty_default_features(&c->term_features, "rxvt-unicode", 0);
break;
}
for (i = 1; i < n; i++) {
log_debug("%s: DA feature: %d", c->name, p[i]);
if (p[i] == 4)
flags |= TERM_SIXEL;
}
log_debug("%s: received secondary DA %.*s", c->name, (int)*size, buf);
tty_set_flags(tty, flags);
tty_update_features(tty);
tty->flags |= TTY_HAVEDA;
return (0);
}
/*
* Handle device status report input. Returns 0 for success, -1 for failure, 1
* for partial.
* Handle extended device attributes input. Returns 0 for success, -1 for
* failure, 1 for partial.
*/
static int
tty_keys_device_status_report(struct tty *tty, const char *buf, size_t len,
size_t *size)
tty_keys_extended_device_attributes(struct tty *tty, const char *buf,
size_t len, size_t *size)
{
struct client *c = tty->client;
u_int i;
char tmp[64];
int flags = 0;
char tmp[128];
*size = 0;
if (tty->flags & TTY_HAVEDSR)
if (tty->flags & TTY_HAVEXDA)
return (-1);
/* First three bytes are always \033[. */
/* First four bytes are always \033P>|. */
if (buf[0] != '\033')
return (-1);
if (len == 1)
return (1);
if (buf[1] != '[')
if (buf[1] != 'P')
return (-1);
if (len == 2)
return (1);
if (buf[2] != 'I' && buf[2] != 'T')
if (buf[2] != '>')
return (-1);
if (len == 3)
return (1);
if (buf[3] != '|')
return (-1);
if (len == 4)
return (1);
/* Copy the rest up to a 'n'. */
for (i = 0; i < (sizeof tmp) - 1 && buf[2 + i] != 'n'; i++) {
if (2 + i == len)
/* Copy the rest up to a '\033\\'. */
for (i = 0; i < (sizeof tmp) - 1; i++) {
if (4 + i == len)
return (1);
tmp[i] = buf[2 + i];
if (buf[4 + i - 1] == '\033' && buf[4 + i] == '\\')
break;
tmp[i] = buf[4 + i];
}
if (i == (sizeof tmp) - 1)
return (-1);
tmp[i] = '\0';
*size = 3 + i;
tmp[i - 1] = '\0';
*size = 5 + i;
/* Set terminal flags. */
if (strncmp(tmp, "ITERM2 ", 7) == 0)
flags |= (TERM_DECSLRM|TERM_256COLOURS|TERM_RGBCOLOURS);
if (strncmp(tmp, "TMUX ", 5) == 0)
flags |= (TERM_256COLOURS|TERM_RGBCOLOURS);
log_debug("%s: received DSR %.*s", c->name, (int)*size, buf);
/* Add terminal features. */
if (strncmp(tmp, "iTerm2 ", 7) == 0)
tty_default_features(&c->term_features, "iTerm2", 0);
else if (strncmp(tmp, "tmux ", 5) == 0)
tty_default_features(&c->term_features, "tmux", 0);
else if (strncmp(tmp, "XTerm(", 6) == 0)
tty_default_features(&c->term_features, "XTerm", 0);
else if (strncmp(tmp, "mintty ", 7) == 0)
tty_default_features(&c->term_features, "mintty", 0);
log_debug("%s: received extended DA %.*s", c->name, (int)*size, buf);
tty_set_flags(tty, flags);
tty->flags |= TTY_HAVEDSR;
free(c->term_type);
c->term_type = xstrdup(tmp);
tty_update_features(tty);
tty->flags |= TTY_HAVEXDA;
return (0);
}