diff options
-rw-r--r-- | src/core/wee-command.c | 62 | ||||
-rw-r--r-- | src/core/wee-completion.c | 26 | ||||
-rw-r--r-- | src/core/wee-config.c | 149 | ||||
-rw-r--r-- | src/core/wee-config.h | 2 | ||||
-rw-r--r-- | src/gui/curses/gui-curses-key.c | 13 | ||||
-rw-r--r-- | src/gui/curses/gui-curses.h | 2 | ||||
-rw-r--r-- | src/gui/gui-buffer.c | 12 | ||||
-rw-r--r-- | src/gui/gui-key.c | 333 | ||||
-rw-r--r-- | src/gui/gui-key.h | 17 | ||||
-rw-r--r-- | tests/unit/gui/test-gui-key.cpp | 318 |
10 files changed, 741 insertions, 193 deletions
diff --git a/src/core/wee-command.c b/src/core/wee-command.c index 0d54f96a7..ab3290ee4 100644 --- a/src/core/wee-command.c +++ b/src/core/wee-command.c @@ -3812,8 +3812,10 @@ command_key_display_list (const char *message_no_key, struct t_gui_key *ptr_key; if (keys_count == 0) + { gui_chat_printf (NULL, message_no_key, gui_key_context_string[context]); + } else { gui_chat_printf (NULL, ""); @@ -3997,7 +3999,7 @@ command_key_reset (int context, const char *key) COMMAND_CALLBACK(key) { struct t_gui_key *ptr_new_key; - int old_keys_count, keys_added, i, context, rc; + int old_keys_count, keys_added, context, rc; /* make C compiler happy */ (void) pointer; @@ -4007,17 +4009,20 @@ COMMAND_CALLBACK(key) /* display all key bindings (current keys) */ if ((argc == 1) || (string_strcmp (argv[1], "list") == 0)) { - for (i = 0; i < GUI_KEY_NUM_CONTEXTS; i++) + for (context = 0; context < GUI_KEY_NUM_CONTEXTS; context++) { if ((argc < 3) - || (string_strcmp (argv[2], gui_key_context_string[i]) == 0)) + || (string_strcmp (argv[2], + gui_key_context_string[context]) == 0)) { command_key_display_list (_("No key binding defined for " "context \"%s\""), /* TRANSLATORS: first "%d" is number of keys */ _("%d key bindings for context " "\"%s\":"), - i, gui_keys[i], gui_keys_count[i]); + context, + gui_keys[context], + gui_keys_count[context]); } } return WEECHAT_RC_OK; @@ -4026,12 +4031,13 @@ COMMAND_CALLBACK(key) /* display redefined or key bindings added */ if (string_strcmp (argv[1], "listdiff") == 0) { - for (i = 0; i < GUI_KEY_NUM_CONTEXTS; i++) + for (context = 0; context < GUI_KEY_NUM_CONTEXTS; context++) { if ((argc < 3) - || (string_strcmp (argv[2], gui_key_context_string[i]) == 0)) + || (string_strcmp (argv[2], + gui_key_context_string[context]) == 0)) { - command_key_display_listdiff (i); + command_key_display_listdiff (context); } } return WEECHAT_RC_OK; @@ -4040,19 +4046,20 @@ COMMAND_CALLBACK(key) /* display default key bindings */ if (string_strcmp (argv[1], "listdefault") == 0) { - for (i = 0; i < GUI_KEY_NUM_CONTEXTS; i++) + for (context = 0; context < GUI_KEY_NUM_CONTEXTS; context++) { if ((argc < 3) - || (string_strcmp (argv[2], gui_key_context_string[i]) == 0)) + || (string_strcmp (argv[2], + gui_key_context_string[context]) == 0)) { command_key_display_list (_("No default key binding for " "context \"%s\""), /* TRANSLATORS: first "%d" is number of keys */ _("%d default key bindings for " "context \"%s\":"), - i, - gui_default_keys[i], - gui_default_keys_count[i]); + context, + gui_default_keys[context], + gui_default_keys_count[context]); } } return WEECHAT_RC_OK; @@ -4258,18 +4265,22 @@ COMMAND_CALLBACK(key) { if ((argc >= 3) && (string_strcmp (argv[2], "-yes") == 0)) { - for (i = 0; i < GUI_KEY_NUM_CONTEXTS; i++) + for (context = 0; context < GUI_KEY_NUM_CONTEXTS; context++) { if ((argc < 4) - || (string_strcmp (argv[3], gui_key_context_string[i]) == 0)) + || (string_strcmp (argv[3], + gui_key_context_string[context]) == 0)) { - gui_key_free_all (&gui_keys[i], &last_gui_key[i], - &gui_keys_count[i]); - gui_key_default_bindings (i); + gui_key_free_all (context, + &gui_keys[context], + &last_gui_key[context], + &gui_keys_count[context], + 1); + gui_key_default_bindings (context, 1); gui_chat_printf (NULL, _("Default key bindings restored for " "context \"%s\""), - gui_key_context_string[i]); + gui_key_context_string[context]); } } } @@ -4287,22 +4298,23 @@ COMMAND_CALLBACK(key) /* add missing keys */ if (string_strcmp (argv[1], "missing") == 0) { - for (i = 0; i < GUI_KEY_NUM_CONTEXTS; i++) + for (context = 0; context < GUI_KEY_NUM_CONTEXTS; context++) { if ((argc < 3) - || (string_strcmp (argv[2], gui_key_context_string[i]) == 0)) + || (string_strcmp (argv[2], + gui_key_context_string[context]) == 0)) { - old_keys_count = gui_keys_count[i]; + old_keys_count = gui_keys_count[context]; gui_key_verbose = 1; - gui_key_default_bindings (i); + gui_key_default_bindings (context, 1); gui_key_verbose = 0; - keys_added = (gui_keys_count[i] > old_keys_count) ? - gui_keys_count[i] - old_keys_count : 0; + keys_added = (gui_keys_count[context] > old_keys_count) ? + gui_keys_count[context] - old_keys_count : 0; gui_chat_printf (NULL, NG_("%d new key added", "%d new keys added " "(context: \"%s\")", keys_added), keys_added, - gui_key_context_string[i]); + gui_key_context_string[context]); } } return WEECHAT_RC_OK; diff --git a/src/core/wee-completion.c b/src/core/wee-completion.c index 4c5fbb12d..150ce8b1d 100644 --- a/src/core/wee-completion.c +++ b/src/core/wee-completion.c @@ -1648,7 +1648,7 @@ completion_list_add_keys_contexts_cb (const void *pointer, void *data, struct t_gui_buffer *buffer, struct t_gui_completion *completion) { - int i; + int context; /* make C compiler happy */ (void) pointer; @@ -1656,9 +1656,9 @@ completion_list_add_keys_contexts_cb (const void *pointer, void *data, (void) completion_item; (void) buffer; - for (i = 0; i < GUI_KEY_NUM_CONTEXTS; i++) + for (context = 0; context < GUI_KEY_NUM_CONTEXTS; context++) { - gui_completion_list_add (completion, gui_key_context_string[i], + gui_completion_list_add (completion, gui_key_context_string[context], 0, WEECHAT_LIST_POS_END); } @@ -1675,7 +1675,7 @@ completion_list_add_keys_codes_cb (const void *pointer, void *data, struct t_gui_buffer *buffer, struct t_gui_completion *completion) { - int i; + int context; struct t_gui_key *ptr_key; /* make C compiler happy */ @@ -1684,9 +1684,9 @@ completion_list_add_keys_codes_cb (const void *pointer, void *data, (void) completion_item; (void) buffer; - for (i = 0; i < GUI_KEY_NUM_CONTEXTS; i++) + for (context = 0; context < GUI_KEY_NUM_CONTEXTS; context++) { - for (ptr_key = gui_keys[i]; ptr_key; ptr_key = ptr_key->next_key) + for (ptr_key = gui_keys[context]; ptr_key; ptr_key = ptr_key->next_key) { gui_completion_list_add (completion, ptr_key->key, 0, WEECHAT_LIST_POS_SORT); @@ -1707,7 +1707,7 @@ completion_list_add_keys_codes_for_reset_cb (const void *pointer, void *data, struct t_gui_buffer *buffer, struct t_gui_completion *completion) { - int i; + int context; struct t_gui_key *ptr_key, *ptr_default_key; /* make C compiler happy */ @@ -1716,12 +1716,13 @@ completion_list_add_keys_codes_for_reset_cb (const void *pointer, void *data, (void) completion_item; (void) buffer; - for (i = 0; i < GUI_KEY_NUM_CONTEXTS; i++) + for (context = 0; context < GUI_KEY_NUM_CONTEXTS; context++) { /* keys added or redefined */ - for (ptr_key = gui_keys[i]; ptr_key; ptr_key = ptr_key->next_key) + for (ptr_key = gui_keys[context]; ptr_key; ptr_key = ptr_key->next_key) { - ptr_default_key = gui_key_search (gui_default_keys[i], ptr_key->key); + ptr_default_key = gui_key_search (gui_default_keys[context], + ptr_key->key); if (!ptr_default_key || (strcmp (ptr_default_key->command, ptr_key->command) != 0)) { @@ -1731,10 +1732,11 @@ completion_list_add_keys_codes_for_reset_cb (const void *pointer, void *data, } /* keys deleted */ - for (ptr_default_key = gui_default_keys[i]; ptr_default_key; + for (ptr_default_key = gui_default_keys[context]; ptr_default_key; ptr_default_key = ptr_default_key->next_key) { - ptr_key = gui_key_search (gui_keys[i], ptr_default_key->key); + ptr_key = gui_key_search (gui_keys[context], + ptr_default_key->key); if (!ptr_key) { gui_completion_list_add (completion, ptr_default_key->key, diff --git a/src/core/wee-config.c b/src/core/wee-config.c index 8aec0eb66..a89eb0540 100644 --- a/src/core/wee-config.c +++ b/src/core/wee-config.c @@ -73,6 +73,9 @@ struct t_config_section *weechat_config_section_proxy = NULL; struct t_config_section *weechat_config_section_bar = NULL; struct t_config_section *weechat_config_section_custom_bar_item = NULL; struct t_config_section *weechat_config_section_notify = NULL; +struct t_config_section *weechat_config_section_key[GUI_KEY_NUM_CONTEXTS] = { + NULL, NULL, NULL, NULL, +}; /* config, startup section */ @@ -1454,7 +1457,7 @@ config_day_change_timer_cb (const void *pointer, void *data, void config_weechat_init_after_read () { - int i; + int context; util_setrlimit (); @@ -1480,10 +1483,10 @@ config_weechat_init_after_read () gui_bar_item_custom_use_temp_items (); /* if no key was found configuration file, then we use default bindings */ - for (i = 0; i < GUI_KEY_NUM_CONTEXTS; i++) + for (context = 0; context < GUI_KEY_NUM_CONTEXTS; context++) { - if (!gui_keys[i]) - gui_key_default_bindings (i); + if (!gui_keys[context]) + gui_key_default_bindings (context, 1); } /* apply filters on all buffers */ @@ -1578,17 +1581,20 @@ int config_weechat_reload_cb (const void *pointer, void *data, struct t_config_file *config_file) { - int i, rc; + int context, rc; /* make C compiler happy */ (void) pointer; (void) data; /* remove all keys */ - for (i = 0; i < GUI_KEY_NUM_CONTEXTS; i++) + for (context = 0; context < GUI_KEY_NUM_CONTEXTS; context++) { - gui_key_free_all (&gui_keys[i], &last_gui_key[i], - &gui_keys_count[i]); + gui_key_free_all (context, + &gui_keys[context], + &last_gui_key[context], + &gui_keys_count[context], + 1); } /* remove all proxies */ @@ -1778,7 +1784,6 @@ config_weechat_palette_change_cb (const void *pointer, void *data, /* make C compiler happy */ (void) pointer; (void) data; - (void) option; error = NULL; number = (int)strtol (option->name, &error, 10); @@ -2602,87 +2607,82 @@ config_weechat_filter_write_cb (const void *pointer, void *data, } /* - * Reads a key option in WeeChat configuration file. + * Searches key context with the section pointer. + * + * Returns key context, -1 if not found. */ int -config_weechat_key_read_cb (const void *pointer, void *data, - struct t_config_file *config_file, - struct t_config_section *section, - const char *option_name, const char *value) +config_weechat_get_key_context (struct t_config_section *section) +{ + int context; + + for (context = 0; context < GUI_KEY_NUM_CONTEXTS; context++) + { + if (section == weechat_config_section_key[context]) + return context; + } + + /* this should never happen */ + return -1; +} + +/* + * Callback called when an option is created in one of these sections: + * key + * key_search + * key_cursor + * key_mouse + */ + +int +config_weechat_key_create_option_cb (const void *pointer, void *data, + struct t_config_file *config_file, + struct t_config_section *section, + const char *option_name, + const char *value) { int context; - char *pos; /* make C compiler happy */ (void) pointer; (void) data; (void) config_file; - if (option_name) - { - context = GUI_KEY_CONTEXT_DEFAULT; - pos = strchr (section->name, '_'); - if (pos) - { - context = gui_key_search_context (pos + 1); - if (context < 0) - context = GUI_KEY_CONTEXT_DEFAULT; - } + if (!value) + return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; - if (value && value[0]) - { - /* bind key (overwrite any binding with same key) */ - gui_key_bind (NULL, context, option_name, value); - } - else - { - /* unbind key if no value given */ - gui_key_unbind (NULL, context, option_name); - } - } + context = config_weechat_get_key_context (section); + gui_key_bind (NULL, context, option_name, value); return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; } /* - * Writes section "key" in WeeChat configuration file. + * Callback called when an option is deleted in one of these sections: + * key + * key_search + * key_cursor + * key_mouse */ int -config_weechat_key_write_cb (const void *pointer, void *data, - struct t_config_file *config_file, - const char *section_name) +config_weechat_key_delete_option_cb (const void *pointer, void *data, + struct t_config_file *config_file, + struct t_config_section *section, + struct t_config_option *option) { - struct t_gui_key *ptr_key; - char *pos; int context; /* make C compiler happy */ (void) pointer; (void) data; + (void) config_file; - if (!config_file_write_line (config_file, section_name, NULL)) - return WEECHAT_CONFIG_WRITE_ERROR; - - context = GUI_KEY_CONTEXT_DEFAULT; - pos = strchr (section_name, '_'); - if (pos) - { - context = gui_key_search_context (pos + 1); - if (context < 0) - context = GUI_KEY_CONTEXT_DEFAULT; - } - for (ptr_key = gui_keys[context]; ptr_key; ptr_key = ptr_key->next_key) - { - if (!config_file_write_line (config_file, ptr_key->key, - "\"%s\"", ptr_key->command)) - { - return WEECHAT_CONFIG_WRITE_ERROR; - } - } + context = config_weechat_get_key_context (section); + gui_key_unbind (NULL, context, option->name); - return WEECHAT_CONFIG_WRITE_OK; + return WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED; } /* @@ -2697,7 +2697,7 @@ int config_weechat_init_options () { struct t_config_section *ptr_section; - int i; + int context; char section_name[128]; weechat_config_file = config_file_new ( @@ -4946,26 +4946,29 @@ config_weechat_init_options () } /* keys */ - for (i = 0; i < GUI_KEY_NUM_CONTEXTS; i++) + for (context = 0; context < GUI_KEY_NUM_CONTEXTS; context++) { - snprintf (section_name, sizeof (section_name), - "key%s%s", - (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : "_", - (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : gui_key_context_string[i]); + snprintf ( + section_name, sizeof (section_name), + "key%s%s", + (context == GUI_KEY_CONTEXT_DEFAULT) ? "" : "_", + (context == GUI_KEY_CONTEXT_DEFAULT) ? + "" : gui_key_context_string[context]); ptr_section = config_file_new_section ( weechat_config_file, section_name, - 0, 0, - &config_weechat_key_read_cb, NULL, NULL, - &config_weechat_key_write_cb, NULL, NULL, - &config_weechat_key_write_cb, NULL, NULL, + 1, 1, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL); + &config_weechat_key_create_option_cb, NULL, NULL, + &config_weechat_key_delete_option_cb, NULL, NULL); if (!ptr_section) { config_file_free (weechat_config_file); weechat_config_file = NULL; return 0; } + weechat_config_section_key[context] = ptr_section; } return 1; diff --git a/src/core/wee-config.h b/src/core/wee-config.h index 921a06203..195efcd75 100644 --- a/src/core/wee-config.h +++ b/src/core/wee-config.h @@ -132,6 +132,7 @@ extern struct t_config_section *weechat_config_section_proxy; extern struct t_config_section *weechat_config_section_bar; extern struct t_config_section *weechat_config_section_custom_bar_item; extern struct t_config_section *weechat_config_section_notify; +extern struct t_config_section *weechat_config_section_key[]; extern struct t_config_option *config_startup_command_after_plugins; extern struct t_config_option *config_startup_command_before_plugins; @@ -387,6 +388,7 @@ extern void config_weechat_debug_set_all (); extern int config_weechat_notify_set (struct t_gui_buffer *buffer, const char *notify); extern void config_get_item_time (char *text_time, int max_length); +extern int config_weechat_get_key_context (struct t_config_section *section); extern int config_weechat_init (); extern int config_weechat_read (); extern int config_weechat_write (); diff --git a/src/gui/curses/gui-curses-key.c b/src/gui/curses/gui-curses-key.c index 6d9a544c1..9dcb2c227 100644 --- a/src/gui/curses/gui-curses-key.c +++ b/src/gui/curses/gui-curses-key.c @@ -45,7 +45,8 @@ #include "../gui-window.h" #include "gui-curses.h" -#define BIND(key, command) gui_key_default_bind(context, key, command) +#define BIND(key, command) \ + gui_key_default_bind(context, key, command, create_option) /* @@ -53,21 +54,25 @@ */ void -gui_key_default_bind (int context, const char *key, const char *command) +gui_key_default_bind (int context, const char *key, const char *command, + int create_option) { struct t_gui_key *ptr_key; ptr_key = gui_key_search (gui_keys[context], key); if (!ptr_key) - gui_key_new (NULL, context, key, command); + gui_key_new (NULL, context, key, command, create_option); } /* * Creates default key bindings for a given context. + * + * If create_option == 1, config options are created, otherwise keys are just + * added to linked list (gui_keys[]). */ void -gui_key_default_bindings (int context) +gui_key_default_bindings (int context, int create_option) { int i; char key_str[32], command[32]; diff --git a/src/gui/curses/gui-curses.h b/src/gui/curses/gui-curses.h index 1e7286d05..086a59edd 100644 --- a/src/gui/curses/gui-curses.h +++ b/src/gui/curses/gui-curses.h @@ -104,7 +104,7 @@ extern void gui_chat_calculate_line_diff (struct t_gui_window *window, int *line_pos, int difference); /* key functions */ -extern void gui_key_default_bindings (int context); +extern void gui_key_default_bindings (int context, int create_option); extern int gui_key_read_cb (const void *pointer, void *data, int fd); /* window functions */ diff --git a/src/gui/gui-buffer.c b/src/gui/gui-buffer.c index 343e15908..4858bc49f 100644 --- a/src/gui/gui-buffer.c +++ b/src/gui/gui-buffer.c @@ -2384,11 +2384,13 @@ gui_buffer_set (struct t_gui_buffer *buffer, const char *property, { if (strcmp (property + 11, "*") == 0) { - gui_key_free_all (&buffer->keys, &buffer->last_key, - &buffer->keys_count); + gui_key_free_all (-1, &buffer->keys, &buffer->last_key, + &buffer->keys_count, 0); } else - gui_key_unbind (buffer, 0, property + 11); + { + gui_key_unbind (buffer, -1, property + 11); + } } else if (strcmp (property, "input") == 0) { @@ -3128,8 +3130,8 @@ gui_buffer_close (struct t_gui_buffer *buffer) gui_nicklist_remove_group (buffer, buffer->nicklist_root); if (buffer->hotlist_max_level_nicks) hashtable_free (buffer->hotlist_max_level_nicks); - gui_key_free_all (&buffer->keys, &buffer->last_key, - &buffer->keys_count); + gui_key_free_all (-1, &buffer->keys, &buffer->last_key, + &buffer->keys_count, 0); gui_buffer_local_var_remove_all (buffer); hashtable_free (buffer->local_variables); if (buffer->plugin_name_for_upgrade) diff --git a/src/gui/gui-key.c b/src/gui/gui-key.c index d5e916ab9..c801b2323 100644 --- a/src/gui/gui-key.c +++ b/src/gui/gui-key.c @@ -31,6 +31,7 @@ #include "../core/weechat.h" #include "../core/wee-config.h" +#include "../core/wee-config-file.h" #include "../core/wee-eval.h" #include "../core/wee-hashtable.h" #include "../core/wee-hdata.h" @@ -112,7 +113,7 @@ time_t gui_key_last_activity_time = 0; /* last activity time (key) */ void gui_key_init () { - int i; + int context; gui_key_combo_buffer[0] = '\0'; gui_key_grab = 0; @@ -120,21 +121,21 @@ gui_key_init () gui_key_last_activity_time = time (NULL); /* create default keys and save them in a separate list */ - for (i = 0; i < GUI_KEY_NUM_CONTEXTS; i++) - { - gui_keys[i] = NULL; - last_gui_key[i] = NULL; - gui_default_keys[i] = NULL; - last_gui_default_key[i] = NULL; - gui_keys_count[i] = 0; - gui_default_keys_count[i] = 0; - gui_key_default_bindings (i); - gui_default_keys[i] = gui_keys[i]; - last_gui_default_key[i] = last_gui_key[i]; - gui_default_keys_count[i] = gui_keys_count[i]; - gui_keys[i] = NULL; - last_gui_key[i] = NULL; - gui_keys_count[i] = 0; + for (context = 0; context < GUI_KEY_NUM_CONTEXTS; context++) + { + gui_keys[context] = NULL; + last_gui_key[context] = NULL; + gui_default_keys[context] = NULL; + last_gui_default_key[context] = NULL; + gui_keys_count[context] = 0; + gui_default_keys_count[context] = 0; + gui_key_default_bindings (context, 0); + gui_default_keys[context] = gui_keys[context]; + last_gui_default_key[context] = last_gui_key[context]; + gui_default_keys_count[context] = gui_keys_count[context]; + gui_keys[context] = NULL; + last_gui_key[context] = NULL; + gui_keys_count[context] = 0; } } @@ -879,6 +880,71 @@ gui_key_legacy_to_alias (const char *key) } /* + * Amends key: transform upper case ctrl keys to lower case and replace " " + * by "space". + * + * Examples: + * "ctrl-a" => "ctrl-a" (unchanged) + * "meta-A" => "meta-A" (unchanged) + * 'return" => "return" (unchanged) + * "ctrl-G" => "ctrl-g" + * "ctrl-C,b" => "ctrl-c,b" + * " " => "space" + * "meta- " => "meta-space" + * + * Note: result must be freed after use. + */ + +char * +gui_key_amend (const char *key) +{ + char **result, str_key[2]; + const char *ptr_key; + int length; + + if (!key) + return NULL; + + if ((key[0] == '@') && strchr (key, ':')) + return strdup (key); + + result = string_dyn_alloc (strlen (key) + 1); + if (!result) + return NULL; + + ptr_key = key; + while (ptr_key && ptr_key[0]) + { + if (ptr_key[0] == ' ') + { + string_dyn_concat (result, "space", -1); + ptr_key++; + } + else if (strncmp (ptr_key, "ctrl-", 5) == 0) + { + string_dyn_concat (result, ptr_key, 5); + ptr_key += 5; + if (ptr_key[0]) + { + str_key[0] = ((ptr_key[0] >= 'A') && (ptr_key[0] <= 'Z')) ? + ptr_key[0] + ('a' - 'A') : ptr_key[0]; + str_key[1] = '\0'; + string_dyn_concat (result, str_key, -1); + ptr_key++; + } + } + else + { + length = utf8_char_size (ptr_key); + string_dyn_concat (result, ptr_key, length); + ptr_key += length; + } + } + + return string_dyn_free (result, 0); +} + +/* * Searches for position of a key (to keep keys sorted). */ @@ -1152,29 +1218,128 @@ gui_key_is_safe (int context, const char *key) } /* + * Callback for changes on a key option. + */ + +void +gui_key_option_change_cb (const void *pointer, void *data, + struct t_config_option *option) +{ + struct t_gui_key *ptr_key; + int context; + + /* make C compiler happy */ + (void) pointer; + (void) data; + + context = config_weechat_get_key_context (option->section); + if (context < 0) + return; + + ptr_key = gui_key_search (gui_keys[context], option->name); + if (!ptr_key) + return; + + if (ptr_key->command) + free (ptr_key->command); + ptr_key->command = strdup (CONFIG_STRING(option)); +} + +/* + * Creates a new key option. + * + * Returns pointer to existing or new option. + */ + +struct t_config_option * +gui_key_new_option (int context, const char *name, const char *value) +{ + struct t_config_option *ptr_option; + struct t_gui_key *ptr_key; + char str_description[1024]; + + if (!name || !value) + return NULL; + + ptr_option = config_file_search_option (weechat_config_file, + weechat_config_section_key[context], + name); + if (ptr_option) + { + config_file_option_set (ptr_option, value, 1); + } + else + { + snprintf (str_description, sizeof (str_description), + _("key \"%s\" in context \"%s\""), + name, + gui_key_context_string[context]); + ptr_key = gui_key_search (gui_default_keys[context], name); + ptr_option = config_file_new_option ( + weechat_config_file, weechat_config_section_key[context], + name, "string", + str_description, + NULL, 0, 0, + (ptr_key) ? ptr_key->command : "", + value, + 0, + NULL, NULL, NULL, + &gui_key_option_change_cb, NULL, NULL, + NULL, NULL, NULL); + } + + return ptr_option; +} + +/* * Adds a new key in keys list. * * If buffer is not null, then key is specific to buffer, otherwise it's general * key (for most keys). * + * If create_option == 1, a config option is created as well. + * * Returns pointer to new key, NULL if error. */ struct t_gui_key * gui_key_new (struct t_gui_buffer *buffer, int context, const char *key, - const char *command) + const char *command, int create_option) { + char *key_amended; + struct t_config_option *ptr_option; struct t_gui_key *new_key; if (!key || !command) return NULL; + key_amended = gui_key_amend (key); + if (!key_amended) + return NULL; + + ptr_option = NULL; + + if (!buffer && create_option) + { + ptr_option = gui_key_new_option (context, key_amended, command); + if (!ptr_option) + { + free (key_amended); + return NULL; + } + } + new_key = malloc (sizeof (*new_key)); if (!new_key) + { + if (ptr_option) + config_file_option_free (ptr_option, 0); + free (key_amended); return NULL; + } - new_key->key = strdup (key); - new_key->chunks = string_split (key, ",", NULL, 0, 0, + new_key->key = key_amended; + new_key->chunks = string_split (key_amended, ",", NULL, 0, 0, &new_key->chunks_count); new_key->command = strdup (command); gui_key_set_areas (new_key); @@ -1182,14 +1347,17 @@ gui_key_new (struct t_gui_buffer *buffer, int context, const char *key, if (buffer) { - gui_key_insert_sorted (&buffer->keys, &buffer->last_key, - &buffer->keys_count, new_key); + gui_key_insert_sorted (&buffer->keys, + &buffer->last_key, + &buffer->keys_count, + new_key); } else { gui_key_insert_sorted (&gui_keys[context], &last_gui_key[context], - &gui_keys_count[context], new_key); + &gui_keys_count[context], + new_key); } if (gui_key_verbose) @@ -1345,7 +1513,7 @@ gui_key_bind (struct t_gui_buffer *buffer, int context, const char *key, gui_key_unbind (buffer, context, key); - return gui_key_new (buffer, context, key, command); + return gui_key_new (buffer, context, key, command, 1); } /* @@ -1374,7 +1542,7 @@ gui_key_bind_plugin_hashtable_map_cb (void *data, ptr_key = gui_key_search (gui_keys[user_data[0]], key); if (!ptr_key) { - if (gui_key_new (NULL, user_data[0], key, value)) + if (gui_key_new (NULL, user_data[0], key, value, 1)) user_data[1]++; } } @@ -1422,17 +1590,25 @@ gui_key_bind_plugin (const char *context, struct t_hashtable *keys) int gui_key_unbind (struct t_gui_buffer *buffer, int context, const char *key) { + char *key_amended; struct t_gui_key *ptr_key; + key_amended = gui_key_amend (key); + if (!key_amended) + return 0; + ptr_key = gui_key_search ((buffer) ? buffer->keys : gui_keys[context], - key); + key_amended); if (!ptr_key) + { + free (key_amended); return 0; + } if (buffer) { - gui_key_free (&buffer->keys, &buffer->last_key, - &buffer->keys_count, ptr_key); + gui_key_free (-1, &buffer->keys, &buffer->last_key, + &buffer->keys_count, ptr_key, 0); } else { @@ -1440,15 +1616,17 @@ gui_key_unbind (struct t_gui_buffer *buffer, int context, const char *key) { gui_chat_printf (NULL, _("Key \"%s\" unbound (context: \"%s\")"), - key, + key_amended, gui_key_context_string[context]); } - gui_key_free (&gui_keys[context], &last_gui_key[context], - &gui_keys_count[context], ptr_key); + gui_key_free (context, &gui_keys[context], &last_gui_key[context], + &gui_keys_count[context], ptr_key, 1); } (void) hook_signal_send ("key_unbind", - WEECHAT_HOOK_SIGNAL_STRING, (char *)key); + WEECHAT_HOOK_SIGNAL_STRING, key_amended); + + free (key_amended); return 1; } @@ -2070,17 +2248,31 @@ end: /* * Deletes a key binding. + * + * If delete_option == 1, the config option is deleted. */ void -gui_key_free (struct t_gui_key **keys, struct t_gui_key **last_key, - int *keys_count, struct t_gui_key *key) +gui_key_free (int context, + struct t_gui_key **keys, struct t_gui_key **last_key, + int *keys_count, struct t_gui_key *key, int delete_option) { + struct t_config_option *ptr_option; int i; if (!key) return; + if (delete_option) + { + ptr_option = config_file_search_option ( + weechat_config_file, + weechat_config_section_key[context], + key->key); + if (ptr_option) + config_file_option_free (ptr_option, 1); + } + /* free memory */ if (key->key) free (key->key); @@ -2113,15 +2305,19 @@ gui_key_free (struct t_gui_key **keys, struct t_gui_key **last_key, /* * Deletes all key bindings. + * + * If delete_option == 1, the config options are deleted. */ void -gui_key_free_all (struct t_gui_key **keys, struct t_gui_key **last_key, - int *keys_count) +gui_key_free_all (int context, struct t_gui_key **keys, + struct t_gui_key **last_key, + int *keys_count, int delete_option) { while (*keys) { - gui_key_free (keys, last_key, keys_count, *keys); + gui_key_free (context, keys, last_key, keys_count, *keys, + delete_option); } } @@ -2501,20 +2697,26 @@ gui_key_paste_cancel () void gui_key_end () { - int i; + int context; /* free key buffer */ if (gui_key_buffer) free (gui_key_buffer); - for (i = 0; i < GUI_KEY_NUM_CONTEXTS; i++) + for (context = 0; context < GUI_KEY_NUM_CONTEXTS; context++) { /* free keys */ - gui_key_free_all (&gui_keys[i], &last_gui_key[i], - &gui_keys_count[i]); + gui_key_free_all (context, + &gui_keys[context], + &last_gui_key[context], + &gui_keys_count[context], + 0); /* free default keys */ - gui_key_free_all (&gui_default_keys[i], &last_gui_default_key[i], - &gui_default_keys_count[i]); + gui_key_free_all (context, + &gui_default_keys[context], + &last_gui_default_key[context], + &gui_default_keys_count[context], + 0); } } @@ -2527,7 +2729,7 @@ gui_key_hdata_key_cb (const void *pointer, void *data, const char *hdata_name) { struct t_hdata *hdata; - int i; + int context; char str_list[128]; /* make C compiler happy */ @@ -2546,28 +2748,32 @@ gui_key_hdata_key_cb (const void *pointer, void *data, HDATA_VAR(struct t_gui_key, score, INTEGER, 0, NULL, NULL); HDATA_VAR(struct t_gui_key, prev_key, POINTER, 0, NULL, hdata_name); HDATA_VAR(struct t_gui_key, next_key, POINTER, 0, NULL, hdata_name); - for (i = 0; i < GUI_KEY_NUM_CONTEXTS; i++) + for (context = 0; context < GUI_KEY_NUM_CONTEXTS; context++) { snprintf (str_list, sizeof (str_list), "gui_keys%s%s", - (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : "_", - (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : gui_key_context_string[i]); - hdata_new_list (hdata, str_list, &gui_keys[i], 0); + (context == GUI_KEY_CONTEXT_DEFAULT) ? "" : "_", + (context == GUI_KEY_CONTEXT_DEFAULT) ? + "" : gui_key_context_string[context]); + hdata_new_list (hdata, str_list, &gui_keys[context], 0); snprintf (str_list, sizeof (str_list), "last_gui_key%s%s", - (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : "_", - (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : gui_key_context_string[i]); - hdata_new_list (hdata, str_list, &last_gui_key[i], 0); + (context == GUI_KEY_CONTEXT_DEFAULT) ? "" : "_", + (context == GUI_KEY_CONTEXT_DEFAULT) ? + "" : gui_key_context_string[context]); + hdata_new_list (hdata, str_list, &last_gui_key[context], 0); snprintf (str_list, sizeof (str_list), "gui_default_keys%s%s", - (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : "_", - (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : gui_key_context_string[i]); - hdata_new_list (hdata, str_list, &gui_default_keys[i], 0); + (context == GUI_KEY_CONTEXT_DEFAULT) ? "" : "_", + (context == GUI_KEY_CONTEXT_DEFAULT) ? + "" : gui_key_context_string[context]); + hdata_new_list (hdata, str_list, &gui_default_keys[context], 0); snprintf (str_list, sizeof (str_list), "last_gui_default_key%s%s", - (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : "_", - (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : gui_key_context_string[i]); - hdata_new_list (hdata, str_list, &last_gui_default_key[i], 0); + (context == GUI_KEY_CONTEXT_DEFAULT) ? "" : "_", + (context == GUI_KEY_CONTEXT_DEFAULT) ? + "" : gui_key_context_string[context]); + hdata_new_list (hdata, str_list, &last_gui_default_key[context], 0); } } return hdata; @@ -2647,7 +2853,7 @@ void gui_key_print_log (struct t_gui_buffer *buffer) { struct t_gui_key *ptr_key; - int i; + int context; if (buffer) { @@ -2662,15 +2868,16 @@ gui_key_print_log (struct t_gui_buffer *buffer) } else { - for (i = 0; i < GUI_KEY_NUM_CONTEXTS; i++) + for (context = 0; context < GUI_KEY_NUM_CONTEXTS; context++) { log_printf (""); - log_printf ("[keys for context: %s]", gui_key_context_string[i]); - log_printf (" keys . . . . . . . . : 0x%lx", gui_keys[i]); - log_printf (" last_key . . . . . . : 0x%lx", last_gui_key[i]); - log_printf (" keys_count . . . . . : %d", gui_keys_count[i]); + log_printf ("[keys for context: %s]", gui_key_context_string[context]); + log_printf (" keys . . . . . . . . : 0x%lx", gui_keys[context]); + log_printf (" last_key . . . . . . : 0x%lx", last_gui_key[context]); + log_printf (" keys_count . . . . . : %d", gui_keys_count[context]); - for (ptr_key = gui_keys[i]; ptr_key; ptr_key = ptr_key->next_key) + for (ptr_key = gui_keys[context]; ptr_key; + ptr_key = ptr_key->next_key) { log_printf (""); gui_key_print_log_key (ptr_key, ""); diff --git a/src/gui/gui-key.h b/src/gui/gui-key.h index fed8ca750..7110a0d9c 100644 --- a/src/gui/gui-key.h +++ b/src/gui/gui-key.h @@ -99,7 +99,8 @@ extern int gui_key_is_safe (int context, const char *key); extern struct t_gui_key *gui_key_new (struct t_gui_buffer *buffer, int context, const char *key, - const char *command); + const char *command, + int create_option); extern struct t_gui_key *gui_key_search (struct t_gui_key *keys, const char *key); extern struct t_gui_key *gui_key_bind (struct t_gui_buffer *buffer, @@ -112,13 +113,17 @@ extern int gui_key_unbind (struct t_gui_buffer *buffer, int context, extern int gui_key_unbind_plugin (const char *context, const char *key); extern int gui_key_focus (const char *key, int context); extern int gui_key_pressed (const char *key_str); -extern void gui_key_free (struct t_gui_key **keys, +extern void gui_key_free (int context, + struct t_gui_key **keys, struct t_gui_key **last_key, int *keys_count, - struct t_gui_key *key); -extern void gui_key_free_all (struct t_gui_key **keys, + struct t_gui_key *key, + int delete_option); +extern void gui_key_free_all (int context, + struct t_gui_key **keys, struct t_gui_key **last_key, - int *keys_count); + int *keys_count, + int delete_option); extern void gui_key_buffer_reset (); extern void gui_key_buffer_add (unsigned char key); extern int gui_key_buffer_search (int start_index, int max_index, @@ -145,6 +150,6 @@ extern void gui_key_print_log (struct t_gui_buffer *buffer); /* key functions (GUI dependent) */ -extern void gui_key_default_bindings (int context); +extern void gui_key_default_bindings (int context, int create_option); #endif /* WEECHAT_GUI_KEY_H */ diff --git a/tests/unit/gui/test-gui-key.cpp b/tests/unit/gui/test-gui-key.cpp index 1cb6323c5..f75294b5d 100644 --- a/tests/unit/gui/test-gui-key.cpp +++ b/tests/unit/gui/test-gui-key.cpp @@ -25,9 +25,24 @@ extern "C" { +#include "src/core/wee-config.h" +#include "src/core/wee-input.h" +#include "src/core/wee-string.h" +#include "src/gui/gui-buffer.h" #include "src/gui/gui-key.h" +extern int gui_key_get_current_context (); extern char *gui_key_legacy_internal_code (const char *key); +extern char *gui_key_amend (const char *key); +extern struct t_config_option *gui_key_new_option (int context, + const char *name, + const char *value); +extern int gui_key_compare_chunks (const char **chunks, int chunks_count, + const char **key_chunks, int key_chunks_count); +extern struct t_gui_key *gui_key_search_part (struct t_gui_buffer *buffer, int context, + const char **chunks1, int chunks1_count, + const char **chunks2, int chunks2_count, + int *exact_match); } #define WEE_CHECK_EXP_KEY(__rc, __key_name, __key_name_alias, __key) \ @@ -94,7 +109,19 @@ TEST(GuiKey, SearchContext) TEST(GuiKey, GetCurrentContext) { - /* TODO: write tests */ + LONGS_EQUAL(GUI_KEY_CONTEXT_DEFAULT, gui_key_get_current_context ()); + + input_data (gui_buffers, "/cursor", NULL); + LONGS_EQUAL(GUI_KEY_CONTEXT_CURSOR, gui_key_get_current_context ()); + + input_data (gui_buffers, "/cursor stop", NULL); + LONGS_EQUAL(GUI_KEY_CONTEXT_DEFAULT, gui_key_get_current_context ()); + + input_data (gui_buffers, "/input search_text_here", NULL); + LONGS_EQUAL(GUI_KEY_CONTEXT_SEARCH, gui_key_get_current_context ()); + + input_data (gui_buffers, "/input search_stop", NULL); + LONGS_EQUAL(GUI_KEY_CONTEXT_DEFAULT, gui_key_get_current_context ()); } /* @@ -836,6 +863,33 @@ TEST(GuiKey, LegacyToAlias) /* * Tests functions: + * gui_key_amend + */ + +TEST(GuiKey, Amend) +{ + char *str; + + WEE_TEST_STR(NULL, gui_key_amend (NULL)); + + /* no changes */ + WEE_TEST_STR("", gui_key_amend ("")); + WEE_TEST_STR("a", gui_key_amend ("a")); + WEE_TEST_STR("@chat:button1", gui_key_amend ("@chat:button1")); + WEE_TEST_STR("meta-A", gui_key_amend ("meta-A")); + WEE_TEST_STR("ctrl-a", gui_key_amend ("ctrl-a")); + WEE_TEST_STR("return", gui_key_amend ("return")); + + /* changes */ + WEE_TEST_STR("ctrl-a", gui_key_amend ("ctrl-A")); + WEE_TEST_STR("ctrl-c,b", gui_key_amend ("ctrl-C,b")); + WEE_TEST_STR("ctrl-c,ctrl-b,A", gui_key_amend ("ctrl-C,ctrl-B,A")); + WEE_TEST_STR("space", gui_key_amend (" ")); + WEE_TEST_STR("meta-space", gui_key_amend ("meta- ")); +} + +/* + * Tests functions: * gui_key_find_pos */ @@ -982,12 +1036,140 @@ TEST(GuiKey, IsSafe) /* * Tests functions: + * gui_key_option_change_cb + */ + +TEST(GuiKey, OptionChangeCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_key_new_option + */ + +TEST(GuiKey, NewOption) +{ + struct t_config_option *ptr_option; + int context; + + POINTERS_EQUAL(NULL, gui_key_new_option (GUI_KEY_CONTEXT_DEFAULT, + NULL, NULL)); + POINTERS_EQUAL(NULL, gui_key_new_option (GUI_KEY_CONTEXT_DEFAULT, + "meta-a,meta-b,meta-c", NULL)); + POINTERS_EQUAL(NULL, gui_key_new_option (GUI_KEY_CONTEXT_DEFAULT, + NULL, "/mute")); + + for (context = 0; context < GUI_KEY_NUM_CONTEXTS; context++) + { + POINTERS_EQUAL(NULL, + config_file_search_option ( + weechat_config_file, + weechat_config_section_key[context], + "meta-a,meta-b,meta-c")); + ptr_option = gui_key_new_option (context, + "meta-a,meta-b,meta-c", "/mute"); + CHECK(ptr_option); + POINTERS_EQUAL(ptr_option, + config_file_search_option ( + weechat_config_file, + weechat_config_section_key[context], + "meta-a,meta-b,meta-c")); + STRCMP_EQUAL("/mute", CONFIG_STRING(ptr_option)); + config_file_option_free (ptr_option, 0); + } +} + +/* + * Tests functions: * gui_key_new */ TEST(GuiKey, New) { - /* TODO: write tests */ + struct t_gui_key *ptr_key; + + POINTERS_EQUAL(NULL, gui_key_new (NULL, GUI_KEY_CONTEXT_DEFAULT, + NULL, NULL, 1)); + POINTERS_EQUAL(NULL, gui_key_new (NULL, GUI_KEY_CONTEXT_DEFAULT, + "meta-a,meta-b,meta-c", NULL, 1)); + POINTERS_EQUAL(NULL, gui_key_new (NULL, GUI_KEY_CONTEXT_DEFAULT, + NULL, "/mute", 1)); + + ptr_key = gui_key_new (NULL, GUI_KEY_CONTEXT_DEFAULT, + "meta-a,meta-b,meta-c", "/mute", 1); + CHECK(ptr_key); + STRCMP_EQUAL("meta-a,meta-b,meta-c", ptr_key->key); + LONGS_EQUAL(3, ptr_key->chunks_count); + STRCMP_EQUAL("meta-a", ptr_key->chunks[0]); + STRCMP_EQUAL("meta-b", ptr_key->chunks[1]); + STRCMP_EQUAL("meta-c", ptr_key->chunks[2]); + LONGS_EQUAL(GUI_KEY_FOCUS_ANY, ptr_key->area_type[0]); + LONGS_EQUAL(GUI_KEY_FOCUS_ANY, ptr_key->area_type[1]); + POINTERS_EQUAL(NULL, ptr_key->area_key); + STRCMP_EQUAL("/mute", ptr_key->command); + LONGS_EQUAL(0, ptr_key->score); + gui_key_free (GUI_KEY_CONTEXT_DEFAULT, + &gui_keys[GUI_KEY_CONTEXT_DEFAULT], + &last_gui_key[GUI_KEY_CONTEXT_DEFAULT], + &gui_keys_count[GUI_KEY_CONTEXT_DEFAULT], + ptr_key, + 1); + + ptr_key = gui_key_new (NULL, GUI_KEY_CONTEXT_CURSOR, + "@chat:z", "/print z", 1); + CHECK(ptr_key); + STRCMP_EQUAL("@chat:z", ptr_key->key); + LONGS_EQUAL(1, ptr_key->chunks_count); + STRCMP_EQUAL("@chat:z", ptr_key->chunks[0]); + LONGS_EQUAL(GUI_KEY_FOCUS_CHAT, ptr_key->area_type[0]); + LONGS_EQUAL(GUI_KEY_FOCUS_ANY, ptr_key->area_type[1]); + STRCMP_EQUAL("z", ptr_key->area_key); + STRCMP_EQUAL("/print z", ptr_key->command); + LONGS_EQUAL(368, ptr_key->score); + gui_key_free (GUI_KEY_CONTEXT_CURSOR, + &gui_keys[GUI_KEY_CONTEXT_CURSOR], + &last_gui_key[GUI_KEY_CONTEXT_CURSOR], + &gui_keys_count[GUI_KEY_CONTEXT_CURSOR], + ptr_key, + 1); + + ptr_key = gui_key_new (NULL, GUI_KEY_CONTEXT_MOUSE, + "@chat:wheelup", "/print wheelup", 1); + CHECK(ptr_key); + STRCMP_EQUAL("@chat:wheelup", ptr_key->key); + LONGS_EQUAL(1, ptr_key->chunks_count); + STRCMP_EQUAL("@chat:wheelup", ptr_key->chunks[0]); + LONGS_EQUAL(GUI_KEY_FOCUS_CHAT, ptr_key->area_type[0]); + LONGS_EQUAL(GUI_KEY_FOCUS_ANY, ptr_key->area_type[1]); + STRCMP_EQUAL("wheelup", ptr_key->area_key); + STRCMP_EQUAL("/print wheelup", ptr_key->command); + LONGS_EQUAL(368, ptr_key->score); + gui_key_free (GUI_KEY_CONTEXT_MOUSE, + &gui_keys[GUI_KEY_CONTEXT_MOUSE], + &last_gui_key[GUI_KEY_CONTEXT_MOUSE], + &gui_keys_count[GUI_KEY_CONTEXT_MOUSE], + ptr_key, + 1); + + ptr_key = gui_key_new (NULL, GUI_KEY_CONTEXT_MOUSE, + "@bar(nicklist)>chat:button1", "/print button1", 1); + CHECK(ptr_key); + STRCMP_EQUAL("@bar(nicklist)>chat:button1", ptr_key->key); + LONGS_EQUAL(1, ptr_key->chunks_count); + STRCMP_EQUAL("@bar(nicklist)>chat:button1", ptr_key->chunks[0]); + LONGS_EQUAL(GUI_KEY_FOCUS_BAR, ptr_key->area_type[0]); + LONGS_EQUAL(GUI_KEY_FOCUS_CHAT, ptr_key->area_type[1]); + STRCMP_EQUAL("button1", ptr_key->area_key); + STRCMP_EQUAL("/print button1", ptr_key->command); + LONGS_EQUAL(272, ptr_key->score); + gui_key_free (GUI_KEY_CONTEXT_MOUSE, + &gui_keys[GUI_KEY_CONTEXT_MOUSE], + &last_gui_key[GUI_KEY_CONTEXT_MOUSE], + &gui_keys_count[GUI_KEY_CONTEXT_MOUSE], + ptr_key, + 1); } /* @@ -997,7 +1179,79 @@ TEST(GuiKey, New) TEST(GuiKey, Search) { - /* TODO: write tests */ + struct t_gui_key *ptr_key; + + POINTERS_EQUAL(NULL, gui_key_search (NULL, NULL)); + POINTERS_EQUAL(NULL, gui_key_search (NULL, "meta-a")); + POINTERS_EQUAL(NULL, + gui_key_search ( + gui_keys[GUI_KEY_CONTEXT_DEFAULT], NULL)); + POINTERS_EQUAL(NULL, + gui_key_search ( + gui_keys[GUI_KEY_CONTEXT_DEFAULT], "")); + POINTERS_EQUAL(NULL, + gui_key_search ( + gui_keys[GUI_KEY_CONTEXT_DEFAULT], "meta-")); + POINTERS_EQUAL(NULL, + gui_key_search ( + gui_keys[GUI_KEY_CONTEXT_DEFAULT], "unknown")); + POINTERS_EQUAL(NULL, + gui_key_search ( + gui_keys[GUI_KEY_CONTEXT_SEARCH], "meta-a")); + POINTERS_EQUAL(NULL, + gui_key_search ( + gui_keys[GUI_KEY_CONTEXT_CURSOR], "meta-a")); + POINTERS_EQUAL(NULL, + gui_key_search ( + gui_keys[GUI_KEY_CONTEXT_MOUSE], "meta-a")); + + ptr_key = gui_key_search (gui_keys[GUI_KEY_CONTEXT_DEFAULT], "meta-a"); + CHECK(ptr_key); + STRCMP_EQUAL("meta-a", ptr_key->key); + STRCMP_EQUAL("/buffer jump smart", ptr_key->command); + + ptr_key = gui_key_search (gui_keys[GUI_KEY_CONTEXT_DEFAULT], + "meta-w,meta-up"); + CHECK(ptr_key); + STRCMP_EQUAL("meta-w,meta-up", ptr_key->key); + STRCMP_EQUAL("/window up", ptr_key->command); +} + +/* + * Tests functions: + * gui_key_compare_chunks + */ + +TEST(GuiKey, CompareChunks) +{ + struct t_gui_key *ptr_key1, *ptr_key2; + + ptr_key1 = gui_key_search (gui_keys[GUI_KEY_CONTEXT_DEFAULT], "meta-a"); + ptr_key2 = gui_key_search (gui_keys[GUI_KEY_CONTEXT_DEFAULT], "meta-w,meta-down"); + LONGS_EQUAL(0, + gui_key_compare_chunks ( + (const char **)ptr_key1->chunks, ptr_key1->chunks_count, + (const char **)ptr_key2->chunks, ptr_key2->chunks_count)); + + ptr_key1 = gui_key_new (NULL, GUI_KEY_CONTEXT_DEFAULT, "meta-w", "/mute", 1); + ptr_key2 = gui_key_search (gui_keys[GUI_KEY_CONTEXT_DEFAULT], "meta-w,meta-down"); + LONGS_EQUAL(1, + gui_key_compare_chunks ( + (const char **)ptr_key1->chunks, ptr_key1->chunks_count, + (const char **)ptr_key2->chunks, ptr_key2->chunks_count)); + gui_key_free (GUI_KEY_CONTEXT_MOUSE, + &gui_keys[GUI_KEY_CONTEXT_MOUSE], + &last_gui_key[GUI_KEY_CONTEXT_MOUSE], + &gui_keys_count[GUI_KEY_CONTEXT_MOUSE], + ptr_key1, + 1); + + ptr_key1 = gui_key_search (gui_keys[GUI_KEY_CONTEXT_DEFAULT], "meta-w,meta-down"); + ptr_key2 = gui_key_search (gui_keys[GUI_KEY_CONTEXT_DEFAULT], "meta-w,meta-down"); + LONGS_EQUAL(2, + gui_key_compare_chunks ( + (const char **)ptr_key1->chunks, ptr_key1->chunks_count, + (const char **)ptr_key2->chunks, ptr_key2->chunks_count)); } /* @@ -1007,7 +1261,63 @@ TEST(GuiKey, Search) TEST(GuiKey, SearchPart) { - /* TODO: write tests */ + struct t_gui_key *new_key, *ptr_key; + char **chunks1, **chunks2; + int chunks1_count, chunks2_count, exact_match; + + chunks1 = string_split ("meta-a", ",", NULL, 0, 0, &chunks1_count); + chunks2 = string_split ("meta-w", ",", NULL, 0, 0, &chunks2_count); + + POINTERS_EQUAL(NULL, gui_key_search_part (NULL, GUI_KEY_CONTEXT_DEFAULT, + NULL, 0, NULL, 0, NULL)); + POINTERS_EQUAL(NULL, gui_key_search_part (NULL, GUI_KEY_CONTEXT_DEFAULT, + (const char **)chunks1, 0, + NULL, 0, + NULL)); + POINTERS_EQUAL(NULL, gui_key_search_part (NULL, GUI_KEY_CONTEXT_DEFAULT, + NULL, 0, + (const char **)chunks2, 0, + NULL)); + POINTERS_EQUAL(NULL, gui_key_search_part (NULL, GUI_KEY_CONTEXT_DEFAULT, + (const char **)chunks1, 0, + (const char **)chunks2, 0, + NULL)); + + exact_match = -1; + ptr_key = gui_key_search_part (NULL, GUI_KEY_CONTEXT_DEFAULT, + (const char **)chunks1, chunks1_count, + NULL, 0, + &exact_match); + CHECK(ptr_key); + STRCMP_EQUAL("meta-a", ptr_key->key); + LONGS_EQUAL(1, exact_match); + + exact_match = -1; + ptr_key = gui_key_search_part (NULL, GUI_KEY_CONTEXT_DEFAULT, + NULL, 0, + (const char **)chunks2, chunks2_count, + &exact_match); + CHECK(ptr_key); + STRCMP_EQUAL("meta-w,meta-b", ptr_key->key); + LONGS_EQUAL(0, exact_match); + + new_key = gui_key_new (NULL, GUI_KEY_CONTEXT_DEFAULT, "meta-w", "/mute", 1); + + exact_match = -1; + ptr_key = gui_key_search_part (NULL, GUI_KEY_CONTEXT_DEFAULT, + NULL, 0, + (const char **)chunks2, chunks2_count, + &exact_match); + CHECK(ptr_key); + STRCMP_EQUAL("meta-w", ptr_key->key); + LONGS_EQUAL(1, exact_match); + + gui_key_free (GUI_KEY_CONTEXT_DEFAULT, + &gui_keys[GUI_KEY_CONTEXT_DEFAULT], + &last_gui_key[GUI_KEY_CONTEXT_DEFAULT], + &gui_keys_count[GUI_KEY_CONTEXT_DEFAULT], + new_key, + 1); } /* |