diff options
Diffstat (limited to 'src')
-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 |
10 files changed, 1035 insertions, 16 deletions
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; } |