summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/plugins/CMakeLists.txt4
-rw-r--r--src/plugins/Makefile.am5
-rw-r--r--src/plugins/fset/CMakeLists.txt33
-rw-r--r--src/plugins/fset/Makefile.am46
-rw-r--r--src/plugins/fset/fset-bar-item.c84
-rw-r--r--src/plugins/fset/fset-bar-item.h29
-rw-r--r--src/plugins/fset/fset-buffer.c465
-rw-r--r--src/plugins/fset/fset-buffer.h41
-rw-r--r--src/plugins/fset/fset-command.c154
-rw-r--r--src/plugins/fset/fset-command.h25
-rw-r--r--src/plugins/fset/fset-config.c218
-rw-r--r--src/plugins/fset/fset-config.h40
-rw-r--r--src/plugins/fset/fset-info.c110
-rw-r--r--src/plugins/fset/fset-info.h25
-rw-r--r--src/plugins/fset/fset-mouse.c120
-rw-r--r--src/plugins/fset/fset-mouse.h28
-rw-r--r--src/plugins/fset/fset-option.c522
-rw-r--r--src/plugins/fset/fset-option.h60
-rw-r--r--src/plugins/fset/fset.c135
-rw-r--r--src/plugins/fset/fset.h35
-rw-r--r--src/plugins/weechat-plugin.h1
21 files changed, 2180 insertions, 0 deletions
diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt
index cbb0fd58a..8683d15a7 100644
--- a/src/plugins/CMakeLists.txt
+++ b/src/plugins/CMakeLists.txt
@@ -86,6 +86,10 @@ if(ENABLE_FIFO)
add_subdirectory(fifo)
endif()
+if(ENABLE_FSET)
+ add_subdirectory(fset)
+endif()
+
if(ENABLE_IRC)
add_subdirectory(irc)
endif()
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 3c959b74e..7a9d3c1ac 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -61,6 +61,10 @@ if PLUGIN_FIFO
fifo_dir = fifo
endif
+if PLUGIN_FSET
+fset_dir = fset
+endif
+
if PLUGIN_IRC
irc_dir = irc
endif
@@ -120,6 +124,7 @@ SUBDIRS = . \
$(charset_dir) \
$(exec_dir) \
$(fifo_dir) \
+ $(fset_dir) \
$(irc_dir) \
$(logger_dir) \
$(relay_dir) \
diff --git a/src/plugins/fset/CMakeLists.txt b/src/plugins/fset/CMakeLists.txt
new file mode 100644
index 000000000..ef6c7e51f
--- /dev/null
+++ b/src/plugins/fset/CMakeLists.txt
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2003-2017 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 <http://www.gnu.org/licenses/>.
+#
+
+add_library(fset MODULE
+fset.c fset.h
+fset-bar-item.c fset-bar-item.h
+fset-buffer.c fset-buffer.h
+fset-command.c fset-command.h
+fset-config.c fset-config.h
+fset-info.c fset-info.h
+fset-mouse.c fset-mouse.h
+fset-option.c fset-option.h)
+set_target_properties(fset PROPERTIES PREFIX "")
+
+target_link_libraries(fset)
+
+install(TARGETS fset LIBRARY DESTINATION ${LIBDIR}/plugins)
diff --git a/src/plugins/fset/Makefile.am b/src/plugins/fset/Makefile.am
new file mode 100644
index 000000000..5121614f6
--- /dev/null
+++ b/src/plugins/fset/Makefile.am
@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2003-2017 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 <http://www.gnu.org/licenses/>.
+#
+
+AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/locale\" $(FSET_CFLAGS)
+
+libdir = ${weechat_libdir}/plugins
+
+lib_LTLIBRARIES = fset.la
+
+fset_la_SOURCES = fset.c \
+ fset.h \
+ fset-bar-item.c \
+ fset-bar-item.h \
+ fset-buffer.c \
+ fset-buffer.h \
+ fset-command.c \
+ fset-command.h \
+ fset-config.c \
+ fset-config.h \
+ fset-info.c \
+ fset-info.h \
+ fset-mouse.c \
+ fset-mouse.h \
+ fset-option.c \
+ fset-option.h
+
+fset_la_LDFLAGS = -module -no-undefined
+fset_la_LIBADD = $(FSET_LFLAGS)
+
+EXTRA_DIST = CMakeLists.txt
diff --git a/src/plugins/fset/fset-bar-item.c b/src/plugins/fset/fset-bar-item.c
new file mode 100644
index 000000000..cfeaeb70e
--- /dev/null
+++ b/src/plugins/fset/fset-bar-item.c
@@ -0,0 +1,84 @@
+/*
+ * fset-bar-item.c - bar item for Fast Set plugin
+ *
+ * Copyright (C) 2003-2017 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+
+#include "../weechat-plugin.h"
+#include "fset.h"
+#include "fset-bar-item.h"
+#include "fset-config.h"
+
+
+struct t_gui_bar_item *fset_bar_item_fset = NULL;
+
+
+/*
+ * Updates fset bar item if fset is enabled.
+ */
+
+void
+fset_bar_item_update ()
+{
+ if (weechat_config_boolean (fset_config_look_enabled))
+ weechat_bar_item_update (FSET_BAR_ITEM_NAME);
+}
+
+/*
+ * Returns content of bar item "buffer_plugin": bar item with buffer plugin.
+ */
+
+char *
+fset_bar_item_fset_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)
+{
+ return NULL;
+}
+
+/*
+ * Initializes fset bar items.
+ *
+ * Returns:
+ * 1: OK
+ * 0: error
+ */
+
+int
+fset_bar_item_init ()
+{
+ fset_bar_item_fset = weechat_bar_item_new (
+ FSET_BAR_ITEM_NAME,
+ &fset_bar_item_fset_cb, NULL, NULL);
+
+ return 1;
+}
+
+/*
+ * Ends fset bar items.
+ */
+
+void
+fset_bar_item_end ()
+{
+ weechat_bar_item_remove (fset_bar_item_fset);
+}
diff --git a/src/plugins/fset/fset-bar-item.h b/src/plugins/fset/fset-bar-item.h
new file mode 100644
index 000000000..b79ea50c6
--- /dev/null
+++ b/src/plugins/fset/fset-bar-item.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2003-2017 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef WEECHAT_FSET_BAR_ITEM_H
+#define WEECHAT_FSET_BAR_ITEM_H 1
+
+#define FSET_BAR_ITEM_NAME "fset"
+
+extern void fset_bar_item_update ();
+extern int fset_bar_item_init ();
+extern void fset_bar_item_end ();
+
+#endif /* WEECHAT_FSET_BAR_ITEM_H */
diff --git a/src/plugins/fset/fset-buffer.c b/src/plugins/fset/fset-buffer.c
new file mode 100644
index 000000000..e95e6b8ad
--- /dev/null
+++ b/src/plugins/fset/fset-buffer.c
@@ -0,0 +1,465 @@
+/*
+ * fset-buffer.c - buffer for Fast Set plugin
+ *
+ * Copyright (C) 2003-2017 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../weechat-plugin.h"
+#include "fset.h"
+#include "fset-buffer.h"
+#include "fset-config.h"
+#include "fset-option.h"
+
+
+struct t_gui_buffer *fset_buffer = NULL;
+int fset_buffer_selected_line = 0;
+struct t_hashtable *fset_buffer_hashtable_pointers = NULL;
+struct t_hashtable *fset_buffer_hashtable_extra_vars = NULL;
+char *fset_buffer_columns[] = { "name", "type", "default_value", "value",
+ NULL };
+int fset_buffer_columns_default_size[] = { 64, 8, 16, 16 };
+
+
+/*
+ * Displays a line with an fset option.
+ */
+
+void
+fset_buffer_display_line (int y, struct t_fset_option *option)
+{
+ char *line, str_format[32], str_value[1024];
+ int i, *ptr_length;
+
+ /* set pointers */
+ weechat_hashtable_set (fset_buffer_hashtable_pointers, "fset_option", option);
+
+ /* set column variables */
+ for (i = 0; fset_buffer_columns[i]; i++)
+ {
+ ptr_length = (int *)weechat_hashtable_get (fset_option_max_length_field,
+ fset_buffer_columns[i]);
+ snprintf (str_format, sizeof (str_format),
+ "%%-%ds",
+ (ptr_length) ? *ptr_length : fset_buffer_columns_default_size[i]);
+ snprintf (str_value, sizeof (str_value),
+ str_format,
+ weechat_hdata_string (fset_hdata_fset_option,
+ option,
+ fset_buffer_columns[i]));
+ weechat_hashtable_set (fset_buffer_hashtable_extra_vars,
+ fset_buffer_columns[i],
+ str_value);
+ }
+
+ /* build string for line */
+ line = weechat_string_eval_expression (
+ (y == fset_buffer_selected_line) ?
+ fset_config_eval_format_option_current :
+ weechat_config_string (fset_config_format_option),
+ fset_buffer_hashtable_pointers,
+ fset_buffer_hashtable_extra_vars,
+ NULL);
+
+ if (line)
+ {
+ weechat_printf_y (fset_buffer, y, "%s", line);
+ free (line);
+ }
+}
+
+/*
+ * Updates list of options in fset buffer.
+ */
+
+void
+fset_buffer_refresh (int clear)
+{
+ char str_title[1024];
+ int num_options, i;
+ struct t_fset_option *ptr_option;
+
+ if (!fset_buffer)
+ return;
+
+ num_options = weechat_arraylist_size (fset_options);
+
+ if (clear)
+ {
+ weechat_buffer_clear (fset_buffer);
+ fset_buffer_selected_line = (num_options > 0) ? 0 : -1;
+ }
+
+ snprintf (str_title, sizeof (str_title), _("Fast Set"));
+ weechat_buffer_set (fset_buffer, "title", str_title);
+
+ for (i = 0; i < num_options; i++)
+ {
+ ptr_option = weechat_arraylist_get (fset_options, i);
+ fset_buffer_display_line (i, ptr_option);
+ }
+}
+
+/*
+ * Sets current selected line.
+ */
+
+void
+fset_buffer_set_current_line (int line)
+{
+ int old_line;
+
+ if ((line >= 0) && (line < weechat_arraylist_size (fset_options)))
+ {
+ old_line = fset_buffer_selected_line;
+ fset_buffer_selected_line = line;
+
+ fset_buffer_display_line (
+ old_line,
+ weechat_arraylist_get (fset_options, old_line));
+ fset_buffer_display_line (
+ fset_buffer_selected_line,
+ weechat_arraylist_get (fset_options, fset_buffer_selected_line));
+ }
+}
+
+/*
+ * Gets info about a window.
+ */
+
+void
+fset_buffer_get_window_info (struct t_gui_window *window,
+ int *start_line_y, int *chat_height)
+{
+ struct t_hdata *hdata_window, *hdata_window_scroll, *hdata_line;
+ struct t_hdata *hdata_line_data;
+ void *window_scroll, *start_line, *line_data;
+
+ hdata_window = weechat_hdata_get ("window");
+ hdata_window_scroll = weechat_hdata_get ("window_scroll");
+ hdata_line = weechat_hdata_get ("line");
+ hdata_line_data = weechat_hdata_get ("line_data");
+ *start_line_y = 0;
+ window_scroll = weechat_hdata_pointer (hdata_window, window, "scroll");
+ if (window_scroll)
+ {
+ start_line = weechat_hdata_pointer (hdata_window_scroll, window_scroll,
+ "start_line");
+ if (start_line)
+ {
+ line_data = weechat_hdata_pointer (hdata_line, start_line, "data");
+ if (line_data)
+ {
+ *start_line_y = weechat_hdata_integer (hdata_line_data,
+ line_data, "y");
+ }
+ }
+ }
+ *chat_height = weechat_hdata_integer (hdata_window, window,
+ "win_chat_height");
+}
+
+/*
+ * Checks if current line is outside window.
+ *
+ * Returns:
+ * 1: line is outside window
+ * 0: line is inside window
+ */
+
+void
+fset_buffer_check_line_outside_window ()
+{
+ struct t_gui_window *window;
+ int start_line_y, chat_height;
+ char str_command[256];
+
+ window = weechat_window_search_with_buffer (fset_buffer);
+ if (!window)
+ return;
+
+ fset_buffer_get_window_info (window, &start_line_y, &chat_height);
+ if ((start_line_y > fset_buffer_selected_line)
+ || (start_line_y <= fset_buffer_selected_line - chat_height))
+ {
+ snprintf (str_command, sizeof (str_command),
+ "/window scroll -window %d %s%d",
+ weechat_window_get_integer (window, "number"),
+ (start_line_y > fset_buffer_selected_line) ? "-" : "+",
+ (start_line_y > fset_buffer_selected_line) ?
+ start_line_y - fset_buffer_selected_line :
+ fset_buffer_selected_line - start_line_y - chat_height + 1);
+ weechat_command (fset_buffer, str_command);
+ }
+}
+
+/*
+ * Callback for signal "window_scrolled".
+ */
+
+int
+fset_buffer_window_scrolled_cb (const void *pointer, void *data,
+ const char *signal, const char *type_data,
+ void *signal_data)
+{
+ int start_line_y, chat_height, line, num_options;
+
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) signal;
+ (void) type_data;
+
+ /* scrolled another window/buffer? then just ignore */
+ if (weechat_window_get_pointer (signal_data, "buffer") != fset_buffer)
+ return WEECHAT_RC_OK;
+
+ fset_buffer_get_window_info (signal_data, &start_line_y, &chat_height);
+
+ line = fset_buffer_selected_line;
+ while (line < start_line_y)
+ {
+ line += chat_height;
+ }
+ while (line >= start_line_y + chat_height)
+ {
+ line -= chat_height;
+ }
+ if (line < start_line_y)
+ line = start_line_y;
+ num_options = weechat_arraylist_size (fset_options);
+ if (line >= num_options)
+ line = num_options - 1;
+ fset_buffer_set_current_line (line);
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * Callback for user data in fset buffer.
+ */
+
+int
+fset_buffer_input_cb (const void *pointer, void *data,
+ struct t_gui_buffer *buffer,
+ const char *input_data)
+{
+ char *actions[][2] = { { "t", "toggle" },
+ { "+", "increase" },
+ { "-", "decrease" },
+ { "r", "reset" },
+ { "u", "unset" },
+ { "s", "set" },
+ { "a", "append" },
+ { NULL, NULL } };
+ char str_command[64];
+ int i;
+
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+
+ /* close buffer */
+ if (strcmp (input_data, "q") == 0)
+ {
+ weechat_buffer_close (buffer);
+ return WEECHAT_RC_OK;
+ }
+
+ /* refresh buffer */
+ if (strcmp (input_data, "$") == 0)
+ {
+ fset_option_get_options ();
+ fset_buffer_refresh (1);
+ return WEECHAT_RC_OK;
+ }
+
+ /* execute action on an option */
+ for (i = 0; actions[i][0]; i++)
+ {
+ if (strcmp (input_data, actions[i][0]) == 0)
+ {
+ snprintf (str_command, sizeof (str_command),
+ "/fset %s", actions[i][1]);
+ weechat_command (buffer, str_command);
+ return WEECHAT_RC_OK;
+ }
+ }
+
+ /* filter options with given text */
+ fset_option_filter_options (input_data);
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * Callback called when fset buffer is closed.
+ */
+
+int
+fset_buffer_close_cb (const void *pointer, void *data,
+ struct t_gui_buffer *buffer)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) buffer;
+
+ fset_buffer = NULL;
+ fset_buffer_selected_line = 0;
+ weechat_arraylist_clear (fset_options);
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * Restore buffer callbacks (input and close) for buffer created by fset
+ * plugin.
+ */
+
+void
+fset_buffer_set_callbacks ()
+{
+ struct t_gui_buffer *ptr_buffer;
+
+ ptr_buffer = weechat_buffer_search (FSET_PLUGIN_NAME, FSET_BUFFER_NAME);
+ if (ptr_buffer)
+ {
+ fset_buffer = ptr_buffer;
+ weechat_buffer_set_pointer (fset_buffer, "close_callback", &fset_buffer_close_cb);
+ weechat_buffer_set_pointer (fset_buffer, "input_callback", &fset_buffer_input_cb);
+ }
+}
+
+/*
+ * Sets keys on fset buffer.
+ */
+
+void
+fset_buffer_set_keys ()
+{
+ char *keys[][2] = { { "meta-t", "toggle" },
+ { "meta-+", "increase" },
+ { "meta--", "decrease" },
+ { "meta-r", "reset" },
+ { "meta-u", "unset" },
+ { "meta-s", "set" },
+ { "meta-a", "append" },
+ { NULL, NULL } };
+ char str_key[64], str_command[64];
+ int i;
+
+ weechat_buffer_set (fset_buffer, "key_bind_meta2-A", "/fset -up");
+ weechat_buffer_set (fset_buffer, "key_bind_meta2-B", "/fset -down");
+ for (i = 0; keys[i][0]; i++)
+ {
+ if (weechat_config_boolean (fset_config_look_use_keys))
+ {
+ snprintf (str_key, sizeof (str_key), "key_bind_%s", keys[i][0]);
+ snprintf (str_command, sizeof (str_command), "/fset -%s", keys[i][1]);
+ weechat_buffer_set (fset_buffer, str_key, str_command);
+ }
+ else
+ {
+ snprintf (str_key, sizeof (str_key), "key_unbind_%s", keys[i][0]);
+ weechat_buffer_set (fset_buffer, str_key, "");
+ }
+ }
+}
+
+/*
+ * Opens fset buffer.
+ */
+
+void
+fset_buffer_open ()
+{
+ if (!fset_buffer)
+ {
+ fset_buffer = weechat_buffer_new (
+ FSET_BUFFER_NAME,
+ &fset_buffer_input_cb, NULL, NULL,
+ &fset_buffer_close_cb, NULL, NULL);
+
+ /* failed to create buffer ? then exit */
+ if (!fset_buffer)
+ return;
+
+ weechat_buffer_set (fset_buffer, "type", "free");
+ weechat_buffer_set (fset_buffer, "title", _("Options"));
+ fset_buffer_set_keys ();
+ weechat_buffer_set (fset_buffer, "localvar_set_type", "option");
+
+ fset_buffer_selected_line = 0;
+ }
+}
+
+/*
+ * Initializes fset buffer.
+ *
+ * Returns:
+ * 1: OK
+ * 0: error
+ */
+
+int
+fset_buffer_init ()
+{
+ fset_buffer_set_callbacks ();
+
+ /* create hashtables used by the bar item callback */
+ fset_buffer_hashtable_pointers = weechat_hashtable_new (
+ 8,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_POINTER,
+ NULL,
+ NULL);
+ if (!fset_buffer_hashtable_pointers)
+ return 0;
+
+ fset_buffer_hashtable_extra_vars = weechat_hashtable_new (
+ 32,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING,
+ NULL,
+ NULL);
+ if (!fset_buffer_hashtable_extra_vars)
+ {
+ weechat_hashtable_free (fset_buffer_hashtable_pointers);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Ends fset buffer.
+ */
+
+void
+fset_buffer_end ()
+{
+ weechat_hashtable_free (fset_buffer_hashtable_pointers);
+ fset_buffer_hashtable_pointers = NULL;
+
+ weechat_hashtable_free (fset_buffer_hashtable_extra_vars);
+ fset_buffer_hashtable_extra_vars = NULL;
+}
diff --git a/src/plugins/fset/fset-buffer.h b/src/plugins/fset/fset-buffer.h
new file mode 100644
index 000000000..c61ef8061
--- /dev/null
+++ b/src/plugins/fset/fset-buffer.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2003-2017 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef WEECHAT_FSET_BUFFER_H
+#define WEECHAT_FSET_BUFFER_H 1
+
+#define FSET_BUFFER_NAME "fset"
+
+extern struct t_gui_buffer *fset_buffer;
+extern int fset_buffer_selected_line;
+
+extern void fset_buffer_refresh (int clear);
+extern void fset_buffer_set_current_line (int line);
+extern void fset_buffer_check_line_outside_window ();
+extern int fset_buffer_window_scrolled_cb (const void *pointer,
+ void *data,
+ const char *signal,
+ const char *type_data,
+ void *signal_data);
+extern void fset_buffer_set_keys ();
+extern void fset_buffer_open ();
+extern int fset_buffer_init ();
+extern void fset_buffer_end ();
+
+#endif /* WEECHAT_FSET_BUFFER_H */
diff --git a/src/plugins/fset/fset-command.c b/src/plugins/fset/fset-command.c
new file mode 100644
index 000000000..025f57892
--- /dev/null
+++ b/src/plugins/fset/fset-command.c
@@ -0,0 +1,154 @@
+/*
+ * fset-command.c - Fast Set command
+ *
+ * Copyright (C) 2003-2017 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+
+#include "../weechat-plugin.h"
+#include "fset.h"
+#include "fset-command.h"
+#include "fset-bar-item.h"
+#include "fset-buffer.h"
+#include "fset-option.h"
+
+
+/*
+ * Callback for command "/fset".
+ */
+
+int
+fset_command_fset (const void *pointer, void *data,
+ struct t_gui_buffer *buffer, int argc,
+ char **argv, char **argv_eol)
+{
+ int num_options, line;
+ long value;
+ char *error;
+
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) buffer;
+ (void) argv_eol;
+
+ if (argc == 1)
+ {
+ if (weechat_arraylist_size (fset_options) == 0)
+ {
+ fset_option_get_options ();
+ }
+ if (!fset_buffer)
+ {
+ fset_buffer_open ();
+ fset_buffer_refresh (1);
+ }
+ weechat_buffer_set (fset_buffer, "display", "1");
+ return WEECHAT_RC_OK;
+ }
+
+ if (weechat_strcasecmp (argv[1], "-refresh") == 0)
+ {
+ fset_bar_item_update ();
+ return WEECHAT_RC_OK;
+ }
+
+ if (weechat_strcasecmp (argv[1], "-bar") == 0)
+ {
+ fset_bar_item_update ();
+ return WEECHAT_RC_OK;
+ }
+
+ if (weechat_strcasecmp (argv[1], "-up") == 0)
+ {
+ if (fset_buffer)
+ {
+ value = 1;
+ if (argc > 2)
+ {
+ error = NULL;
+ value = strtol (argv[2], &error, 10);
+ if (!error || error[0])
+ value = 1;
+ }
+ num_options = weechat_arraylist_size (fset_options);
+ if ((fset_buffer_selected_line >= 0)
+ && (num_options > 0))
+ {
+ line = fset_buffer_selected_line - value;
+ if (line < 0)
+ line = 0;
+ if (line != fset_buffer_selected_line)
+ {
+ fset_buffer_set_current_line (line);
+ fset_buffer_check_line_outside_window ();
+ }
+ }
+ }
+ return WEECHAT_RC_OK;
+ }
+
+ if (weechat_strcasecmp (argv[1], "-down") == 0)
+ {
+ if (fset_buffer)
+ {
+ value = 1;
+ if (argc > 2)
+ {
+ error = NULL;
+ value = strtol (argv[2], &error, 10);
+ if (!error || error[0])
+ value = 1;
+ }
+ num_options = weechat_arraylist_size (fset_options);
+ if ((fset_buffer_selected_line >= 0)
+ && (num_options > 0))
+ {
+ line = fset_buffer_selected_line + value;
+ if (line >= num_options)
+ line = num_options - 1;
+ if (line != fset_buffer_selected_line)
+ {
+ fset_buffer_set_current_line (line);
+ fset_buffer_check_line_outside_window ();
+ }
+ }
+ }
+ return WEECHAT_RC_OK;
+ }
+
+ WEECHAT_COMMAND_ERROR;
+}
+
+/*
+ * Hooks fset commands.
+ */
+
+void
+fset_command_init ()
+{
+ weechat_hook_command (
+ "fset",
+ N_("fast set WeeChat and plugins options"),
+ "-bar || -refresh",
+ N_(" -bar: add the fset bar\n"
+ "-refresh: force the refresh of the \"fset\" bar item"),
+ "-bar || -refresh",
+ &fset_command_fset, NULL, NULL);
+}
diff --git a/src/plugins/fset/fset-command.h b/src/plugins/fset/fset-command.h
new file mode 100644
index 000000000..47053fc68
--- /dev/null
+++ b/src/plugins/fset/fset-command.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2003-2017 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef WEECHAT_FSET_COMMAND_H
+#define WEECHAT_FSET_COMMAND_H 1
+
+extern void fset_command_init ();
+
+#endif /* WEECHAT_FSET_COMMAND_H */
diff --git a/src/plugins/fset/fset-config.c b/src/plugins/fset/fset-config.c
new file mode 100644
index 000000000..6478aef61
--- /dev/null
+++ b/src/plugins/fset/fset-config.c
@@ -0,0 +1,218 @@
+/*
+ * fset-config.c - Fast Set configuration options (file fset.conf)
+ *
+ * Copyright (C) 2003-2017 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "../weechat-plugin.h"
+#include "fset.h"
+#include "fset-config.h"
+#include "fset-buffer.h"
+
+
+struct t_config_file *fset_config_file = NULL;
+
+/* fset config, look section */
+
+struct t_config_option *fset_config_look_enabled;
+struct t_config_option *fset_config_look_use_keys;
+
+/* fset config, format section */
+
+struct t_config_option *fset_config_format_option;
+struct t_config_option *fset_config_format_option_current;
+
+char *fset_config_eval_format_option_current = NULL;
+
+
+/*
+ * Callback for changes on option "fset.look.use_keys".
+ */
+
+void
+fset_config_change_use_keys_cb (const void *pointer, void *data,
+ struct t_config_option *option)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) option;
+
+ if (fset_buffer)
+ fset_buffer_set_keys ();
+}
+
+/*
+ * Callback for changes on format options.
+ */
+
+void
+fset_config_change_format (const void *pointer, void *data,
+ struct t_config_option *option)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) option;
+
+ if (fset_config_eval_format_option_current)
+ free (fset_config_eval_format_option_current);
+
+ fset_config_eval_format_option_current = weechat_string_replace (
+ weechat_config_string (fset_config_format_option_current),
+ "${format_option}",
+ weechat_config_string (fset_config_format_option));
+
+ fset_buffer_refresh (1);
+}
+
+/*
+ * Initializes fset configuration file.
+ *
+ * Returns:
+ * 1: OK
+ * 0: error
+ */
+
+int
+fset_config_init ()
+{
+ struct t_config_section *ptr_section;
+
+ fset_config_file = weechat_config_new (FSET_CONFIG_NAME,
+ NULL, NULL, NULL);
+ if (!fset_config_file)
+ return 0;
+
+ /* look */
+ ptr_section = weechat_config_new_section (fset_config_file, "look",
+ 0, 0,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ if (!ptr_section)
+ {
+ weechat_config_free (fset_config_file);
+ return 0;
+ }
+
+ fset_config_look_enabled = weechat_config_new_option (
+ fset_config_file, ptr_section,
+ "enabled", "boolean",
+ N_("enable fset"),
+ NULL, 0, 0, "on", NULL, 0,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ fset_config_look_use_keys = weechat_config_new_option (
+ fset_config_file, ptr_section,
+ "use_keys", "boolean",
+ N_("use keys alt+X in fset buffer to do actions on options; "
+ "if disabled, only the input is allowed"),
+ NULL, 0, 0, "on", NULL, 0,
+ NULL, NULL, NULL,
+ &fset_config_change_use_keys_cb, NULL, NULL,
+ NULL, NULL, NULL);
+
+ /* format */
+ ptr_section = weechat_config_new_section (fset_config_file, "format",
+ 0, 0,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ if (!ptr_section)
+ {
+ weechat_config_free (fset_config_file);
+ return 0;
+ }
+
+ fset_config_format_option = weechat_config_new_option (
+ fset_config_file, ptr_section,
+ "option", "string",
+ N_("format of each line with an option "
+ "(note: content is evaluated, see /help fset)"),
+ NULL, 0, 0,
+ "${name} ${type} ${default_value} ${value}",
+ NULL, 0,
+ NULL, NULL, NULL,
+ &fset_config_change_format, NULL, NULL,
+ NULL, NULL, NULL);
+ fset_config_format_option_current = weechat_config_new_option (
+ fset_config_file, ptr_section,
+ "option_current", "string",
+ N_("format for the line with current option "
+ "(note: content is evaluated, see /help fset)"),
+ NULL, 0, 0, "${color:,blue}${format_option}", NULL, 0,
+ NULL, NULL, NULL,
+ &fset_config_change_format, NULL, NULL,
+ NULL, NULL, NULL);
+
+ return 1;
+}
+
+/*
+ * Reads fset configuration file.
+ */
+
+int
+fset_config_read ()
+{
+ int rc;
+
+ rc = weechat_config_read (fset_config_file);
+
+ if (rc == WEECHAT_CONFIG_READ_OK)
+ {
+ fset_config_change_format (NULL, NULL, NULL);
+ }
+
+ return rc;
+}
+
+/*
+ * Writes fset configuration file.
+ */
+
+int
+fset_config_write ()
+{
+ return weechat_config_write (fset_config_file);
+}
+
+/*
+ * Frees fset configuration.
+ */
+
+void
+fset_config_free ()
+{
+ weechat_config_free (fset_config_file);
+
+ if (fset_config_eval_format_option_current)
+ {
+ free (fset_config_eval_format_option_current);
+ fset_config_eval_format_option_current = NULL;
+ }
+}
diff --git a/src/plugins/fset/fset-config.h b/src/plugins/fset/fset-config.h
new file mode 100644
index 000000000..6094da917
--- /dev/null
+++ b/src/plugins/fset/fset-config.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2003-2017 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef WEECHAT_FSET_CONFIG_H
+#define WEECHAT_FSET_CONFIG_H 1
+
+#define FSET_CONFIG_NAME "fset"
+
+extern struct t_config_file *fset_config_file;
+
+extern struct t_config_option *fset_config_look_enabled;
+extern struct t_config_option *fset_config_look_use_keys;
+
+extern struct t_config_option *fset_config_format_option;
+extern struct t_config_option *fset_config_format_option_current;
+
+extern char *fset_config_eval_format_option_current;
+
+extern int fset_config_init ();
+extern int fset_config_read ();
+extern int fset_config_write ();
+extern void fset_config_free ();
+
+#endif /* WEECHAT_FSET_CONFIG_H */
diff --git a/src/plugins/fset/fset-info.c b/src/plugins/fset/fset-info.c
new file mode 100644
index 000000000..193eba6ec
--- /dev/null
+++ b/src/plugins/fset/fset-info.c
@@ -0,0 +1,110 @@
+/*
+ * fset-info.c - info, infolist and hdata hooks for Fast Set plugin
+ *
+ * Copyright (C) 2003-2017 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../weechat-plugin.h"
+#include "fset.h"
+#include "fset-option.h"
+
+
+/*
+ * Returns fset infolist "fset_option".
+ */
+
+struct t_infolist *
+fset_info_infolist_fset_option_cb (const void *pointer, void *data,
+ const char *infolist_name,
+ void *obj_pointer,
+ const char *arguments)
+{
+ struct t_infolist *ptr_infolist;
+ struct t_fset_option *ptr_option;
+ int num_options, i;
+
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) infolist_name;
+
+ if (obj_pointer && !fset_option_valid (obj_pointer))
+ return NULL;
+
+ ptr_infolist = weechat_infolist_new ();
+ if (!ptr_infolist)
+ return NULL;
+
+ if (obj_pointer)
+ {
+ /* build list with only one option */
+ if (!fset_option_add_to_infolist (ptr_infolist, obj_pointer))
+ {
+ weechat_infolist_free (ptr_infolist);
+ return NULL;
+ }
+ return ptr_infolist;
+ }
+ else
+ {
+ /* build list with all options matching arguments */
+ num_options = weechat_arraylist_size (fset_options);
+ for (i = 0; i < num_options; i++)
+ {
+ ptr_option = weechat_arraylist_get (fset_options, i);
+ if (!arguments || !arguments[0]
+ || weechat_string_match (ptr_option->name, arguments, 0))
+ {
+ if (!fset_option_add_to_infolist (ptr_infolist, ptr_option))
+ {
+ weechat_infolist_free (ptr_infolist);
+ return NULL;
+ }
+ }
+ }
+ return ptr_infolist;
+ }
+
+ return NULL;
+}
+
+/*
+ * Hooks infolist and hdata.
+ */
+
+void
+fset_info_init ()
+{
+ /* infolist hooks */
+ weechat_hook_infolist (
+ "fset_option",
+ N_("list of fset options"),
+ N_("fset option pointer (optional)"),
+ N_("option name "
+ "(wildcard \"*\" is allowed) (optional)"),
+ &fset_info_infolist_fset_option_cb, NULL, NULL);
+
+ /* hdata hooks */
+ weechat_hook_hdata (
+ "fset_option", N_("fset options"),
+ &fset_option_hdata_option_cb, NULL, NULL);
+}
diff --git a/src/plugins/fset/fset-info.h b/src/plugins/fset/fset-info.h
new file mode 100644
index 000000000..6a381acce
--- /dev/null
+++ b/src/plugins/fset/fset-info.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2003-2017 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef WEECHAT_FSET_INFO_H
+#define WEECHAT_FSET_INFO_H 1
+
+extern void fset_info_init ();
+
+#endif /* WEECHAT_FSET_INFO_H */
diff --git a/src/plugins/fset/fset-mouse.c b/src/plugins/fset/fset-mouse.c
new file mode 100644
index 000000000..587a7b80a
--- /dev/null
+++ b/src/plugins/fset/fset-mouse.c
@@ -0,0 +1,120 @@
+/*
+ * fset-mouse.c - mouse actions for Fast Set plugin
+ *
+ * Copyright (C) 2003-2017 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../weechat-plugin.h"
+#include "fset.h"
+#include "fset-mouse.h"
+#include "fset-bar-item.h"
+#include "fset-buffer.h"
+#include "fset-config.h"
+
+
+/*
+ * Callback called when a mouse action occurs in fset bar item.
+ */
+
+struct t_hashtable *
+fset_focus_cb (const void *pointer, void *data, struct t_hashtable *info)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+
+ return info;
+}
+
+/*
+ * Callback called when a mouse action occurs in fset bar or bar item.
+ */
+
+int
+fset_hsignal_cb (const void *pointer, void *data, const char *signal,
+ struct t_hashtable *hashtable)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) signal;
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * Initializes mouse.
+ *
+ * Returns:
+ * 1: OK
+ * 0: error
+ */
+
+int
+fset_mouse_init ()
+{
+ struct t_hashtable *keys;
+
+ keys = weechat_hashtable_new (4,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING,
+ NULL, NULL);
+ if (!keys)
+ return 0;
+
+ weechat_hook_focus (FSET_BAR_ITEM_NAME, &fset_focus_cb, NULL, NULL);
+
+ weechat_hook_hsignal(FSET_MOUSE_HSIGNAL,
+ &fset_hsignal_cb, NULL, NULL);
+
+ weechat_hashtable_set (
+ keys,
+ "@chat(" FSET_PLUGIN_NAME "." FSET_BUFFER_NAME "):button1*",
+ "hsignal:" FSET_MOUSE_HSIGNAL);
+ weechat_hashtable_set (
+ keys,
+ "@chat(" FSET_PLUGIN_NAME "." FSET_BUFFER_NAME "):button2*",
+ "hsignal:" FSET_MOUSE_HSIGNAL);
+ weechat_hashtable_set (
+ keys,
+ "@chat(" FSET_PLUGIN_NAME "." FSET_BUFFER_NAME "):wheelup",
+ "/fset -up 5");
+ weechat_hashtable_set (
+ keys,
+ "@chat(" FSET_PLUGIN_NAME "." FSET_BUFFER_NAME "):wheeldown",
+ "/fset -down 5");
+ weechat_hashtable_set (keys, "__quiet", "1");
+ weechat_key_bind ("mouse", keys);
+
+ weechat_hashtable_free (keys);
+
+ return 1;
+}
+
+/*
+ * Ends mouse.
+ */
+
+void
+fset_mouse_end ()
+{
+}
diff --git a/src/plugins/fset/fset-mouse.h b/src/plugins/fset/fset-mouse.h
new file mode 100644
index 000000000..d7a8e5e42
--- /dev/null
+++ b/src/plugins/fset/fset-mouse.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2003-2017 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef WEECHAT_FSET_MOUSE_H
+#define WEECHAT_FSET_MOUSE_H 1
+
+#define FSET_MOUSE_HSIGNAL "fset_mouse"
+
+extern int fset_mouse_init ();
+extern void fset_mouse_end ();
+
+#endif /* WEECHAT_FSET_MOUSE_H */
diff --git a/src/plugins/fset/fset-option.c b/src/plugins/fset/fset-option.c
new file mode 100644
index 000000000..ed2afc9c9
--- /dev/null
+++ b/src/plugins/fset/fset-option.c
@@ -0,0 +1,522 @@
+/*
+ * fset-option.c - manage options displayed by Fast Set buffer
+ *
+ * Copyright (C) 2003-2017 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../weechat-plugin.h"
+#include "fset.h"
+#include "fset-option.h"
+#include "fset-buffer.h"
+#include "fset-config.h"
+
+
+struct t_arraylist *fset_options = NULL;
+struct t_hashtable *fset_option_max_length_field = NULL;
+char *fset_option_filter = NULL;
+
+
+/*
+ * Checks if a fset option pointer is valid.
+ *
+ * Returns:
+ * 1: option exists
+ * 0: option does not exist
+ */
+
+int
+fset_option_valid (struct t_fset_option *option)
+{
+ struct t_fset_option *ptr_option;
+ int num_options, i;
+
+ if (!option)
+ return 0;
+
+ num_options = weechat_arraylist_size (fset_options);
+ for (i = 0; i < num_options; i++)
+ {
+ ptr_option = weechat_arraylist_get (fset_options, i);
+ if (ptr_option == option)
+ return 1;
+ }
+
+ /* option not found */
+ return 0;
+}
+
+/*
+ * Searches for an option by name.
+ *
+ * Returns pointer to option found, NULL if not found.
+ */
+
+struct t_fset_option *
+fset_option_search_by_name (const char *name)
+{
+ struct t_fset_option *ptr_option;
+ int num_options, i;
+
+ num_options = weechat_arraylist_size (fset_options);
+ for (i = 0; i < num_options; i++)
+ {
+ ptr_option = weechat_arraylist_get (fset_options, i);
+ if (strcmp (ptr_option->name, name) == 0)
+ return ptr_option;
+ }
+
+ /* option not found */
+ return NULL;
+}
+
+/*
+ * Sets max length for a field in hashtable "fset_option_max_length_field".
+ */
+
+void
+fset_option_set_max_length_field (const char *field, int length)
+{
+ int *value;
+
+ value = weechat_hashtable_get (fset_option_max_length_field, field);
+ if (!value || (length > *value))
+ weechat_hashtable_set (fset_option_max_length_field, field, &length);
+}
+
+/*
+ * Sets the value in option, according to its type.
+ */
+
+void
+fset_option_set_value_string (struct t_config_option *option,
+ const char *type, void *value,
+ char **value_string)
+{
+ char str_value[64];
+
+ if (!value)
+ {
+ *value_string = NULL;
+ }
+ else if (strcmp (type, "boolean") == 0)
+ {
+ *value_string = strdup (*((int *)value) ? "on" : "off");
+ }
+ else if (strcmp (type, "integer") == 0)
+ {
+ snprintf (str_value, sizeof (str_value), "%d", *((int *)value));
+ *value_string = strdup (str_value);
+ }
+ else if (strcmp (type, "string") == 0)
+ {
+ *value_string = strdup ((const char *)value);
+ }
+ else if (strcmp (type, "color") == 0)
+ {
+ *value_string = strdup (weechat_config_color (option));
+ }
+ else
+ {
+ *value_string = strdup ("");
+ }
+}
+
+/*
+ * Checks if an option is matching current filter(s).
+ *
+ * Returns:
+ * 1: option is matching filter(s)
+ * 0: option does not match filter(s)
+ */
+
+int
+fset_option_match_filters (const char *option_name)
+{
+ if (fset_option_filter
+ && !weechat_strcasestr (option_name, fset_option_filter))
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Allocates an fset option structure using a pointer to a
+ * WeeChat/plugin option.
+ *
+ * Returns pointer to new fset option, NULL if the option does not match
+ * filters or if error.
+ */
+
+struct t_fset_option *
+fset_option_alloc (struct t_config_file *config_file,
+ struct t_config_section *section,
+ struct t_config_option *option)
+{
+ struct t_fset_option *new_option;
+ const char *ptr_config_name, *ptr_section_name, *ptr_option_name;
+ const char *ptr_type;
+ void *ptr_default_value, *ptr_value;
+ char *option_name;
+ int length;
+
+ new_option = NULL;
+ option_name = NULL;
+
+ ptr_config_name = weechat_hdata_string (fset_hdata_config_file,
+ config_file, "name");
+ ptr_section_name = weechat_hdata_string (fset_hdata_config_section,
+ section, "name");
+ ptr_option_name = weechat_hdata_string (fset_hdata_config_option,
+ option, "name");
+ length = strlen (ptr_config_name) + 1 +
+ strlen (ptr_section_name) + 1 +
+ strlen (ptr_option_name) + 1;
+ option_name = malloc (length);
+ if (!option_name)
+ goto end;
+ snprintf (option_name, length, "%s.%s.%s",
+ ptr_config_name,
+ ptr_section_name,
+ ptr_option_name);
+
+ if (!fset_option_match_filters (option_name))
+ {
+ /* option does not match filters, ignore it */
+ goto end;
+ }
+
+ new_option = malloc (sizeof (*new_option));
+ if (new_option)
+ {
+ new_option->name = option_name;
+ ptr_type = weechat_config_option_get_string (option, "type");
+ new_option->type = strdup ((ptr_type) ? ptr_type : "");
+ ptr_default_value = weechat_config_option_get_pointer (option,
+ "default_value");
+ ptr_value = weechat_config_option_get_pointer (option, "value");
+ fset_option_set_value_string (option,
+ new_option->type,
+ ptr_default_value,
+ &new_option->default_value);
+ fset_option_set_value_string (option,
+ new_option->type,
+ ptr_value,
+ &new_option->value);
+ fset_option_set_max_length_field ("name", strlen (new_option->name));
+ fset_option_set_max_length_field ("type", strlen (new_option->type));
+ fset_option_set_max_length_field (
+ "default_value",
+ strlen ((new_option->default_value) ?
+ new_option->default_value : "null"));
+ fset_option_set_max_length_field (
+ "value",
+ strlen ((new_option->value) ?
+ new_option->value : "null"));
+ }
+
+end:
+ if (!new_option)
+ {
+ if (option_name)
+ free (option_name);
+ }
+ return new_option;
+}
+
+/*
+ * Compares two options to sort them by name.
+ */
+
+int
+fset_option_compare_options_old_cb (void *data, struct t_arraylist *arraylist,
+ void *pointer1, void *pointer2)
+{
+ struct t_config_option *ptr_option1, *ptr_option2;
+ struct t_config_file *ptr_config1, *ptr_config2;
+ struct t_config_section *ptr_section1, *ptr_section2;
+ const char *ptr_config_name1, *ptr_config_name2;
+ const char *ptr_section_name1, *ptr_section_name2;
+ const char *ptr_option_name1, *ptr_option_name2;
+ int rc;
+
+ /* make C compiler happy */
+ (void) data;
+ (void) arraylist;
+
+ ptr_option1 = (struct t_config_option *)pointer1;
+ ptr_option2 = (struct t_config_option *)pointer2;
+
+ /* compare config file name */
+ ptr_config1 = weechat_hdata_pointer (fset_hdata_config_option,
+ ptr_option1, "config_file");
+ ptr_config_name1 = weechat_hdata_string (fset_hdata_config_file,
+ ptr_config1, "name");
+ ptr_config2 = weechat_hdata_pointer (fset_hdata_config_option,
+ ptr_option2, "config_file");
+ ptr_config_name2 = weechat_hdata_string (fset_hdata_config_file,
+ ptr_config2, "name");
+ rc = weechat_strcasecmp (ptr_config_name1, ptr_config_name2);
+ if (rc != 0)
+ return rc;
+
+ /* compare section name */
+ ptr_section1 = weechat_hdata_pointer (fset_hdata_config_option,
+ ptr_option1, "section");
+ ptr_section_name1 = weechat_hdata_string (fset_hdata_config_section,
+ ptr_section1, "name");
+ ptr_section2 = weechat_hdata_pointer (fset_hdata_config_option,
+ ptr_option2, "section");
+ ptr_section_name2 = weechat_hdata_string (fset_hdata_config_section,
+ ptr_section2, "name");
+ rc = weechat_strcasecmp (ptr_section_name1, ptr_section_name2);
+ if (rc != 0)
+ return rc;
+
+ /* compare option name */
+ ptr_option_name1 = weechat_hdata_string (fset_hdata_config_option,
+ ptr_option1, "name");
+ ptr_option_name2 = weechat_hdata_string (fset_hdata_config_option,
+ ptr_option2, "name");
+ return weechat_strcasecmp (ptr_option_name1, ptr_option_name2);
+}
+
+/*
+ * Compares two options to sort them by name.
+ */
+
+int
+fset_option_compare_options_cb (void *data, struct t_arraylist *arraylist,
+ void *pointer1, void *pointer2)
+{
+ struct t_fset_option *ptr_option1, *ptr_option2;
+
+ /* make C compiler happy */
+ (void) data;
+ (void) arraylist;
+
+ ptr_option1 = (struct t_fset_option *)pointer1;
+ ptr_option2 = (struct t_fset_option *)pointer2;
+
+ return weechat_strcasecmp (ptr_option1->name,
+ ptr_option2->name);
+}
+
+/*
+ * Frees an fset option.
+ */
+
+void
+fset_option_free_cb (void *data, struct t_arraylist *arraylist, void *pointer)
+{
+ struct t_fset_option *option;
+
+ /* make C compiler happy */
+ (void) data;
+ (void) arraylist;
+
+ option = (struct t_fset_option *)pointer;
+
+ if (option->name)
+ free (option->name);
+ if (option->type)
+ free (option->type);
+ if (option->default_value)
+ free (option->default_value);
+ if (option->value)
+ free (option->value);
+
+ free (option);
+}
+
+
+/*
+ * Gets all options to display in fset buffer.
+ */
+
+void
+fset_option_get_options ()
+{
+ struct t_fset_option *new_option;
+ struct t_config_file *ptr_config;
+ struct t_config_section *ptr_section;
+ struct t_config_option *ptr_option;
+
+ weechat_arraylist_clear (fset_options);
+ weechat_hashtable_remove_all (fset_option_max_length_field);
+
+ ptr_config = weechat_hdata_get_list (fset_hdata_config_file,
+ "config_files");
+ while (ptr_config)
+ {
+ ptr_section = weechat_hdata_pointer (fset_hdata_config_file,
+ ptr_config, "sections");
+ while (ptr_section)
+ {
+ ptr_option = weechat_hdata_pointer (fset_hdata_config_section,
+ ptr_section, "options");
+ while (ptr_option)
+ {
+ new_option = fset_option_alloc (ptr_config, ptr_section,
+ ptr_option);
+ if (new_option)
+ weechat_arraylist_add (fset_options, new_option);
+ ptr_option = weechat_hdata_move (fset_hdata_config_option,
+ ptr_option, 1);
+ }
+ ptr_section = weechat_hdata_move (fset_hdata_config_section,
+ ptr_section, 1);
+ }
+ ptr_config = weechat_hdata_move (fset_hdata_config_file,
+ ptr_config, 1);
+ }
+}
+
+/*
+ * Sets filter for fset options.
+ */
+
+void
+fset_option_set_filter (const char *filter)
+{
+ if (fset_option_filter)
+ free (fset_option_filter);
+ fset_option_filter = (filter && (strcmp (filter, "*") != 0)) ?
+ strdup (filter) : NULL;
+}
+
+/*
+ * Filters options.
+ */
+
+void
+fset_option_filter_options (const char *search)
+{
+ fset_option_set_filter (search);
+ fset_option_get_options ();
+ fset_buffer_refresh (1);
+}
+
+/*
+ * Returns hdata for option.
+ */
+
+struct t_hdata *
+fset_option_hdata_option_cb (const void *pointer, void *data,
+ const char *hdata_name)
+{
+ struct t_hdata *hdata;
+
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+
+ hdata = weechat_hdata_new (hdata_name, NULL, NULL, 0, 0, NULL, NULL);
+ if (hdata)
+ {
+ WEECHAT_HDATA_VAR(struct t_fset_option, name, STRING, 0, NULL, NULL);
+ WEECHAT_HDATA_VAR(struct t_fset_option, type, STRING, 0, NULL, NULL);
+ WEECHAT_HDATA_VAR(struct t_fset_option, default_value, STRING, 0, NULL, NULL);
+ WEECHAT_HDATA_VAR(struct t_fset_option, value, STRING, 0, NULL, NULL);
+ }
+ return hdata;
+}
+
+/*
+ * Adds a fset option in an infolist.
+ *
+ * Returns:
+ * 1: OK
+ * 0: error
+ */
+
+int
+fset_option_add_to_infolist (struct t_infolist *infolist,
+ struct t_fset_option *option)
+{
+ struct t_infolist_item *ptr_item;
+
+ if (!infolist || !option)
+ return 0;
+
+ ptr_item = weechat_infolist_new_item (infolist);
+ if (!ptr_item)
+ return 0;
+
+ if (!weechat_infolist_new_var_string (ptr_item, "name", option->name))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Prints fset options in WeeChat log file (usually for crash dump).
+ */
+
+void
+fset_option_print_log ()
+{
+ struct t_fset_option *ptr_option;
+ int num_options, i;
+
+ num_options = weechat_arraylist_size (fset_options);
+ for (i = 0; i < num_options; i++)
+ {
+ ptr_option = weechat_arraylist_get (fset_options, i);
+ weechat_log_printf ("");
+ weechat_log_printf ("[fset option (addr:0x%lx)]", ptr_option);
+ weechat_log_printf (" name. . . . . . . . . : '%s'", ptr_option->name);
+ }
+}
+
+/*
+ * Initializes fset list of options.
+ *
+ * Returns:
+ * 1: OK
+ * 0: error
+ */
+
+int
+fset_option_init ()
+{
+ fset_options = weechat_arraylist_new (100, 1, 0,
+ &fset_option_compare_options_cb, NULL,
+ &fset_option_free_cb, NULL);
+
+ return 1;
+}
+
+/*
+ * Ends fset list of options.
+ */
+
+void
+fset_option_end ()
+{
+ if (fset_options)
+ {
+ weechat_arraylist_free (fset_options);
+ fset_options = NULL;
+ }
+}
diff --git a/src/plugins/fset/fset-option.h b/src/plugins/fset/fset-option.h
new file mode 100644
index 000000000..44457015e
--- /dev/null
+++ b/src/plugins/fset/fset-option.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2003-2017 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef WEECHAT_FSET_OPTION_H
+#define WEECHAT_FSET_OPTION_H 1
+
+#include <time.h>
+
+/* status for fset */
+#define FSET_STATUS_INSTALLED 1
+#define FSET_STATUS_AUTOLOADED 2
+#define FSET_STATUS_HELD 4
+#define FSET_STATUS_RUNNING 8
+#define FSET_STATUS_NEW_VERSION 16
+
+struct t_fset_option
+{
+ char *name; /* option name */
+ char *type; /* option type */
+ char *default_value; /* option default value */
+ char *value; /* option value */
+ struct t_fset_option *prev_option; /* link to previous option */
+ struct t_fset_option *next_option; /* link to next option */
+};
+
+extern struct t_arraylist *fset_options;
+extern struct t_hashtable *fset_option_max_length_field;
+extern char *fset_option_filter;
+
+extern int fset_option_valid (struct t_fset_option *option);
+extern struct t_fset_option *fset_option_search_by_name (const char *name);
+extern void fset_option_set_filter (const char *filter);
+extern void fset_option_get_options ();
+extern void fset_option_filter_options (const char *search);
+extern struct t_hdata *fset_option_hdata_option_cb (const void *pointer,
+ void *data,
+ const char *hdata_name);
+extern int fset_option_add_to_infolist (struct t_infolist *infolist,
+ struct t_fset_option *option);
+extern void fset_option_print_log ();
+extern int fset_option_init ();
+extern void fset_option_end ();
+
+#endif /* WEECHAT_FSET_OPTION_H */
diff --git a/src/plugins/fset/fset.c b/src/plugins/fset/fset.c
new file mode 100644
index 000000000..6f2907c6f
--- /dev/null
+++ b/src/plugins/fset/fset.c
@@ -0,0 +1,135 @@
+/*
+ * fset.c - Fast set of WeeChat and plugins options
+ *
+ * Copyright (C) 2003-2017 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../weechat-plugin.h"
+#include "fset.h"
+#include "fset-bar-item.h"
+#include "fset-buffer.h"
+#include "fset-command.h"
+#include "fset-config.h"
+#include "fset-info.h"
+#include "fset-mouse.h"
+#include "fset-option.h"
+
+
+WEECHAT_PLUGIN_NAME(FSET_PLUGIN_NAME);
+WEECHAT_PLUGIN_DESCRIPTION(N_("Fast set of WeeChat and plugins options"));
+WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>");
+WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION);
+WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE);
+WEECHAT_PLUGIN_PRIORITY(7500);
+
+struct t_weechat_plugin *weechat_fset_plugin = NULL;
+
+struct t_hdata *fset_hdata_config_file = NULL;
+struct t_hdata *fset_hdata_config_section = NULL;
+struct t_hdata *fset_hdata_config_option = NULL;
+struct t_hdata *fset_hdata_fset_option = NULL;
+
+
+/*
+ * Adds the fset bar.
+ */
+
+void
+fset_add_bar ()
+{
+ weechat_bar_new (FSET_BAR_NAME, "on", "0", "window", "", "top",
+ "horizontal", "vertical", "3", "3",
+ "default", "cyan", "default", "on",
+ FSET_BAR_ITEM_NAME);
+}
+
+/*
+ * Initializes fset plugin.
+ */
+
+int
+weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[])
+{
+ /* make C compiler happy */
+ (void) argc;
+ (void) argv;
+
+ weechat_plugin = plugin;
+
+ fset_hdata_config_file = weechat_hdata_get ("config_file");
+ fset_hdata_config_section = weechat_hdata_get ("config_section");
+ fset_hdata_config_option = weechat_hdata_get ("config_option");
+
+ fset_buffer_init ();
+
+ if (!fset_config_init ())
+ return WEECHAT_RC_ERROR;
+
+ fset_config_read ();
+
+ if (!fset_bar_item_init ())
+ return WEECHAT_RC_ERROR;
+
+ fset_option_init ();
+
+ fset_command_init ();
+
+ if (weechat_config_boolean (fset_config_look_enabled))
+ fset_add_bar ();
+
+ fset_bar_item_update ();
+
+ fset_info_init ();
+
+ fset_hdata_fset_option = weechat_hdata_get ("fset_option");
+
+ weechat_hook_signal ("window_scrolled",
+ &fset_buffer_window_scrolled_cb, NULL, NULL);
+
+ fset_mouse_init ();
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * Ends fset plugin.
+ */
+
+int
+weechat_plugin_end (struct t_weechat_plugin *plugin)
+{
+ /* make C compiler happy */
+ (void) plugin;
+
+ fset_mouse_end ();
+
+ fset_bar_item_end ();
+
+ fset_buffer_end ();
+
+ fset_option_end ();
+
+ fset_config_write ();
+ fset_config_free ();
+
+ return WEECHAT_RC_OK;
+}
diff --git a/src/plugins/fset/fset.h b/src/plugins/fset/fset.h
new file mode 100644
index 000000000..1093b6ac8
--- /dev/null
+++ b/src/plugins/fset/fset.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2003-2017 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef WEECHAT_FSET_H
+#define WEECHAT_FSET_H 1
+
+#define weechat_plugin weechat_fset_plugin
+#define FSET_PLUGIN_NAME "fset"
+
+#define FSET_BAR_NAME "fset"
+
+extern struct t_weechat_plugin *weechat_fset_plugin;
+
+extern struct t_hdata *fset_hdata_config_file;
+extern struct t_hdata *fset_hdata_config_section;
+extern struct t_hdata *fset_hdata_config_option;
+extern struct t_hdata *fset_hdata_fset_option;
+
+#endif /* WEECHAT_FSET_H */
diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h
index a78db2cd6..8dfcff406 100644
--- a/src/plugins/weechat-plugin.h
+++ b/src/plugins/weechat-plugin.h
@@ -26,6 +26,7 @@
extern "C" {
#endif /* __cplusplus */
+#include <stddef.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>