summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/wee-command.c225
-rw-r--r--src/core/wee-completion.c86
-rw-r--r--src/core/wee-config.c102
-rw-r--r--src/core/wee-config.h1
-rw-r--r--src/gui/CMakeLists.txt1
-rw-r--r--src/gui/Makefile.am2
-rw-r--r--src/gui/gui-bar-item-custom.c527
-rw-r--r--src/gui/gui-bar-item-custom.h70
-rw-r--r--src/gui/gui-bar-item.h2
-rw-r--r--src/gui/gui-bar.c35
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;
}