mirror of
https://github.com/tmux/tmux.git
synced 2025-03-29 02:08:48 +00:00
Recognise extended key sequences on input (both the forms xterm offers).
This commit is contained in:
parent
5ee4d991b6
commit
e95b644139
103
tty-keys.c
103
tty-keys.c
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <resolv.h>
|
#include <resolv.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -46,6 +47,8 @@ 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 *,
|
static int tty_keys_next1(struct tty *, const char *, size_t, key_code *,
|
||||||
size_t *, int);
|
size_t *, int);
|
||||||
static void tty_keys_callback(int, short, void *);
|
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 *,
|
static int tty_keys_mouse(struct tty *, const char *, size_t, size_t *,
|
||||||
struct mouse_event *);
|
struct mouse_event *);
|
||||||
static int tty_keys_clipboard(struct tty *, const char *, size_t,
|
static int tty_keys_clipboard(struct tty *, const char *, size_t,
|
||||||
@ -690,6 +693,16 @@ tty_keys_next(struct tty *tty)
|
|||||||
goto partial_key;
|
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:
|
first_key:
|
||||||
/* Try to lookup complete key. */
|
/* Try to lookup complete key. */
|
||||||
n = tty_keys_next1(tty, buf, len, &key, &size, expired);
|
n = tty_keys_next1(tty, buf, len, &key, &size, expired);
|
||||||
@ -827,6 +840,96 @@ 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];
|
||||||
|
|
||||||
|
*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 (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 and modifiers. */
|
||||||
|
*key = number|KEYC_XTERM;
|
||||||
|
switch (modifiers) {
|
||||||
|
case 2:
|
||||||
|
(*key) |= KEYC_SHIFT;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
(*key) |= KEYC_ESCAPE;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
(*key) |= (KEYC_SHIFT|KEYC_ESCAPE);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
(*key) |= KEYC_CTRL;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
(*key) |= (KEYC_SHIFT|KEYC_CTRL);
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
(*key) |= (KEYC_ESCAPE|KEYC_CTRL);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
(*key) |= (KEYC_SHIFT|KEYC_ESCAPE|KEYC_CTRL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*key = KEYC_NONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle mouse key input. Returns 0 for success, -1 for failure, 1 for partial
|
* Handle mouse key input. Returns 0 for success, -1 for failure, 1 for partial
|
||||||
* (probably a mouse sequence but need more data).
|
* (probably a mouse sequence but need more data).
|
||||||
|
Loading…
Reference in New Issue
Block a user