diff options
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/plugins/Makefile.am | 5 | ||||
-rw-r--r-- | src/plugins/alias/alias.c | 2 | ||||
-rw-r--r-- | src/plugins/buflist/buflist.c | 2 | ||||
-rw-r--r-- | src/plugins/charset/charset.c | 2 | ||||
-rw-r--r-- | src/plugins/exec/exec.c | 2 | ||||
-rw-r--r-- | src/plugins/fifo/fifo.c | 2 | ||||
-rw-r--r-- | src/plugins/logger/logger-buffer.h | 2 | ||||
-rw-r--r-- | src/plugins/logger/logger.c | 2 | ||||
-rw-r--r-- | src/plugins/spell/spell.c | 2 | ||||
-rw-r--r-- | src/plugins/trigger/trigger.c | 2 | ||||
-rw-r--r-- | src/plugins/typing/CMakeLists.txt | 29 | ||||
-rw-r--r-- | src/plugins/typing/Makefile.am | 35 | ||||
-rw-r--r-- | src/plugins/typing/typing-buffer.c | 198 | ||||
-rw-r--r-- | src/plugins/typing/typing-buffer.h | 60 | ||||
-rw-r--r-- | src/plugins/typing/typing-config.c | 159 | ||||
-rw-r--r-- | src/plugins/typing/typing-config.h | 33 | ||||
-rw-r--r-- | src/plugins/typing/typing.c | 373 | ||||
-rw-r--r-- | src/plugins/typing/typing.h | 44 |
19 files changed, 949 insertions, 9 deletions
diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index eec98270c..44b6544b0 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -184,6 +184,10 @@ if(ENABLE_TRIGGER) add_subdirectory(trigger) endif() +if(ENABLE_TYPING) + add_subdirectory(typing) +endif() + if(ENABLE_XFER) add_subdirectory(xfer) endif() diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index be916ba28..5b885ea38 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -121,6 +121,10 @@ if PLUGIN_TRIGGER trigger_dir = trigger endif +if PLUGIN_TYPING +typing_dir = typing +endif + if PLUGIN_XFER xfer_dir = xfer endif @@ -146,6 +150,7 @@ SUBDIRS = . \ $(php_dir) \ $(spell_dir) \ $(trigger_dir) \ + $(typing_dir) \ $(xfer_dir) EXTRA_DIST = CMakeLists.txt diff --git a/src/plugins/alias/alias.c b/src/plugins/alias/alias.c index c418c5d42..23771c68e 100644 --- a/src/plugins/alias/alias.c +++ b/src/plugins/alias/alias.c @@ -36,7 +36,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Alias commands")); WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(10000); +WEECHAT_PLUGIN_PRIORITY(11000); #define ALIAS_IS_ARG_NUMBER(number) ((number >= '1') && (number <= '9')) diff --git a/src/plugins/buflist/buflist.c b/src/plugins/buflist/buflist.c index a87cfb856..5148a3cf1 100644 --- a/src/plugins/buflist/buflist.c +++ b/src/plugins/buflist/buflist.c @@ -38,7 +38,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Buffers list")); WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(9000); +WEECHAT_PLUGIN_PRIORITY(10000); struct t_weechat_plugin *weechat_buflist_plugin = NULL; diff --git a/src/plugins/charset/charset.c b/src/plugins/charset/charset.c index 90f1e8f9c..59ab8097d 100644 --- a/src/plugins/charset/charset.c +++ b/src/plugins/charset/charset.c @@ -37,7 +37,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Charset conversions")); WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(15000); +WEECHAT_PLUGIN_PRIORITY(16000); #define CHARSET_CONFIG_NAME "charset" diff --git a/src/plugins/exec/exec.c b/src/plugins/exec/exec.c index 04a59bcd4..f90ab5bf1 100644 --- a/src/plugins/exec/exec.c +++ b/src/plugins/exec/exec.c @@ -37,7 +37,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Execution of external commands in WeeChat")); WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(13000); +WEECHAT_PLUGIN_PRIORITY(14000); struct t_weechat_plugin *weechat_exec_plugin = NULL; diff --git a/src/plugins/fifo/fifo.c b/src/plugins/fifo/fifo.c index d9d8f3ac7..9047525da 100644 --- a/src/plugins/fifo/fifo.c +++ b/src/plugins/fifo/fifo.c @@ -42,7 +42,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("FIFO pipe for remote control")); WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(8000); +WEECHAT_PLUGIN_PRIORITY(9000); struct t_weechat_plugin *weechat_fifo_plugin = NULL; #define weechat_plugin weechat_fifo_plugin diff --git a/src/plugins/logger/logger-buffer.h b/src/plugins/logger/logger-buffer.h index 48c50ca4c..68b11f571 100644 --- a/src/plugins/logger/logger-buffer.h +++ b/src/plugins/logger/logger-buffer.h @@ -46,7 +46,7 @@ extern struct t_logger_buffer *logger_buffers; extern struct t_logger_buffer *last_logger_buffer; extern int logger_buffer_valid (struct t_logger_buffer *logger_buffer); -extern struct t_logger_buffer *logger_buffer_add (struct t_gui_buffer *, +extern struct t_logger_buffer *logger_buffer_add (struct t_gui_buffer *buffer, int log_level); extern struct t_logger_buffer *logger_buffer_search_buffer (struct t_gui_buffer *buffer); extern struct t_logger_buffer *logger_buffer_search_log_filename (const char *log_filename); diff --git a/src/plugins/logger/logger.c b/src/plugins/logger/logger.c index fae9c17b3..fc0483967 100644 --- a/src/plugins/logger/logger.c +++ b/src/plugins/logger/logger.c @@ -47,7 +47,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Log buffers to files")); WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(14000); +WEECHAT_PLUGIN_PRIORITY(15000); struct t_weechat_plugin *weechat_logger_plugin = NULL; diff --git a/src/plugins/spell/spell.c b/src/plugins/spell/spell.c index 38e6ef5a8..8244d003e 100644 --- a/src/plugins/spell/spell.c +++ b/src/plugins/spell/spell.c @@ -48,7 +48,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Spell checker for input")); WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(11000); +WEECHAT_PLUGIN_PRIORITY(12000); struct t_weechat_plugin *weechat_spell_plugin = NULL; diff --git a/src/plugins/trigger/trigger.c b/src/plugins/trigger/trigger.c index 3b3885161..4e88a2978 100644 --- a/src/plugins/trigger/trigger.c +++ b/src/plugins/trigger/trigger.c @@ -38,7 +38,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Text replacement and command execution on events WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(12000); +WEECHAT_PLUGIN_PRIORITY(13000); struct t_weechat_plugin *weechat_trigger_plugin = NULL; 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 */ |