summaryrefslogtreecommitdiff
path: root/src/plugins/typing
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/typing')
-rw-r--r--src/plugins/typing/CMakeLists.txt29
-rw-r--r--src/plugins/typing/Makefile.am35
-rw-r--r--src/plugins/typing/typing-buffer.c198
-rw-r--r--src/plugins/typing/typing-buffer.h60
-rw-r--r--src/plugins/typing/typing-config.c159
-rw-r--r--src/plugins/typing/typing-config.h33
-rw-r--r--src/plugins/typing/typing.c373
-rw-r--r--src/plugins/typing/typing.h44
8 files changed, 931 insertions, 0 deletions
diff --git a/src/plugins/typing/CMakeLists.txt b/src/plugins/typing/CMakeLists.txt
new file mode 100644
index 000000000..74158dc7c
--- /dev/null
+++ b/src/plugins/typing/CMakeLists.txt
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2021 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/>.
+#
+
+add_library(typing MODULE
+ typing.c typing.h
+ typing-buffer.c typing-buffer.h
+ typing-config.c typing-config.h
+)
+set_target_properties(typing PROPERTIES PREFIX "")
+
+target_link_libraries(typing coverage_config)
+
+install(TARGETS typing LIBRARY DESTINATION ${WEECHAT_LIBDIR}/plugins)
diff --git a/src/plugins/typing/Makefile.am b/src/plugins/typing/Makefile.am
new file mode 100644
index 000000000..1c1b8c88a
--- /dev/null
+++ b/src/plugins/typing/Makefile.am
@@ -0,0 +1,35 @@
+#
+# Copyright (C) 2021 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/>.
+#
+
+AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/locale\" $(TYPING_CFLAGS)
+
+libdir = ${weechat_libdir}/plugins
+
+lib_LTLIBRARIES = typing.la
+
+typing_la_SOURCES = typing.c \
+ typing.h \
+ typing-buffer.c \
+ typing-buffer.h \
+ typing-config.c \
+ typing-config.h
+typing_la_LDFLAGS = -module -no-undefined
+typing_la_LIBADD = $(TYPING_LFLAGS)
+
+EXTRA_DIST = CMakeLists.txt
diff --git a/src/plugins/typing/typing-buffer.c b/src/plugins/typing/typing-buffer.c
new file mode 100644
index 000000000..1e47a1418
--- /dev/null
+++ b/src/plugins/typing/typing-buffer.c
@@ -0,0 +1,198 @@
+/*
+ * typing-buffer.c - typing buffer list management
+ *
+ * Copyright (C) 2021 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 <string.h>
+#include <stdio.h>
+
+#include "../weechat-plugin.h"
+#include "typing.h"
+#include "typing-buffer.h"
+
+
+struct t_typing_buffer *typing_buffers = NULL;
+struct t_typing_buffer *last_typing_buffer = NULL;
+
+
+/*
+ * Checks if a typing buffer pointer is valid.
+ *
+ * Returns:
+ * 1: typing buffer exists
+ * 0: typing buffer does not exist
+ */
+
+int
+typing_buffer_valid (struct t_typing_buffer *typing_buffer)
+{
+ struct t_typing_buffer *ptr_typing_buffer;
+
+ if (!typing_buffer)
+ return 0;
+
+ for (ptr_typing_buffer = typing_buffers; ptr_typing_buffer;
+ ptr_typing_buffer = ptr_typing_buffer->next_buffer)
+ {
+ if (ptr_typing_buffer == typing_buffer)
+ return 1;
+ }
+
+ /* typing_buffer not found */
+ return 0;
+}
+
+/*
+ * Adds a new buffer for typing status.
+ *
+ * Returns pointer to new typing buffer, NULL if error.
+ */
+
+struct t_typing_buffer *
+typing_buffer_add (struct t_gui_buffer *buffer)
+{
+ struct t_typing_buffer *new_typing_buffer;
+
+ if (!buffer)
+ return NULL;
+
+ if (weechat_typing_plugin->debug)
+ {
+ weechat_printf_date_tags (NULL, 0, "no_log",
+ "%s: start typing for buffer \"%s\"",
+ TYPING_PLUGIN_NAME,
+ weechat_buffer_get_string (buffer, "name"));
+ }
+
+ new_typing_buffer = malloc (sizeof (*new_typing_buffer));
+ if (new_typing_buffer)
+ {
+ new_typing_buffer->buffer = buffer;
+ new_typing_buffer->status = TYPING_BUFFER_STATUS_OFF;
+ new_typing_buffer->last_typed = 0;
+ new_typing_buffer->last_signal_sent = 0;
+
+ new_typing_buffer->prev_buffer = last_typing_buffer;
+ new_typing_buffer->next_buffer = NULL;
+ if (last_typing_buffer)
+ last_typing_buffer->next_buffer = new_typing_buffer;
+ else
+ typing_buffers = new_typing_buffer;
+ last_typing_buffer = new_typing_buffer;
+ }
+
+ return new_typing_buffer;
+}
+
+/*
+ * Searches for typing buffer by buffer pointer.
+ *
+ * Returns pointer to typing buffer found, NULL if not found.
+ */
+
+struct t_typing_buffer *
+typing_buffer_search_buffer (struct t_gui_buffer *buffer)
+{
+ struct t_typing_buffer *ptr_typing_buffer;
+
+ for (ptr_typing_buffer = typing_buffers; ptr_typing_buffer;
+ ptr_typing_buffer = ptr_typing_buffer->next_buffer)
+ {
+ if (ptr_typing_buffer->buffer == buffer)
+ return ptr_typing_buffer;
+ }
+
+ /* typing buffer not found */
+ return NULL;
+}
+
+/*
+ * Removes a typing buffer from list.
+ */
+
+void
+typing_buffer_free (struct t_typing_buffer *typing_buffer)
+{
+ struct t_typing_buffer *new_typing_buffers;
+ struct t_gui_buffer *ptr_buffer;
+
+ if (!typing_buffer)
+ return;
+
+ ptr_buffer = typing_buffer->buffer;
+
+ /* remove typing buffer */
+ if (last_typing_buffer == typing_buffer)
+ last_typing_buffer = typing_buffer->prev_buffer;
+ if (typing_buffer->prev_buffer)
+ {
+ (typing_buffer->prev_buffer)->next_buffer = typing_buffer->next_buffer;
+ new_typing_buffers = typing_buffers;
+ }
+ else
+ new_typing_buffers = typing_buffer->next_buffer;
+
+ if (typing_buffer->next_buffer)
+ (typing_buffer->next_buffer)->prev_buffer = typing_buffer->prev_buffer;
+
+ free (typing_buffer);
+
+ typing_buffers = new_typing_buffers;
+
+ if (weechat_typing_plugin->debug)
+ {
+ weechat_printf_date_tags (
+ NULL, 0, "no_log",
+ "%s: stop typing for buffer \"%s\"",
+ TYPING_PLUGIN_NAME,
+ weechat_buffer_get_string (ptr_buffer, "name"));
+ }
+}
+
+/*
+ * Adds a typing buffer in an infolist.
+ *
+ * Returns:
+ * 1: OK
+ * 0: error
+ */
+
+int
+typing_buffer_add_to_infolist (struct t_infolist *infolist,
+ struct t_typing_buffer *typing_buffer)
+{
+ struct t_infolist_item *ptr_item;
+
+ if (!infolist || !typing_buffer)
+ return 0;
+
+ ptr_item = weechat_infolist_new_item (infolist);
+ if (!ptr_item)
+ return 0;
+
+ if (!weechat_infolist_new_var_pointer (ptr_item, "buffer", typing_buffer->buffer))
+ return 0;
+
+ return 1;
+}
diff --git a/src/plugins/typing/typing-buffer.h b/src/plugins/typing/typing-buffer.h
new file mode 100644
index 000000000..b02c07cfc
--- /dev/null
+++ b/src/plugins/typing/typing-buffer.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 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_PLUGIN_TYPING_BUFFER_H
+#define WEECHAT_PLUGIN_TYPING_BUFFER_H
+
+#include <stdio.h>
+#include <time.h>
+
+struct t_infolist;
+
+enum t_typing_buffer_status
+{
+ TYPING_BUFFER_STATUS_OFF = 0,
+ TYPING_BUFFER_STATUS_TYPING,
+ TYPING_BUFFER_STATUS_PAUSED,
+ TYPING_BUFFER_STATUS_CLEARED,
+ /* number of typing buffer statuses */
+ TYPING_BUFFER_NUM_STATUSES,
+};
+
+/* own typing status */
+
+struct t_typing_buffer
+{
+ struct t_gui_buffer *buffer; /* pointer to buffer */
+ int status; /* status */
+ time_t last_typed; /* last char typed */
+ time_t last_signal_sent; /* last signal sent */
+ struct t_typing_buffer *prev_buffer; /* link to previous buffer */
+ struct t_typing_buffer *next_buffer; /* link to next buffer */
+};
+
+extern struct t_typing_buffer *typing_buffers;
+extern struct t_typing_buffer *last_typing_buffer;
+
+extern int typing_buffer_valid (struct t_typing_buffer *typing_buffer);
+extern struct t_typing_buffer *typing_buffer_add (struct t_gui_buffer *buffer);
+extern struct t_typing_buffer *typing_buffer_search_buffer (struct t_gui_buffer *buffer);
+extern void typing_buffer_free (struct t_typing_buffer *typing_buffer);
+extern int typing_buffer_add_to_infolist (struct t_infolist *infolist,
+ struct t_typing_buffer *typing_buffer);
+
+#endif /* WEECHAT_PLUGIN_TYPING_BUFFER_H */
diff --git a/src/plugins/typing/typing-config.c b/src/plugins/typing/typing-config.c
new file mode 100644
index 000000000..42d0d1051
--- /dev/null
+++ b/src/plugins/typing/typing-config.c
@@ -0,0 +1,159 @@
+/*
+ * typing-config.c - typing configuration options (file typing.conf)
+ *
+ * Copyright (C) 2021 Sébastien Helleu <flashcode@flashtux.org>
+ *
+ * This file is part of WeeChat, the extensible chat client.
+ *
+ * WeeChat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * WeeChat is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../weechat-plugin.h"
+#include "typing.h"
+#include "typing-config.h"
+
+
+struct t_config_file *typing_config_file = NULL;
+struct t_config_section *typing_config_section_cmd = NULL;
+struct t_config_section *typing_config_section_completion = NULL;
+
+/* typing config, look section */
+
+struct t_config_option *typing_config_look_enabled;
+struct t_config_option *typing_config_look_delay_pause;
+
+
+/*
+ * Reloads typing configuration file.
+ */
+
+int
+typing_config_reload (const void *pointer, void *data,
+ struct t_config_file *config_file)
+{
+ int rc;
+
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+
+ rc = weechat_config_reload (config_file);
+
+ typing_setup_hooks ();
+
+ return rc;
+}
+
+/*
+ * Callback for changes on option "typing.look.enabled".
+ */
+
+void
+typing_config_change_enabled (const void *pointer, void *data,
+ struct t_config_option *option)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) option;
+
+ typing_setup_hooks ();
+}
+
+/*
+ * Initializes typing configuration file.
+ *
+ * Returns:
+ * 1: OK
+ * 0: error
+ */
+
+int
+typing_config_init ()
+{
+ struct t_config_section *ptr_section;
+
+ typing_config_file = weechat_config_new (
+ TYPING_CONFIG_NAME,
+ &typing_config_reload, NULL, NULL);
+ if (!typing_config_file)
+ return 0;
+
+ /* look */
+ ptr_section = weechat_config_new_section (typing_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 (typing_config_file);
+ typing_config_file = NULL;
+ return 0;
+ }
+
+ typing_config_look_enabled = weechat_config_new_option (
+ typing_config_file, ptr_section,
+ "enabled", "boolean",
+ N_("typing enabled"),
+ NULL, 0, 0, "on", NULL, 0,
+ NULL, NULL, NULL,
+ &typing_config_change_enabled, NULL, NULL,
+ NULL, NULL, NULL);
+ typing_config_look_delay_pause = weechat_config_new_option (
+ typing_config_file, ptr_section,
+ "delay_pause", "integer",
+ N_("number of seconds after typing last char: if reached, the typing "
+ "status becomes \"paused\" and no more typing signals are sent"),
+ NULL, 1, 3600, "10", NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ return 1;
+}
+
+/*
+ * Reads typing configuration file.
+ */
+
+int
+typing_config_read ()
+{
+ return weechat_config_read (typing_config_file);
+}
+
+/*
+ * Writes typing configuration file.
+ */
+
+int
+typing_config_write ()
+{
+ return weechat_config_write (typing_config_file);
+}
+
+/*
+ * Frees typing configuration.
+ */
+
+void
+typing_config_free ()
+{
+ weechat_config_free (typing_config_file);
+}
diff --git a/src/plugins/typing/typing-config.h b/src/plugins/typing/typing-config.h
new file mode 100644
index 000000000..e367f724c
--- /dev/null
+++ b/src/plugins/typing/typing-config.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 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_PLUGIN_TYPING_CONFIG_H
+#define WEECHAT_PLUGIN_TYPING_CONFIG_H
+
+#define TYPING_CONFIG_NAME "typing"
+
+extern struct t_config_option *typing_config_look_enabled;
+extern struct t_config_option *typing_config_look_delay_pause;
+
+extern int typing_config_init ();
+extern int typing_config_read ();
+extern int typing_config_write ();
+extern void typing_config_free ();
+
+#endif /* WEECHAT_PLUGIN_TYPING_CONFIG_H */
diff --git a/src/plugins/typing/typing.c b/src/plugins/typing/typing.c
new file mode 100644
index 000000000..b29055e24
--- /dev/null
+++ b/src/plugins/typing/typing.c
@@ -0,0 +1,373 @@
+/*
+ * typing.c - manage typing status of users
+ *
+ * Copyright (C) 2021 Sébastien Helleu <flashcode@flashtux.org>
+ *
+ * This file is part of WeeChat, the extensible chat client.
+ *
+ * WeeChat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * WeeChat is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "../weechat-plugin.h"
+#include "typing.h"
+#include "typing-buffer.h"
+#include "typing-config.h"
+
+
+WEECHAT_PLUGIN_NAME(TYPING_PLUGIN_NAME);
+WEECHAT_PLUGIN_DESCRIPTION(N_("Typing status of users"));
+WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>");
+WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION);
+WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE);
+WEECHAT_PLUGIN_PRIORITY(8000);
+
+struct t_weechat_plugin *weechat_typing_plugin = NULL;
+
+struct t_hook *typing_signal_buffer_closing = NULL;
+struct t_hook *typing_signal_input_text_changed = NULL;
+struct t_hook *typing_modifier_input_text_for_buffer = NULL;
+struct t_hook *typing_timer = NULL;
+
+
+/*
+ * Sends a "typing" signal.
+ *
+ * Returns code of last callback executed.
+ */
+
+int
+typing_send_signal (struct t_typing_buffer *typing_buffer,
+ const char *signal_name)
+{
+ if (weechat_typing_plugin->debug)
+ {
+ weechat_printf (NULL, "%s: sending signal \"%s\" for buffer %s",
+ TYPING_PLUGIN_NAME,
+ signal_name,
+ weechat_buffer_get_string (typing_buffer->buffer,
+ "full_name"));
+ }
+
+ typing_buffer->last_signal_sent = time (NULL);
+ return weechat_hook_signal_send (signal_name,
+ WEECHAT_HOOK_SIGNAL_POINTER,
+ typing_buffer->buffer);
+}
+
+/*
+ * Gets typing buffer, creates it if not existing.
+ */
+
+struct t_typing_buffer *
+typing_get_typing_buffer (struct t_gui_buffer *buffer)
+{
+ struct t_typing_buffer *ptr_typing_buffer;
+
+ ptr_typing_buffer = typing_buffer_search_buffer (buffer);
+ if (ptr_typing_buffer)
+ return ptr_typing_buffer;
+
+ return typing_buffer_add (buffer);
+}
+
+/*
+ * Callback for signal "buffer_closing".
+ */
+
+int
+typing_buffer_closing_signal_cb (const void *pointer, void *data,
+ const char *signal,
+ const char *type_data, void *signal_data)
+{
+ struct t_typing_buffer *ptr_typing_buffer;
+
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) signal;
+ (void) type_data;
+
+ ptr_typing_buffer = typing_buffer_search_buffer (signal_data);
+ if (ptr_typing_buffer)
+ typing_buffer_free (ptr_typing_buffer);
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * Callback for signal "buffer_closing".
+ */
+
+int
+typing_input_text_changed_signal_cb (const void *pointer, void *data,
+ const char *signal,
+ const char *type_data, void *signal_data)
+{
+ int text_search;
+ const char *ptr_input, *ptr_input_for_buffer;
+ struct t_gui_buffer *ptr_buffer;
+ struct t_typing_buffer *ptr_typing_buffer;
+
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) signal;
+ (void) type_data;
+
+ ptr_buffer = (struct t_gui_buffer *)signal_data;
+
+ /* ignore any change in input if the user is searching text in the buffer */
+ text_search = weechat_buffer_get_integer (ptr_buffer, "text_search");
+ if (text_search != 0)
+ return WEECHAT_RC_OK;
+
+ ptr_input = weechat_buffer_get_string (ptr_buffer, "input");
+
+ if (ptr_input && ptr_input[0])
+ {
+ /* input is a command? ignore it */
+ ptr_input_for_buffer = weechat_string_input_for_buffer (ptr_input);
+ if (!ptr_input_for_buffer)
+ return WEECHAT_RC_OK;
+
+ ptr_typing_buffer = typing_buffer_search_buffer (ptr_buffer);
+ if (!ptr_typing_buffer)
+ ptr_typing_buffer = typing_buffer_add (ptr_buffer);
+ if (!ptr_typing_buffer)
+ return WEECHAT_RC_OK;
+ ptr_typing_buffer->status = TYPING_BUFFER_STATUS_TYPING;
+ ptr_typing_buffer->last_typed = time (NULL);
+ }
+ else
+ {
+ /* user was typing something? */
+ ptr_typing_buffer = typing_buffer_search_buffer (ptr_buffer);
+ if (ptr_typing_buffer
+ && ((ptr_typing_buffer->status == TYPING_BUFFER_STATUS_TYPING)
+ || (ptr_typing_buffer->status == TYPING_BUFFER_STATUS_PAUSED)))
+ {
+ /*
+ * input cleared: maybe something was sent, not sure, so we just
+ * set the status to "cleared", a signal can be sent later
+ * in timer
+ */
+ ptr_typing_buffer->status = TYPING_BUFFER_STATUS_CLEARED;
+ }
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * Callback for modifier "input_text_for_buffer".
+ */
+
+char *
+typing_input_text_for_buffer_modifier_cb (const void *pointer,
+ void *data,
+ const char *modifier,
+ const char *modifier_data,
+ const char *string)
+{
+ int rc, text_search;
+ unsigned long value;
+ const char *ptr_input_for_buffer;
+ struct t_gui_buffer *ptr_buffer;
+ struct t_typing_buffer *ptr_typing_buffer;
+
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) modifier;
+ (void) string;
+
+ rc = sscanf (modifier_data, "%lx", &value);
+ if ((rc == EOF) || (rc == 0))
+ return NULL;
+ ptr_buffer = (struct t_gui_buffer *)value;
+
+ /* ignore any change in input if the user is searching text in the buffer */
+ text_search = weechat_buffer_get_integer (ptr_buffer, "text_search");
+ if (text_search != 0)
+ return WEECHAT_RC_OK;
+
+ /* string is a command? ignore it */
+ ptr_input_for_buffer = weechat_string_input_for_buffer (string);
+ if (!ptr_input_for_buffer)
+ return NULL;
+
+ ptr_typing_buffer = typing_buffer_search_buffer (ptr_buffer);
+ if (!ptr_typing_buffer)
+ ptr_typing_buffer = typing_buffer_add (ptr_buffer);
+ if (!ptr_typing_buffer)
+ return NULL;
+
+ typing_send_signal (ptr_typing_buffer, "typing_sent");
+ typing_buffer_free (ptr_typing_buffer);
+
+ return NULL;
+}
+
+/*
+ * Callback for modifier "input_text_for_buffer".
+ */
+
+int
+typing_timer_cb (const void *pointer,
+ void *data,
+ int remaining_calls)
+{
+ time_t time_now;
+ int delay_pause;
+ const char *ptr_input, *ptr_input_for_buffer;
+ struct t_typing_buffer *ptr_typing_buffer, *ptr_next_typing_buffer;
+
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) remaining_calls;
+
+ delay_pause = weechat_config_integer (typing_config_look_delay_pause);
+
+ time_now = time (NULL);
+ ptr_typing_buffer = typing_buffers;
+ while (ptr_typing_buffer)
+ {
+ ptr_next_typing_buffer = ptr_typing_buffer->next_buffer;
+
+ if (ptr_typing_buffer->status == TYPING_BUFFER_STATUS_TYPING)
+ {
+ ptr_input = weechat_buffer_get_string (ptr_typing_buffer->buffer,
+ "input");
+ ptr_input_for_buffer = weechat_string_input_for_buffer (ptr_input);
+ if (ptr_input_for_buffer)
+ {
+ /* check if typing is paused */
+ if (ptr_typing_buffer->last_typed < time_now - delay_pause)
+ {
+ ptr_typing_buffer->status = TYPING_BUFFER_STATUS_PAUSED;
+ typing_send_signal (ptr_typing_buffer, "typing_paused");
+ typing_buffer_free (ptr_typing_buffer);
+ }
+ else
+ {
+ typing_send_signal (ptr_typing_buffer, "typing_active");
+ }
+ }
+ else
+ {
+ typing_send_signal (ptr_typing_buffer, "typing_cleared");
+ typing_buffer_free (ptr_typing_buffer);
+ }
+ }
+ else if (ptr_typing_buffer->status == TYPING_BUFFER_STATUS_CLEARED)
+ {
+ typing_send_signal (ptr_typing_buffer, "typing_cleared");
+ typing_buffer_free (ptr_typing_buffer);
+ }
+
+ ptr_typing_buffer = ptr_next_typing_buffer;
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * Creates or removes hooks, according to option typing.look.enabled.
+ */
+
+void
+typing_setup_hooks ()
+{
+ if (weechat_config_boolean (typing_config_look_enabled))
+ {
+ if (!typing_signal_buffer_closing)
+ {
+ if (weechat_typing_plugin->debug >= 2)
+ weechat_printf (NULL, "%s: creating hooks", TYPING_PLUGIN_NAME);
+ typing_signal_buffer_closing = weechat_hook_signal (
+ "buffer_closing",
+ &typing_buffer_closing_signal_cb, NULL, NULL);
+ typing_signal_input_text_changed = weechat_hook_signal (
+ "input_text_changed",
+ &typing_input_text_changed_signal_cb, NULL, NULL);
+ typing_modifier_input_text_for_buffer = weechat_hook_modifier (
+ "input_text_for_buffer",
+ &typing_input_text_for_buffer_modifier_cb, NULL, NULL);
+ typing_timer = weechat_hook_timer (
+ 1000, 0, 0,
+ &typing_timer_cb, NULL, NULL);
+ }
+ }
+ else
+ {
+ if (typing_signal_buffer_closing)
+ {
+ if (weechat_typing_plugin->debug >= 2)
+ weechat_printf (NULL, "%s: removing hooks", TYPING_PLUGIN_NAME);
+ weechat_unhook (typing_signal_buffer_closing);
+ typing_signal_buffer_closing = NULL;
+ weechat_unhook (typing_signal_input_text_changed);
+ typing_signal_input_text_changed = NULL;
+ weechat_unhook (typing_modifier_input_text_for_buffer);
+ typing_modifier_input_text_for_buffer = NULL;
+ weechat_unhook (typing_timer);
+ typing_timer = NULL;
+ }
+ }
+}
+
+/*
+ * Initializes typing 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;
+
+ if (!typing_config_init ())
+ return WEECHAT_RC_ERROR;
+
+ typing_config_read ();
+
+ typing_setup_hooks ();
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * Ends typing plugin.
+ */
+
+int
+weechat_plugin_end (struct t_weechat_plugin *plugin)
+{
+ /* make C compiler happy */
+ (void) plugin;
+
+ typing_config_write ();
+ typing_config_free ();
+
+ return WEECHAT_RC_OK;
+}
diff --git a/src/plugins/typing/typing.h b/src/plugins/typing/typing.h
new file mode 100644
index 000000000..3daa7a4d4
--- /dev/null
+++ b/src/plugins/typing/typing.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 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_PLUGIN_TYPING_H
+#define WEECHAT_PLUGIN_TYPING_H
+
+#define weechat_plugin weechat_typing_plugin
+#define TYPING_PLUGIN_NAME "typing"
+
+struct t_typing
+{
+ struct t_hook *hook; /* command hook */
+ char *name; /* typing name */
+ char *command; /* typing command */
+ char *completion; /* completion for typing (if not set,*/
+ /* uses completion of target cmd) */
+ int running; /* 1 if typing is running */
+ struct t_typing *prev_typing; /* link to previous typing */
+ struct t_typing *next_typing; /* link to next typing */
+};
+
+extern struct t_typing *typing_list;
+
+extern struct t_weechat_plugin *weechat_typing_plugin;
+
+extern void typing_setup_hooks ();
+
+#endif /* WEECHAT_PLUGIN_TYPING_H */