diff options
Diffstat (limited to 'src/plugins/typing/typing.c')
-rw-r--r-- | src/plugins/typing/typing.c | 315 |
1 files changed, 272 insertions, 43 deletions
diff --git a/src/plugins/typing/typing.c b/src/plugins/typing/typing.c index a061591e2..033ac5838 100644 --- a/src/plugins/typing/typing.c +++ b/src/plugins/typing/typing.c @@ -26,6 +26,7 @@ #include "../weechat-plugin.h" #include "typing.h" +#include "typing-bar-item.h" #include "typing-config.h" #include "typing-status.h" @@ -43,6 +44,10 @@ 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; +struct t_hook *typing_signal_typing_set_nick = NULL; +struct t_hook *typing_signal_typing_reset_buffer = NULL; + +int typing_update_item = 0; /* @@ -52,9 +57,7 @@ struct t_hook *typing_timer = NULL; */ int -typing_send_signal (struct t_gui_buffer *buffer, - struct t_typing_status *typing_status, - const char *signal_name) +typing_send_signal (struct t_gui_buffer *buffer, const char *signal_name) { if (weechat_typing_plugin->debug) { @@ -64,7 +67,6 @@ typing_send_signal (struct t_gui_buffer *buffer, weechat_buffer_get_string (buffer, "full_name")); } - typing_status->last_signal_sent = time (NULL); return weechat_hook_signal_send (signal_name, WEECHAT_HOOK_SIGNAL_POINTER, buffer); @@ -86,6 +88,7 @@ typing_buffer_closing_signal_cb (const void *pointer, void *data, (void) type_data; weechat_hashtable_remove (typing_status_self, signal_data); + weechat_hashtable_remove (typing_status_nicks, signal_data); return WEECHAT_RC_OK; } @@ -126,30 +129,33 @@ typing_input_text_changed_signal_cb (const void *pointer, void *data, if (!ptr_input_for_buffer) return WEECHAT_RC_OK; - ptr_typing_status = weechat_hashtable_get (typing_status_self, - ptr_buffer); + ptr_typing_status = typing_status_self_search (ptr_buffer); if (!ptr_typing_status) - ptr_typing_status = typing_status_add (ptr_buffer); + { + ptr_typing_status = typing_status_self_add ( + ptr_buffer, + TYPING_STATUS_STATE_TYPING, + 0); + } if (!ptr_typing_status) return WEECHAT_RC_OK; - ptr_typing_status->status = TYPING_STATUS_STATUS_TYPING; + ptr_typing_status->state = TYPING_STATUS_STATE_TYPING; ptr_typing_status->last_typed = time (NULL); } else { /* user was typing something? */ - ptr_typing_status = weechat_hashtable_get (typing_status_self, - ptr_buffer); + ptr_typing_status = typing_status_self_search (ptr_buffer); if (ptr_typing_status - && ((ptr_typing_status->status == TYPING_STATUS_STATUS_TYPING) - || (ptr_typing_status->status == TYPING_STATUS_STATUS_PAUSED))) + && ((ptr_typing_status->state == TYPING_STATUS_STATE_TYPING) + || (ptr_typing_status->state == TYPING_STATUS_STATE_PAUSED))) { /* * input cleared: maybe something was sent, not sure, so we just - * set the status to "cleared", a signal can be sent later + * set the state to "cleared", a signal can be sent later * in timer */ - ptr_typing_status->status = TYPING_STATUS_STATUS_CLEARED; + ptr_typing_status->state = TYPING_STATUS_STATE_CLEARED; } } @@ -194,13 +200,17 @@ typing_input_text_for_buffer_modifier_cb (const void *pointer, if (!ptr_input_for_buffer) return NULL; - ptr_typing_status = weechat_hashtable_get (typing_status_self, ptr_buffer); + ptr_typing_status = typing_status_self_search (ptr_buffer); if (!ptr_typing_status) - ptr_typing_status = typing_status_add (ptr_buffer); + { + ptr_typing_status = typing_status_self_add (ptr_buffer, + TYPING_STATUS_STATE_OFF, + 0); + } if (!ptr_typing_status) return NULL; - typing_send_signal (ptr_buffer, ptr_typing_status, "typing_sent"); + typing_send_signal (ptr_buffer, "typing_self_sent"); weechat_hashtable_remove (typing_status_self, ptr_buffer); return NULL; @@ -212,73 +222,251 @@ typing_input_text_for_buffer_modifier_cb (const void *pointer, */ void -typing_status_self_map_cb (void *data, - struct t_hashtable *hashtable, - const void *key, const void *value) +typing_status_self_status_map_cb (void *data, + struct t_hashtable *hashtable, + const void *key, const void *value) { struct t_gui_buffer *ptr_buffer; struct t_typing_status *ptr_typing_status; const char *ptr_input, *ptr_input_for_buffer; + time_t current_time; int delay_pause; - /* make C compiler happy */ - (void) data; + current_time = *((time_t *)data); ptr_buffer = (struct t_gui_buffer *)key; ptr_typing_status = (struct t_typing_status *)value; - if (ptr_typing_status->status == TYPING_STATUS_STATUS_TYPING) + if (!ptr_buffer || !ptr_typing_status) + return; + + if (ptr_typing_status->state == TYPING_STATUS_STATE_TYPING) { ptr_input = weechat_buffer_get_string (ptr_buffer, "input"); ptr_input_for_buffer = weechat_string_input_for_buffer (ptr_input); if (ptr_input_for_buffer) { /* check if typing is paused */ - delay_pause = weechat_config_integer (typing_config_look_delay_pause); - if (ptr_typing_status->last_typed < time (NULL) - delay_pause) + delay_pause = weechat_config_integer (typing_config_look_delay_set_paused); + if (ptr_typing_status->last_typed < current_time - delay_pause) { - ptr_typing_status->status = TYPING_STATUS_STATUS_PAUSED; - typing_send_signal (ptr_buffer, ptr_typing_status, - "typing_paused"); + ptr_typing_status->state = TYPING_STATUS_STATE_PAUSED; + typing_send_signal (ptr_buffer, "typing_self_paused"); weechat_hashtable_remove (hashtable, ptr_buffer); } else { - typing_send_signal (ptr_buffer, ptr_typing_status, - "typing_active"); + typing_send_signal (ptr_buffer, "typing_self_typing"); } } else { - typing_send_signal (ptr_buffer, ptr_typing_status, - "typing_cleared"); + typing_send_signal (ptr_buffer, "typing_self_cleared"); weechat_hashtable_remove (hashtable, ptr_buffer); } } - else if (ptr_typing_status->status == TYPING_STATUS_STATUS_CLEARED) + else if (ptr_typing_status->state == TYPING_STATUS_STATE_CLEARED) { - typing_send_signal (ptr_buffer, ptr_typing_status, - "typing_cleared"); + typing_send_signal (ptr_buffer, "typing_self_cleared"); weechat_hashtable_remove (hashtable, ptr_buffer); } } /* - * Callback for modifier "input_text_for_buffer". + * Callback called periodically (via a timer) for each entry in hashtable + * "typing_status_nicks". + */ + +void +typing_status_nicks_status_map_cb (void *data, + struct t_hashtable *hashtable, + const void *key, const void *value) +{ + const char *ptr_nick; + struct t_typing_status *ptr_typing_status; + time_t current_time; + int delay_purge_pause, delay_purge_typing; + + current_time = *((time_t *)data); + + ptr_nick = (const char *)key; + ptr_typing_status = (struct t_typing_status *)value; + + if (!ptr_nick || !ptr_typing_status) + return; + + delay_purge_pause = weechat_config_integer ( + typing_config_look_delay_purge_paused); + delay_purge_typing = weechat_config_integer ( + typing_config_look_delay_purge_typing); + + if (((ptr_typing_status->state == TYPING_STATUS_STATE_PAUSED) + && (ptr_typing_status->last_typed < current_time - delay_purge_pause)) + || ((ptr_typing_status->state == TYPING_STATUS_STATE_TYPING) + && (ptr_typing_status->last_typed < current_time - delay_purge_typing))) + { + weechat_hashtable_remove (hashtable, key); + typing_update_item = 1; + } +} + +/* + * Callback called periodically (via a timer) for each entry in hashtable + * "typing_status_nicks". + */ + +void +typing_status_nicks_hash_map_cb (void *data, + struct t_hashtable *hashtable, + const void *key, const void *value) +{ + struct t_hashtable *ptr_nicks; + + ptr_nicks = (struct t_hashtable *)value; + + if (!ptr_nicks) + return; + + weechat_hashtable_map (ptr_nicks, + &typing_status_nicks_status_map_cb, + data); + + /* no more nicks for the buffer? then remove the buffer */ + if (weechat_hashtable_get_integer (ptr_nicks, "items_count") == 0) + weechat_hashtable_remove (hashtable, key); +} + +/* + * Typing timer used to send continuously the self typing status. */ int -typing_timer_cb (const void *pointer, - void *data, - int remaining_calls) +typing_timer_cb (const void *pointer, void *data, int remaining_calls) { + time_t current_time; + /* make C compiler happy */ (void) pointer; (void) data; (void) remaining_calls; + typing_update_item = 0; + current_time = time (NULL); + weechat_hashtable_map (typing_status_self, - &typing_status_self_map_cb, NULL); + &typing_status_self_status_map_cb, ¤t_time); + weechat_hashtable_map (typing_status_nicks, + &typing_status_nicks_hash_map_cb, ¤t_time); + + if (typing_update_item) + weechat_bar_item_update (TYPING_BAR_ITEM_NAME); + + return WEECHAT_RC_OK; +} + +/* + * Callback for signal "typing_set_nick". + */ + +int +typing_typing_set_nick_signal_cb (const void *pointer, void *data, + const char *signal, + const char *type_data, void *signal_data) +{ + char **items; + int num_items, rc, state, updated; + unsigned long value; + struct t_gui_buffer *ptr_buffer; + struct t_typing_status *ptr_typing_status; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) signal; + (void) type_data; + + items = weechat_string_split ((const char *)signal_data, ";", NULL, + 0, 3, &num_items); + if (!items || (num_items != 3)) + goto end; + + rc = sscanf (items[0], "%lx", &value); + if ((rc == EOF) || (rc == 0)) + goto end; + ptr_buffer = (struct t_gui_buffer *)value; + if (!ptr_buffer) + goto end; + + state = typing_status_search_state (items[1]); + if (state < 0) + goto end; + + if (!items[2][0]) + goto end; + + updated = 0; + ptr_typing_status = typing_status_nick_search (ptr_buffer, items[2]); + if ((state == TYPING_STATUS_STATE_TYPING) + || (state == TYPING_STATUS_STATE_PAUSED)) + { + if (ptr_typing_status) + { + if (ptr_typing_status->state != state) + updated = 1; + ptr_typing_status->state = state; + ptr_typing_status->last_typed = time (NULL); + } + else + { + typing_status_nick_add (ptr_buffer, items[2], state, time (NULL)); + updated = 1; + } + } + else + { + if (ptr_typing_status) + updated = 1; + typing_status_nick_remove (ptr_buffer, items[2]); + } + + if (updated) + weechat_bar_item_update (TYPING_BAR_ITEM_NAME); + +end: + if (items) + weechat_string_free_split (items); + + return WEECHAT_RC_OK; +} + +/* + * Callback for signal "typing_reset_buffer". + */ + +int +typing_typing_reset_buffer_signal_cb (const void *pointer, void *data, + const char *signal, + const char *type_data, void *signal_data) +{ + int items_count; + struct t_gui_buffer *ptr_buffer; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) signal; + (void) type_data; + + ptr_buffer = (struct t_gui_buffer *)signal_data; + + if (!typing_status_nicks) + return WEECHAT_RC_OK; + + items_count = weechat_hashtable_get_integer (typing_status_nicks, + "items_count"); + weechat_hashtable_remove (typing_status_nicks, ptr_buffer); + if (items_count > 0) + weechat_bar_item_update (TYPING_BAR_ITEM_NAME); return WEECHAT_RC_OK; } @@ -290,12 +478,15 @@ typing_timer_cb (const void *pointer, void typing_setup_hooks () { - if (weechat_config_boolean (typing_config_look_enabled)) + if (weechat_config_boolean (typing_config_look_enabled_self)) { if (!typing_signal_buffer_closing) { if (weechat_typing_plugin->debug >= 2) - weechat_printf (NULL, "%s: creating hooks", TYPING_PLUGIN_NAME); + { + weechat_printf (NULL, "%s: creating hooks (self)", + TYPING_PLUGIN_NAME); + } typing_signal_buffer_closing = weechat_hook_signal ( "buffer_closing", &typing_buffer_closing_signal_cb, NULL, NULL); @@ -315,7 +506,10 @@ typing_setup_hooks () if (typing_signal_buffer_closing) { if (weechat_typing_plugin->debug >= 2) - weechat_printf (NULL, "%s: removing hooks", TYPING_PLUGIN_NAME); + { + weechat_printf (NULL, "%s: removing hooks (self)", + TYPING_PLUGIN_NAME); + } weechat_unhook (typing_signal_buffer_closing); typing_signal_buffer_closing = NULL; weechat_unhook (typing_signal_input_text_changed); @@ -326,6 +520,39 @@ typing_setup_hooks () typing_timer = NULL; } } + + if (weechat_config_boolean (typing_config_look_enabled_nicks)) + { + if (!typing_signal_typing_set_nick) + { + if (weechat_typing_plugin->debug >= 2) + { + weechat_printf (NULL, "%s: creating hooks (nicks)", + TYPING_PLUGIN_NAME); + } + typing_signal_typing_set_nick = weechat_hook_signal ( + "typing_set_nick", + &typing_typing_set_nick_signal_cb, NULL, NULL); + typing_signal_typing_reset_buffer = weechat_hook_signal ( + "typing_reset_buffer", + &typing_typing_reset_buffer_signal_cb, NULL, NULL); + } + } + else + { + if (typing_signal_typing_set_nick) + { + if (weechat_typing_plugin->debug >= 2) + { + weechat_printf (NULL, "%s: removing hooks (nicks)", + TYPING_PLUGIN_NAME); + } + weechat_unhook (typing_signal_typing_set_nick); + typing_signal_typing_set_nick = NULL; + weechat_unhook (typing_signal_typing_reset_buffer); + typing_signal_typing_reset_buffer = NULL; + } + } } /* @@ -348,6 +575,8 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) typing_setup_hooks (); + typing_bar_item_init (); + return WEECHAT_RC_OK; } |