I think this can be made neater by making xterm_keys_modifiers do all the work directly rather than searching for the _ all over again, please look at this:
diff --git a/xterm-keys.c b/xterm-keys.c index af3f1e7..5a49520 100644 --- a/xterm-keys.c +++ b/xterm-keys.c @@ -40,8 +40,8 @@ * We accept any but always output the latter (it comes first in the table). */ -int xterm_keys_match(const char *, const char *, size_t); -int xterm_keys_modifiers(const char *, const char *, size_t); +int xterm_keys_match(const char *, const char *, size_t, size_t *, u_int *); +int xterm_keys_modifiers(const char *, size_t, size_t *, u_int *); struct xterm_keys_entry { int key; @@ -122,49 +122,63 @@ const struct xterm_keys_entry xterm_keys_table[] = { * 0 for match, 1 if the end of the buffer is reached (need more data). */ int -xterm_keys_match(const char *template, const char *buf, size_t len) +xterm_keys_match(const char *template, const char *buf, size_t len, + size_t *size, u_int *modifiers) { size_t pos; + int retval; if (len == 0) return (0); pos = 0; do { - if (*template == '_' && buf[pos] >= '1' && buf[pos] <= '8') + if (*template == '_') { + retval = xterm_keys_modifiers(buf, len, &pos, + modifiers); + if (retval != 0) + return (retval); continue; + } if (buf[pos] != *template) return (-1); - } while (*++template != '\0' && ++pos != len); + pos++; + } while (*++template != '\0' && pos != len); if (*template != '\0') /* partial */ return (1); + *size = pos; return (0); } -/* Find modifiers based on template. */ +/* Find modifiers from buffer. */ int -xterm_keys_modifiers(const char *template, const char *buf, size_t len) +xterm_keys_modifiers(const char *buf, size_t len, size_t *pos, u_int *modifiers) { - size_t idx; - int param, modifiers; + u_int flags; - idx = strcspn(template, "_"); - if (idx >= len) - return (0); - param = buf[idx] - '1'; - - modifiers = 0; - if (param & 1) - modifiers |= KEYC_SHIFT; - if (param & 2) - modifiers |= KEYC_ESCAPE; - if (param & 4) - modifiers |= KEYC_CTRL; - if (param & 8) - modifiers |= KEYC_ESCAPE; - return (modifiers); + if (len - *pos < 2) + return (1); + + if (buf[*pos] < '0' || buf[*pos] > '9') + return (-1); + flags = buf[(*pos)++] - '0'; + if (buf[*pos] >= '0' && buf[*pos] <= '9') + flags = (flags * 10) + (buf[(*pos)++] - '0'); + + *modifiers = 0; + if (flags & 1) + *modifiers |= KEYC_SHIFT; + if (flags & 2) + *modifiers |= KEYC_ESCAPE; + if (flags & 4) + *modifiers |= KEYC_CTRL; + if (flags & 8) + *modifiers |= KEYC_ESCAPE; + if (flags & 16) + *modifiers != KEYC_ESCAPE; + return (0); } /* @@ -175,19 +189,19 @@ int xterm_keys_find(const char *buf, size_t len, size_t *size, int *key) { const struct xterm_keys_entry *entry; - u_int i; + u_int i, modifiers; + int matched; for (i = 0; i < nitems(xterm_keys_table); i++) { entry = &xterm_keys_table[i]; - switch (xterm_keys_match(entry->template, buf, len)) { - case 0: - *size = strlen(entry->template); - *key = entry->key; - *key |= xterm_keys_modifiers(entry->template, buf, len); - return (0); - case 1: - return (1); - } + + matched = xterm_keys_match(entry->template, buf, len, size, + &modifiers); + if (matched == -1) + continue; + if (matched == 0) + *key = entry->key | modifiers; + return (matched); } return (-1); } On Fri, May 16, 2014 at 08:00:42PM +0100, Balazs Kezes wrote: > On 2014-05-16 09:48 +0100, Balazs Kezes wrote: > > Now that I managed to reproduce this on my machine, I realized that > > the fix is a bit more complicated than I expected. I can try to gather > > some time in the future to fix it unless you beat me to it. :) > > OK, I've actually managed to create a working fix. Please review and > test. It contains some low level buffer manipulation so be extra > vigilant! Let me know if you want things differently. > > Thanks! > > diff --git a/xterm-keys.c b/xterm-keys.c > index af3f1e7..317c15b 100644 > --- a/xterm-keys.c > +++ b/xterm-keys.c > @@ -34,6 +34,9 @@ > * 7 Alt + Ctrl > * 8 Shift + Alt + Ctrl > * > + * Note that tmux does not support sending the Meta modifier. When a Meta is > + * encountered, it is converted to an Alt. > + * > * Rather than parsing them, just match against a table. > * > * There are three forms for F1-F4 (\\033O_P and \\033O1;_P and \\033[1;_P). > @@ -119,7 +122,8 @@ const struct xterm_keys_entry xterm_keys_table[] = { > > /* > * Match key against buffer, treating _ as a wildcard. Return -1 for no > match, > - * 0 for match, 1 if the end of the buffer is reached (need more data). > + * -2 if the end of the buffer is reached (need more data), otherwise the > length > + * of the match. > */ > int > xterm_keys_match(const char *template, const char *buf, size_t len) > @@ -131,16 +135,22 @@ xterm_keys_match(const char *template, const char *buf, > size_t len) > > pos = 0; > do { > - if (*template == '_' && buf[pos] >= '1' && buf[pos] <= '8') > + if (*template == '_' && buf[pos] >= '1' && buf[pos] <= '9') { > + if (pos+1 != len) { > + // Handle two digit modifiers. > + if (buf[pos+1] >= '0' && buf[pos+1] <= '9') > + pos += 1; > + } > continue; > + } > if (buf[pos] != *template) > return (-1); > } while (*++template != '\0' && ++pos != len); > > if (*template != '\0') /* partial */ > - return (1); > + return (-2); > > - return (0); > + return (pos+1); > } > > /* Find modifiers based on template. */ > @@ -153,8 +163,11 @@ xterm_keys_modifiers(const char *template, const char > *buf, size_t len) > idx = strcspn(template, "_"); > if (idx >= len) > return (0); > - param = buf[idx] - '1'; > + param = buf[idx] - '0'; > + if (idx+1 < len && buf[idx+1] >= '0' && buf[idx+1] <= '9') > + param = param*10 + buf[idx+1] - '0'; > > + param -= 1; > modifiers = 0; > if (param & 1) > modifiers |= KEYC_SHIFT; > @@ -176,17 +189,18 @@ xterm_keys_find(const char *buf, size_t len, size_t > *size, int *key) > { > const struct xterm_keys_entry *entry; > u_int i; > + int match_result; > > for (i = 0; i < nitems(xterm_keys_table); i++) { > entry = &xterm_keys_table[i]; > - switch (xterm_keys_match(entry->template, buf, len)) { > - case 0: > - *size = strlen(entry->template); > + match_result = xterm_keys_match(entry->template, buf, len); > + if (match_result == -2) { > + return (1); > + } else if (match_result >= 0) { > + *size = match_result; > *key = entry->key; > *key |= xterm_keys_modifiers(entry->template, buf, len); > return (0); > - case 1: > - return (1); > } > } > return (-1); > > -- > Balazs ------------------------------------------------------------------------------ "Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE Instantly run your Selenium tests across 300+ browser/OS combos. Get unparalleled scalability from the best Selenium testing platform available Simple to use. Nothing to install. Get started now for free." http://p.sf.net/sfu/SauceLabs _______________________________________________ tmux-users mailing list tmux-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tmux-users