version 1.86, 2016/04/26 22:19:22 |
version 1.87, 2016/04/27 16:40:12 |
|
|
static struct tty_key *tty_keys_find(struct tty *, const char *, size_t, |
static struct tty_key *tty_keys_find(struct tty *, const char *, size_t, |
size_t *); |
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 *); |
size_t *, int); |
static void tty_keys_callback(int, short, void *); |
static void tty_keys_callback(int, short, void *); |
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 *); |
|
|
|
|
/* Look up part of the next key. */ |
/* Look up part of the next key. */ |
static int |
static int |
tty_keys_next1(struct tty *tty, const char *buf, size_t len, key_code *key, |
tty_keys_next1(struct tty *tty, const char *buf, size_t len, key_code *key, |
size_t *size) |
size_t *size, int expired) |
{ |
{ |
struct tty_key *tk, *tk1; |
struct tty_key *tk, *tk1; |
struct utf8_data ud; |
struct utf8_data ud; |
|
|
u_int i; |
u_int i; |
wchar_t wc; |
wchar_t wc; |
|
|
log_debug("next key is %zu (%.*s)", len, (int)len, buf); |
log_debug("next key is %zu (%.*s) (expired=%d)", len, (int)len, buf, |
|
expired); |
|
|
/* Empty buffer is a partial key. */ |
|
if (len == 0) |
|
return (1); |
|
|
|
/* Is this a known key? */ |
/* Is this a known key? */ |
tk = tty_keys_find(tty, buf, len, size); |
tk = tty_keys_find(tty, buf, len, size); |
if (tk != NULL) { |
if (tk != NULL && tk->key != KEYC_UNKNOWN) { |
tk1 = tk; |
tk1 = tk; |
do |
do |
log_debug("keys in list: %#llx", tk->key); |
log_debug("keys in list: %#llx", tk1->key); |
while ((tk1 = tk1->next) != NULL); |
while ((tk1 = tk1->next) != NULL); |
|
if (tk->next != NULL && !expired) |
|
return (1); |
*key = tk->key; |
*key = tk->key; |
return (tk->next != NULL); |
return (0); |
} |
} |
|
|
/* Is this valid UTF-8? */ |
/* Is this valid UTF-8? */ |
more = utf8_open(&ud, (u_char)*buf); |
more = utf8_open(&ud, (u_char)*buf); |
if (more == UTF8_MORE) { |
if (more == UTF8_MORE) { |
*size = ud.size; |
*size = ud.size; |
if (len < ud.size) |
if (len < ud.size) { |
return (1); |
if (!expired) |
|
return (1); |
|
return (-1); |
|
} |
for (i = 1; i < ud.size; i++) |
for (i = 1; i < ud.size; i++) |
more = utf8_append(&ud, (u_char)buf[i]); |
more = utf8_append(&ud, (u_char)buf[i]); |
if (more != UTF8_DONE) |
if (more != UTF8_DONE) |
return (0); |
return (-1); |
|
|
if (utf8_combine(&ud, &wc) != UTF8_DONE) |
if (utf8_combine(&ud, &wc) != UTF8_DONE) |
return (0); |
return (-1); |
*key = wc; |
*key = wc; |
|
|
log_debug("UTF-8 key %.*s %#llx", (int)ud.size, buf, *key); |
log_debug("UTF-8 key %.*s %#llx", (int)ud.size, buf, *key); |
|
|
const char *buf; |
const char *buf; |
size_t len, size; |
size_t len, size; |
cc_t bspace; |
cc_t bspace; |
int delay, expired = 0; |
int delay, expired = 0, n; |
key_code key; |
key_code key; |
|
|
/* Get key buffer. */ |
/* Get key buffer. */ |
|
|
} |
} |
|
|
first_key: |
first_key: |
/* If escape is at the start, try without it. */ |
/* Handle keys starting with escape. */ |
if (*buf == '\033') { |
if (*buf == '\033') { |
switch (tty_keys_next1 (tty, buf + 1, len - 1, &key, &size)) { |
/* A single escape goes as-is if the timer has expired. */ |
case 0: /* found */ |
if (expired && len == 1) { |
if (key != KEYC_UNKNOWN) |
key = '\033'; |
key |= KEYC_ESCAPE; |
size = 1; |
size++; /* include escape */ |
|
goto complete_key; |
goto complete_key; |
case -1: /* not found */ |
|
break; |
|
case 1: |
|
if (expired) |
|
goto complete_key; |
|
goto partial_key; |
|
} |
} |
} |
|
|
|
/* Try with the escape. */ |
/* Look for a key without the escape. */ |
switch (tty_keys_next1 (tty, buf, len, &key, &size)) { |
n = tty_keys_next1(tty, buf + 1, len - 1, &key, &size, expired); |
case 0: /* found */ |
if (n == 0) { /* found */ |
goto complete_key; |
key |= KEYC_ESCAPE; |
case -1: /* not found */ |
size++; |
break; |
|
case 1: |
|
if (expired) |
|
goto complete_key; |
goto complete_key; |
goto partial_key; |
} |
} |
if (n == 1) /* partial */ |
|
goto partial_key; |
|
|
/* Is this an an xterm(1) key? */ |
/* Try with the escape. */ |
switch (xterm_keys_find(buf, len, &size, &key)) { |
n = tty_keys_next1(tty, buf, len, &key, &size, expired); |
case 0: /* found */ |
if (n == 0) /* found */ |
goto complete_key; |
goto complete_key; |
case -1: /* not found */ |
if (n == 1) |
break; |
goto partial_key; |
case 1: |
|
if (expired) |
|
break; |
|
goto partial_key; |
|
} |
|
|
|
/* |
/* Is this an an xterm(1) key? */ |
* If this starts with escape and is at least two keys, it must be |
n = xterm_keys_find(buf, len, &size, &key); |
* complete even if the timer has not expired, because otherwise |
if (n == 0) /* found */ |
* tty_keys_next1 would have found a partial key. If just an escape |
goto complete_key; |
* alone, it needs to wait for the timer first. |
if (n == 1 && !expired) |
*/ |
goto partial_key; |
if (*buf == '\033') { |
|
|
/* |
|
* If this is at least two keys, then it must be complete - |
|
* whether or not the timer has expired - otherwise |
|
* tty_keys_next1 would have returned a partial. |
|
*/ |
if (len >= 2) { |
if (len >= 2) { |
key = (u_char)buf[1] | KEYC_ESCAPE; |
key = (u_char)buf[1] | KEYC_ESCAPE; |
size = 2; |
size = 2; |
goto complete_key; |
goto complete_key; |
} |
} |
if (!expired) |
|
goto partial_key; |
|
} |
} |
|
|
/* No longer key found, use the first character. */ |
/* No longer key found, use the first character. */ |