summaryrefslogtreecommitdiffstats
path: root/tty-keys.c
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@openbsd.org>2013-03-21 18:45:38 +0000
committerNicholas Marriott <nicm@openbsd.org>2013-03-21 18:45:38 +0000
commitd4785fe798fff238c65a9324c0a7b6c9ed3efb7f (patch)
tree3aec1af40d2a2138f01c191cbc7841cc68f8b8c9 /tty-keys.c
parent3d24c75d0f9234f7490f6e5277476fb8d6748da6 (diff)
Don't set key KEYC_NONE on xterm_keys_find match()
When calling xterm_keys_find(); if we get a complete match, don't set the key to unknown before calling the action to complete the binding; otherwise non-prefixed bindings will not work. From Thomas Adam
Diffstat (limited to 'tty-keys.c')
-rw-r--r--tty-keys.c142
1 files changed, 61 insertions, 81 deletions
diff --git a/tty-keys.c b/tty-keys.c
index c7f5372d..7fb96786 100644
--- a/tty-keys.c
+++ b/tty-keys.c
@@ -353,17 +353,19 @@ tty_keys_build(struct tty *tty)
tdkr = &tty_default_raw_keys[i];
s = tdkr->string;
- if (s[0] == '\033' && s[1] != '\0')
- tty_keys_add(tty, s + 1, tdkr->key);
+ if (*s != '\0')
+ tty_keys_add(tty, s, tdkr->key);
}
for (i = 0; i < nitems(tty_default_code_keys); i++) {
tdkc = &tty_default_code_keys[i];
s = tty_term_string(tty->term, tdkc->code);
- if (s[0] == '\033' || s[1] == '\0')
- tty_keys_add(tty, s + 1, tdkc->key);
+ if (*s != '\0')
+ tty_keys_add(tty, s, tdkc->key);
}
+
+ tty_keys_add(tty, "abc", 'x');
}
/* Free the entire key tree. */
@@ -439,34 +441,18 @@ tty_keys_next(struct tty *tty)
cc_t bspace;
int key, delay;
+ /* Get key buffer. */
buf = EVBUFFER_DATA(tty->event->input);
len = EVBUFFER_LENGTH(tty->event->input);
if (len == 0)
return (0);
log_debug("keys are %zu (%.*s)", len, (int) len, buf);
- /* If a normal key, return it. */
- if (*buf != '\033') {
- key = (u_char) *buf;
- evbuffer_drain(tty->event->input, 1);
-
- /*
- * Check for backspace key using termios VERASE - the terminfo
- * kbs entry is extremely unreliable, so cannot be safely
- * used. termios should have a better idea.
- */
- bspace = tty->tio.c_cc[VERASE];
- if (bspace != _POSIX_VDISABLE && key == bspace)
- key = KEYC_BSPACE;
- goto handle_key;
- }
-
/* Is this device attributes response? */
switch (tty_keys_device(tty, buf, len, &size)) {
case 0: /* yes */
- evbuffer_drain(tty->event->input, size);
key = KEYC_NONE;
- goto handle_key;
+ goto complete_key;
case -1: /* no, or not valid */
break;
case 1: /* partial */
@@ -476,9 +462,8 @@ tty_keys_next(struct tty *tty)
/* Is this a mouse key press? */
switch (tty_keys_mouse(tty, buf, len, &size)) {
case 0: /* yes */
- evbuffer_drain(tty->event->input, size);
key = KEYC_MOUSE;
- goto handle_key;
+ goto complete_key;
case -1: /* no, or not valid */
break;
case 1: /* partial */
@@ -488,8 +473,7 @@ tty_keys_next(struct tty *tty)
/* Try to parse a key with an xterm-style modifier. */
switch (xterm_keys_find(buf, len, &size, &key)) {
case 0: /* found */
- evbuffer_drain(tty->event->input, size);
- goto handle_key;
+ goto complete_key;
case -1: /* not found */
break;
case 1:
@@ -497,93 +481,90 @@ tty_keys_next(struct tty *tty)
}
/* Look for matching key string and return if found. */
- tk = tty_keys_find(tty, buf + 1, len - 1, &size);
+ tk = tty_keys_find(tty, buf, len, &size);
if (tk != NULL) {
+ if (tk->next != NULL)
+ goto partial_key;
key = tk->key;
- goto found_key;
+ goto complete_key;
}
- /* Skip the escape. */
- buf++;
- len--;
-
- /* Is there a normal key following? */
- if (len != 0 && *buf != '\033') {
- key = *buf | KEYC_ESCAPE;
- evbuffer_drain(tty->event->input, 2);
- goto handle_key;
- }
+ /* Is this a meta key? */
+ if (len >= 2 && buf[0] == '\033') {
+ if (buf[1] != '\033') {
+ key = buf[1] | KEYC_ESCAPE;
+ size = 2;
+ goto complete_key;
+ }
- /* Or a key string? */
- if (len > 1) {
tk = tty_keys_find(tty, buf + 1, len - 1, &size);
if (tk != NULL) {
- key = tk->key | KEYC_ESCAPE;
size++; /* include escape */
- goto found_key;
+ if (tk->next != NULL)
+ goto partial_key;
+ key = tk->key;
+ if (key != KEYC_NONE)
+ key |= KEYC_ESCAPE;
+ goto complete_key;
}
}
- /* Escape and then nothing useful - fall through. */
+first_key:
+ /* No key found, take first. */
+ key = (u_char) *buf;
+ size = 1;
-partial_key:
/*
- * Escape but no key string. If have already seen an escape and the
- * timer has expired, give up waiting and send the escape.
+ * Check for backspace key using termios VERASE - the terminfo
+ * kbs entry is extremely unreliable, so cannot be safely
+ * used. termios should have a better idea.
*/
- if ((tty->flags & TTY_ESCAPE) &&
- evtimer_initialized(&tty->key_timer) &&
- !evtimer_pending(&tty->key_timer, NULL)) {
- evbuffer_drain(tty->event->input, 1);
- key = '\033';
- goto handle_key;
- }
+ bspace = tty->tio.c_cc[VERASE];
+ if (bspace != _POSIX_VDISABLE && key == bspace)
+ key = KEYC_BSPACE;
- /* Fall through to start the timer. */
+ goto complete_key;
-start_timer:
- /* If already waiting for timer, do nothing. */
- if (evtimer_initialized(&tty->key_timer) &&
- evtimer_pending(&tty->key_timer, NULL))
+partial_key:
+ log_debug("partial key %.*s", (int) len, buf);
+
+ /* If timer is going, check for expiration. */
+ if (tty->flags & TTY_TIMER) {
+ if (evtimer_initialized(&tty->key_timer) &&
+ !evtimer_pending(&tty->key_timer, NULL))
+ goto first_key;
return (0);
+ }
- /* Start the timer and wait for expiry or more data. */
+ /* Get the time period. */
delay = options_get_number(&global_options, "escape-time");
tv.tv_sec = delay / 1000;
tv.tv_usec = (delay % 1000) * 1000L;
+ /* Start the timer. */
if (event_initialized(&tty->key_timer))
evtimer_del(&tty->key_timer);
evtimer_set(&tty->key_timer, tty_keys_callback, tty);
evtimer_add(&tty->key_timer, &tv);
- tty->flags |= TTY_ESCAPE;
+ tty->flags |= TTY_TIMER;
return (0);
-found_key:
- if (tk->next != NULL) {
- /* Partial key. Start the timer if not already expired. */
- if (!(tty->flags & TTY_ESCAPE))
- goto start_timer;
+complete_key:
+ log_debug("complete key %.*s %#x", (int) size, buf, key);
- /* Otherwise, if no key, send the escape alone. */
- if (tk->key == KEYC_NONE)
- goto partial_key;
+ /* Remove data from buffer. */
+ evbuffer_drain(tty->event->input, size);
- /* Or fall through to send the partial key found. */
- }
- evbuffer_drain(tty->event->input, size + 1);
-
- goto handle_key;
-
-handle_key:
+ /* Remove key timer. */
if (event_initialized(&tty->key_timer))
evtimer_del(&tty->key_timer);
+ tty->flags &= ~TTY_TIMER;
+ /* Fire the key. */
if (key != KEYC_NONE)
server_client_handle_key(tty->client, key);
- tty->flags &= ~TTY_ESCAPE;
return (1);
}
@@ -594,11 +575,10 @@ tty_keys_callback(unused int fd, unused short events, void *data)
{
struct tty *tty = data;
- if (!(tty->flags & TTY_ESCAPE))
- return;
-
- while (tty_keys_next(tty))
- ;
+ if (tty->flags & TTY_TIMER) {
+ while (tty_keys_next(tty))
+ ;
+ }
}
/*