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

Reply via email to