diff options
-rw-r--r-- | ChangeLog.adoc | 1 | ||||
-rw-r--r-- | po/POTFILES.in | 2 | ||||
-rw-r--r-- | po/srcfiles.cmake | 2 | ||||
-rw-r--r-- | src/core/wee-command.c | 225 | ||||
-rw-r--r-- | src/core/wee-completion.c | 86 | ||||
-rw-r--r-- | src/core/wee-config.c | 102 | ||||
-rw-r--r-- | src/core/wee-config.h | 1 | ||||
-rw-r--r-- | src/gui/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/gui/Makefile.am | 2 | ||||
-rw-r--r-- | src/gui/gui-bar-item-custom.c | 527 | ||||
-rw-r--r-- | src/gui/gui-bar-item-custom.h | 70 | ||||
-rw-r--r-- | src/gui/gui-bar-item.h | 2 | ||||
-rw-r--r-- | src/gui/gui-bar.c | 35 | ||||
-rw-r--r-- | tests/CMakeLists.txt | 2 | ||||
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/tests.cpp | 2 | ||||
-rw-r--r-- | tests/unit/gui/test-gui-bar-item-custom.cpp | 457 | ||||
-rw-r--r-- | tests/unit/gui/test-gui-bar-item.cpp | 547 |
18 files changed, 2050 insertions, 16 deletions
diff --git a/ChangeLog.adoc b/ChangeLog.adoc index da2868f9e..386bec84f 100644 --- a/ChangeLog.adoc +++ b/ChangeLog.adoc @@ -20,6 +20,7 @@ https://weechat.org/files/releasenotes/ReleaseNotes-devel.html[release notes] New features:: + * core: add command /item to create custom bar items (issue #808) * core: add bar item "spacer" (issue #1700) * core: add case conversion in evaluation of expressions with `lower:string` and `upper:string` (issue #1778) * core: move detailed list of hooks from command `/plugin listfull` to `/debug hooks <plugin>` diff --git a/po/POTFILES.in b/po/POTFILES.in index bad208762..796bee886 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -116,6 +116,8 @@ ./src/gui/gui-bar.h ./src/gui/gui-bar-item.c ./src/gui/gui-bar-item.h +./src/gui/gui-bar-item-custom.c +./src/gui/gui-bar-item-custom.h ./src/gui/gui-bar-window.c ./src/gui/gui-bar-window.h ./src/gui/gui-buffer.c diff --git a/po/srcfiles.cmake b/po/srcfiles.cmake index 38974cb5a..b0d520ca9 100644 --- a/po/srcfiles.cmake +++ b/po/srcfiles.cmake @@ -117,6 +117,8 @@ SET(WEECHAT_SOURCES ./src/gui/gui-bar.h ./src/gui/gui-bar-item.c ./src/gui/gui-bar-item.h +./src/gui/gui-bar-item-custom.c +./src/gui/gui-bar-item-custom.h ./src/gui/gui-bar-window.c ./src/gui/gui-bar-window.h ./src/gui/gui-buffer.c diff --git a/src/core/wee-command.c b/src/core/wee-command.c index f5cab35cc..bc72efa76 100644 --- a/src/core/wee-command.c +++ b/src/core/wee-command.c @@ -66,6 +66,7 @@ #include "wee-version.h" #include "../gui/gui-bar.h" #include "../gui/gui-bar-item.h" +#include "../gui/gui-bar-item-custom.h" #include "../gui/gui-buffer.h" #include "../gui/gui-chat.h" #include "../gui/gui-color.h" @@ -3388,6 +3389,195 @@ COMMAND_CALLBACK(input) } /* + * Callback for command "/item": manages custom bar items + */ + +COMMAND_CALLBACK(item) +{ + struct t_gui_bar_item_custom *ptr_bar_item_custom; + char str_command[4096], str_pos[16]; + int i, update; + + /* make C compiler happy */ + (void) pointer; + (void) data; + + if ((argc == 1) + || ((argc == 2) && (string_strcasecmp (argv[1], "list") == 0))) + { + /* display all custom bar items */ + if (gui_custom_bar_items) + { + gui_chat_printf (NULL, ""); + gui_chat_printf (NULL, + _("Custom bar items:")); + for (ptr_bar_item_custom = gui_custom_bar_items; ptr_bar_item_custom; + ptr_bar_item_custom = ptr_bar_item_custom->next_item) + { + gui_chat_printf ( + NULL, " %s -> \"%s\"", + ptr_bar_item_custom->bar_item->name, + CONFIG_STRING(ptr_bar_item_custom->options[GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT])); + } + } + else + { + gui_chat_printf (NULL, _("No custom bar item defined")); + } + + return WEECHAT_RC_OK; + } + + /* add (or add/replace) a custom bar item */ + if ((string_strcasecmp (argv[1], "add") == 0) + || (string_strcasecmp (argv[1], "addreplace") == 0)) + { + COMMAND_MIN_ARGS(4, argv[1]); + + update = 0; + if (string_strcasecmp (argv[1], "addreplace") == 0) + { + ptr_bar_item_custom = gui_bar_item_custom_search (argv[2]); + if (ptr_bar_item_custom) + { + gui_bar_item_custom_free (ptr_bar_item_custom); + update = 1; + } + } + + ptr_bar_item_custom = gui_bar_item_custom_new (argv[2], argv_eol[3]); + if (ptr_bar_item_custom) + { + gui_chat_printf (NULL, + (update) ? + _("Custom bar item \"%s\" updated") : + _("Custom bar item \"%s\" added"), + argv[2]); + } + else + { + gui_chat_printf (NULL, + _("%sUnable to add custom bar item \"%s\""), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + argv[2]); + } + + return WEECHAT_RC_OK; + } + + /* refresh bar items */ + if (string_strcasecmp (argv[1], "refresh") == 0) + { + for (i = 2; i < argc; i++) + { + gui_bar_item_update (argv[i]); + } + return WEECHAT_RC_OK; + } + + /* recreate a custom bar item */ + if (string_strcasecmp (argv[1], "recreate") == 0) + { + COMMAND_MIN_ARGS(3, "recreate"); + ptr_bar_item_custom = gui_bar_item_custom_search (argv[2]); + if (ptr_bar_item_custom) + { + snprintf (str_command, sizeof (str_command), + "/item addreplace %s %s", + ptr_bar_item_custom->bar_item->name, + CONFIG_STRING(ptr_bar_item_custom->options[GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT])); + gui_buffer_set (buffer, "input", str_command); + snprintf (str_pos, sizeof (str_pos), + "%d", utf8_strlen (str_command)); + gui_buffer_set (buffer, "input_pos", str_pos); + } + else + { + gui_chat_printf (NULL, + _("%sCustom bar item \"%s\" not found"), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + argv[2]); + } + return WEECHAT_RC_OK; + } + + /* rename a custom bar item */ + if (string_strcasecmp (argv[1], "rename") == 0) + { + COMMAND_MIN_ARGS(4, "rename"); + ptr_bar_item_custom = gui_bar_item_custom_search (argv[2]); + if (ptr_bar_item_custom) + { + if (gui_bar_item_custom_rename (ptr_bar_item_custom, argv[3])) + { + gui_chat_printf (NULL, + _("Custom bar item \"%s\" renamed to \"%s\""), + argv[2], argv[3]); + } + else + { + gui_chat_printf (NULL, + _("%sUnable to rename custom bar item " + "\"%s\" to \"%s\""), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + argv[2], argv[3]); + } + } + else + { + gui_chat_printf (NULL, + _("%sCustom bar item \"%s\" not found"), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + argv[2]); + } + return WEECHAT_RC_OK; + } + + /* delete a custom bar item */ + if (string_strcasecmp (argv[1], "del") == 0) + { + COMMAND_MIN_ARGS(3, "del"); + if (string_strcasecmp (argv[2], "-all") == 0) + { + if (gui_custom_bar_items) + { + gui_bar_item_custom_free_all (); + gui_chat_printf (NULL, + _("All custom bar items have been deleted")); + } + else + { + gui_chat_printf (NULL, _("No custom bar item defined")); + } + } + else + { + for (i = 2; i < argc; i++) + { + ptr_bar_item_custom = gui_bar_item_custom_search (argv[i]); + if (ptr_bar_item_custom) + { + gui_bar_item_custom_free (ptr_bar_item_custom); + gui_chat_printf (NULL, + _("Custom bar item \"%s\" deleted"), + argv[i]); + } + else + { + gui_chat_printf (NULL, + _("%sCustom bar item \"%s\" not found"), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + argv[i]); + } + } + } + return WEECHAT_RC_OK; + } + + COMMAND_ERROR; +} + +/* * Displays a key binding. */ @@ -7828,6 +8018,41 @@ command_init () "zoom_merged_buffer || insert || send || paste_start || paste_stop", &command_input, NULL, NULL); hook_command ( + NULL, "item", + N_("manage custom bar items"), + N_("list" + " || add|addreplace <name> <content>" + " || rename <name> <new_name>" + " || refresh <name> [<name>...]" + " || recreate <name>" + " || del <name>|-all"), + N_(" list: list all custom bar items\n" + " add: add a custom bar item\n" + "addreplace: add or replace an existing custom bar item\n" + " name: custom bar item name\n" + " content: content (evaluated, see /help eval)\n" + " rename: rename a custom bar item\n" + " refresh: update content of item in all bars where the item is " + "displayed; any item can be refreshed: default/plugin/custom " + "bar items\n" + " recreate: set input with the command used to edit the custom " + "bar item\n" + " del: delete a custom bar item\n" + " -all: delete all custom bar items\n" + "\n" + "Examples:\n" + " /item add terminfo term:${info:term_width}x${info:term_height}\n" + " /item add bufinfo ${buffer.number}:${buffer.name}" + "${if:${buffer.zoomed}?(Z)}"), + "list" + " || add %(custom_bar_items_names)" + " || addreplace %(custom_bar_items_names) %(custom_bar_item_content)" + " || rename %(custom_bar_items_names) %(custom_bar_items_names)" + " || refresh %(custom_bar_items_names)|%*" + " || recreate %(custom_bar_items_names)" + " || del %(custom_bar_items_names)|-all", + &command_item, NULL, NULL); + hook_command ( NULL, "key", N_("bind/unbind keys"), N_("list|listdefault|listdiff [<context>]" diff --git a/src/core/wee-completion.c b/src/core/wee-completion.c index bbf1c9398..4222e5af4 100644 --- a/src/core/wee-completion.c +++ b/src/core/wee-completion.c @@ -46,6 +46,8 @@ #include "wee-string.h" #include "../gui/gui-completion.h" #include "../gui/gui-bar.h" +#include "../gui/gui-bar-item.h" +#include "../gui/gui-bar-item-custom.h" #include "../gui/gui-bar-window.h" #include "../gui/gui-buffer.h" #include "../gui/gui-color.h" @@ -88,6 +90,84 @@ completion_list_add_bars_names_cb (const void *pointer, void *data, } /* + * Adds custom bar items names to completion list. + */ + +int +completion_list_add_custom_bar_items_names_cb (const void *pointer, void *data, + const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion) +{ + struct t_gui_bar_item_custom *ptr_item; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) completion_item; + (void) buffer; + + for (ptr_item = gui_custom_bar_items; ptr_item; + ptr_item = ptr_item->next_item) + { + gui_completion_list_add (completion, ptr_item->bar_item->name, + 0, WEECHAT_LIST_POS_SORT); + } + + return WEECHAT_RC_OK; +} + +/* + * Adds value of custom bar item content to completion list. + * + * The item name is read in previous argument. + */ + +int +completion_list_add_custom_bar_item_content_cb (const void *pointer, void *data, + const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion) +{ + char **argv; + int argc; + struct t_gui_bar_item_custom *ptr_item; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) completion_item; + (void) buffer; + + if (!completion->args) + return WEECHAT_RC_OK; + + argv = string_split (completion->args, " ", NULL, + WEECHAT_STRING_SPLIT_STRIP_LEFT + | WEECHAT_STRING_SPLIT_STRIP_RIGHT + | WEECHAT_STRING_SPLIT_COLLAPSE_SEPS, + 0, &argc); + if (!argv) + return WEECHAT_RC_OK; + + if (argc > 1) + { + ptr_item = gui_bar_item_custom_search (argv[1]); + if (ptr_item) + { + gui_completion_list_add ( + completion, + CONFIG_STRING(ptr_item->options[GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT]), + 0, + WEECHAT_LIST_POS_SORT); + } + } + string_free_split (argv); + + return WEECHAT_RC_OK; +} + +/* * Adds bar options to completion list. */ @@ -1865,6 +1945,12 @@ completion_init () hook_completion (NULL, "bars_names", /* formerly "%r" */ N_("names of bars"), &completion_list_add_bars_names_cb, NULL, NULL); + hook_completion (NULL, "custom_bar_items_names", + N_("names of custom bar items"), + &completion_list_add_custom_bar_items_names_cb, NULL, NULL); + hook_completion (NULL, "custom_bar_item_content", + N_("content of custom bar item"), + &completion_list_add_custom_bar_item_content_cb, NULL, NULL); hook_completion (NULL, "config_option_values", /* formerly "%v" */ N_("values for a configuration option"), &completion_list_add_config_option_values_cb, NULL, NULL); diff --git a/src/core/wee-config.c b/src/core/wee-config.c index 8edfdb216..dc8d74975 100644 --- a/src/core/wee-config.c +++ b/src/core/wee-config.c @@ -50,6 +50,7 @@ #include "wee-version.h" #include "../gui/gui-bar.h" #include "../gui/gui-bar-item.h" +#include "../gui/gui-bar-item-custom.h" #include "../gui/gui-buffer.h" #include "../gui/gui-chat.h" #include "../gui/gui-color.h" @@ -70,6 +71,7 @@ struct t_config_section *weechat_config_section_debug = NULL; struct t_config_section *weechat_config_section_color = NULL; 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; /* config, startup section */ @@ -1435,6 +1437,8 @@ config_weechat_init_after_read () gui_bar_create_default (); } + 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++) { @@ -1931,6 +1935,86 @@ config_weechat_bar_read_cb (const void *pointer, void *data, } /* + * Reads a custom bar item option in WeeChat configuration file. + */ + +int +config_weechat_bar_item_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) +{ + char *pos_option, *item_name; + struct t_gui_bar_item_custom *ptr_temp_item; + int index_option; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) config_file; + (void) section; + + if (!option_name) + return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; + + pos_option = strchr (option_name, '.'); + if (!pos_option) + return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; + + item_name = string_strndup (option_name, pos_option - option_name); + if (!item_name) + return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; + + pos_option++; + + /* search temporary custom bar item */ + for (ptr_temp_item = gui_temp_custom_bar_items; ptr_temp_item; + ptr_temp_item = ptr_temp_item->next_item) + { + if (strcmp (ptr_temp_item->name, item_name) == 0) + break; + } + if (!ptr_temp_item) + { + /* create new temporary custom bar item */ + ptr_temp_item = gui_bar_item_custom_alloc (item_name); + if (ptr_temp_item) + { + /* add new custom bar item at the end */ + ptr_temp_item->prev_item = last_gui_temp_custom_bar_item; + ptr_temp_item->next_item = NULL; + if (last_gui_temp_custom_bar_item) + last_gui_temp_custom_bar_item->next_item = ptr_temp_item; + else + gui_temp_custom_bar_items = ptr_temp_item; + last_gui_temp_custom_bar_item = ptr_temp_item; + } + } + + if (ptr_temp_item) + { + index_option = gui_bar_item_custom_search_option (pos_option); + if (index_option >= 0) + { + gui_bar_item_custom_create_option_temp (ptr_temp_item, index_option, + value); + } + else + { + gui_chat_printf (NULL, + _("%sWarning: unknown option for section \"%s\": " + "%s (value: \"%s\")"), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + section->name, option_name, value); + } + } + + free (item_name); + + return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; +} + +/* * Reads a layout option in WeeChat configuration file. */ @@ -4658,6 +4742,24 @@ config_weechat_init_options () weechat_config_section_bar = ptr_section; + /* custom bar items */ + ptr_section = config_file_new_section ( + weechat_config_file, "custom_bar_item", + 0, 0, + &config_weechat_bar_item_read_cb, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + if (!ptr_section) + { + config_file_free (weechat_config_file); + weechat_config_file = NULL; + return 0; + } + + weechat_config_section_custom_bar_item = ptr_section; + /* layout */ ptr_section = config_file_new_section ( weechat_config_file, "layout", diff --git a/src/core/wee-config.h b/src/core/wee-config.h index 5cae8d136..0feec6c42 100644 --- a/src/core/wee-config.h +++ b/src/core/wee-config.h @@ -127,6 +127,7 @@ extern struct t_config_file *weechat_config_file; extern struct t_config_section *weechat_config_section_color; 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_option *config_startup_command_after_plugins; diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index bf6688ffb..a135886c9 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -20,6 +20,7 @@ set(LIB_GUI_COMMON_SRC gui-bar.c gui-bar.h gui-bar-item.c gui-bar-item.h + gui-bar-item-custom.c gui-bar-item-custom.h gui-bar-window.c gui-bar-window.h gui-buffer.c gui-buffer.h gui-chat.c gui-chat.h diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index e5d7e9274..f3028d497 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -25,6 +25,8 @@ lib_weechat_gui_common_a_SOURCES = gui-bar.c \ gui-bar.h \ gui-bar-item.c \ gui-bar-item.h \ + gui-bar-item-custom.c \ + gui-bar-item-custom.h \ gui-bar-window.c \ gui-bar-window.h \ gui-buffer.c \ diff --git a/src/gui/gui-bar-item-custom.c b/src/gui/gui-bar-item-custom.c new file mode 100644 index 000000000..c901515a3 --- /dev/null +++ b/src/gui/gui-bar-item-custom.c @@ -0,0 +1,527 @@ +/* + * gui-bar-item-custom.c - custom bar item functions (used by all GUI) + * + * Copyright (C) 2022 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <stddef.h> +#include <string.h> + +#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-string.h" +#include "../plugins/plugin.h" +#include "gui-bar-item-custom.h" +#include "gui-bar-item.h" + + +char *gui_bar_item_custom_option_string[GUI_BAR_ITEM_CUSTOM_NUM_OPTIONS] = +{ "content" }; + +struct t_gui_bar_item_custom *gui_custom_bar_items = NULL; +struct t_gui_bar_item_custom *last_gui_custom_bar_item = NULL; + +/* custom bar items used when reading config */ +struct t_gui_bar_item_custom *gui_temp_custom_bar_items = NULL; +struct t_gui_bar_item_custom *last_gui_temp_custom_bar_item = NULL; + + + +/* + * Checks if a custom bar item name is valid: it must not have any + * space/period. + * + * Returns: + * 1: name is valid + * 0: name is invalid + */ + +int +gui_bar_item_custom_name_valid (const char *name) +{ + if (!name || !name[0]) + return 0; + + /* no spaces allowed */ + if (strchr (name, ' ')) + return 0; + + /* no periods allowed */ + if (strchr (name, '.')) + return 0; + + /* name is valid */ + return 1; +} + +/* + * Searches for a custom bar item option name. + * + * Returns index of option in enum t_gui_bar_item_custom_option, + * -1 if not found. + */ + +int +gui_bar_item_custom_search_option (const char *option_name) +{ + int i; + + if (!option_name) + return -1; + + for (i = 0; i < GUI_BAR_ITEM_CUSTOM_NUM_OPTIONS; i++) + { + if (string_strcasecmp (gui_bar_item_custom_option_string[i], + option_name) == 0) + return i; + } + + /* custom bar item option not found */ + return -1; +} + +/* + * Searches for a custom bar item by name. + */ + +struct t_gui_bar_item_custom * +gui_bar_item_custom_search (const char *item_name) +{ + struct t_gui_bar_item_custom *ptr_item; + + if (!item_name || !item_name[0]) + return NULL; + + for (ptr_item = gui_custom_bar_items; ptr_item; + ptr_item = ptr_item->next_item) + { + if (strcmp (ptr_item->name, item_name) == 0) + return ptr_item; + } + + /* custom bar item not found */ + return NULL; +} + +/* + * Searches for a custom bar item with name of option (like "name.content"). + * + * Returns pointer to custom bar item found, NULL if not found. + */ + +struct t_gui_bar_item_custom * +gui_bar_item_custom_search_with_option_name (const char *option_name) +{ + char *item_name, *pos_option; + struct t_gui_bar_item_custom *ptr_item; + + if (!option_name) + return NULL; + + ptr_item = NULL; + + pos_option = strchr (option_name, '.'); + if (pos_option) + { + item_name = string_strndup (option_name, pos_option - option_name); + if (item_name) + { + for (ptr_item = gui_custom_bar_items; ptr_item; + ptr_item = ptr_item->next_item) + { + if (string_strcasecmp (ptr_item->name, item_name) == 0) + break; + } + free (item_name); + } + } + + return ptr_item; +} + +/* + * Callback called when option "content" is changed. + */ + +void +gui_bar_item_custom_config_change_content (const void *pointer, void *data, + struct t_config_option *option) +{ + struct t_gui_bar_item_custom *ptr_item; + + /* make C compiler happy */ + (void) pointer; + (void) data; + + ptr_item = gui_bar_item_custom_search_with_option_name (option->name); + if (ptr_item) + gui_bar_item_update (ptr_item->name); +} + +/* + * Creates an option for a custom bar item. + * + * Returns pointer to new option, NULL if error. + */ + +struct t_config_option * +gui_bar_item_custom_create_option (const char *item_name, int index_option, + const char *value) +{ + struct t_config_option *ptr_option; + int length; + char *option_name; + + ptr_option = NULL; + + length = strlen (item_name) + 1 + + strlen (gui_bar_item_custom_option_string[index_option]) + 1; + option_name = malloc (length); + if (!option_name) + return NULL; + + snprintf (option_name, length, "%s.%s", + item_name, gui_bar_item_custom_option_string[index_option]); + + switch (index_option) + { + case GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT: + ptr_option = config_file_new_option ( + weechat_config_file, weechat_config_section_custom_bar_item, + option_name, "string", + N_("content of bar item (evaluated, see /help eval)"), + NULL, 0, 0, value, NULL, 0, + NULL, NULL, NULL, + &gui_bar_item_custom_config_change_content, NULL, NULL, + NULL, NULL, NULL); + break; + case GUI_BAR_ITEM_CUSTOM_NUM_OPTIONS: + break; + } + + free (option_name); + + return ptr_option; +} + +/* + * Creates option for a temporary custom bar item (when reading configuration + * file). + */ + +void +gui_bar_item_custom_create_option_temp (struct t_gui_bar_item_custom *temp_item, + int index_option, + const char *value) +{ + struct t_config_option *new_option; + + new_option = gui_bar_item_custom_create_option (temp_item->name, + index_option, + value); + if (new_option + && (index_option >= 0) + && (index_option < GUI_BAR_ITEM_CUSTOM_NUM_OPTIONS)) + { + temp_item->options[index_option] = new_option; + } +} + +/* + * Custom bar item callback. + */ + +char * +gui_bar_item_custom_callback (const void *pointer, + void *data, + struct t_gui_bar_item *item, + struct t_gui_window *window, + struct t_gui_buffer *buffer, + struct t_hashtable *extra_info) +{ + struct t_gui_bar_item_custom *ptr_item; + struct t_hashtable *pointers; + char *result; + + /* make C compiler happy */ + (void) data; + (void) item; + (void) extra_info; + + ptr_item = (struct t_gui_bar_item_custom *)pointer; + if (!ptr_item) + return NULL; + + pointers = hashtable_new (32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, + NULL, + NULL); + if (pointers) + { + hashtable_set (pointers, "window", window); + hashtable_set (pointers, "buffer", buffer); + } + + result = eval_expression ( + CONFIG_STRING(ptr_item->options[GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT]), + pointers, NULL, NULL); + + if (pointers) + hashtable_free (pointers); + + return result; +} + +/* + * Allocates and initializes new custom bar item structure. + * + * Returns pointer to new custom bar item, NULL if error. + */ + +struct t_gui_bar_item_custom * +gui_bar_item_custom_alloc (const char *name) +{ + struct t_gui_bar_item_custom *new_bar_item_custom; + int i; + + new_bar_item_custom = malloc (sizeof (*new_bar_item_custom)); + if (!new_bar_item_custom) + return NULL; + + new_bar_item_custom->name = strdup (name); + for (i = 0; i < GUI_BAR_ITEM_CUSTOM_NUM_OPTIONS; i++) + { + new_bar_item_custom->options[i] = NULL; + } + new_bar_item_custom->bar_item = NULL; + new_bar_item_custom->prev_item = NULL; + new_bar_item_custom->next_item = NULL; + + return new_bar_item_custom; +} + +/* + * Creates bar item in a custom bar item. + */ + +void +gui_bar_item_custom_create_bar_item (struct t_gui_bar_item_custom *item) +{ + if (item->bar_item) + gui_bar_item_free (item->bar_item); + item->bar_item = gui_bar_item_new ( + NULL, + item->name, + &gui_bar_item_custom_callback, + item, + NULL); +} + +/* + * Creates a new custom bar item with options. + * + * Returns pointer to new bar, NULL if error. + */ + +struct t_gui_bar_item_custom * +gui_bar_item_custom_new_with_options (const char *name, + struct t_config_option *content) +{ + struct t_gui_bar_item_custom *new_bar_item_custom; + + /* create custom bar item */ + new_bar_item_custom = gui_bar_item_custom_alloc (name); + if (!new_bar_item_custom) + return NULL; + + new_bar_item_custom->options[GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT] = content; + new_bar_item_custom->bar_item = NULL; + + /* add custom bar item to custom bar items queue */ + new_bar_item_custom->prev_item = last_gui_custom_bar_item; + if (last_gui_custom_bar_item) + last_gui_custom_bar_item->next_item = new_bar_item_custom; + else + gui_custom_bar_items = new_bar_item_custom; + last_gui_custom_bar_item = new_bar_item_custom; + new_bar_item_custom->next_item = NULL; + + return new_bar_item_custom; +} + +/* + * Creates a new custom bar item. + * + * Returns pointer to new custom bar item, NULL if not found. + */ + +struct t_gui_bar_item_custom * +gui_bar_item_custom_new (const char *name, const char *content) +{ + struct t_config_option *option_content; + struct t_gui_bar_item_custom *new_bar_item_custom; + + if (!gui_bar_item_custom_name_valid (name)) + return NULL; + + if (gui_bar_item_custom_search (name)) + return NULL; + + option_content = gui_bar_item_custom_create_option ( + name, + GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT, + content); + + new_bar_item_custom = gui_bar_item_custom_new_with_options (name, + option_content); + if (new_bar_item_custom) + { + gui_bar_item_custom_create_bar_item (new_bar_item_custom); + gui_bar_item_update (name); + } + else + { + if (option_content) + config_file_option_free (option_content, 0); + } + + return new_bar_item_custom; +} + +/* + * Uses temporary custom bar items (created by reading configuration file). + */ + +void +gui_bar_item_custom_use_temp_items () +{ + struct t_gui_bar_item_custom *ptr_temp_item; + + for (ptr_temp_item = gui_temp_custom_bar_items; ptr_temp_item; + ptr_temp_item = ptr_temp_item->next_item) + { + gui_bar_item_custom_create_bar_item (ptr_temp_item); + } + + /* remove any existing custom bar item */ + gui_bar_item_custom_free_all (); + + /* replace custom bar items list by the temporary list */ + gui_custom_bar_items = gui_temp_custom_bar_items; + last_gui_custom_bar_item = last_gui_temp_custom_bar_item; + + gui_temp_custom_bar_items = NULL; + last_gui_temp_custom_bar_item = NULL; +} + +/* + * Renames a custom bar item. + * + * Returns: + * 1: OK + * 0: error + */ + +int +gui_bar_item_custom_rename (struct t_gui_bar_item_custom *item, + const char *new_name) +{ + if (!item || !gui_bar_item_custom_name_valid (new_name)) + return 0; + + if (gui_bar_item_custom_search (new_name)) + return 0; + + free (item->bar_item->name); + item->bar_item->name = strdup (new_name); + + gui_bar_item_update (item->name); + gui_bar_item_update (item->bar_item->name); + + free (item->name); + item->name = strdup (new_name); + + return 1; +} + +/* + * Deletes a custom bar item. + */ + +void +gui_bar_item_custom_free (struct t_gui_bar_item_custom *item) +{ + char *name; + int i; + + if (!item) + return; + + name = strdup (item->name); + + /* remove bar item */ + gui_bar_item_free (item->bar_item); + + /* remove custom bar item from custom bar items list */ + if (item->prev_item) + (item->prev_item)->next_item = item->next_item; + if (item->next_item) + (item->next_item)->prev_item = item->prev_item; + if (gui_custom_bar_items == item) + gui_custom_bar_items = item->next_item; + if (last_gui_custom_bar_item == item) + last_gui_custom_bar_item = item->prev_item; + + /* free data */ + if (item->name) + free (item->name); + for (i = 0; i < GUI_BAR_ITEM_CUSTOM_NUM_OPTIONS; i++) + { + if (item->options[i]) + config_file_option_free (item->options[i], 1); + } + + free (item); + + gui_bar_item_update (name); + + if (name) + free (name); +} + +/* + * Deletes all custom bar items. + */ + +void +gui_bar_item_custom_free_all () +{ + while (gui_custom_bar_items) + { + gui_bar_item_custom_free (gui_custom_bar_items); + } +} diff --git a/src/gui/gui-bar-item-custom.h b/src/gui/gui-bar-item-custom.h new file mode 100644 index 000000000..efb8b70f3 --- /dev/null +++ b/src/gui/gui-bar-item-custom.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2022 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef WEECHAT_GUI_BAR_ITEM_CUSTOM_H +#define WEECHAT_GUI_BAR_ITEM_CUSTOM_H + +struct t_gui_buffer; +struct t_gui_window; +struct t_hashtable; +struct t_weechat_plugin; + +enum t_gui_bar_item_custom_option +{ + GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT = 0, /* item content */ + /* number of bar options */ + GUI_BAR_ITEM_CUSTOM_NUM_OPTIONS, +}; + +struct t_gui_bar_item_custom +{ + /* custom choices */ + char *name; /* item name */ + struct t_config_option *options[GUI_BAR_ITEM_CUSTOM_NUM_OPTIONS]; + + /* internal vars */ + struct t_gui_bar_item *bar_item; /* pointer to bar item */ + struct t_gui_bar_item_custom *prev_item; /* link to previous bar item */ + struct t_gui_bar_item_custom *next_item; /* link to next bar item */ +}; + +/* variables */ + +extern struct t_gui_bar_item_custom *gui_custom_bar_items; +extern struct t_gui_bar_item_custom *last_gui_custom_bar_item; +extern struct t_gui_bar_item_custom *gui_temp_custom_bar_items; +extern struct t_gui_bar_item_custom *last_gui_temp_custom_bar_item; + +/* functions */ + +extern int gui_bar_item_custom_search_option (const char *option_name); +extern struct t_gui_bar_item_custom *gui_bar_item_custom_search (const char *item_name); +extern void gui_bar_item_custom_create_option_temp (struct t_gui_bar_item_custom *temp_item, + int index_option, + const char *value); +extern struct t_gui_bar_item_custom *gui_bar_item_custom_alloc (const char *name); +extern struct t_gui_bar_item_custom *gui_bar_item_custom_new (const char *name, + const char *content); +extern void gui_bar_item_custom_use_temp_items (); +extern int gui_bar_item_custom_rename (struct t_gui_bar_item_custom *item, + const char *new_name); +extern void gui_bar_item_custom_free (struct t_gui_bar_item_custom *item); +extern void gui_bar_item_custom_free_all (); + +#endif /* WEECHAT_GUI_BAR_ITEM_CUSTOM_H */ diff --git a/src/gui/gui-bar-item.h b/src/gui/gui-bar-item.h index fc8dda3bf..c041f4787 100644 --- a/src/gui/gui-bar-item.h +++ b/src/gui/gui-bar-item.h @@ -52,8 +52,10 @@ enum t_gui_bar_item_weechat GUI_BAR_NUM_ITEMS, }; +struct t_gui_bar; struct t_gui_buffer; struct t_gui_window; +struct t_infolist; struct t_gui_bar_item { diff --git a/src/gui/gui-bar.c b/src/gui/gui-bar.c index d77982207..6c421d003 100644 --- a/src/gui/gui-bar.c +++ b/src/gui/gui-bar.c @@ -470,6 +470,9 @@ gui_bar_search_with_option_name (const char *option_name) char *bar_name, *pos_option; struct t_gui_bar *ptr_bar; + if (!option_name) + return NULL; + ptr_bar = NULL; pos_option = strchr (option_name, '.'); @@ -1562,24 +1565,24 @@ gui_bar_alloc (const char *name) int i; new_bar = malloc (sizeof (*new_bar)); - if (new_bar) + if (!new_bar) + return NULL; + + new_bar->name = strdup (name); + for (i = 0; i < GUI_BAR_NUM_OPTIONS; i++) { - new_bar->name = strdup (name); - for (i = 0; i < GUI_BAR_NUM_OPTIONS; i++) - { - new_bar->options[i] = NULL; - } - new_bar->items_count = 0; - new_bar->items_array = NULL; - new_bar->items_buffer = NULL; - new_bar->items_prefix = NULL; - new_bar->items_name = NULL; - new_bar->items_suffix = NULL; - new_bar->bar_window = NULL; - new_bar->bar_refresh_needed = 0; - new_bar->prev_bar = NULL; - new_bar->next_bar = NULL; + new_bar->options[i] = NULL; } + new_bar->items_count = 0; + new_bar->items_array = NULL; + new_bar->items_buffer = NULL; + new_bar->items_prefix = NULL; + new_bar->items_name = NULL; + new_bar->items_suffix = NULL; + new_bar->bar_window = NULL; + new_bar->bar_refresh_needed = 0; + new_bar->prev_bar = NULL; + new_bar->next_bar = NULL; return new_bar; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a0a0c862c..172e5a39a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -42,6 +42,8 @@ set(LIB_WEECHAT_UNIT_TESTS_CORE_SRC unit/core/test-core-url.cpp unit/core/test-core-utf8.cpp unit/core/test-core-util.cpp + unit/gui/test-gui-bar-item.cpp + unit/gui/test-gui-bar-item-custom.cpp unit/gui/test-gui-bar-window.cpp unit/gui/test-gui-buffer.cpp unit/gui/test-gui-chat.cpp diff --git a/tests/Makefile.am b/tests/Makefile.am index d4c610f6a..892837f1b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -39,6 +39,8 @@ lib_weechat_unit_tests_core_a_SOURCES = unit/core/test-core-arraylist.cpp \ unit/core/test-core-url.cpp \ unit/core/test-core-utf8.cpp \ unit/core/test-core-util.cpp \ + unit/gui/test-gui-bar-item.cpp \ + unit/gui/test-gui-bar-item-custom.cpp \ unit/gui/test-gui-bar-window.cpp \ unit/gui/test-gui-buffer.cpp \ unit/gui/test-gui-chat.cpp \ diff --git a/tests/tests.cpp b/tests/tests.cpp index 08a8e3318..6254c0299 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -79,6 +79,8 @@ IMPORT_TEST_GROUP(CoreUrl); IMPORT_TEST_GROUP(CoreUtf8); IMPORT_TEST_GROUP(CoreUtil); /* GUI */ +IMPORT_TEST_GROUP(GuiBarItem); +IMPORT_TEST_GROUP(GuiBarItemCustom); IMPORT_TEST_GROUP(GuiBarWindow); IMPORT_TEST_GROUP(GuiBuffer); IMPORT_TEST_GROUP(GuiChat); diff --git a/tests/unit/gui/test-gui-bar-item-custom.cpp b/tests/unit/gui/test-gui-bar-item-custom.cpp new file mode 100644 index 000000000..5e68e950e --- /dev/null +++ b/tests/unit/gui/test-gui-bar-item-custom.cpp @@ -0,0 +1,457 @@ +/* + * test-gui-bar-item-custom.cpp - test custom bar item functions + * + * Copyright (C) 2022 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "CppUTest/TestHarness.h" + +extern "C" +{ +#include <string.h> +#include "src/core/wee-config.h" +#include "src/gui/gui-bar-item.h" +#include "src/gui/gui-bar-item-custom.h" +#include "src/gui/gui-buffer.h" +#include "src/gui/gui-window.h" + +extern int gui_bar_item_custom_name_valid (const char *name); +extern struct t_gui_bar_item_custom *gui_bar_item_custom_search_with_option_name ( + const char *option_name); +extern char *gui_bar_item_custom_callback (const void *pointer, + void *data, + struct t_gui_bar_item *item, + struct t_gui_window *window, + struct t_gui_buffer *buffer, + struct t_hashtable *extra_info); +extern void gui_bar_item_custom_create_bar_item (struct t_gui_bar_item_custom *item); +} + +TEST_GROUP(GuiBarItemCustom) +{ +}; + +/* + * Tests functions: + * gui_bar_item_custom_name_valid + */ + +TEST(GuiBarItemCustom, NameValid) +{ + LONGS_EQUAL(0, gui_bar_item_custom_name_valid (NULL)); + LONGS_EQUAL(0, gui_bar_item_custom_name_valid ("")); + LONGS_EQUAL(0, gui_bar_item_custom_name_valid (" ")); + LONGS_EQUAL(0, gui_bar_item_custom_name_valid (".")); + LONGS_EQUAL(0, gui_bar_item_custom_name_valid ("abc def")); + LONGS_EQUAL(0, gui_bar_item_custom_name_valid (" abcdef")); + LONGS_EQUAL(0, gui_bar_item_custom_name_valid ("abcdef ")); + LONGS_EQUAL(0, gui_bar_item_custom_name_valid ("abc.def")); + LONGS_EQUAL(0, gui_bar_item_custom_name_valid (".abcdef")); + LONGS_EQUAL(0, gui_bar_item_custom_name_valid ("abcdef.")); + + LONGS_EQUAL(1, gui_bar_item_custom_name_valid ("?")); + LONGS_EQUAL(1, gui_bar_item_custom_name_valid ("abc-def")); + LONGS_EQUAL(1, gui_bar_item_custom_name_valid ("abc-def")); + LONGS_EQUAL(1, gui_bar_item_custom_name_valid ("abc/def/")); + LONGS_EQUAL(1, gui_bar_item_custom_name_valid ("abcdef")); +} + +/* + * Tests functions: + * gui_bar_item_custom_search_option + */ + +TEST(GuiBarItemCustom, SearchOption) +{ + LONGS_EQUAL(-1, gui_bar_item_custom_search_option (NULL)); + LONGS_EQUAL(-1, gui_bar_item_custom_search_option ("")); + LONGS_EQUAL(-1, gui_bar_item_custom_search_option ("zzz")); + + LONGS_EQUAL(0, gui_bar_item_custom_search_option ("content")); +} + +/* + * Tests functions: + * gui_bar_item_custom_search + */ + +TEST(GuiBarItemCustom, Search) +{ + struct t_gui_bar_item_custom *new_item, *new_item2, *ptr_item; + + new_item = gui_bar_item_custom_new ("test", "some content"); + CHECK(new_item); + + new_item2 = gui_bar_item_custom_new ("test2", "some content 2"); + CHECK(new_item2); + + POINTERS_EQUAL(NULL, gui_bar_item_custom_search (NULL)); + POINTERS_EQUAL(NULL, gui_bar_item_custom_search ("")); + POINTERS_EQUAL(NULL, gui_bar_item_custom_search ("zzz")); + + ptr_item = gui_bar_item_custom_search ("test"); + POINTERS_EQUAL(new_item, ptr_item); + STRCMP_EQUAL("test", ptr_item->name); + STRCMP_EQUAL("some content", + CONFIG_STRING(ptr_item->options[GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT])); + CHECK(ptr_item->bar_item); + POINTERS_EQUAL(NULL, ptr_item->bar_item->plugin); + STRCMP_EQUAL("test", ptr_item->bar_item->name); + POINTERS_EQUAL(&gui_bar_item_custom_callback, ptr_item->bar_item->build_callback); + POINTERS_EQUAL(ptr_item, ptr_item->bar_item->build_callback_pointer); + POINTERS_EQUAL(NULL, ptr_item->bar_item->build_callback_data); + + ptr_item = gui_bar_item_custom_search ("test2"); + POINTERS_EQUAL(new_item2, ptr_item); + STRCMP_EQUAL("test2", ptr_item->name); + STRCMP_EQUAL("some content 2", + CONFIG_STRING(ptr_item->options[GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT])); + CHECK(ptr_item->bar_item); + POINTERS_EQUAL(NULL, ptr_item->bar_item->plugin); + STRCMP_EQUAL("test2", ptr_item->bar_item->name); + POINTERS_EQUAL(&gui_bar_item_custom_callback, ptr_item->bar_item->build_callback); + POINTERS_EQUAL(ptr_item, ptr_item->bar_item->build_callback_pointer); + POINTERS_EQUAL(NULL, ptr_item->bar_item->build_callback_data); + + gui_bar_item_custom_free (new_item); + gui_bar_item_custom_free (new_item2); +} + +/* + * Tests functions: + * gui_bar_item_custom_search_with_option_name + */ + +TEST(GuiBarItemCustom, SearchWithOptionName) +{ + struct t_gui_bar_item_custom *new_item, *new_item2; + + new_item = gui_bar_item_custom_new ("test", "some content"); + CHECK(new_item); + + new_item2 = gui_bar_item_custom_new ("test2", "some content 2"); + CHECK(new_item2); + + POINTERS_EQUAL(NULL, gui_bar_item_custom_search_with_option_name (NULL)); + POINTERS_EQUAL(NULL, gui_bar_item_custom_search_with_option_name ("")); + POINTERS_EQUAL(NULL, gui_bar_item_custom_search_with_option_name ("test")); + POINTERS_EQUAL(NULL, gui_bar_item_custom_search_with_option_name ("test2")); + POINTERS_EQUAL(NULL, gui_bar_item_custom_search_with_option_name ("content")); + + POINTERS_EQUAL(new_item, gui_bar_item_custom_search_with_option_name ("test.content")); + POINTERS_EQUAL(new_item2, gui_bar_item_custom_search_with_option_name ("test2.content")); + + gui_bar_item_custom_free (new_item); + gui_bar_item_custom_free (new_item2); +} + +/* + * Tests functions: + * gui_bar_item_custom_config_change_content + */ + +TEST(GuiBarItemCustom, ConfigChangeContent) +{ + struct t_gui_bar_item_custom *new_item; + + new_item = gui_bar_item_custom_new ("test", "some content"); + CHECK(new_item); + STRCMP_EQUAL("some content", + CONFIG_STRING(new_item->options[GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT])); + + config_file_option_set (new_item->options[GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT], + "new content", 1); + + STRCMP_EQUAL("new content", + CONFIG_STRING(new_item->options[GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT])); + + gui_bar_item_custom_free (new_item); +} + +/* + * Tests functions: + * gui_bar_item_custom_create_option_temp + */ + +TEST(GuiBarItemCustom, CreateOptionTemp) +{ + struct t_gui_bar_item_custom *new_item; + + POINTERS_EQUAL(NULL, gui_custom_bar_items); + POINTERS_EQUAL(NULL, last_gui_custom_bar_item); + + new_item = gui_bar_item_custom_alloc ("test"); + CHECK(new_item); + + POINTERS_EQUAL(NULL, new_item->options[GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT]); + + gui_bar_item_custom_create_option_temp (new_item, + GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT, + "some content"); + + STRCMP_EQUAL("some content", + CONFIG_STRING(new_item->options[GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT])); + + gui_bar_item_custom_free (new_item); +} + +/* + * Tests functions: + * gui_bar_item_custom_callback + */ + +TEST(GuiBarItemCustom, Callback) +{ + struct t_gui_bar_item_custom *new_item; + char *content; + + new_item = gui_bar_item_custom_new ( + "test", + "${buffer.number} >> ${buffer.full_name}"); + CHECK(new_item); + + /* custom bar item is NULL => no content */ + POINTERS_EQUAL( + NULL, + gui_bar_item_custom_callback (NULL, NULL, new_item->bar_item, + gui_windows, gui_buffers, NULL)); + + content = gui_bar_item_custom_callback (new_item, NULL, new_item->bar_item, + gui_windows, gui_buffers, NULL); + STRCMP_EQUAL("1 >> core.weechat", content); + free (content); + + gui_bar_item_custom_free (new_item); +} + +/* + * Tests functions: + * gui_bar_item_custom_alloc + * gui_bar_item_custom_create_bar_item + */ + +TEST(GuiBarItemCustom, Alloc) +{ + struct t_gui_bar_item_custom *new_item; + int i; + + new_item = gui_bar_item_custom_alloc ("test"); + CHECK(new_item); + STRCMP_EQUAL("test", new_item->name); + for (i = 0; i < GUI_BAR_ITEM_CUSTOM_NUM_OPTIONS; i++) + { + POINTERS_EQUAL(NULL, new_item->options[i]); + } + POINTERS_EQUAL(NULL, new_item->bar_item); + POINTERS_EQUAL(NULL, new_item->prev_item); + POINTERS_EQUAL(NULL, new_item->next_item); + + gui_bar_item_custom_create_bar_item (new_item); + + /* do it again to free the bar item then reallocate it */ + gui_bar_item_custom_create_bar_item (new_item); + + CHECK(new_item->bar_item); + POINTERS_EQUAL(NULL, new_item->bar_item->plugin); + STRCMP_EQUAL("test", new_item->bar_item->name); + POINTERS_EQUAL(&gui_bar_item_custom_callback, + new_item->bar_item->build_callback); + POINTERS_EQUAL(new_item, new_item->bar_item->build_callback_pointer); + POINTERS_EQUAL(NULL, new_item->bar_item->build_callback_data); + + gui_bar_item_custom_free (new_item); +} + +/* + * Tests functions: + * gui_bar_item_custom_new + * gui_bar_item_custom_new_with_options + * gui_bar_item_custom_create_option + */ + +TEST(GuiBarItemCustom, New) +{ + struct t_gui_bar_item_custom *new_item, *new_item2; + + /* invalid name: contains a space */ + POINTERS_EQUAL(NULL, + gui_bar_item_custom_new ("test item", "some content")); + + new_item = gui_bar_item_custom_new ("test", "some content"); + CHECK(new_item); + + STRCMP_EQUAL("test", new_item->name); + STRCMP_EQUAL( + "some content", + CONFIG_STRING(new_item->options[GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT])); + CHECK(new_item->bar_item); + POINTERS_EQUAL(NULL, new_item->bar_item->plugin); + STRCMP_EQUAL("test", new_item->bar_item->name); + POINTERS_EQUAL(&gui_bar_item_custom_callback, + new_item->bar_item->build_callback); + POINTERS_EQUAL(new_item, new_item->bar_item->build_callback_pointer); + POINTERS_EQUAL(NULL, new_item->bar_item->build_callback_data); + POINTERS_EQUAL(NULL, new_item->prev_item); + POINTERS_EQUAL(NULL, new_item->next_item); + + /* invalid name: already exists */ + POINTERS_EQUAL(NULL, gui_bar_item_custom_new ("test", "some content")); + + /* add another item */ + new_item2 = gui_bar_item_custom_new ("test2", "some content 2"); + CHECK(new_item2); + + POINTERS_EQUAL(NULL, new_item->prev_item); + POINTERS_EQUAL(new_item2, new_item->next_item); + + STRCMP_EQUAL("test2", new_item2->name); + STRCMP_EQUAL( + "some content 2", + CONFIG_STRING(new_item2->options[GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT])); + CHECK(new_item2->bar_item); + POINTERS_EQUAL(NULL, new_item2->bar_item->plugin); + STRCMP_EQUAL("test2", new_item2->bar_item->name); + POINTERS_EQUAL(&gui_bar_item_custom_callback, + new_item2->bar_item->build_callback); + POINTERS_EQUAL(new_item2, new_item2->bar_item->build_callback_pointer); + POINTERS_EQUAL(NULL, new_item2->bar_item->build_callback_data); + POINTERS_EQUAL(new_item, new_item2->prev_item); + POINTERS_EQUAL(NULL, new_item2->next_item); + + gui_bar_item_custom_free (new_item); + gui_bar_item_custom_free (new_item2); +} + +/* + * Tests functions: + * gui_bar_item_custom_use_temp_items + */ + +TEST(GuiBarItemCustom, UseTempItems) +{ + struct t_gui_bar_item_custom *new_item, *new_item2; + + new_item = gui_bar_item_custom_alloc ("test"); + gui_temp_custom_bar_items = new_item; + last_gui_temp_custom_bar_item = new_item; + + new_item2 = gui_bar_item_custom_alloc ("test2"); + new_item->next_item = new_item2; + new_item2->prev_item = new_item; + last_gui_temp_custom_bar_item = new_item2; + + gui_bar_item_custom_use_temp_items (); + + POINTERS_EQUAL(NULL, gui_temp_custom_bar_items); + POINTERS_EQUAL(NULL, last_gui_temp_custom_bar_item); + + POINTERS_EQUAL(new_item, gui_custom_bar_items); + POINTERS_EQUAL(new_item2, last_gui_custom_bar_item); + + gui_bar_item_custom_free (new_item); + gui_bar_item_custom_free (new_item2); + + POINTERS_EQUAL(NULL, gui_custom_bar_items); + POINTERS_EQUAL(NULL, last_gui_custom_bar_item); +} + +/* + * Tests functions: + * gui_bar_item_custom_rename + */ + +TEST(GuiBarItemCustom, Rename) +{ + struct t_gui_bar_item_custom *new_item, *new_item2; + + new_item = gui_bar_item_custom_new ("test", "some content"); + new_item2 = gui_bar_item_custom_new ("test2", "some content 2"); + + CHECK(new_item); + STRCMP_EQUAL("test", new_item->name); + CHECK(new_item->bar_item); + STRCMP_EQUAL("test", new_item->bar_item->name); + + CHECK(new_item2); + STRCMP_EQUAL("test2", new_item2->name); + CHECK(new_item2->bar_item); + STRCMP_EQUAL("test2", new_item2->bar_item->name); + + /* invalid name: contains a space */ + LONGS_EQUAL (0, gui_bar_item_custom_rename (new_item, "second test")); + + /* invalid name: custom bar item already exists */ + LONGS_EQUAL(0, gui_bar_item_custom_rename (new_item, "test2")); + + /* rename OK */ + LONGS_EQUAL(1, gui_bar_item_custom_rename (new_item, "test3")); + + STRCMP_EQUAL("test3", new_item->name); + CHECK(new_item->bar_item); + STRCMP_EQUAL("test3", new_item->bar_item->name); + + gui_bar_item_custom_free (new_item); + gui_bar_item_custom_free (new_item2); +} + +/* + * Tests functions: + * gui_bar_item_custom_free + * gui_bar_item_custom_free_all + */ + +TEST(GuiBarItemCustom, Free) +{ + struct t_gui_bar_item_custom *new_item, *new_item2; + + POINTERS_EQUAL(NULL, gui_custom_bar_items); + POINTERS_EQUAL(NULL, last_gui_custom_bar_item); + + gui_bar_item_custom_free (NULL); + + new_item = gui_bar_item_custom_new ("test", "some content"); + POINTERS_EQUAL(new_item, gui_custom_bar_items); + POINTERS_EQUAL(new_item, last_gui_custom_bar_item); + + new_item2 = gui_bar_item_custom_new ("test2", "some content 2"); + POINTERS_EQUAL(new_item, gui_custom_bar_items); + POINTERS_EQUAL(new_item2, last_gui_custom_bar_item); + + gui_bar_item_custom_free (new_item); + POINTERS_EQUAL(new_item2, gui_custom_bar_items); + POINTERS_EQUAL(new_item2, last_gui_custom_bar_item); + + gui_bar_item_custom_free (new_item2); + POINTERS_EQUAL(NULL, gui_custom_bar_items); + POINTERS_EQUAL(NULL, last_gui_custom_bar_item); + + new_item = gui_bar_item_custom_new ("test", "some content"); + new_item2 = gui_bar_item_custom_new ("test2", "some content 2"); + POINTERS_EQUAL(new_item, gui_custom_bar_items); + POINTERS_EQUAL(new_item2, last_gui_custom_bar_item); + + gui_bar_item_custom_free_all (); + POINTERS_EQUAL(NULL, gui_custom_bar_items); + POINTERS_EQUAL(NULL, last_gui_custom_bar_item); + + /* remove items in reverse order */ + new_item = gui_bar_item_custom_new ("test", "some content"); + new_item2 = gui_bar_item_custom_new ("test2", "some content 2"); + gui_bar_item_custom_free (new_item2); + gui_bar_item_custom_free (new_item); +} diff --git a/tests/unit/gui/test-gui-bar-item.cpp b/tests/unit/gui/test-gui-bar-item.cpp new file mode 100644 index 000000000..390b1792a --- /dev/null +++ b/tests/unit/gui/test-gui-bar-item.cpp @@ -0,0 +1,547 @@ +/* + * test-gui-bar-item.cpp - test bar item functions + * + * Copyright (C) 2022 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "CppUTest/TestHarness.h" + +extern "C" +{ +#include <string.h> +#include "src/gui/gui-bar.h" +#include "src/gui/gui-bar-item.h" + +extern char *gui_bar_item_buffer_name_cb (const void *pointer, void *data, + struct t_gui_bar_item *item, + struct t_gui_window *window, + struct t_gui_buffer *buffer, + struct t_hashtable *extra_info); +} + +TEST_GROUP(GuiBarItem) +{ +}; + +/* + * Tests functions: + * gui_bar_item_valid + */ + +TEST(GuiBarItem, Valid) +{ + LONGS_EQUAL(0, gui_bar_item_valid (NULL)); + LONGS_EQUAL(0, gui_bar_item_valid ((struct t_gui_bar_item *)0x1)); + + LONGS_EQUAL(1, gui_bar_item_valid (gui_bar_items)); + + LONGS_EQUAL(0, gui_bar_item_valid (gui_bar_items + 1)); +} + +/* + * Tests functions: + * gui_bar_item_search + */ + +TEST(GuiBarItem, Search) +{ + struct t_gui_bar_item *ptr_item; + + POINTERS_EQUAL(NULL, gui_bar_item_search (NULL)); + POINTERS_EQUAL(NULL, gui_bar_item_search ("")); + POINTERS_EQUAL(NULL, gui_bar_item_search ("zzz")); + + ptr_item = gui_bar_item_search ("buffer_name"); + CHECK(ptr_item); + POINTERS_EQUAL(NULL, ptr_item->plugin); + STRCMP_EQUAL("buffer_name", ptr_item->name); + POINTERS_EQUAL(&gui_bar_item_buffer_name_cb, ptr_item->build_callback); + POINTERS_EQUAL(NULL, ptr_item->build_callback_pointer); + POINTERS_EQUAL(NULL, ptr_item->build_callback_data); +} + +/* + * Tests functions: + * gui_bar_item_search_with_plugin + */ + +TEST(GuiBarItem, SearchWithPlugin) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_used_in_bar + */ + +TEST(GuiBarItem, UsedInBar) +{ + struct t_gui_bar *ptr_bar; + + ptr_bar = gui_bar_search ("status"); + CHECK(ptr_bar); + + LONGS_EQUAL(0, gui_bar_item_used_in_bar (NULL, NULL, 0)); + LONGS_EQUAL(0, gui_bar_item_used_in_bar (NULL, "", 0)); + LONGS_EQUAL(0, gui_bar_item_used_in_bar (ptr_bar, "zzz", 0)); + LONGS_EQUAL(0, gui_bar_item_used_in_bar (ptr_bar, "buffer_", 0)); + + LONGS_EQUAL(1, gui_bar_item_used_in_bar (ptr_bar, "buffer_name", 0)); + LONGS_EQUAL(1, gui_bar_item_used_in_bar (ptr_bar, "buffer_", 1)); +} + +/* + * Tests functions: + * gui_bar_item_used_in_at_least_one_bar + */ + +TEST(GuiBarItem, UsedInAtLeastOneBar) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_get_vars + */ + +TEST(GuiBarItem, GetVars) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_get_value + */ + +TEST(GuiBarItem, GetValue) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_count_lines + */ + +TEST(GuiBarItem, CountLines) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_new + */ + +TEST(GuiBarItem, New) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_update + */ + +TEST(GuiBarItem, Update) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_free + */ + +TEST(GuiBarItem, Free) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_free_all + */ + +TEST(GuiBarItem, FreeAll) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_free_all_plugin + */ + +TEST(GuiBarItem, FreeAllPlugin) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_input_paste_cb + */ + +TEST(GuiBarItem, InputPasteCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_input_prompt_cb + */ + +TEST(GuiBarItem, InputPromptCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_input_search_cb + */ + +TEST(GuiBarItem, InputSearchCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_input_text_cb + */ + +TEST(GuiBarItem, InputTextCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_time_cb + */ + +TEST(GuiBarItem, TimeCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_buffer_count_cb + */ + +TEST(GuiBarItem, BufferCountCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_buffer_last_number_cb + */ + +TEST(GuiBarItem, BufferLastNumberCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_buffer_plugin_cb + */ + +TEST(GuiBarItem, BufferPluginCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_buffer_number_cb + */ + +TEST(GuiBarItem, BufferNumberCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_buffer_name_cb + */ + +TEST(GuiBarItem, BufferNameCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_buffer_short_name_cb + */ + +TEST(GuiBarItem, BufferShortNameCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_buffer_modes_cb + */ + +TEST(GuiBarItem, BufferModesCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_buffer_filter_cb + */ + +TEST(GuiBarItem, BufferFilterCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_buffer_nicklist_count_cb + */ + +TEST(GuiBarItem, BufferNicklistCountCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_buffer_nicklist_count_groups_cb + */ + +TEST(GuiBarItem, BufferNicklistCountGroupsCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_buffer_nicklist_count_all_cb + */ + +TEST(GuiBarItem, BufferNicklistCountAllCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_buffer_zoom_cb + */ + +TEST(GuiBarItem, BufferZoomCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_scroll_cb + */ + +TEST(GuiBarItem, ScrollCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_hotlist_cb + */ + +TEST(GuiBarItem, HotlistCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_completion_cb + */ + +TEST(GuiBarItem, CompletionCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_buffer_title_cb + */ + +TEST(GuiBarItem, BufferTitleCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_buffer_nicklist_cb + */ + +TEST(GuiBarItem, BufferNicklistCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_window_number_cb + */ + +TEST(GuiBarItem, WindowNumberCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_mouse_status_cb + */ + +TEST(GuiBarItem, MouseStatusCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_away_cb + */ + +TEST(GuiBarItem, AwayCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_spacer_cb + */ + +TEST(GuiBarItem, SpacerCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_focus_buffer_nicklist_cb + */ + +TEST(GuiBarItem, FocusBufferNicklistCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_timer_cb + */ + +TEST(GuiBarItem, TimerCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_signal_cb + */ + +TEST(GuiBarItem, SignalCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_hook_signal + */ + +TEST(GuiBarItem, HookSignal) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_init + */ + +TEST(GuiBarItem, Init) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_end + */ + +TEST(GuiBarItem, End) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_hdata_bar_item_cb + */ + +TEST(GuiBarItem, HdataBarItemCb) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_add_to_infolist + */ + +TEST(GuiBarItem, AddToInfolist) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * gui_bar_item_print_log + */ + +TEST(GuiBarItem, PrintLog) +{ + /* TODO: write tests */ +} |