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
[email protected]
https://lists.sourceforge.net/lists/listinfo/tmux-users