From cdb2d90b893f35326146dbc657952265f1bf61ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 21 Nov 2021 18:04:36 +0100 Subject: [PATCH] =?UTF-8?q?config:=20argv=5Fcompare():=20change=20paramete?= =?UTF-8?q?rs=20to=20=E2=80=98struct=20argv=20*=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of passing raw char** pointers to argv_compare(), pass pointers to ‘struct argv’. This lets argv_compare() handle both argv’s being NULL, or one of them being NULL. That is, the caller no longer needs to check that both argv’s are non-NULL before calling argv_compare(). Furthermore, update has_key_binding_collisions() to require the pipe argv to match, in addition to matching the ‘action’, when allowing a key collision. --- config.c | 86 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 46 insertions(+), 40 deletions(-) diff --git a/config.c b/config.c index 60029ab9..68061cc3 100644 --- a/config.c +++ b/config.c @@ -1557,11 +1557,40 @@ err: return false; } +static int +argv_compare(const struct argv *argv1, const struct argv *argv2) +{ + if (argv1->args == NULL && argv2->args == NULL) + return 0; + + if (argv1->args == NULL) + return -1; + if (argv2->args == NULL) + return 1; + + for (size_t i = 0; ; i++) { + if (argv1->args[i] == NULL && argv2->args[i] == NULL) + return 0; + if (argv1->args[i] == NULL) + return -1; + if (argv2->args[i] == NULL) + return 1; + + int ret = strcmp(argv1->args[i], argv2->args[i]); + if (ret != 0) + return ret; + } + + BUG("unexpected loop break"); + return 1; +} + static bool has_key_binding_collisions(struct context *ctx, int action, const char *const action_map[], const struct config_key_binding_list *bindings, - const struct key_combo_list *key_combos) + const struct key_combo_list *key_combos, + const struct argv *pipe_argv) { for (size_t j = 0; j < bindings->count; j++) { const struct config_key_binding *combo1 = &bindings->arr[j]; @@ -1569,8 +1598,10 @@ has_key_binding_collisions(struct context *ctx, if (combo1->action == BIND_ACTION_NONE) continue; - if (combo1->action == action) - continue; + if (combo1->action == action) { + if (argv_compare(&combo1->pipe.argv, pipe_argv) == 0) + continue; + } for (size_t i = 0; i < key_combos->count; i++) { const struct key_combo *combo2 = &key_combos->combos[i]; @@ -1600,29 +1631,6 @@ has_key_binding_collisions(struct context *ctx, return false; } -static int -argv_compare(char *const *argv1, char *const *argv2) -{ - xassert(argv1 != NULL); - xassert(argv2 != NULL); - - for (size_t i = 0; ; i++) { - if (argv1[i] == NULL && argv2[i] == NULL) - return 0; - if (argv1[i] == NULL) - return -1; - if (argv2[i] == NULL) - return 1; - - int ret = strcmp(argv1[i], argv2[i]); - if (ret != 0) - return ret; - } - - BUG("unexpected loop break"); - return 1; -} - /* * Parses a key binding value on the form * "[cmd-to-exec arg1 arg2] Mods+Key" @@ -1680,7 +1688,7 @@ pipe_argv_from_value(struct context *ctx, struct argv *argv) static void NOINLINE remove_action_from_key_bindings_list(struct config_key_binding_list *bindings, - int action, char **pipe_argv) + int action, const struct argv *pipe_argv) { size_t remove_first_idx = 0; size_t remove_count = 0; @@ -1688,11 +1696,10 @@ remove_action_from_key_bindings_list(struct config_key_binding_list *bindings, for (size_t i = 0; i < bindings->count; i++) { struct config_key_binding *binding = &bindings->arr[i]; - if (binding->action == action && - ((binding->pipe.argv.args == NULL && pipe_argv == NULL) || - (binding->pipe.argv.args != NULL && pipe_argv != NULL && - argv_compare(binding->pipe.argv.args, pipe_argv) == 0))) - { + if (binding->action != action) + continue; + + if (argv_compare(&binding->pipe.argv, pipe_argv) == 0) { if (remove_count++ == 0) remove_first_idx = i; @@ -1736,7 +1743,7 @@ parse_key_binding_section(struct context *ctx, /* Unset binding */ if (strcasecmp(ctx->value, "none") == 0) { - remove_action_from_key_bindings_list(bindings, action, pipe_argv.args); + remove_action_from_key_bindings_list(bindings, action, &pipe_argv); free_argv(&pipe_argv); return true; } @@ -1744,14 +1751,14 @@ parse_key_binding_section(struct context *ctx, struct key_combo_list key_combos = {0}; if (!value_to_key_combos(ctx, &key_combos) || has_key_binding_collisions( - ctx, action, action_map, bindings, &key_combos)) + ctx, action, action_map, bindings, &key_combos, &pipe_argv)) { free_argv(&pipe_argv); free_key_combo_list(&key_combos); return false; } - remove_action_from_key_bindings_list(bindings, action, pipe_argv.args); + remove_action_from_key_bindings_list(bindings, action, &pipe_argv); /* Emit key bindings */ size_t ofs = bindings->count; @@ -2140,11 +2147,10 @@ parse_section_mouse_bindings(struct context *ctx) for (size_t i = 0; i < conf->bindings.mouse.count; i++) { struct config_mouse_binding *binding = &conf->bindings.mouse.arr[i]; - if (binding->action == action && - ((binding->pipe.argv.args == NULL && pipe_argv.args == NULL) || - (binding->pipe.argv.args != NULL && pipe_argv.args != NULL && - argv_compare(binding->pipe.argv.args, pipe_argv.args) == 0))) - { + if (binding->action != action) + continue; + + if (argv_compare(&binding->pipe.argv, &pipe_argv) == 0) { if (binding->pipe.master_copy) free_argv(&binding->pipe.argv); binding->action = BIND_ACTION_NONE;