diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/wee-command.c | 51 | ||||
-rw-r--r-- | src/core/wee-config.c | 108 | ||||
-rw-r--r-- | src/core/wee-hook.c | 565 | ||||
-rw-r--r-- | src/core/wee-hook.h | 24 | ||||
-rw-r--r-- | src/core/wee-util.c | 41 | ||||
-rw-r--r-- | src/core/wee-util.h | 2 | ||||
-rw-r--r-- | src/core/weechat.c | 1 | ||||
-rw-r--r-- | src/gui/curses/gui-curses-infobar.c | 55 | ||||
-rw-r--r-- | src/gui/curses/gui-curses-main.c | 140 | ||||
-rw-r--r-- | src/gui/gtk/gui-gtk-infobar.c | 27 | ||||
-rw-r--r-- | src/gui/gui-completion.c | 16 | ||||
-rw-r--r-- | src/gui/gui-infobar.c | 10 | ||||
-rw-r--r-- | src/gui/gui-infobar.h | 4 | ||||
-rw-r--r-- | src/gui/gui-keyboard.c | 14 | ||||
-rw-r--r-- | src/plugins/demo/demo.c | 28 | ||||
-rw-r--r-- | src/plugins/plugin-api.c | 16 | ||||
-rw-r--r-- | src/plugins/plugin-api.h | 2 | ||||
-rw-r--r-- | src/plugins/weechat-plugin.h | 8 |
18 files changed, 727 insertions, 385 deletions
diff --git a/src/core/wee-command.c b/src/core/wee-command.c index c2b9b9d78..77c70e3a8 100644 --- a/src/core/wee-command.c +++ b/src/core/wee-command.c @@ -494,10 +494,10 @@ command_help (void *data, void *buffer, case 1: gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("%s internal commands:"), PACKAGE_NAME); - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_COMMAND]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->type == HOOK_TYPE_COMMAND) + if (!ptr_hook->deleted && !ptr_hook->plugin && HOOK_COMMAND(ptr_hook, command) && HOOK_COMMAND(ptr_hook, command)[0]) @@ -522,10 +522,10 @@ command_help (void *data, void *buffer, } gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("Other commands:")); - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_COMMAND]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->type == HOOK_TYPE_COMMAND) + if (!ptr_hook->deleted && ptr_hook->plugin && HOOK_COMMAND(ptr_hook, command) && HOOK_COMMAND(ptr_hook, command)[0]) @@ -550,10 +550,10 @@ command_help (void *data, void *buffer, } break; case 2: - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_COMMAND]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->type == HOOK_TYPE_COMMAND) + if (!ptr_hook->deleted && HOOK_COMMAND(ptr_hook, command) && HOOK_COMMAND(ptr_hook, command)[0] && (HOOK_COMMAND(ptr_hook, level) == 0) @@ -886,11 +886,10 @@ command_plugin_list (char *name, int full) { /* commands hooked */ hook_found = 0; - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_COMMAND]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->plugin == ptr_plugin) - && (ptr_hook->type == HOOK_TYPE_COMMAND)) + if (!ptr_hook->deleted && (ptr_hook->plugin == ptr_plugin)) { if (!hook_found) gui_chat_printf (NULL, _(" commands hooked:")); @@ -907,11 +906,10 @@ command_plugin_list (char *name, int full) /* timers hooked */ hook_found = 0; - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_TIMER]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->plugin == ptr_plugin) - && (ptr_hook->type == HOOK_TYPE_TIMER)) + if (!ptr_hook->deleted && (ptr_hook->plugin == ptr_plugin)) { if (!hook_found) gui_chat_printf (NULL, _(" timers hooked:")); @@ -949,11 +947,10 @@ command_plugin_list (char *name, int full) /* fd hooked */ hook_found = 0; - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_FD]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->plugin == ptr_plugin) - && (ptr_hook->type == HOOK_TYPE_FD)) + if (!ptr_hook->deleted && (ptr_hook->plugin == ptr_plugin)) { if (!hook_found) gui_chat_printf (NULL, @@ -968,11 +965,10 @@ command_plugin_list (char *name, int full) /* prints hooked */ hook_found = 0; - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_PRINT]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->plugin == ptr_plugin) - && (ptr_hook->type == HOOK_TYPE_PRINT)) + if (!ptr_hook->deleted && (ptr_hook->plugin == ptr_plugin)) { if (!hook_found) gui_chat_printf (NULL, _(" prints hooked:")); @@ -994,11 +990,10 @@ command_plugin_list (char *name, int full) /* signals hooked */ hook_found = 0; - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_SIGNAL]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->plugin == ptr_plugin) - && (ptr_hook->type == HOOK_TYPE_SIGNAL)) + if (!ptr_hook->deleted && (ptr_hook->plugin == ptr_plugin)) { if (!hook_found) gui_chat_printf (NULL, _(" signals hooked:")); @@ -1012,11 +1007,10 @@ command_plugin_list (char *name, int full) /* config options hooked */ hook_found = 0; - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_CONFIG]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->plugin == ptr_plugin) - && (ptr_hook->type == HOOK_TYPE_CONFIG)) + if (!ptr_hook->deleted && (ptr_hook->plugin == ptr_plugin)) { if (!hook_found) gui_chat_printf (NULL, @@ -1034,11 +1028,10 @@ command_plugin_list (char *name, int full) /* completion hooked */ hook_found = 0; - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_COMPLETION]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->plugin == ptr_plugin) - && (ptr_hook->type == HOOK_TYPE_COMPLETION)) + if (!ptr_hook->deleted && (ptr_hook->plugin == ptr_plugin)) { if (!hook_found) gui_chat_printf (NULL, @@ -2067,10 +2060,10 @@ command_print_stdout () { struct t_hook *ptr_hook; - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_COMMAND]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->type == HOOK_TYPE_COMMAND) + if (!ptr_hook->deleted && HOOK_COMMAND(ptr_hook, command) && HOOK_COMMAND(ptr_hook, command)[0] && !ptr_hook->plugin) diff --git a/src/core/wee-config.c b/src/core/wee-config.c index d8dc7b43b..cc89254ae 100644 --- a/src/core/wee-config.c +++ b/src/core/wee-config.c @@ -36,15 +36,19 @@ #include "weechat.h" #include "wee-config.h" #include "wee-config-file.h" +#include "wee-hook.h" #include "wee-log.h" #include "wee-util.h" #include "wee-list.h" +#include "wee-string.h" #include "../gui/gui-chat.h" #include "../gui/gui-color.h" #include "../gui/gui-hotlist.h" +#include "../gui/gui-infobar.h" #include "../gui/gui-keyboard.h" #include "../gui/gui-status.h" #include "../gui/gui-window.h" +#include "../plugins/plugin.h" struct t_config_file *weechat_config_file = NULL; @@ -178,6 +182,10 @@ struct t_config_option *config_plugins_path; struct t_config_option *config_plugins_autoload; struct t_config_option *config_plugins_extension; +/* hooks */ + +struct t_hook *config_day_change_timer = NULL; + /* * config_change_save_on_exit: called when "save_on_exit" flag is changed @@ -318,6 +326,91 @@ config_change_nicks_colors () } /* + * config_change_infobar_seconds: called when display of seconds in infobar changed + */ + +void +config_change_infobar_seconds () +{ + int seconds; + + if (gui_infobar_refresh_timer) + unhook (gui_infobar_refresh_timer); + + seconds = (CONFIG_BOOLEAN(config_look_infobar_seconds)) ? 1 : 60; + gui_infobar_refresh_timer = hook_timer (NULL, seconds * 1000, seconds, 0, + gui_infobar_refresh_timer_cb, NULL); + (void) gui_infobar_refresh_timer_cb ("force"); +} + +/* + * config_day_change_timer_cb: timer callback for displaying + * "Day changed to xxx" message + */ + +int +config_day_change_timer_cb (void *data) +{ + struct timeval tv_time; + struct tm *local_time; + char text_time[1024], *text_time2; + struct t_gui_buffer *ptr_buffer; + + /* make C compiler happy */ + (void) data; + + gettimeofday (&tv_time, NULL); + local_time = localtime (&tv_time.tv_sec); + + strftime (text_time, sizeof (text_time), + CONFIG_STRING(config_look_day_change_time_format), + local_time); + text_time2 = string_iconv_to_internal (NULL, text_time); + gui_add_hotlist = 0; + for (ptr_buffer = gui_buffers; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + if (ptr_buffer->type == GUI_BUFFER_TYPE_FORMATED) + gui_chat_printf (ptr_buffer, + _("\t\tDay changed to %s"), + (text_time2) ? + text_time2 : text_time); + } + if (text_time2) + free (text_time2); + gui_add_hotlist = 1; + + return WEECHAT_RC_OK; +} + +/* + * config_change_day_change: called when day_change option changed + */ + +void +config_change_day_change () +{ + if (CONFIG_BOOLEAN(config_look_day_change)) + { + if (!config_day_change_timer) + config_day_change_timer = hook_timer (NULL, + 24 * 3600 * 1000, + 24 * 3600, + 0, + &config_day_change_timer_cb, + NULL); + } + else + { + if (config_day_change_timer) + { + unhook (config_day_change_timer); + config_day_change_timer = NULL; + } + } +} + +/* * config_weechat_read_key: read a key in configuration file */ @@ -543,7 +636,7 @@ config_weechat_init () config_look_infobar_seconds = config_file_new_option ( ptr_section, "look_infobar_seconds", "boolean", N_("display seconds in infobar time"), - NULL, 0, 0, "on", &config_change_buffer_content); + NULL, 0, 0, "on", &config_change_infobar_seconds); config_look_infobar_delay_highlight = config_file_new_option ( ptr_section, "look_infobar_delay_highlight", "integer", N_("delay (in seconds) for highlight messages in " @@ -576,7 +669,7 @@ config_weechat_init () config_look_day_change = config_file_new_option ( ptr_section, "look_day_change", "boolean", N_("display special message when day changes"), - NULL, 0, 0, "on", NULL); + NULL, 0, 0, "on", &config_change_day_change); config_look_day_change_time_format = config_file_new_option ( ptr_section, "look_day_change_time_format", "string", N_("time format for date displayed when day changed"), @@ -1045,7 +1138,16 @@ config_weechat_init () int config_weechat_read () { - return config_file_read (weechat_config_file); + int rc; + + rc = config_file_read (weechat_config_file); + if (rc == 0) + { + config_change_infobar_seconds (); + config_change_day_change (); + } + + return rc; } /* diff --git a/src/core/wee-hook.c b/src/core/wee-hook.c index d5d7fcc38..31a782f18 100644 --- a/src/core/wee-hook.c +++ b/src/core/wee-hook.c @@ -38,12 +38,29 @@ #include "../plugins/plugin.h" -struct t_hook *weechat_hooks = NULL; -struct t_hook *last_weechat_hook = NULL; +struct t_hook *weechat_hooks[HOOK_NUM_TYPES]; +struct t_hook *last_weechat_hook[HOOK_NUM_TYPES]; int hook_exec_recursion = 0; +int real_delete_pending = 0; /* + * hook_init: init hooks lists + */ + +void +hook_init () +{ + int type; + + for (type = 0; type < HOOK_NUM_TYPES; type++) + { + weechat_hooks[type] = NULL; + last_weechat_hook[type] = NULL; + } +} + +/* * hook_find_pos: find position for new hook (keeping command list sorted) */ @@ -57,10 +74,10 @@ hook_find_pos (struct t_hook *hook) return NULL; /* for command hook, keep list sorted */ - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[hook->type]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->type == HOOK_TYPE_COMMAND) + if (!ptr_hook->deleted && (string_strcasecmp (HOOK_COMMAND(hook, command), HOOK_COMMAND(ptr_hook, command)) <= 0)) return ptr_hook; @@ -79,7 +96,7 @@ hook_add_to_list (struct t_hook *new_hook) { struct t_hook *pos_hook; - if (weechat_hooks) + if (weechat_hooks[new_hook->type]) { pos_hook = hook_find_pos (new_hook); if (pos_hook) @@ -90,24 +107,24 @@ hook_add_to_list (struct t_hook *new_hook) if (pos_hook->prev_hook) (pos_hook->prev_hook)->next_hook = new_hook; else - weechat_hooks = new_hook; + weechat_hooks[new_hook->type] = new_hook; pos_hook->prev_hook = new_hook; } else { /* add hook to end of list */ - new_hook->prev_hook = last_weechat_hook; + new_hook->prev_hook = last_weechat_hook[new_hook->type]; new_hook->next_hook = NULL; - last_weechat_hook->next_hook = new_hook; - last_weechat_hook = new_hook; + last_weechat_hook[new_hook->type]->next_hook = new_hook; + last_weechat_hook[new_hook->type] = new_hook; } } else { new_hook->prev_hook = NULL; new_hook->next_hook = NULL; - weechat_hooks = new_hook; - last_weechat_hook = new_hook; + weechat_hooks[new_hook->type] = new_hook; + last_weechat_hook[new_hook->type] = new_hook; } } @@ -120,12 +137,12 @@ hook_remove_from_list (struct t_hook *hook) { struct t_hook *new_hooks; - if (last_weechat_hook == hook) - last_weechat_hook = hook->prev_hook; + if (last_weechat_hook[hook->type] == hook) + last_weechat_hook[hook->type] = hook->prev_hook; if (hook->prev_hook) { hook->prev_hook->next_hook = hook->next_hook; - new_hooks = weechat_hooks; + new_hooks = weechat_hooks[hook->type]; } else new_hooks = hook->next_hook; @@ -134,7 +151,7 @@ hook_remove_from_list (struct t_hook *hook) hook->next_hook->prev_hook = hook->prev_hook; free (hook); - weechat_hooks = new_hooks; + weechat_hooks[hook->type] = new_hooks; } /* @@ -144,34 +161,41 @@ hook_remove_from_list (struct t_hook *hook) void hook_remove_deleted () { + int type; struct t_hook *ptr_hook, *next_hook; - - ptr_hook = weechat_hooks; - while (ptr_hook) + + if (real_delete_pending) { - next_hook = ptr_hook->next_hook; - - if (ptr_hook->type == HOOK_TYPE_DELETED) - hook_remove_from_list (ptr_hook); - - ptr_hook = next_hook; + for (type = 0; type < HOOK_NUM_TYPES; type++) + { + ptr_hook = weechat_hooks[type]; + while (ptr_hook) + { + next_hook = ptr_hook->next_hook; + + if (ptr_hook->deleted) + hook_remove_from_list (ptr_hook); + + ptr_hook = next_hook; + } + } + real_delete_pending = 0; } } /* - * hook_init: init a new hook with default values + * hook_init_data: init data a new hook with default values */ void -hook_init (struct t_hook *hook, void *plugin, int type, void *callback_data) +hook_init_data (struct t_hook *hook, void *plugin, int type, void *callback_data) { hook->plugin = plugin; hook->type = type; + hook->deleted = 0; + hook->running = 0; hook->callback_data = callback_data; - hook->hook_data = NULL; - - hook->running = 0; } /* @@ -183,13 +207,17 @@ hook_init (struct t_hook *hook, void *plugin, int type, void *callback_data) int hook_valid (struct t_hook *hook) { + int type; struct t_hook *ptr_hook; - - for (ptr_hook = weechat_hooks; ptr_hook; - ptr_hook = ptr_hook->next_hook) + + for (type = 0; type < HOOK_NUM_TYPES; type++) { - if (ptr_hook == hook) - return 1; + for (ptr_hook = weechat_hooks[type]; ptr_hook; + ptr_hook = ptr_hook->next_hook) + { + if (!ptr_hook->deleted && (ptr_hook == hook)) + return 1; + } } /* hook not found */ @@ -205,14 +233,18 @@ hook_valid (struct t_hook *hook) int hook_valid_for_plugin (void *plugin, struct t_hook *hook) { + int type; struct t_hook *ptr_hook; - - for (ptr_hook = weechat_hooks; ptr_hook; - ptr_hook = ptr_hook->next_hook) + + for (type = 0; type < HOOK_NUM_TYPES; type++) { - if ((ptr_hook == hook) - && (ptr_hook->plugin == (struct t_weechat_plugin *)plugin)) - return 1; + for (ptr_hook = weechat_hooks[type]; ptr_hook; + ptr_hook = ptr_hook->next_hook) + { + if (!ptr_hook->deleted && (ptr_hook == hook) + && (ptr_hook->plugin == (struct t_weechat_plugin *)plugin)) + return 1; + } } /* hook not found */ @@ -228,10 +260,10 @@ hook_search_command (char *command) { struct t_hook *ptr_hook; - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_COMMAND]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->type == HOOK_TYPE_COMMAND) + if (!ptr_hook->deleted && (string_strcasecmp (HOOK_COMMAND(ptr_hook, command), command) == 0)) return ptr_hook; } @@ -260,10 +292,10 @@ hook_command (void *plugin, char *command, char *description, /* increase level for command hooks with same command name so that these commands will not be used any more, until this one is removed */ - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_COMMAND]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->type == HOOK_TYPE_COMMAND) + if (!ptr_hook->deleted && (string_strcasecmp (HOOK_COMMAND(ptr_hook, command), command) == 0)) { HOOK_COMMAND(ptr_hook, level)++; @@ -280,7 +312,7 @@ hook_command (void *plugin, char *command, char *description, return NULL; } - hook_init (new_hook, plugin, HOOK_TYPE_COMMAND, callback_data); + hook_init_data (new_hook, plugin, HOOK_TYPE_COMMAND, callback_data); new_hook->hook_data = new_hook_command; new_hook_command->callback = callback; @@ -328,14 +360,14 @@ hook_command_exec (void *buffer, char *string, int only_builtin) hook_exec_recursion++; - ptr_hook = weechat_hooks; + ptr_hook = weechat_hooks[HOOK_TYPE_COMMAND]; while (ptr_hook) { next_hook = ptr_hook->next_hook; - if ((ptr_hook->type == HOOK_TYPE_COMMAND) + if (!ptr_hook->deleted + && !ptr_hook->running && (HOOK_COMMAND(ptr_hook, level) == 0) - && (!ptr_hook->running) && (!only_builtin || !ptr_hook->plugin) && (!ptr_hook->plugin || !((struct t_gui_buffer *)buffer)->plugin @@ -346,8 +378,7 @@ hook_command_exec (void *buffer, char *string, int only_builtin) ptr_hook->running = 1; rc = (int) (HOOK_COMMAND(ptr_hook, callback)) (ptr_hook->callback_data, buffer, argc, argv, argv_eol); - if (ptr_hook->type == HOOK_TYPE_COMMAND) - ptr_hook->running = 0; + ptr_hook->running = 0; if (hook_exec_recursion > 0) hook_exec_recursion--; if (hook_exec_recursion == 0) @@ -379,11 +410,12 @@ hook_command_exec (void *buffer, char *string, int only_builtin) */ struct t_hook * -hook_timer (void *plugin, long interval, int max_calls, +hook_timer (void *plugin, long interval, int align_second, int max_calls, t_hook_callback_timer *callback, void *callback_data) { struct t_hook *new_hook; struct t_hook_timer *new_hook_timer; + struct timezone tz; new_hook = (struct t_hook *)malloc (sizeof (struct t_hook)); if (!new_hook) @@ -395,13 +427,28 @@ hook_timer (void *plugin, long interval, int max_calls, return NULL; } - hook_init (new_hook, plugin, HOOK_TYPE_TIMER, callback_data); + hook_init_data (new_hook, plugin, HOOK_TYPE_TIMER, callback_data); new_hook->hook_data = new_hook_timer; new_hook_timer->callback = callback; new_hook_timer->interval = interval; new_hook_timer->remaining_calls = max_calls; - gettimeofday (&new_hook_timer->last_exec, NULL); + + tz.tz_minuteswest = 0; + gettimeofday (&new_hook_timer->last_exec, &tz); + + if ((interval >= 1000) && (align_second > 0)) + { + new_hook_timer->last_exec.tv_usec = 0; + new_hook_timer->last_exec.tv_sec = + new_hook_timer->last_exec.tv_sec - + ((new_hook_timer->last_exec.tv_sec - (tz.tz_minuteswest * 60)) % + align_second); + } + + new_hook_timer->next_exec.tv_sec = new_hook_timer->last_exec.tv_sec; + new_hook_timer->next_exec.tv_usec = new_hook_timer->last_exec.tv_usec; + util_timeval_add (&new_hook_timer->next_exec, interval); hook_add_to_list (new_hook); @@ -409,43 +456,104 @@ hook_timer (void *plugin, long interval, int max_calls, } /* + * hook_timer_time_to_next: get time to next timeout + * return 1 if timeout is set with next timeout + * 0 if there's no timeout + */ + +int +hook_timer_time_to_next (struct timeval *tv_time) +{ + struct t_hook *ptr_hook; + int found; + struct timeval tv_now; + long diff_usec; + + found = 0; + tv_time->tv_sec = 0; + tv_time->tv_usec = 0; + + for (ptr_hook = weechat_hooks[HOOK_TYPE_TIMER]; ptr_hook; + ptr_hook = ptr_hook->next_hook) + { + if (!ptr_hook->deleted + && (!found + || (util_timeval_cmp (&HOOK_TIMER(ptr_hook, next_exec), tv_time) < 0))) + { + found = 1; + tv_time->tv_sec = HOOK_TIMER(ptr_hook, next_exec).tv_sec; + tv_time->tv_usec = HOOK_TIMER(ptr_hook, next_exec).tv_usec; + } + } + + /* no timeout found */ + if (!found) + return 0; + + gettimeofday (&tv_now, NULL); + + /* next timeout is past date! */ + if (util_timeval_cmp (tv_time, &tv_now) < 0) + { + tv_time->tv_sec = 0; + tv_time->tv_usec = 0; + return 1; + } + + tv_time->tv_sec = tv_time->tv_sec - tv_now.tv_sec; + diff_usec = tv_time->tv_usec - tv_now.tv_usec; + if (diff_usec >= 0) + tv_time->tv_usec = diff_usec; + else + { + tv_time->tv_sec--; + tv_time->tv_usec = 1000000 + diff_usec; + } + + return 1; +} + +/* * hook_timer_exec: execute timer hooks */ void -hook_timer_exec (struct timeval *tv_time) +hook_timer_exec () { + struct timeval tv_time; struct t_hook *ptr_hook, *next_hook; - long time_diff; + + gettimeofday (&tv_time, NULL); hook_exec_recursion++; - ptr_hook = weechat_hooks; + ptr_hook = weechat_hooks[HOOK_TYPE_TIMER]; while (ptr_hook) { next_hook = ptr_hook->next_hook; - if ((ptr_hook->type == HOOK_TYPE_TIMER) - && (!ptr_hook->running)) + if (!ptr_hook->deleted + && !ptr_hook->running + && (util_timeval_cmp (&HOOK_TIMER(ptr_hook, next_exec), + &tv_time) <= 0)) { - time_diff = util_timeval_diff (&HOOK_TIMER(ptr_hook, last_exec), - tv_time); - if (time_diff >= HOOK_TIMER(ptr_hook, interval)) + ptr_hook->running = 1; + (void) (HOOK_TIMER(ptr_hook, callback)) + (ptr_hook->callback_data); + ptr_hook->running = 0; + if (!ptr_hook->deleted) { - ptr_hook->running = 1; - (void) (HOOK_TIMER(ptr_hook, callback)) - (ptr_hook->callback_data); - if (ptr_hook->type == HOOK_TYPE_TIMER) + HOOK_TIMER(ptr_hook, last_exec).tv_sec = tv_time.tv_sec; + HOOK_TIMER(ptr_hook, last_exec).tv_usec = tv_time.tv_usec; + + util_timeval_add (&HOOK_TIMER(ptr_hook, next_exec), + HOOK_TIMER(ptr_hook, interval)); + + if (HOOK_TIMER(ptr_hook, remaining_calls) > 0) { - ptr_hook->running = 0; - HOOK_TIMER(ptr_hook, last_exec).tv_sec = tv_time->tv_sec; - HOOK_TIMER(ptr_hook, last_exec).tv_usec = tv_time->tv_usec; - if (HOOK_TIMER(ptr_hook, remaining_calls) > 0) - { - HOOK_TIMER(ptr_hook, remaining_calls)--; - if (HOOK_TIMER(ptr_hook, remaining_calls) == 0) - unhook (ptr_hook); - } + HOOK_TIMER(ptr_hook, remaining_calls)--; + if (HOOK_TIMER(ptr_hook, remaining_calls) == 0) + unhook (ptr_hook); } } } @@ -469,11 +577,10 @@ hook_search_fd (int fd) { struct t_hook *ptr_hook; - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_FD]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->type == HOOK_TYPE_FD) - && (HOOK_FD(ptr_hook, fd) == fd)) + if (!ptr_hook->deleted && (HOOK_FD(ptr_hook, fd) == fd)) return ptr_hook; } @@ -505,7 +612,7 @@ hook_fd (void *plugin, int fd, int flags, return NULL; } - hook_init (new_hook, plugin, HOOK_TYPE_FD, callback_data); + hook_init_data (new_hook, plugin, HOOK_TYPE_FD, callback_data); new_hook->hook_data = new_hook_fd; new_hook_fd->callback = callback; @@ -530,10 +637,10 @@ hook_fd_set (fd_set *read_fds, fd_set *write_fds, fd_set *except_fds) FD_ZERO (write_fds); FD_ZERO (except_fds); - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_FD]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if (ptr_hook->type == HOOK_TYPE_FD) + if (!ptr_hook->deleted) { if (HOOK_FD(ptr_hook, flags) & HOOK_FD_FLAG_READ) FD_SET (HOOK_FD(ptr_hook, fd), read_fds); @@ -556,13 +663,13 @@ hook_fd_exec (fd_set *read_fds, fd_set *write_fds, fd_set *except_fds) hook_exec_recursion++; - ptr_hook = weechat_hooks; + ptr_hook = weechat_hooks[HOOK_TYPE_FD]; while (ptr_hook) { next_hook = ptr_hook->next_hook; - if ((ptr_hook->type == HOOK_TYPE_FD) - && (!ptr_hook->running) + if (!ptr_hook->deleted + && !ptr_hook->running && (((HOOK_FD(ptr_hook, flags)& HOOK_FD_FLAG_READ) && (FD_ISSET(HOOK_FD(ptr_hook, fd), read_fds))) || ((HOOK_FD(ptr_hook, flags) & HOOK_FD_FLAG_WRITE) @@ -572,8 +679,7 @@ hook_fd_exec (fd_set *read_fds, fd_set *write_fds, fd_set *except_fds) { ptr_hook->running = 1; (HOOK_FD(ptr_hook, callback)) (ptr_hook->callback_data); - if (ptr_hook->type == HOOK_TYPE_FD) - ptr_hook->running = 0; + ptr_hook->running = 0; } ptr_hook = next_hook; @@ -607,7 +713,7 @@ hook_print (void *plugin, void *buffer, char *message, int strip_colors, return NULL; } - hook_init (new_hook, plugin, HOOK_TYPE_PRINT, callback_data); + hook_init_data (new_hook, plugin, HOOK_TYPE_PRINT, callback_data); new_hook->hook_data = new_hook_print; new_hook_print->callback = callback; @@ -632,10 +738,9 @@ hook_print_exec (void *buffer, time_t date, char *prefix, char *message) if (!message || !message[0]) return; - - prefix_no_color = (char *)gui_color_decode ((unsigned char *)prefix); - if (!prefix_no_color) - return; + + prefix_no_color = (prefix) ? + (char *)gui_color_decode ((unsigned char *)prefix) : NULL; message_no_color = (char *)gui_color_decode ((unsigned char *)message); if (!message_no_color) @@ -646,13 +751,13 @@ hook_print_exec (void *buffer, time_t date, char *prefix, char *message) hook_exec_recursion++; - ptr_hook = weechat_hooks; + ptr_hook = weechat_hooks[HOOK_TYPE_PRINT]; while (ptr_hook) { next_hook = ptr_hook->next_hook; - if ((ptr_hook->type == HOOK_TYPE_PRINT) - && (!ptr_hook->running) + if (!ptr_hook->deleted + && !ptr_hook->running && (!HOOK_PRINT(ptr_hook, buffer) || ((struct t_gui_buffer *)buffer == HOOK_PRINT(ptr_hook, buffer))) && (!HOOK_PRINT(ptr_hook, message) @@ -664,8 +769,7 @@ hook_print_exec (void *buffer, time_t date, char *prefix, char *message) (ptr_hook->callback_data, buffer, date, (HOOK_PRINT(ptr_hook, strip_colors)) ? prefix_no_color : prefix, (HOOK_PRINT(ptr_hook, strip_colors)) ? message_no_color : message); - if (ptr_hook->type == HOOK_TYPE_PRINT) - ptr_hook->running = 0; + ptr_hook->running = 0; } ptr_hook = next_hook; @@ -702,7 +806,7 @@ hook_signal (void *plugin, char *signal, return NULL; } - hook_init (new_hook, plugin, HOOK_TYPE_SIGNAL, callback_data); + hook_init_data (new_hook, plugin, HOOK_TYPE_SIGNAL, callback_data); new_hook->hook_data = new_hook_signal; new_hook_signal->callback = callback; @@ -724,21 +828,20 @@ hook_signal_exec (char *signal, void *pointer) hook_exec_recursion++; - ptr_hook = weechat_hooks; + ptr_hook = weechat_hooks[HOOK_TYPE_SIGNAL]; while (ptr_hook) { next_hook = ptr_hook->next_hook; - if ((ptr_hook->type == HOOK_TYPE_SIGNAL) - && (!ptr_hook->running) + if (!ptr_hook->deleted + && !ptr_hook->running && ((string_strcasecmp (HOOK_SIGNAL(ptr_hook, signal), "*") == 0) || (string_strcasecmp (HOOK_SIGNAL(ptr_hook, signal), signal) == 0))) { ptr_hook->running = 1; (void) (HOOK_SIGNAL(ptr_hook, callback)) (ptr_hook->callback_data, signal, pointer); - if (ptr_hook->type == HOOK_TYPE_SIGNAL) - ptr_hook->running = 0; + ptr_hook->running = 0; } ptr_hook = next_hook; @@ -772,7 +875,7 @@ hook_config (void *plugin, char *type, char *option, return NULL; } - hook_init (new_hook, plugin, HOOK_TYPE_CONFIG, callback_data); + hook_init_data (new_hook, plugin, HOOK_TYPE_CONFIG, callback_data); new_hook->hook_data = new_hook_config; new_hook_config->callback = callback; @@ -795,13 +898,13 @@ hook_config_exec (char *type, char *option, char *value) hook_exec_recursion++; - ptr_hook = weechat_hooks; + ptr_hook = weechat_hooks[HOOK_TYPE_CONFIG]; while (ptr_hook) { next_hook = ptr_hook->next_hook; - if ((ptr_hook->type == HOOK_TYPE_CONFIG) - && (!ptr_hook->running) + if (!ptr_hook->deleted + && !ptr_hook->running && (!HOOK_CONFIG(ptr_hook, type) || (string_strcasecmp (HOOK_CONFIG(ptr_hook, type), type) == 0)) @@ -812,8 +915,7 @@ hook_config_exec (char *type, char *option, char *value) ptr_hook->running = 1; (void) (HOOK_CONFIG(ptr_hook, callback)) (ptr_hook->callback_data, type, option, value); - if (ptr_hook->type == HOOK_TYPE_CONFIG) - ptr_hook->running = 0; + ptr_hook->running = 0; } ptr_hook = next_hook; @@ -850,7 +952,7 @@ hook_completion (void *plugin, char *completion, return NULL; } - hook_init (new_hook, plugin, HOOK_TYPE_COMPLETION, callback_data); + hook_init_data (new_hook, plugin, HOOK_TYPE_COMPLETION, callback_data); new_hook->hook_data = new_hook_completion; new_hook_completion->callback = callback; @@ -875,21 +977,20 @@ hook_completion_exec (void *plugin, char *completion, void *buffer, void *list) hook_exec_recursion++; - ptr_hook = weechat_hooks; + ptr_hook = weechat_hooks[HOOK_TYPE_COMPLETION]; while (ptr_hook) { next_hook = ptr_hook->next_hook; - if ((ptr_hook->type == HOOK_TYPE_COMPLETION) - && (!ptr_hook->running) + if (!ptr_hook->deleted + && !ptr_hook->running && (string_strcasecmp (HOOK_COMPLETION(ptr_hook, completion), completion) == 0)) { ptr_hook->running = 1; (void) (HOOK_COMPLETION(ptr_hook, callback)) (ptr_hook->callback_data, completion, buffer, list); - if (ptr_hook->type == HOOK_TYPE_COMPLETION) - ptr_hook->running = 0; + ptr_hook->running = 0; } ptr_hook = next_hook; @@ -911,23 +1012,23 @@ unhook (struct t_hook *hook) { struct t_hook *ptr_hook; + /* hook already deleted? */ + if (hook->deleted) + return; + /* free data */ if (hook->hook_data) { switch (hook->type) { - case HOOK_TYPE_DELETED: - /* hook will be deleted later, we do nothing here, hook data is - already free */ - break; case HOOK_TYPE_COMMAND: /* decrease level for command hooks with same command name and level higher than this one */ - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_COMMAND]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook != hook) - && (ptr_hook->type == HOOK_TYPE_COMMAND) + if (!ptr_hook->deleted + && (ptr_hook != hook) && (string_strcasecmp (HOOK_COMMAND(ptr_hook, command), HOOK_COMMAND(hook, command)) == 0) && (HOOK_COMMAND(ptr_hook, level) > HOOK_COMMAND(hook, level))) @@ -975,6 +1076,10 @@ unhook (struct t_hook *hook) free (HOOK_COMPLETION(hook, completion)); free ((struct t_hook_completion *)hook->hook_data); break; + case HOOK_NUM_TYPES: + /* this constant is used to count types only, + it is never used as type */ + break; } hook->hook_data = NULL; } @@ -987,7 +1092,8 @@ unhook (struct t_hook *hook) else { /* there is one or more hook exec, then delete later */ - hook->type = HOOK_TYPE_DELETED; + hook->deleted = 1; + real_delete_pending = 1; } } @@ -998,15 +1104,19 @@ unhook (struct t_hook *hook) void unhook_all_plugin (void *plugin) { + int type; struct t_hook *ptr_hook, *next_hook; - ptr_hook = weechat_hooks; - while (ptr_hook) + for (type = 0; type < HOOK_NUM_TYPES; type++) { - next_hook = ptr_hook->next_hook; - if (ptr_hook->plugin == plugin) - unhook (ptr_hook); - ptr_hook = next_hook; + ptr_hook = weechat_hooks[type]; + while (ptr_hook) + { + next_hook = ptr_hook->next_hook; + if (ptr_hook->plugin == plugin) + unhook (ptr_hook); + ptr_hook = next_hook; + } } } @@ -1017,14 +1127,18 @@ unhook_all_plugin (void *plugin) void unhook_all () { + int type; struct t_hook *ptr_hook, *next_hook; - ptr_hook = weechat_hooks; - while (ptr_hook) + for (type = 0; type < HOOK_NUM_TYPES; type++) { - next_hook = ptr_hook->next_hook; - unhook (ptr_hook); - ptr_hook = next_hook; + ptr_hook = weechat_hooks[type]; + while (ptr_hook) + { + next_hook = ptr_hook->next_hook; + unhook (ptr_hook); + ptr_hook = next_hook; + } } } @@ -1035,83 +1149,122 @@ unhook_all () void hook_print_log () { + int type; struct t_hook *ptr_hook; + struct tm *local_time; + char text_time[1024]; - for (ptr_hook = weechat_hooks; ptr_hook; - ptr_hook = ptr_hook->next_hook) + for (type = 0; type < HOOK_NUM_TYPES; type++) { - log_printf (""); - log_printf ("[hook (addr:0x%X)]", ptr_hook); - log_printf (" plugin . . . . . . . . : 0x%X", ptr_hook->plugin); - switch (ptr_hook->type) + for (ptr_hook = weechat_hooks[type]; ptr_hook; + ptr_hook = ptr_hook->next_hook) { - case HOOK_TYPE_DELETED: - log_printf (" type . . . . . . . . . : %d (hook deleted)", ptr_hook->type); - log_printf (" callback_data. . . . . : 0x%X", ptr_hook->callback_data); - log_printf (" hook_data. . . . . . . : 0x%X", ptr_hook->hook_data); - break; - case HOOK_TYPE_COMMAND: - log_printf (" type . . . . . . . . . : %d (command)", ptr_hook->type); - log_printf (" callback_data. . . . . : 0x%X", ptr_hook->callback_data); - log_printf (" command data:"); - log_printf (" callback . . . . . . : 0x%X", HOOK_COMMAND(ptr_hook, callback)); - log_printf (" command. . . . . . . : '%s'", HOOK_COMMAND(ptr_hook, command)); - log_printf (" level. . . . . . . . : %d", HOOK_COMMAND(ptr_hook, level)); - log_printf (" command_desc . . . . : '%s'", HOOK_COMMAND(ptr_hook, description)); - log_printf (" command_args . . . . : '%s'", HOOK_COMMAND(ptr_hook, args)); - log_printf (" command_args_desc. . : '%s'", HOOK_COMMAND(ptr_hook, args_description)); - log_printf (" command_completion . : '%s'", HOOK_COMMAND(ptr_hook, completion)); - break; - case HOOK_TYPE_TIMER: - log_printf (" type . . . . . . . . . : %d (timer)", ptr_hook->type); - log_printf (" callback_data. . . . . : 0x%X", ptr_hook->callback_data); - log_printf (" timer data:"); - log_printf (" callback . . . . . . : 0x%X", HOOK_TIMER(ptr_hook, callback)); - log_printf (" interval . . . . . . : %ld", HOOK_TIMER(ptr_hook, interval)); - log_printf (" last_exec.tv_sec . . : %ld", HOOK_TIMER(ptr_hook, last_exec.tv_sec)); - log_printf (" last_exec.tv_usec. . : %ld", HOOK_TIMER(ptr_hook, last_exec.tv_usec)); - break; - case HOOK_TYPE_FD: - log_printf (" type . . . . . . . . . : %d (fd)", ptr_hook->type); - log_printf (" callback_data. . . . . : 0x%X", ptr_hook->callback_data); - log_printf (" fd data:"); - log_printf (" callback . . . . . . : 0x%X", HOOK_FD(ptr_hook, callback)); - log_printf (" fd . . . . . . . . . : %ld", HOOK_FD(ptr_hook, fd)); - log_printf (" flags. . . . . . . . : %ld", HOOK_FD(ptr_hook, flags)); - break; - case HOOK_TYPE_PRINT: - log_printf (" type . . . . . . . . . : %d (print)", ptr_hook->type); - log_printf (" callback_data. . . . . : 0x%X", ptr_hook->callback_data); - log_printf (" print data:"); - log_printf (" callback . . . . . . : 0x%X", HOOK_PRINT(ptr_hook, callback)); - log_printf (" buffer . . . . . . . : 0x%X", HOOK_PRINT(ptr_hook, buffer)); - log_printf (" message. . . . . . . : '%s'", HOOK_PRINT(ptr_hook, message)); - break; - case HOOK_TYPE_SIGNAL: - log_printf (" type . . . . . . . . . : %d (signal)", ptr_hook->type); - log_printf (" callback_data. . . . . : 0x%X", ptr_hook->callback_data); - log_printf (" signal data:"); - log_printf (" callback . . . . . . : 0x%X", HOOK_SIGNAL(ptr_hook, callback)); - log_printf (" signal . . . . . . . : '%s'", HOOK_SIGNAL(ptr_hook, signal)); - break; - case HOOK_TYPE_CONFIG: - log_printf (" type . . . . . . . . . : %d (config)", ptr_hook->type); - log_printf (" callback_data. . . . . : 0x%X", ptr_hook->callback_data); - log_printf (" config data:"); - log_printf (" callback . . . . . . : 0x%X", HOOK_CONFIG(ptr_hook, callback)); - log_printf (" type . . . . . . . . : '%s'", HOOK_CONFIG(ptr_hook, type)); - log_printf (" option . . . . . . . : '%s'", HOOK_CONFIG(ptr_hook, option)); - break; - case HOOK_TYPE_COMPLETION: - log_printf (" type . . . . . . . . . : %d (completion)", ptr_hook->type); - log_printf (" callback_data. . . . . : 0x%X", ptr_hook->callback_data); - log_printf (" completion data:"); - log_printf (" callback . . . . . . : 0x%X", HOOK_COMPLETION(ptr_hook, callback)); - log_printf (" completion . . . . . : '%s'", HOOK_COMPLETION(ptr_hook, completion)); - break; - } - log_printf (" running. . . . . . . . : %d", ptr_hook->running); - log_printf (" prev_hook. . . . . . . : 0x%X", ptr_hook->prev_hook); - log_printf (" next_hook. . . . . . . : 0x%X", ptr_hook->next_hook); + log_printf (""); + log_printf ("[hook (addr:0x%X)]", ptr_hook); + log_printf (" plugin . . . . . . . . : 0x%X", ptr_hook->plugin); + log_printf (" deleted. . . . . . . . : %d", ptr_hook->deleted); + log_printf (" running. . . . . . . . : %d", ptr_hook->running); + switch (ptr_hook->type) + { + case HOOK_TYPE_COMMAND: + log_printf (" type . . . . . . . . . : %d (command)", ptr_hook->type); + log_printf (" callback_data. . . . . : 0x%X", ptr_hook->callback_data); + if (!ptr_hook->deleted) + { + log_printf (" command data:"); + log_printf (" callback . . . . . . : 0x%X", HOOK_COMMAND(ptr_hook, callback)); + log_printf (" command. . . . . . . : '%s'", HOOK_COMMAND(ptr_hook, command)); + log_printf (" level. . . . . . . . : %d", HOOK_COMMAND(ptr_hook, level)); + log_printf (" command_desc . . . . : '%s'", HOOK_COMMAND(ptr_hook, description)); + log_printf (" command_args . . . . : '%s'", HOOK_COMMAND(ptr_hook, args)); + log_printf (" command_args_desc. . : '%s'", HOOK_COMMAND(ptr_hook, args_description)); + log_printf (" command_completion . : '%s'", HOOK_COMMAND(ptr_hook, completion)); + } + break; + case HOOK_TYPE_TIMER: + log_printf (" type . . . . . . . . . : %d (timer)", ptr_hook->type); + log_printf (" callback_data. . . . . : 0x%X", ptr_hook->callback_data); + if (!ptr_hook->deleted) + { + log_printf (" timer data:"); + log_printf (" callback . . . . . . : 0x%X", HOOK_TIMER(ptr_hook, callback)); + log_printf (" interval . . . . . . : %ld", HOOK_TIMER(ptr_hook, interval)); + local_time = localtime (&HOOK_TIMER(ptr_hook, last_exec).tv_sec); + strftime (text_time, sizeof (text_time), + "%d/%m/%Y %H:%M:%S", local_time); + log_printf (" last_exec.tv_sec . . : %ld (%s)", + HOOK_TIMER(ptr_hook, last_exec.tv_sec), + text_time); + log_printf (" last_exec.tv_usec. . : %ld", HOOK_TIMER(ptr_hook, last_exec.tv_usec)); + local_time = localtime (&HOOK_TIMER(ptr_hook, next_exec).tv_sec); + strftime (text_time, sizeof (text_time), + "%d/%m/%Y %H:%M:%S", local_time); + log_printf (" next_exec.tv_sec . . : %ld (%s)", + HOOK_TIMER(ptr_hook, next_exec.tv_sec), + text_time); + log_printf (" next_exec.tv_usec. . : %ld", HOOK_TIMER(ptr_hook, next_exec.tv_usec)); + } + break; + case HOOK_TYPE_FD: + log_printf (" type . . . . . . . . . : %d (fd)", ptr_hook->type); + log_printf (" callback_data. . . . . : 0x%X", ptr_hook->callback_data); + if (!ptr_hook->deleted) + { + log_printf (" fd data:"); + log_printf (" callback . . . . . . : 0x%X", HOOK_FD(ptr_hook, callback)); + log_printf (" fd . . . . . . . . . : %ld", HOOK_FD(ptr_hook, fd)); + log_printf (" flags. . . . . . . . : %ld", HOOK_FD(ptr_hook, flags)); + } + break; + case HOOK_TYPE_PRINT: + log_printf (" type . . . . . . . . . : %d (print)", ptr_hook->type); + log_printf (" callback_data. . . . . : 0x%X", ptr_hook->callback_data); + if (!ptr_hook->deleted) + { + log_printf (" print data:"); + log_printf (" callback . . . . . . : 0x%X", HOOK_PRINT(ptr_hook, callback)); + log_printf (" buffer . . . . . . . : 0x%X", HOOK_PRINT(ptr_hook, buffer)); + log_printf (" message. . . . . . . : '%s'", HOOK_PRINT(ptr_hook, message)); + } + break; + case HOOK_TYPE_SIGNAL: + log_printf (" type . . . . . . . . . : %d (signal)", ptr_hook->type); + log_printf (" callback_data. . . . . : 0x%X", ptr_hook->callback_data); + if (!ptr_hook->deleted) + { + log_printf (" signal data:"); + log_printf (" callback . . . . . . : 0x%X", HOOK_SIGNAL(ptr_hook, callback)); + log_printf (" signal . . . . . . . : '%s'", HOOK_SIGNAL(ptr_hook, signal)); + } + break; + case HOOK_TYPE_CONFIG: + log_printf (" type . . . . . . . . . : %d (config)", ptr_hook->type); + log_printf (" callback_data. . . . . : 0x%X", ptr_hook->callback_data); + if (!ptr_hook->deleted) + { + log_printf (" config data:"); + log_printf (" callback . . . . . . : 0x%X", HOOK_CONFIG(ptr_hook, callback)); + log_printf (" type . . . . . . . . : '%s'", HOOK_CONFIG(ptr_hook, type)); + log_printf (" option . . . . . . . : '%s'", HOOK_CONFIG(ptr_hook, option)); + } + break; + case HOOK_TYPE_COMPLETION: + log_printf (" type . . . . . . . . . : %d (completion)", ptr_hook->type); + log_printf (" callback_data. . . . . : 0x%X", ptr_hook->callback_data); + if (!ptr_hook->deleted) + { + log_printf (" completion data:"); + log_printf (" callback . . . . . . : 0x%X", HOOK_COMPLETION(ptr_hook, callback)); + log_printf (" completion . . . . . : '%s'", HOOK_COMPLETION(ptr_hook, completion)); + } + break; + case HOOK_NUM_TYPES: + /* this constant is used to count types only, + it is never used as type */ + break; + } + log_printf (" prev_hook. . . . . . . : 0x%X", ptr_hook->prev_hook); + log_printf (" next_hook. . . . . . . : 0x%X", ptr_hook->next_hook); + } } } diff --git a/src/core/wee-hook.h b/src/core/wee-hook.h index caeb5b822..09b5af483 100644 --- a/src/core/wee-hook.h +++ b/src/core/wee-hook.h @@ -24,14 +24,15 @@ enum t_hook_type { - HOOK_TYPE_DELETED = 0, /* used when hook is deleted */ - HOOK_TYPE_COMMAND, /* new command */ + HOOK_TYPE_COMMAND = 0, /* new command */ HOOK_TYPE_TIMER, /* timer */ HOOK_TYPE_FD, /* socket of file descriptor */ HOOK_TYPE_PRINT, /* printed message */ HOOK_TYPE_SIGNAL, /* signal */ HOOK_TYPE_CONFIG, /* config option */ HOOK_TYPE_COMPLETION, /* custom completions */ + /* number of hook types */ + HOOK_NUM_TYPES, }; #define HOOK_FD_FLAG_READ 1 @@ -52,12 +53,12 @@ struct t_hook struct t_weechat_plugin *plugin; /* plugin which created this hook */ /* (NULL for hook created by WeeChat)*/ enum t_hook_type type; /* hook type */ + int deleted; /* hook marked for deletion ? */ + int running; /* 1 if hook is currently running */ void *callback_data; /* data sent to callback */ - + /* hook data (depends on hook type) */ void *hook_data; /* hook specific data */ - - int running; /* 1 if hook is currently running */ struct t_hook *prev_hook; /* link to previous hook */ struct t_hook *next_hook; /* link to next hook */ }; @@ -84,6 +85,7 @@ struct t_hook_timer long interval; /* timer interval (milliseconds) */ int remaining_calls; /* calls remaining (0 = unlimited) */ struct timeval last_exec; /* last time hook was executed */ + struct timeval next_exec; /* next scheduled execution */ }; typedef int (t_hook_callback_fd)(void *); @@ -133,20 +135,22 @@ struct t_hook_completion /* hook variables */ -extern struct t_hook *weechat_hooks; -extern struct t_hook *last_weechat_hook; +extern struct t_hook *weechat_hooks[]; +extern struct t_hook *last_weechat_hook[]; /* hook functions */ +extern void hook_init (); extern int hook_valid (struct t_hook *); extern int hook_valid_for_plugin (void *, struct t_hook *); extern struct t_hook *hook_command (void *, char *, char *, char *, char *, char *, t_hook_callback_command *, void *); extern int hook_command_exec (void *, char *, int); -extern struct t_hook *hook_timer (void *, long, int, t_hook_callback_timer *, - void *); -extern void hook_timer_exec (struct timeval *); +extern struct t_hook *hook_timer (void *, long, int, int, + t_hook_callback_timer *, void *); +extern int hook_timer_time_to_next (struct timeval *); +extern void hook_timer_exec (); extern struct t_hook *hook_fd (void *, int, int, t_hook_callback_fd *,void *); extern void hook_fd_set (fd_set *, fd_set *, fd_set *); extern void hook_fd_exec (fd_set *, fd_set *, fd_set *); diff --git a/src/core/wee-util.c b/src/core/wee-util.c index b9238e5d3..e737c7592 100644 --- a/src/core/wee-util.c +++ b/src/core/wee-util.c @@ -37,6 +37,27 @@ /* + * util_timeval_cmp: compare two timeval structures + * return: -1 if tv1 < tv2 + * 0 if tv1 == tv2 + * 1 if tv1 > tv2 + */ + +int +util_timeval_cmp (struct timeval *tv1, struct timeval *tv2) +{ + if (tv1->tv_sec < tv2->tv_sec) + return -1; + if (tv1->tv_sec > tv2->tv_sec) + return 1; + if (tv1->tv_usec < tv2->tv_usec) + return -1; + if (tv1->tv_usec > tv2->tv_usec) + return 1; + return 0; +} + +/* * util_timeval_diff: calculates difference between two times (return in * milliseconds) */ @@ -58,6 +79,26 @@ util_timeval_diff (struct timeval *tv1, struct timeval *tv2) } /* + * util_timeval_add: add interval (in milliseconds) to a timeval struct + */ + +void +util_timeval_add (struct timeval *tv, long interval) +{ + long usec; + + tv->tv_sec += (interval / 1000); + usec = tv->tv_usec + ((interval % 1000) * 1000); + if (usec > 1000000) + { + tv->tv_usec = usec % 1000000; + tv->tv_sec++; + } + else + tv->tv_usec = usec; +} + +/* * util_get_time_length: calculates time length with a time format */ diff --git a/src/core/wee-util.h b/src/core/wee-util.h index db61830f4..504c0377f 100644 --- a/src/core/wee-util.h +++ b/src/core/wee-util.h @@ -20,7 +20,9 @@ #ifndef __WEECHAT_UTIL_H #define __WEECHAT_UTIL_H 1 +extern int util_timeval_cmp (struct timeval *, struct timeval *); extern long util_timeval_diff (struct timeval *, struct timeval *); +extern void util_timeval_add (struct timeval *, long); extern int util_get_time_length (char *); extern int util_create_dir (char *, int); extern void util_exec_on_files (char *, int (*)(char *)); diff --git a/src/core/weechat.c b/src/core/weechat.c index bbbea7fec..8d6a74d9e 100644 --- a/src/core/weechat.c +++ b/src/core/weechat.c @@ -586,6 +586,7 @@ main (int argc, char *argv[]) signal (SIGQUIT, SIG_IGN); /* ignore SIGQUIT signal */ signal (SIGPIPE, SIG_IGN); /* ignore SIGPIPE signal */ signal (SIGSEGV, weechat_sigsegv); /* crash dump when SIGSEGV received */ + hook_init (); /* initialize hooks */ gui_main_pre_init (&argc, &argv); /* pre-initiliaze interface */ weechat_init_vars (); /* initialize some variables */ command_init (); /* initialize WeeChat commands */ diff --git a/src/gui/curses/gui-curses-infobar.c b/src/gui/curses/gui-curses-infobar.c index eec538c4b..c26db5840 100644 --- a/src/gui/curses/gui-curses-infobar.c +++ b/src/gui/curses/gui-curses-infobar.c @@ -28,7 +28,9 @@ #include "../../core/weechat.h" #include "../../core/wee-config.h" +#include "../../core/wee-hook.h" #include "../../core/wee-string.h" +#include "../../plugins/plugin.h" #include "../gui-infobar.h" #include "../gui-color.h" #include "../gui-main.h" @@ -146,3 +148,56 @@ gui_infobar_draw (struct t_gui_buffer *buffer, int erase) refresh (); } } + +/* + * gui_infobar_refresh_timer_cb: timer callback for refresh of infobar + */ + +int +gui_infobar_refresh_timer_cb (void *data) +{ + /* make C compiler happy */ + (void) data; + + if (gui_ok) + { + if (data) + gui_infobar_draw (gui_current_window->buffer, 1); + else + gui_infobar_draw_time (gui_current_window->buffer); + wmove (GUI_CURSES(gui_current_window)->win_input, + 0, gui_current_window->win_input_cursor_x); + wrefresh (GUI_CURSES(gui_current_window)->win_input); + } + + return WEECHAT_RC_OK; +} + +/* + * gui_infobar_highlight_timer_cb: timer callback for highlights in infobar + */ + +int +gui_infobar_highlight_timer_cb (void *data) +{ + /* make C compiler happy */ + (void) data; + + if (gui_ok) + { + if (gui_infobar && gui_infobar->remaining_time > 0) + { + gui_infobar->remaining_time--; + if (gui_infobar->remaining_time == 0) + { + gui_infobar_remove (); + gui_infobar_draw (gui_current_window->buffer, 1); + } + } + /* remove this timer if there's no more data for infobar */ + if (!gui_infobar) + unhook (gui_infobar_highlight_timer); + } + + return WEECHAT_RC_OK; +} diff --git a/src/gui/curses/gui-curses-main.c b/src/gui/curses/gui-curses-main.c index a885dafc5..eebdade5c 100644 --- a/src/gui/curses/gui-curses-main.c +++ b/src/gui/curses/gui-curses-main.c @@ -42,8 +42,6 @@ #include "../gui-infobar.h" #include "../gui-input.h" #include "../gui-history.h" -#include "../gui-hotlist.h" -#include "../gui-keyboard.h" #include "../gui-window.h" #include "gui-curses.h" @@ -131,34 +129,28 @@ gui_main_quit () void gui_main_loop () { - fd_set read_fds, write_fds, except_fds; - static struct timeval timeout; struct t_gui_buffer *ptr_buffer; - int old_day, old_min, old_sec; - char text_time[1024], *text_time2; - struct timeval tv_time; - struct tm *local_time; + struct timeval tv_timeout; + fd_set read_fds, write_fds, except_fds; quit_weechat = 0; - gettimeofday (&tv_time, NULL); - gui_keyboard_last_activity_time = tv_time.tv_sec; - local_time = localtime (&tv_time.tv_sec); - old_day = local_time->tm_mday; - - old_min = -1; - old_sec = -1; - /* if SIGTERM or SIGHUP received => quit */ signal (SIGTERM, gui_main_quit); signal (SIGHUP, gui_main_quit); while (!quit_weechat) { + /* execute hook timers */ + hook_timer_exec (); + + /* infobar count down */ + + /* refresh needed ? */ if (gui_refresh_screen_needed) gui_window_refresh_screen (0); - + for (ptr_buffer = gui_buffers; ptr_buffer; ptr_buffer = ptr_buffer->next_buffer) { @@ -169,114 +161,22 @@ gui_main_loop () } } - gettimeofday (&tv_time, NULL); - local_time = localtime (&tv_time.tv_sec); - - /* execute hook timers */ - hook_timer_exec (&tv_time); - - /* minute has changed ? => redraw infobar */ - if (local_time->tm_min != old_min) - { - old_min = local_time->tm_min; - gui_infobar_draw (gui_current_window->buffer, 1); - - if (CONFIG_BOOLEAN(config_look_day_change) - && (local_time->tm_mday != old_day)) - { - strftime (text_time, sizeof (text_time), - CONFIG_STRING(config_look_day_change_time_format), - local_time); - text_time2 = string_iconv_to_internal (NULL, text_time); - gui_add_hotlist = 0; - for (ptr_buffer = gui_buffers; ptr_buffer; - ptr_buffer = ptr_buffer->next_buffer) - { - if (ptr_buffer->type == GUI_BUFFER_TYPE_FORMATED) - gui_chat_printf (ptr_buffer, - _("\t\tDay changed to %s"), - (text_time2) ? - text_time2 : text_time); - } - if (text_time2) - free (text_time2); - gui_add_hotlist = 1; - } - old_day = local_time->tm_mday; - } - - /* second has changed ? */ - if (local_time->tm_sec != old_sec) - { - old_sec = local_time->tm_sec; - - /* display time in infobar (if seconds displayed) */ - if (CONFIG_BOOLEAN(config_look_infobar_seconds)) - { - gui_infobar_draw_time (gui_current_window->buffer); - wmove (GUI_CURSES(gui_current_window)->win_input, - 0, gui_current_window->win_input_cursor_x); - wrefresh (GUI_CURSES(gui_current_window)->win_input); - } - - /* infobar count down */ - if (gui_infobar && gui_infobar->remaining_time > 0) - { - gui_infobar->remaining_time--; - if (gui_infobar->remaining_time == 0) - { - gui_infobar_remove (); - gui_infobar_draw (gui_current_window->buffer, 1); - } - } - } - - /* read keyboard */ - - /* on GNU/Hurd 2 select() are causing troubles with keyboard */ - /* waiting for a fix, we use only one select() */ -#ifndef __GNU__ + /* wait for keyboard or network activity */ FD_ZERO (&read_fds); - timeout.tv_sec = 0; - timeout.tv_usec = 8000; - - FD_SET (STDIN_FILENO, &read_fds); - - if (select (FD_SETSIZE, &read_fds, NULL, NULL, &timeout) > 0) - { - if (FD_ISSET (STDIN_FILENO, &read_fds)) - { - gui_keyboard_read (); - } - } - else - gui_keyboard_flush (); -#endif - - /* read sockets/files/pipes */ + FD_ZERO (&write_fds); + FD_ZERO (&except_fds); hook_fd_set (&read_fds, &write_fds, &except_fds); - -#ifdef __GNU__ - timeout.tv_sec = 0; - timeout.tv_usec = 10000; FD_SET (STDIN_FILENO, &read_fds); -#else - timeout.tv_sec = 0; - timeout.tv_usec = 2000; -#endif - - if (select (FD_SETSIZE, - &read_fds, &write_fds, &except_fds, - &timeout) > 0) + if (hook_timer_time_to_next (&tv_timeout)) + select (FD_SETSIZE, &read_fds, &write_fds, &except_fds, &tv_timeout); + else + select (FD_SETSIZE, &read_fds, &write_fds, &except_fds, NULL); + if (FD_ISSET (STDIN_FILENO, &read_fds)) { -#ifdef __GNU__ - if (FD_ISSET (STDIN_FILENO, &read_fds)) - { - gui_keyboard_read (); - } -#endif - hook_fd_exec (&read_fds, &write_fds, &except_fds); + gui_keyboard_read (); + gui_keyboard_flush (); } + hook_fd_exec (&read_fds, &write_fds, &except_fds); } } diff --git a/src/gui/gtk/gui-gtk-infobar.c b/src/gui/gtk/gui-gtk-infobar.c index b6bcafd33..4cbc5889e 100644 --- a/src/gui/gtk/gui-gtk-infobar.c +++ b/src/gui/gtk/gui-gtk-infobar.c @@ -28,6 +28,7 @@ #include "../../core/weechat.h" #include "../../core/wee-config.h" +#include "../../plugins/plugin.h" #include "../gui-infobar.h" #include "../gui-window.h" #include "gui-gtk.h" @@ -76,3 +77,29 @@ gui_infobar_draw (struct t_gui_buffer *buffer, int erase) (void) buffer; (void) erase; } + +/* + * gui_infobar_refresh_timer_cb: timer callback for refresh of infobar + */ + +int +gui_infobar_refresh_timer_cb (void *data) +{ + /* make C compiler happy */ + (void) data; + + return WEECHAT_RC_OK; +} + +/* + * gui_infobar_highlight_timer_cb: timer callback for highlights in infobar + */ + +int +gui_infobar_highlight_timer_cb (void *data) +{ + /* make C compiler happy */ + (void) data; + + return WEECHAT_RC_OK; +} diff --git a/src/gui/gui-completion.c b/src/gui/gui-completion.c index 32dd8015d..3689830ed 100644 --- a/src/gui/gui-completion.c +++ b/src/gui/gui-completion.c @@ -135,10 +135,10 @@ gui_completion_search_command (struct t_gui_completion *completion) { struct t_hook *ptr_hook; - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_COMMAND]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->type == HOOK_TYPE_COMMAND) + if (!ptr_hook->deleted && HOOK_COMMAND(ptr_hook, command) && HOOK_COMMAND(ptr_hook, command)[0] && (HOOK_COMMAND(ptr_hook, level) == 0) @@ -382,10 +382,10 @@ gui_completion_list_add_command_hooks (struct t_gui_completion *completion) { struct t_hook *ptr_hook; - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_COMMAND]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->type == HOOK_TYPE_COMMAND) + if (!ptr_hook->deleted && (HOOK_COMMAND(ptr_hook, command)) && (HOOK_COMMAND(ptr_hook, command)[0])) gui_completion_list_add (completion, @@ -592,10 +592,10 @@ gui_completion_list_add_weechat_cmd (struct t_gui_completion *completion) { struct t_hook *ptr_hook; - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_COMMAND]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->type == HOOK_TYPE_COMMAND) + if (!ptr_hook->deleted && !ptr_hook->plugin && HOOK_COMMAND(ptr_hook, command) && HOOK_COMMAND(ptr_hook, command)[0]) @@ -939,10 +939,10 @@ gui_completion_command (struct t_gui_completion *completion) other_completion = 0; if (!completion->completion_list->items) { - for (ptr_hook = weechat_hooks; ptr_hook; + for (ptr_hook = weechat_hooks[HOOK_TYPE_COMMAND]; ptr_hook; ptr_hook = ptr_hook->next_hook) { - if ((ptr_hook->type == HOOK_TYPE_COMMAND) + if (!ptr_hook->deleted && HOOK_COMMAND(ptr_hook, command) && HOOK_COMMAND(ptr_hook, command)[0] && (HOOK_COMMAND(ptr_hook, level) == 0)) diff --git a/src/gui/gui-infobar.c b/src/gui/gui-infobar.c index 99391f8ce..2f29dd5a8 100644 --- a/src/gui/gui-infobar.c +++ b/src/gui/gui-infobar.c @@ -28,13 +28,16 @@ #include <stdarg.h> #include "../core/weechat.h" +#include "../core/wee-hook.h" #include "../core/wee-log.h" #include "gui-infobar.h" #include "gui-color.h" #include "gui-window.h" -struct t_gui_infobar *gui_infobar; /* pointer to infobar content */ +struct t_gui_infobar *gui_infobar = NULL; /* infobar content */ +struct t_hook *gui_infobar_refresh_timer = NULL; /* refresh timer */ +struct t_hook *gui_infobar_highlight_timer = NULL; /* highlight timer */ /* @@ -73,6 +76,11 @@ gui_infobar_printf (int time_displayed, int color, char *message, ...) gui_infobar_draw (gui_current_window->buffer, 1); if (buf2) free (buf2); + + if (!gui_infobar_highlight_timer) + gui_infobar_highlight_timer = hook_timer (NULL, 1 * 1000, 0, 0, + &gui_infobar_highlight_timer_cb, + NULL); } else log_printf (_("Error: not enough memory for infobar message")); diff --git a/src/gui/gui-infobar.h b/src/gui/gui-infobar.h index 4e2c776ba..080c02110 100644 --- a/src/gui/gui-infobar.h +++ b/src/gui/gui-infobar.h @@ -35,6 +35,8 @@ struct t_gui_infobar /* infobar variables */ extern struct t_gui_infobar *gui_infobar; +extern struct t_hook *gui_infobar_refresh_timer; +extern struct t_hook *gui_infobar_highlight_timer; /* infobar functions */ @@ -46,5 +48,7 @@ extern void gui_infobar_remove_all (); extern void gui_infobar_draw_time (struct t_gui_buffer *); extern void gui_infobar_draw (struct t_gui_buffer *, int); +extern int gui_infobar_refresh_timer_cb (void *); +extern int gui_infobar_highlight_timer_cb (void *); #endif /* gui-infobar.h */ diff --git a/src/gui/gui-keyboard.c b/src/gui/gui-keyboard.c index d80b7a670..edc519042 100644 --- a/src/gui/gui-keyboard.c +++ b/src/gui/gui-keyboard.c @@ -180,6 +180,20 @@ gui_keyboard_init () } /* + * gui_keyboard_init_last_activity_time: init last activity time with current + * time + */ + +void +gui_keyboard_init_last_activity_time () +{ + struct timeval tv_time; + + gettimeofday (&tv_time, NULL); + gui_keyboard_last_activity_time = tv_time.tv_sec; +} + +/* * gui_keyboard_grab_init: init "grab" mode */ diff --git a/src/plugins/demo/demo.c b/src/plugins/demo/demo.c index 186f95218..dd3ce4161 100644 --- a/src/plugins/demo/demo.c +++ b/src/plugins/demo/demo.c @@ -82,6 +82,26 @@ demo_printf_command_cb (void *data, void *buffer, int argc, char **argv, } /* + * demo_infobar_command_cb: demo command for infobar + */ + +int +demo_infobar_command_cb (void *data, void *buffer, int argc, char **argv, + char **argv_eol) +{ + /* make C compiler happy */ + (void) data; + (void) buffer; + (void) argv; + + weechat_infobar_printf (10, NULL, + (argc > 1) ? + argv_eol[1] : _("test infobar")); + + return WEECHAT_RC_OK; +} + +/* * demo_buffer_input_data_cb: callback for input data on buffer */ @@ -286,6 +306,14 @@ weechat_plugin_init (struct t_weechat_plugin *plugin) "", &demo_printf_command_cb, NULL); + weechat_hook_command ("demo_infobar", + _("demo command: print a message in infobar for 10 " + "seconds"), + _("[text]"), + _("text: write this text on infobar"), + "", + &demo_infobar_command_cb, NULL); + weechat_hook_command ("demo_buffer", _("open a new buffer"), _("category name"), diff --git a/src/plugins/plugin-api.c b/src/plugins/plugin-api.c index 0e5386f1d..d2afc619f 100644 --- a/src/plugins/plugin-api.c +++ b/src/plugins/plugin-api.c @@ -1255,9 +1255,15 @@ plugin_api_infobar_printf (struct t_weechat_plugin *plugin, int time_displayed, va_end (argptr); buf2 = string_iconv_to_internal (plugin->charset, buf); - num_color = gui_color_search_config (color_name); - if (num_color < 0) + if (color_name && color_name[0]) + { + num_color = gui_color_search_config (color_name); + if (num_color < 0) + num_color = GUI_COLOR_INFOBAR; + } + else num_color = GUI_COLOR_INFOBAR; + gui_infobar_printf (time_displayed, num_color, "%s", @@ -1314,10 +1320,12 @@ plugin_api_hook_command (struct t_weechat_plugin *plugin, char *command, struct t_hook * plugin_api_hook_timer (struct t_weechat_plugin *plugin, long interval, - int max_calls, int (*callback)(void *), void *data) + int align_second, int max_calls, + int (*callback)(void *), void *data) { if (plugin && (interval > 0) && callback) - return hook_timer (plugin, interval, max_calls, callback, data); + return hook_timer (plugin, interval, align_second, max_calls, + callback, data); return NULL; } diff --git a/src/plugins/plugin-api.h b/src/plugins/plugin-api.h index d4e8c4777..ef1c31553 100644 --- a/src/plugins/plugin-api.h +++ b/src/plugins/plugin-api.h @@ -147,7 +147,7 @@ extern struct t_hook *plugin_api_hook_command (struct t_weechat_plugin *, int (*)(void *, void *, int, char **, char **), void *); extern struct t_hook *plugin_api_hook_timer (struct t_weechat_plugin *, - long, int, + long, int, int, int (*)(void *), void *); extern struct t_hook *plugin_api_hook_fd (struct t_weechat_plugin *, int, int, int, int, diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h index e73755310..d03d0535f 100644 --- a/src/plugins/weechat-plugin.h +++ b/src/plugins/weechat-plugin.h @@ -160,7 +160,7 @@ struct t_weechat_plugin char *, char *, char *, int (*)(void *, void *, int, char **, char **), void *); - struct t_hook *(*hook_timer) (struct t_weechat_plugin *, long, int, + struct t_hook *(*hook_timer) (struct t_weechat_plugin *, long, int, int, int (*)(void *), void *); struct t_hook *(*hook_fd) (struct t_weechat_plugin *, int, int, int, int, int (*)(void *), void *); @@ -407,8 +407,10 @@ struct t_weechat_plugin weechat_plugin->hook_command(weechat_plugin, __command, __description, \ __args, __args_desc, __completion, \ __callback, __data) -#define weechat_hook_timer(__interval, __max_calls, __callback, __data) \ - weechat_plugin->hook_timer(weechat_plugin, __interval, __max_calls, \ +#define weechat_hook_timer(__interval, __align_second, __max_calls, \ + __callback, __data) \ + weechat_plugin->hook_timer(weechat_plugin, __interval, \ + __align_second, __max_calls, \ __callback, __data) #define weechat_hook_fd(__fd, __flag_read, __flag_write, \ __flag_exception, __callback, __data) \ |