From 9d101d847397c1145e66bd7f5f26076eaf1b63ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20T=C5=99=C3=AD=C5=A1ka?= Date: Thu, 4 Aug 2011 13:24:59 +0200 Subject: [PATCH 1/4] check_for_duplicate_bindings --- src/cfgparse.y | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/cfgparse.y b/src/cfgparse.y index 59b22c6c..226363cc 100644 --- a/src/cfgparse.y +++ b/src/cfgparse.y @@ -310,6 +310,35 @@ void kill_configerror_nagbar(bool wait_for_it) { waitpid(configerror_pid, NULL, 0); } +/* + check_for_duplicate_bindings is function looking for duplicated + key bindings loaded from configuration file. It goes trought all bindings + and tests if exists same key mapping in bindings visited before. + If exists, message is printed to "stderr" and error warning is set. +*/ +static bool check_for_duplicate_bindings(struct context *context) { + bool retval = true; + Binding *bind, *current; + TAILQ_FOREACH(current, bindings, bindings) { + bind = TAILQ_FIRST(bindings); + // test only bindings visited up to current binding + while ((bind != TAILQ_END(bindings)) && (bind != current)) { + // testing is not case sensitive + if ((strcasecmp(bind->symbol, current->symbol) == 0) && (bind->keycode == current->keycode) && (bind->mods == current->mods)) { + context->has_errors = true; + fprintf(stderr, "Duplicated keybinding in config file: mod%d with key %s", current->mods, current->symbol); + // if keycode is 0, it´s not necessary to print it. + if(current->keycode != 0) + fprintf(stderr, " and keycode %d", current->keycode); + fprintf(stderr, "\n"); + retval = false; + } + bind = TAILQ_NEXT(bind, bindings); + } + } + return retval; +} + void parse_file(const char *f) { SLIST_HEAD(variables_head, Variable) variables = SLIST_HEAD_INITIALIZER(&variables); int fd, ret, read_bytes = 0; @@ -463,6 +492,8 @@ void parse_file(const char *f) { exit(1); } + check_for_duplicate_bindings(context); + if (context->has_errors) { start_configerror_nagbar(f); } From 787dd4059f3b990cc11726277fded3426b2aeb49 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Thu, 4 Aug 2011 21:25:47 +0200 Subject: [PATCH 2/4] little style fixes for the previous patch --- src/cfgparse.y | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/cfgparse.y b/src/cfgparse.y index 226363cc..ae5a7a73 100644 --- a/src/cfgparse.y +++ b/src/cfgparse.y @@ -311,24 +311,27 @@ void kill_configerror_nagbar(bool wait_for_it) { } /* - check_for_duplicate_bindings is function looking for duplicated - key bindings loaded from configuration file. It goes trought all bindings - and tests if exists same key mapping in bindings visited before. - If exists, message is printed to "stderr" and error warning is set. -*/ + * Checks for duplicate key bindings (the same keycode or keysym is configured + * more than once). If a duplicate binding is found, a message is printed to + * stderr and the has_errors variable is set to true, which will start + * i3-nagbar. + * + */ static bool check_for_duplicate_bindings(struct context *context) { bool retval = true; Binding *bind, *current; TAILQ_FOREACH(current, bindings, bindings) { bind = TAILQ_FIRST(bindings); - // test only bindings visited up to current binding + /* test only bindings visited up to current binding */ while ((bind != TAILQ_END(bindings)) && (bind != current)) { - // testing is not case sensitive - if ((strcasecmp(bind->symbol, current->symbol) == 0) && (bind->keycode == current->keycode) && (bind->mods == current->mods)) { + /* testing is not case sensitive */ + if ((strcasecmp(bind->symbol, current->symbol) == 0) && + (bind->keycode == current->keycode) && + (bind->mods == current->mods)) { context->has_errors = true; fprintf(stderr, "Duplicated keybinding in config file: mod%d with key %s", current->mods, current->symbol); - // if keycode is 0, it´s not necessary to print it. - if(current->keycode != 0) + /* if keycode is 0, this is a keysym binding */ + if (current->keycode != 0) fprintf(stderr, " and keycode %d", current->keycode); fprintf(stderr, "\n"); retval = false; From 4e350664ae73104b3f4c65ffbdac31e1073cc78f Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Thu, 4 Aug 2011 21:38:13 +0200 Subject: [PATCH 3/4] Bugfix: Check that ->symbol != NULL before using strcasecmp() --- src/cfgparse.y | 51 +++++++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/src/cfgparse.y b/src/cfgparse.y index ae5a7a73..b4ec94d2 100644 --- a/src/cfgparse.y +++ b/src/cfgparse.y @@ -317,29 +317,42 @@ void kill_configerror_nagbar(bool wait_for_it) { * i3-nagbar. * */ -static bool check_for_duplicate_bindings(struct context *context) { - bool retval = true; +static void check_for_duplicate_bindings(struct context *context) { Binding *bind, *current; TAILQ_FOREACH(current, bindings, bindings) { - bind = TAILQ_FIRST(bindings); - /* test only bindings visited up to current binding */ - while ((bind != TAILQ_END(bindings)) && (bind != current)) { - /* testing is not case sensitive */ - if ((strcasecmp(bind->symbol, current->symbol) == 0) && - (bind->keycode == current->keycode) && - (bind->mods == current->mods)) { - context->has_errors = true; - fprintf(stderr, "Duplicated keybinding in config file: mod%d with key %s", current->mods, current->symbol); - /* if keycode is 0, this is a keysym binding */ - if (current->keycode != 0) - fprintf(stderr, " and keycode %d", current->keycode); - fprintf(stderr, "\n"); - retval = false; - } - bind = TAILQ_NEXT(bind, bindings); + TAILQ_FOREACH(bind, bindings, bindings) { + /* Abort when we reach the current keybinding, only check the + * bindings before */ + if (bind == current) + break; + + /* Check if one is using keysym while the other is using bindsym. + * If so, skip. */ + /* XXX: It should be checked at a later place (when translating the + * keysym to keycodes) if there are any duplicates */ + if ((bind->symbol == NULL && current->symbol != NULL) || + (bind->symbol != NULL && current->symbol == NULL)) + continue; + + /* If bind is NULL, current has to be NULL, too (see above). + * If the keycodes differ, it can't be a duplicate. */ + if (bind->symbol != NULL && + strcasecmp(bind->symbol, current->symbol) != 0) + continue; + + /* Check if the keycodes or modifiers are different. If so, they + * can't be duplicate */ + if (bind->keycode != current->keycode || + bind->mods != current->mods) + continue; + context->has_errors = true; + fprintf(stderr, "Duplicated keybinding in config file: mod%d with key %s", current->mods, current->symbol); + /* if keycode is 0, this is a keysym binding */ + if (current->keycode != 0) + fprintf(stderr, " and keycode %d", current->keycode); + fprintf(stderr, "\n"); } } - return retval; } void parse_file(const char *f) { From ecc2cae3f7504e65a43e7be6fa56edc0b549f594 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Thu, 4 Aug 2011 21:43:55 +0200 Subject: [PATCH 4/4] Bugfix: use ELOG to actually get the error message into the logfile shown by i3-nagbar --- src/cfgparse.y | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/cfgparse.y b/src/cfgparse.y index b4ec94d2..8426de0b 100644 --- a/src/cfgparse.y +++ b/src/cfgparse.y @@ -346,11 +346,13 @@ static void check_for_duplicate_bindings(struct context *context) { bind->mods != current->mods) continue; context->has_errors = true; - fprintf(stderr, "Duplicated keybinding in config file: mod%d with key %s", current->mods, current->symbol); - /* if keycode is 0, this is a keysym binding */ - if (current->keycode != 0) - fprintf(stderr, " and keycode %d", current->keycode); - fprintf(stderr, "\n"); + if (current->keycode != 0) { + ELOG("Duplicate keybinding in config file:\n modmask %d with keycode %d, command \"%s\"\n", + current->mods, current->keycode, current->command); + } else { + ELOG("Duplicate keybinding in config file:\n modmask %d with keysym %s, command \"%s\"\n", + current->mods, current->symbol, current->command); + } } } }