=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/tty-keys.c,v retrieving revision 1.85 retrieving revision 1.86 diff -c -r1.85 -r1.86 *** src/usr.bin/tmux/tty-keys.c 2016/03/02 15:36:03 1.85 --- src/usr.bin/tmux/tty-keys.c 2016/04/26 22:19:22 1.86 *************** *** 1,4 **** ! /* $OpenBSD: tty-keys.c,v 1.85 2016/03/02 15:36:03 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: tty-keys.c,v 1.86 2016/04/26 22:19:22 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott *************** *** 33,46 **** * into a ternary tree. */ ! void tty_keys_add1(struct tty_key **, const char *, key_code); ! void tty_keys_add(struct tty *, const char *, key_code); ! void tty_keys_free1(struct tty_key *); ! struct tty_key *tty_keys_find1(struct tty_key *, const char *, size_t, size_t *); ! struct tty_key *tty_keys_find(struct tty *, const char *, size_t, size_t *); ! void tty_keys_callback(int, short, void *); ! int tty_keys_mouse(struct tty *, const char *, size_t, size_t *); /* Default raw keys. */ struct tty_default_key_raw { --- 33,49 ---- * into a ternary tree. */ ! static void tty_keys_add1(struct tty_key **, const char *, key_code); ! static void tty_keys_add(struct tty *, const char *, key_code); ! static void tty_keys_free1(struct tty_key *); ! static struct tty_key *tty_keys_find1(struct tty_key *, const char *, size_t, size_t *); ! static struct tty_key *tty_keys_find(struct tty *, const char *, size_t, ! size_t *); ! static int tty_keys_next1(struct tty *, const char *, size_t, key_code *, ! size_t *); ! static void tty_keys_callback(int, short, void *); ! static int tty_keys_mouse(struct tty *, const char *, size_t, size_t *); /* Default raw keys. */ struct tty_default_key_raw { *************** *** 316,322 **** }; /* Add key to tree. */ ! void tty_keys_add(struct tty *tty, const char *s, key_code key) { struct tty_key *tk; --- 319,325 ---- }; /* Add key to tree. */ ! static void tty_keys_add(struct tty *tty, const char *s, key_code key) { struct tty_key *tk; *************** *** 334,340 **** } /* Add next node to the tree. */ ! void tty_keys_add1(struct tty_key **tkp, const char *s, key_code key) { struct tty_key *tk; --- 337,343 ---- } /* Add next node to the tree. */ ! static void tty_keys_add1(struct tty_key **tkp, const char *s, key_code key) { struct tty_key *tk; *************** *** 409,415 **** } /* Free a single key. */ ! void tty_keys_free1(struct tty_key *tk) { if (tk->next != NULL) --- 412,418 ---- } /* Free a single key. */ ! static void tty_keys_free1(struct tty_key *tk) { if (tk->next != NULL) *************** *** 422,428 **** } /* Lookup a key in the tree. */ ! struct tty_key * tty_keys_find(struct tty *tty, const char *buf, size_t len, size_t *size) { *size = 0; --- 425,431 ---- } /* Lookup a key in the tree. */ ! static struct tty_key * tty_keys_find(struct tty *tty, const char *buf, size_t len, size_t *size) { *size = 0; *************** *** 430,436 **** } /* Find the next node. */ ! struct tty_key * tty_keys_find1(struct tty_key *tk, const char *buf, size_t len, size_t *size) { /* If the node is NULL, this is the end of the tree. No match. */ --- 433,439 ---- } /* Find the next node. */ ! static struct tty_key * tty_keys_find1(struct tty_key *tk, const char *buf, size_t len, size_t *size) { /* If the node is NULL, this is the end of the tree. No match. */ *************** *** 460,465 **** --- 463,518 ---- return (tty_keys_find1(tk, buf, len, size)); } + /* Look up part of the next key. */ + static int + tty_keys_next1(struct tty *tty, const char *buf, size_t len, key_code *key, + size_t *size) + { + struct tty_key *tk, *tk1; + struct utf8_data ud; + enum utf8_state more; + u_int i; + wchar_t wc; + + log_debug("next key is %zu (%.*s)", len, (int)len, buf); + + /* Empty buffer is a partial key. */ + if (len == 0) + return (1); + + /* Is this a known key? */ + tk = tty_keys_find(tty, buf, len, size); + if (tk != NULL) { + tk1 = tk; + do + log_debug("keys in list: %#llx", tk->key); + while ((tk1 = tk1->next) != NULL); + *key = tk->key; + return (tk->next != NULL); + } + + /* Is this valid UTF-8? */ + more = utf8_open(&ud, (u_char)*buf); + if (more == UTF8_MORE) { + *size = ud.size; + if (len < ud.size) + return (1); + for (i = 1; i < ud.size; i++) + more = utf8_append(&ud, (u_char)buf[i]); + if (more != UTF8_DONE) + return (0); + + if (utf8_combine(&ud, &wc) != UTF8_DONE) + return (0); + *key = wc; + + log_debug("UTF-8 key %.*s %#llx", (int)ud.size, buf, *key); + return (0); + } + + return (-1); + } + /* * Process at least one key in the buffer and invoke tty->key_callback. Return * 0 if there are no further keys, or 1 if there could be more in the buffer. *************** *** 467,483 **** key_code tty_keys_next(struct tty *tty) { ! struct tty_key *tk; ! struct timeval tv; ! const char *buf; ! size_t len, size; ! cc_t bspace; ! int delay, expired = 0; ! key_code key; ! struct utf8_data ud; ! enum utf8_state more; ! u_int i; ! wchar_t wc; /* Get key buffer. */ buf = EVBUFFER_DATA(tty->event->input); --- 520,531 ---- key_code tty_keys_next(struct tty *tty) { ! struct timeval tv; ! const char *buf; ! size_t len, size; ! cc_t bspace; ! int delay, expired = 0; ! key_code key; /* Get key buffer. */ buf = EVBUFFER_DATA(tty->event->input); *************** *** 485,491 **** if (len == 0) return (0); ! log_debug("keys are %zu (%.*s)", len, (int) len, buf); /* Is this a mouse key press? */ switch (tty_keys_mouse(tty, buf, len, &size)) { --- 533,539 ---- if (len == 0) return (0); ! log_debug("keys are %zu (%.*s)", len, (int)len, buf); /* Is this a mouse key press? */ switch (tty_keys_mouse(tty, buf, len, &size)) { *************** *** 501,568 **** goto partial_key; } ! /* Look for matching key string and return if found. */ ! tk = tty_keys_find(tty, buf, len, &size); ! if (tk != NULL) { ! if (tk->next != NULL) goto partial_key; ! key = tk->key; goto complete_key; } ! /* Try to parse a key with an xterm-style modifier. */ switch (xterm_keys_find(buf, len, &size, &key)) { case 0: /* found */ goto complete_key; case -1: /* not found */ break; case 1: goto partial_key; } ! first_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; } ! ! tk = tty_keys_find(tty, buf + 1, len - 1, &size); ! if (tk != NULL && (!expired || tk->next == NULL)) { ! size++; /* include escape */ ! if (tk->next != NULL) ! goto partial_key; ! key = tk->key; ! if (key != KEYC_UNKNOWN) ! key |= KEYC_ESCAPE; ! goto complete_key; ! } ! } ! ! /* Is this valid UTF-8? */ ! if ((more = utf8_open(&ud, (u_char)*buf) == UTF8_MORE)) { ! size = ud.size; ! if (len < size) { ! if (expired) ! goto discard_key; goto partial_key; - } - for (i = 1; i < size; i++) - more = utf8_append(&ud, (u_char)buf[i]); - if (more != UTF8_DONE) - goto discard_key; - - if (utf8_combine(&ud, &wc) != UTF8_DONE) - goto discard_key; - key = wc; - - log_debug("UTF-8 key %.*s %#llx", (int)size, buf, key); - goto complete_key; } ! /* No key found, take first. */ key = (u_char)*buf; size = 1; --- 549,613 ---- goto partial_key; } ! first_key: ! /* If escape is at the start, try without it. */ ! if (*buf == '\033') { ! switch (tty_keys_next1 (tty, buf + 1, len - 1, &key, &size)) { ! case 0: /* found */ ! if (key != KEYC_UNKNOWN) ! key |= KEYC_ESCAPE; ! size++; /* include escape */ ! goto complete_key; ! case -1: /* not found */ ! break; ! case 1: ! if (expired) ! goto complete_key; goto partial_key; ! } ! } ! ! /* Try with the escape. */ ! switch (tty_keys_next1 (tty, buf, len, &key, &size)) { ! case 0: /* found */ goto complete_key; + case -1: /* not found */ + break; + case 1: + if (expired) + goto complete_key; + goto partial_key; } ! /* Is this an an xterm(1) key? */ switch (xterm_keys_find(buf, len, &size, &key)) { case 0: /* found */ goto complete_key; case -1: /* not found */ break; case 1: + if (expired) + break; goto partial_key; } ! /* ! * If this starts with escape and is at least two keys, it must be ! * complete even if the timer has not expired, because otherwise ! * tty_keys_next1 would have found a partial key. If just an escape ! * alone, it needs to wait for the timer first. ! */ ! if (*buf == '\033') { ! if (len >= 2) { ! key = (u_char)buf[1] | KEYC_ESCAPE; size = 2; goto complete_key; } ! if (!expired) goto partial_key; } ! /* No longer key found, use the first character. */ key = (u_char)*buf; size = 1; *************** *** 578,584 **** goto complete_key; partial_key: ! log_debug("partial key %.*s", (int) len, buf); /* If timer is going, check for expiration. */ if (tty->flags & TTY_TIMER) { --- 623,629 ---- goto complete_key; partial_key: ! log_debug("partial key %.*s", (int)len, buf); /* If timer is going, check for expiration. */ if (tty->flags & TTY_TIMER) { *************** *** 640,646 **** } /* Key timer callback. */ ! void tty_keys_callback(__unused int fd, __unused short events, void *data) { struct tty *tty = data; --- 685,691 ---- } /* Key timer callback. */ ! static void tty_keys_callback(__unused int fd, __unused short events, void *data) { struct tty *tty = data; *************** *** 655,661 **** * Handle mouse key input. Returns 0 for success, -1 for failure, 1 for partial * (probably a mouse sequence but need more data). */ ! int tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size) { struct mouse_event *m = &tty->mouse; --- 700,706 ---- * Handle mouse key input. Returns 0 for success, -1 for failure, 1 for partial * (probably a mouse sequence but need more data). */ ! static int tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size) { struct mouse_event *m = &tty->mouse;