diff options
Diffstat (limited to 'src')
426 files changed, 23795 insertions, 5168 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index add1bc4d5..5da56614e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # Copyright (C) 2007-2008 Julien Louis <ptitlouis@sysif.net> # Copyright (C) 2008-2009 Emmanuel Bouthenot <kolter@openics.org> # diff --git a/src/Makefile.am b/src/Makefile.am index 199316400..75fa7906a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index ea0574c0e..8d84160d5 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # Copyright (C) 2008 Julien Louis <ptitlouis@sysif.net> # Copyright (C) 2009 Emmanuel Bouthenot <kolter@openics.org> # @@ -20,32 +20,33 @@ # set(LIB_CORE_SRC -weechat.c weechat.h -wee-arraylist.c wee-arraylist.h -wee-backtrace.c wee-backtrace.h -wee-command.c wee-command.h -wee-completion.c wee-completion.h -wee-config.c wee-config.h -wee-config-file.c wee-config-file.h -wee-debug.c wee-debug.h -wee-eval.c wee-eval.h -wee-hashtable.c wee-hashtable.h -wee-hdata.c wee-hdata.h -wee-hook.c wee-hook.h -wee-infolist.c wee-infolist.h -wee-input.c wee-input.h -wee-list.c wee-list.h -wee-log.c wee-log.h -wee-network.c wee-network.h -wee-proxy.c wee-proxy.h -wee-secure.c wee-secure.h -wee-string.c wee-string.h -wee-upgrade.c wee-upgrade.h -wee-upgrade-file.c wee-upgrade-file.h -wee-url.c wee-url.h -wee-utf8.c wee-utf8.h -wee-util.c wee-util.h -wee-version.c wee-version.h) + weechat.c weechat.h + wee-arraylist.c wee-arraylist.h + wee-backtrace.c wee-backtrace.h + wee-command.c wee-command.h + wee-completion.c wee-completion.h + wee-config.c wee-config.h + wee-config-file.c wee-config-file.h + wee-debug.c wee-debug.h + wee-eval.c wee-eval.h + wee-hashtable.c wee-hashtable.h + wee-hdata.c wee-hdata.h + wee-hook.c wee-hook.h + wee-infolist.c wee-infolist.h + wee-input.c wee-input.h + wee-list.c wee-list.h + wee-log.c wee-log.h + wee-network.c wee-network.h + wee-proxy.c wee-proxy.h + wee-secure.c wee-secure.h + wee-string.c wee-string.h + wee-upgrade.c wee-upgrade.h + wee-upgrade-file.c wee-upgrade-file.h + wee-url.c wee-url.h + wee-utf8.c wee-utf8.h + wee-util.c wee-util.h + wee-version.c wee-version.h +) # Check for flock support include(CheckSymbolExists) diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 002580d17..6d79fad75 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/core/wee-arraylist.c b/src/core/wee-arraylist.c index c9b1d27f0..729774892 100644 --- a/src/core/wee-arraylist.c +++ b/src/core/wee-arraylist.c @@ -1,7 +1,7 @@ /* * wee-arraylist.c - array lists management * - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -646,8 +646,8 @@ arraylist_clear (struct t_arraylist *arraylist) arraylist->size_alloc = 0; if (arraylist->size_alloc_min > 0) { - arraylist->data = calloc(arraylist->size_alloc_min, - sizeof (*arraylist->data)); + arraylist->data = calloc (arraylist->size_alloc_min, + sizeof (*arraylist->data)); if (!arraylist->data) return 0; arraylist->size_alloc = arraylist->size_alloc_min; diff --git a/src/core/wee-arraylist.h b/src/core/wee-arraylist.h index abed6114f..fc258dbe0 100644 --- a/src/core/wee-arraylist.h +++ b/src/core/wee-arraylist.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_ARRAYLIST_H -#define WEECHAT_ARRAYLIST_H 1 +#define WEECHAT_ARRAYLIST_H struct t_arraylist; diff --git a/src/core/wee-backtrace.c b/src/core/wee-backtrace.c index 23d289ba0..b7c024861 100644 --- a/src/core/wee-backtrace.c +++ b/src/core/wee-backtrace.c @@ -1,7 +1,7 @@ /* * wee-backtrace.c - backtrace after a segfault * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/core/wee-backtrace.h b/src/core/wee-backtrace.h index 341f9c9a4..e1ba7b1c5 100644 --- a/src/core/wee-backtrace.h +++ b/src/core/wee-backtrace.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_BACKTACE_H -#define WEECHAT_BACKTACE_H 1 +#define WEECHAT_BACKTACE_H #define BACKTRACE_MAX 128 diff --git a/src/core/wee-command.c b/src/core/wee-command.c index fee94fc5b..e02968bb2 100644 --- a/src/core/wee-command.c +++ b/src/core/wee-command.c @@ -1,7 +1,7 @@ /* * wee-command.c - WeeChat core commands * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2006 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -547,7 +547,7 @@ COMMAND_CALLBACK(buffer) long number, number1, number2, numbers[3]; char *error, *value, *pos, *str_number1, *pos_number2; int i, error_main_buffer, num_buffers, count, prev_number, clear_number; - int buffer_found; + int buffer_found, arg_name, type_free, switch_to_buffer; /* make C compiler happy */ (void) pointer; @@ -584,6 +584,42 @@ COMMAND_CALLBACK(buffer) return WEECHAT_RC_OK; } + /* create a new buffer */ + if (string_strcasecmp (argv[1], "add") == 0) + { + COMMAND_MIN_ARGS(3, "add"); + arg_name = 2; + type_free = 0; + switch_to_buffer = 0; + for (i = 2; i < argc; i++) + { + if (string_strcasecmp (argv[i], "-free") == 0) + type_free = 1; + else if (string_strcasecmp (argv[i], "-switch") == 0) + switch_to_buffer = 1; + else + arg_name = i; + } + if (gui_buffer_is_reserved_name (argv[arg_name])) + { + gui_chat_printf (NULL, + _("%sError: name \"%s\" is reserved for WeeChat"), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + argv[arg_name]); + return WEECHAT_RC_OK; + } + ptr_buffer = gui_buffer_search_by_name (PLUGIN_CORE, argv[arg_name]); + if (!ptr_buffer) + { + ptr_buffer = gui_buffer_new_user (argv[arg_name]); + if (ptr_buffer && type_free) + gui_buffer_set (ptr_buffer, "type", "free"); + } + if (ptr_buffer && switch_to_buffer) + gui_window_switch_to_buffer (gui_current_window, ptr_buffer, 1); + return WEECHAT_RC_OK; + } + /* clear content of buffer(s) */ if (string_strcasecmp (argv[1], "clear") == 0) { @@ -756,27 +792,20 @@ COMMAND_CALLBACK(buffer) return WEECHAT_RC_OK; } - /* merge buffer with another number in the list */ + /* merge buffer with another buffer in the list */ if (string_strcasecmp (argv[1], "merge") == 0) { COMMAND_MIN_ARGS(3, "merge"); error = NULL; - number = strtol (argv[2], &error, 10); - if (error && !error[0]) - { - ptr_buffer = gui_buffer_search_by_number ((int) number); - if (ptr_buffer) - gui_buffer_merge (buffer, ptr_buffer); - } - else + ptr_buffer = gui_buffer_search_by_number_or_name (argv[2]); + if (!ptr_buffer) { - /* invalid number */ gui_chat_printf (NULL, - _("%sError: incorrect buffer number"), + _("%sError: buffer not found"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]); return WEECHAT_RC_OK; } - + gui_buffer_merge (buffer, ptr_buffer); return WEECHAT_RC_OK; } @@ -934,7 +963,7 @@ COMMAND_CALLBACK(buffer) /* close buffer */ if (string_strcasecmp (argv[1], "close") == 0) { - weechat_buffer = gui_buffer_search_main(); + weechat_buffer = gui_buffer_search_main (); if (argc < 3) { @@ -1089,11 +1118,22 @@ COMMAND_CALLBACK(buffer) /* set a property on buffer */ if (string_strcasecmp (argv[1], "set") == 0) { - COMMAND_MIN_ARGS(4, "set"); - value = string_remove_quotes (argv_eol[3], "'\""); - gui_buffer_set (buffer, argv[2], (value) ? value : argv_eol[3]); - if (value) - free (value); + COMMAND_MIN_ARGS(3, "set"); + if (argc == 3) + { + /* + * default to empty value for valueless buffer "properties", + * e.g. localvar_del_xxx + */ + gui_buffer_set (buffer, argv[2], ""); + } + else + { + value = string_remove_quotes (argv_eol[3], "'\""); + gui_buffer_set (buffer, argv[2], (value) ? value : argv_eol[3]); + if (value) + free (value); + } return WEECHAT_RC_OK; } @@ -1840,7 +1880,7 @@ COMMAND_CALLBACK(debug) ptr_option = config_weechat_debug_get (argv[2]); if (ptr_option) { - config_file_option_free (ptr_option); + config_file_option_free (ptr_option, 1); config_weechat_debug_set_all (); gui_chat_printf (NULL, _("Debug disabled for \"%s\""), argv[2]); @@ -2110,6 +2150,9 @@ COMMAND_CALLBACK(filter) { buffer->filter = 1; gui_filter_buffer (buffer, NULL); + (void) hook_signal_send ( + "buffer_filters_enabled", + WEECHAT_HOOK_SIGNAL_POINTER, buffer); } } else @@ -2165,6 +2208,9 @@ COMMAND_CALLBACK(filter) { buffer->filter = 0; gui_filter_buffer (buffer, NULL); + (void) hook_signal_send ( + "buffer_filters_disabled", + WEECHAT_HOOK_SIGNAL_POINTER, buffer); } } else @@ -2218,6 +2264,10 @@ COMMAND_CALLBACK(filter) /* toggle filters in buffer */ buffer->filter ^= 1; gui_filter_buffer (buffer, NULL); + (void) hook_signal_send ( + (buffer->filter) ? + "buffer_filters_enabled" : "buffer_filters_disabled", + WEECHAT_HOOK_SIGNAL_POINTER, buffer); } else { @@ -4477,10 +4527,10 @@ COMMAND_CALLBACK(plugin) { plugin_argv = string_split (argv_eol[2], " ", 0, 0, &plugin_argc); - plugin_auto_load (plugin_argc, plugin_argv); + plugin_auto_load (plugin_argc, plugin_argv, 1, 1, 1); } else - plugin_auto_load (0, NULL); + plugin_auto_load (0, NULL, 1, 1, 1); return WEECHAT_RC_OK; } @@ -4514,7 +4564,7 @@ COMMAND_CALLBACK(plugin) if (strcmp (argv[2], "*") == 0) { plugin_unload_all (); - plugin_auto_load (plugin_argc, plugin_argv); + plugin_auto_load (plugin_argc, plugin_argv, 1, 1, 1); } else { @@ -4529,7 +4579,7 @@ COMMAND_CALLBACK(plugin) else { plugin_unload_all (); - plugin_auto_load (0, NULL); + plugin_auto_load (0, NULL, 1, 1, 1); } return WEECHAT_RC_OK; } @@ -4553,7 +4603,8 @@ COMMAND_CALLBACK(plugin) COMMAND_CALLBACK(print) { struct t_gui_buffer *ptr_buffer; - int i, escape, to_stdout, to_stderr; + int i, y, escape, to_stdout, to_stderr, arg_new_buffer_name; + int new_buffer_type_free, free_content, switch_to_buffer; time_t date, date_now; struct tm tm_date; char *tags, *pos, *text, *text2, *error, empty_string[1] = { '\0' }; @@ -4565,6 +4616,10 @@ COMMAND_CALLBACK(print) (void) data; ptr_buffer = buffer; + arg_new_buffer_name = -1; + new_buffer_type_free = 0; + switch_to_buffer = 0; + y = -1; date = 0; tags = NULL; prefix = NULL; @@ -4584,6 +4639,21 @@ COMMAND_CALLBACK(print) if (!ptr_buffer) COMMAND_ERROR; } + else if (string_strcasecmp (argv[i], "-newbuffer") == 0) + { + if (i + 1 >= argc) + COMMAND_ERROR; + i++; + arg_new_buffer_name = i; + } + else if (string_strcasecmp (argv[i], "-free") == 0) + { + new_buffer_type_free = 1; + } + else if (string_strcasecmp (argv[i], "-switch") == 0) + { + switch_to_buffer = 1; + } else if (string_strcasecmp (argv[i], "-current") == 0) { ptr_buffer = (gui_current_window) ? gui_current_window->buffer : NULL; @@ -4596,6 +4666,17 @@ COMMAND_CALLBACK(print) { escape = 1; } + else if (string_strcasecmp (argv[i], "-y") == 0) + { + if (i + 1 >= argc) + COMMAND_ERROR; + i++; + error = NULL; + value = strtol (argv[i], &error, 10); + if (!error || error[0]) + COMMAND_ERROR; + y = (int)value; + } else if (string_strcasecmp (argv[i], "-date") == 0) { if (i + 1 >= argc) @@ -4697,8 +4778,11 @@ COMMAND_CALLBACK(print) argv_eol[i] + 1 : argv_eol[i]; } else + { ptr_text = empty_string; + } + /* print to stdout or stderr */ if (to_stdout || to_stderr) { text = string_convert_escaped_chars (ptr_text); @@ -4708,37 +4792,78 @@ COMMAND_CALLBACK(print) fflush ((to_stdout) ? stdout : stderr); free (text); } + return WEECHAT_RC_OK; + } + + if (arg_new_buffer_name >= 0) + { + /* print to new buffer */ + if (gui_buffer_is_reserved_name (argv[arg_new_buffer_name])) + { + gui_chat_printf (NULL, + _("%sError: name \"%s\" is reserved for WeeChat"), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + argv[arg_new_buffer_name]); + return WEECHAT_RC_OK; + } + ptr_buffer = gui_buffer_search_by_name (PLUGIN_CORE, + argv[arg_new_buffer_name]); + if (!ptr_buffer) + { + ptr_buffer = gui_buffer_new_user (argv[arg_new_buffer_name]); + if (ptr_buffer && new_buffer_type_free) + gui_buffer_set (ptr_buffer, "type", "free"); + } } else { - text = strdup (ptr_text); - if (text) + /* print to existing buffer */ + if (!ptr_buffer) + ptr_buffer = gui_buffer_search_main (); + } + + free_content = (ptr_buffer && (ptr_buffer->type == GUI_BUFFER_TYPE_FREE)); + + text = strdup (ptr_text); + if (text) + { + pos = NULL; + if (!prefix) { - pos = NULL; - if (!prefix) + pos = strstr (text, "\\t"); + if (pos) { - pos = strstr (text, "\\t"); - if (pos) - { - pos[0] = '\t'; - memmove (pos + 1, pos + 2, strlen (pos + 2) + 1); - } + pos[0] = (free_content) ? ' ' : '\t'; + memmove (pos + 1, pos + 2, strlen (pos + 2) + 1); } - text2 = (escape) ? - string_convert_escaped_chars (text) : strdup (text); - if (text2) + } + text2 = (escape) ? + string_convert_escaped_chars (text) : strdup (text); + if (text2) + { + if (free_content) + { + gui_chat_printf_y (ptr_buffer, y, + "%s%s", + (prefix) ? prefix : "", + text2); + } + else { gui_chat_printf_date_tags ( ptr_buffer, date, tags, "%s%s", (prefix) ? prefix : ((!prefix && !pos) ? "\t" : ""), text2); - free (text2); } - free (text); + free (text2); } + free (text); } + if (ptr_buffer && switch_to_buffer) + gui_window_switch_to_buffer (gui_current_window, ptr_buffer, 1); + return WEECHAT_RC_OK; } @@ -5513,7 +5638,7 @@ command_set_display_option_list (const char *message, const char *search, * if we are displaying only changed options, skip options plugins.* * because they are all "changed" (default value is always empty string) */ - if (display_only_changed && strcmp(ptr_config->name, "plugins") == 0) + if (display_only_changed && (strcmp (ptr_config->name, "plugins") == 0)) continue; for (ptr_section = ptr_config->sections; ptr_section; ptr_section = ptr_section->next_section) @@ -6180,7 +6305,7 @@ COMMAND_CALLBACK(uptime) if ((argc >= 2) && (string_strcasecmp (argv[1], "-o") == 0)) { - snprintf (str_first_start, sizeof(str_first_start), + snprintf (str_first_start, sizeof (str_first_start), "%s", ctime (&weechat_first_start_time)); if (str_first_start[0]) str_first_start[strlen (str_first_start) - 1] = '\0'; @@ -6256,20 +6381,20 @@ command_version_display (struct t_gui_buffer *buffer, if (send_to_buffer_as_input && !translated_string) { - snprintf (str_first_start, sizeof(str_first_start), + snprintf (str_first_start, sizeof (str_first_start), "%s", ctime (&weechat_first_start_time)); if (str_first_start[0]) str_first_start[strlen (str_first_start) - 1] = '\0'; - snprintf (str_last_start, sizeof(str_last_start), + snprintf (str_last_start, sizeof (str_last_start), "%s", ctime (&weechat_last_start_time)); if (str_last_start[0]) str_last_start[strlen (str_last_start) - 1] = '\0'; } else { - snprintf (str_first_start, sizeof(str_first_start), + snprintf (str_first_start, sizeof (str_first_start), "%s", util_get_time_string (&weechat_first_start_time)); - snprintf (str_last_start, sizeof(str_last_start), + snprintf (str_last_start, sizeof (str_last_start), "%s", util_get_time_string (&weechat_last_start_time)); } } @@ -6967,11 +7092,12 @@ command_init () NULL, "buffer", N_("manage buffers"), N_("list" + " || add [-free] [-switch] <name>" " || clear [<number>|<name>|-merged|-all [<number>|<name>...]]" " || move <number>|-|+" " || swap <number1>|<name1> [<number2>|<name2>]" " || cycle <number>|<name> [<number>|<name>...]" - " || merge <number>" + " || merge <number>|<name>" " || unmerge [<number>|-all]" " || hide [<number>|<name>|-all [<number>|<name>...]]" " || unhide [<number>|<name>|-all [<number>|<name>...]]" @@ -6979,10 +7105,12 @@ command_init () " || close [<n1>[-<n2>]|<name>]" " || notify <level>" " || localvar" - " || set <property> <value>" + " || set <property> [<value>]" " || get <property>" " || <number>|-|+|<name>"), N_(" list: list buffers (without argument, this list is displayed)\n" + " add: add a new buffer (it can be closed with \"/buffer close\" " + "or input \"q\")\n" " clear: clear buffer content (number for a buffer, -merged for " "merged buffers, -all for all buffers, or nothing for current buffer)\n" " move: move buffer in the list (may be relative, for example -1); " @@ -7032,6 +7160,8 @@ command_init () " /buffer cycle #chan1 #chan2 #chan3\n" " merge with core buffer:\n" " /buffer merge 1\n" + " merge with #weechat buffer:\n" + " /buffer merge #weechat\n" " unmerge buffer:\n" " /buffer unmerge\n" " close current buffer:\n" @@ -7044,13 +7174,14 @@ command_init () " /buffer +1\n" " jump to last buffer number:\n" " /buffer +"), - "clear -merged|-all|%(buffers_numbers)|%(buffers_plugins_names) " + "add -free|-switch" + " || clear -merged|-all|%(buffers_numbers)|%(buffers_plugins_names) " "%(buffers_numbers)|%(buffers_plugins_names)|%*" " || move %(buffers_numbers)" " || swap %(buffers_numbers)|%(buffers_plugins_names) " "%(buffers_numbers)|%(buffers_plugins_names)" " || cycle %(buffers_numbers)|%(buffers_plugins_names)|%*" - " || merge %(buffers_numbers)" + " || merge %(buffers_numbers)|%(buffers_plugins_names)" " || unmerge %(buffers_numbers)|-all" " || hide %(buffers_numbers)|%(buffers_plugins_names)|-all " "%(buffers_numbers)|%(buffers_plugins_names)|%*" @@ -7241,10 +7372,13 @@ command_init () "\n" "An expression is considered as \"true\" if it is not NULL, not " "empty, and different from \"0\".\n" - "The comparison is made using integers if the two expressions are " - "valid integers.\n" - "To force a string comparison, add double quotes around each " - "expression, for example:\n" + "The comparison is made using floating point numbers if the two " + "expressions are valid numbers, with one of the following formats:\n" + " - integer (examples: 5, -7)\n" + " - floating point number (examples: 5.2, -7.5, 2.83e-2)\n" + " - hexadecimal number (examples: 0xA3, -0xA3)\n" + "To force a string comparison, you can add double quotes around " + "each expression, for example:\n" " 50 > 100 ==> 0\n" " \"50\" > \"100\" ==> 1\n" "\n" @@ -7291,6 +7425,7 @@ command_init () " /eval -n ${info:version} ==> 0.4.3\n" " /eval -n ${env:HOME} ==> /home/user\n" " /eval -n ${weechat.look.scroll_amount} ==> 3\n" + " /eval -n ${sec.data.freenode_password} ==> secret\n" " /eval -n ${window} ==> 0x2549aa0\n" " /eval -n ${window.buffer} ==> 0x2549320\n" " /eval -n ${window.buffer.full_name} ==> core.weechat\n" @@ -7549,7 +7684,7 @@ command_init () "format: \"@area:key\" or \"@area1>area2:key\" where area can be:\n" " *: any area on screen\n" " chat: chat area (any buffer)\n" - " chat(xxx): char area for buffer with name \"xxx\" (full name " + " chat(xxx): chat area for buffer with name \"xxx\" (full name " "including plugin)\n" " bar(*): any bar\n" " bar(xxx): bar \"xxx\"\n" @@ -7691,29 +7826,39 @@ command_init () hook_command ( NULL, "print", N_("display text on a buffer"), - N_("[-buffer <number>|<name>] [-core] [-escape] [-date <date>] " + N_("[-buffer <number>|<name>] [-newbuffer <name>] [-free] [-switch] " + "[-core|-current] [-y <line>] [-escape] [-date <date>] " "[-tags <tags>] [-action|-error|-join|-network|-quit] [<text>]" " || -stdout|-stderr [<text>]" " || -beep"), - N_(" -buffer: display text in this buffer (default: buffer where " + N_(" -buffer: display text in this buffer (default: buffer where " "command is executed)\n" - " -core: alias of \"-buffer core.weechat\"\n" - "-current: display text on current buffer\n" - " -escape: interpret escaped chars (for example \\a, \\07, \\x07)\n" - " -date: message date, format can be:\n" - " -n: 'n' seconds before now\n" - " +n: 'n' seconds in the future\n" - " n: 'n' seconds since the Epoch (see man time)\n" - " date/time (ISO 8601): yyyy-mm-ddThh:mm:ss, example: " + "-newbuffer: create a new buffer and display text in this buffer\n" + " -free: create a buffer with free content " + "(with -newbuffer only)\n" + " -switch: switch to the buffer\n" + " -core: alias of \"-buffer core.weechat\"\n" + " -current: display text on current buffer\n" + " -y: display on a custom line (for buffer with free content " + "only)\n" + " line: line number for buffer with free content (first line " + "is 0, a negative number displays after last line: -1 = after last " + "line, -2 = two lines after last line, ...)\n" + " -escape: interpret escaped chars (for example \\a, \\07, \\x07)\n" + " -date: message date, format can be:\n" + " -n: 'n' seconds before now\n" + " +n: 'n' seconds in the future\n" + " n: 'n' seconds since the Epoch (see man time)\n" + " date/time (ISO 8601): yyyy-mm-ddThh:mm:ss, example: " "2014-01-19T04:32:55\n" - " time: hh:mm:ss (example: 04:32:55)\n" - " -tags: comma-separated list of tags (see /help filter for a " + " time: hh:mm:ss (example: 04:32:55)\n" + " -tags: comma-separated list of tags (see /help filter for a " "list of tags most commonly used)\n" - " text: text to display (prefix and message must be separated by " + " text: text to display (prefix and message must be separated by " "\"\\t\", if text starts with \"-\", then add a \"\\\" before)\n" - " -stdout: display text on stdout (escaped chars are interpreted)\n" - " -stderr: display text on stderr (escaped chars are interpreted)\n" - " -beep: alias of \"-stderr \\a\"\n" + " -stdout: display text on stdout (escaped chars are interpreted)\n" + " -stderr: display text on stderr (escaped chars are interpreted)\n" + " -beep: alias of \"-stderr \\a\"\n" "\n" "The options -action ... -quit use the prefix defined in options " "\"weechat.look.prefix_*\".\n" @@ -7736,8 +7881,10 @@ command_init () " send alert (BEL):\n" " /print -beep"), "-buffer %(buffers_numbers)|%(buffers_plugins_names)" - " || -core|-escape|-date|-tags|-action|-error|-join|-network|-quit" - " || -prefix" + " || -newbuffer" + " || -y -1|0|1|2|3" + " || -free|-switch|-core|-current|-escape|-date|-tags|-action|-error|" + "-join|-network|-quit" " || -stdout" " || -stderr" " || -beep", @@ -7892,7 +8039,8 @@ command_init () N_("[<option> [<value>]]" " || diff [<option> [<option>...]]" " || env [<variable> [<value>]]"), - N_("option: name of an option (wildcard \"*\" is allowed)\n" + N_("option: name of an option (wildcard \"*\" is allowed to list " + "options, if no value is specified)\n" " value: new value for option, according to type:\n" " boolean: on, off or toggle\n" " integer: number, ++number or --number\n" @@ -7947,7 +8095,7 @@ command_init () &command_unset, NULL, NULL); hook_command ( NULL, "upgrade", - N_("upgrade WeeChat without disconnecting from servers"), + N_("reload the WeeChat binary without disconnecting from servers"), N_("[-yes] [<path_to_binary>|-quit]"), N_(" -yes: required if option \"weechat.look.confirm_upgrade\" " "is enabled\n" @@ -8197,9 +8345,9 @@ command_startup (int plugins_loaded) { if (plugins_loaded) { - command_exec_list(CONFIG_STRING(config_startup_command_after_plugins)); - command_exec_list(weechat_startup_commands); + command_exec_list (CONFIG_STRING(config_startup_command_after_plugins)); + command_exec_list (weechat_startup_commands); } else - command_exec_list(CONFIG_STRING(config_startup_command_before_plugins)); + command_exec_list (CONFIG_STRING(config_startup_command_before_plugins)); } diff --git a/src/core/wee-command.h b/src/core/wee-command.h index 9c7dab125..c57c0106b 100644 --- a/src/core/wee-command.h +++ b/src/core/wee-command.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2006 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -19,7 +19,7 @@ */ #ifndef WEECHAT_COMMAND_H -#define WEECHAT_COMMAND_H 1 +#define WEECHAT_COMMAND_H #define COMMAND_CALLBACK(__command) \ int \ diff --git a/src/core/wee-completion.c b/src/core/wee-completion.c index ec710e1b6..ec2da787f 100644 --- a/src/core/wee-completion.c +++ b/src/core/wee-completion.c @@ -1,7 +1,7 @@ /* * wee-completion.c - completion for WeeChat commands * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -616,7 +616,7 @@ completion_list_add_commands_cb (const void *pointer, void *data, { if (pos) { - snprintf (str_command, sizeof(str_command), + snprintf (str_command, sizeof (str_command), "%s%s", pos, HOOK_COMMAND(ptr_hook, command)); @@ -875,7 +875,7 @@ completion_list_add_plugins_installed_cb (const void *pointer, void *data, struct t_gui_buffer *buffer, struct t_gui_completion *completion) { - char *plugin_path, *plugin_path2, *dir_name; + char *plugin_path, *plugin_path2, *dir_name, *extra_libdir; int length; /* make C compiler happy */ @@ -884,6 +884,22 @@ completion_list_add_plugins_installed_cb (const void *pointer, void *data, (void) completion_item; (void) buffer; + /* plugins in WeeChat extra lib dir */ + extra_libdir = getenv (WEECHAT_EXTRA_LIBDIR); + if (extra_libdir && extra_libdir[0]) + { + length = strlen (extra_libdir) + 16 + 1; + dir_name = malloc (length); + if (dir_name) + { + snprintf (dir_name, length, "%s/plugins", extra_libdir); + util_exec_on_files (dir_name, 1, 0, + &completion_list_add_plugins_installed_exec_cb, + completion); + free (dir_name); + } + } + /* plugins in WeeChat home dir */ if (CONFIG_STRING(config_plugin_path) && CONFIG_STRING(config_plugin_path)[0]) @@ -897,6 +913,7 @@ completion_list_add_plugins_installed_cb (const void *pointer, void *data, (plugin_path2) ? plugin_path2 : ((plugin_path) ? plugin_path : CONFIG_STRING(config_plugin_path)), + 1, 0, &completion_list_add_plugins_installed_exec_cb, completion); @@ -912,7 +929,7 @@ completion_list_add_plugins_installed_cb (const void *pointer, void *data, if (dir_name) { snprintf (dir_name, length, "%s/plugins", WEECHAT_LIBDIR); - util_exec_on_files (dir_name, 0, + util_exec_on_files (dir_name, 1, 0, &completion_list_add_plugins_installed_exec_cb, completion); free (dir_name); @@ -983,7 +1000,7 @@ completion_list_add_plugins_commands_cb (const void *pointer, void *data, { if (pos) { - snprintf (str_command, sizeof(str_command), + snprintf (str_command, sizeof (str_command), "%s%s", pos, HOOK_COMMAND(ptr_hook, command)); @@ -1000,7 +1017,7 @@ completion_list_add_plugins_commands_cb (const void *pointer, void *data, } } - string_free_split(argv); + string_free_split (argv); return WEECHAT_RC_OK; } @@ -1264,7 +1281,7 @@ completion_list_add_weechat_commands_cb (const void *pointer, void *data, { if (pos) { - snprintf (str_command, sizeof(str_command), + snprintf (str_command, sizeof (str_command), "%s%s", pos, HOOK_COMMAND(ptr_hook, command)); diff --git a/src/core/wee-completion.h b/src/core/wee-completion.h index 65ff60a3e..89b7dafb2 100644 --- a/src/core/wee-completion.h +++ b/src/core/wee-completion.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_COMPLETION_H -#define WEECHAT_COMPLETION_H 1 +#define WEECHAT_COMPLETION_H struct t_gui_buffer; struct t_gui_completion; diff --git a/src/core/wee-config-file.c b/src/core/wee-config-file.c index 208a4924b..56e949688 100644 --- a/src/core/wee-config-file.c +++ b/src/core/wee-config-file.c @@ -1,7 +1,7 @@ /* * wee-config-file.c - configuration files/sections/options management * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2006 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -1588,7 +1588,7 @@ config_file_option_unset (struct t_config_option *option) } else { - config_file_option_free (option); + config_file_option_free (option, 0); rc = WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED; } @@ -1692,6 +1692,8 @@ config_file_option_rename (struct t_config_option *option, free (full_old_name); if (full_new_name) free (full_new_name); + + config_file_hook_config_exec (option); } /* @@ -1824,7 +1826,11 @@ config_file_option_get_string (struct t_config_option *option, if (!option || !property) return NULL; - if (string_strcasecmp (property, "name") == 0) + if (string_strcasecmp (property, "config_name") == 0) + return option->config_file->name; + else if (string_strcasecmp (property, "section_name") == 0) + return option->section->name; + else if (string_strcasecmp (property, "name") == 0) return option->name; else if (string_strcasecmp (property, "parent_name") == 0) return option->parent_name; @@ -1941,7 +1947,7 @@ int config_file_option_has_changed (struct t_config_option *option) case CONFIG_OPTION_TYPE_INTEGER: return CONFIG_INTEGER(option) != CONFIG_INTEGER_DEFAULT(option); case CONFIG_OPTION_TYPE_STRING: - return strcmp(CONFIG_STRING(option), CONFIG_STRING_DEFAULT(option)) != 0; + return strcmp (CONFIG_STRING(option), CONFIG_STRING_DEFAULT(option)) != 0; case CONFIG_OPTION_TYPE_COLOR: return CONFIG_COLOR(option) != CONFIG_COLOR_DEFAULT(option); case CONFIG_NUM_OPTION_TYPES: @@ -2449,6 +2455,17 @@ config_file_write_internal (struct t_config_file *config_file, if (fflush (config_file->file) != 0) goto error; + /* + * ensure the file is really written on the storage device; + * this is disabled by default because it is really slow + * (about 20 to 200x slower) + */ + if (CONFIG_BOOLEAN(config_look_save_config_with_fsync)) + { + if (fsync (fileno (config_file->file)) != 0) + goto error; + } + /* close temp file */ fclose (config_file->file); config_file->file = NULL; @@ -2651,7 +2668,7 @@ config_file_read_internal (struct t_config_file *config_file, int reload) { undefined_value = 0; /* remove simple or double quotes and spaces at the end */ - if (strlen(pos) > 1) + if (strlen (pos) > 1) { pos2 = pos + strlen (pos) - 1; while ((pos2 > pos) && (pos2[0] == ' ')) @@ -2864,14 +2881,18 @@ config_file_option_free_data (struct t_config_option *option) */ void -config_file_option_free (struct t_config_option *option) +config_file_option_free (struct t_config_option *option, int run_callback) { struct t_config_section *ptr_section; struct t_config_option *new_options; + char *option_full_name; if (!option) return; + option_full_name = (run_callback) ? + config_file_option_full_name (option) : NULL; + ptr_section = option->section; /* free data */ @@ -2895,6 +2916,12 @@ config_file_option_free (struct t_config_option *option) } free (option); + + if (option_full_name) + { + hook_config_exec (option_full_name, NULL); + free (option_full_name); + } } /* @@ -2909,7 +2936,7 @@ config_file_section_free_options (struct t_config_section *section) while (section->options) { - config_file_option_free (section->options); + config_file_option_free (section->options, 0); } } @@ -3176,11 +3203,11 @@ config_file_hdata_config_option_cb (const void *pointer, void *data, */ int -config_file_add_option_to_infolist(struct t_infolist *infolist, - struct t_config_file *config_file, - struct t_config_section *section, - struct t_config_option *option, - const char *option_name) +config_file_add_option_to_infolist (struct t_infolist *infolist, + struct t_config_file *config_file, + struct t_config_section *section, + struct t_config_option *option, + const char *option_name) { char *option_full_name, *value, *string_values; struct t_config_option *ptr_parent_option; diff --git a/src/core/wee-config-file.h b/src/core/wee-config-file.h index 10b635e44..666fa751c 100644 --- a/src/core/wee-config-file.h +++ b/src/core/wee-config-file.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2006 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -19,7 +19,9 @@ */ #ifndef WEECHAT_CONFIG_FILE_H -#define WEECHAT_CONFIG_FILE_H 1 +#define WEECHAT_CONFIG_FILE_H + +#include <stdio.h> #define CONFIG_BOOLEAN(option) (*((int *)((option)->value))) #define CONFIG_BOOLEAN_DEFAULT(option) (*((int *)((option)->default_value))) @@ -287,7 +289,8 @@ extern int config_file_write_line (struct t_config_file *config_file, extern int config_file_write (struct t_config_file *config_files); extern int config_file_read (struct t_config_file *config_file); extern int config_file_reload (struct t_config_file *config_file); -extern void config_file_option_free (struct t_config_option *option); +extern void config_file_option_free (struct t_config_option *option, + int run_callback); extern void config_file_section_free_options (struct t_config_section *section); extern void config_file_section_free (struct t_config_section *section); extern void config_file_free (struct t_config_file *config_file); diff --git a/src/core/wee-config.c b/src/core/wee-config.c index 3589a042a..a44e0b80f 100644 --- a/src/core/wee-config.c +++ b/src/core/wee-config.c @@ -1,7 +1,7 @@ /* * wee-config.c - WeeChat configuration options (file weechat.conf) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2006 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -178,6 +178,7 @@ struct t_config_option *config_look_read_marker; struct t_config_option *config_look_read_marker_always_show; struct t_config_option *config_look_read_marker_string; struct t_config_option *config_look_save_config_on_exit; +struct t_config_option *config_look_save_config_with_fsync; struct t_config_option *config_look_save_layout_on_exit; struct t_config_option *config_look_scroll_amount; struct t_config_option *config_look_scroll_bottom_after_switch; @@ -272,6 +273,7 @@ struct t_config_option *config_completion_partial_completion_command; struct t_config_option *config_completion_partial_completion_command_arg; struct t_config_option *config_completion_partial_completion_count; struct t_config_option *config_completion_partial_completion_other; +struct t_config_option *config_completion_partial_completion_templates; /* config, history section */ @@ -317,6 +319,7 @@ char **config_nick_colors = NULL; int config_num_nick_colors = 0; struct t_hashtable *config_hashtable_nick_color_force = NULL; char *config_item_time_evaluated = NULL; +struct t_hashtable *config_hashtable_completion_partial_templates = NULL; /* @@ -994,9 +997,10 @@ config_get_item_time (char *text_time, int max_length) date = time (NULL); local_time = localtime (&date); - strftime (text_time, max_length, - config_item_time_evaluated, - local_time); + if (strftime (text_time, max_length, + config_item_time_evaluated, + local_time) == 0) + text_time[0] = '\0'; } /* @@ -1173,6 +1177,51 @@ config_change_nick_colors (const void *pointer, void *data, } /* + * Callback for changes on option + * "weechat.completion.partial_completion_templates". + */ + +void +config_change_completion_partial_completion_templates (const void *pointer, + void *data, + struct t_config_option *option) +{ + char **items; + int num_items, i; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) option; + + if (!config_hashtable_completion_partial_templates) + { + config_hashtable_completion_partial_templates = hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, + NULL, NULL); + } + else + { + hashtable_remove_all (config_hashtable_completion_partial_templates); + } + + items = string_split ( + CONFIG_STRING(config_completion_partial_completion_templates), + ",", 0, 0, &num_items); + if (items) + { + for (i = 0; i < num_items; i++) + { + hashtable_set (config_hashtable_completion_partial_templates, + items[i], NULL); + } + string_free_split (items); + } +} + +/* * Callback for changes on option "weechat.network.gnutls_ca_file". */ @@ -1281,7 +1330,8 @@ config_day_change_timer_cb (const void *pointer, void *data, } /* send signal "day_changed" */ - strftime (str_time, sizeof (str_time), "%Y-%m-%d", local_time); + if (strftime (str_time, sizeof (str_time), "%Y-%m-%d", local_time) == 0) + str_time[0] = '\0'; (void) hook_signal_send ("day_changed", WEECHAT_HOOK_SIGNAL_STRING, str_time); } @@ -1466,7 +1516,7 @@ config_weechat_debug_create_option_cb (const void *pointer, void *data, rc = config_file_option_set (ptr_option, value, 1); else { - config_file_option_free (ptr_option); + config_file_option_free (ptr_option, 1); rc = WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; } } @@ -1512,7 +1562,7 @@ config_weechat_debug_delete_option_cb (const void *pointer, void *data, (void) config_file; (void) section; - config_file_option_free (option); + config_file_option_free (option, 1); config_weechat_debug_set_all (); @@ -1592,7 +1642,7 @@ config_weechat_palette_create_option_cb (const void *pointer, void *data, rc = config_file_option_set (ptr_option, value, 1); else { - config_file_option_free (ptr_option); + config_file_option_free (ptr_option, 1); rc = WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; } } @@ -1652,7 +1702,7 @@ config_weechat_palette_delete_option_cb (const void *pointer, void *data, if (error && !error[0]) gui_color_palette_remove (number); - config_file_option_free (option); + config_file_option_free (option, 1); return WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED; } @@ -2088,7 +2138,7 @@ config_weechat_notify_create_option_cb (const void *pointer, void *data, rc = config_file_option_set (ptr_option, value, 1); else { - config_file_option_free (ptr_option); + config_file_option_free (ptr_option, 1); rc = WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; } } @@ -2134,7 +2184,7 @@ config_weechat_notify_delete_option_cb (const void *pointer, void *data, (void) config_file; (void) section; - config_file_option_free (option); + config_file_option_free (option, 1); gui_buffer_notify_set_all (); @@ -2376,6 +2426,7 @@ config_weechat_init_options () if (!ptr_section) { config_file_free (weechat_config_file); + weechat_config_file = NULL; return 0; } @@ -2392,6 +2443,7 @@ config_weechat_init_options () if (!ptr_section) { config_file_free (weechat_config_file); + weechat_config_file = NULL; return 0; } @@ -2446,6 +2498,7 @@ config_weechat_init_options () if (!ptr_section) { config_file_free (weechat_config_file); + weechat_config_file = NULL; return 0; } @@ -2831,8 +2884,10 @@ config_weechat_init_options () config_look_hotlist_count_max = config_file_new_option ( weechat_config_file, ptr_section, "hotlist_count_max", "integer", - N_("max number of messages count to display in hotlist for a buffer " - "(0 = never display messages count)"), + N_("max number of messages count to display in hotlist for a buffer: " + "0 = never display messages count, " + "other number = display max N messages count (from the highest to " + "lowest priority)"), NULL, 0, GUI_HOTLIST_NUM_PRIORITIES, "2", NULL, 0, NULL, NULL, NULL, &config_change_buffer_content, NULL, NULL, @@ -3139,7 +3194,9 @@ config_weechat_init_options () weechat_config_file, ptr_section, "paste_max_lines", "integer", N_("max number of lines for paste without asking user " - "(-1 = disable this feature)"), + "(-1 = disable this feature); this option is used only if the bar " + "item \"input_paste\" is used in at least one bar (by default it " + "is used in \"input\" bar)"), NULL, -1, INT_MAX, "1", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); config_look_prefix[GUI_CHAT_PREFIX_ERROR] = config_file_new_option ( @@ -3343,6 +3400,17 @@ config_weechat_init_options () NULL, NULL, NULL, &config_change_save_config_on_exit, NULL, NULL, NULL, NULL, NULL); + config_look_save_config_with_fsync = config_file_new_option ( + weechat_config_file, ptr_section, + "save_config_with_fsync", "boolean", + N_("use fsync to synchronize the configuration file with the storage " + "device (see man fsync); this is slower but should prevent any " + "data loss in case of power failure during the save of " + "configuration file"), + NULL, 0, 0, "off", NULL, 0, + NULL, NULL, NULL, + &config_change_save_config_on_exit, NULL, NULL, + NULL, NULL, NULL); config_look_save_layout_on_exit = config_file_new_option ( weechat_config_file, ptr_section, "save_layout_on_exit", "integer", @@ -3446,8 +3514,9 @@ config_weechat_init_options () "window_title", "string", N_("title for window (terminal for Curses GUI), set on startup; " "an empty string will keep title unchanged " - "(note: content is evaluated, see /help eval)"), - NULL, 0, 0, "WeeChat ${info:version}", NULL, 0, + "(note: content is evaluated, see /help eval); example: " + "\"WeeChat ${info:version}\""), + NULL, 0, 0, "", NULL, 0, NULL, NULL, NULL, &config_change_window_title, NULL, NULL, NULL, NULL, NULL); @@ -3496,6 +3565,7 @@ config_weechat_init_options () if (!ptr_section) { config_file_free (weechat_config_file); + weechat_config_file = NULL; return 0; } @@ -3510,6 +3580,7 @@ config_weechat_init_options () if (!ptr_section) { config_file_free (weechat_config_file); + weechat_config_file = NULL; return 0; } @@ -4070,6 +4141,7 @@ config_weechat_init_options () if (!ptr_section) { config_file_free (weechat_config_file); + weechat_config_file = NULL; return 0; } @@ -4133,7 +4205,7 @@ config_weechat_init_options () config_completion_partial_completion_alert = config_file_new_option ( weechat_config_file, ptr_section, "partial_completion_alert", "boolean", - N_("alert user when a partial completion occurs"), + N_("send alert (BEL) when a partial completion occurs"), NULL, 0, 0, "on", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); config_completion_partial_completion_command = config_file_new_option ( @@ -4163,6 +4235,17 @@ config_weechat_init_options () "begin with same letters)"), NULL, 0, 0, "off", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + config_completion_partial_completion_templates = config_file_new_option ( + weechat_config_file, ptr_section, + "partial_completion_templates", "string", + N_("comma-separated list of templates for which partial completion is " + "enabled by default (with Tab key instead of shift-Tab); " + "the list of templates is in documentation: plugin API reference, " + "function \"weechat_hook_command\""), + NULL, 0, 0, "config_options", NULL, 0, + NULL, NULL, NULL, + &config_change_completion_partial_completion_templates, NULL, NULL, + NULL, NULL, NULL); /* history */ ptr_section = config_file_new_section (weechat_config_file, "history", @@ -4175,6 +4258,7 @@ config_weechat_init_options () if (!ptr_section) { config_file_free (weechat_config_file); + weechat_config_file = NULL; return 0; } @@ -4228,6 +4312,7 @@ config_weechat_init_options () if (!ptr_section) { config_file_free (weechat_config_file); + weechat_config_file = NULL; return 0; } @@ -4244,6 +4329,7 @@ config_weechat_init_options () if (!ptr_section) { config_file_free (weechat_config_file); + weechat_config_file = NULL; return 0; } @@ -4291,6 +4377,7 @@ config_weechat_init_options () if (!ptr_section) { config_file_free (weechat_config_file); + weechat_config_file = NULL; return 0; } @@ -4345,6 +4432,7 @@ config_weechat_init_options () if (!ptr_section) { config_file_free (weechat_config_file); + weechat_config_file = NULL; return 0; } @@ -4362,6 +4450,7 @@ config_weechat_init_options () if (!ptr_section) { config_file_free (weechat_config_file); + weechat_config_file = NULL; return 0; } @@ -4377,6 +4466,7 @@ config_weechat_init_options () if (!ptr_section) { config_file_free (weechat_config_file); + weechat_config_file = NULL; return 0; } @@ -4394,6 +4484,7 @@ config_weechat_init_options () if (!ptr_section) { config_file_free (weechat_config_file); + weechat_config_file = NULL; return 0; } @@ -4415,6 +4506,7 @@ config_weechat_init_options () if (!ptr_section) { config_file_free (weechat_config_file); + weechat_config_file = NULL; return 0; } } @@ -4472,6 +4564,8 @@ config_weechat_init () config_change_word_chars_highlight (NULL, NULL, NULL); if (!config_word_chars_input) config_change_word_chars_input (NULL, NULL, NULL); + if (!config_hashtable_completion_partial_templates) + config_change_completion_partial_completion_templates (NULL, NULL, NULL); return rc; } @@ -4580,4 +4674,10 @@ config_weechat_free () free (config_item_time_evaluated); config_item_time_evaluated = NULL; } + + if (config_hashtable_completion_partial_templates) + { + hashtable_free (config_hashtable_completion_partial_templates); + config_hashtable_completion_partial_templates = NULL; + } } diff --git a/src/core/wee-config.h b/src/core/wee-config.h index 1ab3b763d..a5d4b3e9c 100644 --- a/src/core/wee-config.h +++ b/src/core/wee-config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2006 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -19,7 +19,7 @@ */ #ifndef WEECHAT_CONFIG_H -#define WEECHAT_CONFIG_H 1 +#define WEECHAT_CONFIG_H #include <regex.h> #include <wctype.h> @@ -229,6 +229,7 @@ extern struct t_config_option *config_look_read_marker; extern struct t_config_option *config_look_read_marker_always_show; extern struct t_config_option *config_look_read_marker_string; extern struct t_config_option *config_look_save_config_on_exit; +extern struct t_config_option *config_look_save_config_with_fsync; extern struct t_config_option *config_look_save_layout_on_exit; extern struct t_config_option *config_look_scroll_amount; extern struct t_config_option *config_look_scroll_bottom_after_switch; @@ -319,6 +320,7 @@ extern struct t_config_option *config_completion_partial_completion_command; extern struct t_config_option *config_completion_partial_completion_command_arg; extern struct t_config_option *config_completion_partial_completion_count; extern struct t_config_option *config_completion_partial_completion_other; +extern struct t_config_option *config_completion_partial_completion_templates; extern struct t_config_option *config_history_display_default; extern struct t_config_option *config_history_max_buffer_lines_minutes; @@ -353,6 +355,7 @@ extern int config_word_chars_input_count; extern char **config_nick_colors; extern int config_num_nick_colors; extern struct t_hashtable *config_hashtable_nick_color_force; +extern struct t_hashtable *config_hashtable_completion_partial_templates; extern void config_set_nick_colors (); extern struct t_config_option *config_weechat_debug_get (const char *plugin_name); diff --git a/src/core/wee-debug.c b/src/core/wee-debug.c index 9bd33b4ba..7b2929b28 100644 --- a/src/core/wee-debug.c +++ b/src/core/wee-debug.c @@ -1,7 +1,7 @@ /* * wee-debug.c - debug functions * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -571,12 +571,18 @@ debug_libs_cb (const void *pointer, void *data, void debug_directories () { + char *extra_libdir; + + extra_libdir = getenv (WEECHAT_EXTRA_LIBDIR); + gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("Directories:")); - gui_chat_printf (NULL, " home : %s (%s: %s)", + gui_chat_printf (NULL, " home: %s (%s: %s)", weechat_home, _("default"), WEECHAT_HOME); - gui_chat_printf (NULL, " lib : %s", WEECHAT_LIBDIR); - gui_chat_printf (NULL, " share : %s", WEECHAT_SHAREDIR); + gui_chat_printf (NULL, " lib: %s", WEECHAT_LIBDIR); + gui_chat_printf (NULL, " lib (extra): %s", + (extra_libdir && extra_libdir[0]) ? extra_libdir : "-"); + gui_chat_printf (NULL, " share: %s", WEECHAT_SHAREDIR); gui_chat_printf (NULL, " locale: %s", LOCALEDIR); } diff --git a/src/core/wee-debug.h b/src/core/wee-debug.h index 7cd3811b7..ec815cc83 100644 --- a/src/core/wee-debug.h +++ b/src/core/wee-debug.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_DEBUG_H -#define WEECHAT_DEBUG_H 1 +#define WEECHAT_DEBUG_H struct t_gui_window_tree; diff --git a/src/core/wee-eval.c b/src/core/wee-eval.c index c6d5b246d..2cba33a22 100644 --- a/src/core/wee-eval.c +++ b/src/core/wee-eval.c @@ -1,7 +1,7 @@ /* * wee-eval.c - evaluate expressions with references to internal vars * - * Copyright (C) 2012-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2012-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -50,16 +50,10 @@ char *comparisons[EVAL_NUM_COMPARISONS] = { "=~", "!~", "=*", "!*", "==", "!=", "<=", "<", ">=", ">" }; -char *eval_replace_vars (const char *expr, struct t_hashtable *pointers, - struct t_hashtable *extra_vars, int extra_vars_eval, - const char *prefix, const char *suffix, - struct t_eval_regex *eval_regex); +char *eval_replace_vars (const char *expr, + struct t_eval_context *eval_context); char *eval_expression_condition (const char *expr, - struct t_hashtable *pointers, - struct t_hashtable *extra_vars, - int extra_vars_eval, - const char *prefix, - const char *suffix); + struct t_eval_context *eval_context); /* @@ -216,7 +210,7 @@ eval_hdata_get_value (struct t_hdata *hdata, void *pointer, const char *path) break; case WEECHAT_HDATA_TIME: snprintf (str_value, sizeof (str_value), - "%ld", (long)hdata_time (hdata, pointer, var_name)); + "%lld", (long long)hdata_time (hdata, pointer, var_name)); value = strdup (str_value); break; case WEECHAT_HDATA_HASHTABLE: @@ -249,7 +243,7 @@ eval_hdata_get_value (struct t_hdata *hdata, void *pointer, const char *path) break; case HASHTABLE_TIME: snprintf (str_value, sizeof (str_value), - "%ld", (long)(*((time_t *)ptr_value))); + "%lld", (long long)(*((time_t *)ptr_value))); value = strdup (str_value); break; case HASHTABLE_NUM_TYPES: @@ -318,46 +312,37 @@ end: char * eval_replace_vars_cb (void *data, const char *text) { - struct t_hashtable *pointers, *extra_vars; - struct t_eval_regex *eval_regex; + struct t_eval_context *eval_context; struct t_config_option *ptr_option; struct t_gui_buffer *ptr_buffer; char str_value[512], *value, *pos, *pos1, *pos2, *hdata_name, *list_name; char *tmp, *info_name, *hide_char, *hidden_string, *error, *condition; - const char *prefix, *suffix, *ptr_value, *ptr_arguments, *ptr_string; + const char *ptr_value, *ptr_arguments, *ptr_string; struct t_hdata *hdata; void *pointer; - int i, length_hide_char, length, index, rc, extra_vars_eval, screen; + int i, length_hide_char, length, index, rc, screen; int count_suffix; long number; long unsigned int ptr; time_t date; struct tm *date_tmp; - pointers = (struct t_hashtable *)(((void **)data)[0]); - extra_vars = (struct t_hashtable *)(((void **)data)[1]); - extra_vars_eval = *(int *)(((void **)data)[2]); - prefix = (const char *)(((void **)data)[3]); - suffix = (const char *)(((void **)data)[4]); - eval_regex = (struct t_eval_regex *)(((void **)data)[5]); + eval_context = (struct t_eval_context *)data; /* 1. variable in hashtable "extra_vars" */ - if (extra_vars) + if (eval_context->extra_vars) { - ptr_value = hashtable_get (extra_vars, text); + ptr_value = hashtable_get (eval_context->extra_vars, text); if (ptr_value) { - if (extra_vars_eval) + if (eval_context->extra_vars_eval) { tmp = strdup (ptr_value); if (!tmp) return NULL; - hashtable_remove (extra_vars, text); - value = eval_replace_vars (tmp, pointers, - extra_vars, extra_vars_eval, - prefix, suffix, - eval_regex); - hashtable_set (extra_vars, text, tmp); + hashtable_remove (eval_context->extra_vars, text); + value = eval_replace_vars (tmp, eval_context); + hashtable_set (eval_context->extra_vars, text, tmp); free (tmp); return value; } @@ -374,10 +359,7 @@ eval_replace_vars_cb (void *data, const char *text) */ if (strncmp (text, "eval:", 5) == 0) { - return eval_replace_vars (text + 5, pointers, - extra_vars, extra_vars_eval, - prefix, suffix, - eval_regex); + return eval_replace_vars (text + 5, eval_context); } /* 3. convert escaped chars */ @@ -469,14 +451,14 @@ eval_replace_vars_cb (void *data, const char *text) /* 6. regex group captured */ if (strncmp (text, "re:", 3) == 0) { - if (eval_regex && eval_regex->result) + if (eval_context->regex && eval_context->regex->result) { if (strcmp (text + 3, "+") == 0) - number = eval_regex->last_match; + number = eval_context->regex->last_match; else if (strcmp (text + 3, "#") == 0) { snprintf (str_value, sizeof (str_value), - "%d", eval_regex->last_match); + "%d", eval_context->regex->last_match); return strdup (str_value); } else @@ -485,11 +467,13 @@ eval_replace_vars_cb (void *data, const char *text) if (!error || error[0]) number = -1; } - if ((number >= 0) && (number <= eval_regex->last_match)) + if ((number >= 0) && (number <= eval_context->regex->last_match)) { return string_strndup ( - eval_regex->result + eval_regex->match[number].rm_so, - eval_regex->match[number].rm_eo - eval_regex->match[number].rm_so); + eval_context->regex->result + + eval_context->regex->match[number].rm_so, + eval_context->regex->match[number].rm_eo - + eval_context->regex->match[number].rm_so); } } return strdup (""); @@ -550,16 +534,22 @@ eval_replace_vars_cb (void *data, const char *text) if (strncmp (text, "if:", 3) == 0) { value = NULL; - pos = (char *)eval_strstr_level (text + 3, "?", prefix, suffix, 1); + pos = (char *)eval_strstr_level (text + 3, + "?", + eval_context->prefix, + eval_context->suffix, + 1); pos2 = (pos) ? - (char *)eval_strstr_level (pos + 1, ":", prefix, suffix, 1) : NULL; + (char *)eval_strstr_level (pos + 1, + ":", + eval_context->prefix, + eval_context->suffix, + 1) : NULL; condition = (pos) ? strndup (text + 3, pos - (text + 3)) : strdup (text + 3); if (!condition) return strdup (""); - tmp = eval_expression_condition (condition, pointers, - extra_vars, extra_vars_eval, - prefix, suffix); + tmp = eval_expression_condition (condition, eval_context); rc = eval_is_true (tmp); if (tmp) free (tmp); @@ -575,10 +565,7 @@ eval_replace_vars_cb (void *data, const char *text) strndup (pos + 1, pos2 - pos - 1) : strdup (pos + 1); if (tmp) { - value = eval_replace_vars (tmp, pointers, - extra_vars, extra_vars_eval, - prefix, suffix, - eval_regex); + value = eval_replace_vars (tmp, eval_context); free (tmp); } } @@ -595,10 +582,7 @@ eval_replace_vars_cb (void *data, const char *text) */ if (pos2) { - value = eval_replace_vars (pos2 + 1, pointers, - extra_vars, extra_vars_eval, - prefix, suffix, - eval_regex); + value = eval_replace_vars (pos2 + 1, eval_context); } else { @@ -644,7 +628,7 @@ eval_replace_vars_cb (void *data, const char *text) } /* 13. local variable in buffer */ - ptr_buffer = hashtable_get (pointers, "buffer"); + ptr_buffer = hashtable_get (eval_context->pointers, "buffer"); if (ptr_buffer) { ptr_value = hashtable_get (ptr_buffer->local_variables, text); @@ -707,7 +691,7 @@ eval_replace_vars_cb (void *data, const char *text) if (!pointer) { - pointer = hashtable_get (pointers, hdata_name); + pointer = hashtable_get (eval_context->pointers, hdata_name); if (!pointer) goto end; } @@ -730,24 +714,31 @@ end: */ char * -eval_replace_vars (const char *expr, struct t_hashtable *pointers, - struct t_hashtable *extra_vars, int extra_vars_eval, - const char *prefix, const char *suffix, - struct t_eval_regex *eval_regex) +eval_replace_vars (const char *expr, struct t_eval_context *eval_context) { - const void *ptr[6]; const char *no_replace_prefix_list[] = { "if:", NULL }; + char *result; - ptr[0] = pointers; - ptr[1] = extra_vars; - ptr[2] = &extra_vars_eval; - ptr[3] = prefix; - ptr[4] = suffix; - ptr[5] = eval_regex; + eval_context->recursion_count++; - return string_replace_with_callback (expr, prefix, suffix, - no_replace_prefix_list, - &eval_replace_vars_cb, ptr, NULL); + if (eval_context->recursion_count < EVAL_RECURSION_MAX) + { + result = string_replace_with_callback (expr, + eval_context->prefix, + eval_context->suffix, + no_replace_prefix_list, + &eval_replace_vars_cb, + eval_context, + NULL); + } + else + { + result = strdup (""); + } + + eval_context->recursion_count--; + + return result; } /* @@ -769,7 +760,7 @@ eval_compare (const char *expr1, int comparison, const char *expr2) { int rc, string_compare, length1, length2; regex_t regex; - long value1, value2; + double value1, value2; char *error; rc = 0; @@ -816,12 +807,14 @@ eval_compare (const char *expr1, int comparison, const char *expr2) if (!string_compare) { - value1 = strtol (expr1, &error, 10); + value1 = strtod (expr1, &error); if (!error || error[0]) + { string_compare = 1; + } else { - value2 = strtol (expr2, &error, 10); + value2 = strtod (expr2, &error); if (!error || error[0]) string_compare = 1; } @@ -870,11 +863,7 @@ end: char * eval_expression_condition (const char *expr, - struct t_hashtable *pointers, - struct t_hashtable *extra_vars, - int extra_vars_eval, - const char *prefix, - const char *suffix) + struct t_eval_context *eval_context) { int logic, comp, length, level, rc; const char *pos, *pos_end; @@ -927,9 +916,7 @@ eval_expression_condition (const char *expr, sub_expr = string_strndup (expr2, pos_end + 1 - expr2); if (!sub_expr) goto end; - tmp_value = eval_expression_condition (sub_expr, pointers, - extra_vars, extra_vars_eval, - prefix, suffix); + tmp_value = eval_expression_condition (sub_expr, eval_context); free (sub_expr); rc = eval_is_true (tmp_value); if (tmp_value) @@ -949,9 +936,7 @@ eval_expression_condition (const char *expr, { pos++; } - tmp_value = eval_expression_condition (pos, pointers, - extra_vars, extra_vars_eval, - prefix, suffix); + tmp_value = eval_expression_condition (pos, eval_context); rc = eval_is_true (tmp_value); if (tmp_value) free (tmp_value); @@ -989,26 +974,14 @@ eval_expression_condition (const char *expr, || (comp == EVAL_COMPARE_REGEX_NOT_MATCHING)) { /* for regex: just replace vars in both expressions */ - tmp_value = eval_replace_vars (sub_expr, pointers, - extra_vars, extra_vars_eval, - prefix, suffix, - NULL); - tmp_value2 = eval_replace_vars (pos, pointers, - extra_vars, extra_vars_eval, - prefix, suffix, - NULL); + tmp_value = eval_replace_vars (sub_expr, eval_context); + tmp_value2 = eval_replace_vars (pos, eval_context); } else { /* other comparison: fully evaluate both expressions */ - tmp_value = eval_expression_condition (sub_expr, pointers, - extra_vars, - extra_vars_eval, - prefix, suffix); - tmp_value2 = eval_expression_condition (pos, pointers, - extra_vars, - extra_vars_eval, - prefix, suffix); + tmp_value = eval_expression_condition (sub_expr, eval_context); + tmp_value2 = eval_expression_condition (pos, eval_context); } free (sub_expr); value = eval_compare (tmp_value, comp, tmp_value2); @@ -1046,9 +1019,7 @@ eval_expression_condition (const char *expr, sub_expr = string_strndup (expr2 + 1, pos - expr2 - 1); if (!sub_expr) goto end; - tmp_value = eval_expression_condition (sub_expr, pointers, - extra_vars, extra_vars_eval, - prefix, suffix); + tmp_value = eval_expression_condition (sub_expr, eval_context); free (sub_expr); if (!pos[1]) { @@ -1083,8 +1054,7 @@ eval_expression_condition (const char *expr, * at this point, there is no more logical operator neither comparison, * so we just replace variables in string and return the result */ - value = eval_replace_vars (expr2, pointers, extra_vars, extra_vars_eval, - prefix, suffix, NULL); + value = eval_replace_vars (expr2, eval_context); end: if (expr2) @@ -1119,9 +1089,7 @@ end: char * eval_replace_regex (const char *string, regex_t *regex, const char *replace, - struct t_hashtable *pointers, - struct t_hashtable *extra_vars, int extra_vars_eval, - const char *prefix, const char *suffix) + struct t_eval_context *eval_context) { char *result, *result2, *str_replace; int length, length_replace, start_offset, i, rc, end; @@ -1136,6 +1104,8 @@ eval_replace_regex (const char *string, regex_t *regex, const char *replace, return NULL; snprintf (result, length, "%s", string); + eval_context->regex = &eval_regex; + start_offset = 0; while (result && result[start_offset]) { @@ -1174,10 +1144,7 @@ eval_replace_regex (const char *string, regex_t *regex, const char *replace, eval_regex.result = result; - str_replace = eval_replace_vars (replace, pointers, - extra_vars, extra_vars_eval, - prefix, suffix, - &eval_regex); + str_replace = eval_replace_vars (replace, eval_context); length_replace = (str_replace) ? strlen (str_replace) : 0; @@ -1259,9 +1226,9 @@ char * eval_expression (const char *expr, struct t_hashtable *pointers, struct t_hashtable *extra_vars, struct t_hashtable *options) { - int condition, extra_vars_eval, rc, pointers_allocated, regex_allocated; + struct t_eval_context eval_context; + int condition, rc, pointers_allocated, regex_allocated; char *value; - const char *prefix, *suffix; const char *default_prefix = EVAL_DEFAULT_PREFIX; const char *default_suffix = EVAL_DEFAULT_SUFFIX; const char *ptr_value, *regex_replace; @@ -1272,11 +1239,8 @@ eval_expression (const char *expr, struct t_hashtable *pointers, return NULL; condition = 0; - extra_vars_eval = 0; pointers_allocated = 0; regex_allocated = 0; - prefix = default_prefix; - suffix = default_suffix; regex = NULL; regex_replace = NULL; @@ -1297,6 +1261,14 @@ eval_expression (const char *expr, struct t_hashtable *pointers, pointers_allocated = 1; } + eval_context.pointers = pointers; + eval_context.extra_vars = extra_vars; + eval_context.extra_vars_eval = 0; + eval_context.prefix = default_prefix; + eval_context.suffix = default_suffix; + eval_context.regex = NULL; + eval_context.recursion_count = 0; + /* * set window/buffer with pointer to current window/buffer * (if not already defined in the hashtable) @@ -1324,17 +1296,17 @@ eval_expression (const char *expr, struct t_hashtable *pointers, /* check if extra vars must be evaluated */ ptr_value = hashtable_get (options, "extra"); if (ptr_value && (strcmp (ptr_value, "eval") == 0)) - extra_vars_eval = 1; + eval_context.extra_vars_eval = 1; /* check for custom prefix */ ptr_value = hashtable_get (options, "prefix"); if (ptr_value && ptr_value[0]) - prefix = ptr_value; + eval_context.prefix = ptr_value; /* check for custom suffix */ ptr_value = hashtable_get (options, "suffix"); if (ptr_value && ptr_value[0]) - suffix = ptr_value; + eval_context.suffix = ptr_value; /* check for regex */ ptr_value = hashtable_get (options, "regex"); @@ -1365,9 +1337,7 @@ eval_expression (const char *expr, struct t_hashtable *pointers, if (condition) { /* evaluate as condition (return a boolean: "0" or "1") */ - value = eval_expression_condition (expr, pointers, - extra_vars, extra_vars_eval, - prefix, suffix); + value = eval_expression_condition (expr, &eval_context); rc = eval_is_true (value); if (value) free (value); @@ -1379,15 +1349,12 @@ eval_expression (const char *expr, struct t_hashtable *pointers, { /* replace with regex */ value = eval_replace_regex (expr, regex, regex_replace, - pointers, extra_vars, extra_vars_eval, - prefix, suffix); + &eval_context); } else { /* only replace variables in expression */ - value = eval_replace_vars (expr, pointers, - extra_vars, extra_vars_eval, - prefix, suffix, NULL); + value = eval_replace_vars (expr, &eval_context); } } diff --git a/src/core/wee-eval.h b/src/core/wee-eval.h index 4b4967bc3..8522b9efa 100644 --- a/src/core/wee-eval.h +++ b/src/core/wee-eval.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2012-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_EVAL_H -#define WEECHAT_EVAL_H 1 +#define WEECHAT_EVAL_H #include <regex.h> @@ -28,6 +28,8 @@ #define EVAL_DEFAULT_PREFIX "${" #define EVAL_DEFAULT_SUFFIX "}" +#define EVAL_RECURSION_MAX 32 + struct t_hashtable; enum t_eval_logical_op @@ -61,6 +63,17 @@ struct t_eval_regex int last_match; }; +struct t_eval_context +{ + struct t_hashtable *pointers; + struct t_hashtable *extra_vars; + int extra_vars_eval; + const char *prefix; + const char *suffix; + struct t_eval_regex *regex; + int recursion_count; +}; + extern int eval_is_true (const char *value); extern char *eval_expression (const char *expr, struct t_hashtable *pointers, diff --git a/src/core/wee-hashtable.c b/src/core/wee-hashtable.c index 508c30892..7e1572966 100644 --- a/src/core/wee-hashtable.c +++ b/src/core/wee-hashtable.c @@ -1,7 +1,7 @@ /* * wee-hashtable.c - implementation of hashtable * - * Copyright (C) 2010-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2010-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -554,7 +554,7 @@ hashtable_to_string (enum t_hashtable_type type, const void *value) break; case HASHTABLE_TIME: snprintf (str_value, sizeof (str_value), - "%ld", (long)(*((time_t *)value))); + "%lld", (long long)(*((time_t *)value))); return str_value; break; case HASHTABLE_NUM_TYPES: @@ -1314,7 +1314,7 @@ hashtable_print_log (struct t_hashtable *hashtable, const char *name) log_printf (" key (buffer) . . . : 0x%lx", ptr_item->key); break; case HASHTABLE_TIME: - log_printf (" key (time) . . . . : %ld", *((time_t *)ptr_item->key)); + log_printf (" key (time) . . . . : %lld", (long long)(*((time_t *)ptr_item->key))); break; case HASHTABLE_NUM_TYPES: break; diff --git a/src/core/wee-hashtable.h b/src/core/wee-hashtable.h index 2ea414574..6733d76c0 100644 --- a/src/core/wee-hashtable.h +++ b/src/core/wee-hashtable.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2010-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_HASHTABLE_H -#define WEECHAT_HASHTABLE_H 1 +#define WEECHAT_HASHTABLE_H struct t_hashtable; struct t_infolist_item; diff --git a/src/core/wee-hdata.c b/src/core/wee-hdata.c index 4631b8de9..cfb326c8c 100644 --- a/src/core/wee-hdata.c +++ b/src/core/wee-hdata.c @@ -1,7 +1,7 @@ /* * wee-hdata.c - direct access to WeeChat data using hashtables * - * Copyright (C) 2011-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2011-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -557,7 +557,7 @@ hdata_move (struct t_hdata *hdata, void *pointer, int count) return NULL; ptr_var = (count < 0) ? hdata->var_prev : hdata->var_next; - abs_count = abs(count); + abs_count = abs (count); for (i = 0; i < abs_count; i++) { diff --git a/src/core/wee-hdata.h b/src/core/wee-hdata.h index eaa2a3431..6a771737b 100644 --- a/src/core/wee-hdata.h +++ b/src/core/wee-hdata.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2011-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_HDATA_H -#define WEECHAT_HDATA_H 1 +#define WEECHAT_HDATA_H #include <time.h> diff --git a/src/core/wee-hook.c b/src/core/wee-hook.c index 277f75388..8e83c0a8e 100644 --- a/src/core/wee-hook.c +++ b/src/core/wee-hook.c @@ -1,7 +1,7 @@ /* * wee-hook.c - WeeChat hooks management * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2012 Simon Arlott * * This file is part of WeeChat, the extensible chat client. @@ -25,6 +25,7 @@ #endif #include <stdlib.h> +#include <stdio.h> #include <stddef.h> #include <unistd.h> #include <string.h> @@ -1013,9 +1014,12 @@ hook_command_run_exec (struct t_gui_buffer *buffer, const char *command) if (!hook_matching && !strchr (HOOK_COMMAND_RUN(ptr_hook, command), ' ')) { - hook_matching = (string_strncasecmp (ptr_command, - HOOK_COMMAND_RUN(ptr_hook, command), - utf8_strlen (HOOK_COMMAND_RUN(ptr_hook, command))) == 0); + length = strlen (HOOK_COMMAND_RUN(ptr_hook, command)); + hook_matching = ((string_strncasecmp (ptr_command, + HOOK_COMMAND_RUN(ptr_hook, command), + utf8_strlen (HOOK_COMMAND_RUN(ptr_hook, command))) == 0) + && ((ptr_command[length] == ' ') + || (ptr_command[length] == '\0'))); } if (hook_matching) @@ -1058,9 +1062,9 @@ hook_timer_init (struct t_hook *hook) gettimeofday (&HOOK_TIMER(hook, last_exec), NULL); time_now = time (NULL); - local_time = localtime(&time_now); + local_time = localtime (&time_now); local_hour = local_time->tm_hour; - gm_time = gmtime(&time_now); + gm_time = gmtime (&time_now); gm_hour = gm_time->tm_hour; if ((local_time->tm_year > gm_time->tm_year) || (local_time->tm_mon > gm_time->tm_mon) @@ -3672,7 +3676,7 @@ hook_set (struct t_hook *hook, const char *property, const char *value) if (string_strcasecmp (property, "subplugin") == 0) { if (hook->subplugin) - free(hook->subplugin); + free (hook->subplugin); hook->subplugin = strdup (value); } else if (string_strcasecmp (property, "stdin") == 0) @@ -4801,11 +4805,12 @@ hook_print_log () local_time = localtime (&seconds); if (local_time) { - strftime (text_time, sizeof (text_time), - "%d/%m/%Y %H:%M:%S", local_time); + if (strftime (text_time, sizeof (text_time), + "%d/%m/%Y %H:%M:%S", local_time) == 0) + text_time[0] = '\0'; } - log_printf (" last_exec.tv_sec. . . : %ld (%s)", - HOOK_TIMER(ptr_hook, last_exec.tv_sec), + log_printf (" last_exec.tv_sec. . . : %lld (%s)", + (long long)(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)); text_time[0] = '\0'; @@ -4813,11 +4818,12 @@ hook_print_log () local_time = localtime (&seconds); if (local_time) { - strftime (text_time, sizeof (text_time), - "%d/%m/%Y %H:%M:%S", local_time); + if (strftime (text_time, sizeof (text_time), + "%d/%m/%Y %H:%M:%S", local_time) == 0) + text_time[0] = '\0'; } - log_printf (" next_exec.tv_sec. . . : %ld (%s)", - HOOK_TIMER(ptr_hook, next_exec.tv_sec), + log_printf (" next_exec.tv_sec. . . : %lld (%s)", + (long long)(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; diff --git a/src/core/wee-hook.h b/src/core/wee-hook.h index d721138b6..f01f05b9c 100644 --- a/src/core/wee-hook.h +++ b/src/core/wee-hook.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2012 Simon Arlott * * This file is part of WeeChat, the extensible chat client. @@ -19,7 +19,7 @@ */ #ifndef WEECHAT_HOOK_H -#define WEECHAT_HOOK_H 1 +#define WEECHAT_HOOK_H #include <unistd.h> #include <time.h> diff --git a/src/core/wee-infolist.c b/src/core/wee-infolist.c index bf393e11c..ee9af9299 100644 --- a/src/core/wee-infolist.c +++ b/src/core/wee-infolist.c @@ -1,7 +1,7 @@ /* * wee-infolist.c - info lists management * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -147,6 +147,7 @@ infolist_new_var_integer (struct t_infolist_item *item, new_var->value = malloc (sizeof (int)); if (new_var->value) *((int *)new_var->value) = value; + new_var->size = 0; /* not used for an integer */ new_var->prev_var = item->last_var; new_var->next_var = NULL; @@ -181,6 +182,7 @@ infolist_new_var_string (struct t_infolist_item *item, new_var->name = strdup (name); new_var->type = INFOLIST_STRING; new_var->value = (value) ? strdup (value) : NULL; + new_var->size = 0; /* not used for a string */ new_var->prev_var = item->last_var; new_var->next_var = NULL; @@ -215,6 +217,7 @@ infolist_new_var_pointer (struct t_infolist_item *item, new_var->name = strdup (name); new_var->type = INFOLIST_POINTER; new_var->value = pointer; + new_var->size = 0; /* not used for a pointer */ new_var->prev_var = item->last_var; new_var->next_var = NULL; @@ -288,6 +291,7 @@ infolist_new_var_time (struct t_infolist_item *item, new_var->value = malloc (sizeof (time_t)); if (new_var->value) *((time_t *)new_var->value) = time; + new_var->size = 0; /* not used for a time */ new_var->prev_var = item->last_var; new_var->next_var = NULL; @@ -770,7 +774,7 @@ infolist_print_log () log_printf (" size of buffer . . . : %d", ptr_var->size); break; case INFOLIST_TIME: - log_printf (" value (time) . . . . : %ld", *((time_t *)ptr_var->value)); + log_printf (" value (time) . . . . : %lld", (long long)(*((time_t *)ptr_var->value))); break; } log_printf (" prev_var . . . . . . : 0x%lx", ptr_var->prev_var); diff --git a/src/core/wee-infolist.h b/src/core/wee-infolist.h index 1502ae84b..f07b618ba 100644 --- a/src/core/wee-infolist.h +++ b/src/core/wee-infolist.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_INFOLIST_H -#define WEECHAT_INFOLIST_H 1 +#define WEECHAT_INFOLIST_H #include <time.h> diff --git a/src/core/wee-input.c b/src/core/wee-input.c index e90e31650..16feb7f77 100644 --- a/src/core/wee-input.c +++ b/src/core/wee-input.c @@ -1,7 +1,7 @@ /* * wee-input.c - default input callback for buffers * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -194,8 +194,7 @@ input_data (struct t_gui_buffer *buffer, const char *data) rc = WEECHAT_RC_OK; - if (!buffer || !gui_buffer_valid (buffer) - || !data || !data[0] || (data[0] == '\r') || (data[0] == '\n')) + if (!buffer || !gui_buffer_valid (buffer) || !data) { return WEECHAT_RC_ERROR; } @@ -213,12 +212,12 @@ input_data (struct t_gui_buffer *buffer, const char *data) data); /* data was dropped? */ - if (new_data && !new_data[0]) + if (data[0] && new_data && !new_data[0]) goto end; first_command = 1; ptr_data = (new_data) ? new_data : data; - while (ptr_data && ptr_data[0]) + while (ptr_data) { /* * if the buffer pointer is not valid any more (or if it's another diff --git a/src/core/wee-input.h b/src/core/wee-input.h index d9567b5c2..a47c15677 100644 --- a/src/core/wee-input.h +++ b/src/core/wee-input.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_INPUT_H -#define WEECHAT_INPUT_H 1 +#define WEECHAT_INPUT_H struct t_gui_buffer; struct t_weechat_plugin; diff --git a/src/core/wee-list.c b/src/core/wee-list.c index a3c0090d1..2469b52b2 100644 --- a/src/core/wee-list.c +++ b/src/core/wee-list.c @@ -1,7 +1,7 @@ /* * wee-list.c - sorted lists * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/core/wee-list.h b/src/core/wee-list.h index dbdd01376..2f923d08b 100644 --- a/src/core/wee-list.h +++ b/src/core/wee-list.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_LIST_H -#define WEECHAT_LIST_H 1 +#define WEECHAT_LIST_H struct t_weelist_item { diff --git a/src/core/wee-log.c b/src/core/wee-log.c index be35cc689..051439051 100644 --- a/src/core/wee-log.c +++ b/src/core/wee-log.c @@ -1,7 +1,7 @@ /* * wee-log.c - WeeChat log file (weechat.log) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -273,7 +273,7 @@ log_crash_rename () local_time->tm_year + 1900, local_time->tm_mon + 1, local_time->tm_mday, - getpid()); + getpid ()); if (rename (old_name, new_name) == 0) { string_fprintf (stderr, "*** Full crash dump was saved to %s file.\n", diff --git a/src/core/wee-log.h b/src/core/wee-log.h index a43ef7701..25cc6e901 100644 --- a/src/core/wee-log.h +++ b/src/core/wee-log.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,9 @@ */ #ifndef WEECHAT_LOG_H -#define WEECHAT_LOG_H 1 +#define WEECHAT_LOG_H + +#include <stdio.h> extern char *weechat_log_filename; extern FILE *weechat_log_file; diff --git a/src/core/wee-network.c b/src/core/wee-network.c index f5beb4f7f..d5494f1d2 100644 --- a/src/core/wee-network.c +++ b/src/core/wee-network.c @@ -1,7 +1,7 @@ /* * wee-network.c - network functions * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2010 Emmanuel Bouthenot <kolter@openics.org> * Copyright (C) 2010 Gu1ll4um3r0m41n <aeroxteam@gmail.com> * Copyright (C) 2012 Simon Arlott @@ -160,7 +160,7 @@ network_end () if (!weechat_no_gnutls) { gnutls_certificate_free_credentials (gnutls_xcred); - gnutls_global_deinit(); + gnutls_global_deinit (); } #endif /* HAVE_GNUTLS */ network_init_gnutls_ok = 0; @@ -321,7 +321,7 @@ network_resolve (const char *hostname, char *ip, int *version) if (!res) return 0; - if (getnameinfo (res->ai_addr, res->ai_addrlen, ipbuffer, sizeof(ipbuffer), + if (getnameinfo (res->ai_addr, res->ai_addrlen, ipbuffer, sizeof (ipbuffer), NULL, 0, NI_NUMERICHOST) != 0) { freeaddrinfo (res); @@ -494,9 +494,9 @@ network_pass_socks5proxy (struct t_proxy *proxy, int sock, const char *address, } /* authentication successful then giving address/port to connect */ - addr_len = strlen(address); + addr_len = strlen (address); addr_buffer_len = 4 + 1 + addr_len + 2; - addr_buffer = malloc (addr_buffer_len * sizeof(*addr_buffer)); + addr_buffer = malloc (addr_buffer_len * sizeof (*addr_buffer)); if (!addr_buffer) return 0; addr_buffer[0] = 5; /* version 5 */ @@ -984,7 +984,7 @@ network_connect_child (struct t_hook *hook_connect) if (tmp_num_groups >= retry) { /* shuffle while adding */ - rand_num = tmp_host + (rand() % ((i + 1) - tmp_host)); + rand_num = tmp_host + (rand () % ((i + 1) - tmp_host)); if (rand_num == i) res_reorder[i++] = ptr_res; else @@ -1015,7 +1015,7 @@ network_connect_child (struct t_hook *hook_connect) if (tmp_num_groups < retry) { /* shuffle while adding */ - rand_num = tmp_host + (rand() % ((i + 1) - tmp_host)); + rand_num = tmp_host + (rand () % ((i + 1) - tmp_host)); if (rand_num == i) res_reorder[i++] = ptr_res; else @@ -1208,7 +1208,7 @@ network_connect_child (struct t_hook *hook_connect) cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof (sock)); - memcpy(CMSG_DATA(cmsg), &sock, sizeof (sock)); + memcpy (CMSG_DATA(cmsg), &sock, sizeof (sock)); msg.msg_controllen = cmsg->cmsg_len; num_written = sendmsg (HOOK_CONNECT(hook_connect, child_send), &msg, 0); (void) num_written; @@ -1470,7 +1470,7 @@ network_connect_child_read_cb (const void *pointer, void *data, int fd) && cmsg->cmsg_type == SCM_RIGHTS && cmsg->cmsg_len >= sizeof (sock)) { - memcpy(&sock, CMSG_DATA(cmsg), sizeof (sock)); + memcpy (&sock, CMSG_DATA(cmsg), sizeof (sock)); } } } diff --git a/src/core/wee-network.h b/src/core/wee-network.h index d469256ab..e4984b618 100644 --- a/src/core/wee-network.h +++ b/src/core/wee-network.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_NETWORK_H -#define WEECHAT_NETWORK_H 1 +#define WEECHAT_NETWORK_H #include <sys/types.h> #include <sys/socket.h> diff --git a/src/core/wee-proxy.c b/src/core/wee-proxy.c index 2bb1b1880..7bfa48f61 100644 --- a/src/core/wee-proxy.c +++ b/src/core/wee-proxy.c @@ -1,7 +1,7 @@ /* * wee-proxy.c - proxy functions * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -458,17 +458,17 @@ proxy_new (const char *name, const char *type, const char *ipv6, if (!new_proxy) { if (option_type) - config_file_option_free (option_type); + config_file_option_free (option_type, 0); if (option_ipv6) - config_file_option_free (option_ipv6); + config_file_option_free (option_ipv6, 0); if (option_address) - config_file_option_free (option_address); + config_file_option_free (option_address, 0); if (option_port) - config_file_option_free (option_port); + config_file_option_free (option_port, 0); if (option_username) - config_file_option_free (option_username); + config_file_option_free (option_username, 0); if (option_password) - config_file_option_free (option_password); + config_file_option_free (option_password, 0); } return new_proxy; @@ -516,7 +516,7 @@ proxy_use_temp_proxies () { if (ptr_temp_proxy->options[i]) { - config_file_option_free (ptr_temp_proxy->options[i]); + config_file_option_free (ptr_temp_proxy->options[i], 0); ptr_temp_proxy->options[i] = NULL; } } @@ -564,7 +564,7 @@ proxy_free (struct t_proxy *proxy) free (proxy->name); for (i = 0; i < PROXY_NUM_OPTIONS; i++) { - config_file_option_free (proxy->options[i]); + config_file_option_free (proxy->options[i], 1); } free (proxy); diff --git a/src/core/wee-proxy.h b/src/core/wee-proxy.h index 5bfdf1ab8..902e36709 100644 --- a/src/core/wee-proxy.h +++ b/src/core/wee-proxy.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_PROXY_H -#define WEECHAT_PROXY_H 1 +#define WEECHAT_PROXY_H struct t_infolist; diff --git a/src/core/wee-secure.c b/src/core/wee-secure.c index 51b1de262..b30f0dd66 100644 --- a/src/core/wee-secure.c +++ b/src/core/wee-secure.c @@ -1,7 +1,7 @@ /* * wee-secure.c - secured data configuration options (file sec.conf) * - * Copyright (C) 2013-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2013-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -952,6 +952,7 @@ secure_init_options () if (!ptr_section) { config_file_free (secure_config_file); + secure_config_file = NULL; return 0; } @@ -1006,6 +1007,7 @@ secure_init_options () if (!ptr_section) { config_file_free (secure_config_file); + secure_config_file = NULL; return 0; } diff --git a/src/core/wee-secure.h b/src/core/wee-secure.h index d46fa8610..9c01eb068 100644 --- a/src/core/wee-secure.h +++ b/src/core/wee-secure.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2013-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_SECURE_H -#define WEECHAT_SECURE_H 1 +#define WEECHAT_SECURE_H #define SECURE_CONFIG_NAME "sec" diff --git a/src/core/wee-string.c b/src/core/wee-string.c index b6765d9b7..0bdb2f356 100644 --- a/src/core/wee-string.c +++ b/src/core/wee-string.c @@ -1,7 +1,7 @@ /* * wee-string.c - string functions * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -24,6 +24,7 @@ #endif #include <stdlib.h> +#include <stdio.h> #include <errno.h> #include <stdarg.h> #include <string.h> @@ -2174,7 +2175,7 @@ string_split_command (const char *command, char separator) nb_substr = 1; ptr = command; - while ((p = strchr(ptr, separator)) != NULL) + while ((p = strchr (ptr, separator)) != NULL) { nb_substr++; ptr = ++p; @@ -2184,7 +2185,7 @@ string_split_command (const char *command, char separator) if (!array) return NULL; - buffer = malloc (strlen(command) + 1); + buffer = malloc (strlen (command) + 1); if (!buffer) { free (array); @@ -2194,7 +2195,7 @@ string_split_command (const char *command, char separator) ptr = command; str_idx = 0; arr_idx = 0; - while(*ptr != '\0') + while (*ptr != '\0') { type = 0; if (*ptr == separator) @@ -2234,7 +2235,7 @@ string_split_command (const char *command, char separator) free (buffer); - array2 = realloc (array, (arr_idx + 1) * sizeof(array[0])); + array2 = realloc (array, (arr_idx + 1) * sizeof (array[0])); if (!array2) { if (array) @@ -2287,7 +2288,7 @@ string_iconv (int from_utf8, const char *from_code, const char *to_code, #ifdef HAVE_ICONV if (from_code && from_code[0] && to_code && to_code[0] - && (string_strcasecmp(from_code, to_code) != 0)) + && (string_strcasecmp (from_code, to_code) != 0)) { cd = iconv_open (to_code, from_code); if (cd == (iconv_t)(-1)) diff --git a/src/core/wee-string.h b/src/core/wee-string.h index 0c2f0d997..9d7257e70 100644 --- a/src/core/wee-string.h +++ b/src/core/wee-string.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,8 +18,9 @@ */ #ifndef WEECHAT_STRING_H -#define WEECHAT_STRING_H 1 +#define WEECHAT_STRING_H +#include <stdio.h> #include <stdint.h> #include <regex.h> diff --git a/src/core/wee-upgrade-file.c b/src/core/wee-upgrade-file.c index d2bfbd69d..79fe6b248 100644 --- a/src/core/wee-upgrade-file.c +++ b/src/core/wee-upgrade-file.c @@ -1,7 +1,7 @@ /* * wee-upgrade-file.c - save/restore data for upgrading WeeChat * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/core/wee-upgrade-file.h b/src/core/wee-upgrade-file.h index b2cd119ed..af3727d18 100644 --- a/src/core/wee-upgrade-file.h +++ b/src/core/wee-upgrade-file.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,9 @@ */ #ifndef WEECHAT_UPGRADE_FILE_H -#define WEECHAT_UPGRADE_FILE_H 1 +#define WEECHAT_UPGRADE_FILE_H + +#include <stdio.h> #define UPGRADE_SIGNATURE "===== WeeChat Upgrade file v2.2 - binary, do not edit! =====" diff --git a/src/core/wee-upgrade.c b/src/core/wee-upgrade.c index 6bf2f0577..5afa33266 100644 --- a/src/core/wee-upgrade.c +++ b/src/core/wee-upgrade.c @@ -1,7 +1,7 @@ /* * wee-upgrade.c - save/restore session data of WeeChat core * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -509,6 +509,9 @@ upgrade_weechat_read_buffer (struct t_infolist *infolist) ptr_buffer->input = infolist_integer (infolist, "input"); ptr_buffer->input_get_unknown_commands = infolist_integer (infolist, "input_get_unknown_commands"); + ptr_buffer->input_get_empty = + infolist_integer (infolist, "input_get_empty"); + if (infolist_integer (infolist, "input_buffer_alloc") > 0) { ptr_buffer->input_buffer = @@ -851,6 +854,8 @@ upgrade_weechat_load () gui_color_buffer_assign (); gui_color_buffer_display (); + gui_buffer_user_set_callbacks (); + secure_buffer_assign (); secure_buffer_display (); @@ -907,7 +912,7 @@ upgrade_weechat_end () /* remove .upgrade files */ util_exec_on_files (weechat_home, - 0, + 0, 0, &upgrade_weechat_remove_file_cb, NULL); /* display message for end of /upgrade with duration */ diff --git a/src/core/wee-upgrade.h b/src/core/wee-upgrade.h index 3b39fe547..94d3c23ef 100644 --- a/src/core/wee-upgrade.h +++ b/src/core/wee-upgrade.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_UPGRADE_H -#define WEECHAT_UPGRADE_H 1 +#define WEECHAT_UPGRADE_H #include "wee-upgrade-file.h" diff --git a/src/core/wee-url.c b/src/core/wee-url.c index bacb02852..c24329b15 100644 --- a/src/core/wee-url.c +++ b/src/core/wee-url.c @@ -1,7 +1,7 @@ /* * wee-url.c - URL transfer * - * Copyright (C) 2012-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2012-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -871,7 +871,7 @@ weeurl_get_mask_value (struct t_url_constant *constants, { for (i = 0; i < num_items; i++) { - item = string_remove_quotes(items[i], "'\""); + item = string_remove_quotes (items[i], "'\""); if (item) { index = weeurl_search_constant (constants, item); @@ -1115,7 +1115,7 @@ weeurl_download (const char *url, struct t_hashtable *options) goto end; } - curl = curl_easy_init(); + curl = curl_easy_init (); if (!curl) { rc = 3; diff --git a/src/core/wee-url.h b/src/core/wee-url.h index 7f6f3b033..513d2592a 100644 --- a/src/core/wee-url.h +++ b/src/core/wee-url.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2012-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,9 @@ */ #ifndef WEECHAT_URL_H -#define WEECHAT_URL_H 1 +#define WEECHAT_URL_H + +#include <stdio.h> struct t_hashtable; struct t_infolist; diff --git a/src/core/wee-utf8.c b/src/core/wee-utf8.c index fcc2c6fe6..b27302584 100644 --- a/src/core/wee-utf8.c +++ b/src/core/wee-utf8.c @@ -1,7 +1,7 @@ /* * wee-utf8.c - UTF-8 string functions * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -138,7 +138,7 @@ utf8_is_valid (const char *string, int length, char **error) { goto invalid; } - code_point = utf8_char_int(string); + code_point = utf8_char_int (string); if ((code_point < 0x10000) || (code_point > 0x1FFFFF)) goto invalid; string += 4; @@ -433,7 +433,7 @@ utf8_char_size (const char *string) /* * Gets length of an UTF-8 string in number of chars (not bytes). - * Result is <= strlen(string). + * Result is <= strlen (string). * * Returns length of string (>= 0). */ diff --git a/src/core/wee-utf8.h b/src/core/wee-utf8.h index fe54be58b..b8b748cb7 100644 --- a/src/core/wee-utf8.h +++ b/src/core/wee-utf8.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_UTF8_H -#define WEECHAT_UTF8_H 1 +#define WEECHAT_UTF8_H #ifndef __USE_XOPEN #define __USE_XOPEN diff --git a/src/core/wee-util.c b/src/core/wee-util.c index 22eb0e43e..8760aacea 100644 --- a/src/core/wee-util.c +++ b/src/core/wee-util.c @@ -1,7 +1,7 @@ /* * wee-util.c - some useful functions * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -24,6 +24,7 @@ #endif #include <stdlib.h> +#include <stdio.h> #include <stdint.h> #include <errno.h> #include <string.h> @@ -316,8 +317,9 @@ util_get_time_string (const time_t *date) local_time = localtime (date); if (local_time) { - strftime (text_time, sizeof (text_time), - CONFIG_STRING(config_look_time_format), local_time); + if (strftime (text_time, sizeof (text_time), + CONFIG_STRING(config_look_time_format), local_time) == 0) + text_time[0] = '\0'; } return text_time; @@ -357,7 +359,7 @@ util_catch_signal (int signum, void (*handler)(int)) sigemptyset (&act.sa_mask); act.sa_flags = 0; act.sa_handler = handler; - sigaction(signum, &act, NULL); + sigaction (signum, &act, NULL); } /* @@ -485,11 +487,12 @@ util_mkdir_parents (const char *directory, int mode) */ void -util_exec_on_files (const char *directory, int hidden_files, +util_exec_on_files (const char *directory, int recurse_subdirs, + int hidden_files, void (*callback)(void *data, const char *filename), void *callback_data) { - char complete_filename[1024]; + char complete_filename[PATH_MAX]; DIR *dir; struct dirent *entry; struct stat statbuf; @@ -507,7 +510,17 @@ util_exec_on_files (const char *directory, int hidden_files, snprintf (complete_filename, sizeof (complete_filename), "%s/%s", directory, entry->d_name); lstat (complete_filename, &statbuf); - if (!S_ISDIR(statbuf.st_mode)) + if (S_ISDIR(statbuf.st_mode)) + { + if (recurse_subdirs + && (strcmp (entry->d_name, ".") != 0) + && (strcmp (entry->d_name, "..") != 0)) + { + util_exec_on_files (complete_filename, 1, hidden_files, + callback, callback_data); + } + } + else { (*callback) (callback_data, complete_filename); } @@ -530,7 +543,7 @@ char * util_search_full_lib_name_ext (const char *filename, const char *extension, const char *plugins_dir) { - char *name_with_ext, *final_name; + char *name_with_ext, *final_name, *extra_libdir; int length; struct stat st; @@ -543,6 +556,33 @@ util_search_full_lib_name_ext (const char *filename, const char *extension, filename, (strchr (filename, '.')) ? "" : extension); + /* try libdir from environment variable WEECHAT_EXTRA_LIBDIR */ + extra_libdir = getenv (WEECHAT_EXTRA_LIBDIR); + if (extra_libdir && extra_libdir[0]) + { + length = strlen (extra_libdir) + strlen (name_with_ext) + + strlen (plugins_dir) + 16; + final_name = malloc (length); + if (!final_name) + { + free (name_with_ext); + return NULL; + } + snprintf (final_name, length, + "%s%s%s%s%s", + extra_libdir, + DIR_SEPARATOR, + plugins_dir, + DIR_SEPARATOR, + name_with_ext); + if ((stat (final_name, &st) == 0) && (st.st_size > 0)) + { + free (name_with_ext); + return final_name; + } + free (final_name); + } + /* try WeeChat user's dir */ length = strlen (weechat_home) + strlen (name_with_ext) + strlen (plugins_dir) + 16; @@ -679,7 +719,7 @@ util_file_get_content (const char *filename) if (!buffer2) goto error; buffer = buffer2; - count = fread (&buffer[fp], sizeof(char), 1024, f); + count = fread (&buffer[fp], sizeof (char), 1024, f); if (count <= 0) goto error; fp += count; @@ -699,7 +739,7 @@ error: if (buffer) free (buffer); if (f) - fclose(f); + fclose (f); return NULL; } diff --git a/src/core/wee-util.h b/src/core/wee-util.h index fe17e0117..53ae47535 100644 --- a/src/core/wee-util.h +++ b/src/core/wee-util.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_UTIL_H -#define WEECHAT_UTIL_H 1 +#define WEECHAT_UTIL_H #include <time.h> @@ -46,7 +46,8 @@ extern void util_catch_signal (int signum, void (*handler)(int)); extern int util_mkdir_home (const char *directory, int mode); extern int util_mkdir (const char *directory, int mode); extern int util_mkdir_parents (const char *directory, int mode); -extern void util_exec_on_files (const char *directory, int hidden_files, +extern void util_exec_on_files (const char *directory, int recurse_subdirs, + int hidden_files, void (*callback)(void *data, const char *filename), void *callback_data); diff --git a/src/core/wee-version.c b/src/core/wee-version.c index a587bb176..806296b46 100644 --- a/src/core/wee-version.c +++ b/src/core/wee-version.c @@ -1,7 +1,7 @@ /* * wee-version.c - functions for WeeChat version * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -134,3 +134,16 @@ version_get_compilation_time () { return __TIME__; } + +/* + * Returns date/time of WeeChat compilation. + * + * Example: + * Dec 16 2012 18:10:22 + */ + +const char * +version_get_compilation_date_time () +{ + return __DATE__ " " __TIME__; +} diff --git a/src/core/wee-version.h b/src/core/wee-version.h index 30273ddc2..d7d32d52a 100644 --- a/src/core/wee-version.h +++ b/src/core/wee-version.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_VERSION_H -#define WEECHAT_VERSION_H 1 +#define WEECHAT_VERSION_H extern const char *version_get_name (); extern const char *version_get_version (); @@ -27,5 +27,6 @@ extern const char *version_get_git (); extern const char *version_get_version_with_git (); extern const char *version_get_compilation_date (); extern const char *version_get_compilation_time (); +extern const char *version_get_compilation_date_time (); #endif /* WEECHAT_VERSION_H */ diff --git a/src/core/weechat.c b/src/core/weechat.c index 6d89679a4..f74598ad5 100644 --- a/src/core/weechat.c +++ b/src/core/weechat.c @@ -17,7 +17,7 @@ * * weechat.c - WeeChat main functions * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -79,6 +79,7 @@ #include "../plugins/plugin-api.h" +int weechat_headless = 0; /* 1 if running headless (no GUI) */ int weechat_debug_core = 0; /* debug level for core */ char *weechat_argv0 = NULL; /* WeeChat binary file name (argv[0])*/ int weechat_upgrading = 0; /* =1 if WeeChat is upgrading */ @@ -87,7 +88,7 @@ time_t weechat_first_start_time = 0; /* start time (used by /uptime cmd) */ int weechat_upgrade_count = 0; /* number of /upgrade done */ struct timeval weechat_current_start_timeval; /* start time used to display */ /* duration of /upgrade */ -int weechat_quit = 0; /* = 1 if quit request from user */ +volatile sig_atomic_t weechat_quit = 0; /* = 1 if quit request from user */ volatile sig_atomic_t weechat_quit_signal = 0; /* signal received, */ /* WeeChat must quit */ char *weechat_home = NULL; /* home dir. (default: ~/.weechat) */ @@ -131,13 +132,13 @@ weechat_display_copyright () */ void -weechat_display_usage (char *exec_name) +weechat_display_usage () { weechat_display_copyright (); string_fprintf (stdout, "\n"); string_fprintf (stdout, _("Usage: %s [option...] [plugin:option...]\n"), - exec_name, exec_name); + weechat_argv0); string_fprintf (stdout, "\n"); string_fprintf ( stdout, @@ -159,7 +160,22 @@ weechat_display_usage (char *exec_name) "(see /help upgrade in WeeChat)\n" " -v, --version display WeeChat version\n" " plugin:option option for plugin (see man weechat)\n")); - string_fprintf(stdout, "\n"); + string_fprintf (stdout, "\n"); + + /* extra options in headless mode */ + if (weechat_headless) + { + string_fprintf (stdout, _("Extra options in headless mode:\n")); + string_fprintf ( + stdout, + _(" --daemon run WeeChat as a daemon (fork, " + "new process group, file descriptors closed);\n")); + string_fprintf ( + stdout, + _(" (by default in headless mode " + "WeeChat is blocking and does not run in background)\n")); + string_fprintf (stdout, "\n"); + } } /* @@ -173,7 +189,7 @@ weechat_parse_args (int argc, char *argv[]) { int i; - weechat_argv0 = (argv && argv[0]) ? strdup (argv[0]) : NULL; + weechat_argv0 = (argv[0]) ? strdup (argv[0]) : NULL; weechat_upgrading = 0; weechat_home = NULL; weechat_server_cmd_line = 0; @@ -208,7 +224,7 @@ weechat_parse_args (int argc, char *argv[]) else if ((strcmp (argv[i], "-h") == 0) || (strcmp (argv[i], "--help") == 0)) { - weechat_display_usage (argv[0]); + weechat_display_usage (); weechat_shutdown (EXIT_SUCCESS, 0); } else if ((strcmp (argv[i], "-l") == 0) @@ -403,6 +419,14 @@ weechat_create_home_dir () void weechat_startup_message () { + if (weechat_headless) + { + string_fprintf (stdout, + _("WeeChat is running in headless mode " + "(Ctrl-C to quit).")); + string_fprintf (stdout, "\n"); + } + if (CONFIG_BOOLEAN(config_startup_display_logo)) { gui_chat_printf ( @@ -445,8 +469,7 @@ weechat_startup_message () "\n" "Moreover, there is inline help with /help on all commands and " "options (use Tab key to complete the name).\n" - "The command /iset (script iset.pl) can help to customize " - "WeeChat: /script install iset.pl\n" + "The command /fset can help to customize WeeChat.\n" "\n" "You can add and connect to an IRC server with /server and " "/connect commands (see /help server).")); @@ -595,21 +618,18 @@ weechat_shutdown (int return_code, int crash) free (weechat_local_charset); if (crash) - abort(); + abort (); else if (return_code >= 0) exit (return_code); } /* - * Initializes WeeChat. + * Initializes gettext. */ void -weechat_init (int argc, char *argv[], void (*gui_init_cb)()) +weechat_init_gettext () { - weechat_first_start_time = time (NULL); /* initialize start time */ - gettimeofday (&weechat_current_start_timeval, NULL); - weechat_locale_ok = (setlocale (LC_ALL, "") != NULL); /* init gettext */ #ifdef ENABLE_NLS bindtextdomain (PACKAGE, LOCALEDIR); @@ -623,6 +643,17 @@ weechat_init (int argc, char *argv[], void (*gui_init_cb)()) weechat_local_charset = strdup (""); #endif /* HAVE_LANGINFO_CODESET */ utf8_init (); +} + +/* + * Initializes WeeChat. + */ + +void +weechat_init (int argc, char *argv[], void (*gui_init_cb)()) +{ + weechat_first_start_time = time (NULL); /* initialize start time */ + gettimeofday (&weechat_current_start_timeval, NULL); /* catch signals */ util_catch_signal (SIGINT, SIG_IGN); /* signal ignored */ diff --git a/src/core/weechat.h b/src/core/weechat.h index f53c26b21..9420ff415 100644 --- a/src/core/weechat.h +++ b/src/core/weechat.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -19,7 +19,7 @@ */ #ifndef WEECHAT_H -#define WEECHAT_H 1 +#define WEECHAT_H #ifdef HAVE_CONFIG_H #include "config.h" @@ -53,7 +53,7 @@ #endif /* !defined(_) */ -#define WEECHAT_COPYRIGHT_DATE "(C) 2003-2017" +#define WEECHAT_COPYRIGHT_DATE "(C) 2003-2018" #define WEECHAT_WEBSITE "https://weechat.org/" #define WEECHAT_WEBSITE_DOWNLOAD "https://weechat.org/download" @@ -93,7 +93,11 @@ /* internal charset */ #define WEECHAT_INTERNAL_CHARSET "UTF-8" +/* name of environment variable with an extra lib dir */ +#define WEECHAT_EXTRA_LIBDIR "WEECHAT_EXTRA_LIBDIR" + /* global variables and functions */ +extern int weechat_headless; extern int weechat_debug_core; extern char *weechat_argv0; extern int weechat_upgrading; @@ -101,7 +105,7 @@ extern int weechat_first_start; extern time_t weechat_first_start_time; extern struct timeval weechat_current_start_timeval; extern int weechat_upgrade_count; -extern int weechat_quit; +extern volatile sig_atomic_t weechat_quit; extern volatile sig_atomic_t weechat_quit_signal; extern char *weechat_home; extern char *weechat_local_charset; @@ -112,6 +116,7 @@ extern char *weechat_startup_commands; extern void weechat_term_check (); extern void weechat_shutdown (int return_code, int crash); +extern void weechat_init_gettext (); extern void weechat_init (int argc, char *argv[], void (*gui_init_cb)()); extern void weechat_end (void (*gui_end_cb)(int clean_exit)); diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 5bd415da3..d9d85cec5 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # @@ -18,32 +18,31 @@ # set(LIB_GUI_COMMON_SRC -gui-bar.c gui-bar.h -gui-bar-item.c gui-bar-item.h -gui-bar-window.c gui-bar-window.h -gui-buffer.c gui-buffer.h -gui-chat.c gui-chat.h -gui-color.c gui-color.h -gui-completion.c gui-completion.h -gui-cursor.c gui-cursor.h -gui-filter.c gui-filter.h -gui-focus.c gui-focus.h -gui-history.c gui-history.h -gui-hotlist.c gui-hotlist.h -gui-input.c gui-input.h -gui-key.c gui-key.h -gui-layout.c gui-layout.h -gui-line.c gui-line.h -gui-main.h -gui-mouse.c gui-mouse.h -gui-nick.c gui-nick.h -gui-nicklist.c gui-nicklist.h -gui-window.c gui-window.h) + gui-bar.c gui-bar.h + gui-bar-item.c gui-bar-item.h + gui-bar-window.c gui-bar-window.h + gui-buffer.c gui-buffer.h + gui-chat.c gui-chat.h + gui-color.c gui-color.h + gui-completion.c gui-completion.h + gui-cursor.c gui-cursor.h + gui-filter.c gui-filter.h + gui-focus.c gui-focus.h + gui-history.c gui-history.h + gui-hotlist.c gui-hotlist.h + gui-input.c gui-input.h + gui-key.c gui-key.h + gui-layout.c gui-layout.h + gui-line.c gui-line.h + gui-main.h + gui-mouse.c gui-mouse.h + gui-nick.c gui-nick.h + gui-nicklist.c gui-nicklist.h + gui-window.c gui-window.h +) include_directories(${CMAKE_BINARY_DIR}) add_library(weechat_gui_common STATIC ${LIB_GUI_COMMON_SRC}) list(APPEND STATIC_LIBS weechat_gui_common) -if(ENABLE_NCURSES) - subdirs(curses) -endif() +subdirs(curses) diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index ca1d98625..3709383b3 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # @@ -63,10 +63,6 @@ lib_weechat_gui_common_a_SOURCES = gui-bar.c \ gui-window.c \ gui-window.h -if GUI_NCURSES -curses_dir=curses -endif - -SUBDIRS = . $(curses_dir) +SUBDIRS = . curses EXTRA_DIST = CMakeLists.txt diff --git a/src/gui/curses/CMakeLists.txt b/src/gui/curses/CMakeLists.txt index cdb8f9d78..b2ef51417 100644 --- a/src/gui/curses/CMakeLists.txt +++ b/src/gui/curses/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # Copyright (C) 2007-2008 Julien Louis <ptitlouis@sysif.net> # Copyright (C) 2009 Emmanuel Bouthenot <kolter@openics.org> # @@ -19,40 +19,8 @@ # along with WeeChat. If not, see <http://www.gnu.org/licenses/>. # -set(LIB_GUI_CURSES_SRC -gui-curses.h -gui-curses-bar-window.c -gui-curses-chat.c -gui-curses-color.c -gui-curses-key.c -gui-curses-main.c -gui-curses-mouse.c -gui-curses-term.c -gui-curses-window.c) - -set(WEECHAT_CURSES_MAIN_SRC -main.c) - -set(EXECUTABLE weechat) - -find_package(Ncurses) -if(NCURSES_FOUND) - check_include_files(ncursesw/ncurses.h NCURSESW_HEADERS) - if(NCURSESW_HEADERS) - add_definitions(-DHAVE_NCURSESW_CURSES_H) - else() - check_include_files(ncurses.h NCURSES_HEADERS) - if(NCURSES_HEADERS) - add_definitions(-DHAVE_NCURSES_H) - endif() - endif() - list(APPEND EXTRA_LIBS ${NCURSES_LIBRARY}) -endif() - -if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") - if(HAVE_BACKTRACE) - list(APPEND EXTRA_LIBS "execinfo") - endif() +if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" AND HAVE_BACKTRACE) + list(APPEND EXTRA_LIBS "execinfo") endif() if(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS") @@ -78,34 +46,10 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") list(APPEND EXTRA_LIBS "resolv") endif() -include_directories(.. ../../core ../../plugins ${NCURSES_INCLUDE_PATH}) - -add_library(weechat_gui_curses STATIC ${LIB_GUI_CURSES_SRC}) - -add_executable(${EXECUTABLE} ${WEECHAT_CURSES_MAIN_SRC}) - -add_dependencies(${EXECUTABLE} weechat_gui_curses) - -# Due to circular references, we must link two times with libweechat_core.a and libweechat_gui_common.a -target_link_libraries(${EXECUTABLE} ${STATIC_LIBS} weechat_gui_curses ${EXTRA_LIBS} ${STATIC_LIBS}) - -# Create a symbolic link weechat-curses -> weechat -# This link is created for compatibility with old versions on /upgrade. -# It may be removed in future. -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${EXECUTABLE}-curses${CMAKE_EXECUTABLE_SUFFIX} - COMMAND ${CMAKE_COMMAND} -E remove -f "weechat-curses${CMAKE_EXECUTABLE_SUFFIX}" - COMMAND ${CMAKE_COMMAND} -E create_symlink "weechat${CMAKE_EXECUTABLE_SUFFIX}" "weechat-curses${CMAKE_EXECUTABLE_SUFFIX}" - DEPENDS ${EXECUTABLE} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Creating symbolic link ${EXECUTABLE}-curses${CMAKE_EXECUTABLE_SUFFIX}" - ) -add_custom_target(${EXECUTABLE}-curses${CMAKE_EXECUTABLE_SUFFIX} ALL - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${EXECUTABLE}-curses${CMAKE_EXECUTABLE_SUFFIX} -) -add_dependencies(${EXECUTABLE}-curses${CMAKE_EXECUTABLE_SUFFIX} ${EXECUTABLE}) -list(APPEND CMAKE_INSTALL_MANIFEST_FILES "${CMAKE_INSTALL_PREFIX}/bin/weechat-curses${CMAKE_EXECUTABLE_SUFFIX}") +if(ENABLE_NCURSES) + subdirs(normal) +endif() -# Install executable and symbolic link -install(TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${EXECUTABLE}-curses${CMAKE_EXECUTABLE_SUFFIX} DESTINATION bin) +if(ENABLE_HEADLESS) + subdirs(headless) +endif() diff --git a/src/gui/curses/Makefile.am b/src/gui/curses/Makefile.am index cc8bc4919..88a8113fe 100644 --- a/src/gui/curses/Makefile.am +++ b/src/gui/curses/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # @@ -17,46 +17,14 @@ # along with WeeChat. If not, see <http://www.gnu.org/licenses/>. # -AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/locale\" $(NCURSES_CFLAGS) +if GUI_NCURSES +normal_dir=normal +endif -noinst_LIBRARIES = lib_weechat_gui_curses.a +if HEADLESS +headless_dir=headless +endif -lib_weechat_gui_curses_a_SOURCES = gui-curses-bar-window.c \ - gui-curses-chat.c \ - gui-curses-color.c \ - gui-curses-key.c \ - gui-curses-main.c \ - gui-curses-mouse.c \ - gui-curses-term.c \ - gui-curses-window.c \ - gui-curses.h - -bin_PROGRAMS = weechat - -# Due to circular references, we must link two times with libweechat_core.a -# (and with two different path/names to be kept by linker) -weechat_LDADD = ./../../core/lib_weechat_core.a \ - ../../plugins/lib_weechat_plugins.a \ - ../lib_weechat_gui_common.a \ - lib_weechat_gui_curses.a \ - ../../core/lib_weechat_core.a \ - $(PLUGINS_LFLAGS) \ - $(NCURSES_LFLAGS) \ - $(GCRYPT_LFLAGS) \ - $(GNUTLS_LFLAGS) \ - $(CURL_LFLAGS) \ - -lm - -weechat_SOURCES = main.c +SUBDIRS = . $(normal_dir) $(headless_dir) EXTRA_DIST = CMakeLists.txt - -# Create a symbolic link weechat-curses -> weechat -# This link is created for compatibility with old versions on /upgrade. -# It may be removed in future. -install-exec-hook: - (cd '$(DESTDIR)$(bindir)' && rm -f weechat-curses$(EXEEXT) && $(LN_S) weechat weechat-curses$(EXEEXT)) - -# Remove symbolic link on uninstall -uninstall-hook: - (cd '$(DESTDIR)$(bindir)' && rm -f weechat-curses$(EXEEXT)) diff --git a/src/gui/curses/gui-curses-bar-window.c b/src/gui/curses/gui-curses-bar-window.c index dcf49e727..9ade3bc8d 100644 --- a/src/gui/curses/gui-curses-bar-window.c +++ b/src/gui/curses/gui-curses-bar-window.c @@ -1,7 +1,7 @@ /* * gui-curses-bar-window.c - bar window functions for Curses GUI * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/gui/curses/gui-curses-chat.c b/src/gui/curses/gui-curses-chat.c index f5d47e1f2..7fb229e88 100644 --- a/src/gui/curses/gui-curses-chat.c +++ b/src/gui/curses/gui-curses-chat.c @@ -1,7 +1,7 @@ /* * gui-curses-chat.c - chat display functions for Curses GUI * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -649,14 +649,19 @@ gui_chat_display_day_changed (struct t_gui_window *window, /* build the message to display */ if (date1) { - strftime (temp_message, sizeof (temp_message), - CONFIG_STRING(config_look_day_change_message_2dates), date1); - strftime (message, sizeof (message), temp_message, date2); + if (strftime (temp_message, sizeof (temp_message), + CONFIG_STRING(config_look_day_change_message_2dates), + date1) == 0) + temp_message[0] = '\0'; + if (strftime (message, sizeof (message), temp_message, date2) == 0) + message[0] = '\0'; } else { - strftime (message, sizeof (message), - CONFIG_STRING(config_look_day_change_message_1date), date2); + if (strftime (message, sizeof (message), + CONFIG_STRING(config_look_day_change_message_1date), + date2) == 0) + message[0] = '\0'; } message_with_color = (strstr (message, "${")) ? @@ -1928,9 +1933,10 @@ gui_chat_get_bare_line (struct t_gui_line *line) && CONFIG_STRING(config_look_bare_display_time_format)[0]) { local_time = localtime (&line->data->date); - strftime (str_time, sizeof (str_time), - CONFIG_STRING(config_look_bare_display_time_format), - local_time); + if (strftime (str_time, sizeof (str_time), + CONFIG_STRING(config_look_bare_display_time_format), + local_time) == 0) + str_time[0] = '\0'; } tag_prefix_nick = gui_line_search_tag_starting_with (line, "prefix_nick_"); diff --git a/src/gui/curses/gui-curses-color.c b/src/gui/curses/gui-curses-color.c index d2571fbd0..feb74163e 100644 --- a/src/gui/curses/gui-curses-color.c +++ b/src/gui/curses/gui-curses-color.c @@ -1,7 +1,7 @@ /* * gui-curses-color.c - color functions for Curses GUI * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -1497,7 +1497,7 @@ gui_color_init_weechat () void gui_color_alloc () { - if (has_colors()) + if (has_colors ()) { start_color (); use_default_colors (); diff --git a/src/gui/curses/gui-curses-key.c b/src/gui/curses/gui-curses-key.c index cc4ad6054..d7d6c1e17 100644 --- a/src/gui/curses/gui-curses-key.c +++ b/src/gui/curses/gui-curses-key.c @@ -1,7 +1,7 @@ /* * gui-curses-key.c - keyboard functions for Curses GUI * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/gui/curses/gui-curses-main.c b/src/gui/curses/gui-curses-main.c index ade0a9878..7355f7dee 100644 --- a/src/gui/curses/gui-curses-main.c +++ b/src/gui/curses/gui-curses-main.c @@ -1,7 +1,7 @@ /* * gui-curses-main.c - main loop for Curses GUI * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -78,12 +78,20 @@ gui_main_get_password (const char **prompt, char *password, int size) { int line, i, ch; + memset (password, '\0', size); + + if (weechat_headless) + { + password[0] = ' '; + return; + } + initscr (); cbreak (); noecho (); raw (); - clear(); + clear (); line = 0; @@ -96,7 +104,6 @@ gui_main_get_password (const char **prompt, char *password, int size) mvaddstr (line, 0, "=> "); refresh (); - memset (password, '\0', size); i = 0; while (i < size - 1) { @@ -136,6 +143,16 @@ gui_main_get_password (const char **prompt, char *password, int size) } /* + * Callback for system signal SIGINT: quits WeeChat. + */ + +void +gui_main_signal_sigint () +{ + weechat_quit = 1; +} + +/* * Initializes GUI. */ @@ -147,6 +164,11 @@ gui_main_init () struct t_gui_bar_window *ptr_bar_win; char title[256]; +#ifdef WEECHAT_HEADLESS + /* allow Ctrl-C to quit WeeChat in headless mode */ + util_catch_signal (SIGINT, &gui_main_signal_sigint); +#endif /* WEECHAT_HEADLESS */ + initscr (); if (CONFIG_BOOLEAN(config_look_eat_newline_glitch)) @@ -265,13 +287,13 @@ gui_main_handle_quit_signals () switch (weechat_quit_signal) { case SIGHUP: - snprintf (str_signal, sizeof(str_signal), "SIGHUP"); + snprintf (str_signal, sizeof (str_signal), "SIGHUP"); break; case SIGQUIT: - snprintf (str_signal, sizeof(str_signal), "SIGQUIT"); + snprintf (str_signal, sizeof (str_signal), "SIGQUIT"); break; case SIGTERM: - snprintf (str_signal, sizeof(str_signal), "SIGTERM"); + snprintf (str_signal, sizeof (str_signal), "SIGTERM"); break; default: str_signal[0] = '\0'; @@ -280,9 +302,9 @@ gui_main_handle_quit_signals () if (str_signal[0]) { - snprintf (str_weechat_signal, sizeof(str_weechat_signal), + snprintf (str_weechat_signal, sizeof (str_weechat_signal), "signal_%s", str_signal); - string_tolower(str_weechat_signal); + string_tolower (str_weechat_signal); rc = hook_signal_send (str_weechat_signal, WEECHAT_HOOK_SIGNAL_STRING, NULL); if ((rc != WEECHAT_RC_OK_EAT) && !weechat_quit) @@ -432,11 +454,19 @@ gui_main_loop () send_signal_sigwinch = 0; /* catch SIGWINCH signal: redraw screen */ - util_catch_signal (SIGWINCH, &gui_main_signal_sigwinch); + if (!weechat_headless) + util_catch_signal (SIGWINCH, &gui_main_signal_sigwinch); /* hook stdin (read keyboard) */ - hook_fd_keyboard = hook_fd (NULL, STDIN_FILENO, 1, 0, 0, - &gui_key_read_cb, NULL, NULL); + if (weechat_headless) + { + hook_fd_keyboard = NULL; + } + else + { + hook_fd_keyboard = hook_fd (NULL, STDIN_FILENO, 1, 0, 0, + &gui_key_read_cb, NULL, NULL); + } gui_window_ask_refresh (1); @@ -486,7 +516,8 @@ gui_main_loop () } /* remove keyboard hook */ - unhook (hook_fd_keyboard); + if (hook_fd_keyboard) + unhook (hook_fd_keyboard); } /* diff --git a/src/gui/curses/gui-curses-mouse.c b/src/gui/curses/gui-curses-mouse.c index 2cf9d3037..0afe8a50b 100644 --- a/src/gui/curses/gui-curses-mouse.c +++ b/src/gui/curses/gui-curses-mouse.c @@ -1,7 +1,7 @@ /* * gui-curses-mouse.c - mouse functions for Curses GUI * - * Copyright (C) 2011-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2011-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/gui/curses/gui-curses-term.c b/src/gui/curses/gui-curses-term.c index 3e26f7fb7..369fda331 100644 --- a/src/gui/curses/gui-curses-term.c +++ b/src/gui/curses/gui-curses-term.c @@ -1,7 +1,7 @@ /* * gui-curses-term.c - terminal functions for Curses GUI * - * Copyright (C) 2011-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2011-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -23,6 +23,7 @@ #include "config.h" #endif +#ifndef WEECHAT_HEADLESS #ifdef HAVE_NCURSESW_CURSES_H #ifdef __sun #include <ncurses/term.h> @@ -32,6 +33,7 @@ #else #include <term.h> #endif /* HAVE_NCURSESW_CURSES_H */ +#endif /* WEECHAT_HEADLESS */ /* @@ -45,10 +47,10 @@ void gui_term_set_eat_newline_glitch (int value) { -#ifdef HAVE_EAT_NEWLINE_GLITCH +#if !defined(WEECHAT_HEADLESS) && defined(HAVE_EAT_NEWLINE_GLITCH) eat_newline_glitch = value; #else /* make C compiler happy */ (void) value; -#endif /* HAVE_EAT_NEWLINE_GLITCH */ +#endif } diff --git a/src/gui/curses/gui-curses-window.c b/src/gui/curses/gui-curses-window.c index a95b2724e..3b410dfd7 100644 --- a/src/gui/curses/gui-curses-window.c +++ b/src/gui/curses/gui-curses-window.c @@ -1,7 +1,7 @@ /* * gui-curses-window.c - window display functions for Curses GUI * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -570,6 +570,8 @@ gui_window_emphasize (WINDOW *window, int x, int y, int count) else { /* exclusive or (XOR) with attributes */ + attrs = 0; + pair = 0; ptr_attrs = &attrs; ptr_pair = &pair; wattr_get (window, ptr_attrs, ptr_pair, NULL); @@ -2563,7 +2565,7 @@ gui_window_term_display_infos () gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("Terminal infos:")); gui_chat_printf (NULL, _(" TERM='%s', size: %dx%d"), - getenv("TERM"), gui_term_cols, gui_term_lines); + getenv ("TERM"), gui_term_cols, gui_term_lines); } /* diff --git a/src/gui/curses/gui-curses.h b/src/gui/curses/gui-curses.h index 35185f291..7f7359d29 100644 --- a/src/gui/curses/gui-curses.h +++ b/src/gui/curses/gui-curses.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,10 +18,13 @@ */ #ifndef WEECHAT_GUI_CURSES_H -#define WEECHAT_GUI_CURSES_H 1 +#define WEECHAT_GUI_CURSES_H #include <time.h> +#ifdef WEECHAT_HEADLESS +#include "ncurses-fake.h" +#else #ifdef HAVE_NCURSESW_CURSES_H #include <ncursesw/ncurses.h> #elif HAVE_NCURSES_H @@ -29,6 +32,7 @@ #else #include <curses.h> #endif /* HAVE_NCURSESW_CURSES_H */ +#endif /* WEECHAT_HEADLESS */ struct t_gui_buffer; struct t_gui_line; diff --git a/src/gui/curses/headless/CMakeLists.txt b/src/gui/curses/headless/CMakeLists.txt new file mode 100644 index 000000000..3aa6b4448 --- /dev/null +++ b/src/gui/curses/headless/CMakeLists.txt @@ -0,0 +1,57 @@ +# +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> +# +# This file is part of WeeChat, the extensible chat client. +# +# WeeChat is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# WeeChat is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with WeeChat. If not, see <http://www.gnu.org/licenses/>. +# + +add_definitions(-DWEECHAT_HEADLESS) + +# fake ncurses lib (for headless mode and tests) +set(LIB_WEECHAT_NCURSES_FAKE_SRC + ncurses-fake.h + ncurses-fake.c +) +add_library(weechat_ncurses_fake STATIC ${LIB_WEECHAT_NCURSES_FAKE_SRC}) + +set(LIB_GUI_CURSES_SRC + ../gui-curses.h + ../gui-curses-bar-window.c + ../gui-curses-chat.c + ../gui-curses-color.c + ../gui-curses-key.c + ../gui-curses-main.c + ../gui-curses-mouse.c + ../gui-curses-term.c + ../gui-curses-window.c +) + +include_directories(. .. ../../core ../../plugins) + +add_library(weechat_gui_headless STATIC ${LIB_GUI_CURSES_SRC}) + +set(WEECHAT_CURSES_MAIN_HEADLESS_SRC main.c) + +set(EXECUTABLE weechat-headless) + +add_executable(${EXECUTABLE} ${WEECHAT_CURSES_MAIN_HEADLESS_SRC}) + +add_dependencies(${EXECUTABLE} weechat_gui_headless weechat_ncurses_fake) + +# Due to circular references, we must link two times with libweechat_core.a and libweechat_gui_common.a +target_link_libraries(${EXECUTABLE} ${STATIC_LIBS} weechat_gui_headless weechat_ncurses_fake ${EXTRA_LIBS} ${STATIC_LIBS}) + +# Install executable +install(TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin) diff --git a/src/gui/curses/headless/Makefile.am b/src/gui/curses/headless/Makefile.am new file mode 100644 index 000000000..08c2d164e --- /dev/null +++ b/src/gui/curses/headless/Makefile.am @@ -0,0 +1,55 @@ +# +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> +# +# This file is part of WeeChat, the extensible chat client. +# +# WeeChat is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# WeeChat is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with WeeChat. If not, see <http://www.gnu.org/licenses/>. +# + +AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/locale\" -DWEECHAT_HEADLESS + +noinst_LIBRARIES = lib_weechat_ncurses_fake.a lib_weechat_gui_headless.a + +lib_weechat_ncurses_fake_a_SOURCES = ncurses-fake.c \ + ncurses-fake.h + +lib_weechat_gui_headless_a_SOURCES = ../gui-curses-bar-window.c \ + ../gui-curses-chat.c \ + ../gui-curses-color.c \ + ../gui-curses-key.c \ + ../gui-curses-main.c \ + ../gui-curses-mouse.c \ + ../gui-curses-term.c \ + ../gui-curses-window.c \ + ../gui-curses.h + +bin_PROGRAMS = weechat-headless + +# Due to circular references, we must link two times with libweechat_core.a +# (and with two different path/names to be kept by linker) +weechat_headless_LDADD = ./../../../core/lib_weechat_core.a \ + ../../../plugins/lib_weechat_plugins.a \ + ../../lib_weechat_gui_common.a \ + lib_weechat_gui_headless.a \ + lib_weechat_ncurses_fake.a \ + ../../../core/lib_weechat_core.a \ + $(PLUGINS_LFLAGS) \ + $(GCRYPT_LFLAGS) \ + $(GNUTLS_LFLAGS) \ + $(CURL_LFLAGS) \ + -lm + +weechat_headless_SOURCES = main.c + +EXTRA_DIST = CMakeLists.txt diff --git a/src/gui/curses/headless/main.c b/src/gui/curses/headless/main.c new file mode 100644 index 000000000..194150405 --- /dev/null +++ b/src/gui/curses/headless/main.c @@ -0,0 +1,125 @@ +/* + * main.c - entry point for headless mode (no GUI) + * + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> + +#include "../../../core/weechat.h" +#include "../../gui-main.h" +#include "../gui-curses.h" + + +/* + * Daemonizes the process. + */ + +void +daemonize () +{ + pid_t pid; + int fd, i; + + printf (_("Running WeeChat in background...")); + printf (" "); + + pid = fork(); + + if (pid < 0) + { + printf (_("fork error")); + printf ("\n"); + exit (EXIT_FAILURE); + } + + if (pid > 0) + { + /* parent process */ + printf (_("OK")); + printf ("\n"); + exit (EXIT_SUCCESS); + } + + /* child process */ + + /* obtain a new process group */ + setsid (); + + /* close all file descriptors */ + for (i = sysconf(_SC_OPEN_MAX); i >= 0; --i) + { + close (i); + } + fd = open ("/dev/null", O_RDWR); + (void) dup (fd); + (void) dup (fd); +} + +/* + * Entry point for WeeChat in headless mode (no GUI). + */ + +int +main (int argc, char *argv[]) +{ + int i, daemon; + + weechat_init_gettext (); + + /* + * Enable a special "headless" mode, where some things are slightly + * different, for example: + * - no read of stdin (keyboard/mouse) + * - don't catch any terminal related signal + */ + weechat_headless = 1; + + /* + * If "--daemon" is received in command line arguments, + * daemonize the process. + */ + daemon = 0; + for (i = 1; i < argc; i++) + { + if (strcmp (argv[i], "--daemon") == 0) + { + daemon = 1; + break; + } + } + if (daemon) + daemonize (); + + /* init, main loop and end */ + weechat_init (argc, argv, &gui_main_init); + gui_main_loop (); + weechat_end (&gui_main_end); + + return EXIT_SUCCESS; +} diff --git a/src/gui/curses/headless/ncurses-fake.c b/src/gui/curses/headless/ncurses-fake.c new file mode 100644 index 000000000..da1e4ac8d --- /dev/null +++ b/src/gui/curses/headless/ncurses-fake.c @@ -0,0 +1,433 @@ +/* + * ncurses-fake.c - fake ncurses lib (for headless mode and tests) + * + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ncurses-fake.h" + + +/* simulate 80x25 terminal */ +WINDOW _stdscr = { 0, 0, 24, 79, 0, 0 }; +WINDOW *stdscr = &_stdscr; +chtype acs_map[256]; + + +WINDOW * +initscr () +{ + return stdscr; +} + +int +endwin () +{ + return OK; +} + +WINDOW * +newwin (int nlines, int ncols, int begin_y, int begin_x) +{ + (void) nlines; + (void) ncols; + (void) begin_y; + (void) begin_x; + + return stdscr; +} + +int +delwin (WINDOW *win) +{ + (void) win; + + return OK; +} + +int +move (int y, int x) +{ + (void) y; + (void) x; + + return OK; +} + +int +wmove (WINDOW *win, int y, int x) +{ + (void) win; + (void) y; + (void) x; + + return OK; +} + +int +wattr_on (WINDOW *win, attr_t attrs, void *opts) +{ + (void) win; + (void) attrs; + (void) opts; + + return OK; +} + +int +wattr_off (WINDOW *win, attr_t attrs, void *opts) +{ + (void) win; + (void) attrs; + (void) opts; + + return OK; +} + +int +wattr_get (WINDOW *win, attr_t *attrs, short *pair, void *opts) +{ + (void) win; + (void) attrs; + (void) pair; + (void) opts; + + return OK; +} + +int +wattr_set (WINDOW *win, attr_t attrs, short pair, void *opts) +{ + (void) win; + (void) attrs; + (void) pair; + (void) opts; + + return OK; +} + +int +wattron (WINDOW *win, int attrs) +{ + (void) win; + (void) attrs; + + return OK; +} + +int +wattroff (WINDOW *win, int attrs) +{ + (void) win; + (void) attrs; + + return OK; +} + +int +waddstr (WINDOW *win, const char *str) +{ + (void) win; + (void) str; + + return OK; +} + +int +waddnstr (WINDOW *win, const char *str, int n) +{ + (void) win; + (void) str; + (void) n; + + return OK; +} + +int +mvaddstr (int y, int x, const char *str) +{ + (void) y; + (void) x; + (void) str; + + return OK; +} + +int +mvwaddstr (WINDOW *win, int y, int x, const char *str) +{ + (void) win; + (void) y; + (void) x; + (void) str; + + return OK; +} + +int +wclrtobot (WINDOW *win) +{ + (void) win; + + return OK; +} + +int +refresh () +{ + return OK; +} + +int +wrefresh (WINDOW *win) +{ + (void) win; + + return OK; +} + +int +wnoutrefresh (WINDOW *win) +{ + (void) win; + + return OK; +} + +int +wclrtoeol (WINDOW *win) +{ + (void) win; + + return OK; +} + +int +mvwprintw (WINDOW *win, int y, int x, const char *fmt, ...) +{ + (void) win; + (void) y; + (void) x; + (void) fmt; + + return OK; +} + +int +init_pair (short pair, short f, short b) +{ + (void) pair; + (void) f; + (void) b; + + return OK; +} + +bool +has_colors () +{ + return TRUE; +} + +int +cbreak () +{ + return OK; +} + +int +start_color () +{ + return OK; +} + +int +noecho () +{ + return OK; +} + +int +clear () +{ + return OK; +} + +int +wclear (WINDOW *win) +{ + (void) win; + + return OK; +} + +bool +can_change_color () +{ + /* not supported in WeeChat anyway */ + return FALSE; +} + +int +curs_set (int visibility) +{ + (void) visibility; + + return 1; /* 0 == invisible, 1 == normal, 2 == very visible */ +} + +int +nodelay (WINDOW *win, bool bf) +{ + (void) win; + (void) bf; + + return OK; +} + +int +werase (WINDOW *win) +{ + (void) win; + + return OK; +} + +int +wbkgdset (WINDOW *win, chtype ch) +{ + (void) win; + (void) ch; + + return OK; +} + +void +wchgat (WINDOW *win, int n, attr_t attr, short color, const void *opts) +{ + (void) win; + (void) n; + (void) attr; + (void) color; + (void) opts; +} + +int +mvwchgat (WINDOW *win, int y, int x, int n, attr_t attr, short pair, + const void *opts) +{ + (void) win; + (void) y; + (void) x; + (void) n; + (void) attr; + (void) pair; + (void) opts; + + return OK; +} + + +void +whline (WINDOW *win, chtype ch, int n) +{ + (void) win; + (void) ch; + (void) n; +} + +void +wvline (WINDOW *win, chtype ch, int n) +{ + (void) win; + (void) ch; + (void) n; +} + +int +mvwhline (WINDOW *win, int y, int x, chtype ch, int n) +{ + (void) win; + (void) y; + (void) x; + (void) ch; + (void) n; + + return OK; +} + +int +mvwvline (WINDOW *win, int y, int x, chtype ch, int n) +{ + (void) win; + (void) y; + (void) x; + (void) ch; + (void) n; + + return OK; +} + +int +raw () +{ + return OK; +} + +int +wcolor_set (WINDOW *win, short pair, void *opts) +{ + (void) win; + (void) pair; + (void) opts; + + return OK; +} + +void +cur_term () +{ +} + +int +use_default_colors () +{ + return OK; +} + +int +resizeterm (int lines, int columns) +{ + (void) lines; + (void) columns; + + return OK; +} + +int +getch () +{ + return ERR; +} + +int +wgetch (WINDOW *win) +{ + (void) win; + + return OK; +} diff --git a/src/gui/curses/headless/ncurses-fake.h b/src/gui/curses/headless/ncurses-fake.h new file mode 100644 index 000000000..79ce6fc25 --- /dev/null +++ b/src/gui/curses/headless/ncurses-fake.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef WEECHAT_NCURSES_FAKE_H +#define WEECHAT_NCURSES_FAKE_H + +#define ERR (-1) +#define OK (0) + +#define TRUE 1 +#define FALSE 0 + +#define COLS 80 +#define LINES 25 +#define COLORS 256 +#define COLOR_PAIRS 256 + +#define COLOR_PAIR(x) x + +#define COLOR_BLACK 0 +#define COLOR_RED 1 +#define COLOR_GREEN 2 +#define COLOR_YELLOW 3 +#define COLOR_BLUE 4 +#define COLOR_MAGENTA 5 +#define COLOR_CYAN 6 +#define COLOR_WHITE 7 + +#define A_BOLD 0 +#define A_UNDERLINE 0 +#define A_REVERSE 0 +#define A_ITALIC 0 + +#define ACS_HLINE '-' +#define ACS_VLINE '|' + +#define getyx(win, x, y) \ + x = 0; \ + y = 0; + +#define getmaxyx(win, x, y) \ + x = 0; \ + y = 0; + +struct _window +{ + int _cury, _curx; + int _maxy, _maxx; + int _begy, _begx; +}; +typedef struct _window WINDOW; + +typedef unsigned char bool; +typedef int attr_t; +typedef unsigned chtype; + +extern WINDOW *stdscr; +extern chtype acs_map[]; + +extern WINDOW *initscr (); +extern int endwin (); +extern WINDOW *newwin (int nlines, int ncols, int begin_y, int begin_x); +extern int delwin (WINDOW *win); +extern int move (int y, int x); +extern int wmove (WINDOW *win, int y, int x); +extern int wattr_on (WINDOW *win, attr_t attrs, void *opts); +extern int wattr_off (WINDOW *win, attr_t attrs, void *opts); +extern int wattr_get (WINDOW *win, attr_t *attrs, short *pair, void *opts); +extern int wattr_set (WINDOW *win, attr_t attrs, short pair, void *opts); +extern int wattron (WINDOW *win, int attrs); +extern int wattroff (WINDOW *win, int attrs); +extern int waddstr (WINDOW *win, const char *str); +extern int waddnstr (WINDOW *win, const char *str, int n); +extern int mvaddstr (int y, int x, const char *str); +extern int mvwaddstr (WINDOW *win, int y, int x, const char *str); +extern int wclrtobot (WINDOW *win); +extern int refresh (); +extern int wrefresh (WINDOW *win); +extern int wnoutrefresh (WINDOW *win); +extern int wclrtoeol (WINDOW *win); +extern int mvwprintw (WINDOW *win, int y, int x, const char *fmt, ...); +extern int init_pair (short pair, short f, short b); +extern bool has_colors (); +extern int cbreak (); +extern int start_color (); +extern int noecho (); +extern int clear (); +extern int wclear (WINDOW *win); +extern bool can_change_color (); +extern int curs_set (int visibility); +extern int nodelay (WINDOW *win, bool bf); +extern int werase (WINDOW *win); +extern int wbkgdset (WINDOW *win, chtype ch); +extern void wchgat (WINDOW *win, int n, attr_t attr, short color, + const void *opts); +extern int mvwchgat (WINDOW *win, int y, int x, int n, attr_t attr, short pair, + const void *opts); +extern void whline (WINDOW *win, chtype ch, int n); +extern void wvline (WINDOW *win, chtype ch, int n); +extern int mvwhline (WINDOW *win, int y, int x, chtype ch, int n); +extern int mvwvline (WINDOW *win, int y, int x, chtype ch, int n); +extern int raw (); +extern int wcolor_set (WINDOW *win, short pair, void *opts); +extern void cur_term (); +extern int use_default_colors (); +extern int resizeterm (); +extern int getch (); +extern int wgetch (WINDOW *win); + +#endif /* WEECHAT_NCURSES_FAKE_H */ diff --git a/src/gui/curses/normal/CMakeLists.txt b/src/gui/curses/normal/CMakeLists.txt new file mode 100644 index 000000000..b22fcf76c --- /dev/null +++ b/src/gui/curses/normal/CMakeLists.txt @@ -0,0 +1,76 @@ +# +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> +# +# This file is part of WeeChat, the extensible chat client. +# +# WeeChat is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# WeeChat is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with WeeChat. If not, see <http://www.gnu.org/licenses/>. +# + +set(LIB_GUI_CURSES_SRC + ../gui-curses.h + ../gui-curses-bar-window.c + ../gui-curses-chat.c + ../gui-curses-color.c + ../gui-curses-key.c + ../gui-curses-main.c + ../gui-curses-mouse.c + ../gui-curses-term.c + ../gui-curses-window.c +) + +find_package(Ncurses) +if(NCURSES_FOUND) + check_include_files(ncursesw/ncurses.h NCURSESW_HEADERS) + if(NCURSESW_HEADERS) + add_definitions(-DHAVE_NCURSESW_CURSES_H) + else() + check_include_files(ncurses.h NCURSES_HEADERS) + if(NCURSES_HEADERS) + add_definitions(-DHAVE_NCURSES_H) + endif() + endif() +endif() + +include_directories(.. ../../core ../../plugins ${NCURSES_INCLUDE_PATH}) + +add_library(weechat_gui_curses_normal STATIC ${LIB_GUI_CURSES_SRC}) + +set(WEECHAT_CURSES_MAIN_SRC main.c) + +set(EXECUTABLE weechat) + +add_executable(${EXECUTABLE} ${WEECHAT_CURSES_MAIN_SRC}) + +add_dependencies(${EXECUTABLE} weechat_gui_curses_normal) + +list(APPEND EXTRA_LIBS ${NCURSES_LIBRARY}) + +# Due to circular references, we must link two times with libweechat_core.a and libweechat_gui_common.a +target_link_libraries(${EXECUTABLE} ${STATIC_LIBS} weechat_gui_curses_normal ${EXTRA_LIBS} ${STATIC_LIBS}) + +# Create a symbolic link weechat-curses -> weechat +# This link is created for compatibility with old versions on /upgrade. +# It may be removed in future. +add_custom_command( + TARGET ${EXECUTABLE} + COMMAND ${CMAKE_COMMAND} -E remove -f "weechat-curses${CMAKE_EXECUTABLE_SUFFIX}" + COMMAND ${CMAKE_COMMAND} -E create_symlink "weechat${CMAKE_EXECUTABLE_SUFFIX}" "weechat-curses${CMAKE_EXECUTABLE_SUFFIX}" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Creating symbolic link ${EXECUTABLE}-curses${CMAKE_EXECUTABLE_SUFFIX}" +) +list(APPEND CMAKE_INSTALL_MANIFEST_FILES "${CMAKE_INSTALL_PREFIX}/bin/weechat-curses${CMAKE_EXECUTABLE_SUFFIX}") + +# Install executable and symbolic link +install(TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${EXECUTABLE}-curses${CMAKE_EXECUTABLE_SUFFIX} DESTINATION bin) diff --git a/src/gui/curses/normal/Makefile.am b/src/gui/curses/normal/Makefile.am new file mode 100644 index 000000000..2e9127266 --- /dev/null +++ b/src/gui/curses/normal/Makefile.am @@ -0,0 +1,62 @@ +# +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> +# +# This file is part of WeeChat, the extensible chat client. +# +# WeeChat is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# WeeChat is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with WeeChat. If not, see <http://www.gnu.org/licenses/>. +# + +AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/locale\" $(NCURSES_CFLAGS) + +noinst_LIBRARIES = lib_weechat_gui_curses.a + +lib_weechat_gui_curses_a_SOURCES = ../gui-curses-bar-window.c \ + ../gui-curses-chat.c \ + ../gui-curses-color.c \ + ../gui-curses-key.c \ + ../gui-curses-main.c \ + ../gui-curses-mouse.c \ + ../gui-curses-term.c \ + ../gui-curses-window.c \ + ../gui-curses.h + +bin_PROGRAMS = weechat + +# Due to circular references, we must link two times with libweechat_core.a +# (and with two different path/names to be kept by linker) +weechat_LDADD = ./../../../core/lib_weechat_core.a \ + ../../../plugins/lib_weechat_plugins.a \ + ../../lib_weechat_gui_common.a \ + lib_weechat_gui_curses.a \ + ../../../core/lib_weechat_core.a \ + $(PLUGINS_LFLAGS) \ + $(NCURSES_LFLAGS) \ + $(GCRYPT_LFLAGS) \ + $(GNUTLS_LFLAGS) \ + $(CURL_LFLAGS) \ + -lm + +weechat_SOURCES = main.c + +EXTRA_DIST = CMakeLists.txt + +# Create a symbolic link weechat-curses -> weechat +# This link is created for compatibility with old versions on /upgrade. +# It may be removed in future. +install-exec-hook: + (cd '$(DESTDIR)$(bindir)' && $(RM) weechat-curses$(EXEEXT) && $(LN_S) weechat weechat-curses$(EXEEXT)) + +# Remove symbolic link on uninstall +uninstall-hook: + (cd '$(DESTDIR)$(bindir)' && $(RM) weechat-curses$(EXEEXT)) diff --git a/src/gui/curses/main.c b/src/gui/curses/normal/main.c index ae2c7ec5f..b3e57e99b 100644 --- a/src/gui/curses/main.c +++ b/src/gui/curses/normal/main.c @@ -1,7 +1,7 @@ /* * main.c - entry point for Curses GUI * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -25,9 +25,9 @@ #include <stdlib.h> -#include "../../core/weechat.h" -#include "../gui-main.h" -#include "gui-curses.h" +#include "../../../core/weechat.h" +#include "../../gui-main.h" +#include "../gui-curses.h" /* @@ -37,6 +37,8 @@ int main (int argc, char *argv[]) { + /* init, main loop and end */ + weechat_init_gettext (); weechat_init (argc, argv, &gui_main_init); gui_main_loop (); weechat_end (&gui_main_end); diff --git a/src/gui/gui-bar-item.c b/src/gui/gui-bar-item.c index eba0d3971..e379d27a0 100644 --- a/src/gui/gui-bar-item.c +++ b/src/gui/gui-bar-item.c @@ -1,7 +1,7 @@ /* * gui-bar-item.c - bar item functions (used by all GUI) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -758,8 +758,8 @@ gui_bar_item_input_paste_cb (const void *pointer, void *data, lines = gui_key_get_paste_lines (); snprintf (str_paste, sizeof (str_paste), - NG_("%sPaste %d line ? [ctrl-Y] Yes [ctrl-N] No", - "%sPaste %d lines ? [ctrl-Y] Yes [ctrl-N] No", + NG_("%sPaste %d line? [ctrl-Y] Yes [ctrl-N] No", + "%sPaste %d lines? [ctrl-Y] Yes [ctrl-N] No", lines), gui_color_get_custom (gui_color_get_name (CONFIG_COLOR(config_color_input_actions))), lines); diff --git a/src/gui/gui-bar-item.h b/src/gui/gui-bar-item.h index e657aa83f..70403825d 100644 --- a/src/gui/gui-bar-item.h +++ b/src/gui/gui-bar-item.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_BAR_ITEM_H -#define WEECHAT_GUI_BAR_ITEM_H 1 +#define WEECHAT_GUI_BAR_ITEM_H enum t_gui_bar_item_weechat { diff --git a/src/gui/gui-bar-window.c b/src/gui/gui-bar-window.c index 154f1dc27..9bc7dfc88 100644 --- a/src/gui/gui-bar-window.c +++ b/src/gui/gui-bar-window.c @@ -1,7 +1,7 @@ /* * gui-bar-window.c - bar window functions (used by all GUI) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -828,7 +828,7 @@ gui_bar_window_content_get_with_filling (struct t_gui_bar_window *bar_window, total_items = 0; max_length = 1; max_length_screen = 1; - split_items = malloc(bar_window->items_count * sizeof(*split_items)); + split_items = malloc (bar_window->items_count * sizeof (*split_items)); for (i = 0; i < bar_window->items_count; i++) { if (bar_window->items_subcount[i] > 0) diff --git a/src/gui/gui-bar-window.h b/src/gui/gui-bar-window.h index c5e4a1e43..a78224e1d 100644 --- a/src/gui/gui-bar-window.h +++ b/src/gui/gui-bar-window.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_BAR_WINDOW_H -#define WEECHAT_GUI_BAR_WINDOW_H 1 +#define WEECHAT_GUI_BAR_WINDOW_H #include "gui-bar.h" diff --git a/src/gui/gui-bar.c b/src/gui/gui-bar.c index c2b3c2dfc..adcda616b 100644 --- a/src/gui/gui-bar.c +++ b/src/gui/gui-bar.c @@ -1,7 +1,7 @@ /* * gui-bar.c - bar functions (used by all GUI) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -1708,33 +1708,33 @@ gui_bar_new (const char *name, const char *hidden, const char *priority, if (!new_bar) { if (option_hidden) - config_file_option_free (option_hidden); + config_file_option_free (option_hidden, 0); if (option_priority) - config_file_option_free (option_priority); + config_file_option_free (option_priority, 0); if (option_type) - config_file_option_free (option_type); + config_file_option_free (option_type, 0); if (option_conditions) - config_file_option_free (option_conditions); + config_file_option_free (option_conditions, 0); if (option_position) - config_file_option_free (option_position); + config_file_option_free (option_position, 0); if (option_filling_top_bottom) - config_file_option_free (option_filling_top_bottom); + config_file_option_free (option_filling_top_bottom, 0); if (option_filling_left_right) - config_file_option_free (option_filling_left_right); + config_file_option_free (option_filling_left_right, 0); if (option_size) - config_file_option_free (option_size); + config_file_option_free (option_size, 0); if (option_size_max) - config_file_option_free (option_size_max); + config_file_option_free (option_size_max, 0); if (option_color_fg) - config_file_option_free (option_color_fg); + config_file_option_free (option_color_fg, 0); if (option_color_delim) - config_file_option_free (option_color_delim); + config_file_option_free (option_color_delim, 0); if (option_color_bg) - config_file_option_free (option_color_bg); + config_file_option_free (option_color_bg, 0); if (option_separator) - config_file_option_free (option_separator); + config_file_option_free (option_separator, 0); if (option_items) - config_file_option_free (option_items); + config_file_option_free (option_items, 0); } return new_bar; @@ -1790,7 +1790,7 @@ gui_bar_use_temp_bars () { if (ptr_temp_bar->options[i]) { - config_file_option_free (ptr_temp_bar->options[i]); + config_file_option_free (ptr_temp_bar->options[i], 0); ptr_temp_bar->options[i] = NULL; } } @@ -2171,7 +2171,7 @@ gui_bar_free (struct t_gui_bar *bar) for (i = 0; i < GUI_BAR_NUM_OPTIONS; i++) { if (bar->options[i]) - config_file_option_free (bar->options[i]); + config_file_option_free (bar->options[i], 1); } gui_bar_free_items_arrays (bar); diff --git a/src/gui/gui-bar.h b/src/gui/gui-bar.h index 0dd5cd8ff..fcf236b74 100644 --- a/src/gui/gui-bar.h +++ b/src/gui/gui-bar.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_BAR_H -#define WEECHAT_GUI_BAR_H 1 +#define WEECHAT_GUI_BAR_H struct t_infolist; struct t_weechat_plugin; diff --git a/src/gui/gui-buffer.c b/src/gui/gui-buffer.c index f30a78db7..db80180a4 100644 --- a/src/gui/gui-buffer.c +++ b/src/gui/gui-buffer.c @@ -1,7 +1,7 @@ /* * gui-buffer.c - buffer functions (used by all GUI) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -42,6 +42,7 @@ #include "../core/wee-infolist.h" #include "../core/wee-list.h" #include "../core/wee-log.h" +#include "../core/wee-secure.h" #include "../core/wee-string.h" #include "../core/wee-utf8.h" #include "../plugins/plugin.h" @@ -73,6 +74,11 @@ int gui_buffers_visited_count = 0; /* number of visited buffers*/ int gui_buffers_visited_frozen = 0; /* 1 to forbid list updates */ struct t_gui_buffer *gui_buffer_last_displayed = NULL; /* last b. displayed */ +char *gui_buffer_reserved_names[] = +{ GUI_BUFFER_MAIN, SECURE_BUFFER_NAME, GUI_COLOR_BUFFER_NAME, + NULL +}; + char *gui_buffer_notify_string[GUI_BUFFER_NUM_NOTIFY] = { "none", "highlight", "message", "all" }; @@ -84,9 +90,9 @@ char *gui_buffer_properties_get_integer[] = "nicklist_case_sensitive", "nicklist_max_length", "nicklist_display_groups", "nicklist_count", "nicklist_groups_count", "nicklist_nicks_count", "nicklist_visible_count", "input", "input_get_unknown_commands", - "input_size", "input_length", "input_pos", "input_1st_display", - "num_history", "text_search", "text_search_exact", "text_search_regex", - "text_search_where", "text_search_found", + "input_get_empty", "input_size", "input_length", "input_pos", + "input_1st_display", "num_history", "text_search", "text_search_exact", + "text_search_regex", "text_search_where", "text_search_found", NULL }; char *gui_buffer_properties_get_string[] = @@ -107,7 +113,7 @@ char *gui_buffer_properties_set[] = "highlight_words_del", "highlight_regex", "highlight_tags_restrict", "highlight_tags", "hotlist_max_level_nicks", "hotlist_max_level_nicks_add", "hotlist_max_level_nicks_del", "input", "input_pos", - "input_get_unknown_commands", + "input_get_unknown_commands", "input_get_empty", NULL }; @@ -547,6 +553,31 @@ gui_buffer_input_buffer_init (struct t_gui_buffer *buffer) } /* + * Checks if the name is reserved for WeeChat. + * + * Returns: + * 0: name is not reserved for WeeChat + * 1: name is reserved for WeeChat + */ + +int +gui_buffer_is_reserved_name (const char *name) +{ + int i; + + if (!name) + return 0; + + for (i = 0; gui_buffer_reserved_names[i]; i++) + { + if (strcmp (name, gui_buffer_reserved_names[i]) == 0) + break; + } + + return (gui_buffer_reserved_names[i]) ? 1 : 0; +} + +/* * Creates a new buffer in current window. * * Returns pointer to new buffer, NULL if error. @@ -661,6 +692,7 @@ gui_buffer_new (struct t_weechat_plugin *plugin, new_buffer->input_callback_pointer = input_callback_pointer; new_buffer->input_callback_data = input_callback_data; new_buffer->input_get_unknown_commands = 0; + new_buffer->input_get_empty = 0; gui_buffer_input_buffer_init (new_buffer); /* undo for input */ @@ -756,6 +788,71 @@ gui_buffer_new (struct t_weechat_plugin *plugin, } /* + * Input callback for user buffers. + */ + +int +gui_buffer_user_input_cb (const void *pointer, void *data, + struct t_gui_buffer *buffer, const char *input_data) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + + if (string_strcasecmp (input_data, "q") == 0) + { + gui_buffer_close (buffer); + } + + return WEECHAT_RC_OK; +} + +/* + * Creates a new user buffer in current window. + * + * Returns pointer to new buffer, NULL if error. + */ + +struct t_gui_buffer * +gui_buffer_new_user (const char *name) +{ + struct t_gui_buffer *new_buffer; + + new_buffer = gui_buffer_new (NULL, name, + &gui_buffer_user_input_cb, NULL, NULL, + NULL, NULL, NULL); + if (new_buffer) + gui_buffer_set (new_buffer, "localvar_set_type", "user"); + + return new_buffer; +} + +/* + * Sets callbacks on user buffers. + */ + +void +gui_buffer_user_set_callbacks () +{ + struct t_gui_buffer *ptr_buffer; + const char *ptr_type; + + for (ptr_buffer = gui_buffers; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + if (!ptr_buffer->plugin + && !gui_buffer_is_reserved_name (ptr_buffer->name)) + { + ptr_type = gui_buffer_get_string (ptr_buffer, "localvar_type"); + if (ptr_type && (strcmp (ptr_type, "user") == 0)) + { + ptr_buffer->input_callback = &gui_buffer_user_input_cb; + } + } + } +} + +/* * Checks if a buffer pointer is valid. * * Returns: @@ -1063,6 +1160,8 @@ gui_buffer_get_integer (struct t_gui_buffer *buffer, const char *property) return buffer->input; else if (string_strcasecmp (property, "input_get_unknown_commands") == 0) return buffer->input_get_unknown_commands; + else if (string_strcasecmp (property, "input_get_empty") == 0) + return buffer->input_get_empty; else if (string_strcasecmp (property, "input_size") == 0) return buffer->input_buffer_size; else if (string_strcasecmp (property, "input_length") == 0) @@ -1761,6 +1860,20 @@ gui_buffer_set_input_get_unknown_commands (struct t_gui_buffer *buffer, } /* + * Sets flag "input_get_empty" for a buffer. + */ + +void +gui_buffer_set_input_get_empty (struct t_gui_buffer *buffer, + int input_get_empty) +{ + if (!buffer) + return; + + buffer->input_get_empty = (input_get_empty) ? 1 : 0; +} + +/* * Sets unread marker for a buffer. */ @@ -2025,6 +2138,13 @@ gui_buffer_set (struct t_gui_buffer *buffer, const char *property, if (error && !error[0]) gui_buffer_set_input_get_unknown_commands (buffer, number); } + else if (string_strcasecmp (property, "input_get_empty") == 0) + { + error = NULL; + number = strtol (value, &error, 10); + if (error && !error[0]) + gui_buffer_set_input_get_empty (buffer, number); + } else if (string_strncasecmp (property, "localvar_set_", 13) == 0) { if (value) @@ -4125,6 +4245,7 @@ gui_buffer_hdata_buffer_cb (const void *pointer, void *data, HDATA_VAR(struct t_gui_buffer, input_callback_pointer, POINTER, 0, NULL, NULL); HDATA_VAR(struct t_gui_buffer, input_callback_data, POINTER, 0, NULL, NULL); HDATA_VAR(struct t_gui_buffer, input_get_unknown_commands, INTEGER, 0, NULL, NULL); + HDATA_VAR(struct t_gui_buffer, input_get_empty, INTEGER, 0, NULL, NULL); HDATA_VAR(struct t_gui_buffer, input_buffer, STRING, 0, NULL, NULL); HDATA_VAR(struct t_gui_buffer, input_buffer_alloc, INTEGER, 0, NULL, NULL); HDATA_VAR(struct t_gui_buffer, input_buffer_size, INTEGER, 0, NULL, NULL); @@ -4321,6 +4442,8 @@ gui_buffer_add_to_infolist (struct t_infolist *infolist, return 0; if (!infolist_new_var_integer (ptr_item, "input_get_unknown_commands", buffer->input_get_unknown_commands)) return 0; + if (!infolist_new_var_integer (ptr_item, "input_get_empty", buffer->input_get_empty)) + return 0; if (!infolist_new_var_string (ptr_item, "input_buffer", buffer->input_buffer)) return 0; if (!infolist_new_var_integer (ptr_item, "input_buffer_alloc", buffer->input_buffer_alloc)) @@ -4532,6 +4655,7 @@ gui_buffer_print_log () log_printf (" input_callback_pointer. : 0x%lx", ptr_buffer->input_callback_pointer); log_printf (" input_callback_data . . : 0x%lx", ptr_buffer->input_callback_data); log_printf (" input_get_unknown_cmd . : %d", ptr_buffer->input_get_unknown_commands); + log_printf (" input_get_empty . . . . : %d", ptr_buffer->input_get_empty); log_printf (" input_buffer. . . . . . : '%s'", ptr_buffer->input_buffer); log_printf (" input_buffer_alloc. . . : %d", ptr_buffer->input_buffer_alloc); log_printf (" input_buffer_size . . . : %d", ptr_buffer->input_buffer_size); diff --git a/src/gui/gui-buffer.h b/src/gui/gui-buffer.h index 1f009a88a..fa9eb761c 100644 --- a/src/gui/gui-buffer.h +++ b/src/gui/gui-buffer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_BUFFER_H -#define WEECHAT_GUI_BUFFER_H 1 +#define WEECHAT_GUI_BUFFER_H #include <limits.h> #include <regex.h> @@ -154,6 +154,8 @@ struct t_gui_buffer /* to this buffer */ int input_get_unknown_commands; /* 1 if unknown commands are sent to */ /* input_callback */ + int input_get_empty; /* 1 if empty input is sent to */ + /* input_callback */ char *input_buffer; /* input buffer */ int input_buffer_alloc; /* input buffer: allocated size */ int input_buffer_size; /* buffer size in bytes */ @@ -233,6 +235,7 @@ extern int gui_buffers_visited_index; extern int gui_buffers_visited_count; extern int gui_buffers_visited_frozen; extern struct t_gui_buffer *gui_buffer_last_displayed; +extern char *gui_buffer_reserved_names[]; extern char *gui_buffer_notify_string[]; extern char *gui_buffer_properties_get_integer[]; extern char *gui_buffer_properties_get_string[]; @@ -246,6 +249,7 @@ extern const char *gui_buffer_get_short_name (struct t_gui_buffer *buffer); extern void gui_buffer_build_full_name (struct t_gui_buffer *buffer); extern void gui_buffer_notify_set_all (); extern void gui_buffer_input_buffer_init (struct t_gui_buffer *buffer); +extern int gui_buffer_is_reserved_name (const char *name); extern struct t_gui_buffer *gui_buffer_new (struct t_weechat_plugin *plugin, const char *name, int (*input_callback)(const void *pointer, @@ -259,6 +263,8 @@ extern struct t_gui_buffer *gui_buffer_new (struct t_weechat_plugin *plugin, struct t_gui_buffer *buffer), const void *close_callback_pointer, void *close_callback_data); +extern struct t_gui_buffer *gui_buffer_new_user (const char *name); +extern void gui_buffer_user_set_callbacks (); extern int gui_buffer_valid (struct t_gui_buffer *buffer); extern char *gui_buffer_string_replace_local_var (struct t_gui_buffer *buffer, const char *string); diff --git a/src/gui/gui-chat.c b/src/gui/gui-chat.c index 5fc018dba..9af2d2371 100644 --- a/src/gui/gui-chat.c +++ b/src/gui/gui-chat.c @@ -1,7 +1,7 @@ /* * gui-chat.c - chat functions (used by all GUI) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -116,9 +116,9 @@ gui_chat_prefix_build () ptr_prefix = CONFIG_STRING(config_look_prefix[i]); pos_color = strstr (ptr_prefix, "${"); - snprintf(prefix, sizeof (prefix), "%s%s\t", - (ptr_prefix[0] && (!pos_color || (pos_color > ptr_prefix))) ? GUI_COLOR(prefix_color[i]) : "", - ptr_prefix); + snprintf (prefix, sizeof (prefix), "%s%s\t", + (ptr_prefix[0] && (!pos_color || (pos_color > ptr_prefix))) ? GUI_COLOR(prefix_color[i]) : "", + ptr_prefix); if (pos_color) gui_chat_prefix[i] = eval_expression (prefix, NULL, NULL, NULL); @@ -1016,9 +1016,10 @@ gui_chat_hsignal_quote_line_cb (const void *pointer, void *data, local_time = localtime (&line_date); if (local_time) { - strftime (str_time, sizeof (str_time), - CONFIG_STRING(config_look_quote_time_format), - local_time); + if (strftime (str_time, sizeof (str_time), + CONFIG_STRING(config_look_quote_time_format), + local_time) == 0) + str_time[0] = '\0'; } } } diff --git a/src/gui/gui-chat.h b/src/gui/gui-chat.h index e1a6d1840..135a79bb6 100644 --- a/src/gui/gui-chat.h +++ b/src/gui/gui-chat.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,8 +18,9 @@ */ #ifndef WEECHAT_GUI_CHAT_H -#define WEECHAT_GUI_CHAT_H 1 +#define WEECHAT_GUI_CHAT_H +#include <stdio.h> #include <time.h> struct t_hashtable; diff --git a/src/gui/gui-color.c b/src/gui/gui-color.c index fcfb2a9bd..b20d704f4 100644 --- a/src/gui/gui-color.c +++ b/src/gui/gui-color.c @@ -1,7 +1,7 @@ /* * gui-color.c - color functions (used by all GUI) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/gui/gui-color.h b/src/gui/gui-color.h index 8ffd87257..68f3f03f4 100644 --- a/src/gui/gui-color.h +++ b/src/gui/gui-color.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_COLOR_H -#define WEECHAT_GUI_COLOR_H 1 +#define WEECHAT_GUI_COLOR_H #include <regex.h> diff --git a/src/gui/gui-completion.c b/src/gui/gui-completion.c index 10d099866..99248f70d 100644 --- a/src/gui/gui-completion.c +++ b/src/gui/gui-completion.c @@ -1,7 +1,7 @@ /* * gui-completion.c - word completion according to context (used by all GUI) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -36,6 +36,7 @@ #include "../core/wee-arraylist.h" #include "../core/wee-completion.h" #include "../core/wee-config.h" +#include "../core/wee-hashtable.h" #include "../core/wee-hdata.h" #include "../core/wee-hook.h" #include "../core/wee-list.h" @@ -114,6 +115,7 @@ gui_completion_buffer_init (struct t_gui_completion *completion, completion->direction = 0; completion->add_space = 1; completion->force_partial_completion = 0; + completion->reverse_partial_completion = 0; completion->list = arraylist_new ( 32, 1, 0, @@ -509,6 +511,12 @@ gui_completion_build_list_template (struct t_gui_completion *completion, pos_end - pos); if (custom_completion) { + if (hashtable_has_key ( + config_hashtable_completion_partial_templates, + custom_completion)) + { + completion->reverse_partial_completion = 1; + } gui_completion_custom (completion, custom_completion, plugin); @@ -1073,6 +1081,9 @@ gui_completion_complete (struct t_gui_completion *completion) partial_completion = CONFIG_BOOLEAN(config_completion_partial_completion_other); } + if (completion->reverse_partial_completion) + partial_completion ^= 1; + common_prefix_size = 0; if (partial_completion && completion->list && (completion->list->size > 0)) @@ -1387,6 +1398,7 @@ gui_completion_hdata_completion_cb (const void *pointer, void *data, HDATA_VAR(struct t_gui_completion, direction, INTEGER, 0, NULL, NULL); HDATA_VAR(struct t_gui_completion, add_space, INTEGER, 0, NULL, NULL); HDATA_VAR(struct t_gui_completion, force_partial_completion, INTEGER, 0, NULL, NULL); + HDATA_VAR(struct t_gui_completion, reverse_partial_completion, INTEGER, 0, NULL, NULL); HDATA_VAR(struct t_gui_completion, list, POINTER, 0, NULL, NULL); HDATA_VAR(struct t_gui_completion, word_found, STRING, 0, NULL, NULL); HDATA_VAR(struct t_gui_completion, word_found_is_nick, INTEGER, 0, NULL, NULL); @@ -1427,23 +1439,24 @@ void gui_completion_print_log (struct t_gui_completion *completion) { log_printf ("[completion (addr:0x%lx)]", completion); - log_printf (" buffer. . . . . . . . . : 0x%lx", completion->buffer); - log_printf (" context . . . . . . . . : %d", completion->context); - log_printf (" base_command. . . . . . : '%s'", completion->base_command); - log_printf (" base_command_arg_index. : %d", completion->base_command_arg_index); - log_printf (" base_word . . . . . . . : '%s'", completion->base_word); - log_printf (" base_word_pos . . . . . : %d", completion->base_word_pos); - log_printf (" position. . . . . . . . : %d", completion->position); - log_printf (" args. . . . . . . . . . : '%s'", completion->args); - log_printf (" direction . . . . . . . : %d", completion->direction); - log_printf (" add_space . . . . . . . : %d", completion->add_space); - log_printf (" force_partial_completion: %d", completion->force_partial_completion); - log_printf (" list. . . . . . . . . . : 0x%lx", completion->list); - log_printf (" word_found. . . . . . . : '%s'", completion->word_found); - log_printf (" word_found_is_nick. . . : %d", completion->word_found_is_nick); - log_printf (" position_replace. . . . : %d", completion->position_replace); - log_printf (" diff_size . . . . . . . : %d", completion->diff_size); - log_printf (" diff_length . . . . . . : %d", completion->diff_length); + log_printf (" buffer. . . . . . . . . . : 0x%lx", completion->buffer); + log_printf (" context . . . . . . . . . : %d", completion->context); + log_printf (" base_command. . . . . . . : '%s'", completion->base_command); + log_printf (" base_command_arg_index. . : %d", completion->base_command_arg_index); + log_printf (" base_word . . . . . . . . : '%s'", completion->base_word); + log_printf (" base_word_pos . . . . . . : %d", completion->base_word_pos); + log_printf (" position. . . . . . . . . : %d", completion->position); + log_printf (" args. . . . . . . . . . . : '%s'", completion->args); + log_printf (" direction . . . . . . . . : %d", completion->direction); + log_printf (" add_space . . . . . . . . : %d", completion->add_space); + log_printf (" force_partial_completion. : %d", completion->force_partial_completion); + log_printf (" reverse_partial_completion: %d", completion->reverse_partial_completion); + log_printf (" list. . . . . . . . . . . : 0x%lx", completion->list); + log_printf (" word_found. . . . . . . . : '%s'", completion->word_found); + log_printf (" word_found_is_nick. . . . : %d", completion->word_found_is_nick); + log_printf (" position_replace. . . . . : %d", completion->position_replace); + log_printf (" diff_size . . . . . . . . : %d", completion->diff_size); + log_printf (" diff_length . . . . . . . : %d", completion->diff_length); if (completion->list) { log_printf (""); diff --git a/src/gui/gui-completion.h b/src/gui/gui-completion.h index 43b49be75..b6aa36cdc 100644 --- a/src/gui/gui-completion.h +++ b/src/gui/gui-completion.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_COMPLETION_H -#define WEECHAT_GUI_COMPLETION_H 1 +#define WEECHAT_GUI_COMPLETION_H #define GUI_COMPLETION_NULL 0 #define GUI_COMPLETION_COMMAND 1 @@ -46,7 +46,8 @@ struct t_gui_completion char *args; /* command line args (including base word) */ int direction; /* +1=search next word, -1=previous word */ int add_space; /* add space after completion? */ - int force_partial_completion; /* force partial completion? */ + int force_partial_completion; /* force partial completion? */ + int reverse_partial_completion; /* reverse partial completion? */ /* for command argument completion */ struct t_arraylist *list; /* data list for completion */ diff --git a/src/gui/gui-cursor.c b/src/gui/gui-cursor.c index 52d3d079e..5b5cf8b85 100644 --- a/src/gui/gui-cursor.c +++ b/src/gui/gui-cursor.c @@ -1,7 +1,7 @@ /* * gui-cursor.c - functions for free movement of cursor (used by all GUI) * - * Copyright (C) 2011-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2011-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/gui/gui-cursor.h b/src/gui/gui-cursor.h index 2b52ebbb3..3159d8b14 100644 --- a/src/gui/gui-cursor.h +++ b/src/gui/gui-cursor.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2011-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_CURSOR_H -#define WEECHAT_GUI_CURSOR_H 1 +#define WEECHAT_GUI_CURSOR_H /* cursor variables */ diff --git a/src/gui/gui-filter.c b/src/gui/gui-filter.c index 15338b022..ed2de8259 100644 --- a/src/gui/gui-filter.c +++ b/src/gui/gui-filter.c @@ -1,7 +1,7 @@ /* * gui-filter.c - filter functions (used by all GUI) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/gui/gui-filter.h b/src/gui/gui-filter.h index 04d9751fb..16df5d8b8 100644 --- a/src/gui/gui-filter.h +++ b/src/gui/gui-filter.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_FILTER_H -#define WEECHAT_GUI_FILTER_H 1 +#define WEECHAT_GUI_FILTER_H #include <regex.h> diff --git a/src/gui/gui-focus.c b/src/gui/gui-focus.c index 7a14d63e6..9e622bc1b 100644 --- a/src/gui/gui-focus.c +++ b/src/gui/gui-focus.c @@ -1,7 +1,7 @@ /* * gui-focus.c - functions about focus (cursor mode and mouse) (used by all GUI) * - * Copyright (C) 2011-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2011-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -39,26 +39,26 @@ #include "gui-window.h" -#define FOCUS_STR(__name, __string) \ +#define FOCUS_STR(__name, __string) \ hashtable_set (hashtable, __name, __string); -#define FOCUS_STR_VAR(__name, __var) \ +#define FOCUS_STR_VAR(__name, __var) \ hashtable_set (hashtable, __name, (__var) ? __var : ""); -#define FOCUS_INT(__name, __int) \ - snprintf (str_value, sizeof (str_value), "%d", __int); \ +#define FOCUS_INT(__name, __int) \ + snprintf (str_value, sizeof (str_value), "%d", __int); \ hashtable_set (hashtable, __name, str_value); -#define FOCUS_TIME(__name, __time) \ - snprintf (str_value, sizeof (str_value), "%ld", (long)__time); \ +#define FOCUS_TIME(__name, __time) \ + snprintf (str_value, sizeof (str_value), "%lld", (long long)__time); \ hashtable_set (hashtable, __name, str_value); -#define FOCUS_PTR(__name, __pointer) \ - if (__pointer) \ - { \ - snprintf (str_value, sizeof (str_value), \ - "0x%lx", (long unsigned int)__pointer); \ - hashtable_set (hashtable, __name, str_value); \ - } \ - else \ - { \ - hashtable_set (hashtable, __name, ""); \ +#define FOCUS_PTR(__name, __pointer) \ + if (__pointer) \ + { \ + snprintf (str_value, sizeof (str_value), \ + "0x%lx", (long unsigned int)__pointer); \ + hashtable_set (hashtable, __name, str_value); \ + } \ + else \ + { \ + hashtable_set (hashtable, __name, ""); \ } diff --git a/src/gui/gui-focus.h b/src/gui/gui-focus.h index 93bd2b730..f8142105b 100644 --- a/src/gui/gui-focus.h +++ b/src/gui/gui-focus.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2011-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_FOCUS_H -#define WEECHAT_GUI_FOCUS_H 1 +#define WEECHAT_GUI_FOCUS_H /* focus structures */ diff --git a/src/gui/gui-history.c b/src/gui/gui-history.c index 2eaaf68d8..d205fd0d5 100644 --- a/src/gui/gui-history.c +++ b/src/gui/gui-history.c @@ -1,7 +1,7 @@ /* * gui-history.c - memorize commands or text for buffers (used by all GUI) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. diff --git a/src/gui/gui-history.h b/src/gui/gui-history.h index ba3a5d9b7..115c045af 100644 --- a/src/gui/gui-history.h +++ b/src/gui/gui-history.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_HISTORY_H -#define WEECHAT_GUI_HISTORY_H 1 +#define WEECHAT_GUI_HISTORY_H struct t_gui_buffer; diff --git a/src/gui/gui-hotlist.c b/src/gui/gui-hotlist.c index 86f118d35..fc49ffbdb 100644 --- a/src/gui/gui-hotlist.c +++ b/src/gui/gui-hotlist.c @@ -1,7 +1,7 @@ /* * gui-hotlist.c - hotlist management (used by all GUI) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/gui/gui-hotlist.h b/src/gui/gui-hotlist.h index 56138292f..8660abdb6 100644 --- a/src/gui/gui-hotlist.h +++ b/src/gui/gui-hotlist.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_HOTLIST_H -#define WEECHAT_GUI_HOTLIST_H 1 +#define WEECHAT_GUI_HOTLIST_H enum t_gui_hotlist_priority { diff --git a/src/gui/gui-input.c b/src/gui/gui-input.c index 2c284677d..c9d7d695d 100644 --- a/src/gui/gui-input.c +++ b/src/gui/gui-input.c @@ -1,7 +1,7 @@ /* * gui-input.c - input functions (used by all GUI) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -364,7 +364,7 @@ gui_input_clipboard_copy (const char *buffer, int size) if (gui_input_clipboard != NULL) free (gui_input_clipboard); - gui_input_clipboard = malloc((size + 1) * sizeof(*gui_input_clipboard)); + gui_input_clipboard = malloc ((size + 1) * sizeof (*gui_input_clipboard)); if (gui_input_clipboard) { @@ -412,7 +412,8 @@ gui_input_return (struct t_gui_buffer *buffer) gui_window_bare_display_toggle (NULL); } - if (buffer->input && (buffer->input_buffer_size > 0)) + if (buffer->input + && (buffer->input_get_empty || (buffer->input_buffer_size > 0))) { buffer->input_buffer[buffer->input_buffer_size] = '\0'; command = strdup (buffer->input_buffer); diff --git a/src/gui/gui-input.h b/src/gui/gui-input.h index a1e903bc5..db172bf0b 100644 --- a/src/gui/gui-input.h +++ b/src/gui/gui-input.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_INPUT_H -#define WEECHAT_GUI_INPUT_H 1 +#define WEECHAT_GUI_INPUT_H struct t_gui_buffer; diff --git a/src/gui/gui-key.c b/src/gui/gui-key.c index 4fbd2db21..021376c41 100644 --- a/src/gui/gui-key.c +++ b/src/gui/gui-key.c @@ -1,7 +1,7 @@ /* * gui-key.c - keyboard functions (used by all GUI) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -927,6 +927,15 @@ gui_key_unbind_plugin (const char *context, const char *key) if (ctxt < 0) return 0; + if (strncmp (key, "quiet:", 6) == 0) + { + key += 6; + } + else + { + gui_key_verbose = 1; + } + if (strncmp (key, "area:", 5) == 0) { num_keys = 0; @@ -944,9 +953,7 @@ gui_key_unbind_plugin (const char *context, const char *key) && ptr_key->area_name[1] && (strcmp (ptr_key->area_name[1], area_name) == 0))) { - gui_key_verbose = 1; num_keys += gui_key_unbind (NULL, ctxt, ptr_key->key); - gui_key_verbose = 0; } } free (area_name); @@ -954,11 +961,11 @@ gui_key_unbind_plugin (const char *context, const char *key) } else { - gui_key_verbose = 1; num_keys = gui_key_unbind (NULL, ctxt, key); - gui_key_verbose = 0; } + gui_key_verbose = 0; + return num_keys; } @@ -1913,22 +1920,22 @@ gui_key_hdata_key_cb (const void *pointer, void *data, "gui_keys%s%s", (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : "_", (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : gui_key_context_string[i]); - hdata_new_list(hdata, str_list, &gui_keys[i], 0); + hdata_new_list (hdata, str_list, &gui_keys[i], 0); snprintf (str_list, sizeof (str_list), "last_gui_key%s%s", (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : "_", (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : gui_key_context_string[i]); - hdata_new_list(hdata, str_list, &last_gui_key[i], 0); + hdata_new_list (hdata, str_list, &last_gui_key[i], 0); snprintf (str_list, sizeof (str_list), "gui_default_keys%s%s", (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : "_", (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : gui_key_context_string[i]); - hdata_new_list(hdata, str_list, &gui_default_keys[i], 0); + hdata_new_list (hdata, str_list, &gui_default_keys[i], 0); snprintf (str_list, sizeof (str_list), "last_gui_default_key%s%s", (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : "_", (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : gui_key_context_string[i]); - hdata_new_list(hdata, str_list, &last_gui_default_key[i], 0); + hdata_new_list (hdata, str_list, &last_gui_default_key[i], 0); } } return hdata; diff --git a/src/gui/gui-key.h b/src/gui/gui-key.h index 8da66b58f..97570a491 100644 --- a/src/gui/gui-key.h +++ b/src/gui/gui-key.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_KEY_H -#define WEECHAT_GUI_KEY_H 1 +#define WEECHAT_GUI_KEY_H #include <time.h> diff --git a/src/gui/gui-layout.c b/src/gui/gui-layout.c index 2a0128f55..4b2febe9d 100644 --- a/src/gui/gui-layout.c +++ b/src/gui/gui-layout.c @@ -1,7 +1,7 @@ /* * gui-layout.c - layout functions (used by all GUI) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/gui/gui-layout.h b/src/gui/gui-layout.h index 77683e7bc..37a454ec7 100644 --- a/src/gui/gui-layout.h +++ b/src/gui/gui-layout.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_LAYOUT_H -#define WEECHAT_GUI_LAYOUT_H 1 +#define WEECHAT_GUI_LAYOUT_H #define GUI_LAYOUT_DEFAULT_NAME "default" diff --git a/src/gui/gui-line.c b/src/gui/gui-line.c index c34a7a970..7b4894c29 100644 --- a/src/gui/gui-line.c +++ b/src/gui/gui-line.c @@ -1,7 +1,7 @@ /* * gui-line.c - line functions (used by all GUI) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -945,17 +945,24 @@ gui_line_add_to_list (struct t_gui_lines *lines, line->next_line = NULL; lines->last_line = line; - /* adjust "prefix_max_length" if this prefix length is > max */ - gui_line_get_prefix_for_display (line, NULL, &prefix_length, NULL, - &prefix_is_nick); - if (prefix_is_nick) - prefix_length += config_length_nick_prefix_suffix; - if (prefix_length > lines->prefix_max_length) - lines->prefix_max_length = prefix_length; - - /* adjust "lines_hidden" if the line is hidden */ - if (!line->data->displayed) + /* + * adjust "prefix_max_length" if this prefix length is > max + * (only if the line is displayed + */ + if (line->data->displayed) + { + gui_line_get_prefix_for_display (line, NULL, &prefix_length, NULL, + &prefix_is_nick); + if (prefix_is_nick) + prefix_length += config_length_nick_prefix_suffix; + if (prefix_length > lines->prefix_max_length) + lines->prefix_max_length = prefix_length; + } + else + { + /* adjust "lines_hidden" if the line is hidden */ (lines->lines_hidden)++; + } lines->lines_count++; } diff --git a/src/gui/gui-line.h b/src/gui/gui-line.h index d36236370..a57d59ae3 100644 --- a/src/gui/gui-line.h +++ b/src/gui/gui-line.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_LINE_H -#define WEECHAT_GUI_LINE_H 1 +#define WEECHAT_GUI_LINE_H #include <time.h> #include <regex.h> diff --git a/src/gui/gui-main.h b/src/gui/gui-main.h index 37191129a..b9b815cc5 100644 --- a/src/gui/gui-main.h +++ b/src/gui/gui-main.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_MAIN_H -#define WEECHAT_GUI_MAIN_H 1 +#define WEECHAT_GUI_MAIN_H /* main functions (GUI dependent) */ diff --git a/src/gui/gui-mouse.c b/src/gui/gui-mouse.c index 5e78c3068..a47b39d45 100644 --- a/src/gui/gui-mouse.c +++ b/src/gui/gui-mouse.c @@ -1,7 +1,7 @@ /* * gui-mouse.c - functions for mouse (used by all GUI) * - * Copyright (C) 2011-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2011-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/gui/gui-mouse.h b/src/gui/gui-mouse.h index 55daf6533..8c34e0a0b 100644 --- a/src/gui/gui-mouse.h +++ b/src/gui/gui-mouse.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2011-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_MOUSE_H -#define WEECHAT_GUI_MOUSE_H 1 +#define WEECHAT_GUI_MOUSE_H /* mouse variables */ diff --git a/src/gui/gui-nick.c b/src/gui/gui-nick.c index 595d1d860..5f7c57072 100644 --- a/src/gui/gui-nick.c +++ b/src/gui/gui-nick.c @@ -1,7 +1,7 @@ /* * gui-nick.c - nick functions (used by all GUI) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/gui/gui-nick.h b/src/gui/gui-nick.h index 5ac715700..98a1d3d10 100644 --- a/src/gui/gui-nick.h +++ b/src/gui/gui-nick.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_NICK_H -#define WEECHAT_GUI_NICK_H 1 +#define WEECHAT_GUI_NICK_H extern const char *gui_nick_find_color (const char *nickname); extern const char *gui_nick_find_color_name (const char *nickname); diff --git a/src/gui/gui-nicklist.c b/src/gui/gui-nicklist.c index de067455b..f8c35a3a9 100644 --- a/src/gui/gui-nicklist.c +++ b/src/gui/gui-nicklist.c @@ -1,7 +1,7 @@ /* * gui-nicklist.c - nicklist functions (used by all GUI) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -219,7 +219,7 @@ gui_nicklist_search_group_internal (struct t_gui_buffer *buffer, while (ptr_group) { ptr_name = (skip_digits) ? - gui_nicklist_get_group_start(ptr_group->name) : ptr_group->name; + gui_nicklist_get_group_start (ptr_group->name) : ptr_group->name; if (strcmp (ptr_name, name) == 0) return ptr_group; ptr_group = ptr_group->next_group; @@ -680,6 +680,13 @@ gui_nicklist_get_next_item (struct t_gui_buffer *buffer, /* find next group by parents */ while ((ptr_group = ptr_group->parent)) { + if (ptr_group->nicks) + { + *group = ptr_group; + *nick = ptr_group->nicks; + return; + } + if (ptr_group->next_group) { *group = ptr_group->next_group; diff --git a/src/gui/gui-nicklist.h b/src/gui/gui-nicklist.h index 6cc9f8d41..d0179c886 100644 --- a/src/gui/gui-nicklist.h +++ b/src/gui/gui-nicklist.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_NICKLIST_H -#define WEECHAT_GUI_NICKLIST_H 1 +#define WEECHAT_GUI_NICKLIST_H struct t_gui_buffer; struct t_infolist; diff --git a/src/gui/gui-window.c b/src/gui/gui-window.c index 722dce13e..eb380e489 100644 --- a/src/gui/gui-window.c +++ b/src/gui/gui-window.c @@ -1,7 +1,7 @@ /* * gui-window.c - window functions (used by all GUI) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/gui/gui-window.h b/src/gui/gui-window.h index 61b872ff8..58b1f5434 100644 --- a/src/gui/gui-window.h +++ b/src/gui/gui-window.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,7 +18,7 @@ */ #ifndef WEECHAT_GUI_WINDOW_H -#define WEECHAT_GUI_WINDOW_H 1 +#define WEECHAT_GUI_WINDOW_H struct t_infolist; struct t_gui_bar_window; diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index cbb0fd58a..e4e06e262 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # Copyright (C) 2009 Emmanuel Bouthenot <kolter@openics.org> # # This file is part of WeeChat, the extensible chat client. @@ -19,14 +19,17 @@ # set(LIB_PLUGINS_SRC -weechat-plugin.h -plugin.c plugin.h -plugin-api.c plugin-api.h -plugin-config.h plugin-config.c) + weechat-plugin.h + plugin.c plugin.h + plugin-api.c plugin-api.h + plugin-config.h plugin-config.c +) set(LIB_PLUGINS_SCRIPTS_SRC -plugin-script.c plugin-script.h -plugin-script-api.c plugin-script-api.h) + plugin-script.c plugin-script.h + plugin-script-api.c plugin-script-api.h + plugin-script-config.c plugin-script-config.h +) include_directories(${CMAKE_BINARY_DIR}) add_library(weechat_plugins STATIC ${LIB_PLUGINS_SRC}) @@ -86,6 +89,10 @@ if(ENABLE_FIFO) add_subdirectory(fifo) endif() +if(ENABLE_FSET) + add_subdirectory(fset) +endif() + if(ENABLE_IRC) add_subdirectory(irc) endif() @@ -151,6 +158,13 @@ if(ENABLE_SCRIPTS AND ENABLE_JAVASCRIPT) endif() endif() +if(ENABLE_SCRIPTS AND ENABLE_PHP) + find_package(PHP) + if(PHP_FOUND) + add_subdirectory(php) + endif() +endif() + if(ENABLE_TRIGGER) add_subdirectory(trigger) endif() diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index 3c959b74e..3d813ba66 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # Copyright (C) 2006-2009 Emmanuel Bouthenot <kolter@openics.org> # # This file is part of WeeChat, the extensible chat client. @@ -35,7 +35,9 @@ noinst_LTLIBRARIES = lib_weechat_plugins_scripts.la lib_weechat_plugins_scripts_la_SOURCES = plugin-script.c \ plugin-script.h \ plugin-script-api.c \ - plugin-script-api.h + plugin-script-api.h \ + plugin-script-config.c \ + plugin-script-config.h if PLUGIN_ALIAS alias_dir = alias @@ -61,6 +63,10 @@ if PLUGIN_FIFO fifo_dir = fifo endif +if PLUGIN_FSET +fset_dir = fset +endif + if PLUGIN_IRC irc_dir = irc endif @@ -105,6 +111,10 @@ if PLUGIN_JAVASCRIPT javascript_dir = javascript endif +if PLUGIN_PHP +php_dir = php +endif + if PLUGIN_TRIGGER trigger_dir = trigger endif @@ -120,6 +130,7 @@ SUBDIRS = . \ $(charset_dir) \ $(exec_dir) \ $(fifo_dir) \ + $(fset_dir) \ $(irc_dir) \ $(logger_dir) \ $(relay_dir) \ @@ -131,6 +142,7 @@ SUBDIRS = . \ $(tcl_dir) \ $(guile_dir) \ $(javascript_dir) \ + $(php_dir) \ $(trigger_dir) \ $(xfer_dir) diff --git a/src/plugins/alias/CMakeLists.txt b/src/plugins/alias/CMakeLists.txt index 931772f8e..f6c5df1df 100644 --- a/src/plugins/alias/CMakeLists.txt +++ b/src/plugins/alias/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/alias/Makefile.am b/src/plugins/alias/Makefile.am index e929b17c2..3bbdf2adc 100644 --- a/src/plugins/alias/Makefile.am +++ b/src/plugins/alias/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/alias/alias-command.c b/src/plugins/alias/alias-command.c index 9c1b2326b..eea0603d1 100644 --- a/src/plugins/alias/alias-command.c +++ b/src/plugins/alias/alias-command.c @@ -1,7 +1,7 @@ /* * alias-command.c - alias commands * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/alias/alias-command.h b/src/plugins/alias/alias-command.h index d4774dd93..df916b33b 100644 --- a/src/plugins/alias/alias-command.h +++ b/src/plugins/alias/alias-command.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2013-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_ALIAS_COMMAND_H -#define WEECHAT_ALIAS_COMMAND_H 1 +#ifndef WEECHAT_PLUGIN_ALIAS_COMMAND_H +#define WEECHAT_PLUGIN_ALIAS_COMMAND_H extern void alias_command_init (); -#endif /* WEECHAT_ALIAS_COMMAND_H */ +#endif /* WEECHAT_PLUGIN_ALIAS_COMMAND_H */ diff --git a/src/plugins/alias/alias-completion.c b/src/plugins/alias/alias-completion.c index b4e6a9ce0..ba7cfde84 100644 --- a/src/plugins/alias/alias-completion.c +++ b/src/plugins/alias/alias-completion.c @@ -1,7 +1,7 @@ /* * alias-completion.c - completion for alias commands * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/alias/alias-completion.h b/src/plugins/alias/alias-completion.h index 02b0987d8..ca8ec5175 100644 --- a/src/plugins/alias/alias-completion.h +++ b/src/plugins/alias/alias-completion.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2013-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_ALIAS_COMPLETION_H -#define WEECHAT_ALIAS_COMPLETION_H 1 +#ifndef WEECHAT_PLUGIN_ALIAS_COMPLETION_H +#define WEECHAT_PLUGIN_ALIAS_COMPLETION_H extern void alias_completion_init (); -#endif /* WEECHAT_ALIAS_COMPLETION_H */ +#endif /* WEECHAT_PLUGIN_ALIAS_COMPLETION_H */ diff --git a/src/plugins/alias/alias-config.c b/src/plugins/alias/alias-config.c index b0f963d23..479ac743e 100644 --- a/src/plugins/alias/alias-config.c +++ b/src/plugins/alias/alias-config.c @@ -1,7 +1,7 @@ /* * alias-config.c - alias configuration options (file alias.conf) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -31,46 +31,42 @@ struct t_config_file *alias_config_file = NULL; struct t_config_section *alias_config_section_cmd = NULL; struct t_config_section *alias_config_section_completion = NULL; -char *alias_default_cmd[][2] = -{ { "AAWAY", "allserv /away" }, - { "AME", "allchan /me" }, - { "AMSG", "allchan /msg *" }, - { "ANICK", "allserv /nick" }, - { "BEEP", "print -beep" }, - { "BYE", "quit" }, - { "C", "buffer clear" }, - { "CL", "buffer clear" }, - { "CLOSE", "buffer close" }, - { "CHAT", "dcc chat" }, - { "EXIT", "quit" }, - { "IG", "ignore" }, - { "J", "join" }, - { "K", "kick" }, - { "KB", "kickban" }, - { "LEAVE", "part" }, - { "M", "msg" }, - { "MUB", "unban *" }, - { "MSGBUF", "command -buffer $1 * /input send $2-" }, - { "N", "names" }, - { "Q", "query" }, - { "REDRAW", "window refresh" }, - { "SAY", "msg *" }, - { "SIGNOFF", "quit" }, - { "T", "topic" }, - { "UB", "unban" }, - { "UMODE", "mode $nick" }, - { "V", "command core version" }, - { "W", "who" }, - { "WC", "window merge" }, - { "WI", "whois" }, - { "WII", "whois $1 $1" }, - { "WW", "whowas" }, - { NULL, NULL }, -}; - -char *alias_default_completion[][2] = -{ { "MSGBUF", "%(buffers_plugins_names)" }, - { NULL, NULL }, +char *alias_default[][3] = +{ { "AAWAY", "allserv /away", NULL }, + { "AME", "allchan /me", NULL }, + { "AMSG", "allchan /msg *", NULL }, + { "ANICK", "allserv /nick", NULL }, + { "BEEP", "print -beep", NULL }, + { "BYE", "quit", NULL }, + { "C", "buffer clear", NULL }, + { "CL", "buffer clear", NULL }, + { "CLOSE", "buffer close", NULL }, + { "CHAT", "dcc chat", NULL }, + { "EXIT", "quit", NULL }, + { "IG", "ignore", NULL }, + { "J", "join", NULL }, + { "K", "kick", NULL }, + { "KB", "kickban", NULL }, + { "LEAVE", "part", NULL }, + { "M", "msg", NULL }, + { "MUB", "unban *", NULL }, + { "MSGBUF", "command -buffer $1 * /input send $2-", + "%(buffers_plugins_names)" }, + { "N", "names", NULL }, + { "Q", "query", NULL }, + { "REDRAW", "window refresh", NULL }, + { "SAY", "msg *", NULL }, + { "SIGNOFF", "quit", NULL }, + { "T", "topic", NULL }, + { "UB", "unban", NULL }, + { "UMODE", "mode $nick", NULL }, + { "V", "command core version", NULL }, + { "W", "who", NULL }, + { "WC", "window merge", NULL }, + { "WI", "whois", NULL }, + { "WII", "whois $1 $1", NULL }, + { "WW", "whowas", NULL }, + { NULL, NULL, NULL }, }; /* @@ -204,11 +200,11 @@ alias_config_cmd_write_default_cb (const void *pointer, void *data, if (!weechat_config_write_line (config_file, section_name, NULL)) return WEECHAT_CONFIG_WRITE_ERROR; - for (i = 0; alias_default_cmd[i][0]; i++) + for (i = 0; alias_default[i][0]; i++) { if (!weechat_config_write_line (config_file, - alias_default_cmd[i][0], - "\"%s\"", alias_default_cmd[i][1])) + alias_default[i][0], + "\"%s\"", alias_default[i][1])) return WEECHAT_CONFIG_WRITE_ERROR; } @@ -291,12 +287,15 @@ alias_config_completion_write_default_cb (const void *pointer, void *data, if (!weechat_config_write_line (config_file, section_name, NULL)) return WEECHAT_CONFIG_WRITE_ERROR; - for (i = 0; alias_default_completion[i][0]; i++) + for (i = 0; alias_default[i][0]; i++) { - if (!weechat_config_write_line (config_file, - alias_default_completion[i][0], - "\"%s\"", alias_default_completion[i][1])) - return WEECHAT_CONFIG_WRITE_ERROR; + if (alias_default[i][2]) + { + if (!weechat_config_write_line (config_file, + alias_default[i][0], + "\"%s\"", alias_default[i][2])) + return WEECHAT_CONFIG_WRITE_ERROR; + } } return WEECHAT_CONFIG_WRITE_OK; @@ -387,6 +386,7 @@ alias_config_init () if (!ptr_section) { weechat_config_free (alias_config_file); + alias_config_file = NULL; return 0; } alias_config_section_cmd = ptr_section; @@ -403,6 +403,7 @@ alias_config_init () if (!ptr_section) { weechat_config_free (alias_config_file); + alias_config_file = NULL; return 0; } alias_config_section_completion = ptr_section; diff --git a/src/plugins/alias/alias-config.h b/src/plugins/alias/alias-config.h index 6dba8b594..e7f66efea 100644 --- a/src/plugins/alias/alias-config.h +++ b/src/plugins/alias/alias-config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,13 +17,15 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_ALIAS_CONFIG_H -#define WEECHAT_ALIAS_CONFIG_H 1 +#ifndef WEECHAT_PLUGIN_ALIAS_CONFIG_H +#define WEECHAT_PLUGIN_ALIAS_CONFIG_H extern struct t_config_file *alias_config_file; extern struct t_config_section *alias_config_section_cmd; extern struct t_config_section *alias_config_section_completion; +extern char *alias_default[][3]; + extern void alias_config_cmd_new_option (const char *name, const char *command); extern void alias_config_completion_new_option (const char *name, @@ -32,4 +34,4 @@ extern int alias_config_init (); extern int alias_config_read (); extern int alias_config_write (); -#endif /* WEECHAT_ALIAS_CONFIG_H */ +#endif /* WEECHAT_PLUGIN_ALIAS_CONFIG_H */ diff --git a/src/plugins/alias/alias-info.c b/src/plugins/alias/alias-info.c index 45b7a52dc..e95806713 100644 --- a/src/plugins/alias/alias-info.c +++ b/src/plugins/alias/alias-info.c @@ -1,7 +1,7 @@ /* * alias-info.c - info and infolist hooks for alias plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -23,10 +23,11 @@ #include "../weechat-plugin.h" #include "alias.h" +#include "alias-config.h" /* - * Returns alias infolist "alias". + * Returns infolist "alias". */ struct t_infolist * @@ -82,6 +83,58 @@ alias_info_infolist_alias_cb (const void *pointer, void *data, } /* + * Returns infolist "alias_default". + */ + +struct t_infolist * +alias_info_infolist_alias_default_cb (const void *pointer, void *data, + const char *infolist_name, + void *obj_pointer, const char *arguments) +{ + struct t_infolist *ptr_infolist; + struct t_infolist_item *ptr_item; + int i; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) infolist_name; + (void) obj_pointer; + (void) arguments; + + ptr_infolist = weechat_infolist_new (); + if (!ptr_infolist) + return NULL; + + for (i = 0; alias_default[i][0]; i++) + { + ptr_item = weechat_infolist_new_item (ptr_infolist); + if (!ptr_item) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + if (!weechat_infolist_new_var_string (ptr_item, "name", alias_default[i][0])) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + if (!weechat_infolist_new_var_string (ptr_item, "command", alias_default[i][1])) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + if (!weechat_infolist_new_var_string (ptr_item, "completion", alias_default[i][2])) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + } + + return ptr_infolist; +} + +/* * Hooks infolist for alias plugin. */ @@ -93,4 +146,8 @@ alias_info_init () N_("alias pointer (optional)"), N_("alias name (wildcard \"*\" is allowed) (optional)"), &alias_info_infolist_alias_cb, NULL, NULL); + weechat_hook_infolist ( + "alias_default", N_("list of default aliases"), + NULL, NULL, + &alias_info_infolist_alias_default_cb, NULL, NULL); } diff --git a/src/plugins/alias/alias-info.h b/src/plugins/alias/alias-info.h index 3fcbc17fa..4c1beee39 100644 --- a/src/plugins/alias/alias-info.h +++ b/src/plugins/alias/alias-info.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_ALIAS_INFO_H -#define WEECHAT_ALIAS_INFO_H 1 +#ifndef WEECHAT_PLUGIN_ALIAS_INFO_H +#define WEECHAT_PLUGIN_ALIAS_INFO_H extern void alias_info_init (); -#endif /* WEECHAT_ALIAS_INFO_H */ +#endif /* WEECHAT_PLUGIN_ALIAS_INFO_H */ diff --git a/src/plugins/alias/alias.c b/src/plugins/alias/alias.c index edd2e226b..c7794e22f 100644 --- a/src/plugins/alias/alias.c +++ b/src/plugins/alias/alias.c @@ -1,7 +1,7 @@ /* * alias.c - alias plugin for WeeChat: command aliases * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -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(9000); +WEECHAT_PLUGIN_PRIORITY(10000); #define ALIAS_IS_ARG_NUMBER(number) ((number >= '1') && (number <= '9')) @@ -312,7 +312,7 @@ alias_run_command (struct t_gui_buffer **buffer, const char *command) struct t_gui_buffer *old_current_buffer, *new_current_buffer; /* save current buffer pointer */ - old_current_buffer = weechat_current_buffer(); + old_current_buffer = weechat_current_buffer (); /* execute command */ string = weechat_buffer_string_replace_local_var (*buffer, command); @@ -322,7 +322,7 @@ alias_run_command (struct t_gui_buffer **buffer, const char *command) free (string); /* get new current buffer */ - new_current_buffer = weechat_current_buffer(); + new_current_buffer = weechat_current_buffer (); /* * if current buffer was changed by command, then we'll use this one for @@ -415,7 +415,7 @@ alias_cb (const void *pointer, void *data, } else { - alias_command = malloc (1 + strlen((args_replaced) ? args_replaced : *ptr_cmd) + 1); + alias_command = malloc (1 + strlen ((args_replaced) ? args_replaced : *ptr_cmd) + 1); if (alias_command) { strcpy (alias_command, "/"); diff --git a/src/plugins/alias/alias.h b/src/plugins/alias/alias.h index cf43c6d7a..01b90f79a 100644 --- a/src/plugins/alias/alias.h +++ b/src/plugins/alias/alias.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_ALIAS_H -#define WEECHAT_ALIAS_H 1 +#ifndef WEECHAT_PLUGIN_ALIAS_H +#define WEECHAT_PLUGIN_ALIAS_H #define weechat_plugin weechat_alias_plugin #define ALIAS_PLUGIN_NAME "alias" @@ -52,4 +52,4 @@ extern void alias_free_all (); extern int alias_add_to_infolist (struct t_infolist *infolist, struct t_alias *alias); -#endif /* WEECHAT_ALIAS_H */ +#endif /* WEECHAT_PLUGIN_ALIAS_H */ diff --git a/src/plugins/aspell/CMakeLists.txt b/src/plugins/aspell/CMakeLists.txt index f6b0f84e0..d15151b32 100644 --- a/src/plugins/aspell/CMakeLists.txt +++ b/src/plugins/aspell/CMakeLists.txt @@ -1,6 +1,6 @@ # # Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> -# Copyright (C) 2006-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2006-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/aspell/Makefile.am b/src/plugins/aspell/Makefile.am index 11b763f32..a446f7f16 100644 --- a/src/plugins/aspell/Makefile.am +++ b/src/plugins/aspell/Makefile.am @@ -1,6 +1,6 @@ # # Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> -# Copyright (C) 2006-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2006-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/aspell/weechat-aspell-bar-item.c b/src/plugins/aspell/weechat-aspell-bar-item.c index e89821a85..cdcb1a612 100644 --- a/src/plugins/aspell/weechat-aspell-bar-item.c +++ b/src/plugins/aspell/weechat-aspell-bar-item.c @@ -2,7 +2,7 @@ * weechat-aspell-bar-item.c - bar items for aspell plugin * * Copyright (C) 2012 Nils Görs <weechatter@arcor.de> - * Copyright (C) 2012-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2012-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/aspell/weechat-aspell-bar-item.h b/src/plugins/aspell/weechat-aspell-bar-item.h index 678bf9732..da8ebf714 100644 --- a/src/plugins/aspell/weechat-aspell-bar-item.h +++ b/src/plugins/aspell/weechat-aspell-bar-item.h @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_ASPELL_BAR_ITEM_H -#define WEECHAT_ASPELL_BAR_ITEM_H 1 +#ifndef WEECHAT_PLUGIN_ASPELL_BAR_ITEM_H +#define WEECHAT_PLUGIN_ASPELL_BAR_ITEM_H extern void weechat_aspell_bar_item_init (); -#endif /* WEECHAT_ASPELL_BAR_ITEM_H */ +#endif /* WEECHAT_PLUGIN_ASPELL_BAR_ITEM_H */ diff --git a/src/plugins/aspell/weechat-aspell-command.c b/src/plugins/aspell/weechat-aspell-command.c index 4ba11742d..6d66eb7d4 100644 --- a/src/plugins/aspell/weechat-aspell-command.c +++ b/src/plugins/aspell/weechat-aspell-command.c @@ -1,7 +1,7 @@ /* * weechat-aspell-command.c - aspell commands * - * Copyright (C) 2013-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2013-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -158,7 +158,7 @@ weechat_aspell_command_speller_list_dicts () enchant_broker_list_dicts (broker, weechat_aspell_enchant_dict_describe_cb, NULL); #else - config = new_aspell_config(); + config = new_aspell_config (); list = get_aspell_dict_info_list (config); elements = aspell_dict_info_list_elements (list); @@ -191,7 +191,9 @@ weechat_aspell_command_speller_list_dicts () } snprintf (str_dict, sizeof (str_dict), "%-22s %s%s", - dict->name, lang, str_country); + dict->name, + (lang) ? lang : "?", + str_country); weechat_printf (NULL, " %s", str_dict); diff --git a/src/plugins/aspell/weechat-aspell-command.h b/src/plugins/aspell/weechat-aspell-command.h index 61e0fe5e4..c2a86286d 100644 --- a/src/plugins/aspell/weechat-aspell-command.h +++ b/src/plugins/aspell/weechat-aspell-command.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2013-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_ASPELL_COMMAND_H -#define WEECHAT_ASPELL_COMMAND_H 1 +#ifndef WEECHAT_PLUGIN_ASPELL_COMMAND_H +#define WEECHAT_PLUGIN_ASPELL_COMMAND_H extern void weechat_aspell_command_init (); -#endif /* WEECHAT_ASPELL_COMMAND_H */ +#endif /* WEECHAT_PLUGIN_ASPELL_COMMAND_H */ diff --git a/src/plugins/aspell/weechat-aspell-completion.c b/src/plugins/aspell/weechat-aspell-completion.c index 12a8f1470..244b794b2 100644 --- a/src/plugins/aspell/weechat-aspell-completion.c +++ b/src/plugins/aspell/weechat-aspell-completion.c @@ -1,7 +1,7 @@ /* * weechat-aspell-completion.c - completion for aspell commands * - * Copyright (C) 2013-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2013-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/aspell/weechat-aspell-completion.h b/src/plugins/aspell/weechat-aspell-completion.h index 067211fda..f7119ab8a 100644 --- a/src/plugins/aspell/weechat-aspell-completion.h +++ b/src/plugins/aspell/weechat-aspell-completion.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2013-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_ASPELL_COMPLETION_H -#define WEECHAT_ASPELL_COMPLETION_H 1 +#ifndef WEECHAT_PLUGIN_ASPELL_COMPLETION_H +#define WEECHAT_PLUGIN_ASPELL_COMPLETION_H extern void weechat_aspell_completion_init (); -#endif /* WEECHAT_ASPELL_COMPLETION_H */ +#endif /* WEECHAT_PLUGIN_ASPELL_COMPLETION_H */ diff --git a/src/plugins/aspell/weechat-aspell-config.c b/src/plugins/aspell/weechat-aspell-config.c index 0d12e9df6..1899bb09b 100644 --- a/src/plugins/aspell/weechat-aspell-config.c +++ b/src/plugins/aspell/weechat-aspell-config.c @@ -2,7 +2,7 @@ * weechat-aspell-config.c - aspell configuration options (file aspell.conf) * * Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> - * Copyright (C) 2006-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2006-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -450,6 +450,7 @@ weechat_aspell_config_init () if (!ptr_section) { weechat_config_free (weechat_aspell_config_file); + weechat_aspell_config_file = NULL; return 0; } @@ -493,6 +494,7 @@ weechat_aspell_config_init () if (!ptr_section) { weechat_config_free (weechat_aspell_config_file); + weechat_aspell_config_file = NULL; return 0; } @@ -568,6 +570,7 @@ weechat_aspell_config_init () if (!ptr_section) { weechat_config_free (weechat_aspell_config_file); + weechat_aspell_config_file = NULL; return 0; } @@ -585,6 +588,7 @@ weechat_aspell_config_init () if (!ptr_section) { weechat_config_free (weechat_aspell_config_file); + weechat_aspell_config_file = NULL; return 0; } @@ -619,6 +623,7 @@ weechat_aspell_config_init () if (!ptr_section) { weechat_config_free (weechat_aspell_config_file); + weechat_aspell_config_file = NULL; return 0; } diff --git a/src/plugins/aspell/weechat-aspell-config.h b/src/plugins/aspell/weechat-aspell-config.h index dc0d42043..f662b52a4 100644 --- a/src/plugins/aspell/weechat-aspell-config.h +++ b/src/plugins/aspell/weechat-aspell-config.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> - * Copyright (C) 2006-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2006-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_ASPELL_CONFIG_H -#define WEECHAT_ASPELL_CONFIG_H 1 +#ifndef WEECHAT_PLUGIN_ASPELL_CONFIG_H +#define WEECHAT_PLUGIN_ASPELL_CONFIG_H #define ASPELL_CONFIG_NAME "aspell" @@ -51,4 +51,4 @@ extern int weechat_aspell_config_read (); extern int weechat_aspell_config_write (); extern void weechat_aspell_config_free (); -#endif /* WEECHAT_ASPELL_CONFIG_H */ +#endif /* WEECHAT_PLUGIN_ASPELL_CONFIG_H */ diff --git a/src/plugins/aspell/weechat-aspell-info.c b/src/plugins/aspell/weechat-aspell-info.c index f8fbf4d07..831971699 100644 --- a/src/plugins/aspell/weechat-aspell-info.c +++ b/src/plugins/aspell/weechat-aspell-info.c @@ -1,7 +1,7 @@ /* * weechat-aspell-info.c - info for aspell plugin * - * Copyright (C) 2013-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2013-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/aspell/weechat-aspell-info.h b/src/plugins/aspell/weechat-aspell-info.h index 6f9155470..c25e766f2 100644 --- a/src/plugins/aspell/weechat-aspell-info.h +++ b/src/plugins/aspell/weechat-aspell-info.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2013-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_ASPELL_INFO_H -#define WEECHAT_ASPELL_INFO_H 1 +#ifndef WEECHAT_PLUGIN_ASPELL_INFO_H +#define WEECHAT_PLUGIN_ASPELL_INFO_H extern void weechat_aspell_info_init (); -#endif /* WEECHAT_ASPELL_INFO_H */ +#endif /* WEECHAT_PLUGIN_ASPELL_INFO_H */ diff --git a/src/plugins/aspell/weechat-aspell-speller.c b/src/plugins/aspell/weechat-aspell-speller.c index 52bde0163..4e9bf099b 100644 --- a/src/plugins/aspell/weechat-aspell-speller.c +++ b/src/plugins/aspell/weechat-aspell-speller.c @@ -2,7 +2,7 @@ * weechat-aspell-speller.c - speller management for aspell plugin * * Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> - * Copyright (C) 2006-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2006-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -161,7 +161,7 @@ weechat_aspell_speller_new (const char *lang) } #else /* create a speller instance for the newly created cell */ - config = new_aspell_config(); + config = new_aspell_config (); aspell_config_replace (config, "lang", lang); #endif /* USE_ENCHANT */ diff --git a/src/plugins/aspell/weechat-aspell-speller.h b/src/plugins/aspell/weechat-aspell-speller.h index 620451a3f..9f33880b0 100644 --- a/src/plugins/aspell/weechat-aspell-speller.h +++ b/src/plugins/aspell/weechat-aspell-speller.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> - * Copyright (C) 2006-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2006-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_ASPELL_SPELLER_H -#define WEECHAT_ASPELL_SPELLER_H 1 +#ifndef WEECHAT_PLUGIN_ASPELL_SPELLER_H +#define WEECHAT_PLUGIN_ASPELL_SPELLER_H struct t_aspell_speller_buffer { @@ -48,4 +48,4 @@ extern struct t_aspell_speller_buffer *weechat_aspell_speller_buffer_new (struct extern int weechat_aspell_speller_init (); extern void weechat_aspell_speller_end (); -#endif /* WEECHAT_ASPELL_SPELLER_H */ +#endif /* WEECHAT_PLUGIN_ASPELL_SPELLER_H */ diff --git a/src/plugins/aspell/weechat-aspell.c b/src/plugins/aspell/weechat-aspell.c index 1d126607c..67dfe3a18 100644 --- a/src/plugins/aspell/weechat-aspell.c +++ b/src/plugins/aspell/weechat-aspell.c @@ -2,7 +2,7 @@ * weechat-aspell.c - aspell plugin for WeeChat: color for misspelled words * * Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> - * Copyright (C) 2006-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2006-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2012 Nils Görs <weechatter@arcor.de> * * This file is part of WeeChat, the extensible chat client. @@ -46,7 +46,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Spell checker for input (with Aspell)")); 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); struct t_weechat_plugin *weechat_aspell_plugin = NULL; diff --git a/src/plugins/aspell/weechat-aspell.h b/src/plugins/aspell/weechat-aspell.h index a21dbf70f..192d40767 100644 --- a/src/plugins/aspell/weechat-aspell.h +++ b/src/plugins/aspell/weechat-aspell.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> - * Copyright (C) 2006-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2006-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_ASPELL_H -#define WEECHAT_ASPELL_H 1 +#ifndef WEECHAT_PLUGIN_ASPELL_H +#define WEECHAT_PLUGIN_ASPELL_H #ifdef USE_ENCHANT #include <enchant.h> @@ -49,4 +49,4 @@ extern char *weechat_aspell_build_option_name (struct t_gui_buffer *buffer); extern const char *weechat_aspell_get_dict_with_buffer_name (const char *name); extern const char *weechat_aspell_get_dict (struct t_gui_buffer *buffer); -#endif /* WEECHAT_ASPELL_H */ +#endif /* WEECHAT_PLUGIN_ASPELL_H */ diff --git a/src/plugins/buflist/CMakeLists.txt b/src/plugins/buflist/CMakeLists.txt index 21d6f0e00..eb24926b9 100644 --- a/src/plugins/buflist/CMakeLists.txt +++ b/src/plugins/buflist/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/buflist/Makefile.am b/src/plugins/buflist/Makefile.am index 2cc5a3944..664c62fb9 100644 --- a/src/plugins/buflist/Makefile.am +++ b/src/plugins/buflist/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/buflist/buflist-bar-item.c b/src/plugins/buflist/buflist-bar-item.c index 0d3c3c45b..88668f6a4 100644 --- a/src/plugins/buflist/buflist-bar-item.c +++ b/src/plugins/buflist/buflist-bar-item.c @@ -1,7 +1,7 @@ /* * buflist-bar-item.c - bar item for buflist plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -29,32 +29,81 @@ #include "buflist-config.h" -struct t_gui_bar_item *buflist_bar_item_buflist = NULL; +struct t_gui_bar_item *buflist_bar_item_buflist[BUFLIST_BAR_NUM_ITEMS]; struct t_hashtable *buflist_hashtable_pointers = NULL; struct t_hashtable *buflist_hashtable_extra_vars = NULL; -struct t_hashtable *buflist_hashtable_options = NULL; struct t_hashtable *buflist_hashtable_options_conditions = NULL; -struct t_arraylist *buflist_list_buffers = NULL; +struct t_arraylist *buflist_list_buffers[BUFLIST_BAR_NUM_ITEMS]; -int old_line_number_current_buffer = -1; +int old_line_number_current_buffer[BUFLIST_BAR_NUM_ITEMS]; /* - * Updates buflist bar item if buflist is enabled. + * Returns the bar item name with an index. + */ + +const char * +buflist_bar_item_get_name (int index) +{ + static char item_name[32]; + + if (index == 0) + { + snprintf (item_name, sizeof (item_name), "%s", BUFLIST_BAR_ITEM_NAME); + } + else + { + snprintf (item_name, sizeof (item_name), + "%s%d", + BUFLIST_BAR_ITEM_NAME, + index + 1); + } + return item_name; +} + +/* + * Returns the bar item index with an item name, -1 if not found. + */ + +int +buflist_bar_item_get_index (const char *item_name) +{ + int i; + const char *ptr_item_name; + + for (i = 0; i < BUFLIST_BAR_NUM_ITEMS; i++) + { + ptr_item_name = buflist_bar_item_get_name (i); + if (strcmp (ptr_item_name, item_name) == 0) + return i; + } + + return -1; +} + +/* + * Updates buflist bar item if buflist is enabled (or if force argument is 1). */ void -buflist_bar_item_update () +buflist_bar_item_update (int force) { - if (weechat_config_boolean (buflist_config_look_enabled)) - weechat_bar_item_update (BUFLIST_BAR_ITEM_NAME); + int i; + + if (force || weechat_config_boolean (buflist_config_look_enabled)) + { + for (i = 0; i < BUFLIST_BAR_NUM_ITEMS; i++) + { + weechat_bar_item_update (buflist_bar_item_get_name (i)); + } + } } /* * Checks if the bar can be scrolled, the bar must have: * - a position "left" or "right" * - a filling "vertical" - * - "buflist" as first item. + * - the item_name as first item. * * Returns: * 1: bar can be scrolled @@ -62,7 +111,7 @@ buflist_bar_item_update () */ int -buflist_bar_item_bar_can_scroll (struct t_gui_bar *bar) +buflist_bar_item_bar_can_scroll (struct t_gui_bar *bar, const char *item_name) { const char *ptr_bar_name, *ptr_bar_position, *ptr_bar_filling; int items_count, *items_subcount; @@ -104,8 +153,11 @@ buflist_bar_item_bar_can_scroll (struct t_gui_bar *bar) if (!items_subcount || (items_subcount[0] <= 0)) return 0; items_name = weechat_hdata_pointer (buflist_hdata_bar, bar, "items_name"); - if (!items_name || (strcmp (items_name[0][0], BUFLIST_BAR_ITEM_NAME) != 0)) + if (!items_name || !items_name[0] || !items_name[0][0] + || (strcmp (items_name[0][0], item_name) != 0)) + { return 0; + } /* OK, bar can be scrolled! */ return 1; @@ -154,11 +206,11 @@ buflist_bar_item_auto_scroll_bar_window (struct t_gui_bar_window *bar_window, } /* - * Auto-scrolls all bars with buflist item as first item. + * Auto-scrolls all bars with a given buflist item as first item. */ void -buflist_bar_item_auto_scroll (int line_number) +buflist_bar_item_auto_scroll (const char *item_name, int line_number) { struct t_gui_bar *ptr_bar; struct t_gui_bar_window *ptr_bar_window; @@ -173,7 +225,8 @@ buflist_bar_item_auto_scroll (int line_number) { ptr_bar_window = weechat_hdata_pointer (buflist_hdata_bar, ptr_bar, "bar_window"); - if (ptr_bar_window && buflist_bar_item_bar_can_scroll (ptr_bar)) + if (ptr_bar_window && buflist_bar_item_bar_can_scroll (ptr_bar, + item_name)) { buflist_bar_item_auto_scroll_bar_window (ptr_bar_window, line_number); @@ -191,7 +244,7 @@ buflist_bar_item_auto_scroll (int line_number) { ptr_bar = weechat_hdata_pointer (buflist_hdata_bar_window, ptr_bar_window, "bar"); - if (buflist_bar_item_bar_can_scroll (ptr_bar)) + if (buflist_bar_item_bar_can_scroll (ptr_bar, item_name)) { buflist_bar_item_auto_scroll_bar_window (ptr_bar_window, line_number); @@ -232,15 +285,13 @@ buflist_bar_item_buflist_cb (const void *pointer, void *data, const char *hotlist_priority[4] = { "low", "message", "private", "highlight" }; const char indent_empty[1] = { '\0' }; - const char *ptr_lag; - int num_buffers, is_channel, is_private; + const char *ptr_lag, *ptr_item_name; + int item_index, num_buffers, is_channel, is_private; int i, j, length_max_number, current_buffer, number, prev_number, priority; int rc, count, line_number, line_number_current_buffer; /* make C compiler happy */ - (void) pointer; (void) data; - (void) item; (void) window; (void) buffer; (void) extra_info; @@ -254,8 +305,12 @@ buflist_bar_item_buflist_cb (const void *pointer, void *data, buflist = weechat_string_dyn_alloc (256); - ptr_format = weechat_config_string (buflist_config_format_buffer); - ptr_format_current = weechat_config_string (buflist_config_format_buffer_current); + item_index = (int)((unsigned long)pointer); + + weechat_hashtable_set (buflist_hashtable_pointers, "bar_item", item); + + ptr_format = buflist_config_format_buffer_eval; + ptr_format_current = buflist_config_format_buffer_current_eval; ptr_current_buffer = weechat_current_buffer (); @@ -271,10 +326,11 @@ buflist_bar_item_buflist_cb (const void *pointer, void *data, snprintf (str_format_number_empty, sizeof (str_format_number_empty), "%%-%ds", length_max_number); - if (buflist_list_buffers) - weechat_arraylist_free (buflist_list_buffers); - buflist_list_buffers = weechat_arraylist_new (16, 0, 1, - NULL, NULL, NULL, NULL); + if (buflist_list_buffers[item_index]) + weechat_arraylist_free (buflist_list_buffers[item_index]); + buflist_list_buffers[item_index] = weechat_arraylist_new ( + 16, 0, 1, + NULL, NULL, NULL, NULL); buffers = buflist_sort_buffers (); @@ -306,7 +362,7 @@ buflist_bar_item_buflist_cb (const void *pointer, void *data, if (!rc) continue; - weechat_arraylist_add (buflist_list_buffers, ptr_buffer); + weechat_arraylist_add (buflist_list_buffers[item_index], ptr_buffer); current_buffer = (ptr_buffer == ptr_current_buffer); @@ -316,10 +372,13 @@ buflist_bar_item_buflist_cb (const void *pointer, void *data, ptr_name = weechat_hdata_string (buflist_hdata_buffer, ptr_buffer, "short_name"); if (!ptr_name) + { ptr_name = weechat_hdata_string (buflist_hdata_buffer, ptr_buffer, "name"); + } - if (*buflist[0]) + if (weechat_config_boolean (buflist_config_look_add_newline) + && *buflist[0]) { if (!weechat_string_dyn_concat (buflist, "\n")) goto error; @@ -428,8 +487,7 @@ buflist_bar_item_buflist_cb (const void *pointer, void *data, /* set extra variables */ weechat_hashtable_set (buflist_hashtable_extra_vars, "format_buffer", - weechat_config_string ( - buflist_config_format_buffer)); + buflist_config_format_buffer_eval); weechat_hashtable_set (buflist_hashtable_extra_vars, "number", str_number); weechat_hashtable_set (buflist_hashtable_extra_vars, @@ -440,6 +498,10 @@ buflist_bar_item_buflist_cb (const void *pointer, void *data, "indent", ptr_format_indent); weechat_hashtable_set (buflist_hashtable_extra_vars, "name", ptr_name); + weechat_hashtable_set (buflist_hashtable_extra_vars, + "format_name", + weechat_config_string ( + buflist_config_format_name)); /* hotlist */ ptr_hotlist_format = weechat_config_string ( @@ -498,7 +560,7 @@ buflist_bar_item_buflist_cb (const void *pointer, void *data, weechat_hashtable_set ( buflist_hashtable_extra_vars, "format_hotlist", - (str_hotlist) ? weechat_config_string (buflist_config_format_hotlist) : ""); + (str_hotlist) ? buflist_config_format_hotlist_eval : ""); weechat_hashtable_set (buflist_hashtable_extra_vars, "hotlist", (str_hotlist) ? str_hotlist : ""); @@ -525,7 +587,7 @@ buflist_bar_item_buflist_cb (const void *pointer, void *data, (current_buffer) ? ptr_format_current : ptr_format, buflist_hashtable_pointers, buflist_hashtable_extra_vars, - buflist_hashtable_options); + NULL); /* concatenate string */ rc = weechat_string_dyn_concat (buflist, line); @@ -547,12 +609,15 @@ end: weechat_string_dyn_free (buflist, 0); weechat_arraylist_free (buffers); - if ((line_number_current_buffer != old_line_number_current_buffer) + if ((line_number_current_buffer != old_line_number_current_buffer[item_index]) && (weechat_config_integer (buflist_config_look_auto_scroll) >= 0)) { - buflist_bar_item_auto_scroll (line_number_current_buffer); + ptr_item_name = weechat_hdata_string (buflist_hdata_bar_item, + item, "name"); + buflist_bar_item_auto_scroll (ptr_item_name, + line_number_current_buffer); } - old_line_number_current_buffer = line_number_current_buffer; + old_line_number_current_buffer[item_index] = line_number_current_buffer; return str_buflist; } @@ -568,6 +633,8 @@ end: int buflist_bar_item_init () { + int i; + /* create hashtables used by the bar item callback */ buflist_hashtable_pointers = weechat_hashtable_new ( 32, @@ -590,20 +657,6 @@ buflist_bar_item_init () return 0; } - buflist_hashtable_options = weechat_hashtable_new ( - 32, - WEECHAT_HASHTABLE_STRING, - WEECHAT_HASHTABLE_STRING, - NULL, - NULL); - if (!buflist_hashtable_options) - { - weechat_hashtable_free (buflist_hashtable_pointers); - weechat_hashtable_free (buflist_hashtable_extra_vars); - return 0; - } - weechat_hashtable_set (buflist_hashtable_options, "extra", "eval"); - buflist_hashtable_options_conditions = weechat_hashtable_new ( 32, WEECHAT_HASHTABLE_STRING, @@ -613,16 +666,21 @@ buflist_bar_item_init () { weechat_hashtable_free (buflist_hashtable_pointers); weechat_hashtable_free (buflist_hashtable_extra_vars); - weechat_hashtable_free (buflist_hashtable_options); return 0; } weechat_hashtable_set (buflist_hashtable_options_conditions, "type", "condition"); /* bar items */ - buflist_bar_item_buflist = weechat_bar_item_new ( - BUFLIST_BAR_ITEM_NAME, - &buflist_bar_item_buflist_cb, NULL, NULL); + for (i = 0; i < BUFLIST_BAR_NUM_ITEMS; i++) + { + buflist_list_buffers[i] = NULL; + old_line_number_current_buffer[i] = -1; + buflist_bar_item_buflist[i] = weechat_bar_item_new ( + buflist_bar_item_get_name (i), + &buflist_bar_item_buflist_cb, + (const void *)((long unsigned)i), NULL); + } return 1; } @@ -634,7 +692,12 @@ buflist_bar_item_init () void buflist_bar_item_end () { - weechat_bar_item_remove (buflist_bar_item_buflist); + int i; + + for (i = 0; i < BUFLIST_BAR_NUM_ITEMS; i++) + { + weechat_bar_item_remove (buflist_bar_item_buflist[i]); + } weechat_hashtable_free (buflist_hashtable_pointers); buflist_hashtable_pointers = NULL; @@ -642,15 +705,15 @@ buflist_bar_item_end () weechat_hashtable_free (buflist_hashtable_extra_vars); buflist_hashtable_extra_vars = NULL; - weechat_hashtable_free (buflist_hashtable_options); - buflist_hashtable_options = NULL; - weechat_hashtable_free (buflist_hashtable_options_conditions); buflist_hashtable_options_conditions = NULL; - if (buflist_list_buffers) + for (i = 0; i < BUFLIST_BAR_NUM_ITEMS; i++) { - weechat_arraylist_free (buflist_list_buffers); - buflist_list_buffers = NULL; + if (buflist_list_buffers[i]) + { + weechat_arraylist_free (buflist_list_buffers[i]); + buflist_list_buffers[i] = NULL; + } } } diff --git a/src/plugins/buflist/buflist-bar-item.h b/src/plugins/buflist/buflist-bar-item.h index c8626c0cf..1dc976d59 100644 --- a/src/plugins/buflist/buflist-bar-item.h +++ b/src/plugins/buflist/buflist-bar-item.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,15 +17,19 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_BUFLIST_BAR_ITEM_H -#define WEECHAT_BUFLIST_BAR_ITEM_H 1 +#ifndef WEECHAT_PLUGIN_BUFLIST_BAR_ITEM_H +#define WEECHAT_PLUGIN_BUFLIST_BAR_ITEM_H #define BUFLIST_BAR_ITEM_NAME "buflist" -extern struct t_arraylist *buflist_list_buffers; +#define BUFLIST_BAR_NUM_ITEMS 3 -extern void buflist_bar_item_update (); +extern struct t_arraylist *buflist_list_buffers[BUFLIST_BAR_NUM_ITEMS]; + +extern const char *buflist_bar_item_get_name (int index); +extern int buflist_bar_item_get_index (const char *item_name); +extern void buflist_bar_item_update (int force); extern int buflist_bar_item_init (); extern void buflist_bar_item_end (); -#endif /* WEECHAT_BUFLIST_BAR_ITEM_H */ +#endif /* WEECHAT_PLUGIN_BUFLIST_BAR_ITEM_H */ diff --git a/src/plugins/buflist/buflist-command.c b/src/plugins/buflist/buflist-command.c index 9ee8a59e3..203d567fc 100644 --- a/src/plugins/buflist/buflist-command.c +++ b/src/plugins/buflist/buflist-command.c @@ -1,7 +1,7 @@ /* * buflist-command.c - buflist command * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -53,7 +53,7 @@ buflist_command_buflist (const void *pointer, void *data, if (weechat_strcasecmp (argv[1], "refresh") == 0) { - buflist_bar_item_update (); + buflist_bar_item_update (0); return WEECHAT_RC_OK; } @@ -72,7 +72,8 @@ buflist_command_init () N_("bar item with list of buffers"), "bar || refresh", N_(" bar: add the \"buflist\" bar\n" - "refresh: force the refresh of the \"buflist\" bar item\n" + "refresh: force the refresh of the bar items (buflist, buflist2 " + "and buflist3)\n" "\n" "The lines with buffers are displayed using string evaluation " "(see /help eval for the format), with these options:\n" @@ -83,6 +84,9 @@ buflist_command_init () " - buflist.format.buffer_current: format for the current buffer\n" "\n" "The following variables can be used in these options:\n" + " - bar item data (see hdata \"bar_item\" in API doc for a complete " + "list), for example:\n" + " - ${bar_item.name}\n" " - buffer data (see hdata \"buffer\" in API doc for a complete " "list), for example:\n" " - ${buffer.number}\n" @@ -120,6 +124,8 @@ buflist_command_init () "(set only if the option buflist.look.nick_prefix is enabled)\n" " - ${nick_prefix}: nick prefix for a channel " "(set only if the option buflist.look.nick_prefix is enabled)\n" + " - ${format_name}: formatted name (evaluation of option " + "buflist.format.name)\n" " - ${name}: the short name (if set), with a fallback on the " "name\n" " - ${color_hotlist}: the color depending on the highest " diff --git a/src/plugins/buflist/buflist-command.h b/src/plugins/buflist/buflist-command.h index 5f622ecee..ed2a7cbb5 100644 --- a/src/plugins/buflist/buflist-command.h +++ b/src/plugins/buflist/buflist-command.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_BUFLIST_COMMAND_H -#define WEECHAT_BUFLIST_COMMAND_H 1 +#ifndef WEECHAT_PLUGIN_BUFLIST_COMMAND_H +#define WEECHAT_PLUGIN_BUFLIST_COMMAND_H extern void buflist_command_init (); -#endif /* WEECHAT_BUFLIST_COMMAND_H */ +#endif /* WEECHAT_PLUGIN_BUFLIST_COMMAND_H */ diff --git a/src/plugins/buflist/buflist-config.c b/src/plugins/buflist/buflist-config.c index 0c3df353d..a32826d86 100644 --- a/src/plugins/buflist/buflist-config.c +++ b/src/plugins/buflist/buflist-config.c @@ -1,7 +1,7 @@ /* * buflist-config.c - buflist configuration options (file buflist.conf) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -20,6 +20,7 @@ */ #include <stdlib.h> +#include <stdio.h> #include <string.h> #include "../weechat-plugin.h" @@ -32,6 +33,7 @@ struct t_config_file *buflist_config_file = NULL; /* buflist config, look section */ +struct t_config_option *buflist_config_look_add_newline; struct t_config_option *buflist_config_look_auto_scroll; struct t_config_option *buflist_config_look_display_conditions; struct t_config_option *buflist_config_look_enabled; @@ -53,6 +55,7 @@ struct t_config_option *buflist_config_format_hotlist_level_none; struct t_config_option *buflist_config_format_hotlist_separator; struct t_config_option *buflist_config_format_indent; struct t_config_option *buflist_config_format_lag; +struct t_config_option *buflist_config_format_name; struct t_config_option *buflist_config_format_nick_prefix; struct t_config_option *buflist_config_format_number; @@ -60,6 +63,9 @@ struct t_hook **buflist_config_signals_refresh = NULL; int buflist_config_num_signals_refresh = 0; char **buflist_config_sort_fields = NULL; int buflist_config_sort_fields_count = 0; +char *buflist_config_format_buffer_eval = NULL; +char *buflist_config_format_buffer_current_eval = NULL; +char *buflist_config_format_hotlist_eval = NULL; /* @@ -121,7 +127,7 @@ buflist_config_signal_buffer_cb (const void *pointer, void *data, (void) type_data; (void) signal_data; - buflist_bar_item_update (); + buflist_bar_item_update (0); return WEECHAT_RC_OK; } @@ -222,13 +228,13 @@ buflist_config_change_enabled (const void *pointer, void *data, /* buflist enabled */ buflist_config_hook_signals_refresh (); weechat_command (NULL, "/mute /bar show buflist"); - buflist_bar_item_update (); + buflist_bar_item_update (0); } else { /* buflist disabled */ weechat_command (NULL, "/mute /bar hide buflist"); - weechat_bar_item_update (BUFLIST_BAR_ITEM_NAME); + buflist_bar_item_update (1); } } @@ -252,7 +258,7 @@ buflist_config_change_sort (const void *pointer, void *data, weechat_config_string (buflist_config_look_sort), ",", 0, 0, &buflist_config_sort_fields_count); - buflist_bar_item_update (); + buflist_bar_item_update (0); } /* @@ -286,11 +292,11 @@ buflist_config_change_nick_prefix (const void *pointer, void *data, (void) option; buflist_config_change_signals_refresh (NULL, NULL, NULL); - buflist_bar_item_update (); + buflist_bar_item_update (0); } /* - * Callback for changes on format options. + * Callback for changes on options needing bar item refresh. */ void @@ -302,7 +308,68 @@ buflist_config_change_buflist (const void *pointer, void *data, (void) data; (void) option; - buflist_bar_item_update (); + buflist_bar_item_update (0); +} + +/* + * Replace formats like ${format_xxx} by evaluated form: ${eval:${format_xxx}}. + * + * Note: result must be freed after use. + */ + +char * +buflist_config_add_eval_for_formats (const char *string) +{ + char *formats[] = { "format_buffer", "format_number", "indent", + "format_nick_prefix", "format_name", + "format_hotlist", "hotlist", "format_lag", + "color_hotlist", NULL }; + char *result, *tmp, format[512], format_eval[512]; + int i; + + result = strdup (string); + for (i = 0; formats[i]; i++) + { + snprintf (format, sizeof (format), + "${%s}", formats[i]); + snprintf (format_eval, sizeof (format_eval), + "${eval:${%s}}", formats[i]); + tmp = weechat_string_replace (result, format, format_eval); + free (result); + result = tmp; + } + return result; +} + +/* + * Callback for changes on some format options. + */ + +void +buflist_config_change_format (const void *pointer, void *data, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) option; + + if (buflist_config_format_buffer_eval) + free (buflist_config_format_buffer_eval); + buflist_config_format_buffer_eval = buflist_config_add_eval_for_formats ( + weechat_config_string (buflist_config_format_buffer)); + + if (buflist_config_format_buffer_current_eval) + free (buflist_config_format_buffer_current_eval); + buflist_config_format_buffer_current_eval = buflist_config_add_eval_for_formats ( + weechat_config_string (buflist_config_format_buffer_current)); + + if (buflist_config_format_hotlist_eval) + free (buflist_config_format_hotlist_eval); + buflist_config_format_hotlist_eval = buflist_config_add_eval_for_formats ( + weechat_config_string (buflist_config_format_hotlist)); + + buflist_bar_item_update (0); } /* @@ -334,9 +401,21 @@ buflist_config_init () if (!ptr_section) { weechat_config_free (buflist_config_file); + buflist_config_file = NULL; return 0; } + buflist_config_look_add_newline = weechat_config_new_option ( + buflist_config_file, ptr_section, + "add_newline", "boolean", + N_("add newline between the buffers displayed, so each buffer is " + "displayed on a separate line (recommended); if disabled, newlines " + "must be manually added in the formats with \"${\\n}\", " + "and the mouse actions are not possible any more"), + NULL, 0, 0, "on", NULL, 0, + NULL, NULL, NULL, + &buflist_config_change_buflist, NULL, NULL, + NULL, NULL, NULL); buflist_config_look_auto_scroll = weechat_config_new_option ( buflist_config_file, ptr_section, "auto_scroll", "integer", @@ -454,6 +533,7 @@ buflist_config_init () if (!ptr_section) { weechat_config_free (buflist_config_file); + buflist_config_file = NULL; return 0; } @@ -461,12 +541,19 @@ buflist_config_init () buflist_config_file, ptr_section, "buffer", "string", N_("format of each line with a buffer " - "(note: content is evaluated, see /help buflist)"), + "(note: content is evaluated, see /help buflist); " + "example: standard format for bar item \"buflist\" and only the " + "buffer number between square brackets for other bar items " + "(\"buflist2\" and \"buflist3\"): " + "\"${if:${bar_item.name}==buflist?${format_number}${indent}" + "${format_nick_prefix}${color_hotlist}${format_name}:" + "[${number}]}\""), NULL, 0, 0, - "${format_number}${indent}${format_nick_prefix}${color_hotlist}${name}", + "${format_number}${indent}${format_nick_prefix}${color_hotlist}" + "${format_name}", NULL, 0, NULL, NULL, NULL, - &buflist_config_change_buflist, NULL, NULL, + &buflist_config_change_format, NULL, NULL, NULL, NULL, NULL); buflist_config_format_buffer_current = weechat_config_new_option ( buflist_config_file, ptr_section, @@ -475,7 +562,7 @@ buflist_config_init () "(note: content is evaluated, see /help buflist)"), NULL, 0, 0, "${color:,blue}${format_buffer}", NULL, 0, NULL, NULL, NULL, - &buflist_config_change_buflist, NULL, NULL, + &buflist_config_change_format, NULL, NULL, NULL, NULL, NULL); buflist_config_format_hotlist = weechat_config_new_option ( buflist_config_file, ptr_section, @@ -486,7 +573,7 @@ buflist_config_init () " ${color:green}(${hotlist}${color:green})", NULL, 0, NULL, NULL, NULL, - &buflist_config_change_buflist, NULL, NULL, + &buflist_config_change_format, NULL, NULL, NULL, NULL, NULL); buflist_config_format_hotlist_level[0] = weechat_config_new_option ( buflist_config_file, ptr_section, @@ -562,6 +649,15 @@ buflist_config_init () NULL, NULL, NULL, &buflist_config_change_buflist, NULL, NULL, NULL, NULL, NULL); + buflist_config_format_name = weechat_config_new_option ( + buflist_config_file, ptr_section, + "name", "string", + N_("format for buffer name " + "(note: content is evaluated, see /help buflist)"), + NULL, 0, 0, "${name}", NULL, 0, + NULL, NULL, NULL, + &buflist_config_change_buflist, NULL, NULL, + NULL, NULL, NULL); buflist_config_format_nick_prefix = weechat_config_new_option ( buflist_config_file, ptr_section, "nick_prefix", "string", @@ -601,6 +697,7 @@ buflist_config_read () { buflist_config_change_sort (NULL, NULL, NULL); buflist_config_change_signals_refresh (NULL, NULL, NULL); + buflist_config_change_format (NULL, NULL, NULL); } return rc; @@ -634,4 +731,11 @@ buflist_config_free () buflist_config_sort_fields = NULL; buflist_config_sort_fields_count = 0; } + + if (buflist_config_format_buffer_eval) + free (buflist_config_format_buffer_eval); + if (buflist_config_format_buffer_current_eval) + free (buflist_config_format_buffer_current_eval); + if (buflist_config_format_hotlist_eval) + free (buflist_config_format_hotlist_eval); } diff --git a/src/plugins/buflist/buflist-config.h b/src/plugins/buflist/buflist-config.h index 263dff9f2..7bff4beac 100644 --- a/src/plugins/buflist/buflist-config.h +++ b/src/plugins/buflist/buflist-config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_BUFLIST_CONFIG_H -#define WEECHAT_BUFLIST_CONFIG_H 1 +#ifndef WEECHAT_PLUGIN_BUFLIST_CONFIG_H +#define WEECHAT_PLUGIN_BUFLIST_CONFIG_H #define BUFLIST_CONFIG_NAME "buflist" @@ -32,6 +32,7 @@ extern struct t_config_file *buflist_config_file; +extern struct t_config_option *buflist_config_look_add_newline; extern struct t_config_option *buflist_config_look_auto_scroll; extern struct t_config_option *buflist_config_look_display_conditions; extern struct t_config_option *buflist_config_look_enabled; @@ -51,15 +52,19 @@ extern struct t_config_option *buflist_config_format_hotlist_level_none; extern struct t_config_option *buflist_config_format_hotlist_separator; extern struct t_config_option *buflist_config_format_indent; extern struct t_config_option *buflist_config_format_lag; +extern struct t_config_option *buflist_config_format_name; extern struct t_config_option *buflist_config_format_nick_prefix; extern struct t_config_option *buflist_config_format_number; extern char **buflist_config_sort_fields; extern int buflist_config_sort_fields_count; +extern char *buflist_config_format_buffer_eval; +extern char *buflist_config_format_buffer_current_eval; +extern char *buflist_config_format_hotlist_eval; extern int buflist_config_init (); extern int buflist_config_read (); extern int buflist_config_write (); extern void buflist_config_free (); -#endif /* WEECHAT_BUFLIST_CONFIG_H */ +#endif /* WEECHAT_PLUGIN_BUFLIST_CONFIG_H */ diff --git a/src/plugins/buflist/buflist-mouse.c b/src/plugins/buflist/buflist-mouse.c index c574edb59..297bf2305 100644 --- a/src/plugins/buflist/buflist-mouse.c +++ b/src/plugins/buflist/buflist-mouse.c @@ -1,7 +1,7 @@ /* * buflist-mouse.c - mouse actions for buflist * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -40,7 +40,7 @@ buflist_focus_cb (const void *pointer, void *data, struct t_hashtable *info) const char *ptr_bar_item_name, *ptr_bar_item_line, *keys, *ptr_value; long item_line; char *error, str_value[128], **list_keys; - int i, num_keys, type; + int i, item_index, num_keys, type; struct t_gui_buffer *ptr_buffer; /* make C compiler happy */ @@ -49,12 +49,13 @@ buflist_focus_cb (const void *pointer, void *data, struct t_hashtable *info) ptr_buffer = NULL; - if (!buflist_list_buffers) - goto end; - /* check bar item name */ ptr_bar_item_name = weechat_hashtable_get (info, "_bar_item_name"); - if (strcmp (ptr_bar_item_name, BUFLIST_BAR_ITEM_NAME) != 0) + item_index = buflist_bar_item_get_index (ptr_bar_item_name); + if (item_index < 0) + goto end; + + if (!buflist_list_buffers[item_index]) goto end; /* check bar item line */ @@ -65,13 +66,14 @@ buflist_focus_cb (const void *pointer, void *data, struct t_hashtable *info) if (!error || error[0]) goto end; if ((item_line < 0) - || (item_line >= weechat_arraylist_size (buflist_list_buffers))) + || (item_line >= weechat_arraylist_size (buflist_list_buffers[item_index]))) { goto end; } /* check if buffer pointer is still valid */ - ptr_buffer = weechat_arraylist_get (buflist_list_buffers, item_line); + ptr_buffer = weechat_arraylist_get (buflist_list_buffers[item_index], + item_line); if (!ptr_buffer) goto end; if (!weechat_hdata_check_pointer ( @@ -128,10 +130,10 @@ end: break; case WEECHAT_HDATA_TIME: snprintf (str_value, sizeof (str_value), - "%ld", + "%lld", (ptr_buffer) ? - (long int)weechat_hdata_time (buflist_hdata_buffer, - ptr_buffer, list_keys[i]) : -1); + (long long)weechat_hdata_time (buflist_hdata_buffer, + ptr_buffer, list_keys[i]) : -1); weechat_hashtable_set (info, list_keys[i], str_value); break; default: /* ignore other types */ @@ -321,10 +323,16 @@ buflist_hsignal_cb (const void *pointer, void *data, const char *signal, int buflist_mouse_init () { - weechat_hook_focus (BUFLIST_BAR_ITEM_NAME, &buflist_focus_cb, NULL, NULL); + int i; + + for (i = 0; i < BUFLIST_BAR_NUM_ITEMS; i++) + { + weechat_hook_focus (buflist_bar_item_get_name (i), + &buflist_focus_cb, NULL, NULL); + } - weechat_hook_hsignal(BUFLIST_MOUSE_HSIGNAL, - &buflist_hsignal_cb, NULL, NULL); + weechat_hook_hsignal (BUFLIST_MOUSE_HSIGNAL, + &buflist_hsignal_cb, NULL, NULL); return 1; } diff --git a/src/plugins/buflist/buflist-mouse.h b/src/plugins/buflist/buflist-mouse.h index df4c4e393..ada6e2a12 100644 --- a/src/plugins/buflist/buflist-mouse.h +++ b/src/plugins/buflist/buflist-mouse.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,12 +17,12 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_BUFLIST_MOUSE_H -#define WEECHAT_BUFLIST_MOUSE_H 1 +#ifndef WEECHAT_PLUGIN_BUFLIST_MOUSE_H +#define WEECHAT_PLUGIN_BUFLIST_MOUSE_H #define BUFLIST_MOUSE_HSIGNAL "buflist_mouse" extern int buflist_mouse_init (); extern void buflist_mouse_end (); -#endif /* WEECHAT_BUFLIST_MOUSE_H */ +#endif /* WEECHAT_PLUGIN_BUFLIST_MOUSE_H */ diff --git a/src/plugins/buflist/buflist.c b/src/plugins/buflist/buflist.c index 97d33387c..bdc8aea76 100644 --- a/src/plugins/buflist/buflist.c +++ b/src/plugins/buflist/buflist.c @@ -1,7 +1,7 @@ /* * buflist.c - Bar with list of buffers * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -36,7 +36,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(8000); +WEECHAT_PLUGIN_PRIORITY(9000); struct t_weechat_plugin *weechat_buflist_plugin = NULL; @@ -44,6 +44,7 @@ struct t_hdata *buflist_hdata_window = NULL; struct t_hdata *buflist_hdata_buffer = NULL; struct t_hdata *buflist_hdata_hotlist = NULL; struct t_hdata *buflist_hdata_bar = NULL; +struct t_hdata *buflist_hdata_bar_item = NULL; struct t_hdata *buflist_hdata_bar_window = NULL; @@ -70,8 +71,8 @@ buflist_add_bar () */ void -buflist_buffer_get_irc_pointers(struct t_gui_buffer *buffer, - void **irc_server, void **irc_channel) +buflist_buffer_get_irc_pointers (struct t_gui_buffer *buffer, + void **irc_server, void **irc_channel) { const char *ptr_server_name, *ptr_channel_name, *ptr_name; struct t_hdata *hdata_irc_server, *hdata_irc_channel; @@ -370,6 +371,10 @@ buflist_script_loaded_cb (const void *pointer, void *data, const char *signal, (void) signal; (void) type_data; + /* display a warning only if buflist is enabled */ + if (!weechat_config_boolean (buflist_config_look_enabled)) + return WEECHAT_RC_OK; + if (!signal_data) return WEECHAT_RC_OK; @@ -399,6 +404,8 @@ int weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) { struct t_hashtable *keys; + char str_key[256]; + int i; /* make C compiler happy */ (void) argc; @@ -410,6 +417,7 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) buflist_hdata_buffer = weechat_hdata_get ("buffer"); buflist_hdata_hotlist = weechat_hdata_get ("hotlist"); buflist_hdata_bar = weechat_hdata_get ("bar"); + buflist_hdata_bar_item = weechat_hdata_get ("bar_item"); buflist_hdata_bar_window = weechat_hdata_get ("bar_window"); if (!buflist_config_init ()) @@ -425,7 +433,7 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) if (weechat_config_boolean (buflist_config_look_enabled)) buflist_add_bar (); - buflist_bar_item_update (); + buflist_bar_item_update (0); buflist_mouse_init (); @@ -449,12 +457,19 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) /* default mouse actions */ weechat_hashtable_remove_all (keys); - weechat_hashtable_set (keys, - "@item(" BUFLIST_BAR_ITEM_NAME "):button1*", - "hsignal:" BUFLIST_MOUSE_HSIGNAL); - weechat_hashtable_set (keys, - "@item(" BUFLIST_BAR_ITEM_NAME "):button2*", - "hsignal:" BUFLIST_MOUSE_HSIGNAL); + for (i = 0; i < BUFLIST_BAR_NUM_ITEMS; i++) + { + snprintf (str_key, sizeof (str_key), + "@item(%s):button1*", + buflist_bar_item_get_name (i)); + weechat_hashtable_set (keys, + str_key, "hsignal:" BUFLIST_MOUSE_HSIGNAL); + snprintf (str_key, sizeof (str_key), + "@item(%s):button2*", + buflist_bar_item_get_name (i)); + weechat_hashtable_set (keys, + str_key, "hsignal:" BUFLIST_MOUSE_HSIGNAL); + } weechat_hashtable_set (keys, "@bar(" BUFLIST_BAR_NAME "):ctrl-wheelup", "hsignal:" BUFLIST_MOUSE_HSIGNAL); diff --git a/src/plugins/buflist/buflist.h b/src/plugins/buflist/buflist.h index 91e3062e3..487e7031d 100644 --- a/src/plugins/buflist/buflist.h +++ b/src/plugins/buflist/buflist.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_BUFLIST_H -#define WEECHAT_BUFLIST_H 1 +#ifndef WEECHAT_PLUGIN_BUFLIST_H +#define WEECHAT_PLUGIN_BUFLIST_H #define weechat_plugin weechat_buflist_plugin #define BUFLIST_PLUGIN_NAME "buflist" @@ -31,11 +31,13 @@ extern struct t_hdata *buflist_hdata_window; extern struct t_hdata *buflist_hdata_buffer; extern struct t_hdata *buflist_hdata_hotlist; extern struct t_hdata *buflist_hdata_bar; +extern struct t_hdata *buflist_hdata_bar_item; extern struct t_hdata *buflist_hdata_bar_window; extern void buflist_add_bar (); -extern void buflist_buffer_get_irc_pointers(struct t_gui_buffer *buffer, - void **irc_server, void **irc_channel); +extern void buflist_buffer_get_irc_pointers (struct t_gui_buffer *buffer, + void **irc_server, + void **irc_channel); extern struct t_arraylist *buflist_sort_buffers (); -#endif /* WEECHAT_BUFLIST_H */ +#endif /* WEECHAT_PLUGIN_BUFLIST_H */ diff --git a/src/plugins/charset/CMakeLists.txt b/src/plugins/charset/CMakeLists.txt index 27d40ed22..1a4894a8c 100644 --- a/src/plugins/charset/CMakeLists.txt +++ b/src/plugins/charset/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/charset/Makefile.am b/src/plugins/charset/Makefile.am index 76e0db23c..370a0659a 100644 --- a/src/plugins/charset/Makefile.am +++ b/src/plugins/charset/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/charset/charset.c b/src/plugins/charset/charset.c index 29f8c89d9..dd5e1779a 100644 --- a/src/plugins/charset/charset.c +++ b/src/plugins/charset/charset.c @@ -1,7 +1,7 @@ /* * charset.c - charset plugin for WeeChat: encode/decode strings * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -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(14000); +WEECHAT_PLUGIN_PRIORITY(15000); #define CHARSET_CONFIG_NAME "charset" @@ -216,6 +216,7 @@ charset_config_init () if (!ptr_section) { weechat_config_free (charset_config_file); + charset_config_file = NULL; return 0; } @@ -252,6 +253,7 @@ charset_config_init () if (!ptr_section) { weechat_config_free (charset_config_file); + charset_config_file = NULL; return 0; } @@ -268,6 +270,7 @@ charset_config_init () if (!ptr_section) { weechat_config_free (charset_config_file); + charset_config_file = NULL; return 0; } diff --git a/src/plugins/exec/CMakeLists.txt b/src/plugins/exec/CMakeLists.txt index 470087194..54d04a38a 100644 --- a/src/plugins/exec/CMakeLists.txt +++ b/src/plugins/exec/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/exec/Makefile.am b/src/plugins/exec/Makefile.am index 552a79443..de3101972 100644 --- a/src/plugins/exec/Makefile.am +++ b/src/plugins/exec/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/exec/exec-buffer.c b/src/plugins/exec/exec-buffer.c index 936d7e52d..6ec89f408 100644 --- a/src/plugins/exec/exec-buffer.c +++ b/src/plugins/exec/exec-buffer.c @@ -1,7 +1,7 @@ /* * exec-buffer.c - buffers with output of commands * - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/exec/exec-buffer.h b/src/plugins/exec/exec-buffer.h index 1877ec04c..7cd2e1c62 100644 --- a/src/plugins/exec/exec-buffer.h +++ b/src/plugins/exec/exec-buffer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_EXEC_BUFFER_H -#define WEECHAT_EXEC_BUFFER_H 1 +#ifndef WEECHAT_PLUGIN_EXEC_BUFFER_H +#define WEECHAT_PLUGIN_EXEC_BUFFER_H extern void exec_buffer_set_callbacks (); extern struct t_gui_buffer *exec_buffer_new (const char *name, @@ -26,4 +26,4 @@ extern struct t_gui_buffer *exec_buffer_new (const char *name, int clear_buffer, int switch_to_buffer); -#endif /* WEECHAT_EXEC_BUFFER_H */ +#endif /* WEECHAT_PLUGIN_EXEC_BUFFER_H */ diff --git a/src/plugins/exec/exec-command.c b/src/plugins/exec/exec-command.c index bcb82e994..1ba3bf53c 100644 --- a/src/plugins/exec/exec-command.c +++ b/src/plugins/exec/exec-command.c @@ -1,7 +1,7 @@ /* * exec-command.c - exec command * - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -108,11 +108,13 @@ exec_command_list () { /* process has ended */ local_time = localtime (&ptr_exec_cmd->start_time); - strftime (str_time1, sizeof (str_time1), - "%Y-%m-%d %H:%M:%S", local_time); + if (strftime (str_time1, sizeof (str_time1), + "%Y-%m-%d %H:%M:%S", local_time) == 0) + str_time1[0] = '\0'; local_time = localtime (&ptr_exec_cmd->end_time); - strftime (str_time2, sizeof (str_time2), - "%Y-%m-%d %H:%M:%S", local_time); + if (strftime (str_time2, sizeof (str_time2), + "%Y-%m-%d %H:%M:%S", local_time) == 0) + str_time2[0] = '\0'; weechat_printf (NULL, " %s%s%s %d%s%s%s: %s\"%s%s%s\"%s (%s -> %s, %s)", weechat_color (weechat_config_string (exec_config_color_flag_finished)), @@ -333,7 +335,7 @@ exec_command_parse_options (struct t_exec_cmd_options *cmd_options, if (argv[i][0] == '"') { /* search the ending double quote */ - length_total = 1; + length_total = 2; end = i; while (end < argc) { @@ -807,8 +809,9 @@ exec_command_init () " || -set <id> <property> <value>" " || -del <id>|-all [<id>...]"), N_(" -list: list commands\n" - " -sh: use the shell to execute the command (WARNING: use this " - "option ONLY if all arguments are safe, see option -nosh)\n" + " -sh: use the shell to execute the command, many commands can " + "be piped (WARNING: use this option ONLY if all arguments are " + "safe, see option -nosh)\n" " -nosh: do not use the shell to execute the command (required if " "the command has some unsafe data, for example the content of a " "message from another user) (default)\n" diff --git a/src/plugins/exec/exec-command.h b/src/plugins/exec/exec-command.h index 06be3ae4a..a15708e8f 100644 --- a/src/plugins/exec/exec-command.h +++ b/src/plugins/exec/exec-command.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_EXEC_COMMAND_H -#define WEECHAT_EXEC_COMMAND_H 1 +#ifndef WEECHAT_PLUGIN_EXEC_COMMAND_H +#define WEECHAT_PLUGIN_EXEC_COMMAND_H struct t_exec_cmd_options { @@ -48,4 +48,4 @@ extern int exec_command_run (struct t_gui_buffer *buffer, int start_arg); extern void exec_command_init (); -#endif /* WEECHAT_EXEC_COMMAND_H */ +#endif /* WEECHAT_PLUGIN_EXEC_COMMAND_H */ diff --git a/src/plugins/exec/exec-completion.c b/src/plugins/exec/exec-completion.c index 520915851..52f034c94 100644 --- a/src/plugins/exec/exec-completion.c +++ b/src/plugins/exec/exec-completion.c @@ -1,7 +1,7 @@ /* * exec-completion.c - completion for exec commands * - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/exec/exec-completion.h b/src/plugins/exec/exec-completion.h index c44fabad9..b9cdc0b62 100644 --- a/src/plugins/exec/exec-completion.h +++ b/src/plugins/exec/exec-completion.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_EXEC_COMPLETION_H -#define WEECHAT_EXEC_COMPLETION_H 1 +#ifndef WEECHAT_PLUGIN_EXEC_COMPLETION_H +#define WEECHAT_PLUGIN_EXEC_COMPLETION_H extern void exec_completion_init (); -#endif /* WEECHAT_EXEC_COMPLETION_H */ +#endif /* WEECHAT_PLUGIN_EXEC_COMPLETION_H */ diff --git a/src/plugins/exec/exec-config.c b/src/plugins/exec/exec-config.c index e8accdcd8..43693aa47 100644 --- a/src/plugins/exec/exec-config.c +++ b/src/plugins/exec/exec-config.c @@ -1,7 +1,7 @@ /* * exec-config.c - exec configuration options (file exec.conf) * - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -109,6 +109,7 @@ exec_config_init () if (!ptr_section) { weechat_config_free (exec_config_file); + exec_config_file = NULL; return 0; } @@ -141,6 +142,7 @@ exec_config_init () if (!ptr_section) { weechat_config_free (exec_config_file); + exec_config_file = NULL; return 0; } diff --git a/src/plugins/exec/exec-config.h b/src/plugins/exec/exec-config.h index 667b6e48f..537597c11 100644 --- a/src/plugins/exec/exec-config.h +++ b/src/plugins/exec/exec-config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_EXEC_CONFIG_H -#define WEECHAT_EXEC_CONFIG_H 1 +#ifndef WEECHAT_PLUGIN_EXEC_CONFIG_H +#define WEECHAT_PLUGIN_EXEC_CONFIG_H #define EXEC_CONFIG_NAME "exec" @@ -38,4 +38,4 @@ extern int exec_config_read (); extern int exec_config_write (); extern void exec_config_free (); -#endif /* WEECHAT_EXEC_CONFIG_H */ +#endif /* WEECHAT_PLUGIN_EXEC_CONFIG_H */ diff --git a/src/plugins/exec/exec.c b/src/plugins/exec/exec.c index 10fbd6386..d40188396 100644 --- a/src/plugins/exec/exec.c +++ b/src/plugins/exec/exec.c @@ -1,7 +1,7 @@ /* * exec.c - execution of external commands in WeeChat * - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -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(12000); +WEECHAT_PLUGIN_PRIORITY(13000); struct t_weechat_plugin *weechat_exec_plugin = NULL; @@ -691,8 +691,8 @@ exec_print_log () weechat_log_printf (" command . . . . . . . . . : '%s'", ptr_exec_cmd->command); weechat_log_printf (" pid . . . . . . . . . . . : %d", ptr_exec_cmd->pid); weechat_log_printf (" detached. . . . . . . . . : %d", ptr_exec_cmd->detached); - weechat_log_printf (" start_time. . . . . . . . : %ld", ptr_exec_cmd->start_time); - weechat_log_printf (" end_time. . . . . . . . . : %ld", ptr_exec_cmd->end_time); + weechat_log_printf (" start_time. . . . . . . . : %lld", (long long)ptr_exec_cmd->start_time); + weechat_log_printf (" end_time. . . . . . . . . : %lld", (long long)ptr_exec_cmd->end_time); weechat_log_printf (" output_to_buffer. . . . . : %d", ptr_exec_cmd->output_to_buffer); weechat_log_printf (" output_to_buffer_exec_cmd : %d", ptr_exec_cmd->output_to_buffer_exec_cmd); weechat_log_printf (" buffer_full_name. . . . . : '%s'", ptr_exec_cmd->buffer_full_name); diff --git a/src/plugins/exec/exec.h b/src/plugins/exec/exec.h index 31003773c..c333a0dd9 100644 --- a/src/plugins/exec/exec.h +++ b/src/plugins/exec/exec.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_EXEC_H -#define WEECHAT_EXEC_H 1 +#ifndef WEECHAT_PLUGIN_EXEC_H +#define WEECHAT_PLUGIN_EXEC_H #include <unistd.h> #include <time.h> @@ -88,4 +88,4 @@ extern int exec_process_cb (const void *pointer, void *data, extern void exec_free (struct t_exec_cmd *exec_cmd); extern void exec_free_all (); -#endif /* WEECHAT_EXEC_H */ +#endif /* WEECHAT_PLUGIN_EXEC_H */ diff --git a/src/plugins/fifo/CMakeLists.txt b/src/plugins/fifo/CMakeLists.txt index cd2297b0c..e71700893 100644 --- a/src/plugins/fifo/CMakeLists.txt +++ b/src/plugins/fifo/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/fifo/Makefile.am b/src/plugins/fifo/Makefile.am index 6521e3cd8..2003a94a2 100644 --- a/src/plugins/fifo/Makefile.am +++ b/src/plugins/fifo/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/fifo/fifo-command.c b/src/plugins/fifo/fifo-command.c index 047189dc2..94b05acd6 100644 --- a/src/plugins/fifo/fifo-command.c +++ b/src/plugins/fifo/fifo-command.c @@ -1,7 +1,7 @@ /* * fifo-command.c - fifo command * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/fifo/fifo-command.h b/src/plugins/fifo/fifo-command.h index 476d03966..1e93abb93 100644 --- a/src/plugins/fifo/fifo-command.h +++ b/src/plugins/fifo/fifo-command.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_FIFO_COMMAND_H -#define WEECHAT_FIFO_COMMAND_H 1 +#ifndef WEECHAT_PLUGIN_FIFO_COMMAND_H +#define WEECHAT_PLUGIN_FIFO_COMMAND_H extern void fifo_command_init (); -#endif /* WEECHAT_FIFO_COMMAND_H */ +#endif /* WEECHAT_PLUGIN_FIFO_COMMAND_H */ diff --git a/src/plugins/fifo/fifo-config.c b/src/plugins/fifo/fifo-config.c index 8d255b46c..e08435c75 100644 --- a/src/plugins/fifo/fifo-config.c +++ b/src/plugins/fifo/fifo-config.c @@ -1,7 +1,7 @@ /* * fifo-config.c - fifo configuration options (file fifo.conf) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -50,7 +50,7 @@ fifo_config_change_file_enabled (const void *pointer, void *data, fifo_remove (); if (weechat_config_boolean (fifo_config_file_enabled)) - fifo_create(); + fifo_create (); } /* @@ -103,6 +103,7 @@ fifo_config_init () if (!ptr_section) { weechat_config_free (fifo_config_file); + fifo_config_file = NULL; return 0; } diff --git a/src/plugins/fifo/fifo-config.h b/src/plugins/fifo/fifo-config.h index ea7923905..2b01bccb8 100644 --- a/src/plugins/fifo/fifo-config.h +++ b/src/plugins/fifo/fifo-config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_FIFO_CONFIG_H -#define WEECHAT_FIFO_CONFIG_H 1 +#ifndef WEECHAT_PLUGIN_FIFO_CONFIG_H +#define WEECHAT_PLUGIN_FIFO_CONFIG_H #define FIFO_CONFIG_NAME "fifo" @@ -31,4 +31,4 @@ extern int fifo_config_read (); extern int fifo_config_write (); extern void fifo_config_free (); -#endif /* WEECHAT_FIFO_CONFIG_H */ +#endif /* WEECHAT_PLUGIN_FIFO_CONFIG_H */ diff --git a/src/plugins/fifo/fifo-info.c b/src/plugins/fifo/fifo-info.c index 421d6e14d..9bbe1ba89 100644 --- a/src/plugins/fifo/fifo-info.c +++ b/src/plugins/fifo/fifo-info.c @@ -1,7 +1,7 @@ /* * fifo-info.c - info and infolist hooks for fifo plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/fifo/fifo-info.h b/src/plugins/fifo/fifo-info.h index 27acec1bd..a272cb614 100644 --- a/src/plugins/fifo/fifo-info.h +++ b/src/plugins/fifo/fifo-info.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_FIFO_INFO_H -#define WEECHAT_FIFO_INFO_H 1 +#ifndef WEECHAT_PLUGIN_FIFO_INFO_H +#define WEECHAT_PLUGIN_FIFO_INFO_H extern void fifo_info_init (); -#endif /* WEECHAT_FIFO_INFO_H */ +#endif /* WEECHAT_PLUGIN_FIFO_INFO_H */ diff --git a/src/plugins/fifo/fifo.c b/src/plugins/fifo/fifo.c index 44c0eeac8..07bd72285 100644 --- a/src/plugins/fifo/fifo.c +++ b/src/plugins/fifo/fifo.c @@ -1,7 +1,7 @@ /* * fifo.c - fifo plugin for WeeChat: remote control with FIFO pipe * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -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(7000); +WEECHAT_PLUGIN_PRIORITY(8000); struct t_weechat_plugin *weechat_fifo_plugin = NULL; #define weechat_plugin weechat_fifo_plugin diff --git a/src/plugins/fifo/fifo.h b/src/plugins/fifo/fifo.h index 4c63ed7a6..563d13a3c 100644 --- a/src/plugins/fifo/fifo.h +++ b/src/plugins/fifo/fifo.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_FIFO_H -#define WEECHAT_FIFO_H 1 +#ifndef WEECHAT_PLUGIN_FIFO_H +#define WEECHAT_PLUGIN_FIFO_H #define weechat_plugin weechat_fifo_plugin #define FIFO_PLUGIN_NAME "fifo" @@ -31,4 +31,4 @@ extern char *fifo_filename; extern void fifo_create (); extern void fifo_remove (); -#endif /* WEECHAT_FIFO_H */ +#endif /* WEECHAT_PLUGIN_FIFO_H */ diff --git a/src/plugins/fset/CMakeLists.txt b/src/plugins/fset/CMakeLists.txt new file mode 100644 index 000000000..5ff81f945 --- /dev/null +++ b/src/plugins/fset/CMakeLists.txt @@ -0,0 +1,34 @@ +# +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> +# +# This file is part of WeeChat, the extensible chat client. +# +# WeeChat is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# WeeChat is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with WeeChat. If not, see <http://www.gnu.org/licenses/>. +# + +add_library(fset MODULE +fset.c fset.h +fset-bar-item.c fset-bar-item.h +fset-buffer.c fset-buffer.h +fset-command.c fset-command.h +fset-completion.c fset-completion.h +fset-config.c fset-config.h +fset-info.c fset-info.h +fset-mouse.c fset-mouse.h +fset-option.c fset-option.h) +set_target_properties(fset PROPERTIES PREFIX "") + +target_link_libraries(fset) + +install(TARGETS fset LIBRARY DESTINATION ${LIBDIR}/plugins) diff --git a/src/plugins/fset/Makefile.am b/src/plugins/fset/Makefile.am new file mode 100644 index 000000000..c4b86bd72 --- /dev/null +++ b/src/plugins/fset/Makefile.am @@ -0,0 +1,48 @@ +# +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> +# +# This file is part of WeeChat, the extensible chat client. +# +# WeeChat is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# WeeChat is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with WeeChat. If not, see <http://www.gnu.org/licenses/>. +# + +AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/locale\" $(FSET_CFLAGS) + +libdir = ${weechat_libdir}/plugins + +lib_LTLIBRARIES = fset.la + +fset_la_SOURCES = fset.c \ + fset.h \ + fset-bar-item.c \ + fset-bar-item.h \ + fset-buffer.c \ + fset-buffer.h \ + fset-command.c \ + fset-command.h \ + fset-completion.c \ + fset-completion.h \ + fset-config.c \ + fset-config.h \ + fset-info.c \ + fset-info.h \ + fset-mouse.c \ + fset-mouse.h \ + fset-option.c \ + fset-option.h + +fset_la_LDFLAGS = -module -no-undefined +fset_la_LIBADD = $(FSET_LFLAGS) + +EXTRA_DIST = CMakeLists.txt diff --git a/src/plugins/fset/fset-bar-item.c b/src/plugins/fset/fset-bar-item.c new file mode 100644 index 000000000..08031e30e --- /dev/null +++ b/src/plugins/fset/fset-bar-item.c @@ -0,0 +1,225 @@ +/* + * fset-bar-item.c - bar item for Fast Set plugin + * + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "../weechat-plugin.h" +#include "fset.h" +#include "fset-bar-item.h" +#include "fset-buffer.h" +#include "fset-config.h" +#include "fset-option.h" + + +struct t_gui_bar_item *fset_bar_item_fset = NULL; + + +/* + * Updates fset bar item if fset is enabled. + */ + +void +fset_bar_item_update () +{ + weechat_bar_item_update (FSET_BAR_ITEM_NAME); +} + +/* + * Returns content of bar item "buffer_plugin": bar item with buffer plugin. + */ + +char * +fset_bar_item_fset_cb (const void *pointer, void *data, + struct t_gui_bar_item *item, + struct t_gui_window *window, + struct t_gui_buffer *buffer, + struct t_hashtable *extra_info) +{ + struct t_fset_option *ptr_fset_option; + struct t_config_option *ptr_option; + char str_help[8192], **default_and_values; + const char **ptr_string_values; + int i; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) item; + (void) window; + (void) buffer; + (void) extra_info; + + if (!fset_buffer) + return NULL; + + ptr_fset_option = weechat_arraylist_get (fset_options, + fset_buffer_selected_line); + if (!ptr_fset_option) + return NULL; + + default_and_values = weechat_string_dyn_alloc (256); + if (!default_and_values) + return NULL; + + weechat_string_dyn_concat (default_and_values, weechat_color ("bar_fg")); + weechat_string_dyn_concat (default_and_values, _("default: ")); + if (ptr_fset_option->default_value) + { + if (ptr_fset_option->type == FSET_OPTION_TYPE_STRING) + { + weechat_string_dyn_concat (default_and_values, + weechat_color ( + weechat_config_string ( + fset_config_color_help_quotes))); + weechat_string_dyn_concat (default_and_values, "\""); + } + weechat_string_dyn_concat ( + default_and_values, + weechat_color (weechat_config_string (fset_config_color_help_default_value))); + weechat_string_dyn_concat (default_and_values, + ptr_fset_option->default_value); + if (ptr_fset_option->type == FSET_OPTION_TYPE_STRING) + { + weechat_string_dyn_concat (default_and_values, + weechat_color ( + weechat_config_string ( + fset_config_color_help_quotes))); + weechat_string_dyn_concat (default_and_values, "\""); + } + } + else + { + weechat_string_dyn_concat ( + default_and_values, + weechat_color (weechat_config_string (fset_config_color_help_default_value))); + weechat_string_dyn_concat (default_and_values, FSET_OPTION_VALUE_NULL); + } + + if ((ptr_fset_option->string_values && ptr_fset_option->string_values[0]) + || (ptr_fset_option->type == FSET_OPTION_TYPE_INTEGER)) + { + ptr_option = weechat_config_get (ptr_fset_option->name); + if (ptr_option) + { + ptr_string_values = NULL; + if (ptr_fset_option->string_values && ptr_fset_option->string_values[0]) + { + ptr_string_values = weechat_config_option_get_pointer ( + ptr_option, "string_values"); + } + if (ptr_string_values + || (ptr_fset_option->type == FSET_OPTION_TYPE_INTEGER)) + { + weechat_string_dyn_concat (default_and_values, + weechat_color ("bar_fg")); + weechat_string_dyn_concat (default_and_values, ", "); + weechat_string_dyn_concat (default_and_values, _("values:")); + weechat_string_dyn_concat (default_and_values, " "); + if (ptr_string_values) + { + for (i = 0; ptr_string_values[i]; i++) + { + if (i > 0) + { + weechat_string_dyn_concat (default_and_values, + weechat_color ("bar_fg")); + weechat_string_dyn_concat (default_and_values, ", "); + } + weechat_string_dyn_concat ( + default_and_values, + weechat_color ( + weechat_config_string ( + fset_config_color_help_values))); + weechat_string_dyn_concat (default_and_values, + ptr_string_values[i]); + } + } + else + { + weechat_string_dyn_concat ( + default_and_values, + weechat_color ( + weechat_config_string ( + fset_config_color_help_values))); + weechat_string_dyn_concat (default_and_values, + ptr_fset_option->min); + weechat_string_dyn_concat (default_and_values, + weechat_color ("bar_fg")); + weechat_string_dyn_concat (default_and_values, " ... "); + weechat_string_dyn_concat ( + default_and_values, + weechat_color ( + weechat_config_string ( + fset_config_color_help_values))); + weechat_string_dyn_concat (default_and_values, + ptr_fset_option->max); + } + } + } + } + + snprintf (str_help, sizeof (str_help), + /* TRANSLATORS: "%s%s%s:" at beginning of string it the name of option */ + _("%s%s%s: %s %s[%s%s]%s"), + weechat_color (weechat_config_string (fset_config_color_help_name)), + ptr_fset_option->name, + weechat_color ("bar_fg"), + (ptr_fset_option->description && ptr_fset_option->description[0]) ? + _(ptr_fset_option->description) : _("(no description)"), + weechat_color ("bar_delim"), + *default_and_values, + weechat_color ("bar_delim"), + weechat_color ("bar_fg")); + + weechat_string_dyn_free (default_and_values, 1); + + return strdup (str_help); +} + +/* + * Initializes fset bar items. + * + * Returns: + * 1: OK + * 0: error + */ + +int +fset_bar_item_init () +{ + fset_bar_item_fset = weechat_bar_item_new ( + FSET_BAR_ITEM_NAME, + &fset_bar_item_fset_cb, NULL, NULL); + + return 1; +} + +/* + * Ends fset bar items. + */ + +void +fset_bar_item_end () +{ + weechat_bar_item_remove (fset_bar_item_fset); +} diff --git a/src/plugins/fset/fset-bar-item.h b/src/plugins/fset/fset-bar-item.h new file mode 100644 index 000000000..e0e5558db --- /dev/null +++ b/src/plugins/fset/fset-bar-item.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef WEECHAT_PLUGIN_FSET_BAR_ITEM_H +#define WEECHAT_PLUGIN_FSET_BAR_ITEM_H + +#define FSET_BAR_ITEM_NAME "fset" + +extern void fset_bar_item_update (); +extern int fset_bar_item_init (); +extern void fset_bar_item_end (); + +#endif /* WEECHAT_PLUGIN_FSET_BAR_ITEM_H */ diff --git a/src/plugins/fset/fset-buffer.c b/src/plugins/fset/fset-buffer.c new file mode 100644 index 000000000..aaae50b61 --- /dev/null +++ b/src/plugins/fset/fset-buffer.c @@ -0,0 +1,1452 @@ +/* + * fset-buffer.c - buffer for Fast Set plugin + * + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "../weechat-plugin.h" +#include "fset.h" +#include "fset-buffer.h" +#include "fset-bar-item.h" +#include "fset-config.h" +#include "fset-option.h" + + +struct t_gui_buffer *fset_buffer = NULL; +int fset_buffer_selected_line = 0; +struct t_hashtable *fset_buffer_hashtable_pointers = NULL; +struct t_hashtable *fset_buffer_hashtable_extra_vars = NULL; + + +/* + * Sets title of fset buffer. + */ + +void +fset_buffer_set_title () +{ + int num_options; + char str_marked[32], str_title[1024]; + + if (!fset_buffer) + return; + + str_marked[0] = '\0'; + if (fset_option_count_marked > 0) + { + snprintf (str_marked, sizeof (str_marked), + " (%s: %s%d%s)", + weechat_config_string (fset_config_look_marked_string), + weechat_color (weechat_config_string (fset_config_color_title_marked_options)), + fset_option_count_marked, + weechat_color ("bar_fg")); + } + + num_options = weechat_arraylist_size (fset_options); + + snprintf (str_title, sizeof (str_title), + _("%s%d%s/%s%d%s%s | Filter: %s%s%s | Sort: %s%s%s | " + "Key(input): " + "alt+space=toggle boolean, " + "alt+'-'(-)=subtract 1 or set, " + "alt+'+'(+)=add 1 or append, " + "alt+f,alt+r(r)=reset, " + "alt+f,alt+u(u)=unset, " + "alt+enter(s)=set, " + "alt+f,alt+n(n)=set new value, " + "alt+f,alt+a(a)=append, " + "alt+','=mark/unmark, " + "shift+down=mark and move down, " + "shift+up=move up and mark, " + "($)=refresh, " + "($$)=unmark/refresh, " + "(m)=mark matching options, " + "(u)=unmark matching options, " + "alt+p(p)=toggle plugins desc, " + "alt+v(v)=toggle help bar, " + "ctrl+X(x)=switch format, " + "(q)=close buffer"), + weechat_color (weechat_config_string (fset_config_color_title_current_option)), + (num_options > 0) ? fset_buffer_selected_line + 1 : 0, + weechat_color ("bar_fg"), + weechat_color (weechat_config_string (fset_config_color_title_count_options)), + num_options, + weechat_color ("bar_fg"), + str_marked, + weechat_color (weechat_config_string (fset_config_color_title_filter)), + (fset_option_filter) ? fset_option_filter : "*", + weechat_color ("bar_fg"), + weechat_color (weechat_config_string (fset_config_color_title_sort)), + weechat_config_string (fset_config_look_sort), + weechat_color ("bar_fg")); + + weechat_buffer_set (fset_buffer, "title", str_title); +} + +/* + * Fills a field with spaces (according to max length for this field). + * + * If fill_right == 1, fills with spaces on the right. Otherwise + * fills with spaces on the left before the value. + * + * If skip_colors == 1, the field value may contain color codes, so + * weechat_strlen_screen() is used instead of weechat_utf8_strlen_screen() + * and then the functions is slower. + */ + +void +fset_buffer_fills_field (char *field, char *field_spaces, + int size, int max_length, + int fill_right, int skip_colors) +{ + int length, length_screen, num_spaces; + + length = strlen (field); + length_screen = (skip_colors) ? + weechat_strlen_screen (field) : weechat_utf8_strlen_screen (field); + + if (max_length > size - 1) + max_length = size - 1; + + num_spaces = max_length - length_screen; + if (num_spaces > 0) + { + if (length + num_spaces >= size) + num_spaces = size - length - 1; + + if (fill_right) + { + /* add spaces after the value */ + memset (field + length, ' ', num_spaces); + } + else + { + /* insert spaces before the value */ + memmove (field + num_spaces, field, length); + memset (field, ' ', num_spaces); + } + field[length + num_spaces] = '\0'; + } + + /* field with spaces */ + if (field_spaces) + { + memset (field_spaces, ' ', max_length); + field_spaces[max_length] = '\0'; + } +} + +/* + * Displays a line with an fset option using an evaluated format. + */ + +void +fset_buffer_display_option_eval (struct t_fset_option *fset_option) +{ + char *line, str_color_line[128], **lines; + char str_field[4096], str_field2[4096]; + char str_color_value[128], str_color_quotes[128], str_number[64]; + int selected_line, y, i, num_lines; + int default_value_undef, value_undef, value_changed; + int add_quotes, add_quotes_parent, format_number; + + if (!fset_option) + return; + + selected_line = (fset_option->index == fset_buffer_selected_line) ? 1 : 0; + + default_value_undef = (fset_option->default_value == NULL) ? 1 : 0; + value_undef = (fset_option->value == NULL) ? 1 : 0; + value_changed = (fset_option_value_is_changed (fset_option)) ? 1 : 0; + + /* set pointers */ + weechat_hashtable_set (fset_buffer_hashtable_pointers, + "fset_option", fset_option); + + /* file */ + snprintf (str_field, sizeof (str_field), "%s", fset_option->file); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__file", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s", + weechat_color ( + weechat_config_string ( + (value_changed) ? + fset_config_color_name_changed[selected_line] : + fset_config_color_name[selected_line])), + (fset_option->file) ? fset_option->file : ""); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_file", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->file, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "file", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_file", str_field2); + + /* section */ + snprintf (str_field, sizeof (str_field), "%s", fset_option->section); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__section", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s", + weechat_color ( + weechat_config_string ( + (value_changed) ? + fset_config_color_name_changed[selected_line] : + fset_config_color_name[selected_line])), + (fset_option->section) ? fset_option->section : ""); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_section", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->section, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "section", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_section", str_field2); + + /* option */ + snprintf (str_field, sizeof (str_field), "%s", fset_option->option); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__option", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s", + weechat_color ( + weechat_config_string ( + (value_changed) ? + fset_config_color_name_changed[selected_line] : + fset_config_color_name[selected_line])), + (fset_option->option) ? fset_option->option : ""); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_option", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->option, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "option", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_option", str_field2); + + /* name */ + snprintf (str_field, sizeof (str_field), "%s", fset_option->name); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__name", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s", + weechat_color ( + weechat_config_string ( + (value_changed) ? + fset_config_color_name_changed[selected_line] : + fset_config_color_name[selected_line])), + (fset_option->name) ? fset_option->name : ""); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_name", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->name, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "name", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_name", str_field2); + + /* parent_name */ + snprintf (str_field, sizeof (str_field), "%s", fset_option->parent_name); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__parent_name", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s", + weechat_color (weechat_config_string (fset_config_color_parent_name[selected_line])), + (fset_option->parent_name) ? fset_option->parent_name : ""); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_parent_name", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->parent_name, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "parent_name", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_parent_name", str_field2); + + /* type */ + snprintf (str_field, sizeof (str_field), + "%s", _(fset_option_type_string[fset_option->type])); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__type", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s", + weechat_color (weechat_config_string (fset_config_color_type[selected_line])), + _(fset_option_type_string[fset_option->type])); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_type", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->type, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "type", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_type", str_field2); + + /* type_en */ + snprintf (str_field, sizeof (str_field), + "%s", fset_option_type_string[fset_option->type]); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__type_en", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s", + weechat_color (weechat_config_string (fset_config_color_type[selected_line])), + fset_option_type_string[fset_option->type]); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_type_en", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->type_en, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "type_en", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_type_en", str_field2); + + /* type_short */ + snprintf (str_field, sizeof (str_field), + "%s", fset_option_type_string_short[fset_option->type]); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__type_short", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s", + weechat_color (weechat_config_string (fset_config_color_type[selected_line])), + fset_option_type_string_short[fset_option->type]); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_type_short", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->type_short, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "type_short", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_type_short", str_field2); + + /* type_tiny */ + snprintf (str_field, sizeof (str_field), + "%s", fset_option_type_string_tiny[fset_option->type]); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__type_tiny", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s", + weechat_color (weechat_config_string (fset_config_color_type[selected_line])), + fset_option_type_string_tiny[fset_option->type]); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_type_tiny", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->type_tiny, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "type_tiny", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_type_tiny", str_field2); + + /* default_value */ + add_quotes = (fset_option->default_value && (fset_option->type == FSET_OPTION_TYPE_STRING)) ? 1 : 0; + snprintf (str_color_value, sizeof (str_color_value), + "%s", + weechat_color ( + weechat_config_string ( + (default_value_undef) ? + fset_config_color_value_undef[selected_line] : + fset_config_color_default_value[selected_line]))); + snprintf (str_field, sizeof (str_field), + "%s", (fset_option->default_value) ? fset_option->default_value : FSET_OPTION_VALUE_NULL); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__default_value", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s%s%s%s%s", + (add_quotes) ? weechat_color (weechat_config_string (fset_config_color_quotes[selected_line])) : "", + (add_quotes) ? "\"" : "", + str_color_value, + (fset_option->default_value) ? fset_option->default_value : FSET_OPTION_VALUE_NULL, + (add_quotes) ? weechat_color (weechat_config_string (fset_config_color_quotes[selected_line])) : "", + (add_quotes) ? "\"" : ""); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_default_value", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->default_value, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "default_value", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_default_value", str_field2); + + /* value */ + add_quotes = (fset_option->value && (fset_option->type == FSET_OPTION_TYPE_STRING)) ? 1 : 0; + if ((fset_option->type == FSET_OPTION_TYPE_COLOR) + && weechat_config_boolean (fset_config_look_use_color_value)) + { + snprintf (str_color_value, sizeof (str_color_value), + "%s", + weechat_color (fset_option->value)); + } + else if (value_undef) + { + snprintf (str_color_value, sizeof (str_color_value), + "%s", + weechat_color ( + weechat_config_string ( + fset_config_color_value_undef[selected_line]))); + snprintf (str_color_quotes, sizeof (str_color_quotes), + "%s", + weechat_color ( + weechat_config_string ( + fset_config_color_quotes[selected_line]))); + } + else if (value_changed) + { + snprintf (str_color_value, sizeof (str_color_value), + "%s", + weechat_color ( + weechat_config_string ( + fset_config_color_value_changed[selected_line]))); + snprintf (str_color_quotes, sizeof (str_color_quotes), + "%s", + weechat_color ( + weechat_config_string ( + fset_config_color_quotes_changed[selected_line]))); + } + else + { + snprintf (str_color_value, sizeof (str_color_value), + "%s", + weechat_color ( + weechat_config_string ( + fset_config_color_value[selected_line]))); + snprintf (str_color_quotes, sizeof (str_color_quotes), + "%s", + weechat_color ( + weechat_config_string ( + fset_config_color_quotes[selected_line]))); + } + snprintf (str_field, sizeof (str_field), + "%s", (fset_option->value) ? fset_option->value : FSET_OPTION_VALUE_NULL); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__value", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s%s%s%s%s", + (add_quotes) ? str_color_quotes : "", + (add_quotes) ? "\"" : "", + str_color_value, + (fset_option->value) ? fset_option->value : FSET_OPTION_VALUE_NULL, + (add_quotes) ? str_color_quotes : "", + (add_quotes) ? "\"" : ""); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_value", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->value, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "value", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_value", str_field2); + + /* value2 (value with parent value in case of inherited value) */ + if (value_undef && fset_option->parent_value) + { + add_quotes_parent = (fset_option->parent_value && (fset_option->type == FSET_OPTION_TYPE_STRING)) ? 1 : 0; + snprintf (str_field, sizeof (str_field), + "%s -> %s", + (fset_option->value) ? fset_option->value : FSET_OPTION_VALUE_NULL, + (fset_option->parent_value) ? fset_option->parent_value : FSET_OPTION_VALUE_NULL); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__value2", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s%s%s%s%s%s -> %s%s%s%s%s%s", + (add_quotes) ? str_color_quotes : "", + (add_quotes) ? "\"" : "", + str_color_value, + (fset_option->value) ? fset_option->value : FSET_OPTION_VALUE_NULL, + (add_quotes) ? str_color_quotes : "", + (add_quotes) ? "\"" : "", + weechat_color ("default"), + (add_quotes_parent) ? weechat_color (weechat_config_string (fset_config_color_quotes[selected_line])) : "", + (add_quotes_parent) ? "\"" : "", + weechat_color (weechat_config_string (fset_config_color_parent_value[selected_line])), + (fset_option->parent_value) ? fset_option->parent_value : FSET_OPTION_VALUE_NULL, + (add_quotes_parent) ? weechat_color (weechat_config_string (fset_config_color_quotes[selected_line])) : "", + (add_quotes_parent) ? "\"" : ""); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_value2", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->value2, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "value2", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_value2", str_field2); + } + else + { + snprintf (str_field, sizeof (str_field), + "%s", + (fset_option->value) ? fset_option->value : FSET_OPTION_VALUE_NULL); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__value2", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s%s%s%s%s", + (add_quotes) ? str_color_quotes : "", + (add_quotes) ? "\"" : "", + str_color_value, + (fset_option->value) ? fset_option->value : FSET_OPTION_VALUE_NULL, + (add_quotes) ? str_color_quotes : "", + (add_quotes) ? "\"" : ""); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_value2", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->value2, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "value2", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_value2", str_field2); + } + + /* parent_value (set only if value is NULL and inherited from parent) */ + if (value_undef && fset_option->parent_value) + { + add_quotes_parent = (fset_option->parent_value && (fset_option->type == FSET_OPTION_TYPE_STRING)) ? 1 : 0; + snprintf (str_field, sizeof (str_field), + "%s", + (fset_option->parent_value) ? fset_option->parent_value : FSET_OPTION_VALUE_NULL); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__parent_value", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s%s%s%s%s", + (add_quotes_parent) ? weechat_color (weechat_config_string (fset_config_color_quotes[selected_line])) : "", + (add_quotes_parent) ? "\"" : "", + weechat_color (weechat_config_string (fset_config_color_parent_value[selected_line])), + (fset_option->parent_value) ? fset_option->parent_value : FSET_OPTION_VALUE_NULL, + (add_quotes_parent) ? weechat_color (weechat_config_string (fset_config_color_quotes[selected_line])) : "", + (add_quotes_parent) ? "\"" : ""); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_parent_value", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->parent_value, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "parent_value", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_parent_value", str_field2); + } + else + { + str_field[0] = '\0'; + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__parent_value", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_parent_value", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->parent_value, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "parent_value", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_parent_value", str_field2); + } + + /* min */ + snprintf (str_field, sizeof (str_field), "%s", fset_option->min); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__min", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s", + weechat_color (weechat_config_string (fset_config_color_min[selected_line])), + (fset_option->min) ? fset_option->min : ""); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_min", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->min, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "min", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_min", str_field2); + + /* max */ + snprintf (str_field, sizeof (str_field), "%s", fset_option->max); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__max", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s", + weechat_color (weechat_config_string (fset_config_color_max[selected_line])), + (fset_option->max) ? fset_option->max : ""); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_max", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->max, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "max", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_max", str_field); + + /* description */ + snprintf (str_field, sizeof (str_field), + "%s", (fset_option->description && fset_option->description[0]) ? _(fset_option->description) : ""); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__description", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s", + weechat_color (weechat_config_string (fset_config_color_description[selected_line])), + (fset_option->description && fset_option->description[0]) ? _(fset_option->description) : ""); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_description", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->description, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "description", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_description", str_field2); + + /* description2 */ + snprintf (str_field, sizeof (str_field), + "%s", (fset_option->description && fset_option->description[0]) ? _(fset_option->description) : _("(no description)")); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__description2", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s", + weechat_color (weechat_config_string (fset_config_color_description[selected_line])), + (fset_option->description && fset_option->description[0]) ? _(fset_option->description) : _("(no description)")); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_description2", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->description2, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "description2", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_description2", str_field2); + + /* description_en */ + snprintf (str_field, sizeof (str_field), "%s", fset_option->description); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__description_en", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s", + weechat_color (weechat_config_string (fset_config_color_description[selected_line])), + (fset_option->description) ? fset_option->description : ""); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_description_en", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->description_en, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "description_en", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_description_en", str_field2); + + /* description_en2 */ + snprintf (str_field, sizeof (str_field), + "%s", (fset_option->description && fset_option->description[0]) ? fset_option->description : "(no description)"); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__description_en2", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s", + weechat_color (weechat_config_string (fset_config_color_description[selected_line])), + (fset_option->description && fset_option->description[0]) ? fset_option->description : "(no description)"); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_description_en2", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->description_en2, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "description_en2", str_field); + + /* string_values */ + snprintf (str_field, sizeof (str_field), "%s", fset_option->string_values); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__string_values", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s", + weechat_color (weechat_config_string (fset_config_color_string_values[selected_line])), + (fset_option->string_values) ? fset_option->string_values : ""); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_string_values", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->string_values, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "string_values", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_string_values", str_field2); + + /* marked */ + snprintf (str_field, sizeof (str_field), + "%s", + (fset_option->marked) ? + weechat_config_string (fset_config_look_marked_string) : + weechat_config_string (fset_config_look_unmarked_string)); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__marked", str_field); + snprintf (str_field, sizeof (str_field), + "%s%s", + (fset_option->marked) ? + weechat_color (weechat_config_string (fset_config_color_marked[selected_line])) : + weechat_color (weechat_config_string (fset_config_color_unmarked[selected_line])), + (fset_option->marked) ? + weechat_config_string (fset_config_look_marked_string) : + weechat_config_string (fset_config_look_unmarked_string)); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_marked", str_field); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + fset_option_max_length->marked, 1, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "marked", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_marked", str_field2); + + /* index */ + snprintf (str_field, sizeof (str_field), "%d", fset_option->index + 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "__index", str_field); + snprintf (str_field, sizeof (str_field), + "%s%d", + weechat_color (weechat_config_string (fset_config_color_index[selected_line])), + fset_option->index + 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "_index", str_field); + snprintf (str_number, sizeof (str_number), + "%d", weechat_arraylist_size (fset_options)); + fset_buffer_fills_field (str_field, str_field2, sizeof (str_field), + strlen (str_number), 0, 1); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "index", str_field); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "empty_index", str_field2); + + /* set other variables depending on the value */ + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "default_value_undef", + (default_value_undef) ? "1" : "0"); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "value_undef", + (value_undef) ? "1" : "0"); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "value_changed", + (value_changed) ? "1" : "0"); + + /* set other variables */ + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "selected_line", + (selected_line) ? "1" : "0"); + weechat_hashtable_set (fset_buffer_hashtable_extra_vars, + "newline", "\r\n"); + + /* build string for line */ + str_color_line[0] = '\0'; + format_number = weechat_config_integer (fset_config_look_format_number); + if (selected_line) + { + snprintf (str_color_line, sizeof (str_color_line), + ",%s", + weechat_config_string ( + fset_config_color_line_selected_bg[format_number - 1])); + } + else if (fset_option->marked) + { + snprintf (str_color_line, sizeof (str_color_line), + ",%s", + weechat_config_string ( + fset_config_color_line_marked_bg[format_number - 1])); + } + + /* evaluate line */ + line = weechat_string_eval_expression ( + weechat_config_string (fset_config_format_option[format_number - 1]), + fset_buffer_hashtable_pointers, + fset_buffer_hashtable_extra_vars, + NULL); + if (line) + { + lines = weechat_string_split (line, "\r\n", 0, 0, &num_lines); + if (lines) + { + y = fset_option->index * fset_config_format_option_num_lines[format_number - 1]; + for (i = 0; i < num_lines; i++) + { + weechat_printf_y ( + fset_buffer, y, + "%s%s", + (str_color_line[0]) ? weechat_color (str_color_line) : "", + lines[i]); + y++; + } + weechat_string_free_split (lines); + } + free (line); + } +} + +/* + * Displays a line with an fset option using a predefined format + * (much faster because there is no eval). + */ + +void +fset_buffer_display_option_predefined_format (struct t_fset_option *fset_option) +{ + int selected_line, value_undef, value_changed, format_number; + int add_quotes, add_quotes_parent; + char str_marked[128], str_name[4096], str_type[128], str_value[4096]; + char str_color_line[128], str_color_value[128], str_color_quotes[128]; + + selected_line = (fset_option->index == fset_buffer_selected_line) ? 1 : 0; + value_undef = (fset_option->value == NULL) ? 1 : 0; + value_changed = (fset_option_value_is_changed (fset_option)) ? 1 : 0; + format_number = weechat_config_integer (fset_config_look_format_number); + + str_color_line[0] = '\0'; + if (selected_line) + { + snprintf (str_color_line, sizeof (str_color_line), + ",%s", + weechat_config_string ( + fset_config_color_line_selected_bg[format_number - 1])); + } + else if (fset_option->marked) + { + snprintf (str_color_line, sizeof (str_color_line), + ",%s", + weechat_config_string ( + fset_config_color_line_marked_bg[format_number - 1])); + } + + snprintf (str_marked, sizeof (str_marked), + "%s", + (fset_option->marked) ? + weechat_config_string (fset_config_look_marked_string) : + weechat_config_string (fset_config_look_unmarked_string)); + fset_buffer_fills_field (str_marked, NULL, sizeof (str_marked), + fset_option_max_length->marked, 1, 0); + + snprintf (str_name, sizeof (str_name), + "%s", + (fset_option->name) ? fset_option->name : ""); + fset_buffer_fills_field (str_name, NULL, sizeof (str_name), + fset_option_max_length->name, 1, 0); + + snprintf (str_type, sizeof (str_type), + "%s", + _(fset_option_type_string[fset_option->type])); + fset_buffer_fills_field (str_type, NULL, sizeof (str_type), + fset_option_max_length->type, 1, 0); + + add_quotes = (fset_option->value && (fset_option->type == FSET_OPTION_TYPE_STRING)) ? 1 : 0; + if ((fset_option->type == FSET_OPTION_TYPE_COLOR) + && weechat_config_boolean (fset_config_look_use_color_value)) + { + snprintf (str_color_value, sizeof (str_color_value), + "%s", + weechat_color (fset_option->value)); + } + else if (value_undef) + { + snprintf (str_color_value, sizeof (str_color_value), + "%s", + weechat_color ( + weechat_config_string ( + fset_config_color_value_undef[selected_line]))); + snprintf (str_color_quotes, sizeof (str_color_quotes), + "%s", + weechat_color ( + weechat_config_string ( + fset_config_color_quotes[selected_line]))); + } + else if (value_changed) + { + snprintf (str_color_value, sizeof (str_color_value), + "%s", + weechat_color ( + weechat_config_string ( + fset_config_color_value_changed[selected_line]))); + snprintf (str_color_quotes, sizeof (str_color_quotes), + "%s", + weechat_color ( + weechat_config_string ( + fset_config_color_quotes_changed[selected_line]))); + } + else + { + snprintf (str_color_value, sizeof (str_color_value), + "%s", + weechat_color ( + weechat_config_string ( + fset_config_color_value[selected_line]))); + snprintf (str_color_quotes, sizeof (str_color_quotes), + "%s", + weechat_color ( + weechat_config_string ( + fset_config_color_quotes[selected_line]))); + } + if (value_undef && fset_option->parent_value) + { + add_quotes_parent = (fset_option->parent_value && (fset_option->type == FSET_OPTION_TYPE_STRING)) ? 1 : 0; + snprintf (str_value, sizeof (str_value), + "%s%s%s%s%s%s%s -> %s%s%s%s%s%s", + (add_quotes) ? str_color_quotes : "", + (add_quotes) ? "\"" : "", + str_color_value, + (fset_option->value) ? fset_option->value : FSET_OPTION_VALUE_NULL, + (add_quotes) ? str_color_quotes : "", + (add_quotes) ? "\"" : "", + weechat_color ("default"), + (add_quotes_parent) ? weechat_color (weechat_config_string (fset_config_color_quotes[selected_line])) : "", + (add_quotes_parent) ? "\"" : "", + weechat_color (weechat_config_string (fset_config_color_parent_value[selected_line])), + (fset_option->parent_value) ? fset_option->parent_value : FSET_OPTION_VALUE_NULL, + (add_quotes_parent) ? weechat_color (weechat_config_string (fset_config_color_quotes[selected_line])) : "", + (add_quotes_parent) ? "\"" : ""); + } + else + { + snprintf (str_value, sizeof (str_value), + "%s%s%s%s%s%s", + (add_quotes) ? str_color_quotes : "", + (add_quotes) ? "\"" : "", + str_color_value, + (fset_option->value) ? fset_option->value : FSET_OPTION_VALUE_NULL, + (add_quotes) ? str_color_quotes : "", + (add_quotes) ? "\"" : ""); + } + + weechat_printf_y ( + fset_buffer, fset_option->index, + "%s%s%s %s%s %s%s %s", + (str_color_line[0]) ? weechat_color (str_color_line) : "", + (fset_option->marked) ? + weechat_color ( + weechat_config_string (fset_config_color_marked[selected_line])) : + weechat_color ( + weechat_config_string (fset_config_color_unmarked[selected_line])), + str_marked, + weechat_color ( + weechat_config_string ( + (value_changed) ? + fset_config_color_name_changed[selected_line] : + fset_config_color_name[selected_line])), + str_name, + weechat_color ( + weechat_config_string (fset_config_color_type[selected_line])), + str_type, + str_value); +} + +/* + * Displays a line with an fset option. + */ + +void +fset_buffer_display_option (struct t_fset_option *fset_option) +{ + int format_number; + const char *ptr_format; + + format_number = weechat_config_integer (fset_config_look_format_number); + ptr_format = weechat_config_string (fset_config_format_option[format_number - 1]); + + if (ptr_format && ptr_format[0]) + fset_buffer_display_option_eval (fset_option); + else + fset_buffer_display_option_predefined_format (fset_option); +} + +/* + * Updates list of options in fset buffer. + */ + +void +fset_buffer_refresh (int clear) +{ + int num_options, i; + struct t_fset_option *ptr_fset_option; + + if (!fset_buffer) + return; + + num_options = weechat_arraylist_size (fset_options); + + if (clear) + weechat_buffer_clear (fset_buffer); + + for (i = 0; i < num_options; i++) + { + ptr_fset_option = weechat_arraylist_get (fset_options, i); + if (ptr_fset_option) + fset_buffer_display_option (ptr_fset_option); + } + + fset_buffer_set_title (); + fset_bar_item_update (); +} + +/* + * Sets current selected line. + */ + +void +fset_buffer_set_current_line (int line) +{ + int old_line; + + if ((line >= 0) && (line < weechat_arraylist_size (fset_options))) + { + old_line = fset_buffer_selected_line; + fset_buffer_selected_line = line; + + if (old_line != fset_buffer_selected_line) + { + fset_buffer_display_option ( + weechat_arraylist_get (fset_options, old_line)); + } + fset_buffer_display_option ( + weechat_arraylist_get (fset_options, fset_buffer_selected_line)); + + fset_buffer_set_title (); + fset_bar_item_update (); + } +} + +/* + * Gets info about a window. + */ + +void +fset_buffer_get_window_info (struct t_gui_window *window, + int *start_line_y, int *chat_height) +{ + struct t_hdata *hdata_window, *hdata_window_scroll, *hdata_line; + struct t_hdata *hdata_line_data; + void *window_scroll, *start_line, *line_data; + + hdata_window = weechat_hdata_get ("window"); + hdata_window_scroll = weechat_hdata_get ("window_scroll"); + hdata_line = weechat_hdata_get ("line"); + hdata_line_data = weechat_hdata_get ("line_data"); + *start_line_y = 0; + window_scroll = weechat_hdata_pointer (hdata_window, window, "scroll"); + if (window_scroll) + { + start_line = weechat_hdata_pointer (hdata_window_scroll, window_scroll, + "start_line"); + if (start_line) + { + line_data = weechat_hdata_pointer (hdata_line, start_line, "data"); + if (line_data) + { + *start_line_y = weechat_hdata_integer (hdata_line_data, + line_data, "y"); + } + } + } + *chat_height = weechat_hdata_integer (hdata_window, window, + "win_chat_height"); +} + +/* + * Checks if current line is outside window. + * + * Returns: + * 1: line is outside window + * 0: line is inside window + */ + +void +fset_buffer_check_line_outside_window () +{ + struct t_gui_window *window; + int start_line_y, chat_height, format_number, lines_per_option; + int selected_y, selected_y2; + char str_command[256]; + + window = weechat_window_search_with_buffer (fset_buffer); + if (!window) + return; + + fset_buffer_get_window_info (window, &start_line_y, &chat_height); + + format_number = weechat_config_integer (fset_config_look_format_number); + lines_per_option = fset_config_format_option_num_lines[format_number - 1]; + if (lines_per_option > chat_height) + return; + selected_y = fset_buffer_selected_line * lines_per_option; + selected_y2 = selected_y + lines_per_option - 1; + + if ((start_line_y > selected_y) + || (start_line_y < selected_y2 - chat_height + 1)) + { + snprintf (str_command, sizeof (str_command), + "/window scroll -window %d %s%d", + weechat_window_get_integer (window, "number"), + (start_line_y > selected_y) ? "-" : "+", + (start_line_y > selected_y) ? + start_line_y - selected_y : + selected_y2 - start_line_y - chat_height + 1); + weechat_command (fset_buffer, str_command); + } +} + +/* + * Callback for signal "window_scrolled". + */ + +int +fset_buffer_window_scrolled_cb (const void *pointer, void *data, + const char *signal, const char *type_data, + void *signal_data) +{ + int start_line_y, chat_height, line, num_options; + int format_number, lines_per_option; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) signal; + (void) type_data; + + /* scrolled another window/buffer? then just ignore */ + if (weechat_window_get_pointer (signal_data, "buffer") != fset_buffer) + return WEECHAT_RC_OK; + + fset_buffer_get_window_info (signal_data, &start_line_y, &chat_height); + + format_number = weechat_config_integer (fset_config_look_format_number); + lines_per_option = fset_config_format_option_num_lines[format_number - 1]; + line = fset_buffer_selected_line; + while (line * lines_per_option < start_line_y) + { + line += chat_height / lines_per_option; + } + while (line * lines_per_option >= start_line_y + chat_height) + { + line -= chat_height / lines_per_option; + } + if (line * lines_per_option < start_line_y) + line = (start_line_y / lines_per_option) + 1; + + num_options = weechat_arraylist_size (fset_options); + if (line >= num_options) + line = num_options - 1; + fset_buffer_set_current_line (line); + + return WEECHAT_RC_OK; +} + +/* + * Callback for user data in fset buffer. + */ + +int +fset_buffer_input_cb (const void *pointer, void *data, + struct t_gui_buffer *buffer, + const char *input_data) +{ + char *actions[][2] = { + { "<<", "/fset -go 0" }, + { ">>", "/fset -go end" }, + { "<", "/fset -left" }, + { ">", "/fset -right" }, + { "t", "/fset -toggle" }, + { "-", "/fset -add -1" }, + { "+", "/fset -add 1" }, + { "r", "/fset -reset" }, + { "u", "/fset -unset" }, + { "s", "/fset -set" }, + { "n", "/fset -setnew" }, + { "a", "/fset -append" }, + { ",", "/fset -mark 1" }, + { "p", "/mute /set fset.look.show_plugins_desc toggle" }, + { "v", "/bar toggle " FSET_BAR_NAME }, + { "x", "/fset -format" }, + { NULL, NULL }, + }; + const char *ptr_input; + int i; + + /* make C compiler happy */ + (void) pointer; + (void) data; + + /* close buffer */ + if (strcmp (input_data, "q") == 0) + { + weechat_buffer_close (buffer); + return WEECHAT_RC_OK; + } + + /* refresh buffer */ + if (strcmp (input_data, "$") == 0) + { + fset_option_get_options (); + fset_buffer_refresh (0); + return WEECHAT_RC_OK; + } + + /* unmark all options and refresh buffer */ + if (strcmp (input_data, "$$") == 0) + { + fset_option_unmark_all (); + fset_option_get_options (); + fset_buffer_refresh (0); + return WEECHAT_RC_OK; + } + + /* mark options matching filter */ + if (strncmp (input_data, "m:", 2) == 0) + { + fset_option_mark_options_matching_filter (input_data + 2, 1); + return WEECHAT_RC_OK; + } + + /* unmark options matching filter */ + if (strncmp (input_data, "u:", 2) == 0) + { + fset_option_mark_options_matching_filter (input_data + 2, 0); + return WEECHAT_RC_OK; + } + + /* change sort of options */ + if (strncmp (input_data, "s:", 2) == 0) + { + if (input_data[2]) + weechat_config_option_set (fset_config_look_sort, input_data + 2, 1); + else + weechat_config_option_reset (fset_config_look_sort, 1); + return WEECHAT_RC_OK; + } + + /* export options in a file */ + if (strncmp (input_data, "w:", 2) == 0) + { + if (input_data[2]) + { + fset_option_export ( + input_data + 2, + weechat_config_boolean (fset_config_look_export_help_default)); + } + return WEECHAT_RC_OK; + } + + /* export options in a file (without help) */ + if (strncmp (input_data, "w-:", 3) == 0) + { + if (input_data[3]) + fset_option_export (input_data + 3, 0); + return WEECHAT_RC_OK; + } + + /* export options in a file (with help) */ + if (strncmp (input_data, "w+:", 3) == 0) + { + if (input_data[3]) + fset_option_export (input_data + 3, 1); + return WEECHAT_RC_OK; + } + + /* execute action on an option */ + for (i = 0; actions[i][0]; i++) + { + if (strcmp (input_data, actions[i][0]) == 0) + { + weechat_command (buffer, actions[i][1]); + return WEECHAT_RC_OK; + } + } + + /* filter options with given text */ + ptr_input = input_data; + while (ptr_input[0] == ' ') + { + ptr_input++; + } + if (ptr_input[0]) + fset_option_filter_options (ptr_input); + + return WEECHAT_RC_OK; +} + +/* + * Callback called when fset buffer is closed. + */ + +int +fset_buffer_close_cb (const void *pointer, void *data, + struct t_gui_buffer *buffer) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) buffer; + + fset_buffer = NULL; + fset_buffer_selected_line = 0; + weechat_arraylist_clear (fset_options); + fset_option_count_marked = 0; + + return WEECHAT_RC_OK; +} + +/* + * Restore buffer callbacks (input and close) for buffer created by fset + * plugin. + */ + +void +fset_buffer_set_callbacks () +{ + struct t_gui_buffer *ptr_buffer; + + ptr_buffer = weechat_buffer_search (FSET_PLUGIN_NAME, FSET_BUFFER_NAME); + if (ptr_buffer) + { + fset_buffer = ptr_buffer; + weechat_buffer_set_pointer (fset_buffer, "close_callback", &fset_buffer_close_cb); + weechat_buffer_set_pointer (fset_buffer, "input_callback", &fset_buffer_input_cb); + } +} + +/* + * Sets keys on fset buffer. + */ + +void +fset_buffer_set_keys () +{ + char *keys[][2] = { + { "meta2-A", "/fset -up" }, + { "meta2-B", "/fset -down" }, + { "meta-meta2-1~", "/fset -go 0" }, + { "meta-meta2-4~", "/fset -go end" }, + { "meta2-23~", "/fset -left" }, + { "meta2-24~", "/fset -right" }, + { "meta-space", "/fset -toggle" }, + { "meta--", "/fset -add -1" }, + { "meta-+", "/fset -add 1" }, + { "meta-fmeta-r", "/fset -reset" }, + { "meta-fmeta-u", "/fset -unset" }, + { "meta-ctrl-J", "/fset -set" }, + { "meta-ctrl-M", "/fset -set" }, + { "meta-fmeta-n", "/fset -setnew" }, + { "meta-fmeta-a", "/fset -append" }, + { "meta-,", "/fset -mark" }, + { "meta2-a", "/fset -up; /fset -mark" }, + { "meta2-b", "/fset -mark; /fset -down" }, + { "ctrl-L", "/fset -refresh" }, + { "meta-p", "/mute /set fset.look.show_plugins_desc toggle" }, + { "meta-v", "/bar toggle " FSET_BAR_NAME }, + { "ctrl-X", "/fset -format" }, + { NULL, NULL }, + }; + char str_key[64]; + int i; + + for (i = 0; keys[i][0]; i++) + { + if (weechat_config_boolean (fset_config_look_use_keys)) + { + snprintf (str_key, sizeof (str_key), "key_bind_%s", keys[i][0]); + weechat_buffer_set (fset_buffer, str_key, keys[i][1]); + } + else + { + snprintf (str_key, sizeof (str_key), "key_unbind_%s", keys[i][0]); + weechat_buffer_set (fset_buffer, str_key, ""); + } + } +} + +/* + * Sets the local variable "filter" in the fset buffer. + */ + +void +fset_buffer_set_localvar_filter () +{ + if (!fset_buffer) + return; + + weechat_buffer_set (fset_buffer, "localvar_set_filter", + (fset_option_filter) ? fset_option_filter : "*"); +} + +/* + * Opens fset buffer. + */ + +void +fset_buffer_open () +{ + if (!fset_buffer) + { + fset_buffer = weechat_buffer_new ( + FSET_BUFFER_NAME, + &fset_buffer_input_cb, NULL, NULL, + &fset_buffer_close_cb, NULL, NULL); + + /* failed to create buffer ? then exit */ + if (!fset_buffer) + return; + + weechat_buffer_set (fset_buffer, "type", "free"); + fset_buffer_set_keys (); + weechat_buffer_set (fset_buffer, "localvar_set_type", "option"); + fset_buffer_set_localvar_filter (); + + fset_buffer_selected_line = 0; + } +} + +/* + * Initializes fset buffer. + * + * Returns: + * 1: OK + * 0: error + */ + +int +fset_buffer_init () +{ + fset_buffer_set_callbacks (); + + /* create hashtables used by the bar item callback */ + fset_buffer_hashtable_pointers = weechat_hashtable_new ( + 8, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, + NULL, + NULL); + if (!fset_buffer_hashtable_pointers) + return 0; + + fset_buffer_hashtable_extra_vars = weechat_hashtable_new ( + 128, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, + NULL); + if (!fset_buffer_hashtable_extra_vars) + { + weechat_hashtable_free (fset_buffer_hashtable_pointers); + return 0; + } + + return 1; +} + +/* + * Ends fset buffer. + */ + +void +fset_buffer_end () +{ + weechat_hashtable_free (fset_buffer_hashtable_pointers); + fset_buffer_hashtable_pointers = NULL; + + weechat_hashtable_free (fset_buffer_hashtable_extra_vars); + fset_buffer_hashtable_extra_vars = NULL; +} diff --git a/src/plugins/fset/fset-buffer.h b/src/plugins/fset/fset-buffer.h new file mode 100644 index 000000000..bb6832e14 --- /dev/null +++ b/src/plugins/fset/fset-buffer.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef WEECHAT_PLUGIN_FSET_BUFFER_H +#define WEECHAT_PLUGIN_FSET_BUFFER_H + +#define FSET_BUFFER_NAME "fset" + +struct t_fset_option; + +extern struct t_gui_buffer *fset_buffer; +extern int fset_buffer_selected_line; + +extern void fset_buffer_set_title (); +extern void fset_buffer_display_option (struct t_fset_option *fset_option); +extern void fset_buffer_refresh (int clear); +extern void fset_buffer_set_current_line (int line); +extern void fset_buffer_check_line_outside_window (); +extern int fset_buffer_window_scrolled_cb (const void *pointer, + void *data, + const char *signal, + const char *type_data, + void *signal_data); +extern void fset_buffer_set_keys (); +extern void fset_buffer_set_localvar_filter (); +extern void fset_buffer_open (); +extern int fset_buffer_init (); +extern void fset_buffer_end (); + +#endif /* WEECHAT_PLUGIN_FSET_BUFFER_H */ diff --git a/src/plugins/fset/fset-command.c b/src/plugins/fset/fset-command.c new file mode 100644 index 000000000..67b6322d5 --- /dev/null +++ b/src/plugins/fset/fset-command.c @@ -0,0 +1,802 @@ +/* + * fset-command.c - Fast Set command + * + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "../weechat-plugin.h" +#include "fset.h" +#include "fset-command.h" +#include "fset-bar-item.h" +#include "fset-buffer.h" +#include "fset-config.h" +#include "fset-option.h" + + +/* + * Gets the currently selected fset_option pointer and the associated + * config_option pointer. + */ + +void +fset_command_get_option (struct t_fset_option **fset_option, + struct t_config_option **config_option) +{ + + *config_option = NULL; + + *fset_option = weechat_arraylist_get (fset_options, + fset_buffer_selected_line); + if (*fset_option) + *config_option = weechat_config_get ((*fset_option)->name); +} + +/* + * Gets an integer argument given to the /fset command. + */ + +int +fset_command_get_int_arg (int argc, char **argv, int arg_number, + int default_value) +{ + long value; + char *error; + + value = default_value; + if (argc > arg_number) + { + error = NULL; + value = strtol (argv[arg_number], &error, 10); + if (!error || error[0]) + value = default_value; + } + return (int)value; +} + +/* + * Callback for command "/fset". + */ + +int +fset_command_fset (const void *pointer, void *data, + struct t_gui_buffer *buffer, int argc, + char **argv, char **argv_eol) +{ + int num_options, line, value, i, with_help, min, max, format_number; + char str_command[512], str_number[64]; + const char *ptr_filename; + struct t_fset_option *ptr_fset_option; + struct t_config_option *ptr_option; + struct t_gui_window *ptr_window; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) buffer; + + if (argc == 1) + { + if (weechat_arraylist_size (fset_options) == 0) + { + fset_option_get_options (); + } + if (!fset_buffer) + { + fset_buffer_open (); + fset_buffer_refresh (1); + } + weechat_buffer_set (fset_buffer, "display", "1"); + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "-bar") == 0) + { + fset_add_bar (); + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "-refresh") == 0) + { + fset_option_get_options (); + fset_buffer_refresh (0); + weechat_command (NULL, "/window refresh"); + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "-up") == 0) + { + if (fset_buffer) + { + value = fset_command_get_int_arg (argc, argv, 2, 1); + num_options = weechat_arraylist_size (fset_options); + if (num_options > 0) + { + line = fset_buffer_selected_line - value; + if (line < 0) + line = 0; + if (line != fset_buffer_selected_line) + { + fset_buffer_set_current_line (line); + fset_buffer_check_line_outside_window (); + } + } + } + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "-down") == 0) + { + if (fset_buffer) + { + value = fset_command_get_int_arg (argc, argv, 2, 1); + num_options = weechat_arraylist_size (fset_options); + if (num_options > 0) + { + line = fset_buffer_selected_line + value; + if (line >= num_options) + line = num_options - 1; + if (line != fset_buffer_selected_line) + { + fset_buffer_set_current_line (line); + fset_buffer_check_line_outside_window (); + } + } + } + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "-left") == 0) + { + if (fset_buffer) + { + ptr_window = weechat_window_search_with_buffer (fset_buffer); + if (ptr_window) + { + value = fset_command_get_int_arg ( + argc, argv, 2, + weechat_config_integer (fset_config_look_scroll_horizontal)); + if (value < 1) + value = 1; + else if (value > 100) + value = 100; + snprintf (str_command, sizeof (str_command), + "/window scroll_horiz -window %d -%d%%", + weechat_window_get_integer (ptr_window, "number"), + value); + weechat_command (fset_buffer, str_command); + } + } + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "-right") == 0) + { + if (fset_buffer) + { + ptr_window = weechat_window_search_with_buffer (fset_buffer); + if (ptr_window) + { + value = fset_command_get_int_arg ( + argc, argv, 2, + weechat_config_integer (fset_config_look_scroll_horizontal)); + if (value < 1) + value = 1; + else if (value > 100) + value = 100; + snprintf (str_command, sizeof (str_command), + "/window scroll_horiz -window %d %d%%", + weechat_window_get_integer (ptr_window, "number"), + value); + weechat_command (fset_buffer, str_command); + } + } + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "-go") == 0) + { + if (fset_buffer) + { + if (argc < 3) + WEECHAT_COMMAND_ERROR; + if (weechat_strcasecmp (argv[2], "end") == 0) + line = weechat_arraylist_size (fset_options) - 1; + else + line = fset_command_get_int_arg (argc, argv, 2, -1); + if (line >= 0) + { + fset_buffer_set_current_line (line); + fset_buffer_check_line_outside_window (); + } + } + return WEECHAT_RC_OK; + } + + if (argv[1][0] == '-') + { + if (weechat_strcasecmp (argv[1], "-toggle") == 0) + { + if (fset_option_count_marked > 0) + { + num_options = weechat_arraylist_size (fset_options); + for (i = 0; i < num_options; i++) + { + ptr_fset_option = weechat_arraylist_get (fset_options, i); + if (ptr_fset_option && ptr_fset_option->marked) + { + ptr_option = weechat_config_get (ptr_fset_option->name); + if (ptr_option) + fset_option_toggle_value (ptr_fset_option, ptr_option); + } + } + } + else + { + fset_command_get_option (&ptr_fset_option, &ptr_option); + fset_option_toggle_value (ptr_fset_option, ptr_option); + } + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "-add") == 0) + { + value = fset_command_get_int_arg (argc, argv, 2, 0); + if (value == 0) + WEECHAT_COMMAND_ERROR; + + if (fset_option_count_marked > 0) + { + num_options = weechat_arraylist_size (fset_options); + for (i = 0; i < num_options; i++) + { + ptr_fset_option = weechat_arraylist_get (fset_options, i); + if (ptr_fset_option && ptr_fset_option->marked) + { + ptr_option = weechat_config_get (ptr_fset_option->name); + if (ptr_option) + fset_option_add_value (ptr_fset_option, ptr_option, value); + } + } + } + else + { + fset_command_get_option (&ptr_fset_option, &ptr_option); + if (ptr_fset_option && + ((ptr_fset_option->type == FSET_OPTION_TYPE_INTEGER) + || (ptr_fset_option->type == FSET_OPTION_TYPE_COLOR))) + { + fset_option_add_value (ptr_fset_option, ptr_option, value); + } + else + { + fset_option_set (ptr_fset_option, ptr_option, buffer, + (value > 0) ? 1 : 0); + } + } + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "-reset") == 0) + { + if (fset_option_count_marked > 0) + { + num_options = weechat_arraylist_size (fset_options); + for (i = 0; i < num_options; i++) + { + ptr_fset_option = weechat_arraylist_get (fset_options, i); + if (ptr_fset_option && ptr_fset_option->marked) + { + ptr_option = weechat_config_get (ptr_fset_option->name); + if (ptr_option) + fset_option_reset_value (ptr_fset_option, ptr_option); + } + } + } + else + { + fset_command_get_option (&ptr_fset_option, &ptr_option); + fset_option_reset_value (ptr_fset_option, ptr_option); + } + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "-unset") == 0) + { + if (fset_option_count_marked > 0) + { + num_options = weechat_arraylist_size (fset_options); + for (i = 0; i < num_options; i++) + { + ptr_fset_option = weechat_arraylist_get (fset_options, i); + if (ptr_fset_option && ptr_fset_option->marked) + { + ptr_option = weechat_config_get (ptr_fset_option->name); + if (ptr_option) + fset_option_unset_value (ptr_fset_option, ptr_option); + } + } + } + else + { + fset_command_get_option (&ptr_fset_option, &ptr_option); + fset_option_unset_value (ptr_fset_option, ptr_option); + } + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "-set") == 0) + { + fset_command_get_option (&ptr_fset_option, &ptr_option); + fset_option_set (ptr_fset_option, ptr_option, buffer, 0); + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "-setnew") == 0) + { + fset_command_get_option (&ptr_fset_option, &ptr_option); + fset_option_set (ptr_fset_option, ptr_option, buffer, -1); + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "-append") == 0) + { + fset_command_get_option (&ptr_fset_option, &ptr_option); + fset_option_set (ptr_fset_option, ptr_option, buffer, 1); + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "-mark") == 0) + { + fset_command_get_option (&ptr_fset_option, &ptr_option); + fset_option_toggle_mark (ptr_fset_option, ptr_option); + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "-format") == 0) + { + min = weechat_hdata_integer (fset_hdata_config_option, + fset_config_look_format_number, + "min"); + max = weechat_hdata_integer (fset_hdata_config_option, + fset_config_look_format_number, + "max"); + format_number = weechat_config_integer (fset_config_look_format_number) + 1; + if (format_number > max) + format_number = min; + snprintf (str_number, sizeof (str_number), "%d", format_number); + weechat_config_option_set (fset_config_look_format_number, + str_number, 1); + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "-export") == 0) + { + if (argc < 3) + WEECHAT_COMMAND_ERROR; + with_help = weechat_config_boolean (fset_config_look_export_help_default); + ptr_filename = argv_eol[2]; + if (weechat_strcasecmp (argv[2], "-help") == 0) + { + with_help = 1; + if (argc < 4) + WEECHAT_COMMAND_ERROR; + ptr_filename = argv_eol[3]; + } + else if (weechat_strcasecmp (argv[2], "-nohelp") == 0) + { + with_help = 0; + if (argc < 4) + WEECHAT_COMMAND_ERROR; + ptr_filename = argv_eol[3]; + } + num_options = weechat_arraylist_size (fset_options); + if (num_options == 0) + { + weechat_printf (NULL, + _("%s%s: there are no options displayed, " + "unable to export."), + weechat_prefix ("error"), FSET_PLUGIN_NAME); + return WEECHAT_RC_OK; + } + if (!fset_option_export (ptr_filename, with_help)) + WEECHAT_COMMAND_ERROR; + return WEECHAT_RC_OK; + } + + WEECHAT_COMMAND_ERROR; + } + else + { + /* set new filter */ + if (!fset_buffer) + fset_buffer_open (); + weechat_buffer_set (fset_buffer, "display", "1"); + fset_option_filter_options (argv_eol[1]); + } + + return WEECHAT_RC_OK; +} + +/* + * Hooks execution of command "/set". + */ + +int +fset_command_run_set_cb (const void *pointer, void *data, + struct t_gui_buffer *buffer, const char *command) +{ + char **argv, *old_filter, *result, str_number[64]; + const char *ptr_condition; + int rc, argc, old_count_marked, old_buffer_selected_line, condition_ok; + struct t_arraylist *old_options; + struct t_fset_option_max_length *old_max_length; + struct t_hashtable *eval_extra_vars, *eval_options; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) buffer; + + /* ignore /set command if issued on fset buffer */ + if (fset_buffer && (buffer == fset_buffer)) + return WEECHAT_RC_OK; + + if (strncmp (command, "/set", 4) != 0) + return WEECHAT_RC_OK; + + ptr_condition = weechat_config_string (fset_config_look_condition_catch_set); + if (!ptr_condition || !ptr_condition[0]) + return WEECHAT_RC_OK; + + rc = WEECHAT_RC_OK; + + argv = weechat_string_split (command, " ", 0, 0, &argc); + + if (argc > 2) + goto end; + + /* + * ignore "diff" and "env" arguments for /set + * (we must not catch that in fset!) + */ + if ((argc > 1) + && ((weechat_strcasecmp (argv[1], "diff") == 0) + || (weechat_strcasecmp (argv[1], "env") == 0))) + { + goto end; + } + + /* backup current options/max length field/selected line/filter */ + old_options = fset_options; + fset_options = fset_option_get_arraylist_options (); + old_count_marked = fset_option_count_marked; + old_max_length = fset_option_max_length; + fset_option_max_length = fset_option_get_max_length (); + old_filter = (fset_option_filter) ? strdup (fset_option_filter) : NULL; + fset_option_set_filter ((argc > 1) ? argv[1] : NULL); + old_buffer_selected_line = fset_buffer_selected_line; + fset_buffer_selected_line = 0; + + fset_option_get_options (); + + /* evaluate condition to catch /set command */ + condition_ok = 0; + eval_extra_vars = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, + NULL); + eval_options = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (eval_extra_vars && eval_options) + { + snprintf (str_number, sizeof (str_number), + "%d", weechat_arraylist_size (fset_options)); + weechat_hashtable_set (eval_extra_vars, "count", str_number); + weechat_hashtable_set (eval_extra_vars, "name", + (argc > 1) ? argv[1] : ""); + weechat_hashtable_set (eval_options, "type", "condition"); + result = weechat_string_eval_expression (ptr_condition, + NULL, + eval_extra_vars, + eval_options); + condition_ok = (result && (strcmp (result, "1") == 0)); + if (result) + free (result); + } + if (eval_extra_vars) + weechat_hashtable_free (eval_extra_vars); + if (eval_options) + weechat_hashtable_free (eval_options); + + /* check condition to trigger the fset buffer */ + if (condition_ok) + { + if (old_options) + weechat_arraylist_free (old_options); + if (old_max_length) + free (old_max_length); + if (old_filter) + free (old_filter); + + if (!fset_buffer) + fset_buffer_open (); + + fset_buffer_set_localvar_filter (); + fset_buffer_refresh (1); + weechat_buffer_set (fset_buffer, "display", "1"); + + rc = WEECHAT_RC_OK_EAT; + } + else + { + weechat_arraylist_free (fset_options); + fset_options = old_options; + fset_option_count_marked = old_count_marked; + free (fset_option_max_length); + fset_option_max_length = old_max_length; + fset_option_set_filter (old_filter); + if (old_filter) + free (old_filter); + fset_buffer_selected_line = old_buffer_selected_line; + } + +end: + if (argv) + weechat_string_free_split (argv); + + return rc; +} + +/* + * Hooks fset commands. + */ + +void +fset_command_init () +{ + weechat_hook_command ( + "fset", + N_("fast set WeeChat and plugins options"), + N_("-bar" + " || -refresh" + " || -up|-down [<number>]" + " || -left|-right [<percent>]" + " || -go <line>|end" + " || -toggle" + " || -add [<value>]" + " || -reset" + " || -unset" + " || -set" + " || -setnew" + " || -append" + " || -mark" + " || -format" + " || -export [-help|-nohelp] <filename>" + " || <filter>"), + N_(" -bar: add the help bar\n" + " -refresh: refresh list of options, then whole screen " + "(command: /window refresh)\n" + " -up: move the selected line up by \"number\" lines\n" + " -down: move the selected line down by \"number\" lines\n" + " -left: scroll the fset buffer by \"percent\" of width " + "on the left\n" + " -right: scroll the fset buffer by \"percent\" of width " + "on the right\n" + " -go: select a line by number, first line number is 0 " + "(\"end\" to select the last line)\n" + " -toggle: toggle the boolean value\n" + " -add: add \"value\" (which can be a negative number) " + "for integers and colors, set/append to value for other types " + "(set for a negative value, append for a positive value)\n" + " -reset: reset the value of option\n" + " -unset: unset the option\n" + " -set: add the /set command in input to edit the value of " + "option (move the cursor at the beginning of value)\n" + " -setnew: add the /set command in input to edit a new value " + "for the option\n" + " -append: add the /set command to append something in the value " + "of option (move the cursor at the end of value)\n" + " -mark: toggle mark\n" + " -format: switch to the next available format\n" + " -export: export the options and values displayed in a file " + "(each line has format: \"/set name value\" or \"/unset name\")\n" + " -help: force writing of help on options in exported file " + "(see /help fset.look.export_help_default)\n" + " -nohelp: do not write help on options in exported file " + "(see /help fset.look.export_help_default)\n" + " filter: set a new filter to see only matching options (this " + "filter can be used as input in fset buffer as well); allowed " + "formats are:\n" + " * show all options (no filter)\n" + " xxx show only options with \"xxx\" in name\n" + " f:xxx show only configuration file \"xxx\"\n" + " t:xxx show only type \"xxx\" (bool/int/str/col)\n" + " d show only changed options\n" + " d:xxx show only changed options with \"xxx\" in " + "name\n" + " d=xxx show only changed options with \"xxx\" in " + "value\n" + " d==xxx show only changed options with exact value " + "\"xxx\"\n" + " =xxx show only options with \"xxx\" in value\n" + " ==xxx show only options with exact value \"xxx\"\n" + " c:xxx show only options matching the evaluated " + "condition \"xxx\", using following variables: file, section, " + "option, name, parent_name, type, type_en, type_short " + "(bool/int/str/col), type_tiny (b/i/s/c), default_value, " + "default_value_undef, value, quoted_value, value_undef, " + "value_changed, parent_value, min, max, description, description2, " + "description_en, description_en2, string_values\n" + "\n" + "The lines with options are displayed using string evaluation " + "(see /help eval for the format), with these options:\n" + " - fset.format.option1: first format for an option\n" + " - fset.format.option2: second format for an option\n" + "\n" + "The following variables can be used in these options:\n" + " - option data, with color and padded by spaces on the right:\n" + " - ${file}: configuration file (for example \"weechat\" or " + "\"irc\")\n" + " - ${section}: section\n" + " - ${option}: option name\n" + " - ${name}: full option name (file.section.option)\n" + " - ${parent_name}: parent option name\n" + " - ${type}: option type (translated)\n" + " - ${type_en}: option type (in English)\n" + " - ${type_short}: short option type (bool/int/str/col)\n" + " - ${type_tiny}: tiny option type (b/i/s/c)\n" + " - ${default_value}: option default value\n" + " - ${default_value_undef}: \"1\" if default value is null, " + "otherwise \"0\"\n" + " - ${value}: option value\n" + " - ${value_undef}: \"1\" if value is null, otherwise \"0\"\n" + " - ${value_changed}: \"1\" if value is different from default " + "value, otherwise \"0\"\n" + " - ${value2}: option value, with inherited value if null\n" + " - ${parent_value}: parent option value\n" + " - ${min}: min value\n" + " - ${max}: max value\n" + " - ${description}: option description (translated)\n" + " - ${description2}: option description (translated), " + "\"(no description)\" (translated) if there's no description\n" + " - ${description_en}: option description (in English)\n" + " - ${description_en2}: option description (in English), " + "\"(no description)\" if there's no description\n" + " - ${string_values}: string values allowed for set of an " + "integer option using strings\n" + " - ${marked}: \"1\" if option is marked, otherwise \"0\"\n" + " - ${index}: index of option in list\n" + " - option data, with color but no spaces:\n" + " - same names prefixed by underscore, for example: ${_name}, " + "${_type}, ...\n" + " - option data, raw format (no colors/spaces):\n" + " - same names prefixed by two underscores, for example: " + "${__name}, ${__type}, ...\n" + " - option data, only spaces:\n" + " - same names prefixed with \"empty_\", for example: " + "${empty_name}, ${empty_type}\n" + " - other data:\n" + " - ${selected_line}: \"1\" if the line is selected, " + "otherwise \"0\"\n" + " - ${newline}: insert a new line at point, so the option is " + "displayed on multiple lines\n" + "\n" + "Keys and input to move in on fset buffer:\n" + " up move one line up\n" + " down move one line down\n" + " pgup move one page up\n" + " pgdn move one page down\n" + " alt-home << move to first line\n" + " alt-end >> move to last line\n" + " F11 < scroll horizontally on the left\n" + " F12 > scroll horizontally on the right\n" + "\n" + "Keys and input to set options on fset buffer:\n" + " alt+space t toggle boolean value\n" + " alt+'-' - subtract 1 from value for integer/color, " + "set value for other types\n" + " alt+'+' + add 1 to value for integer/color, append " + "to value for other types\n" + " alt+f, alt+r r reset value\n" + " alt+f, alt+u u unset value\n" + " alt+enter s set value\n" + " alt+f, alt+n n set new value\n" + " alt+f, alt+a a append to value\n" + " alt+',' , mark/unmark option\n" + " shift+up move one line up and mark/unmark option\n" + " shift+down mark/unmark option and move one line down\n" + " m:xxx mark options displayed that are " + "matching filter \"xxx\" (any filter on option or value is allowed, " + "see filters above)\n" + " u:xxx unmark options displayed that are " + "matching filter \"xxx\" (any filter on option or value is allowed, " + "see filters above)\n" + "\n" + "Other keys and input on fset buffer:\n" + " ctrl+L refresh options and whole screen " + "(command: /fset -refresh)\n" + " $ refresh options (keep marked options)\n" + " $$ refresh options (unmark all options)\n" + " alt+p p toggle plugin description options " + "(plugins.desc.*)\n" + " alt+v v toggle help bar\n" + " s:x,y sort options by fields x,y " + "(see /help fset.look.sort)\n" + " s: reset sort to its default value " + "(see /help fset.look.sort)\n" + " w:xxx export options in file \"xxx\"\n" + " w-:xxx export options in file \"xxx\" without help\n" + " w+:xxx export options in file \"xxx\" with help\n" + " ctrl+X x switch the format used to display options\n" + " q close fset buffer\n" + "\n" + "Mouse actions on fset buffer:\n" + " wheel up/down move line up/down\n" + " left button move line here\n" + " right button toggle boolean (on/off) or " + "edit the option value\n" + " right button + drag left/right increase/decrease value " + "for integer/color, set/append to value for other types\n" + " right button + drag up/down mark/unmark multiple options\n" + "\n" + "Note: if input has one or more leading spaces, the following text " + "is interpreted as a filter, without the spaces. For example " + "\" q\" searches all options with \"q\" inside name while \"q\" " + "closes the fset buffer.\n" + "\n" + "Examples:\n" + " show IRC options changed:\n" + " /fset d:irc.*\n" + " show all options with \"nicklist\" in name:\n" + " /fset nicklist\n" + " show all values which contain \"red\":\n" + " /fset =red\n" + " show all values which are exactly \"red\":\n" + " /fset ==red\n" + " show all integer options in irc plugin:\n" + " /fset c:${file} == irc && ${type_en} == integer"), + "-bar" + " || -refresh" + " || -up 1|2|3|4|5" + " || -down 1|2|3|4|5" + " || -left 10|20|30|40|50|60|70|80|90|100" + " || -right 10|20|30|40|50|60|70|80|90|100" + " || -go 0|end" + " || -toggle" + " || -add -1|1" + " || -reset" + " || -unset" + " || -set" + " || -setnew" + " || -append" + " || -mark" + " || -format" + " || -export -help|-nohelp|%(filename) %(filename)" + " || *|c:|f:|s:|d|d:|d=|d==|=|==|%(fset_options)", + &fset_command_fset, NULL, NULL); + weechat_hook_command_run ("/set", &fset_command_run_set_cb, NULL, NULL); +} diff --git a/src/plugins/fset/fset-command.h b/src/plugins/fset/fset-command.h new file mode 100644 index 000000000..10a929f52 --- /dev/null +++ b/src/plugins/fset/fset-command.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef WEECHAT_PLUGIN_FSET_COMMAND_H +#define WEECHAT_PLUGIN_FSET_COMMAND_H + +extern void fset_command_init (); + +#endif /* WEECHAT_PLUGIN_FSET_COMMAND_H */ diff --git a/src/plugins/fset/fset-completion.c b/src/plugins/fset/fset-completion.c new file mode 100644 index 000000000..dcca9c37c --- /dev/null +++ b/src/plugins/fset/fset-completion.c @@ -0,0 +1,119 @@ +/* + * fset-completion.c - completion for Fast Set commands + * + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> + +#include "../weechat-plugin.h" +#include "fset.h" + + +/* + * Adds current server to completion list. + */ + +int +fset_completion_option_cb (const void *pointer, void *data, + const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion) +{ + struct t_config_file *ptr_config; + struct t_config_section *ptr_section; + struct t_config_option *ptr_option; + char **words; + int config_section_added, num_words, i; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) completion_item; + (void) buffer; + + ptr_config = weechat_hdata_get_list (fset_hdata_config_file, + "config_files"); + while (ptr_config) + { + ptr_section = weechat_hdata_pointer (fset_hdata_config_file, + ptr_config, "sections"); + while (ptr_section) + { + config_section_added = 0; + ptr_option = weechat_hdata_pointer (fset_hdata_config_section, + ptr_section, "options"); + while (ptr_option) + { + if (!config_section_added) + { + weechat_hook_completion_list_add ( + completion, + weechat_config_option_get_string (ptr_option, + "config_name"), + 0, WEECHAT_LIST_POS_SORT); + weechat_hook_completion_list_add ( + completion, + weechat_config_option_get_string (ptr_option, + "section_name"), + 0, WEECHAT_LIST_POS_SORT); + config_section_added = 1; + } + weechat_hook_completion_list_add ( + completion, + weechat_config_option_get_string (ptr_option, "name"), + 0, + WEECHAT_LIST_POS_SORT); + words = weechat_string_split ( + weechat_config_option_get_string (ptr_option, "name"), + "_", 0, 0, &num_words); + if (words && (num_words > 1)) + { + for (i = 0; i < num_words; i++) + { + weechat_hook_completion_list_add ( + completion, words[i], 0, WEECHAT_LIST_POS_SORT); + } + } + if (words) + weechat_string_free_split (words); + ptr_option = weechat_hdata_move (fset_hdata_config_option, + ptr_option, 1); + } + ptr_section = weechat_hdata_move (fset_hdata_config_section, + ptr_section, 1); + } + ptr_config = weechat_hdata_move (fset_hdata_config_file, + ptr_config, 1); + } + + return WEECHAT_RC_OK; +} + +/* + * Hooks completions. + */ + +void +fset_completion_init () +{ + weechat_hook_completion ("fset_options", + N_("configuration files, sections, options and " + "words of options"), + &fset_completion_option_cb, NULL, NULL); +} diff --git a/src/plugins/fset/fset-completion.h b/src/plugins/fset/fset-completion.h new file mode 100644 index 000000000..76bcd143b --- /dev/null +++ b/src/plugins/fset/fset-completion.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef WEECHAT_PLUGIN_FSET_COMPLETION_H +#define WEECHAT_PLUGIN_FSET_COMPLETION_H + +extern void fset_completion_init (); + +#endif /* WEECHAT_PLUGIN_FSET_COMPLETION_H */ diff --git a/src/plugins/fset/fset-config.c b/src/plugins/fset/fset-config.c new file mode 100644 index 000000000..2796e8383 --- /dev/null +++ b/src/plugins/fset/fset-config.c @@ -0,0 +1,1096 @@ +/* + * fset-config.c - Fast Set configuration options (file fset.conf) + * + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <string.h> + +#include "../weechat-plugin.h" +#include "fset.h" +#include "fset-config.h" +#include "fset-bar-item.h" +#include "fset-buffer.h" +#include "fset-option.h" + + +struct t_config_file *fset_config_file = NULL; + +/* fset config, look section */ + +struct t_config_option *fset_config_look_auto_unmark; +struct t_config_option *fset_config_look_condition_catch_set; +struct t_config_option *fset_config_look_export_help_default; +struct t_config_option *fset_config_look_format_number; +struct t_config_option *fset_config_look_marked_string; +struct t_config_option *fset_config_look_scroll_horizontal; +struct t_config_option *fset_config_look_show_plugins_desc; +struct t_config_option *fset_config_look_sort; +struct t_config_option *fset_config_look_unmarked_string; +struct t_config_option *fset_config_look_use_color_value; +struct t_config_option *fset_config_look_use_keys; +struct t_config_option *fset_config_look_use_mute; + +/* fset config, format section */ + +struct t_config_option *fset_config_format_option[2]; +struct t_config_option *fset_config_format_export_help; +struct t_config_option *fset_config_format_export_option; +struct t_config_option *fset_config_format_export_option_null; + +/* fset config, color section */ + +struct t_config_option *fset_config_color_default_value[2]; +struct t_config_option *fset_config_color_description[2]; +struct t_config_option *fset_config_color_file[2]; +struct t_config_option *fset_config_color_file_changed[2]; +struct t_config_option *fset_config_color_help_default_value; +struct t_config_option *fset_config_color_help_description; +struct t_config_option *fset_config_color_help_name; +struct t_config_option *fset_config_color_help_quotes; +struct t_config_option *fset_config_color_help_values; +struct t_config_option *fset_config_color_index[2]; +struct t_config_option *fset_config_color_line_marked_bg[2]; +struct t_config_option *fset_config_color_line_selected_bg[2]; +struct t_config_option *fset_config_color_marked[2]; +struct t_config_option *fset_config_color_max[2]; +struct t_config_option *fset_config_color_min[2]; +struct t_config_option *fset_config_color_name[2]; +struct t_config_option *fset_config_color_name_changed[2]; +struct t_config_option *fset_config_color_option[2]; +struct t_config_option *fset_config_color_option_changed[2]; +struct t_config_option *fset_config_color_parent_name[2]; +struct t_config_option *fset_config_color_parent_value[2]; +struct t_config_option *fset_config_color_quotes[2]; +struct t_config_option *fset_config_color_quotes_changed[2]; +struct t_config_option *fset_config_color_section[2]; +struct t_config_option *fset_config_color_section_changed[2]; +struct t_config_option *fset_config_color_string_values[2]; +struct t_config_option *fset_config_color_title_count_options; +struct t_config_option *fset_config_color_title_current_option; +struct t_config_option *fset_config_color_title_filter; +struct t_config_option *fset_config_color_title_marked_options; +struct t_config_option *fset_config_color_title_sort; +struct t_config_option *fset_config_color_type[2]; +struct t_config_option *fset_config_color_unmarked[2]; +struct t_config_option *fset_config_color_value[2]; +struct t_config_option *fset_config_color_value_changed[2]; +struct t_config_option *fset_config_color_value_undef[2]; + +char **fset_config_sort_fields = NULL; +int fset_config_sort_fields_count = 0; +int fset_config_format_option_num_lines[2] = { 1, 1 }; + + +/* + * Callback for changes on option "fset.look.format_number". + */ + +void +fset_config_change_format_number_cb (const void *pointer, void *data, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) option; + + fset_buffer_refresh (1); + fset_buffer_check_line_outside_window (); +} + +/* + * Callback for changes on option "fset.look.show_plugins_desc". + */ + +void +fset_config_change_show_plugins_desc_cb (const void *pointer, void *data, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) option; + + if (fset_buffer) + { + fset_option_get_options (); + fset_buffer_refresh (1); + } +} + +/* + * Callback for changes on option "fset.look.sort". + */ + +void +fset_config_change_sort_cb (const void *pointer, void *data, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) option; + + if (fset_config_sort_fields) + weechat_string_free_split (fset_config_sort_fields); + + fset_config_sort_fields = weechat_string_split ( + weechat_config_string (fset_config_look_sort), + ",", 0, 0, &fset_config_sort_fields_count); + + if (fset_buffer) + { + fset_option_get_options (); + fset_buffer_refresh (0); + } +} + +/* + * Callback for changes on option "fset.look.use_color_value". + */ + +void +fset_config_change_use_color_value_cb (const void *pointer, void *data, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) option; + + fset_buffer_refresh (0); +} + +/* + * Callback for changes on option "fset.look.use_keys". + */ + +void +fset_config_change_use_keys_cb (const void *pointer, void *data, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) option; + + if (fset_buffer) + fset_buffer_set_keys (); +} + +/* + * Counts the number of "substring" in "string". + * + * Returns the number of times substring is in string. + */ + +int +fset_config_count_substring (const char *string, + const char *substring) +{ + int count, length; + const char *pos; + + count = 0; + length = strlen (substring); + pos = string; + while (pos && pos[0]) + { + pos = strstr (pos, substring); + if (!pos) + break; + count++; + pos += length; + } + + return count; +} + +/* + * Callback for changes on format options. + */ + +void +fset_config_change_format_cb (const void *pointer, void *data, + struct t_config_option *option) +{ + int i; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) option; + + for (i = 0; i < 2; i++) + { + fset_config_format_option_num_lines[i] = fset_config_count_substring ( + weechat_config_string (fset_config_format_option[i]), "${newline}") + 1; + } + + fset_buffer_refresh (1); + fset_buffer_check_line_outside_window (); +} + +/* + * Callback for changes on help color options. + */ + +void +fset_config_change_help_color_cb (const void *pointer, void *data, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) option; + + fset_bar_item_update (); +} + +/* + * Callback for changes on color options. + */ + +void +fset_config_change_color_cb (const void *pointer, void *data, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) option; + + fset_buffer_refresh (0); +} + +/* + * Callback for changes on title color options. + */ + +void +fset_config_change_title_color_cb (const void *pointer, void *data, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) option; + + fset_buffer_set_title (); +} + +/* + * Initializes fset configuration file. + * + * Returns: + * 1: OK + * 0: error + */ + +int +fset_config_init () +{ + struct t_config_section *ptr_section; + + fset_config_file = weechat_config_new (FSET_CONFIG_NAME, + NULL, NULL, NULL); + if (!fset_config_file) + return 0; + + /* look */ + ptr_section = weechat_config_new_section (fset_config_file, "look", + 0, 0, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + if (!ptr_section) + { + weechat_config_free (fset_config_file); + fset_config_file = NULL; + return 0; + } + + fset_config_look_auto_unmark = weechat_config_new_option ( + fset_config_file, ptr_section, + "auto_unmark", "boolean", + N_("automatically unmark all options after an action on marked " + "options or after a refresh"), + NULL, 0, 0, "off", NULL, 0, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + fset_config_look_condition_catch_set = weechat_config_new_option ( + fset_config_file, ptr_section, + "condition_catch_set", "string", + N_("condition to catch /set command and display results in the fset " + "buffer; following variables can be used: ${name} (name of option " + "given for the /set command), ${count} (number of options found " + "with the /set argument); an empty string disables the catch of " + "/set command; with value \"1\", the fset buffer is always used " + "with /set command"), + NULL, 0, 0, "${count} >= 1", NULL, 0, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + fset_config_look_export_help_default = weechat_config_new_option ( + fset_config_file, ptr_section, + "export_help_default", "boolean", + N_("write help for each option exported by default (this can be " + "overridden with arguments \"-help\" and \"-nohelp\" for command " + "/fset -export)"), + NULL, 0, 0, "on", NULL, 0, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + fset_config_look_format_number = weechat_config_new_option ( + fset_config_file, ptr_section, + "format_number", "integer", + N_("number of format used to display options; this is dynamically " + "changed by the key ctrl-X on the fset buffer"), + NULL, 1, 2, "1", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_format_number_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_look_marked_string = weechat_config_new_option ( + fset_config_file, ptr_section, + "marked_string", "string", + N_("string displayed when an option is marked (to do an action on " + "multiple options)"), + NULL, 0, 0, "*", NULL, 0, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + fset_config_look_scroll_horizontal = weechat_config_new_option ( + fset_config_file, ptr_section, + "scroll_horizontal", "integer", + N_("left/right scroll in fset buffer (percent of width)"), + NULL, 1, 100, "10", NULL, 0, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + fset_config_look_show_plugins_desc = weechat_config_new_option ( + fset_config_file, ptr_section, + "show_plugins_desc", "boolean", + N_("show the plugin description options (plugins.desc.*)"), + NULL, 0, 0, "off", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_show_plugins_desc_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_look_sort = weechat_config_new_option ( + fset_config_file, ptr_section, + "sort", "string", + N_("comma-separated list of fields to sort options (see /help fset " + "for a list of fields); char \"-\" can be used before field to " + "reverse order, char \"~\" can be used to do a case insensitive " + "comparison; example: \"-~name\" for case insensitive and reverse " + "sort on option name"), + NULL, 0, 0, "~name", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_sort_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_look_unmarked_string = weechat_config_new_option ( + fset_config_file, ptr_section, + "unmarked_string", "string", + N_("string displayed when an option is not marked"), + NULL, 0, 0, " ", NULL, 0, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + fset_config_look_use_color_value = weechat_config_new_option ( + fset_config_file, ptr_section, + "use_color_value", "boolean", + N_("use the color to display value of color options"), + NULL, 0, 0, "off", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_use_color_value_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_look_use_keys = weechat_config_new_option ( + fset_config_file, ptr_section, + "use_keys", "boolean", + N_("use keys alt+X in fset buffer to do actions on options; " + "if disabled, only the input is allowed"), + NULL, 0, 0, "on", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_use_keys_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_look_use_mute = weechat_config_new_option ( + fset_config_file, ptr_section, + "use_mute", "boolean", + N_("use /mute command to set options"), + NULL, 0, 0, "off", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_use_keys_cb, NULL, NULL, + NULL, NULL, NULL); + + /* format */ + ptr_section = weechat_config_new_section (fset_config_file, "format", + 0, 0, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + if (!ptr_section) + { + weechat_config_free (fset_config_file); + fset_config_file = NULL; + return 0; + } + + fset_config_format_option[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "option1", "string", + N_("first format of each line with an option which is not marked " + "nor the selected one " + "(note: content is evaluated, see /help fset); " + "an empty string uses the default format " + "(\"${marked} ${name} ${type} ${value2}\"), which is without " + "evaluation of string and then much faster; " + "formats can be switched with key ctrl+X"), + NULL, 0, 0, + "", + NULL, 0, + NULL, NULL, NULL, + &fset_config_change_format_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_format_option[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "option2", "string", + N_("second format of each line with an option which is not marked " + "not the selected one " + "(note: content is evaluated, see /help fset); " + "an empty string uses the default format " + "(\"${marked} ${name} ${type} ${value2}\"), which is without " + "evaluation of string and then much faster; " + "formats can be switched with key ctrl+X"), + NULL, 0, 0, + "${marked} ${name} ${type} ${value2}${newline}" + " ${empty_name} ${_default_value}${color:darkgray} -- " + "${min}..${max}${newline}" + " ${empty_name} ${description}", + NULL, 0, + NULL, NULL, NULL, + &fset_config_change_format_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_format_export_help = weechat_config_new_option ( + fset_config_file, ptr_section, + "export_help", "string", + N_("format of help line written before each option exported in a file " + "(note: content is evaluated, see /help fset)"), + NULL, 0, 0, + "# ${description2}", + NULL, 0, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + fset_config_format_export_option = weechat_config_new_option ( + fset_config_file, ptr_section, + "export_option", "string", + N_("format of each option exported in a file " + "(note: content is evaluated, see /help fset)"), + NULL, 0, 0, + "/set ${name} ${quoted_value}", + NULL, 0, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + fset_config_format_export_option_null = weechat_config_new_option ( + fset_config_file, ptr_section, + "export_option_null", "string", + N_("format of each option with \"null\" value exported in a file " + "(note: content is evaluated, see /help fset)"), + NULL, 0, 0, + "/unset ${name}", + NULL, 0, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + + /* color */ + ptr_section = weechat_config_new_section (fset_config_file, "color", + 0, 0, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + if (!ptr_section) + { + weechat_config_free (fset_config_file); + fset_config_file = NULL; + return 0; + } + + fset_config_color_default_value[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "default_value", "color", + N_("color for default value"), + NULL, 0, 0, "default", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_default_value[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "default_value_selected", "color", + N_("color for default value on the selected line"), + NULL, 0, 0, "white", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_description[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "description", "color", + N_("color for description"), + NULL, 0, 0, "default", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_description[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "description_selected", "color", + N_("color for description on the selected line"), + NULL, 0, 0, "white", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_file[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "file", "color", + N_("color for file"), + NULL, 0, 0, "default", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_file[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "file_selected", "color", + N_("color for file on the selected line"), + NULL, 0, 0, "white", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_file_changed[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "file_changed", "color", + N_("color for file if value is changed"), + NULL, 0, 0, "brown", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_file_changed[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "file_changed_selected", "color", + N_("color for file if value is changed on the selected line"), + NULL, 0, 0, "yellow", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_help_default_value = weechat_config_new_option ( + fset_config_file, ptr_section, + "help_default_value", "color", + N_("color for default value in help bar"), + NULL, 0, 0, "white", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_help_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_help_description = weechat_config_new_option ( + fset_config_file, ptr_section, + "help_description", "color", + N_("color for description in help bar"), + NULL, 0, 0, "default", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_help_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_help_name = weechat_config_new_option ( + fset_config_file, ptr_section, + "help_name", "color", + N_("color for name in help bar"), + NULL, 0, 0, "white", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_help_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_help_quotes = weechat_config_new_option ( + fset_config_file, ptr_section, + "help_quotes", "color", + N_("color for quotes around string values"), + NULL, 0, 0, "darkgray", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_help_values = weechat_config_new_option ( + fset_config_file, ptr_section, + "help_values", "color", + N_("color for allowed values"), + NULL, 0, 0, "default", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_index[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "index", "color", + N_("color for index of option"), + NULL, 0, 0, "cyan", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_index[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "index_selected", "color", + N_("color for index of option on the selected line"), + NULL, 0, 0, "lightcyan", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_line_marked_bg[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "line_marked_bg1", "color", + N_("background color for a marked line " + "(used with the first format, see option fset.format.option1)"), + NULL, 0, 0, "default", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_line_marked_bg[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "line_marked_bg2", "color", + N_("background color for a marked line " + "(used with the second format, see option fset.format.option2)"), + NULL, 0, 0, "default", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_line_selected_bg[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "line_selected_bg1", "color", + N_("background color for the selected line " + "(used with the first format, see option fset.format.option1)"), + NULL, 0, 0, "blue", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_line_selected_bg[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "line_selected_bg2", "color", + N_("background color for the selected line " + "(used with the second format, see option fset.format.option2)"), + NULL, 0, 0, "red", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_marked[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "marked", "color", + N_("color for mark indicator"), + NULL, 0, 0, "brown", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_marked[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "marked_selected", "color", + N_("color for mark indicator on the selected line"), + NULL, 0, 0, "yellow", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_max[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "max", "color", + N_("color for max value"), + NULL, 0, 0, "default", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_max[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "max_selected", "color", + N_("color for max value on the selected line"), + NULL, 0, 0, "white", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_min[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "min", "color", + N_("color for min value"), + NULL, 0, 0, "default", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_min[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "min_selected", "color", + N_("color for min value on the selected line"), + NULL, 0, 0, "white", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_name[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "name", "color", + N_("color for name"), + NULL, 0, 0, "default", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_name[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "name_selected", "color", + N_("color for name on the selected line"), + NULL, 0, 0, "white", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_name_changed[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "name_changed", "color", + N_("color for name if value is changed"), + NULL, 0, 0, "brown", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_name_changed[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "name_changed_selected", "color", + N_("color for name if value is changed on the selected line"), + NULL, 0, 0, "yellow", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_option[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "option", "color", + N_("color for option"), + NULL, 0, 0, "default", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_option[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "option_selected", "color", + N_("color for option on the selected line"), + NULL, 0, 0, "white", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_option_changed[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "option_changed", "color", + N_("color for option if value is changed"), + NULL, 0, 0, "brown", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_option_changed[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "option_changed_selected", "color", + N_("color for option if value is changed on the selected line"), + NULL, 0, 0, "yellow", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_parent_name[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "parent_name", "color", + N_("color for name of parent option"), + NULL, 0, 0, "default", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_parent_name[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "parent_name_selected", "color", + N_("color for name of parent option on the selected line"), + NULL, 0, 0, "white", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_parent_value[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "parent_value", "color", + N_("color for value of parent option"), + NULL, 0, 0, "cyan", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_parent_value[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "parent_value_selected", "color", + N_("color for value of parent option on the selected line"), + NULL, 0, 0, "lightcyan", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_quotes[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "quotes", "color", + N_("color for quotes around string values"), + NULL, 0, 0, "darkgray", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_quotes[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "quotes_selected", "color", + N_("color for quotes around string values on the selected line"), + NULL, 0, 0, "default", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_quotes_changed[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "quotes_changed", "color", + N_("color for quotes around string values which are changed"), + NULL, 0, 0, "default", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_quotes_changed[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "quotes_changed_selected", "color", + N_("color for quotes around string values which are changed " + "on the selected line"), + NULL, 0, 0, "white", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_section[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "section", "color", + N_("color for section"), + NULL, 0, 0, "default", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_section[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "section_selected", "color", + N_("color for section on the selected line"), + NULL, 0, 0, "white", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_section_changed[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "section_changed", "color", + N_("color for section if value is changed"), + NULL, 0, 0, "brown", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_section_changed[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "section_changed_selected", "color", + N_("color for section if value is changed on the selected line"), + NULL, 0, 0, "yellow", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_string_values[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "string_values", "color", + N_("color for string values"), + NULL, 0, 0, "default", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_string_values[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "string_values_selected", "color", + N_("color for string values on the selected line"), + NULL, 0, 0, "white", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_title_count_options = weechat_config_new_option ( + fset_config_file, ptr_section, + "title_count_options", "color", + N_("color for the count of options found with the current filter " + "in title of buffer"), + NULL, 0, 0, "cyan", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_title_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_title_current_option = weechat_config_new_option ( + fset_config_file, ptr_section, + "title_current_option", "color", + N_("color for current option number in title of buffer"), + NULL, 0, 0, "lightcyan", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_title_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_title_filter = weechat_config_new_option ( + fset_config_file, ptr_section, + "title_filter", "color", + N_("color for filter in title of buffer"), + NULL, 0, 0, "yellow", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_title_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_title_marked_options = weechat_config_new_option ( + fset_config_file, ptr_section, + "title_marked_options", "color", + N_("color for number of marked options in title of buffer"), + NULL, 0, 0, "lightgreen", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_title_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_title_sort = weechat_config_new_option ( + fset_config_file, ptr_section, + "title_sort", "color", + N_("color for sort in title of buffer"), + NULL, 0, 0, "white", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_title_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_type[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "type", "color", + N_("color for type"), + NULL, 0, 0, "green", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_type[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "type_selected", "color", + N_("color for type on the selected line"), + NULL, 0, 0, "lightgreen", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_unmarked[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "unmarked", "color", + N_("color for mark indicator when the option is not marked"), + NULL, 0, 0, "default", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_unmarked[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "unmarked_selected", "color", + N_("color for mark indicator when the option is not marked " + "on the selected line"), + NULL, 0, 0, "white", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_value[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "value", "color", + N_("color for value"), + NULL, 0, 0, "cyan", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_value[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "value_selected", "color", + N_("color for value on the selected line"), + NULL, 0, 0, "lightcyan", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_value_changed[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "value_changed", "color", + N_("color for value changed (different from default)"), + NULL, 0, 0, "brown", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_value_changed[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "value_changed_selected", "color", + N_("color for value changed (different from default) on the selected " + "line"), + NULL, 0, 0, "yellow", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_value_undef[0] = weechat_config_new_option ( + fset_config_file, ptr_section, + "value_undef", "color", + N_("color for undefined value"), + NULL, 0, 0, "magenta", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + fset_config_color_value_undef[1] = weechat_config_new_option ( + fset_config_file, ptr_section, + "value_undef_selected", "color", + N_("color for undefined value on the selected line"), + NULL, 0, 0, "lightmagenta", NULL, 0, + NULL, NULL, NULL, + &fset_config_change_color_cb, NULL, NULL, + NULL, NULL, NULL); + + return 1; +} + +/* + * Reads fset configuration file. + */ + +int +fset_config_read () +{ + int rc; + + rc = weechat_config_read (fset_config_file); + + if (rc == WEECHAT_CONFIG_READ_OK) + { + fset_config_change_sort_cb (NULL, NULL, NULL); + fset_config_change_format_cb (NULL, NULL, NULL); + } + + return rc; +} + +/* + * Writes fset configuration file. + */ + +int +fset_config_write () +{ + return weechat_config_write (fset_config_file); +} + +/* + * Frees fset configuration. + */ + +void +fset_config_free () +{ + weechat_config_free (fset_config_file); + + if (fset_config_sort_fields) + { + weechat_string_free_split (fset_config_sort_fields); + fset_config_sort_fields = NULL; + fset_config_sort_fields_count = 0; + } +} diff --git a/src/plugins/fset/fset-config.h b/src/plugins/fset/fset-config.h new file mode 100644 index 000000000..5f4f83ecb --- /dev/null +++ b/src/plugins/fset/fset-config.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef WEECHAT_PLUGIN_FSET_CONFIG_H +#define WEECHAT_PLUGIN_FSET_CONFIG_H + +#define FSET_CONFIG_NAME "fset" + +extern struct t_config_file *fset_config_file; + +extern struct t_config_option *fset_config_look_auto_unmark; +extern struct t_config_option *fset_config_look_condition_catch_set; +extern struct t_config_option *fset_config_look_export_help_default; +extern struct t_config_option *fset_config_look_format_number; +extern struct t_config_option *fset_config_look_marked_string; +extern struct t_config_option *fset_config_look_scroll_horizontal; +extern struct t_config_option *fset_config_look_show_plugins_desc; +extern struct t_config_option *fset_config_look_sort; +extern struct t_config_option *fset_config_look_unmarked_string; +extern struct t_config_option *fset_config_look_use_color_value; +extern struct t_config_option *fset_config_look_use_keys; +extern struct t_config_option *fset_config_look_use_mute; + +extern struct t_config_option *fset_config_format_option[2]; +extern struct t_config_option *fset_config_format_export_help; +extern struct t_config_option *fset_config_format_export_option; +extern struct t_config_option *fset_config_format_export_option_null; + +extern struct t_config_option *fset_config_color_default_value[2]; +extern struct t_config_option *fset_config_color_description[2]; +extern struct t_config_option *fset_config_color_file[2]; +extern struct t_config_option *fset_config_color_file_changed[2]; +extern struct t_config_option *fset_config_color_help_default_value; +extern struct t_config_option *fset_config_color_help_description; +extern struct t_config_option *fset_config_color_help_name; +extern struct t_config_option *fset_config_color_help_quotes; +extern struct t_config_option *fset_config_color_help_values; +extern struct t_config_option *fset_config_color_index[2]; +extern struct t_config_option *fset_config_color_line_marked_bg[2]; +extern struct t_config_option *fset_config_color_line_selected_bg[2]; +extern struct t_config_option *fset_config_color_marked[2]; +extern struct t_config_option *fset_config_color_max[2]; +extern struct t_config_option *fset_config_color_min[2]; +extern struct t_config_option *fset_config_color_name[2]; +extern struct t_config_option *fset_config_color_name_changed[2]; +extern struct t_config_option *fset_config_color_option[2]; +extern struct t_config_option *fset_config_color_option_changed[2]; +extern struct t_config_option *fset_config_color_parent_name[2]; +extern struct t_config_option *fset_config_color_parent_value[2]; +extern struct t_config_option *fset_config_color_quotes[2]; +extern struct t_config_option *fset_config_color_quotes_changed[2]; +extern struct t_config_option *fset_config_color_section[2]; +extern struct t_config_option *fset_config_color_section_changed[2]; +extern struct t_config_option *fset_config_color_string_values[2]; +extern struct t_config_option *fset_config_color_title_count_options; +extern struct t_config_option *fset_config_color_title_current_option; +extern struct t_config_option *fset_config_color_title_filter; +extern struct t_config_option *fset_config_color_title_marked_options; +extern struct t_config_option *fset_config_color_title_sort; +extern struct t_config_option *fset_config_color_type[2]; +extern struct t_config_option *fset_config_color_unmarked[2]; +extern struct t_config_option *fset_config_color_value[2]; +extern struct t_config_option *fset_config_color_value_changed[2]; +extern struct t_config_option *fset_config_color_value_undef[2]; + +extern char **fset_config_sort_fields; +extern int fset_config_sort_fields_count; +extern int fset_config_format_option_num_lines[2]; + +extern int fset_config_init (); +extern int fset_config_read (); +extern int fset_config_write (); +extern void fset_config_free (); + +#endif /* WEECHAT_PLUGIN_FSET_CONFIG_H */ diff --git a/src/plugins/fset/fset-info.c b/src/plugins/fset/fset-info.c new file mode 100644 index 000000000..f78a00de0 --- /dev/null +++ b/src/plugins/fset/fset-info.c @@ -0,0 +1,112 @@ +/* + * fset-info.c - info, infolist and hdata hooks for Fast Set plugin + * + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "../weechat-plugin.h" +#include "fset.h" +#include "fset-option.h" + + +/* + * Returns fset infolist "fset_option". + */ + +struct t_infolist * +fset_info_infolist_fset_option_cb (const void *pointer, void *data, + const char *infolist_name, + void *obj_pointer, + const char *arguments) +{ + struct t_infolist *ptr_infolist; + struct t_fset_option *ptr_fset_option; + int num_options, i; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) infolist_name; + + if (obj_pointer && !fset_option_valid (obj_pointer)) + return NULL; + + ptr_infolist = weechat_infolist_new (); + if (!ptr_infolist) + return NULL; + + if (obj_pointer) + { + /* build list with only one option */ + if (!fset_option_add_to_infolist (ptr_infolist, obj_pointer)) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + return ptr_infolist; + } + else + { + /* build list with all options matching arguments */ + num_options = weechat_arraylist_size (fset_options); + for (i = 0; i < num_options; i++) + { + ptr_fset_option = weechat_arraylist_get (fset_options, i); + if (ptr_fset_option + && (!arguments || !arguments[0] + || weechat_string_match (ptr_fset_option->name, + arguments, 0))) + { + if (!fset_option_add_to_infolist (ptr_infolist, ptr_fset_option)) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + } + } + return ptr_infolist; + } + + return NULL; +} + +/* + * Hooks infolist and hdata. + */ + +void +fset_info_init () +{ + /* infolist hooks */ + weechat_hook_infolist ( + "fset_option", + N_("list of fset options"), + N_("fset option pointer (optional)"), + N_("option name " + "(wildcard \"*\" is allowed) (optional)"), + &fset_info_infolist_fset_option_cb, NULL, NULL); + + /* hdata hooks */ + weechat_hook_hdata ( + "fset_option", N_("fset options"), + &fset_option_hdata_option_cb, NULL, NULL); +} diff --git a/src/plugins/fset/fset-info.h b/src/plugins/fset/fset-info.h new file mode 100644 index 000000000..6f30036f9 --- /dev/null +++ b/src/plugins/fset/fset-info.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef WEECHAT_PLUGIN_FSET_INFO_H +#define WEECHAT_PLUGIN_FSET_INFO_H + +extern void fset_info_init (); + +#endif /* WEECHAT_PLUGIN_FSET_INFO_H */ diff --git a/src/plugins/fset/fset-mouse.c b/src/plugins/fset/fset-mouse.c new file mode 100644 index 000000000..266ad75d9 --- /dev/null +++ b/src/plugins/fset/fset-mouse.c @@ -0,0 +1,361 @@ +/* + * fset-mouse.c - mouse actions for Fast Set plugin + * + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "../weechat-plugin.h" +#include "fset.h" +#include "fset-mouse.h" +#include "fset-bar-item.h" +#include "fset-buffer.h" +#include "fset-config.h" +#include "fset-option.h" + + +/* + * Callback called when a mouse action occurs in fset bar item. + */ + +struct t_hashtable * +fset_mouse_focus_cb (const void *pointer, void *data, struct t_hashtable *info) +{ + const char *buffer; + int rc; + long unsigned int value; + struct t_gui_buffer *ptr_buffer; + long y; + char *error, str_value[128]; + struct t_fset_option *ptr_fset_option; + + /* make C compiler happy */ + (void) pointer; + (void) data; + + if (!fset_buffer) + return info; + + buffer = weechat_hashtable_get (info, "_buffer"); + if (!buffer) + return info; + + rc = sscanf (buffer, "%lx", &value); + if ((rc == EOF) || (rc == 0)) + return info; + + ptr_buffer = (struct t_gui_buffer *)value; + + if (!ptr_buffer || (ptr_buffer != fset_buffer)) + return info; + + error = NULL; + y = strtol (weechat_hashtable_get (info, "_chat_line_y"), &error, 10); + if (!error || error[0]) + return info; + + if (y < 0) + return info; + + ptr_fset_option = weechat_arraylist_get (fset_options, y); + if (!ptr_fset_option) + return info; + + snprintf (str_value, sizeof (str_value), + "0x%lx", (long unsigned int)ptr_fset_option); + weechat_hashtable_set (info, "fset_option", str_value); + weechat_hashtable_set (info, "fset_option_name", ptr_fset_option->name); + weechat_hashtable_set (info, "fset_option_parent_name", ptr_fset_option->parent_name); + weechat_hashtable_set (info, "fset_option_type", fset_option_type_string[ptr_fset_option->type]); + weechat_hashtable_set (info, "fset_option_default_value", ptr_fset_option->default_value); + weechat_hashtable_set (info, "fset_option_value", ptr_fset_option->value); + weechat_hashtable_set (info, "fset_option_parent_value", ptr_fset_option->parent_value); + weechat_hashtable_set (info, "fset_option_min", ptr_fset_option->min); + weechat_hashtable_set (info, "fset_option_max", ptr_fset_option->max); + weechat_hashtable_set (info, "fset_option_description", ptr_fset_option->description); + weechat_hashtable_set (info, "fset_option_string_values", ptr_fset_option->string_values); + weechat_hashtable_set (info, "fset_option_marked", (ptr_fset_option->marked) ? "1" : "0"); + + return info; +} + +/* + * Get distance between x and x2 (as a positive integer); + */ + +int +fset_mouse_get_distance_x (struct t_hashtable *hashtable) +{ + int distance, x, x2; + char *error; + + distance = 0; + error = NULL; + x = (int)strtol (weechat_hashtable_get (hashtable, "_chat_line_x"), + &error, 10); + if (error && !error[0]) + { + error = NULL; + x2 = (int)strtol (weechat_hashtable_get (hashtable, "_chat_line_x2"), + &error, 10); + if (error && !error[0]) + { + distance = (x2 - x) / 3; + if (distance < 0) + distance *= -1; + else if (distance == 0) + distance = 1; + } + } + return distance; +} + +/* + * Gets coordinates: y, y2, chat_line_y, chat_line_y2 from hashtable. + * + * Returns: + * 1: OK, all coordinates are set + * 0: error (coordinates must not be used) + */ + +int +fset_mouse_get_coords (struct t_hashtable *hashtable, + int *y, int *y2, int *chat_line_y, int *chat_line_y2) +{ + char *error; + const char *ptr_value; + + ptr_value = weechat_hashtable_get (hashtable, "_y"); + if (!ptr_value) + return 0; + error = NULL; + *y = (int)strtol (ptr_value, &error, 10); + if (!error || error[0]) + return 0; + + ptr_value = weechat_hashtable_get (hashtable, "_y2"); + if (!ptr_value) + return 0; + error = NULL; + *y2 = (int)strtol (ptr_value, &error, 10); + if (!error || error[0]) + return 0; + + ptr_value = weechat_hashtable_get (hashtable, "_chat_line_y"); + if (!ptr_value) + return 0; + error = NULL; + *chat_line_y = (int)strtol (ptr_value, &error, 10); + if (!error || error[0]) + return 0; + + ptr_value = weechat_hashtable_get (hashtable, "_chat_line_y2"); + if (!ptr_value) + return 0; + error = NULL; + *chat_line_y2 = (int)strtol (ptr_value, &error, 10); + if (!error || error[0]) + return 0; + + return 1; +} + +/* + * Callback called when a mouse action occurs in fset bar or bar item. + */ + +int +fset_mouse_hsignal_cb (const void *pointer, void *data, const char *signal, + struct t_hashtable *hashtable) +{ + const char *ptr_key, *ptr_chat_line_y, *ptr_fset_option_pointer; + char str_command[1024]; + struct t_fset_option *ptr_fset_option; + long unsigned int value; + int rc, distance, num_options, y, y2, chat_line_y, chat_line_y2; + int min_y, max_y, i; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) signal; + + if (!fset_buffer) + return WEECHAT_RC_OK; + + ptr_key = weechat_hashtable_get (hashtable, "_key"); + ptr_chat_line_y = weechat_hashtable_get (hashtable, "_chat_line_y"); + ptr_fset_option_pointer = weechat_hashtable_get (hashtable, "fset_option"); + + if (!ptr_key || !ptr_chat_line_y || !ptr_fset_option_pointer) + return WEECHAT_RC_OK; + + rc = sscanf (ptr_fset_option_pointer, "%lx", &value); + if ((rc == EOF) || (rc == 0)) + return WEECHAT_RC_OK; + ptr_fset_option = (struct t_fset_option *)value; + if (!ptr_fset_option) + return WEECHAT_RC_OK; + + snprintf (str_command, sizeof (str_command), + "/fset -go %s", + ptr_chat_line_y); + weechat_command (fset_buffer, str_command); + + if (weechat_string_match (ptr_key, "button2-gesture-left*", 1)) + { + distance = fset_mouse_get_distance_x (hashtable); + if ((ptr_fset_option->type == FSET_OPTION_TYPE_INTEGER) + || (ptr_fset_option->type == FSET_OPTION_TYPE_COLOR)) + { + snprintf (str_command, sizeof (str_command), + "/fset -add -%d", + distance); + } + else + { + snprintf (str_command, sizeof (str_command), "/fset -set"); + } + weechat_command (fset_buffer, str_command); + } + else if (weechat_string_match (ptr_key, "button2-gesture-right*", 1)) + { + distance = fset_mouse_get_distance_x (hashtable); + if ((ptr_fset_option->type == FSET_OPTION_TYPE_INTEGER) + || (ptr_fset_option->type == FSET_OPTION_TYPE_COLOR)) + { + snprintf (str_command, sizeof (str_command), + "/fset -add %d", + distance); + } + else + { + snprintf (str_command, sizeof (str_command), "/fset -append"); + } + weechat_command (fset_buffer, str_command); + } + else if (weechat_string_match (ptr_key, "button2*", 1)) + { + if (fset_mouse_get_coords (hashtable, &y, &y2, + &chat_line_y, &chat_line_y2)) + { + if (y == y2) + { + /* toggle or set option */ + snprintf ( + str_command, sizeof (str_command), + "/fset %s", + (ptr_fset_option->type == FSET_OPTION_TYPE_BOOLEAN) ? + "-toggle" : "-set"); + weechat_command (fset_buffer, str_command); + } + else if ((chat_line_y >= 0) || (chat_line_y2 >= 0)) + { + /* mark/unmark multiple options */ + num_options = weechat_arraylist_size (fset_options); + if (chat_line_y < 0) + chat_line_y = (y > y2) ? 0 : num_options - 1; + else if (chat_line_y2 < 0) + chat_line_y2 = (y > y2) ? 0 : num_options - 1; + min_y = (chat_line_y < chat_line_y2) ? + chat_line_y : chat_line_y2; + max_y = (chat_line_y > chat_line_y2) ? + chat_line_y : chat_line_y2; + if (min_y < 0) + min_y = 0; + if (max_y > num_options - 1) + max_y = num_options - 1; + for (i = min_y; i <= max_y; i++) + { + ptr_fset_option = weechat_arraylist_get (fset_options, i); + if (ptr_fset_option) + { + fset_option_toggle_mark (ptr_fset_option, NULL); + } + } + snprintf (str_command, sizeof (str_command), + "/fset -go %d", + chat_line_y2); + weechat_command (fset_buffer, str_command); + } + } + } + + return WEECHAT_RC_OK; +} + +/* + * Initializes mouse. + * + * Returns: + * 1: OK + * 0: error + */ + +int +fset_mouse_init () +{ + struct t_hashtable *keys; + + keys = weechat_hashtable_new (4, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (!keys) + return 0; + + weechat_hook_focus ("chat", &fset_mouse_focus_cb, NULL, NULL); + + weechat_hook_hsignal (FSET_MOUSE_HSIGNAL, + &fset_mouse_hsignal_cb, NULL, NULL); + + weechat_hashtable_set ( + keys, + "@chat(" FSET_PLUGIN_NAME "." FSET_BUFFER_NAME "):button1", + "/window ${_window_number};/fset -go ${_chat_line_y}"); + weechat_hashtable_set ( + keys, + "@chat(" FSET_PLUGIN_NAME "." FSET_BUFFER_NAME "):button2*", + "hsignal:" FSET_MOUSE_HSIGNAL); + weechat_hashtable_set ( + keys, + "@chat(" FSET_PLUGIN_NAME "." FSET_BUFFER_NAME "):wheelup", + "/fset -up 5"); + weechat_hashtable_set ( + keys, + "@chat(" FSET_PLUGIN_NAME "." FSET_BUFFER_NAME "):wheeldown", + "/fset -down 5"); + weechat_hashtable_set (keys, "__quiet", "1"); + weechat_key_bind ("mouse", keys); + + weechat_hashtable_free (keys); + + return 1; +} + +/* + * Ends mouse. + */ + +void +fset_mouse_end () +{ +} diff --git a/src/plugins/fset/fset-mouse.h b/src/plugins/fset/fset-mouse.h new file mode 100644 index 000000000..e34d6db03 --- /dev/null +++ b/src/plugins/fset/fset-mouse.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef WEECHAT_PLUGIN_FSET_MOUSE_H +#define WEECHAT_PLUGIN_FSET_MOUSE_H + +#define FSET_MOUSE_HSIGNAL "fset_mouse" + +extern int fset_mouse_init (); +extern void fset_mouse_end (); + +#endif /* WEECHAT_PLUGIN_FSET_MOUSE_H */ diff --git a/src/plugins/fset/fset-option.c b/src/plugins/fset/fset-option.c new file mode 100644 index 000000000..0153d67f8 --- /dev/null +++ b/src/plugins/fset/fset-option.c @@ -0,0 +1,1787 @@ +/* + * fset-option.c - manage options displayed by Fast Set buffer + * + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> + +#include "../weechat-plugin.h" +#include "fset.h" +#include "fset-option.h" +#include "fset-buffer.h" +#include "fset-config.h" + + +/* options */ +struct t_arraylist *fset_options = NULL; +int fset_option_count_marked = 0; +struct t_fset_option_max_length *fset_option_max_length = NULL; + +/* filters */ +char *fset_option_filter = NULL; +struct t_hashtable *fset_option_filter_hashtable_pointers = NULL; +struct t_hashtable *fset_option_filter_hashtable_extra_vars = NULL; +struct t_hashtable *fset_option_filter_hashtable_options = NULL; + +/* refresh */ +struct t_hashtable *fset_option_timer_options_changed = NULL; +struct t_hook *fset_option_timer_hook = NULL; + +/* types */ +char *fset_option_type_string[FSET_OPTION_NUM_TYPES] = +{ N_("boolean"), N_("integer"), N_("string"), N_("color") }; +char *fset_option_type_string_short[FSET_OPTION_NUM_TYPES] = +{ "bool", "int", "str", "col" }; +char *fset_option_type_string_tiny[FSET_OPTION_NUM_TYPES] = +{ "b", "i", "s", "c" }; + + +/* + * Checks if a fset option pointer is valid. + * + * Returns: + * 1: option exists + * 0: option does not exist + */ + +int +fset_option_valid (struct t_fset_option *fset_option) +{ + struct t_fset_option *ptr_fset_option; + int num_options, i; + + if (!fset_option) + return 0; + + num_options = weechat_arraylist_size (fset_options); + for (i = 0; i < num_options; i++) + { + ptr_fset_option = weechat_arraylist_get (fset_options, i); + if (ptr_fset_option == fset_option) + return 1; + } + + /* fset option not found */ + return 0; +} + +/* + * Searches for an option by name. + * + * If line is not NULL, *line is set with the line number of option found + * (-1 if line is not found). + * + * Returns pointer to option found, NULL if not found. + */ + +struct t_fset_option * +fset_option_search_by_name (const char *name, int *line) +{ + struct t_fset_option *ptr_fset_option; + int num_options, i; + + if (line) + *line = -1; + + num_options = weechat_arraylist_size (fset_options); + for (i = 0; i < num_options; i++) + { + ptr_fset_option = weechat_arraylist_get (fset_options, i); + if (ptr_fset_option && (strcmp (ptr_fset_option->name, name) == 0)) + { + if (line) + *line = i; + return ptr_fset_option; + } + } + + /* fset option not found */ + return NULL; +} + +/* + * Checks if the option value is changed (different from the default value). + * + * Returns: + * 1: value has been changed + * 0: value is the same as default value + */ + +int +fset_option_value_is_changed (struct t_fset_option *fset_option) +{ + if (!fset_option->value && !fset_option->default_value) + return 0; + + if ((fset_option->value && !fset_option->default_value) + || (!fset_option->value && fset_option->default_value)) + { + return 1; + } + + return (strcmp (fset_option->value, + fset_option->default_value) != 0) ? 1 : 0; +} + +/* + * Sets the value in option, according to its type. + */ + +void +fset_option_set_value_string (struct t_config_option *option, + enum t_fset_option_type type, void *value, + int default_value, + char **value_string) +{ + char str_value[64]; + void *ptr_string_values; + + if (!value) + { + *value_string = NULL; + } + else + { + switch (type) + { + case FSET_OPTION_TYPE_BOOLEAN: + *value_string = strdup (*((int *)value) ? "on" : "off"); + break; + case FSET_OPTION_TYPE_INTEGER: + ptr_string_values = weechat_config_option_get_pointer ( + option, "string_values"); + if (ptr_string_values) + { + *value_string = strdup ( + (default_value) ? weechat_config_string_default (option) : weechat_config_string (option)); + } + else + { + snprintf (str_value, sizeof (str_value), "%d", *((int *)value)); + *value_string = strdup (str_value); + } + break; + case FSET_OPTION_TYPE_STRING: + *value_string = strdup ( + (default_value) ? weechat_config_string_default (option) : weechat_config_string (option)); + break; + case FSET_OPTION_TYPE_COLOR: + *value_string = strdup ( + (default_value) ? weechat_config_color_default (option) : weechat_config_color (option)); + break; + case FSET_OPTION_NUM_TYPES: + break; + } + } +} + +/* + * Checks if a string matches a mask. + * + * If mask has no "*" inside, it just checks if "mask" is inside the "string". + * If mask has at least one "*" inside, the function weechat_string_match is + * used. + * + * Returns: + * 1: string matches mask + * 0: string does not match mask + */ + +int +fset_option_string_match (const char *string, const char *mask) +{ + if (strchr (mask, '*')) + return weechat_string_match (string, mask, 0); + else + return (weechat_strcasestr (string, mask)) ? 1 : 0; +} + +/* + * Adds the properties of an fset option in a hashtable + * (keys and values must be strings). + */ + +void +fset_option_add_option_in_hashtable (struct t_hashtable *hashtable, + struct t_fset_option *fset_option) +{ + int length; + char *value; + + weechat_hashtable_set (hashtable, "file", fset_option->file); + weechat_hashtable_set (hashtable, "section", fset_option->section); + weechat_hashtable_set (hashtable, "option", fset_option->option); + weechat_hashtable_set (hashtable, "name", fset_option->name); + weechat_hashtable_set (hashtable, "parent_name", fset_option->parent_name); + weechat_hashtable_set (hashtable, + "type", _(fset_option_type_string[fset_option->type])); + weechat_hashtable_set (hashtable, + "type_en", fset_option_type_string[fset_option->type]); + weechat_hashtable_set (hashtable, + "type_short", fset_option_type_string_short[fset_option->type]); + weechat_hashtable_set (hashtable, + "type_tiny", fset_option_type_string_tiny[fset_option->type]); + weechat_hashtable_set (hashtable, + "default_value", fset_option->default_value); + weechat_hashtable_set (hashtable, "value", fset_option->value); + if (fset_option->value && (fset_option->type == FSET_OPTION_TYPE_STRING)) + { + length = 1 + strlen (fset_option->value) + 1 + 1; + value = malloc (length); + if (value) + { + snprintf (value, length, "\"%s\"", fset_option->value); + weechat_hashtable_set (hashtable, "quoted_value", value); + free (value); + } + else + { + weechat_hashtable_set (hashtable, + "quoted_value", fset_option->value); + } + } + else + { + weechat_hashtable_set (hashtable, "quoted_value", fset_option->value); + } + weechat_hashtable_set (hashtable, + "parent_value", fset_option->parent_value); + weechat_hashtable_set (hashtable, "min", fset_option->min); + weechat_hashtable_set (hashtable, "max", fset_option->max); + weechat_hashtable_set (hashtable, + "description", + (fset_option->description && fset_option->description[0]) ? + _(fset_option->description) : ""); + weechat_hashtable_set (hashtable, + "description2", + (fset_option->description && fset_option->description[0]) ? + _(fset_option->description) : _("(no description)")); + weechat_hashtable_set (hashtable, + "description_en", fset_option->description); + weechat_hashtable_set (hashtable, + "description_en2", + (fset_option->description && fset_option->description[0]) ? + fset_option->description : "(no description)"); + weechat_hashtable_set (hashtable, + "string_values", fset_option->string_values); + weechat_hashtable_set (hashtable, + "default_value_undef", + (fset_option->default_value == NULL) ? "1" : "0"); + weechat_hashtable_set (hashtable, + "value_undef", + (fset_option->value == NULL) ? "1" : "0"); + weechat_hashtable_set (hashtable, + "value_changed", + (fset_option_value_is_changed (fset_option)) ? "1" : "0"); +} + +/* + * Checks if an option is matching current filter(s). + * + * Returns: + * 1: option is matching filter(s) + * 0: option does not match filter(s) + */ + +int +fset_option_match_filter (struct t_fset_option *fset_option, const char *filter) +{ + int match; + char *result; + + if (!filter || !filter[0]) + return 1; + + if (strncmp (filter, "c:", 2) == 0) + { + weechat_hashtable_set (fset_option_filter_hashtable_pointers, + "fset_option", fset_option); + fset_option_add_option_in_hashtable ( + fset_option_filter_hashtable_extra_vars, + fset_option); + result = weechat_string_eval_expression ( + fset_option_filter + 2, + fset_option_filter_hashtable_pointers, + fset_option_filter_hashtable_extra_vars, + fset_option_filter_hashtable_options); + match = (result && (strcmp (result, "1") == 0)) ? 1 : 0; + if (result) + free (result); + return match; + } + else if (strncmp (filter, "f:", 2) == 0) + { + /* filter by config name */ + return (weechat_strcasecmp (fset_option->file, + filter + 2) == 0) ? 1 : 0; + } + else if (strncmp (filter, "t:", 2) == 0) + { + /* filter by type */ + return (weechat_strcasecmp ( + fset_option_type_string_short[fset_option->type], + filter + 2) == 0) ? 1 : 0; + } + else if (strncmp (filter, "d==", 3) == 0) + { + /* filter by modified values (on exact value) */ + if (!fset_option_value_is_changed (fset_option)) + return 0; + return (weechat_strcasecmp ( + (fset_option->value) ? fset_option->value : FSET_OPTION_VALUE_NULL, + filter + 3) == 0) ? 1 : 0; + } + else if (strncmp (filter, "d=", 2) == 0) + { + /* filter by modified values (on value) */ + if (!fset_option_value_is_changed (fset_option)) + return 0; + return (fset_option_string_match ( + (fset_option->value) ? fset_option->value : FSET_OPTION_VALUE_NULL, + filter + 2)) ? 1 : 0; + } + else if (strncmp (filter, "d:", 2) == 0) + { + /* filter by modified values (on name) */ + if (!fset_option_value_is_changed (fset_option)) + return 0; + return fset_option_string_match (fset_option->name, + filter + 2) ? 1 : 0; + } + else if (strcmp (filter, "d") == 0) + { + /* filter by modified values */ + return (fset_option_value_is_changed (fset_option)) ? 1 : 0; + } + else if (strncmp (filter, "==", 2) == 0) + { + /* filter by exact value */ + return (weechat_strcasecmp ( + (fset_option->value) ? fset_option->value : FSET_OPTION_VALUE_NULL, + filter + 2) == 0) ? 1 : 0; + } + else if (filter[0] == '=') + { + /* filter by value */ + return (fset_option_string_match ( + (fset_option->value) ? fset_option->value : FSET_OPTION_VALUE_NULL, + filter + 1)) ? 1 : 0; + } + else + { + /* filter by option name */ + return (fset_option_string_match (fset_option->name, filter)) ? 1 : 0; + } +} + +/* + * Sets (or sets again) values (except name) in an fset option. + */ + +void +fset_option_set_values (struct t_fset_option *fset_option, + struct t_config_option *option) +{ + const char *ptr_config_name, *ptr_section_name, *ptr_option_name; + const char *ptr_parent_name, *ptr_description; + const char **ptr_string_values; + void *ptr_default_value, *ptr_value; + struct t_config_option *ptr_parent_option; + int length, *ptr_type, *ptr_min, *ptr_max; + char str_value[64]; + + /* file */ + if (fset_option->file) + { + free (fset_option->file); + fset_option->file = NULL; + } + ptr_config_name = weechat_config_option_get_string (option, "config_name"); + fset_option->file = strdup (ptr_config_name); + + /* section */ + if (fset_option->section) + { + free (fset_option->section); + fset_option->section = NULL; + } + ptr_section_name = weechat_config_option_get_string (option, "section_name"); + fset_option->section = strdup (ptr_section_name); + + /* option */ + if (fset_option->option) + { + free (fset_option->option); + fset_option->option = NULL; + } + ptr_option_name = weechat_config_option_get_string (option, "name"); + fset_option->option = strdup (ptr_option_name); + + /* name */ + if (fset_option->name) + { + free (fset_option->name); + fset_option->name = NULL; + } + length = strlen (ptr_config_name) + 1 + + strlen (ptr_section_name) + 1 + + strlen (ptr_option_name) + 1; + fset_option->name = malloc (length); + if (fset_option->name) + { + snprintf (fset_option->name, length, "%s.%s.%s", + ptr_config_name, + ptr_section_name, + ptr_option_name); + } + + /* parent name */ + if (fset_option->parent_name) + { + free (fset_option->parent_name); + fset_option->parent_name = NULL; + } + ptr_parent_name = weechat_config_option_get_string (option, "parent_name"); + fset_option->parent_name = (ptr_parent_name) ? strdup (ptr_parent_name) : NULL; + + /* type */ + ptr_type = weechat_config_option_get_pointer (option, "type"); + fset_option->type = *ptr_type; + + /* default value */ + if (fset_option->default_value) + { + free (fset_option->default_value); + fset_option->default_value = NULL; + } + ptr_default_value = weechat_config_option_get_pointer (option, + "default_value"); + fset_option_set_value_string (option, + fset_option->type, + ptr_default_value, + 1, + &fset_option->default_value); + + /* value */ + if (fset_option->value) + { + free (fset_option->value); + fset_option->value = NULL; + } + ptr_value = weechat_config_option_get_pointer (option, "value"); + fset_option_set_value_string (option, + fset_option->type, + ptr_value, + 0, + &fset_option->value); + + /* parent_value */ + if (fset_option->parent_value) + { + free (fset_option->parent_value); + fset_option->parent_value = NULL; + } + if (ptr_parent_name) + { + ptr_parent_option = weechat_config_get (ptr_parent_name); + if (ptr_parent_option) + { + ptr_value = weechat_config_option_get_pointer (ptr_parent_option, + "value"); + fset_option_set_value_string (ptr_parent_option, + fset_option->type, + ptr_value, + 0, + &fset_option->parent_value); + } + } + + /* min value */ + if (fset_option->min) + { + free (fset_option->min); + fset_option->min = NULL; + } + ptr_min = weechat_config_option_get_pointer (option, "min"); + snprintf (str_value, sizeof (str_value), "%d", *ptr_min); + fset_option->min = strdup (str_value); + + /* max value */ + if (fset_option->max) + { + free (fset_option->max); + fset_option->max = NULL; + } + ptr_max = weechat_config_option_get_pointer (option, "max"); + snprintf (str_value, sizeof (str_value), "%d", *ptr_max); + fset_option->max = strdup (str_value); + + /* description */ + if (fset_option->description) + { + free (fset_option->description); + fset_option->description = NULL; + } + ptr_description = weechat_config_option_get_string (option, "description"); + fset_option->description = strdup ((ptr_description) ? ptr_description : ""); + + /* string_values */ + if (fset_option->string_values) + { + free (fset_option->string_values); + fset_option->string_values = NULL; + } + ptr_string_values = weechat_config_option_get_pointer (option, "string_values"); + if (ptr_string_values) + { + fset_option->string_values = weechat_string_build_with_split_string ( + ptr_string_values, ","); + } + else + { + fset_option->string_values = strdup (""); + } +} + +/* + * Sets max length for fields, for one option. + */ + +void +fset_option_set_max_length_fields_option (struct t_fset_option *fset_option) +{ + int length, length_value, length_parent_value; + + /* file */ + length = weechat_utf8_strlen_screen (fset_option->file); + if (length > fset_option_max_length->file) + fset_option_max_length->file = length; + + /* section */ + length = weechat_utf8_strlen_screen (fset_option->section); + if (length > fset_option_max_length->section) + fset_option_max_length->section = length; + + /* option */ + length = weechat_utf8_strlen_screen (fset_option->option); + if (length > fset_option_max_length->option) + fset_option_max_length->option = length; + + /* name */ + length = weechat_utf8_strlen_screen (fset_option->name); + if (length > fset_option_max_length->name) + fset_option_max_length->name = length; + + /* parent_name */ + length = (fset_option->parent_name) ? + weechat_utf8_strlen_screen (fset_option->name) : 0; + if (length > fset_option_max_length->parent_name) + fset_option_max_length->parent_name = length; + + /* type */ + length = weechat_utf8_strlen_screen (_(fset_option_type_string[fset_option->type])); + if (length > fset_option_max_length->type) + fset_option_max_length->type = length; + + /* type_en */ + length = weechat_utf8_strlen_screen (fset_option_type_string[fset_option->type]); + if (length > fset_option_max_length->type_en) + fset_option_max_length->type_en = length; + + /* type_short */ + length = weechat_utf8_strlen_screen (fset_option_type_string_short[fset_option->type]); + if (length > fset_option_max_length->type_short) + fset_option_max_length->type_short = length; + + /* type_tiny */ + length = weechat_utf8_strlen_screen (fset_option_type_string_tiny[fset_option->type]); + if (length > fset_option_max_length->type_tiny) + fset_option_max_length->type_tiny = length; + + /* default_value */ + if (fset_option->default_value) + { + length = weechat_utf8_strlen_screen (fset_option->default_value); + if (fset_option->type == FSET_OPTION_TYPE_STRING) + length += 2; + } + else + { + length = weechat_utf8_strlen_screen (FSET_OPTION_VALUE_NULL); + } + if (length > fset_option_max_length->default_value) + fset_option_max_length->default_value = length; + + /* value */ + if (fset_option->value) + { + length_value = weechat_utf8_strlen_screen (fset_option->value); + if (fset_option->type == FSET_OPTION_TYPE_STRING) + length_value += 2; + } + else + { + length_value = weechat_utf8_strlen_screen (FSET_OPTION_VALUE_NULL); + } + if (length_value > fset_option_max_length->value) + fset_option_max_length->value = length_value; + + /* parent_value */ + if (fset_option->parent_value) + { + length_parent_value = weechat_utf8_strlen_screen (fset_option->parent_value); + if (fset_option->type == FSET_OPTION_TYPE_STRING) + length_parent_value += 2; + } + else + { + length_parent_value = weechat_utf8_strlen_screen (FSET_OPTION_VALUE_NULL); + } + if (length_parent_value > fset_option_max_length->parent_value) + fset_option_max_length->parent_value = length_parent_value; + + /* value2 */ + length = length_value; + if (!fset_option->value) + length += 4 + length_parent_value; + if (length > fset_option_max_length->value2) + fset_option_max_length->value2 = length; + + /* min */ + length = weechat_utf8_strlen_screen (fset_option->min); + if (length > fset_option_max_length->min) + fset_option_max_length->min = length; + + /* max */ + length = weechat_utf8_strlen_screen (fset_option->max); + if (length > fset_option_max_length->max) + fset_option_max_length->max = length; + + /* description */ + length = (fset_option->description && fset_option->description[0]) ? + weechat_utf8_strlen_screen (_(fset_option->description)) : 0; + if (length > fset_option_max_length->description) + fset_option_max_length->description = length; + + /* description2 */ + length = weechat_utf8_strlen_screen ( + (fset_option->description && fset_option->description[0]) ? + _(fset_option->description) : _("(no description)")); + if (length > fset_option_max_length->description2) + fset_option_max_length->description2 = length; + + /* description_en */ + length = weechat_utf8_strlen_screen (fset_option->description); + if (length > fset_option_max_length->description_en) + fset_option_max_length->description_en = length; + + /* description_en2 */ + length = weechat_utf8_strlen_screen ( + (fset_option->description && fset_option->description[0]) ? + fset_option->description : _("(no description)")); + if (length > fset_option_max_length->description_en2) + fset_option_max_length->description_en2 = length; + + /* string_values */ + length = weechat_utf8_strlen_screen (fset_option->string_values); + if (length > fset_option_max_length->string_values) + fset_option_max_length->string_values = length; + + /* marked */ + length = weechat_utf8_strlen_screen (weechat_config_string (fset_config_look_marked_string)); + if (length > fset_option_max_length->marked) + fset_option_max_length->marked = length; + length = weechat_utf8_strlen_screen (weechat_config_string (fset_config_look_unmarked_string)); + if (length > fset_option_max_length->marked) + fset_option_max_length->marked = length; +} + +/* + * Initializes max length for fields. + */ + +void +fset_option_init_max_length (struct t_fset_option_max_length *max_length) +{ + memset (max_length, 0, sizeof (*max_length)); +} + +/* + * Sets max length for fields, for all options. + */ + +void +fset_option_set_max_length_fields_all () +{ + int i, num_options; + struct t_fset_option *ptr_fset_option; + + /* first clear all max lengths */ + fset_option_init_max_length (fset_option_max_length); + + /* set max length for fields, for all options */ + num_options = weechat_arraylist_size (fset_options); + for (i = 0; i < num_options; i++) + { + ptr_fset_option = weechat_arraylist_get (fset_options, i); + if (ptr_fset_option) + fset_option_set_max_length_fields_option (ptr_fset_option); + } +} + +/* + * Allocates an fset option structure using a pointer to a + * WeeChat/plugin option. + * + * Returns pointer to new fset option, NULL if error. + */ + +struct t_fset_option * +fset_option_alloc (struct t_config_option *option) +{ + struct t_fset_option *new_fset_option; + + new_fset_option = malloc (sizeof (*new_fset_option)); + if (!new_fset_option) + return NULL; + + new_fset_option->index = 0; + new_fset_option->file = NULL; + new_fset_option->section = NULL; + new_fset_option->option = NULL; + new_fset_option->name = NULL; + new_fset_option->parent_name = NULL; + new_fset_option->type = 0; + new_fset_option->default_value = NULL; + new_fset_option->value = NULL; + new_fset_option->parent_value = NULL; + new_fset_option->min = NULL; + new_fset_option->max = NULL; + new_fset_option->description = NULL; + new_fset_option->string_values = NULL; + new_fset_option->marked = 0; + + fset_option_set_values (new_fset_option, option); + + return new_fset_option; +} + +/* + * Allocates an fset option structure using a pointer to a + * WeeChat/plugin option. + * + * Returns pointer to new fset option, NULL if the option does not match + * filters or if error. + */ + +struct t_fset_option * +fset_option_add (struct t_config_option *option) +{ + struct t_fset_option *new_fset_option; + + new_fset_option = fset_option_alloc (option); + if (!new_fset_option) + return NULL; + + if (!weechat_config_boolean (fset_config_look_show_plugins_desc) + && (strcmp (new_fset_option->file, "plugins") == 0) + && (strcmp (new_fset_option->section, "desc") == 0)) + { + fset_option_free (new_fset_option); + return NULL; + } + + /* check if option match filters (if not, ignore it) */ + if (!fset_option_match_filter (new_fset_option, fset_option_filter)) + { + fset_option_free (new_fset_option); + return NULL; + } + + fset_option_set_max_length_fields_option (new_fset_option); + + return new_fset_option; +} + +/* + * Compares two options to sort them by name. + */ + +int +fset_option_compare_options_cb (void *data, struct t_arraylist *arraylist, + void *pointer1, void *pointer2) +{ + int i, reverse, case_sensitive, rc; + const char *ptr_field; + + /* make C compiler happy */ + (void) data; + (void) arraylist; + + if (!fset_hdata_fset_option) + return 1; + + for (i = 0; i < fset_config_sort_fields_count; i++) + { + reverse = 1; + case_sensitive = 1; + ptr_field = fset_config_sort_fields[i]; + while ((ptr_field[0] == '-') || (ptr_field[0] == '~')) + { + if (ptr_field[0] == '-') + reverse *= -1; + else if (ptr_field[0] == '~') + case_sensitive ^= 1; + ptr_field++; + } + rc = weechat_hdata_compare (fset_hdata_fset_option, + pointer1, pointer2, + ptr_field, + case_sensitive); + rc *= reverse; + if (rc != 0) + return rc; + } + + return 1; +} + +/* + * Frees an fset option. + */ + +void +fset_option_free (struct t_fset_option *fset_option) +{ + if (!fset_option) + return; + + if (fset_option->file) + free (fset_option->file); + if (fset_option->section) + free (fset_option->section); + if (fset_option->option) + free (fset_option->option); + if (fset_option->name) + free (fset_option->name); + if (fset_option->parent_name) + free (fset_option->parent_name); + if (fset_option->default_value) + free (fset_option->default_value); + if (fset_option->value) + free (fset_option->value); + if (fset_option->parent_value) + free (fset_option->parent_value); + if (fset_option->min) + free (fset_option->min); + if (fset_option->max) + free (fset_option->max); + if (fset_option->description) + free (fset_option->description); + if (fset_option->string_values) + free (fset_option->string_values); + + free (fset_option); +} + +/* + * Frees an fset option (arraylist callback). + */ + +void +fset_option_free_cb (void *data, struct t_arraylist *arraylist, void *pointer) +{ + struct t_fset_option *fset_option; + + /* make C compiler happy */ + (void) data; + (void) arraylist; + + fset_option = (struct t_fset_option *)pointer; + + fset_option_free (fset_option); +} + +/* + * Allocates and returns the arraylist to store options. + */ + +struct t_arraylist * +fset_option_get_arraylist_options () +{ + return weechat_arraylist_new (100, 1, 0, + &fset_option_compare_options_cb, NULL, + &fset_option_free_cb, NULL); +} + +/* + * Allocates and returns the structure to store max length of fields. + */ + +struct t_fset_option_max_length * +fset_option_get_max_length () +{ + struct t_fset_option_max_length *max_length; + + max_length = malloc (sizeof (*fset_option_max_length)); + if (max_length) + fset_option_init_max_length (max_length); + + return max_length; +} + +/* + * Gets all options to display in fset buffer. + */ + +void +fset_option_get_options () +{ + struct t_fset_option *new_fset_option, *ptr_fset_option; + struct t_config_file *ptr_config; + struct t_config_section *ptr_section; + struct t_config_option *ptr_option; + struct t_hashtable *marked_options; + int i, num_options; + + /* save marked options in a hashtable */ + if (!weechat_config_boolean (fset_config_look_auto_unmark)) + { + marked_options = weechat_hashtable_new (256, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, + NULL, NULL); + num_options = weechat_arraylist_size (fset_options); + for (i = 0; i < num_options; i++) + { + ptr_fset_option = weechat_arraylist_get (fset_options, i); + if (ptr_fset_option && ptr_fset_option->marked) + weechat_hashtable_set (marked_options, ptr_fset_option->name, NULL); + } + } + else + { + marked_options = NULL; + } + + /* clear options */ + weechat_arraylist_clear (fset_options); + fset_option_count_marked = 0; + fset_option_init_max_length (fset_option_max_length); + + /* get options */ + ptr_config = weechat_hdata_get_list (fset_hdata_config_file, + "config_files"); + while (ptr_config) + { + ptr_section = weechat_hdata_pointer (fset_hdata_config_file, + ptr_config, "sections"); + while (ptr_section) + { + ptr_option = weechat_hdata_pointer (fset_hdata_config_section, + ptr_section, "options"); + while (ptr_option) + { + new_fset_option = fset_option_add (ptr_option); + if (new_fset_option) + weechat_arraylist_add (fset_options, new_fset_option); + ptr_option = weechat_hdata_move (fset_hdata_config_option, + ptr_option, 1); + } + ptr_section = weechat_hdata_move (fset_hdata_config_section, + ptr_section, 1); + } + ptr_config = weechat_hdata_move (fset_hdata_config_file, + ptr_config, 1); + } + + num_options = weechat_arraylist_size (fset_options); + + for (i = 0; i < num_options; i++) + { + ptr_fset_option = weechat_arraylist_get (fset_options, i); + if (ptr_fset_option) + ptr_fset_option->index = i; + } + + /* check selected line */ + if (num_options == 0) + fset_buffer_selected_line = 0; + else if (fset_buffer_selected_line >= num_options) + fset_buffer_selected_line = num_options - 1; + + /* restore marked options */ + if (marked_options) + { + for (i = 0; i < num_options; i++) + { + ptr_fset_option = weechat_arraylist_get (fset_options, i); + if (ptr_fset_option + && weechat_hashtable_has_key (marked_options, + ptr_fset_option->name)) + { + ptr_fset_option->marked = 1; + fset_option_count_marked++; + } + } + weechat_hashtable_free (marked_options); + } +} + +/* + * Sets the filter. + */ + +void +fset_option_set_filter (const char *filter) +{ + if (fset_option_filter) + free (fset_option_filter); + fset_option_filter = (filter && (strcmp (filter, "*") != 0)) ? + strdup (filter) : NULL; +} + +/* + * Filters options. + */ + +void +fset_option_filter_options (const char *filter) +{ + fset_buffer_selected_line = 0; + + fset_option_set_filter (filter); + + fset_buffer_set_localvar_filter (); + + fset_option_get_options (); + + fset_buffer_refresh (1); +} + +/* + * Toggles a boolean option. + */ + +void +fset_option_toggle_value (struct t_fset_option *fset_option, + struct t_config_option *option) +{ + if (!fset_option || !option + || (fset_option->type != FSET_OPTION_TYPE_BOOLEAN)) + return; + + weechat_config_option_set (option, "toggle", 1); +} + +/* + * Adds a value to an integer/color option. + */ + +void +fset_option_add_value (struct t_fset_option *fset_option, + struct t_config_option *option, + int value) +{ + char str_value[128]; + + if (!fset_option || !option + || ((fset_option->type != FSET_OPTION_TYPE_INTEGER) + && (fset_option->type != FSET_OPTION_TYPE_COLOR))) + return; + + snprintf (str_value, sizeof (str_value), + "%s%d", + (value > 0) ? "++" : "--", + (value > 0) ? value : value * -1); + weechat_config_option_set (option, str_value, 1); +} + +/* + * Resets the value of an option. + */ + +void +fset_option_reset_value (struct t_fset_option *fset_option, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) fset_option; + + if (!option) + return; + + weechat_config_option_reset (option, 1); +} + +/* + * Unsets the value of an option. + */ + +void +fset_option_unset_value (struct t_fset_option *fset_option, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) fset_option; + + if (!option) + return; + + weechat_config_option_unset (option); +} + +/* + * Sets the value of an option. + * + * If set_mode == -1, edit an empty value. + * If set_mode == 0, edit the current value. + * If set_mode == 1, append to the current value (move the cursor at the end of + * value) + */ + +void +fset_option_set (struct t_fset_option *fset_option, + struct t_config_option *option, + struct t_gui_buffer *buffer, + int set_mode) +{ + int use_mute, add_quotes, input_pos; + char str_input[4096], str_pos[32]; + + /* make C compiler happy */ + (void) option; + + if (!fset_option) + return; + + use_mute = weechat_config_boolean (fset_config_look_use_mute); + add_quotes = (fset_option->type == FSET_OPTION_TYPE_STRING) ? 1 : 0; + snprintf (str_input, sizeof (str_input), + "%s/set %s %s%s%s", + (use_mute) ? "/mute " : "", + fset_option->name, + (add_quotes) ? "\"" : "", + (set_mode != -1) ? ((fset_option->value) ? fset_option->value : "") : "", + (add_quotes) ? "\"" : ""); + weechat_buffer_set (buffer, "input", str_input); + input_pos = ((use_mute) ? 6 : 0) + /* "/mute " */ + 5 + /* "/set " */ + weechat_utf8_strlen (fset_option->name) + 1 + + ((add_quotes) ? 1 : 0) + + ((set_mode == 1) ? ((fset_option->value) ? + weechat_utf8_strlen (fset_option->value) : 0) : 0); + snprintf (str_pos, sizeof (str_pos), "%d", input_pos); + weechat_buffer_set (buffer, "input_pos", str_pos); +} + +/* + * Marks/unmarks an option. + */ + +void +fset_option_toggle_mark (struct t_fset_option *fset_option, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) option; + + if (!fset_option) + return; + + fset_option->marked ^= 1; + fset_option_count_marked += (fset_option->marked) ? 1 : -1; + + fset_buffer_display_option (fset_option); +} + +/* + * Mark/unmark options matching a filter. + */ + +void +fset_option_mark_options_matching_filter (const char *filter, int mark) +{ + int num_options, i, mark_old, matching, set_title; + struct t_fset_option *ptr_fset_option; + + set_title = 0; + + num_options = weechat_arraylist_size (fset_options); + for (i = 0; i < num_options; i++) + { + ptr_fset_option = weechat_arraylist_get (fset_options, i); + if (ptr_fset_option) + { + mark_old = ptr_fset_option->marked; + matching = fset_option_match_filter (ptr_fset_option, filter); + if (matching) + { + if (!mark_old && mark) + { + ptr_fset_option->marked = 1; + fset_option_count_marked++; + fset_buffer_display_option (ptr_fset_option); + set_title = 1; + } + else if (mark_old && !mark) + { + ptr_fset_option->marked = 0; + fset_option_count_marked--; + fset_buffer_display_option (ptr_fset_option); + set_title = 1; + } + } + } + } + + if (set_title) + fset_buffer_set_title (); +} + +/* + * Unmarks all options. + */ + +void +fset_option_unmark_all () +{ + int num_options, marked, set_title, i; + struct t_fset_option *ptr_fset_option; + + set_title = 0; + + num_options = weechat_arraylist_size (fset_options); + for (i = 0; i < num_options; i++) + { + ptr_fset_option = weechat_arraylist_get (fset_options, i); + if (ptr_fset_option) + { + marked = ptr_fset_option->marked; + ptr_fset_option->marked = 0; + if (marked) + { + fset_buffer_display_option (ptr_fset_option); + set_title = 1; + } + } + } + fset_option_count_marked = 0; + + if (set_title) + fset_buffer_set_title (); +} + +/* + * Exports options currently displayed in fset buffer. + * + * If with_help == 1, the help is displayed above each option + * and options are separated by an empty line. + * + * Returns: + * 1: export OK + * 0: error + */ + +int +fset_option_export (const char *filename, int with_help) +{ + int num_options, i; + char *line; + FILE *file; + struct t_fset_option *ptr_fset_option; + struct t_hashtable *hashtable_pointers, *hashtable_extra_vars; + + file = fopen (filename, "w"); + if (!file) + return 0; + + chmod (filename, 0600); + + hashtable_pointers = weechat_hashtable_new ( + 8, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, + NULL, NULL); + hashtable_extra_vars = weechat_hashtable_new ( + 128, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + + num_options = weechat_arraylist_size (fset_options); + for (i = 0; i < num_options; i++) + { + ptr_fset_option = weechat_arraylist_get (fset_options, i); + if (ptr_fset_option) + { + weechat_hashtable_set (hashtable_pointers, + "fset_option", ptr_fset_option); + fset_option_add_option_in_hashtable (hashtable_extra_vars, + ptr_fset_option); + if (with_help) + { + if (i > 0) + fprintf (file, "\n"); + line = weechat_string_eval_expression ( + weechat_config_string (fset_config_format_export_help), + hashtable_pointers, + hashtable_extra_vars, + NULL); + if (line && line[0]) + fprintf (file, "%s\n", line); + if (line) + free (line); + } + line = weechat_string_eval_expression ( + (ptr_fset_option->value) ? + weechat_config_string (fset_config_format_export_option) : + weechat_config_string (fset_config_format_export_option_null), + hashtable_pointers, + hashtable_extra_vars, + NULL); + if (line && line[0]) + fprintf (file, "%s\n", line); + if (line) + free (line); + } + } + + fclose (file); + + if (hashtable_pointers) + weechat_hashtable_free (hashtable_pointers); + if (hashtable_extra_vars) + weechat_hashtable_free (hashtable_extra_vars); + + return 1; +} + +/* + * Refreshes the fset buffer after the change of an option. + */ + +void +fset_option_config_changed (const char *option_name) +{ + struct t_fset_option *ptr_fset_option, *new_fset_option; + struct t_config_option *ptr_option; + int full_refresh, line, num_options; + + if (!fset_buffer) + return; + + full_refresh = 0; + + ptr_fset_option = (option_name) ? + fset_option_search_by_name (option_name, &line) : NULL; + ptr_option = (option_name) ? weechat_config_get (option_name) : NULL; + + if (ptr_fset_option) + { + if (ptr_option) + { + fset_option_set_values (ptr_fset_option, ptr_option); + fset_buffer_display_option (ptr_fset_option); + } + else + { + /* option removed: get options and refresh the whole buffer */ + full_refresh = 1; + } + } + else if (ptr_option) + { + new_fset_option = fset_option_alloc (ptr_option); + if (fset_option_match_filter (new_fset_option, fset_option_filter)) + { + /* option added: get options and refresh the whole buffer */ + full_refresh = 1; + } + } + + if (full_refresh) + { + fset_option_get_options (); + fset_buffer_refresh (1); + } + else + { + num_options = weechat_arraylist_size (fset_options); + for (line = 0; line < num_options; line++) + { + ptr_fset_option = weechat_arraylist_get (fset_options, line); + if (ptr_fset_option + && ptr_fset_option->parent_name + && option_name + && (strcmp (ptr_fset_option->parent_name, option_name) == 0)) + { + ptr_option = weechat_config_get (ptr_fset_option->name); + if (ptr_option) + fset_option_set_values (ptr_fset_option, ptr_option); + } + } + fset_option_set_max_length_fields_all (); + fset_buffer_refresh (0); + } +} + +/* + * Callback called by the timer for each option changed. + */ + +void +fset_option_timer_option_changed_cb (void *data, + struct t_hashtable *hashtable, + const void *key, + const void *value) +{ + /* make C compiler happy */ + (void) data; + (void) hashtable; + (void) value; + + fset_option_config_changed (key); +} + +/* + * Callback for timer after an option is changed. + */ + +int +fset_option_config_timer_cb (const void *pointer, + void *data, + int remaining_calls) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) remaining_calls; + + weechat_hashtable_map (fset_option_timer_options_changed, + &fset_option_timer_option_changed_cb, + NULL); + weechat_hashtable_remove_all (fset_option_timer_options_changed); + + fset_option_timer_hook = NULL; + + return WEECHAT_RC_OK; +} + +/* + * Callback for config option changed. + */ + +int +fset_option_config_cb (const void *pointer, + void *data, + const char *option, + const char *value) +{ + const char *ptr_info; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) value; + + /* do nothing if fset buffer is not opened */ + if (!fset_buffer) + return WEECHAT_RC_OK; + + /* do nothing if WeeChat is upgrading */ + ptr_info = weechat_info_get ("weechat_upgrading", NULL); + if (ptr_info && (strcmp (ptr_info, "1") == 0)) + return WEECHAT_RC_OK; + + weechat_hashtable_set (fset_option_timer_options_changed, + option, NULL); + + if (!fset_option_timer_hook) + { + fset_option_timer_hook = weechat_hook_timer ( + 1, 0, 1, + &fset_option_config_timer_cb, NULL, NULL); + } + + return WEECHAT_RC_OK; +} + +/* + * Returns hdata for option. + */ + +struct t_hdata * +fset_option_hdata_option_cb (const void *pointer, void *data, + const char *hdata_name) +{ + struct t_hdata *hdata; + + /* make C compiler happy */ + (void) pointer; + (void) data; + + hdata = weechat_hdata_new (hdata_name, NULL, NULL, 0, 0, NULL, NULL); + if (hdata) + { + WEECHAT_HDATA_VAR(struct t_fset_option, index, INTEGER, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_fset_option, file, STRING, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_fset_option, section, STRING, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_fset_option, option, STRING, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_fset_option, name, STRING, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_fset_option, parent_name, STRING, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_fset_option, type, INTEGER, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_fset_option, default_value, STRING, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_fset_option, value, STRING, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_fset_option, parent_value, STRING, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_fset_option, min, STRING, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_fset_option, max, STRING, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_fset_option, description, STRING, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_fset_option, string_values, STRING, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_fset_option, marked, INTEGER, 0, NULL, NULL); + } + return hdata; +} + +/* + * Adds a fset option in an infolist. + * + * Returns: + * 1: OK + * 0: error + */ + +int +fset_option_add_to_infolist (struct t_infolist *infolist, + struct t_fset_option *fset_option) +{ + struct t_infolist_item *ptr_item; + + if (!infolist || !fset_option) + return 0; + + ptr_item = weechat_infolist_new_item (infolist); + if (!ptr_item) + return 0; + + if (!weechat_infolist_new_var_integer (ptr_item, "index", fset_option->index)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "file", fset_option->file)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "section", fset_option->section)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "option", fset_option->option)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "name", fset_option->name)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "parent_name", fset_option->parent_name)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "type", _(fset_option_type_string[fset_option->type]))) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "type_en", fset_option_type_string[fset_option->type])) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "default_value", fset_option->default_value)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "value", fset_option->value)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "parent_value", fset_option->parent_value)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "min", fset_option->min)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "max", fset_option->max)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "description", + (fset_option->description && fset_option->description[0]) ? + _(fset_option->description) : "")) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "description_en", fset_option->description)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "string_values", fset_option->description)) + return 0; + if (!weechat_infolist_new_var_integer (ptr_item, "marked", fset_option->marked)) + return 0; + + return 1; +} + +/* + * Prints fset options in WeeChat log file (usually for crash dump). + */ + +void +fset_option_print_log () +{ + struct t_fset_option *ptr_fset_option; + int num_options, i; + + num_options = weechat_arraylist_size (fset_options); + for (i = 0; i < num_options; i++) + { + ptr_fset_option = weechat_arraylist_get (fset_options, i); + if (!ptr_fset_option) + continue; + weechat_log_printf (""); + weechat_log_printf ("[fset option (addr:0x%lx)]", ptr_fset_option); + weechat_log_printf (" index . . . . . . . . : %d", ptr_fset_option->index); + weechat_log_printf (" file. . . . . . . . . : '%s'", ptr_fset_option->file); + weechat_log_printf (" section . . . . . . . : '%s'", ptr_fset_option->section); + weechat_log_printf (" option. . . . . . . . : '%s'", ptr_fset_option->option); + weechat_log_printf (" name. . . . . . . . . : '%s'", ptr_fset_option->name); + weechat_log_printf (" parent_name . . . . . : '%s'", ptr_fset_option->parent_name); + weechat_log_printf (" type. . . . . . . . . : %d ('%s')", + ptr_fset_option->type, + fset_option_type_string[ptr_fset_option->type]); + weechat_log_printf (" default_value . . . . : '%s'", ptr_fset_option->default_value); + weechat_log_printf (" value . . . . . . . . : '%s'", ptr_fset_option->value); + weechat_log_printf (" parent_value. . . . . : '%s'", ptr_fset_option->parent_value); + weechat_log_printf (" min . . . . . . . . . : '%s'", ptr_fset_option->min); + weechat_log_printf (" max . . . . . . . . . : '%s'", ptr_fset_option->max); + weechat_log_printf (" description . . . . . : '%s'", ptr_fset_option->description); + weechat_log_printf (" string_values . . . . : '%s'", ptr_fset_option->string_values); + weechat_log_printf (" marked. . . . . . . . : %d", ptr_fset_option->marked); + } +} + +/* + * Initializes fset list of options. + * + * Returns: + * 1: OK + * 0: error + */ + +int +fset_option_init () +{ + fset_options = fset_option_get_arraylist_options (); + if (!fset_options) + return 0; + fset_option_count_marked = 0; + + fset_option_max_length = fset_option_get_max_length (); + if (!fset_option_max_length) + { + weechat_arraylist_free (fset_options); + return 0; + } + + fset_option_filter_hashtable_pointers = weechat_hashtable_new ( + 8, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, + NULL, NULL); + if (!fset_option_filter_hashtable_pointers) + { + weechat_arraylist_free (fset_options); + free (fset_option_max_length); + return 0; + } + fset_option_filter_hashtable_extra_vars = weechat_hashtable_new ( + 128, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (!fset_option_filter_hashtable_extra_vars) + { + weechat_arraylist_free (fset_options); + free (fset_option_max_length); + weechat_hashtable_free (fset_option_filter_hashtable_pointers); + return 0; + } + fset_option_filter_hashtable_options = weechat_hashtable_new ( + 8, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (!fset_option_filter_hashtable_options) + { + weechat_arraylist_free (fset_options); + free (fset_option_max_length); + weechat_hashtable_free (fset_option_filter_hashtable_pointers); + weechat_hashtable_free (fset_option_filter_hashtable_extra_vars); + return 0; + } + weechat_hashtable_set (fset_option_filter_hashtable_options, + "type", "condition"); + + fset_option_timer_options_changed = weechat_hashtable_new ( + 128, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, + NULL, NULL); + if (!fset_option_timer_options_changed) + { + weechat_arraylist_free (fset_options); + free (fset_option_max_length); + weechat_hashtable_free (fset_option_filter_hashtable_pointers); + weechat_hashtable_free (fset_option_filter_hashtable_extra_vars); + weechat_hashtable_free (fset_option_filter_hashtable_options); + return 0; + } + + return 1; +} + +/* + * Ends fset list of options. + */ + +void +fset_option_end () +{ + if (fset_options) + { + weechat_arraylist_free (fset_options); + fset_options = NULL; + } + fset_option_count_marked = 0; + if (fset_option_max_length) + { + free (fset_option_max_length); + fset_option_max_length = NULL; + } + if (fset_option_filter) + { + free (fset_option_filter); + fset_option_filter = NULL; + } + if (fset_option_filter_hashtable_pointers) + { + weechat_hashtable_free (fset_option_filter_hashtable_pointers); + fset_option_filter_hashtable_pointers = NULL; + } + if (fset_option_filter_hashtable_extra_vars) + { + weechat_hashtable_free (fset_option_filter_hashtable_extra_vars); + fset_option_filter_hashtable_extra_vars = NULL; + } + if (fset_option_filter_hashtable_options) + { + weechat_hashtable_free (fset_option_filter_hashtable_options); + fset_option_filter_hashtable_options = NULL; + } + if (fset_option_timer_options_changed) + { + weechat_hashtable_free (fset_option_timer_options_changed); + fset_option_timer_options_changed = NULL; + } +} diff --git a/src/plugins/fset/fset-option.h b/src/plugins/fset/fset-option.h new file mode 100644 index 000000000..b724ab8a0 --- /dev/null +++ b/src/plugins/fset/fset-option.h @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef WEECHAT_PLUGIN_FSET_OPTION_H +#define WEECHAT_PLUGIN_FSET_OPTION_H + +#define FSET_OPTION_VALUE_NULL "null" + +enum t_fset_option_type +{ + FSET_OPTION_TYPE_BOOLEAN = 0, + FSET_OPTION_TYPE_INTEGER, + FSET_OPTION_TYPE_STRING, + FSET_OPTION_TYPE_COLOR, + /* number of option types */ + FSET_OPTION_NUM_TYPES, +}; + +struct t_fset_option +{ + int index; /* index of option in list */ + char *file; /* config file name (eg: "weechat")*/ + char *section; /* section name (eg: "look") */ + char *option; /* option name */ + char *name; /* option full name: file.sect.opt */ + char *parent_name; /* parent option name */ + enum t_fset_option_type type; /* option type */ + char *default_value; /* option default value */ + char *value; /* option value */ + char *parent_value; /* parent option value */ + char *min; /* min value */ + char *max; /* max value */ + char *description; /* option description */ + char *string_values; /* string values for option */ + int marked; /* option marked for group oper. */ + struct t_fset_option *prev_option; /* link to previous option */ + struct t_fset_option *next_option; /* link to next option */ +}; + +struct t_fset_option_max_length +{ + int file; + int section; + int option; + int name; + int parent_name; + int type; + int type_en; + int type_short; + int type_tiny; + int default_value; + int value; + int parent_value; + int value2; + int min; + int max; + int description; + int description2; + int description_en; + int description_en2; + int string_values; + int marked; +}; + +extern struct t_arraylist *fset_options; +extern int fset_option_count_marked; +extern struct t_fset_option_max_length *fset_option_max_length; +extern char *fset_option_filter; +extern char *fset_option_type_string[]; +extern char *fset_option_type_string_short[]; +extern char *fset_option_type_string_tiny[]; + +extern int fset_option_valid (struct t_fset_option *option); +extern struct t_fset_option *fset_option_search_by_name (const char *name, + int *line); +extern int fset_option_value_is_changed (struct t_fset_option *option); +extern void fset_option_set_max_length_fields_all (); +extern void fset_option_free (struct t_fset_option *fset_option); +extern struct t_arraylist *fset_option_get_arraylist_options (); +extern struct t_fset_option_max_length *fset_option_get_max_length (); +extern void fset_option_get_options (); +extern void fset_option_set_filter (const char *filter); +extern void fset_option_filter_options (const char *filter); +extern void fset_option_toggle_value (struct t_fset_option *fset_option, + struct t_config_option *option); +extern void fset_option_add_value (struct t_fset_option *fset_option, + struct t_config_option *option, + int value); +extern void fset_option_reset_value (struct t_fset_option *fset_option, + struct t_config_option *option); +extern void fset_option_unset_value (struct t_fset_option *fset_option, + struct t_config_option *option); +extern void fset_option_set (struct t_fset_option *fset_option, + struct t_config_option *option, + struct t_gui_buffer *buffer, + int set_mode); +extern void fset_option_toggle_mark (struct t_fset_option *fset_option, + struct t_config_option *option); +extern void fset_option_mark_options_matching_filter (const char *filter, + int mark); +extern void fset_option_unmark_all (); +extern int fset_option_export (const char *filename, int with_help); +extern int fset_option_config_cb (const void *pointer, + void *data, + const char *option, + const char *value); +extern struct t_hdata *fset_option_hdata_option_cb (const void *pointer, + void *data, + const char *hdata_name); +extern int fset_option_add_to_infolist (struct t_infolist *infolist, + struct t_fset_option *option); +extern void fset_option_print_log (); +extern int fset_option_init (); +extern void fset_option_end (); + +#endif /* WEECHAT_PLUGIN_FSET_OPTION_H */ diff --git a/src/plugins/fset/fset.c b/src/plugins/fset/fset.c new file mode 100644 index 000000000..d5f72881f --- /dev/null +++ b/src/plugins/fset/fset.c @@ -0,0 +1,183 @@ +/* + * fset.c - Fast set of WeeChat and plugins options + * + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "../weechat-plugin.h" +#include "fset.h" +#include "fset-bar-item.h" +#include "fset-buffer.h" +#include "fset-command.h" +#include "fset-completion.h" +#include "fset-config.h" +#include "fset-info.h" +#include "fset-mouse.h" +#include "fset-option.h" + + +WEECHAT_PLUGIN_NAME(FSET_PLUGIN_NAME); +WEECHAT_PLUGIN_DESCRIPTION(N_("Fast set of WeeChat and plugins options")); +WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); +WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); +WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); +WEECHAT_PLUGIN_PRIORITY(2000); + +struct t_weechat_plugin *weechat_fset_plugin = NULL; + +struct t_hdata *fset_hdata_config_file = NULL; +struct t_hdata *fset_hdata_config_section = NULL; +struct t_hdata *fset_hdata_config_option = NULL; +struct t_hdata *fset_hdata_fset_option = NULL; + + +/* + * Callback for signal "debug_dump". + */ + +int +fset_debug_dump_cb (const void *pointer, void *data, + const char *signal, const char *type_data, + void *signal_data) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) signal; + (void) type_data; + + if (!signal_data + || (weechat_strcasecmp ((char *)signal_data, FSET_PLUGIN_NAME) == 0)) + { + weechat_log_printf (""); + weechat_log_printf ("***** \"%s\" plugin dump *****", + weechat_plugin->name); + + fset_option_print_log (); + + weechat_log_printf (""); + weechat_log_printf ("***** End of \"%s\" plugin dump *****", + weechat_plugin->name); + } + + return WEECHAT_RC_OK; +} + +/* + * Adds the fset bar. + */ + +void +fset_add_bar () +{ + weechat_bar_new ( + FSET_BAR_NAME, "off", "0", "window", + "${buffer.full_name} == " FSET_PLUGIN_NAME "." FSET_BAR_NAME, + "top", "horizontal", "vertical", "3", "3", + "default", "cyan", "default", "on", + FSET_BAR_ITEM_NAME); +} + +/* + * Initializes fset plugin. + */ + +int +weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) +{ + const char *ptr_filter; + + /* make C compiler happy */ + (void) argc; + (void) argv; + + weechat_plugin = plugin; + + fset_hdata_config_file = weechat_hdata_get ("config_file"); + fset_hdata_config_section = weechat_hdata_get ("config_section"); + fset_hdata_config_option = weechat_hdata_get ("config_option"); + + fset_buffer_init (); + + fset_option_init (); + + if (!fset_config_init ()) + return WEECHAT_RC_ERROR; + + fset_config_read (); + + if (!fset_bar_item_init ()) + return WEECHAT_RC_ERROR; + + fset_command_init (); + + fset_completion_init (); + + fset_add_bar (); + + fset_bar_item_update (); + + fset_info_init (); + + fset_hdata_fset_option = weechat_hdata_get ("fset_option"); + + /* hook some signals */ + weechat_hook_signal ("debug_dump", &fset_debug_dump_cb, NULL, NULL); + weechat_hook_signal ("window_scrolled", + &fset_buffer_window_scrolled_cb, NULL, NULL); + + fset_mouse_init (); + + weechat_hook_config ("*", &fset_option_config_cb, NULL, NULL); + + if (fset_buffer) + { + ptr_filter = weechat_buffer_get_string (fset_buffer, "localvar_filter"); + fset_option_filter_options (ptr_filter); + } + + return WEECHAT_RC_OK; +} + +/* + * Ends fset plugin. + */ + +int +weechat_plugin_end (struct t_weechat_plugin *plugin) +{ + /* make C compiler happy */ + (void) plugin; + + fset_mouse_end (); + + fset_bar_item_end (); + + fset_buffer_end (); + + fset_option_end (); + + fset_config_write (); + fset_config_free (); + + return WEECHAT_RC_OK; +} diff --git a/src/plugins/fset/fset.h b/src/plugins/fset/fset.h new file mode 100644 index 000000000..b32e76f1c --- /dev/null +++ b/src/plugins/fset/fset.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef WEECHAT_PLUGIN_FSET_H +#define WEECHAT_PLUGIN_FSET_H + +#define weechat_plugin weechat_fset_plugin +#define FSET_PLUGIN_NAME "fset" + +#define FSET_BAR_NAME "fset" + +extern struct t_weechat_plugin *weechat_fset_plugin; + +extern struct t_hdata *fset_hdata_config_file; +extern struct t_hdata *fset_hdata_config_section; +extern struct t_hdata *fset_hdata_config_option; +extern struct t_hdata *fset_hdata_fset_option; + +extern void fset_add_bar (); + +#endif /* WEECHAT_PLUGIN_FSET_H */ diff --git a/src/plugins/guile/CMakeLists.txt b/src/plugins/guile/CMakeLists.txt index 96053f968..58119762b 100644 --- a/src/plugins/guile/CMakeLists.txt +++ b/src/plugins/guile/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2011-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2011-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/guile/Makefile.am b/src/plugins/guile/Makefile.am index 3c102cdf3..583c3c69d 100644 --- a/src/plugins/guile/Makefile.am +++ b/src/plugins/guile/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2011-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2011-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/guile/weechat-guile-api.c b/src/plugins/guile/weechat-guile-api.c index 2842b39ae..6e48fa035 100644 --- a/src/plugins/guile/weechat-guile-api.c +++ b/src/plugins/guile/weechat-guile-api.c @@ -1,7 +1,7 @@ /* * weechat-guile-api.c - guile API functions * - * Copyright (C) 2011-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2011-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2012 Simon Arlott * * This file is part of WeeChat, the extensible chat client. @@ -57,6 +57,8 @@ plugin_script_str2ptr (weechat_guile_plugin, \ GUILE_CURRENT_SCRIPT_NAME, \ guile_function_name, __string) +#define API_STATIC_STRING(__string) \ + plugin_script_get_static_string(&guile_data, __string); #define API_SCM_TO_STRING(__str) \ weechat_guile_api_scm_to_string(__str, \ guile_strings, &guile_num_strings) @@ -68,27 +70,23 @@ } #define API_RETURN_OK \ API_FREE_STRINGS; \ - return SCM_BOOL_T + return scm_from_int (1) #define API_RETURN_ERROR \ API_FREE_STRINGS \ - return SCM_BOOL_F + return scm_from_int (0) #define API_RETURN_EMPTY \ API_FREE_STRINGS; \ return scm_from_locale_string("") #define API_RETURN_STRING(__string) \ + return_value = scm_from_locale_string ((__string) ? __string : ""); \ API_FREE_STRINGS; \ - if (__string) \ - return scm_from_locale_string(__string); \ - return scm_from_locale_string("") + return return_value #define API_RETURN_STRING_FREE(__string) \ - API_FREE_STRINGS; \ + return_value = scm_from_locale_string ((__string) ? __string : ""); \ if (__string) \ - { \ - return_value = scm_from_locale_string (__string); \ free (__string); \ - return return_value; \ - } \ - return scm_from_locale_string("") + API_FREE_STRINGS; \ + return return_value #define API_RETURN_INT(__int) \ API_FREE_STRINGS; \ return scm_from_int (__int) @@ -189,7 +187,7 @@ weechat_guile_api_register (SCM name, SCM author, SCM version, SCM license, /* register script */ guile_current_script = plugin_script_add (weechat_guile_plugin, - &guile_scripts, &last_guile_script, + &guile_data, (guile_current_script_filename) ? guile_current_script_filename : "", API_SCM_TO_STRING(name), @@ -233,6 +231,7 @@ SCM weechat_guile_api_plugin_get_name (SCM plugin) { const char *result; + SCM return_value; API_INIT_FUNC(1, "plugin_get_name", API_RETURN_EMPTY); if (!scm_is_string (plugin)) @@ -291,6 +290,7 @@ SCM weechat_guile_api_gettext (SCM string) { const char *result; + SCM return_value; API_INIT_FUNC(1, "gettext", API_RETURN_EMPTY); if (!scm_is_string (string)) @@ -305,6 +305,7 @@ SCM weechat_guile_api_ngettext (SCM single, SCM plural, SCM count) { const char *result; + SCM return_value; API_INIT_FUNC(1, "ngettext", API_RETURN_EMPTY); if (!scm_is_string (single) || !scm_is_string (plural) @@ -395,6 +396,21 @@ weechat_guile_api_string_mask_to_regex (SCM mask) } SCM +weechat_guile_api_string_format_size (SCM size) +{ + char *result; + SCM return_value; + + API_INIT_FUNC(1, "string_format_size", API_RETURN_EMPTY); + if (!scm_is_integer (size)) + API_WRONG_ARGS(API_RETURN_EMPTY); + + result = weechat_string_format_size (scm_to_ulong_long (size)); + + API_RETURN_STRING_FREE(result); +} + +SCM weechat_guile_api_string_remove_color (SCM string, SCM replacement) { char *result; @@ -428,6 +444,7 @@ SCM weechat_guile_api_string_input_for_buffer (SCM string) { const char *result; + SCM return_value; API_INIT_FUNC(1, "string_input_for_buffer", API_RETURN_EMPTY); if (!scm_is_string (string)) @@ -563,7 +580,8 @@ weechat_guile_api_mkdir_parents (SCM directory, SCM mode) SCM weechat_guile_api_list_new () { - char *result; + const char *result; + SCM return_value; API_INIT_FUNC(1, "list_new", API_RETURN_EMPTY); @@ -575,7 +593,8 @@ weechat_guile_api_list_new () SCM weechat_guile_api_list_add (SCM weelist, SCM data, SCM where, SCM user_data) { - char *result; + const char *result; + SCM return_value; API_INIT_FUNC(1, "list_add", API_RETURN_EMPTY); if (!scm_is_string (weelist) || !scm_is_string (data) @@ -593,7 +612,8 @@ weechat_guile_api_list_add (SCM weelist, SCM data, SCM where, SCM user_data) SCM weechat_guile_api_list_search (SCM weelist, SCM data) { - char *result; + const char *result; + SCM return_value; API_INIT_FUNC(1, "list_search", API_RETURN_EMPTY); if (!scm_is_string (weelist) || !scm_is_string (data)) @@ -623,7 +643,8 @@ weechat_guile_api_list_search_pos (SCM weelist, SCM data) SCM weechat_guile_api_list_casesearch (SCM weelist, SCM data) { - char *result; + const char *result; + SCM return_value; API_INIT_FUNC(1, "list_casesearch", API_RETURN_EMPTY); if (!scm_is_string (weelist) || !scm_is_string (data)) @@ -653,7 +674,8 @@ weechat_guile_api_list_casesearch_pos (SCM weelist, SCM data) SCM weechat_guile_api_list_get (SCM weelist, SCM position) { - char *result; + const char *result; + SCM return_value; API_INIT_FUNC(1, "list_get", API_RETURN_EMPTY); if (!scm_is_string (weelist) || !scm_is_integer (position)) @@ -681,7 +703,8 @@ weechat_guile_api_list_set (SCM item, SCM new_value) SCM weechat_guile_api_list_next (SCM item) { - char *result; + const char *result; + SCM return_value; API_INIT_FUNC(1, "list_next", API_RETURN_EMPTY); if (!scm_is_string (item)) @@ -695,7 +718,8 @@ weechat_guile_api_list_next (SCM item) SCM weechat_guile_api_list_prev (SCM item) { - char *result; + const char *result; + SCM return_value; API_INIT_FUNC(1, "list_prev", API_RETURN_EMPTY); if (!scm_is_string (item)) @@ -710,6 +734,7 @@ SCM weechat_guile_api_list_string (SCM item) { const char *result; + SCM return_value; API_INIT_FUNC(1, "list_string", API_RETURN_EMPTY); if (!scm_is_string (item)) @@ -787,7 +812,7 @@ weechat_guile_api_config_reload_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); rc = (int *) weechat_guile_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -801,8 +826,6 @@ weechat_guile_api_config_reload_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -813,7 +836,7 @@ weechat_guile_api_config_reload_cb (const void *pointer, void *data, SCM weechat_guile_api_config_new (SCM name, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "config_new", API_RETURN_EMPTY); @@ -828,7 +851,7 @@ weechat_guile_api_config_new (SCM name, SCM function, SCM data) API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -849,8 +872,8 @@ weechat_guile_api_config_read_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); func_argv[3] = (option_name) ? (char *)option_name : empty_arg; func_argv[4] = (value) ? (char *)value : empty_arg; @@ -866,10 +889,6 @@ weechat_guile_api_config_read_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); return ret; } @@ -894,7 +913,7 @@ weechat_guile_api_config_section_write_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); func_argv[2] = (section_name) ? (char *)section_name : empty_arg; rc = (int *) weechat_guile_exec (script, @@ -909,8 +928,6 @@ weechat_guile_api_config_section_write_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -935,7 +952,7 @@ weechat_guile_api_config_section_write_default_cb (const void *pointer, void *da if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); func_argv[2] = (section_name) ? (char *)section_name : empty_arg; rc = (int *) weechat_guile_exec (script, @@ -950,8 +967,6 @@ weechat_guile_api_config_section_write_default_cb (const void *pointer, void *da ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -978,8 +993,8 @@ weechat_guile_api_config_section_create_option_cb (const void *pointer, void *da if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); func_argv[3] = (option_name) ? (char *)option_name : empty_arg; func_argv[4] = (value) ? (char *)value : empty_arg; @@ -995,10 +1010,6 @@ weechat_guile_api_config_section_create_option_cb (const void *pointer, void *da ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); return ret; } @@ -1024,9 +1035,9 @@ weechat_guile_api_config_section_delete_option_cb (const void *pointer, void *da if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); - func_argv[3] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); + func_argv[3] = (char *)API_PTR2STR(option); rc = (int *) weechat_guile_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -1040,12 +1051,6 @@ weechat_guile_api_config_section_delete_option_cb (const void *pointer, void *da ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -1060,7 +1065,7 @@ weechat_guile_api_config_new_section (SCM args) SCM function_read, data_read, function_write, data_write; SCM function_write_default, data_write_default, function_create_option; SCM data_create_option, function_delete_option, data_delete_option; - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "config_new_section", API_RETURN_EMPTY); @@ -1115,13 +1120,13 @@ weechat_guile_api_config_new_section (SCM args) API_SCM_TO_STRING(function_delete_option), API_SCM_TO_STRING(data_delete_option))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_config_search_section (SCM config_file, SCM section_name) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "config_search_section", API_RETURN_EMPTY); @@ -1131,7 +1136,7 @@ weechat_guile_api_config_search_section (SCM config_file, SCM section_name) result = API_PTR2STR(weechat_config_search_section (API_STR2PTR(API_SCM_TO_STRING(config_file)), API_SCM_TO_STRING(section_name))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -1151,7 +1156,7 @@ weechat_guile_api_config_option_check_value_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); func_argv[2] = (value) ? (char *)value : empty_arg; rc = (int *) weechat_guile_exec (script, @@ -1166,8 +1171,6 @@ weechat_guile_api_config_option_check_value_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -1191,16 +1194,13 @@ weechat_guile_api_config_option_change_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); rc = (int *) weechat_guile_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, "ss", func_argv); - if (func_argv[1]) - free (func_argv[1]); - if (rc) free (rc); } @@ -1222,16 +1222,13 @@ weechat_guile_api_config_option_delete_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); rc = (int *) weechat_guile_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, "ss", func_argv); - if (func_argv[1]) - free (func_argv[1]); - if (rc) free (rc); } @@ -1244,7 +1241,7 @@ weechat_guile_api_config_new_option (SCM args) SCM max, default_value, value, null_value_allowed, function_check_value; SCM data_check_value, function_change, data_change, function_delete; SCM data_delete; - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "config_new_option", API_RETURN_EMPTY); @@ -1304,14 +1301,14 @@ weechat_guile_api_config_new_option (SCM args) API_SCM_TO_STRING(function_delete), API_SCM_TO_STRING(data_delete))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_config_search_option (SCM config_file, SCM section, SCM option_name) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "config_search_option", API_RETURN_EMPTY); @@ -1323,7 +1320,7 @@ weechat_guile_api_config_search_option (SCM config_file, SCM section, API_STR2PTR(API_SCM_TO_STRING(section)), API_SCM_TO_STRING(option_name))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -1503,6 +1500,7 @@ SCM weechat_guile_api_config_string (SCM option) { const char *result; + SCM return_value; API_INIT_FUNC(1, "config_string", API_RETURN_EMPTY); if (!scm_is_string (option)) @@ -1517,6 +1515,7 @@ SCM weechat_guile_api_config_string_default (SCM option) { const char *result; + SCM return_value; API_INIT_FUNC(1, "config_string_default", API_RETURN_EMPTY); if (!scm_is_string (option)) @@ -1531,6 +1530,7 @@ SCM weechat_guile_api_config_color (SCM option) { const char *result; + SCM return_value; API_INIT_FUNC(1, "config_color", API_RETURN_EMPTY); if (!scm_is_string (option)) @@ -1545,6 +1545,7 @@ SCM weechat_guile_api_config_color_default (SCM option) { const char *result; + SCM return_value; API_INIT_FUNC(1, "config_color_default", API_RETURN_EMPTY); if (!scm_is_string (option)) @@ -1678,7 +1679,7 @@ weechat_guile_api_config_free (SCM config_file) SCM weechat_guile_api_config_get (SCM option) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "config_get", API_RETURN_EMPTY); @@ -1687,13 +1688,14 @@ weechat_guile_api_config_get (SCM option) result = API_PTR2STR(weechat_config_get (API_SCM_TO_STRING(option))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_config_get_plugin (SCM option) { const char *result; + SCM return_value; API_INIT_FUNC(1, "config_get_plugin", API_RETURN_EMPTY); if (!scm_is_string (option)) @@ -1812,6 +1814,7 @@ SCM weechat_guile_api_prefix (SCM prefix) { const char *result; + SCM return_value; API_INIT_FUNC(0, "prefix", API_RETURN_EMPTY); if (!scm_is_string (prefix)) @@ -1826,6 +1829,7 @@ SCM weechat_guile_api_color (SCM color) { const char *result; + SCM return_value; API_INIT_FUNC(0, "color", API_RETURN_EMPTY); if (!scm_is_string (color)) @@ -1920,7 +1924,7 @@ weechat_guile_api_hook_command_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (argc > 1) ? argv_eol[1] : empty_arg; rc = (int *) weechat_guile_exec (script, @@ -1935,8 +1939,6 @@ weechat_guile_api_hook_command_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -1949,7 +1951,7 @@ weechat_guile_api_hook_command (SCM command, SCM description, SCM args, SCM args_description, SCM completion, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hook_command", API_RETURN_EMPTY); @@ -1970,7 +1972,7 @@ weechat_guile_api_hook_command (SCM command, SCM description, SCM args, API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -1992,8 +1994,8 @@ weechat_guile_api_hook_completion_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (completion_item) ? (char *)completion_item : empty_arg; - func_argv[2] = API_PTR2STR(buffer); - func_argv[3] = API_PTR2STR(completion); + func_argv[2] = (char *)API_PTR2STR(buffer); + func_argv[3] = (char *)API_PTR2STR(completion); rc = (int *) weechat_guile_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -2007,10 +2009,6 @@ weechat_guile_api_hook_completion_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -2022,7 +2020,7 @@ SCM weechat_guile_api_hook_completion (SCM completion, SCM description, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hook_completion", API_RETURN_EMPTY); @@ -2038,13 +2036,14 @@ weechat_guile_api_hook_completion (SCM completion, SCM description, API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_hook_completion_get_string (SCM completion, SCM property) { const char *result; + SCM return_value; API_INIT_FUNC(1, "hook_completion_get_string", API_RETURN_EMPTY); if (!scm_is_string (completion) || !scm_is_string (property)) @@ -2091,7 +2090,7 @@ weechat_guile_api_hook_command_run_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (command) ? (char *)command : empty_arg; rc = (int *) weechat_guile_exec (script, @@ -2106,8 +2105,6 @@ weechat_guile_api_hook_command_run_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -2118,7 +2115,7 @@ weechat_guile_api_hook_command_run_cb (const void *pointer, void *data, SCM weechat_guile_api_hook_command_run (SCM command, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hook_command_run", API_RETURN_EMPTY); @@ -2133,7 +2130,7 @@ weechat_guile_api_hook_command_run (SCM command, SCM function, SCM data) API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2180,7 +2177,7 @@ SCM weechat_guile_api_hook_timer (SCM interval, SCM align_second, SCM max_calls, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hook_timer", API_RETURN_EMPTY); @@ -2198,7 +2195,7 @@ weechat_guile_api_hook_timer (SCM interval, SCM align_second, SCM max_calls, API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2206,7 +2203,7 @@ weechat_guile_api_hook_fd_cb (const void *pointer, void *data, int fd) { struct t_plugin_script *script; void *func_argv[2]; - char str_fd[32], empty_arg[1] = { '\0' }; + char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; int *rc, ret; @@ -2215,15 +2212,13 @@ weechat_guile_api_hook_fd_cb (const void *pointer, void *data, int fd) if (ptr_function && ptr_function[0]) { - snprintf (str_fd, sizeof (str_fd), "%d", fd); - func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = str_fd; + func_argv[1] = &fd; rc = (int *) weechat_guile_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "ss", func_argv); + "si", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2243,7 +2238,7 @@ SCM weechat_guile_api_hook_fd (SCM fd, SCM read, SCM write, SCM exception, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hook_fd", API_RETURN_EMPTY); @@ -2262,7 +2257,7 @@ weechat_guile_api_hook_fd (SCM fd, SCM read, SCM write, SCM exception, API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2329,7 +2324,7 @@ SCM weechat_guile_api_hook_process (SCM command, SCM timeout, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hook_process", API_RETURN_EMPTY); @@ -2345,14 +2340,14 @@ weechat_guile_api_hook_process (SCM command, SCM timeout, SCM function, API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_hook_process_hashtable (SCM command, SCM options, SCM timeout, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; struct t_hashtable *c_options; @@ -2379,7 +2374,7 @@ weechat_guile_api_hook_process_hashtable (SCM command, SCM options, SCM timeout, if (c_options) weechat_hashtable_free (c_options); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2390,7 +2385,6 @@ weechat_guile_api_hook_connect_cb (const void *pointer, void *data, { struct t_plugin_script *script; void *func_argv[6]; - char str_status[32], str_gnutls_rc[32], str_sock[32]; char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; int *rc, ret; @@ -2400,21 +2394,17 @@ weechat_guile_api_hook_connect_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { - snprintf (str_status, sizeof (str_status), "%d", status); - snprintf (str_gnutls_rc, sizeof (str_gnutls_rc), "%d", gnutls_rc); - snprintf (str_sock, sizeof (str_sock), "%d", sock); - func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = str_status; - func_argv[2] = str_gnutls_rc; - func_argv[3] = str_sock; + func_argv[1] = &status; + func_argv[2] = &gnutls_rc; + func_argv[3] = &sock; func_argv[4] = (ip_address) ? (char *)ip_address : empty_arg; func_argv[5] = (error) ? (char *)error : empty_arg; rc = (int *) weechat_guile_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "ssssss", func_argv); + "siiiss", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2435,7 +2425,7 @@ weechat_guile_api_hook_connect (SCM proxy, SCM address, SCM port, SCM ipv6, SCM retry, SCM local_hostname, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hook_connect", API_RETURN_EMPTY); @@ -2461,7 +2451,7 @@ weechat_guile_api_hook_connect (SCM proxy, SCM address, SCM port, SCM ipv6, API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2487,10 +2477,10 @@ weechat_guile_api_hook_print_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { - snprintf (timebuffer, sizeof (timebuffer), "%ld", (long int)date); + snprintf (timebuffer, sizeof (timebuffer), "%lld", (long long)date); func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = timebuffer; func_argv[3] = weechat_string_build_with_split_string (tags, ","); if (!func_argv[3]) @@ -2512,8 +2502,6 @@ weechat_guile_api_hook_print_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); if (func_argv[3]) free (func_argv[3]); @@ -2527,7 +2515,7 @@ SCM weechat_guile_api_hook_print (SCM buffer, SCM tags, SCM message, SCM strip_colors, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hook_print", API_RETURN_EMPTY); @@ -2546,7 +2534,7 @@ weechat_guile_api_hook_print (SCM buffer, SCM tags, SCM message, API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2559,7 +2547,7 @@ weechat_guile_api_hook_signal_cb (const void *pointer, void *data, char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; static char str_value[64]; - int *rc, ret, free_needed; + int *rc, ret; script = (struct t_plugin_script *)pointer; plugin_script_get_function_and_data (data, &ptr_function, &ptr_data); @@ -2568,7 +2556,6 @@ weechat_guile_api_hook_signal_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (signal) ? (char *)signal : empty_arg; - free_needed = 0; if (strcmp (type_data, WEECHAT_HOOK_SIGNAL_STRING) == 0) { func_argv[2] = (signal_data) ? (char *)signal_data : empty_arg; @@ -2585,8 +2572,7 @@ weechat_guile_api_hook_signal_cb (const void *pointer, void *data, } else if (strcmp (type_data, WEECHAT_HOOK_SIGNAL_POINTER) == 0) { - func_argv[2] = API_PTR2STR(signal_data); - free_needed = 1; + func_argv[2] = (char *)API_PTR2STR(signal_data); } else func_argv[2] = empty_arg; @@ -2603,8 +2589,6 @@ weechat_guile_api_hook_signal_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (free_needed && func_argv[2]) - free (func_argv[2]); return ret; } @@ -2615,7 +2599,7 @@ weechat_guile_api_hook_signal_cb (const void *pointer, void *data, SCM weechat_guile_api_hook_signal (SCM signal, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hook_signal", API_RETURN_EMPTY); @@ -2629,7 +2613,7 @@ weechat_guile_api_hook_signal (SCM signal, SCM function, SCM data) API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -2716,7 +2700,7 @@ weechat_guile_api_hook_hsignal_cb (const void *pointer, void *data, SCM weechat_guile_api_hook_hsignal (SCM signal, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hook_hsignal", API_RETURN_EMPTY); @@ -2731,7 +2715,7 @@ weechat_guile_api_hook_hsignal (SCM signal, SCM function, SCM data) API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -2798,7 +2782,7 @@ weechat_guile_api_hook_config_cb (const void *pointer, void *data, SCM weechat_guile_api_hook_config (SCM option, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hook_config", API_RETURN_EMPTY); @@ -2813,7 +2797,7 @@ weechat_guile_api_hook_config (SCM option, SCM function, SCM data) API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } char * @@ -2849,7 +2833,7 @@ weechat_guile_api_hook_modifier_cb (const void *pointer, void *data, SCM weechat_guile_api_hook_modifier (SCM modifier, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hook_modifier", API_RETURN_EMPTY); @@ -2864,7 +2848,7 @@ weechat_guile_api_hook_modifier (SCM modifier, SCM function, SCM data) API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -2893,7 +2877,7 @@ weechat_guile_api_hook_info_cb (const void *pointer, void *data, { struct t_plugin_script *script; void *func_argv[3]; - char empty_arg[1] = { '\0' }; + char empty_arg[1] = { '\0' }, *result; const char *ptr_function, *ptr_data; script = (struct t_plugin_script *)pointer; @@ -2905,10 +2889,12 @@ weechat_guile_api_hook_info_cb (const void *pointer, void *data, func_argv[1] = (info_name) ? (char *)info_name : empty_arg; func_argv[2] = (arguments) ? (char *)arguments : empty_arg; - return (const char *)weechat_guile_exec (script, - WEECHAT_SCRIPT_EXEC_STRING, - ptr_function, - "sss", func_argv); + result = (char *)weechat_guile_exec (script, + WEECHAT_SCRIPT_EXEC_STRING, + ptr_function, + "sss", func_argv); + + return API_STATIC_STRING(result); } return NULL; @@ -2918,7 +2904,7 @@ SCM weechat_guile_api_hook_info (SCM info_name, SCM description, SCM args_description, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hook_info", API_RETURN_EMPTY); @@ -2936,7 +2922,7 @@ weechat_guile_api_hook_info (SCM info_name, SCM description, API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_hashtable * @@ -2974,7 +2960,7 @@ weechat_guile_api_hook_info_hashtable (SCM info_name, SCM description, SCM output_description, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hook_info_hashtable", API_RETURN_EMPTY); @@ -2993,7 +2979,7 @@ weechat_guile_api_hook_info_hashtable (SCM info_name, SCM description, API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_infolist * @@ -3014,18 +3000,15 @@ weechat_guile_api_hook_infolist_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (infolist_name) ? (char *)infolist_name : empty_arg; - func_argv[2] = API_PTR2STR(obj_pointer); + func_argv[2] = (char *)API_PTR2STR(obj_pointer); func_argv[3] = (arguments) ? (char *)arguments : empty_arg; result = (struct t_infolist *)weechat_guile_exec ( script, - WEECHAT_SCRIPT_EXEC_STRING, + WEECHAT_SCRIPT_EXEC_POINTER, ptr_function, "ssss", func_argv); - if (func_argv[2]) - free (func_argv[2]); - return result; } @@ -3037,7 +3020,7 @@ weechat_guile_api_hook_infolist (SCM infolist_name, SCM description, SCM pointer_description, SCM args_description, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hook_infolist", API_RETURN_EMPTY); @@ -3056,7 +3039,7 @@ weechat_guile_api_hook_infolist (SCM infolist_name, SCM description, API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_hashtable * @@ -3089,7 +3072,7 @@ weechat_guile_api_hook_focus_cb (const void *pointer, void *data, SCM weechat_guile_api_hook_focus (SCM area, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hook_focus", API_RETURN_EMPTY); @@ -3104,7 +3087,7 @@ weechat_guile_api_hook_focus (SCM area, SCM function, SCM data) API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -3161,7 +3144,7 @@ weechat_guile_api_buffer_input_data_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (input_data) ? (char *)input_data : empty_arg; rc = (int *) weechat_guile_exec (script, @@ -3176,8 +3159,6 @@ weechat_guile_api_buffer_input_data_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -3201,7 +3182,7 @@ weechat_guile_api_buffer_close_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); rc = (int *) weechat_guile_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -3215,8 +3196,6 @@ weechat_guile_api_buffer_close_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -3228,7 +3207,7 @@ SCM weechat_guile_api_buffer_new (SCM name, SCM function_input, SCM data_input, SCM function_close, SCM data_close) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "buffer_new", API_RETURN_EMPTY); @@ -3247,13 +3226,13 @@ weechat_guile_api_buffer_new (SCM name, SCM function_input, SCM data_input, API_SCM_TO_STRING(function_close), API_SCM_TO_STRING(data_close))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_buffer_search (SCM plugin, SCM name) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "buffer_search", API_RETURN_EMPTY); @@ -3263,33 +3242,33 @@ weechat_guile_api_buffer_search (SCM plugin, SCM name) result = API_PTR2STR(weechat_buffer_search (API_SCM_TO_STRING(plugin), API_SCM_TO_STRING(name))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_buffer_search_main () { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "buffer_search_main", API_RETURN_EMPTY); result = API_PTR2STR(weechat_buffer_search_main ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_current_buffer () { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "current_buffer", API_RETURN_EMPTY); result = API_PTR2STR(weechat_current_buffer ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -3361,6 +3340,7 @@ SCM weechat_guile_api_buffer_get_string (SCM buffer, SCM property) { const char *result; + SCM return_value; API_INIT_FUNC(1, "buffer_get_string", API_RETURN_EMPTY); if (!scm_is_string (buffer) || !scm_is_string (property)) @@ -3375,7 +3355,7 @@ weechat_guile_api_buffer_get_string (SCM buffer, SCM property) SCM weechat_guile_api_buffer_get_pointer (SCM buffer, SCM property) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "buffer_get_pointer", API_RETURN_EMPTY); @@ -3385,7 +3365,7 @@ weechat_guile_api_buffer_get_pointer (SCM buffer, SCM property) result = API_PTR2STR(weechat_buffer_get_pointer (API_STR2PTR(API_SCM_TO_STRING(buffer)), API_SCM_TO_STRING(property))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -3437,20 +3417,20 @@ weechat_guile_api_buffer_match_list (SCM buffer, SCM string) SCM weechat_guile_api_current_window () { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "current_window", API_RETURN_EMPTY); result = API_PTR2STR(weechat_current_window ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_window_search_with_buffer (SCM buffer) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "window_search_with_buffer", API_RETURN_EMPTY); @@ -3459,7 +3439,7 @@ weechat_guile_api_window_search_with_buffer (SCM buffer) result = API_PTR2STR(weechat_window_search_with_buffer (API_STR2PTR(API_SCM_TO_STRING(buffer)))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -3481,6 +3461,7 @@ SCM weechat_guile_api_window_get_string (SCM window, SCM property) { const char *result; + SCM return_value; API_INIT_FUNC(1, "window_get_string", API_RETURN_EMPTY); if (!scm_is_string (window) || !scm_is_string (property)) @@ -3495,7 +3476,7 @@ weechat_guile_api_window_get_string (SCM window, SCM property) SCM weechat_guile_api_window_get_pointer (SCM window, SCM property) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "window_get_pointer", API_RETURN_EMPTY); @@ -3505,7 +3486,7 @@ weechat_guile_api_window_get_pointer (SCM window, SCM property) result = API_PTR2STR(weechat_window_get_pointer (API_STR2PTR(API_SCM_TO_STRING(window)), API_SCM_TO_STRING(property))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -3524,7 +3505,7 @@ SCM weechat_guile_api_nicklist_add_group (SCM buffer, SCM parent_group, SCM name, SCM color, SCM visible) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "nicklist_add_group", API_RETURN_EMPTY); @@ -3539,13 +3520,13 @@ weechat_guile_api_nicklist_add_group (SCM buffer, SCM parent_group, SCM name, API_SCM_TO_STRING(color), scm_to_int (visible))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_nicklist_search_group (SCM buffer, SCM from_group, SCM name) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "nicklist_search_group", API_RETURN_EMPTY); @@ -3557,7 +3538,7 @@ weechat_guile_api_nicklist_search_group (SCM buffer, SCM from_group, SCM name) API_STR2PTR(API_SCM_TO_STRING(from_group)), API_SCM_TO_STRING(name))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -3565,7 +3546,7 @@ weechat_guile_api_nicklist_add_nick (SCM buffer, SCM group, SCM name, SCM color, SCM prefix, SCM prefix_color, SCM visible) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "nicklist_add_nick", API_RETURN_EMPTY); @@ -3583,13 +3564,13 @@ weechat_guile_api_nicklist_add_nick (SCM buffer, SCM group, SCM name, API_SCM_TO_STRING(prefix_color), scm_to_int (visible))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_nicklist_search_nick (SCM buffer, SCM from_group, SCM name) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "nicklist_search_nick", API_RETURN_EMPTY); @@ -3601,7 +3582,7 @@ weechat_guile_api_nicklist_search_nick (SCM buffer, SCM from_group, SCM name) API_STR2PTR(API_SCM_TO_STRING(from_group)), API_SCM_TO_STRING(name))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -3665,6 +3646,7 @@ weechat_guile_api_nicklist_group_get_string (SCM buffer, SCM group, SCM property) { const char *result; + SCM return_value; API_INIT_FUNC(1, "nicklist_group_get_string", API_RETURN_EMPTY); if (!scm_is_string (buffer) || !scm_is_string (group) @@ -3682,7 +3664,7 @@ SCM weechat_guile_api_nicklist_group_get_pointer (SCM buffer, SCM group, SCM property) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "nicklist_group_get_pointer", API_RETURN_EMPTY); @@ -3694,7 +3676,7 @@ weechat_guile_api_nicklist_group_get_pointer (SCM buffer, SCM group, API_STR2PTR(API_SCM_TO_STRING(group)), API_SCM_TO_STRING(property))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -3734,6 +3716,7 @@ SCM weechat_guile_api_nicklist_nick_get_string (SCM buffer, SCM nick, SCM property) { const char *result; + SCM return_value; API_INIT_FUNC(1, "nicklist_nick_get_string", API_RETURN_EMPTY); if (!scm_is_string (buffer) || !scm_is_string (nick) @@ -3750,7 +3733,7 @@ weechat_guile_api_nicklist_nick_get_string (SCM buffer, SCM nick, SCM property) SCM weechat_guile_api_nicklist_nick_get_pointer (SCM buffer, SCM nick, SCM property) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "nicklist_nick_get_pointer", API_RETURN_EMPTY); @@ -3762,7 +3745,7 @@ weechat_guile_api_nicklist_nick_get_pointer (SCM buffer, SCM nick, SCM property) API_STR2PTR(API_SCM_TO_STRING(nick)), API_SCM_TO_STRING(property))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -3785,7 +3768,7 @@ weechat_guile_api_nicklist_nick_set (SCM buffer, SCM nick, SCM property, SCM weechat_guile_api_bar_item_search (SCM name) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "bar_item_search", API_RETURN_EMPTY); @@ -3794,7 +3777,7 @@ weechat_guile_api_bar_item_search (SCM name) result = API_PTR2STR(weechat_bar_item_search (API_SCM_TO_STRING(name))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } char * @@ -3818,39 +3801,27 @@ weechat_guile_api_bar_item_build_cb (const void *pointer, void *data, { /* new callback: data, item, window, buffer, extra_info */ func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(item); - func_argv[2] = API_PTR2STR(window); - func_argv[3] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(item); + func_argv[2] = (char *)API_PTR2STR(window); + func_argv[3] = (char *)API_PTR2STR(buffer); func_argv[4] = extra_info; ret = (char *)weechat_guile_exec (script, WEECHAT_SCRIPT_EXEC_STRING, ptr_function + 7, "ssssh", func_argv); - - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); } else { /* old callback: data, item, window */ func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(item); - func_argv[2] = API_PTR2STR(window); + func_argv[1] = (char *)API_PTR2STR(item); + func_argv[2] = (char *)API_PTR2STR(window); ret = (char *)weechat_guile_exec (script, WEECHAT_SCRIPT_EXEC_STRING, ptr_function, "sss", func_argv); - - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); } return ret; @@ -3862,7 +3833,7 @@ weechat_guile_api_bar_item_build_cb (const void *pointer, void *data, SCM weechat_guile_api_bar_item_new (SCM name, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "bar_item_new", API_RETURN_EMPTY); @@ -3877,7 +3848,7 @@ weechat_guile_api_bar_item_new (SCM name, SCM function, SCM data) API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -3907,7 +3878,7 @@ weechat_guile_api_bar_item_remove (SCM item) SCM weechat_guile_api_bar_search (SCM name) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "bar_search", API_RETURN_EMPTY); @@ -3916,7 +3887,7 @@ weechat_guile_api_bar_search (SCM name) result = API_PTR2STR(weechat_bar_search (API_SCM_TO_STRING(name))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -3925,7 +3896,7 @@ weechat_guile_api_bar_new (SCM args) SCM name, hidden, priority, type, conditions, position, filling_top_bottom; SCM filling_left_right, size, size_max, color_fg, color_delim, color_bg; SCM separator, items; - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "bar_new", API_RETURN_EMPTY); @@ -3974,7 +3945,7 @@ weechat_guile_api_bar_new (SCM args) API_SCM_TO_STRING(separator), API_SCM_TO_STRING(items))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -4039,6 +4010,7 @@ SCM weechat_guile_api_info_get (SCM info_name, SCM arguments) { const char *result; + SCM return_value; API_INIT_FUNC(1, "info_get", API_RETURN_EMPTY); if (!scm_is_string (info_name) || !scm_is_string (arguments)) @@ -4080,20 +4052,20 @@ weechat_guile_api_info_get_hashtable (SCM info_name, SCM hash) SCM weechat_guile_api_infolist_new () { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "infolist_new", API_RETURN_EMPTY); result = API_PTR2STR(weechat_infolist_new ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_infolist_new_item (SCM infolist) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "infolist_new_item", API_RETURN_EMPTY); @@ -4102,13 +4074,13 @@ weechat_guile_api_infolist_new_item (SCM infolist) result = API_PTR2STR(weechat_infolist_new_item (API_STR2PTR(API_SCM_TO_STRING(infolist)))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_infolist_new_var_integer (SCM item, SCM name, SCM value) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "infolist_new_var_integer", API_RETURN_EMPTY); @@ -4120,13 +4092,13 @@ weechat_guile_api_infolist_new_var_integer (SCM item, SCM name, SCM value) API_SCM_TO_STRING(name), scm_to_int (value))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_infolist_new_var_string (SCM item, SCM name, SCM value) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "infolist_new_var_string", API_RETURN_EMPTY); @@ -4138,13 +4110,13 @@ weechat_guile_api_infolist_new_var_string (SCM item, SCM name, SCM value) API_SCM_TO_STRING(name), API_SCM_TO_STRING(value))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_infolist_new_var_pointer (SCM item, SCM name, SCM value) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "infolist_new_var_pointer", API_RETURN_EMPTY); @@ -4156,13 +4128,13 @@ weechat_guile_api_infolist_new_var_pointer (SCM item, SCM name, SCM value) API_SCM_TO_STRING(name), API_STR2PTR(API_SCM_TO_STRING(value)))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_infolist_new_var_time (SCM item, SCM name, SCM value) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "infolist_new_var_time", API_RETURN_EMPTY); @@ -4174,13 +4146,13 @@ weechat_guile_api_infolist_new_var_time (SCM item, SCM name, SCM value) API_SCM_TO_STRING(name), scm_to_int (value))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_infolist_search_var (SCM infolist, SCM name) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "infolist_search_var", API_RETURN_EMPTY); @@ -4190,13 +4162,13 @@ weechat_guile_api_infolist_search_var (SCM infolist, SCM name) result = API_PTR2STR(weechat_infolist_search_var (API_STR2PTR(API_SCM_TO_STRING(infolist)), API_SCM_TO_STRING(name))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_infolist_get (SCM name, SCM pointer, SCM arguments) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "infolist_get", API_RETURN_EMPTY); @@ -4208,7 +4180,7 @@ weechat_guile_api_infolist_get (SCM name, SCM pointer, SCM arguments) API_STR2PTR(API_SCM_TO_STRING(pointer)), API_SCM_TO_STRING(arguments))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -4255,6 +4227,7 @@ SCM weechat_guile_api_infolist_fields (SCM infolist) { const char *result; + SCM return_value; API_INIT_FUNC(1, "infolist_fields", API_RETURN_EMPTY); if (!scm_is_string (infolist)) @@ -4284,6 +4257,7 @@ SCM weechat_guile_api_infolist_string (SCM infolist, SCM variable) { const char *result; + SCM return_value; API_INIT_FUNC(1, "infolist_string", API_RETURN_EMPTY); if (!scm_is_string (infolist) || !scm_is_string (variable)) @@ -4298,7 +4272,7 @@ weechat_guile_api_infolist_string (SCM infolist, SCM variable) SCM weechat_guile_api_infolist_pointer (SCM infolist, SCM variable) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "infolist_pointer", API_RETURN_EMPTY); @@ -4308,30 +4282,22 @@ weechat_guile_api_infolist_pointer (SCM infolist, SCM variable) result = API_PTR2STR(weechat_infolist_pointer (API_STR2PTR(API_SCM_TO_STRING(infolist)), API_SCM_TO_STRING(variable))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_infolist_time (SCM infolist, SCM variable) { - char timebuffer[64], *result; time_t time; - struct tm *date_tmp; - SCM return_value; - API_INIT_FUNC(1, "infolist_time", API_RETURN_EMPTY); + API_INIT_FUNC(1, "infolist_time", API_RETURN_LONG(0)); if (!scm_is_string (infolist) || !scm_is_string (variable)) - API_WRONG_ARGS(API_RETURN_EMPTY); + API_WRONG_ARGS(API_RETURN_LONG(0)); - timebuffer[0] = '\0'; time = weechat_infolist_time (API_STR2PTR(API_SCM_TO_STRING(infolist)), API_SCM_TO_STRING(variable)); - date_tmp = localtime (&time); - if (date_tmp) - strftime (timebuffer, sizeof (timebuffer), "%F %T", date_tmp); - result = strdup (timebuffer); - API_RETURN_STRING_FREE(result); + API_RETURN_LONG(time); } SCM @@ -4349,7 +4315,7 @@ weechat_guile_api_infolist_free (SCM infolist) SCM weechat_guile_api_hdata_get (SCM name) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hdata_get", API_RETURN_EMPTY); @@ -4358,7 +4324,7 @@ weechat_guile_api_hdata_get (SCM name) result = API_PTR2STR(weechat_hdata_get (API_SCM_TO_STRING(name))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -4380,6 +4346,7 @@ SCM weechat_guile_api_hdata_get_var_type_string (SCM hdata, SCM name) { const char *result; + SCM return_value; API_INIT_FUNC(1, "hdata_get_var_type_string", API_RETURN_EMPTY); if (!scm_is_string (hdata) || !scm_is_string (name)) @@ -4413,6 +4380,7 @@ weechat_guile_api_hdata_get_var_array_size_string (SCM hdata, SCM pointer, SCM name) { const char *result; + SCM return_value; API_INIT_FUNC(1, "hdata_get_var_array_size_string", API_RETURN_EMPTY); if (!scm_is_string (hdata) || !scm_is_string (pointer) @@ -4430,6 +4398,7 @@ SCM weechat_guile_api_hdata_get_var_hdata (SCM hdata, SCM name) { const char *result; + SCM return_value; API_INIT_FUNC(1, "hdata_get_var_hdata", API_RETURN_EMPTY); if (!scm_is_string (hdata) || !scm_is_string (name)) @@ -4444,7 +4413,7 @@ weechat_guile_api_hdata_get_var_hdata (SCM hdata, SCM name) SCM weechat_guile_api_hdata_get_list (SCM hdata, SCM name) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hdata_get_list", API_RETURN_EMPTY); @@ -4454,7 +4423,7 @@ weechat_guile_api_hdata_get_list (SCM hdata, SCM name) result = API_PTR2STR(weechat_hdata_get_list (API_STR2PTR(API_SCM_TO_STRING(hdata)), API_SCM_TO_STRING(name))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -4477,7 +4446,7 @@ weechat_guile_api_hdata_check_pointer (SCM hdata, SCM list, SCM pointer) SCM weechat_guile_api_hdata_move (SCM hdata, SCM pointer, SCM count) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hdata_move", API_RETURN_EMPTY); @@ -4489,13 +4458,13 @@ weechat_guile_api_hdata_move (SCM hdata, SCM pointer, SCM count) API_STR2PTR(API_SCM_TO_STRING(pointer)), scm_to_int (count))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM weechat_guile_api_hdata_search (SCM hdata, SCM pointer, SCM search, SCM move) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hdata_search", API_RETURN_EMPTY); @@ -4508,7 +4477,7 @@ weechat_guile_api_hdata_search (SCM hdata, SCM pointer, SCM search, SCM move) API_SCM_TO_STRING(search), scm_to_int (move))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -4566,6 +4535,7 @@ SCM weechat_guile_api_hdata_string (SCM hdata, SCM pointer, SCM name) { const char *result; + SCM return_value; API_INIT_FUNC(1, "hdata_string", API_RETURN_EMPTY); if (!scm_is_string (hdata) || !scm_is_string (pointer) @@ -4582,7 +4552,7 @@ weechat_guile_api_hdata_string (SCM hdata, SCM pointer, SCM name) SCM weechat_guile_api_hdata_pointer (SCM hdata, SCM pointer, SCM name) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "hdata_pointer", API_RETURN_EMPTY); @@ -4594,7 +4564,7 @@ weechat_guile_api_hdata_pointer (SCM hdata, SCM pointer, SCM name) API_STR2PTR(API_SCM_TO_STRING(pointer)), API_SCM_TO_STRING(name))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -4681,6 +4651,7 @@ SCM weechat_guile_api_hdata_get_string (SCM hdata, SCM property) { const char *result; + SCM return_value; API_INIT_FUNC(1, "hdata_get_string", API_RETURN_EMPTY); if (!scm_is_string (hdata) || !scm_is_string (property)) @@ -4712,9 +4683,9 @@ weechat_guile_api_upgrade_read_cb (const void *pointer, void *data, snprintf (str_object_id, sizeof (str_object_id), "%d", object_id); func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(upgrade_file); + func_argv[1] = (char *)API_PTR2STR(upgrade_file); func_argv[2] = str_object_id; - func_argv[3] = API_PTR2STR(infolist); + func_argv[3] = (char *)API_PTR2STR(infolist); rc = (int *) weechat_guile_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -4728,10 +4699,6 @@ weechat_guile_api_upgrade_read_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -4742,7 +4709,7 @@ weechat_guile_api_upgrade_read_cb (const void *pointer, void *data, SCM weechat_guile_api_upgrade_new (SCM filename, SCM function, SCM data) { - char *result; + const char *result; SCM return_value; API_INIT_FUNC(1, "upgrade_new", API_RETURN_EMPTY); @@ -4759,7 +4726,7 @@ weechat_guile_api_upgrade_new (SCM filename, SCM function, SCM data) API_SCM_TO_STRING(function), API_SCM_TO_STRING(data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } SCM @@ -4839,6 +4806,7 @@ weechat_guile_api_module_init (void *data) API_DEF_FUNC(string_has_highlight, 2); API_DEF_FUNC(string_has_highlight_regex, 2); API_DEF_FUNC(string_mask_to_regex, 1); + API_DEF_FUNC(string_format_size, 1); API_DEF_FUNC(string_remove_color, 2); API_DEF_FUNC(string_is_command_char, 1); API_DEF_FUNC(string_input_for_buffer, 1); diff --git a/src/plugins/guile/weechat-guile-api.h b/src/plugins/guile/weechat-guile-api.h index 0e8371f5f..079c3e623 100644 --- a/src/plugins/guile/weechat-guile-api.h +++ b/src/plugins/guile/weechat-guile-api.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2011-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_GUILE_API_H -#define WEECHAT_GUILE_API_H 1 +#ifndef WEECHAT_PLUGIN_GUILE_API_H +#define WEECHAT_PLUGIN_GUILE_API_H extern int weechat_guile_api_buffer_input_data_cb (const void *pointer, void *data, @@ -29,4 +29,4 @@ extern int weechat_guile_api_buffer_close_cb (const void *pointer, struct t_gui_buffer *buffer); extern void weechat_guile_api_module_init (void *data); -#endif /* WEECHAT_GUILE_API_H */ +#endif /* WEECHAT_PLUGIN_GUILE_API_H */ diff --git a/src/plugins/guile/weechat-guile.c b/src/plugins/guile/weechat-guile.c index b79f9049d..52f0c8631 100644 --- a/src/plugins/guile/weechat-guile.c +++ b/src/plugins/guile/weechat-guile.c @@ -1,7 +1,7 @@ /* * weechat-guile.c - guile (scheme) plugin for WeeChat * - * Copyright (C) 2011-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2011-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -42,11 +42,33 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Support of scheme scripts (with Guile)")); WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(3000); +WEECHAT_PLUGIN_PRIORITY(4000); struct t_weechat_plugin *weechat_guile_plugin = NULL; -int guile_quiet; +struct t_plugin_script_data guile_data; + +struct t_config_file *guile_config_file = NULL; +struct t_config_option *guile_config_look_check_license = NULL; +struct t_config_option *guile_config_look_eval_keep_context = NULL; + +int guile_quiet = 0; + +struct t_plugin_script *guile_script_eval = NULL; +int guile_eval_mode = 0; +int guile_eval_send_input = 0; +int guile_eval_exec_commands = 0; +struct t_gui_buffer *guile_eval_buffer = NULL; +char *guile_eval_output = NULL; +#define GUILE_EVAL_SCRIPT \ + "(weechat:register \"" WEECHAT_SCRIPT_EVAL_NAME "\" \"\" \"1.0\" " \ + "\"" WEECHAT_LICENSE "\" \"Evaluation of source code\" " \ + "\"\" \"\")\n" \ + "\n" \ + "(define (script_guile_eval code)\n" \ + " (eval-string code)\n" \ + ")\n" + struct t_plugin_script *guile_scripts = NULL; struct t_plugin_script *last_guile_script = NULL; struct t_plugin_script *guile_current_script = NULL; @@ -54,7 +76,7 @@ struct t_plugin_script *guile_registered_script = NULL; const char *guile_current_script_filename = NULL; SCM guile_module_weechat; SCM guile_port; -char *guile_stdout = NULL; +char **guile_buffer_output = NULL; struct t_guile_function { @@ -89,20 +111,66 @@ char *guile_action_autoload_list = NULL; /* - * Flushes stdout. + * Flushes output. */ void -weechat_guile_stdout_flush () +weechat_guile_output_flush () { - if (guile_stdout) + const char *ptr_command; + char *command; + int length; + + if (!*guile_buffer_output[0]) + return; + + if (guile_eval_mode) { - weechat_printf (NULL, - weechat_gettext ("%s: stdout/stderr: %s%s"), - GUILE_PLUGIN_NAME, guile_stdout, ""); - free (guile_stdout); - guile_stdout = NULL; + /* if there's no buffer, we catch the output, so there's no flush */ + if (!guile_eval_buffer) + return; + + if (guile_eval_send_input) + { + if (guile_eval_exec_commands) + ptr_command = *guile_buffer_output; + else + ptr_command = weechat_string_input_for_buffer (*guile_buffer_output); + if (ptr_command) + { + weechat_command (guile_eval_buffer, *guile_buffer_output); + } + else + { + length = 1 + strlen (*guile_buffer_output) + 1; + command = malloc (length); + if (command) + { + snprintf (command, length, "%c%s", + *guile_buffer_output[0], *guile_buffer_output); + weechat_command (guile_eval_buffer, + (command[0]) ? command : " "); + free (command); + } + } + } + else + { + weechat_printf (guile_eval_buffer, "%s", *guile_buffer_output); + } + } + else + { + /* script (no eval mode) */ + weechat_printf ( + NULL, + weechat_gettext ("%s: stdout/stderr (%s): %s"), + GUILE_PLUGIN_NAME, + (guile_current_script) ? guile_current_script->name : "?", + *guile_buffer_output); } + + weechat_string_dyn_copy (guile_buffer_output, NULL); } /* @@ -269,9 +337,11 @@ weechat_guile_exec (struct t_plugin_script *script, { struct t_plugin_script *old_guile_current_script; SCM rc, old_current_module; - void *argv2[17], *ret_value; + void *argv2[17], *ret_value, *ret_temp; int i, argc, *ret_int; + ret_value = NULL; + old_guile_current_script = guile_current_script; old_current_module = NULL; if (script->interpreter) @@ -310,12 +380,27 @@ weechat_guile_exec (struct t_plugin_script *script, rc = weechat_guile_exec_function (function, NULL, 0); } - ret_value = NULL; + weechat_guile_output_flush (); if ((ret_type == WEECHAT_SCRIPT_EXEC_STRING) && (scm_is_string (rc))) { ret_value = scm_to_locale_string (rc); } + else if ((ret_type == WEECHAT_SCRIPT_EXEC_POINTER) && (scm_is_string (rc))) + { + ret_temp = scm_to_locale_string (rc); + if (ret_temp) + { + ret_value = plugin_script_str2ptr (weechat_guile_plugin, + script->name, function, + ret_temp); + free (ret_temp); + } + else + { + ret_value = NULL; + } + } else if ((ret_type == WEECHAT_SCRIPT_EXEC_INT) && (scm_is_integer (rc))) { ret_int = malloc (sizeof (*ret_int)); @@ -332,13 +417,17 @@ weechat_guile_exec (struct t_plugin_script *script, } else { - weechat_printf (NULL, - weechat_gettext ("%s%s: function \"%s\" must return " - "a valid value"), - weechat_prefix ("error"), GUILE_PLUGIN_NAME, function); + if (ret_type != WEECHAT_SCRIPT_EXEC_IGNORE) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: function \"%s\" must " + "return a valid value"), + weechat_prefix ("error"), GUILE_PLUGIN_NAME, + function); + } } - if (ret_value == NULL) + if ((ret_type != WEECHAT_SCRIPT_EXEC_IGNORE) && !ret_value) { weechat_printf (NULL, weechat_gettext ("%s%s: error in function \"%s\""), @@ -354,16 +443,43 @@ weechat_guile_exec (struct t_plugin_script *script, } /* - * Initializes guile module for script. + * Initializes guile module for a script file. */ void -weechat_guile_module_init_script (void *data) +weechat_guile_module_init_file (void *filename) { SCM rc; weechat_guile_catch (scm_c_eval_string, "(use-modules (weechat))"); - rc = weechat_guile_catch (scm_c_primitive_load, data); + rc = weechat_guile_catch (scm_c_primitive_load, filename); + + /* error loading script? */ + if (rc == SCM_BOOL_F) + { + /* if script was registered, remove it from list */ + if (guile_current_script) + { + plugin_script_remove (weechat_guile_plugin, + &guile_scripts, &last_guile_script, + guile_current_script); + } + guile_current_script = NULL; + guile_registered_script = NULL; + } +} + +/* + * Initializes guile module for a string with guile code. + */ + +void +weechat_guile_module_init_code (void *code) +{ + SCM rc; + + weechat_guile_catch (scm_c_eval_string, "(use-modules (weechat))"); + rc = weechat_guile_catch (scm_c_eval_string, code); /* error loading script? */ if (rc == SCM_BOOL_F) @@ -383,16 +499,30 @@ weechat_guile_module_init_script (void *data) /* * Loads a guile script. * - * Returns: - * 1: OK - * 0: error + * If code is NULL, the content of filename is read and executed. + * If code is not NULL, it is executed (the file is not read). + * + * Returns pointer to new registered script, NULL if error. */ -int -weechat_guile_load (const char *filename) +struct t_plugin_script * +weechat_guile_load (const char *filename, const char *code) { char *filename2, *ptr_base_name, *base_name; SCM module; + struct stat buf; + + if (!code) + { + if (stat (filename, &buf) != 0) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: script \"%s\" not found"), + weechat_prefix ("error"), GUILE_PLUGIN_NAME, + filename); + return NULL; + } + } if ((weechat_guile_plugin->debug >= 2) || !guile_quiet) { @@ -405,15 +535,24 @@ weechat_guile_load (const char *filename) guile_registered_script = NULL; guile_current_script_filename = filename; - filename2 = strdup (filename); - if (!filename2) - return 0; - - ptr_base_name = basename (filename2); - base_name = strdup (ptr_base_name); - module = scm_c_define_module (base_name, - &weechat_guile_module_init_script, filename2); - free (filename2); + if (code) + { + module = scm_c_define_module (filename, + &weechat_guile_module_init_code, + (char *)code); + } + else + { + filename2 = strdup (filename); + if (!filename2) + return NULL; + ptr_base_name = basename (filename2); + base_name = strdup (ptr_base_name); + module = scm_c_define_module (base_name, + &weechat_guile_module_init_file, + filename2); + free (filename2); + } if (!guile_registered_script) { @@ -421,7 +560,7 @@ weechat_guile_load (const char *filename) weechat_gettext ("%s%s: function \"register\" not " "found (or failed) in file \"%s\""), weechat_prefix ("error"), GUILE_PLUGIN_NAME, filename); - return 0; + return NULL; } weechat_guile_catch (scm_gc_protect_object, (void *)module); @@ -442,7 +581,7 @@ weechat_guile_load (const char *filename) WEECHAT_HOOK_SIGNAL_STRING, guile_current_script->filename); - return 1; + return guile_current_script; } /* @@ -455,7 +594,7 @@ weechat_guile_load_cb (void *data, const char *filename) /* make C compiler happy */ (void) data; - weechat_guile_load (filename); + weechat_guile_load (filename, NULL); } /* @@ -570,7 +709,7 @@ weechat_guile_reload_name (const char *name) weechat_gettext ("%s: script \"%s\" unloaded"), GUILE_PLUGIN_NAME, name); } - weechat_guile_load (filename); + weechat_guile_load (filename, NULL); free (filename); } } @@ -583,6 +722,64 @@ weechat_guile_reload_name (const char *name) } /* + * Evaluates guile source code. + * + * Returns: + * 1: OK + * 0: error + */ + +int +weechat_guile_eval (struct t_gui_buffer *buffer, int send_to_buffer_as_input, + int exec_commands, const char *code) +{ + void *func_argv[1], *result; + + if (!guile_script_eval) + { + guile_quiet = 1; + guile_script_eval = weechat_guile_load (WEECHAT_SCRIPT_EVAL_NAME, + GUILE_EVAL_SCRIPT); + guile_quiet = 0; + if (!guile_script_eval) + return 0; + } + + weechat_guile_output_flush (); + + guile_eval_mode = 1; + guile_eval_send_input = send_to_buffer_as_input; + guile_eval_exec_commands = exec_commands; + guile_eval_buffer = buffer; + + func_argv[0] = (char *)code; + result = weechat_guile_exec (guile_script_eval, + WEECHAT_SCRIPT_EXEC_IGNORE, + "script_guile_eval", + "s", func_argv); + /* result is ignored */ + if (result) + free (result); + + weechat_guile_output_flush (); + + guile_eval_mode = 0; + guile_eval_send_input = 0; + guile_eval_exec_commands = 0; + guile_eval_buffer = NULL; + + if (!weechat_config_boolean (guile_config_look_eval_keep_context)) + { + guile_quiet = 1; + weechat_guile_unload (guile_script_eval); + guile_quiet = 0; + guile_script_eval = NULL; + } + + return 1; +} + +/* * Callback for command "/guile". */ @@ -591,13 +788,12 @@ weechat_guile_command_cb (const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { - char *ptr_name, *path_script; - SCM value; + char *ptr_name, *ptr_code, *path_script; + int i, send_to_buffer_as_input, exec_commands; /* make C compiler happy */ (void) pointer; (void) data; - (void) buffer; if (argc == 1) { @@ -629,6 +825,10 @@ weechat_guile_command_cb (const void *pointer, void *data, { weechat_guile_unload_all (); } + else if (weechat_strcasecmp (argv[1], "version") == 0) + { + plugin_script_display_interpreter (weechat_guile_plugin, 0); + } else WEECHAT_COMMAND_ERROR; } @@ -663,7 +863,8 @@ weechat_guile_command_cb (const void *pointer, void *data, /* load guile script */ path_script = plugin_script_search_path (weechat_guile_plugin, ptr_name); - weechat_guile_load ((path_script) ? path_script : ptr_name); + weechat_guile_load ((path_script) ? path_script : ptr_name, + NULL); if (path_script) free (path_script); } @@ -681,14 +882,36 @@ weechat_guile_command_cb (const void *pointer, void *data, } else if (weechat_strcasecmp (argv[1], "eval") == 0) { - /* eval guile code */ - value = weechat_guile_catch (scm_c_eval_string, argv_eol[2]); - if (!SCM_EQ_P (value, SCM_UNDEFINED) - && !SCM_EQ_P (value, SCM_UNSPECIFIED)) + send_to_buffer_as_input = 0; + exec_commands = 0; + ptr_code = argv_eol[2]; + for (i = 2; i < argc; i++) { - scm_display (value, guile_port); + if (argv[i][0] == '-') + { + if (strcmp (argv[i], "-o") == 0) + { + if (i + 1 >= argc) + WEECHAT_COMMAND_ERROR; + send_to_buffer_as_input = 1; + exec_commands = 0; + ptr_code = argv_eol[i + 1]; + } + else if (strcmp (argv[i], "-oc") == 0) + { + if (i + 1 >= argc) + WEECHAT_COMMAND_ERROR; + send_to_buffer_as_input = 1; + exec_commands = 1; + ptr_code = argv_eol[i + 1]; + } + } + else + break; } - weechat_guile_stdout_flush (); + if (!weechat_guile_eval (buffer, send_to_buffer_as_input, + exec_commands, ptr_code)) + WEECHAT_COMMAND_ERROR; } else WEECHAT_COMMAND_ERROR; @@ -736,6 +959,29 @@ weechat_guile_hdata_cb (const void *pointer, void *data, } /* + * Returns guile info "guile_eval". + */ + +const char * +weechat_guile_info_eval_cb (const void *pointer, void *data, + const char *info_name, + const char *arguments) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) info_name; + + weechat_guile_eval (NULL, 0, 0, (arguments) ? arguments : ""); + if (guile_eval_output) + free (guile_eval_output); + guile_eval_output = strdup (*guile_buffer_output); + weechat_string_dyn_copy (guile_buffer_output, NULL); + + return guile_eval_output; +} + +/* * Returns infolist with guile scripts. */ @@ -786,35 +1032,6 @@ weechat_guile_signal_debug_dump_cb (const void *pointer, void *data, } /* - * Display infos about external libraries used. - */ - -int -weechat_guile_signal_debug_libs_cb (const void *pointer, void *data, - const char *signal, - const char *type_data, void *signal_data) -{ - /* make C compiler happy */ - (void) pointer; - (void) data; - (void) signal; - (void) type_data; - (void) signal_data; - -#if defined(SCM_MAJOR_VERSION) && defined(SCM_MINOR_VERSION) && defined(SCM_MICRO_VERSION) - weechat_printf (NULL, " %s: %d.%d.%d", - GUILE_PLUGIN_NAME, - SCM_MAJOR_VERSION, - SCM_MINOR_VERSION, - SCM_MICRO_VERSION); -#else - weechat_printf (NULL, " %s: (?)", GUILE_PLUGIN_NAME); -#endif /* defined(SCM_MAJOR_VERSION) && defined(SCM_MINOR_VERSION) && defined(SCM_MICRO_VERSION) */ - - return WEECHAT_RC_OK; -} - -/* * Timer for executing actions. */ @@ -921,39 +1138,28 @@ weechat_guile_port_fill_input (SCM port) void weechat_guile_port_write (SCM port, const void *data, size_t size) { - char *new_stdout; - int length_stdout; + char *data2, *ptr_data, *ptr_newline; /* make C compiler happy */ (void) port; - /* concatenate str to guile_stdout */ - if (guile_stdout) + data2 = malloc (size + 1); + if (!data2) + return; + + memcpy (data2, data, size); + data2[size] = '\0'; + + ptr_data = data2; + while ((ptr_newline = strchr (ptr_data, '\n')) != NULL) { - length_stdout = strlen (guile_stdout); - new_stdout = realloc (guile_stdout, length_stdout + size + 1); - if (!new_stdout) - { - free (guile_stdout); - return; - } - guile_stdout = new_stdout; - memcpy (guile_stdout + length_stdout, data, size); - guile_stdout[length_stdout + size] = '\0'; + ptr_newline[0] = '\0'; + weechat_string_dyn_concat (guile_buffer_output, ptr_data); + weechat_guile_output_flush (); + ptr_newline[0] = '\n'; + ptr_data = ++ptr_newline; } - else - { - guile_stdout = malloc (size + 1); - if (guile_stdout) - { - memcpy (guile_stdout, data, size); - guile_stdout[size] = '\0'; - } - } - - /* flush stdout if at least "\n" is in string */ - if (guile_stdout && (strchr (guile_stdout, '\n'))) - weechat_guile_stdout_flush (); + weechat_string_dyn_concat (guile_buffer_output, ptr_data); } /* @@ -963,11 +1169,31 @@ weechat_guile_port_write (SCM port, const void *data, size_t size) int weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) { - struct t_plugin_script_init init; + char str_version[128]; weechat_guile_plugin = plugin; - guile_stdout = NULL; + /* set interpreter name and version */ + weechat_hashtable_set (plugin->variables, "interpreter_name", + plugin->name); +#if defined(SCM_MAJOR_VERSION) && defined(SCM_MINOR_VERSION) && defined(SCM_MICRO_VERSION) + snprintf (str_version, sizeof (str_version), + "%d.%d.%d", + SCM_MAJOR_VERSION, + SCM_MINOR_VERSION, + SCM_MICRO_VERSION); + weechat_hashtable_set (plugin->variables, "interpreter_version", + str_version); +#else + (void) str_version; + weechat_hashtable_set (plugin->variables, "interpreter_version", + ""); +#endif /* defined(SCM_MAJOR_VERSION) && defined(SCM_MINOR_VERSION) && defined(SCM_MICRO_VERSION) */ + + /* init stdout/stderr buffer */ + guile_buffer_output = weechat_string_dyn_alloc (256); + if (!guile_buffer_output) + return WEECHAT_RC_ERROR; #ifdef HAVE_GUILE_GMP_MEMORY_FUNCTIONS /* @@ -986,17 +1212,23 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) scm_c_use_module ("weechat"); weechat_guile_catch (scm_gc_protect_object, (void *)guile_module_weechat); - init.callback_command = &weechat_guile_command_cb; - init.callback_completion = &weechat_guile_completion_cb; - init.callback_hdata = &weechat_guile_hdata_cb; - init.callback_infolist = &weechat_guile_infolist_cb; - init.callback_signal_debug_dump = &weechat_guile_signal_debug_dump_cb; - init.callback_signal_debug_libs = &weechat_guile_signal_debug_libs_cb; - init.callback_signal_script_action = &weechat_guile_signal_script_action_cb; - init.callback_load_file = &weechat_guile_load_cb; + guile_data.config_file = &guile_config_file; + guile_data.config_look_check_license = &guile_config_look_check_license; + guile_data.config_look_eval_keep_context = &guile_config_look_eval_keep_context; + guile_data.scripts = &guile_scripts; + guile_data.last_script = &last_guile_script; + guile_data.callback_command = &weechat_guile_command_cb; + guile_data.callback_completion = &weechat_guile_completion_cb; + guile_data.callback_hdata = &weechat_guile_hdata_cb; + guile_data.callback_info_eval = &weechat_guile_info_eval_cb; + guile_data.callback_infolist = &weechat_guile_infolist_cb; + guile_data.callback_signal_debug_dump = &weechat_guile_signal_debug_dump_cb; + guile_data.callback_signal_script_action = &weechat_guile_signal_script_action_cb; + guile_data.callback_load_file = &weechat_guile_load_cb; + guile_data.unload_all = &weechat_guile_unload_all; guile_quiet = 1; - plugin_script_init (weechat_guile_plugin, argc, argv, &init); + plugin_script_init (weechat_guile_plugin, argc, argv, &guile_data); guile_quiet = 0; plugin_script_display_short_list (weechat_guile_plugin, @@ -1015,7 +1247,12 @@ weechat_plugin_end (struct t_weechat_plugin *plugin) { /* unload all scripts */ guile_quiet = 1; - plugin_script_end (plugin, &guile_scripts, &weechat_guile_unload_all); + if (guile_script_eval) + { + weechat_guile_unload (guile_script_eval); + guile_script_eval = NULL; + } + plugin_script_end (plugin, &guile_data); guile_quiet = 0; /* unprotect module */ @@ -1028,6 +1265,9 @@ weechat_plugin_end (struct t_weechat_plugin *plugin) free (guile_action_remove_list); if (guile_action_autoload_list) free (guile_action_autoload_list); + weechat_string_dyn_free (guile_buffer_output, 1); + if (guile_eval_output) + free (guile_eval_output); return WEECHAT_RC_OK; } diff --git a/src/plugins/guile/weechat-guile.h b/src/plugins/guile/weechat-guile.h index 2ef3a5900..d2b7d4028 100644 --- a/src/plugins/guile/weechat-guile.h +++ b/src/plugins/guile/weechat-guile.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2011-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_GUILE_H -#define WEECHAT_GUILE_H 1 +#ifndef WEECHAT_PLUGIN_GUILE_H +#define WEECHAT_PLUGIN_GUILE_H #define weechat_plugin weechat_guile_plugin #define GUILE_PLUGIN_NAME "guile" @@ -27,6 +27,8 @@ extern struct t_weechat_plugin *weechat_guile_plugin; +extern struct t_plugin_script_data guile_data; + extern int guile_quiet; extern struct t_plugin_script *guile_scripts; extern struct t_plugin_script *last_guile_script; @@ -46,4 +48,4 @@ extern void *weechat_guile_exec (struct t_plugin_script *script, extern int weechat_guile_port_fill_input (SCM port); extern void weechat_guile_port_write (SCM port, const void *data, size_t size); -#endif /* WEECHAT_GUILE_H */ +#endif /* WEECHAT_PLUGIN_GUILE_H */ diff --git a/src/plugins/irc/CMakeLists.txt b/src/plugins/irc/CMakeLists.txt index a5703afef..f205adbc5 100644 --- a/src/plugins/irc/CMakeLists.txt +++ b/src/plugins/irc/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # @@ -33,6 +33,7 @@ irc-info.c irc-info.h irc-input.c irc-input.h irc-message.c irc-message.h irc-mode.c irc-mode.h +irc-modelist.c irc-modelist.h irc-msgbuffer.c irc-msgbuffer.h irc-nick.c irc-nick.h irc-notify.c irc-notify.h diff --git a/src/plugins/irc/Makefile.am b/src/plugins/irc/Makefile.am index 208ce118f..966dc6813 100644 --- a/src/plugins/irc/Makefile.am +++ b/src/plugins/irc/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # @@ -53,6 +53,8 @@ irc_la_SOURCES = irc.c \ irc-message.h \ irc-mode.c \ irc-mode.h \ + irc-modelist.c \ + irc-modelist.h \ irc-msgbuffer.c \ irc-msgbuffer.h \ irc-nick.c \ diff --git a/src/plugins/irc/irc-bar-item.c b/src/plugins/irc/irc-bar-item.c index e4494bb0b..02428b9a8 100644 --- a/src/plugins/irc/irc-bar-item.c +++ b/src/plugins/irc/irc-bar-item.c @@ -1,7 +1,7 @@ /* * irc-bar-item.c - bar items for IRC plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -280,7 +280,7 @@ irc_bar_item_buffer_modes (const void *pointer, void *data, modes_without_args = NULL; if (!irc_config_display_channel_modes_arguments (channel->modes)) { - pos_space = strchr(channel->modes, ' '); + pos_space = strchr (channel->modes, ' '); if (pos_space) { modes_without_args = weechat_strndup ( diff --git a/src/plugins/irc/irc-bar-item.h b/src/plugins/irc/irc-bar-item.h index 5889ea599..1173f9e72 100644 --- a/src/plugins/irc/irc-bar-item.h +++ b/src/plugins/irc/irc-bar-item.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,10 +17,10 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_BAR_ITEM_H -#define WEECHAT_IRC_BAR_ITEM_H 1 +#ifndef WEECHAT_PLUGIN_IRC_BAR_ITEM_H +#define WEECHAT_PLUGIN_IRC_BAR_ITEM_H extern void irc_bar_item_update_channel (); extern void irc_bar_item_init (); -#endif /* WEECHAT_IRC_BAR_ITEM_H */ +#endif /* WEECHAT_PLUGIN_IRC_BAR_ITEM_H */ diff --git a/src/plugins/irc/irc-buffer.c b/src/plugins/irc/irc-buffer.c index b0a1e5ccd..7928c65ee 100644 --- a/src/plugins/irc/irc-buffer.c +++ b/src/plugins/irc/irc-buffer.c @@ -1,7 +1,7 @@ /* * irc-buffer.c - buffer functions for IRC plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/irc/irc-buffer.h b/src/plugins/irc/irc-buffer.h index cd0d828ce..034398e40 100644 --- a/src/plugins/irc/irc-buffer.h +++ b/src/plugins/irc/irc-buffer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_BUFFER_H -#define WEECHAT_IRC_BUFFER_H 1 +#ifndef WEECHAT_PLUGIN_IRC_BUFFER_H +#define WEECHAT_PLUGIN_IRC_BUFFER_H #define IRC_BUFFER_GET_SERVER(__buffer) \ struct t_weechat_plugin *buffer_plugin = NULL; \ @@ -56,4 +56,4 @@ extern int irc_buffer_nickcmp_cb (const void *pointer, void *data, extern struct t_gui_buffer *irc_buffer_search_server_lowest_number (); extern struct t_gui_buffer *irc_buffer_search_private_lowest_number (struct t_irc_server *server); -#endif /* WEECHAT_IRC_BUFFER_H */ +#endif /* WEECHAT_PLUGIN_IRC_BUFFER_H */ diff --git a/src/plugins/irc/irc-channel.c b/src/plugins/irc/irc-channel.c index b184a5330..ab24038a0 100644 --- a/src/plugins/irc/irc-channel.c +++ b/src/plugins/irc/irc-channel.c @@ -1,7 +1,7 @@ /* * irc-channel.c - channel and private chat management for IRC plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -33,6 +33,7 @@ #include "irc-color.h" #include "irc-command.h" #include "irc-config.h" +#include "irc-modelist.h" #include "irc-nick.h" #include "irc-server.h" #include "irc-input.h" @@ -356,7 +357,7 @@ irc_channel_create_buffer (struct t_irc_server *server, } /* set highlights settings on channel buffer */ - weechat_buffer_set( + weechat_buffer_set ( ptr_buffer, "highlight_words_add", (channel_type == IRC_CHANNEL_TYPE_CHANNEL) ? @@ -426,6 +427,7 @@ irc_channel_new (struct t_irc_server *server, int channel_type, { struct t_irc_channel *new_channel; struct t_gui_buffer *ptr_buffer; + const char *ptr_chanmode; /* create buffer for channel (or use existing one) */ ptr_buffer = irc_channel_create_buffer (server, channel_type, @@ -479,6 +481,14 @@ irc_channel_new (struct t_irc_server *server, int channel_type, new_channel->nicks_speaking[1] = NULL; new_channel->nicks_speaking_time = NULL; new_channel->last_nick_speaking_time = NULL; + new_channel->modelists = NULL; + new_channel->last_modelist = NULL; + for (ptr_chanmode = irc_server_get_chanmodes (server); ptr_chanmode[0]; + ptr_chanmode++) + { + if (ptr_chanmode[0] != ',') + irc_modelist_new (new_channel, ptr_chanmode[0]); + } new_channel->join_smart_filtered = NULL; new_channel->buffer = ptr_buffer; new_channel->buffer_as_string = NULL; @@ -711,8 +721,8 @@ irc_channel_check_whox (struct t_irc_server *server, } else { - irc_channel_remove_account(server, channel); - irc_channel_remove_away(server, channel); + irc_channel_remove_account (server, channel); + irc_channel_remove_away (server, channel); } } } @@ -1360,6 +1370,22 @@ irc_channel_display_nick_back_in_pv (struct t_irc_server *server, } /* + * Sets state for modelists in a channel. + */ + +void +irc_channel_modelist_set_state (struct t_irc_channel *channel, int state) +{ + struct t_irc_modelist *ptr_modelist; + + for (ptr_modelist = channel->modelists; ptr_modelist; + ptr_modelist = ptr_modelist->next_modelist) + { + ptr_modelist->state = state; + } +} + +/* * Frees a channel and remove it from channels list. */ @@ -1387,6 +1413,7 @@ irc_channel_free (struct t_irc_server *server, struct t_irc_channel *channel) /* free linked lists */ irc_nick_free_all (server, channel); + irc_modelist_free_all (channel); /* free channel data */ if (channel->name) @@ -1472,6 +1499,8 @@ irc_channel_hdata_channel_cb (const void *pointer, void *data, WEECHAT_HDATA_VAR(struct t_irc_channel, nicks_speaking, POINTER, 0, NULL, NULL); WEECHAT_HDATA_VAR(struct t_irc_channel, nicks_speaking_time, POINTER, 0, NULL, "irc_channel_speaking"); WEECHAT_HDATA_VAR(struct t_irc_channel, last_nick_speaking_time, POINTER, 0, NULL, "irc_channel_speaking"); + WEECHAT_HDATA_VAR(struct t_irc_channel, modelists, POINTER, 0, NULL, "irc_modelist"); + WEECHAT_HDATA_VAR(struct t_irc_channel, last_modelist, POINTER, 0, NULL, "irc_modelist"); WEECHAT_HDATA_VAR(struct t_irc_channel, join_smart_filtered, HASHTABLE, 0, NULL, NULL); WEECHAT_HDATA_VAR(struct t_irc_channel, buffer, POINTER, 0, NULL, "buffer"); WEECHAT_HDATA_VAR(struct t_irc_channel, buffer_as_string, STRING, 0, NULL, NULL); @@ -1629,6 +1658,7 @@ irc_channel_print_log (struct t_irc_channel *channel) struct t_irc_channel_speaking *ptr_nick_speaking; int i, index; struct t_irc_nick *ptr_nick; + struct t_irc_modelist *ptr_modelist; weechat_log_printf (""); weechat_log_printf (" => channel %s (addr:0x%lx):", channel->name, channel); @@ -1656,6 +1686,8 @@ irc_channel_print_log (struct t_irc_channel *channel) weechat_log_printf (" nicks_speaking[1]. . . . : 0x%lx", channel->nicks_speaking[1]); weechat_log_printf (" nicks_speaking_time. . . : 0x%lx", channel->nicks_speaking_time); weechat_log_printf (" last_nick_speaking_time. : 0x%lx", channel->last_nick_speaking_time); + weechat_log_printf (" modelists. . . . . . . . : 0x%lx", channel->modelists); + weechat_log_printf (" last_modelist. . . . . . : 0x%lx", channel->last_modelist); weechat_log_printf (" join_smart_filtered. . . : 0x%lx (hashtable: '%s')", channel->join_smart_filtered, weechat_hashtable_get_string (channel->join_smart_filtered, @@ -1686,13 +1718,18 @@ irc_channel_print_log (struct t_irc_channel *channel) ptr_nick_speaking; ptr_nick_speaking = ptr_nick_speaking->next_nick) { - weechat_log_printf (" nick speaking time: '%s', time: %ld", + weechat_log_printf (" nick speaking time: '%s', time: %lld", ptr_nick_speaking->nick, - ptr_nick_speaking->time_last_message); + (long long)ptr_nick_speaking->time_last_message); } } for (ptr_nick = channel->nicks; ptr_nick; ptr_nick = ptr_nick->next_nick) { irc_nick_print_log (ptr_nick); } + for (ptr_modelist = channel->modelists; ptr_modelist; + ptr_modelist = ptr_modelist->next_modelist) + { + irc_modelist_print_log (ptr_modelist); + } } diff --git a/src/plugins/irc/irc-channel.h b/src/plugins/irc/irc-channel.h index 73a68b712..d078d1d33 100644 --- a/src/plugins/irc/irc-channel.h +++ b/src/plugins/irc/irc-channel.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_CHANNEL_H -#define WEECHAT_IRC_CHANNEL_H 1 +#ifndef WEECHAT_PLUGIN_IRC_CHANNEL_H +#define WEECHAT_PLUGIN_IRC_CHANNEL_H #include <time.h> @@ -32,6 +32,7 @@ #define IRC_CHANNEL_NICKS_SPEAKING_LIMIT 128 struct t_irc_server; +struct t_irc_modelist; struct t_irc_channel_speaking { @@ -71,6 +72,8 @@ struct t_irc_channel struct t_irc_channel_speaking *nicks_speaking_time; /* for smart filter */ /* of join/part/quit messages */ struct t_irc_channel_speaking *last_nick_speaking_time; + struct t_irc_modelist *modelists; /* modelists in the channel */ + struct t_irc_modelist *last_modelist; /* last modelist in the channel */ struct t_hashtable *join_smart_filtered; /* smart filtered joins */ struct t_gui_buffer *buffer; /* buffer allocated for channel */ char *buffer_as_string; /* used to return buffer info */ @@ -158,6 +161,8 @@ extern int irc_channel_autorejoin_cb (const void *pointer, void *data, extern void irc_channel_display_nick_back_in_pv (struct t_irc_server *server, struct t_irc_nick *nick, const char *nickname); +extern void irc_channel_modelist_set_state (struct t_irc_channel *channel, + int state); extern struct t_hdata *irc_channel_hdata_channel_cb (const void *pointer, void *data, const char *hdata_name); @@ -168,4 +173,4 @@ extern int irc_channel_add_to_infolist (struct t_infolist *infolist, struct t_irc_channel *channel); extern void irc_channel_print_log (struct t_irc_channel *channel); -#endif /* WEECHAT_IRC_CHANNEL_H */ +#endif /* WEECHAT_PLUGIN_IRC_CHANNEL_H */ diff --git a/src/plugins/irc/irc-color.c b/src/plugins/irc/irc-color.c index 20395c385..2f33e7db3 100644 --- a/src/plugins/irc/irc-color.c +++ b/src/plugins/irc/irc-color.c @@ -1,7 +1,7 @@ /* * irc-color.c - IRC color decoding/encoding in messages * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/irc/irc-color.h b/src/plugins/irc/irc-color.h index 218c20432..82004cff5 100644 --- a/src/plugins/irc/irc-color.h +++ b/src/plugins/irc/irc-color.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_COLOR_H -#define WEECHAT_IRC_COLOR_H 1 +#ifndef WEECHAT_PLUGIN_IRC_COLOR_H +#define WEECHAT_PLUGIN_IRC_COLOR_H #define IRC_NUM_COLORS 100 @@ -114,4 +114,4 @@ extern char *irc_color_for_tags (const char *color); extern int irc_color_weechat_add_to_infolist (struct t_infolist *infolist); extern void irc_color_end (); -#endif /* WEECHAT_IRC_COLOR_H */ +#endif /* WEECHAT_PLUGIN_IRC_COLOR_H */ diff --git a/src/plugins/irc/irc-command.c b/src/plugins/irc/irc-command.c index bb40e000d..22a1977e2 100644 --- a/src/plugins/irc/irc-command.c +++ b/src/plugins/irc/irc-command.c @@ -1,7 +1,7 @@ /* * irc-command.c - IRC commands * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -30,6 +30,7 @@ #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> +#include <regex.h> #include "../weechat-plugin.h" #include "irc.h" @@ -42,6 +43,7 @@ #include "irc-input.h" #include "irc-message.h" #include "irc-mode.h" +#include "irc-modelist.h" #include "irc-msgbuffer.h" #include "irc-nick.h" #include "irc-notify.h" @@ -238,6 +240,10 @@ irc_command_mode_masks (struct t_irc_server *server, char modes[128+1], masks[1024], *mask; struct t_irc_channel *ptr_channel; struct t_irc_nick *ptr_nick; + struct t_irc_modelist *ptr_modelist; + struct t_irc_modelist_item *ptr_item; + long number; + char *error; if (irc_mode_get_chanmode_type (server, mode[0]) != 'A') { @@ -265,15 +271,31 @@ irc_command_mode_masks (struct t_irc_server *server, masks[0] = '\0'; ptr_channel = irc_channel_search (server, channel_name); + ptr_modelist = irc_modelist_search (ptr_channel, mode[0]); for (; argv[pos_masks]; pos_masks++) { mask = NULL; - /* use default_ban_mask for nick arguments */ if (ptr_channel) { - if (!strchr (argv[pos_masks], '!') + /* use modelist item for number arguments */ + if (ptr_modelist && (set[0] == '-')) + { + error = NULL; + number = strtol (argv[pos_masks], &error, 10); + if (error && !error[0]) + { + ptr_item = irc_modelist_item_search_number (ptr_modelist, + number - 1); + if (ptr_item) + mask = strdup (ptr_item->mask); + } + } + + /* use default_ban_mask for nick arguments */ + if (!mask + && !strchr (argv[pos_masks], '!') && !strchr (argv[pos_masks], '@')) { ptr_nick = irc_nick_search (server, ptr_channel, @@ -1544,8 +1566,8 @@ IRC_COMMAND_CALLBACK(ctcp) { /* generate argument for PING if not provided */ gettimeofday (&tv, NULL); - snprintf (str_time, sizeof (str_time), "%ld %ld", - (long)tv.tv_sec, (long)tv.tv_usec); + snprintf (str_time, sizeof (str_time), "%lld %ld", + (long long)tv.tv_sec, (long)tv.tv_usec); ctcp_args = str_time; } else @@ -2562,7 +2584,8 @@ irc_command_join_server (struct t_irc_server *server, const char *arguments, } } if (manual_join - && weechat_config_boolean (irc_config_look_buffer_open_before_join)) + && weechat_config_boolean (irc_config_look_buffer_open_before_join) + && !irc_channel_search (server, pos_channel)) { /* * open the channel buffer immediately (do not wait for the @@ -2914,98 +2937,95 @@ IRC_COMMAND_CALLBACK(links) IRC_COMMAND_CALLBACK(list) { char buf[512], *ptr_channel_name, *ptr_server_name, *ptr_regex; + regex_t *new_regexp; int i, ret; IRC_BUFFER_GET_SERVER(buffer); - IRC_COMMAND_CHECK_SERVER("list", 1); /* make C compiler happy */ (void) pointer; (void) data; - if (ptr_server->cmd_list_regexp) + ptr_channel_name = NULL; + ptr_server_name = NULL; + ptr_regex = NULL; + new_regexp = NULL; + + for (i = 1; i < argc; i++) { - regfree (ptr_server->cmd_list_regexp); - free (ptr_server->cmd_list_regexp); - ptr_server->cmd_list_regexp = NULL; + if (weechat_strcasecmp (argv[i], "-server") == 0) + { + if (argc <= i + 1) + WEECHAT_COMMAND_ERROR; + ptr_server = irc_server_search (argv[i + 1]); + if (!ptr_server) + WEECHAT_COMMAND_ERROR; + i++; + } + else if (weechat_strcasecmp (argv[i], "-re") == 0) + { + if (argc <= i + 1) + WEECHAT_COMMAND_ERROR; + ptr_regex = argv_eol[i + 1]; + i++; + } + else if (!ptr_channel_name) + ptr_channel_name = argv[i]; + else if (!ptr_server_name) + ptr_server_name = argv[i]; + else + WEECHAT_COMMAND_ERROR; } - if (argc > 1) + IRC_COMMAND_CHECK_SERVER("list", 1); + + if (ptr_regex) { - ptr_channel_name = NULL; - ptr_server_name = NULL; - ptr_regex = NULL; - for (i = 1; i < argc; i++) + new_regexp = malloc (sizeof (*new_regexp)); + if (!new_regexp) { - if (weechat_strcasecmp (argv[i], "-re") == 0) - { - if (i < argc - 1) - { - ptr_regex = argv_eol[i + 1]; - i++; - } - } - else - { - if (!ptr_channel_name) - ptr_channel_name = argv[i]; - else if (!ptr_server_name) - ptr_server_name = argv[i]; - } + weechat_printf ( + ptr_server->buffer, + _("%s%s: not enough memory for regular expression"), + weechat_prefix ("error"), IRC_PLUGIN_NAME); + return WEECHAT_RC_OK; } - if (!ptr_channel_name && !ptr_server_name && !ptr_regex) + ret = weechat_string_regcomp (new_regexp, + ptr_regex, + REG_EXTENDED | REG_ICASE | REG_NOSUB); + if (ret != 0) { - irc_server_sendf (ptr_server, IRC_SERVER_SEND_OUTQ_PRIO_HIGH, NULL, - "LIST"); + regerror (ret, new_regexp, buf, sizeof (buf)); + weechat_printf ( + ptr_server->buffer, + _("%s%s: \"%s\" is not a valid regular expression " + "(%s)"), + weechat_prefix ("error"), IRC_PLUGIN_NAME, + ptr_regex, buf); + free (new_regexp); + return WEECHAT_RC_OK; } - else + if (ptr_server->cmd_list_regexp) { - if (ptr_regex) - { - ptr_server->cmd_list_regexp = malloc ( - sizeof (*ptr_server->cmd_list_regexp)); - if (ptr_server->cmd_list_regexp) - { - if ((ret = weechat_string_regcomp ( - ptr_server->cmd_list_regexp, ptr_regex, - REG_EXTENDED | REG_ICASE | REG_NOSUB)) != 0) - { - regerror (ret, ptr_server->cmd_list_regexp, - buf, sizeof(buf)); - weechat_printf ( - ptr_server->buffer, - _("%s%s: \"%s\" is not a valid regular expression " - "(%s)"), - weechat_prefix ("error"), IRC_PLUGIN_NAME, - argv_eol[1], buf); - free (ptr_server->cmd_list_regexp); - ptr_server->cmd_list_regexp = NULL; - return WEECHAT_RC_OK; - } - } - else - { - weechat_printf ( - ptr_server->buffer, - _("%s%s: not enough memory for regular expression"), - weechat_prefix ("error"), IRC_PLUGIN_NAME); - return WEECHAT_RC_OK; - } - } - irc_server_sendf (ptr_server, IRC_SERVER_SEND_OUTQ_PRIO_HIGH, NULL, - "LIST%s%s%s%s", - (ptr_channel_name) ? " " : "", - (ptr_channel_name) ? ptr_channel_name : "", - (ptr_server_name) ? " " : "", - (ptr_server_name) ? ptr_server_name : ""); + regfree (ptr_server->cmd_list_regexp); + free (ptr_server->cmd_list_regexp); } + ptr_server->cmd_list_regexp = new_regexp; } - else + else if (ptr_server->cmd_list_regexp) { - irc_server_sendf (ptr_server, IRC_SERVER_SEND_OUTQ_PRIO_HIGH, NULL, - "LIST"); + regfree (ptr_server->cmd_list_regexp); + free (ptr_server->cmd_list_regexp); + ptr_server->cmd_list_regexp = NULL; } + irc_server_sendf (ptr_server, IRC_SERVER_SEND_OUTQ_PRIO_HIGH, NULL, + "LIST%s%s%s%s", + (ptr_channel_name) ? " " : "", + (ptr_channel_name) ? ptr_channel_name : "", + (ptr_server_name) ? " " : "", + (ptr_server_name) ? ptr_server_name : ""); + return WEECHAT_RC_OK; } @@ -4606,13 +4626,22 @@ IRC_COMMAND_CALLBACK(saquit) void irc_command_display_server (struct t_irc_server *server, int with_detail) { - char *cmd_pwd_hidden; + char *cmd_pwd_hidden, str_nick[1024]; int num_channels, num_pv; + str_nick[0] = '\0'; + if (server->nick) + { + snprintf (str_nick, sizeof (str_nick), + ", %s %s", + _("nick:"), + server->nick); + } + if (with_detail) { weechat_printf (NULL, ""); - weechat_printf (NULL, _("Server: %s%s %s[%s%s%s]%s%s"), + weechat_printf (NULL, _("Server: %s%s %s[%s%s%s]%s%s%s"), IRC_COLOR_CHAT_SERVER, server->name, IRC_COLOR_CHAT_DELIMITERS, @@ -4621,6 +4650,7 @@ irc_command_display_server (struct t_irc_server *server, int with_detail) _("connected") : _("not connected"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_RESET, + str_nick, (server->temp_server) ? _(" (temporary)") : ""); /* addresses */ if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_ADDRESSES])) @@ -4986,6 +5016,15 @@ irc_command_display_server (struct t_irc_server *server, int with_detail) weechat_printf (NULL, " notify . . . . . . . : %s'%s'", IRC_COLOR_CHAT_VALUE, weechat_config_string (server->options[IRC_SERVER_OPTION_NOTIFY])); + + /* split_msg_max_length */ + if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_SPLIT_MSG_MAX_LENGTH])) + weechat_printf (NULL, " split_msg_max_length : (%d)", + IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_SPLIT_MSG_MAX_LENGTH)); + else + weechat_printf (NULL, " split_msg_max_length : %s%d", + IRC_COLOR_CHAT_VALUE, + weechat_config_integer (server->options[IRC_SERVER_OPTION_SPLIT_MSG_MAX_LENGTH])); } else { @@ -4995,16 +5034,16 @@ irc_command_display_server (struct t_irc_server *server, int with_detail) num_pv = irc_server_get_pv_count (server); weechat_printf ( NULL, - " %s %s%s %s[%s%s%s]%s%s, %d %s, %d pv", + " %s %s%s %s[%s%s%s]%s%s%s, %d %s, %d pv", (server->is_connected) ? "*" : " ", IRC_COLOR_CHAT_SERVER, server->name, IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_RESET, - (server->is_connected) ? - _("connected") : _("not connected"), + (server->is_connected) ? _("connected") : _("not connected"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_RESET, + str_nick, (server->temp_server) ? _(" (temporary)") : "", num_channels, NG_("channel", "channels", num_channels), @@ -6563,20 +6602,21 @@ irc_command_init () "links", N_("list all servernames which are known by the server answering the " "query"), - N_("[[<server>] <server_mask>]"), - N_(" server: this server should answer the query\n" + N_("[[<target>] <server_mask>]"), + N_(" target: this remote server should answer the query\n" "server_mask: list of servers must match this mask"), NULL, &irc_command_links, NULL, NULL); weechat_hook_command ( "list", N_("list channels and their topic"), - N_("[<channel>[,<channel>...]] [<server>] " - "[-re <regex>]"), - N_("channel: channel to list\n" - " server: server name\n" + N_("[-server <server>] [-re <regex>] [<channel>[,<channel>...]] " + "[<target>]"), + N_(" server: send to this server (internal name)\n" " regex: POSIX extended regular expression used to filter results " "(case insensitive, can start by \"(?-i)\" to become case " "sensitive)\n" + "channel: channel to list\n" + " target: server name\n" "\n" "Examples:\n" " list all channels on server (can be very slow on large networks):\n" @@ -6586,7 +6626,9 @@ irc_command_init () " list all channels beginning with \"#weechat\" (can be very slow " "on large networks):\n" " /list -re #weechat.*"), - NULL, &irc_command_list, NULL, NULL); + "-server %(irc_servers)" + " || -re", + &irc_command_list, NULL, NULL); weechat_hook_command ( "lusers", N_("get statistics about the size of the IRC network"), @@ -6732,9 +6774,9 @@ irc_command_init () weechat_hook_command ( "ping", N_("send a ping to server"), - N_("<server1> [<server2>]"), - N_("server1: server\n" - "server2: forward ping to this server"), + N_("<target1> [<target2>]"), + N_("target1: server\n" + "target2: forward ping to this server"), NULL, &irc_command_ping, NULL, NULL); weechat_hook_command ( "pong", @@ -6849,18 +6891,20 @@ irc_command_init () weechat_hook_command ( "server", N_("list, add or remove IRC servers"), - N_("list|listfull [<server>]" - " || add <server> <hostname>[/<port>] [-temp] [-<option>[=<value>]] " + N_("list|listfull [<name>]" + " || add <name> <hostname>[/<port>] [-temp] [-<option>[=<value>]] " "[-no<option>]" - " || copy|rename <server> <new_name>" - " || reorder <server> [<server>...]" - " || open <server>|-all [<server>...]" - " || del|keep <server>" + " || copy|rename <name> <new_name>" + " || reorder <name> [<name>...]" + " || open <name>|-all [<name>...]" + " || del|keep <name>" " || deloutq|jump|raw"), N_(" list: list servers (without argument, this list is displayed)\n" "listfull: list servers with detailed info for each server\n" " add: add a new server\n" - " server: server name, for internal and display use\n" + " name: server name, for internal and display use; this name " + "is used to connect to the server (/connect name) and to set server " + "options: irc.server.name.xxx\n" "hostname: name or IP address of server, with optional port " "(default: 6667), many addresses can be separated by a comma\n" " -temp: add a temporary server (not saved)\n" @@ -6919,16 +6963,16 @@ irc_command_init () weechat_hook_command ( "squit", N_("disconnect server links"), - N_("<server> <comment>"), - N_( " server: server name\n" + N_("<target> <comment>"), + N_( " target: server name\n" "comment: comment"), NULL, &irc_command_squit, NULL, NULL); weechat_hook_command ( "stats", N_("query statistics about server"), - N_("[<query> [<server>]]"), + N_("[<query> [<target>]]"), N_(" query: c/h/i/k/l/m/o/y/u (see RFC1459)\n" - "server: server name"), + "target: server name"), NULL, &irc_command_stats, NULL, NULL); weechat_hook_command ( "summon", @@ -6963,17 +7007,21 @@ irc_command_init () weechat_hook_command ( "unban", N_("unban nicks or hosts"), - N_("[<channel>] <nick> [<nick>...]"), + N_("[<channel>] <nick>|<number> [<nick>|<number>...]"), N_("channel: channel name\n" - " nick: nick or host"), - NULL, &irc_command_unban, NULL, NULL); + " nick: nick or host\n" + " number: ban number (as displayed by command /ban)"), + "%(irc_modelist_masks:b)|%(irc_modelist_numbers:b)", + &irc_command_unban, NULL, NULL); weechat_hook_command ( "unquiet", N_("unquiet nicks or hosts"), - N_("[<channel>] <nick> [<nick>...]"), + N_("[<channel>] <nick>|<number> [<nick>|<number>...]"), N_("channel: channel name\n" - " nick: nick or host"), - "%(irc_channel_nicks_hosts)", &irc_command_unquiet, NULL, NULL); + " nick: nick or host\n" + " number: quiet number (as displayed by command /quiet)"), + "%(irc_modelist_masks:q)|%(irc_modelist_numbers:q)", + &irc_command_unquiet, NULL, NULL); weechat_hook_command ( "userhost", N_("return a list of information about nicks"), @@ -6989,8 +7037,8 @@ irc_command_init () weechat_hook_command ( "version", N_("give the version info of nick or server (current or specified)"), - N_("[<server>|<nick>]"), - N_("server: server name\n" + N_("[<target>|<nick>]"), + N_("target: server name\n" " nick: nick"), "%(nicks)", &irc_command_version, NULL, NULL); weechat_hook_command ( @@ -7024,8 +7072,8 @@ irc_command_init () weechat_hook_command ( "whois", N_("query information about user(s)"), - N_("[<server>] [<nick>[,<nick>...]]"), - N_("server: server name\n" + N_("[<target>] [<nick>[,<nick>...]]"), + N_("target: server name\n" " nick: nick (may be a mask)\n" "\n" "Without argument, this command will do a whois on:\n" diff --git a/src/plugins/irc/irc-command.h b/src/plugins/irc/irc-command.h index 67ddd506e..c6a31dc57 100644 --- a/src/plugins/irc/irc-command.h +++ b/src/plugins/irc/irc-command.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_COMMAND_H -#define WEECHAT_IRC_COMMAND_H 1 +#ifndef WEECHAT_PLUGIN_IRC_COMMAND_H +#define WEECHAT_PLUGIN_IRC_COMMAND_H struct t_irc_server; struct t_irc_channel; @@ -77,4 +77,4 @@ extern void irc_command_quit_server (struct t_irc_server *server, const char *arguments); extern void irc_command_init (); -#endif /* WEECHAT_IRC_COMMAND_H */ +#endif /* WEECHAT_PLUGIN_IRC_COMMAND_H */ diff --git a/src/plugins/irc/irc-completion.c b/src/plugins/irc/irc-completion.c index 3562e3d84..4e72a8570 100644 --- a/src/plugins/irc/irc-completion.c +++ b/src/plugins/irc/irc-completion.c @@ -1,7 +1,7 @@ /* * irc-completion.c - completion for IRC commands * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -31,6 +31,7 @@ #include "irc-completion.h" #include "irc-config.h" #include "irc-ignore.h" +#include "irc-modelist.h" #include "irc-nick.h" #include "irc-notify.h" #include "irc-server.h" @@ -421,6 +422,92 @@ irc_completion_channel_nicks_hosts_cb (const void *pointer, void *data, } /* + * Adds modelist masks of current channel to completion list. + */ + +int +irc_completion_modelist_masks_cb (const void *pointer, void *data, + const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion) +{ + char *pos; + struct t_irc_modelist *ptr_modelist; + struct t_irc_modelist_item *ptr_item; + + IRC_BUFFER_GET_SERVER_CHANNEL(buffer); + + /* make C compiler happy */ + (void) pointer; + (void) data; + + pos = strchr (completion_item, ':'); + if (pos) + pos++; + + if (pos && pos[0] && ptr_channel) + { + ptr_modelist = irc_modelist_search (ptr_channel, pos[0]); + if (ptr_modelist) + { + for (ptr_item = ptr_modelist->items; ptr_item; + ptr_item = ptr_item->next_item) + { + weechat_hook_completion_list_add (completion, + ptr_item->mask, + 0, WEECHAT_LIST_POS_END); + } + } + } + + return WEECHAT_RC_OK; +} + +/* + * Adds modelist numbers of current channel to completion list. + */ + +int +irc_completion_modelist_numbers_cb (const void *pointer, void *data, + const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion) +{ + char *pos, str_number[32]; + struct t_irc_modelist *ptr_modelist; + struct t_irc_modelist_item *ptr_item; + + IRC_BUFFER_GET_SERVER_CHANNEL(buffer); + + /* make C compiler happy */ + (void) pointer; + (void) data; + + pos = strchr (completion_item, ':'); + if (pos) + pos++; + + if (pos && pos[0] && ptr_channel) + { + ptr_modelist = irc_modelist_search (ptr_channel, pos[0]); + if (ptr_modelist) + { + for (ptr_item = ptr_modelist->items; ptr_item; + ptr_item = ptr_item->next_item) + { + snprintf (str_number, sizeof (str_number), + "%d", ptr_item->number + 1); + weechat_hook_completion_list_add (completion, + str_number, + 0, WEECHAT_LIST_POS_END); + } + } + } + + return WEECHAT_RC_OK; +} + +/* * Adds topic of current channel to completion list. */ @@ -758,6 +845,14 @@ irc_completion_init () weechat_hook_completion ("irc_channel_nicks_hosts", N_("nicks and hostnames of current IRC channel"), &irc_completion_channel_nicks_hosts_cb, NULL, NULL); + weechat_hook_completion ("irc_modelist_masks", + N_("modelist masks of current IRC channel; " + "required argument: modelist mode"), + &irc_completion_modelist_masks_cb, NULL, NULL); + weechat_hook_completion ("irc_modelist_numbers", + N_("modelist numbers of current IRC channel; " + "required argument: modelist mode"), + &irc_completion_modelist_numbers_cb, NULL, NULL); weechat_hook_completion ("irc_channel_topic", N_("topic of current IRC channel"), &irc_completion_channel_topic_cb, NULL, NULL); diff --git a/src/plugins/irc/irc-completion.h b/src/plugins/irc/irc-completion.h index 5d644f44c..21659d1a5 100644 --- a/src/plugins/irc/irc-completion.h +++ b/src/plugins/irc/irc-completion.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_COMPLETION_H -#define WEECHAT_IRC_COMPLETION_H 1 +#ifndef WEECHAT_PLUGIN_IRC_COMPLETION_H +#define WEECHAT_PLUGIN_IRC_COMPLETION_H extern void irc_completion_init (); -#endif /* WEECHAT_IRC_COMPLETION_H */ +#endif /* WEECHAT_PLUGIN_IRC_COMPLETION_H */ diff --git a/src/plugins/irc/irc-config.c b/src/plugins/irc/irc-config.c index 1b1c85a98..04bccb25c 100644 --- a/src/plugins/irc/irc-config.c +++ b/src/plugins/irc/irc-config.c @@ -1,7 +1,7 @@ /* * irc-config.c - IRC configuration options (file irc.conf) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -23,7 +23,6 @@ #include <unistd.h> #include <stdio.h> #include <string.h> -#include <ctype.h> #include <time.h> #include <limits.h> #include <pwd.h> @@ -224,7 +223,7 @@ irc_config_compute_nick_colors () } /* if colors are displayed for nicks in nicklist, refresh them */ - if (weechat_config_boolean(irc_config_look_color_nicks_in_nicklist)) + if (weechat_config_boolean (irc_config_look_color_nicks_in_nicklist)) irc_nick_nicklist_set_color_all (); } @@ -995,11 +994,9 @@ irc_config_server_check_value_cb (const void *pointer, void *data, { int index_option, proxy_found; const char *pos_error, *proxy_name; + char *error; + long number; struct t_infolist *infolist; -#ifdef HAVE_GNUTLS - char *fingerprint_eval, **fingerprints, *str_sizes; - int i, j, rc, algo, length; -#endif /* HAVE_GNUTLS */ /* make C compiler happy */ (void) data; @@ -1051,81 +1048,30 @@ irc_config_server_check_value_cb (const void *pointer, void *data, return 0; } break; - case IRC_SERVER_OPTION_SSL_FINGERPRINT: -#ifdef HAVE_GNUTLS + case IRC_SERVER_OPTION_SPLIT_MSG_MAX_LENGTH: if (!value || !value[0]) break; - fingerprint_eval = weechat_string_eval_expression ( - value, NULL, NULL, NULL); - if (!fingerprint_eval || !fingerprint_eval[0]) - { - weechat_printf ( - NULL, - _("%s%s: the evaluated fingerprint must not be " - "empty"), - weechat_prefix ("error"), - IRC_PLUGIN_NAME); - if (fingerprint_eval) - free (fingerprint_eval); - return 0; - } - fingerprints = weechat_string_split ( - (fingerprint_eval) ? fingerprint_eval : value, - ",", 0, 0, NULL); - if (!fingerprints) + error = NULL; + number = strtol (value, &error, 10); + if (!error || error[0]) { - free (fingerprint_eval); + /* + * not a valid number, but we return 1 (OK) to let WeeChat + * display the appropriate error + */ return 1; } - rc = 0; - for (i = 0; fingerprints[i]; i++) - { - length = strlen (fingerprints[i]); - algo = irc_server_fingerprint_search_algo_with_size ( - length * 4); - if (algo < 0) - { - rc = -1; - break; - } - for (j = 0; j < length; j++) - { - if (!isxdigit ((unsigned char)fingerprints[i][j])) - { - rc = -2; - break; - } - } - if (rc < 0) - break; - } - weechat_string_free_split (fingerprints); - free (fingerprint_eval); - switch (rc) + if ((number < 0) + || ((number > 0) && (number < 128)) + || (number > 4096)) { - case -1: /* invalid size */ - str_sizes = irc_server_fingerprint_str_sizes (); - weechat_printf ( - NULL, - _("%s%s: invalid fingerprint size, the " - "number of hexadecimal digits must be " - "one of: %s"), - weechat_prefix ("error"), - IRC_PLUGIN_NAME, - (str_sizes) ? str_sizes : "?"); - if (str_sizes) - free (str_sizes); - return 0; - case -2: /* invalid content */ - weechat_printf ( + weechat_printf ( NULL, - _("%s%s: invalid fingerprint, it must " - "contain only hexadecimal digits (0-9, " - "a-f)"), + _("%s%s: invalid length for split, it must be " + "either 0 or any integer between 128 and 4096"), weechat_prefix ("error"), IRC_PLUGIN_NAME); - return 0; + return 0; } -#endif /* HAVE_GNUTLS */ break; } } @@ -1533,7 +1479,9 @@ irc_config_server_new_option (struct t_config_file *config_file, option_name, "string", N_("list of hostname/port or IP/port for server (separated by " "comma) " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1660,7 +1608,9 @@ irc_config_server_new_option (struct t_config_file *config_file, "fingerprints can be separated by commas; if this option " "is set, the other checks on certificates are NOT " "performed (option \"ssl_verify\") " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1693,7 +1643,9 @@ irc_config_server_new_option (struct t_config_file *config_file, config_file, section, option_name, "string", N_("password for server " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1757,7 +1709,9 @@ irc_config_server_new_option (struct t_config_file *config_file, option_name, "string", N_("username for SASL authentication; this option is not used " "for mechanism \"external\" " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1776,7 +1730,9 @@ irc_config_server_new_option (struct t_config_file *config_file, N_("password for SASL authentication; this option is not used " "for mechanisms \"ecdsa-nist256p-challenge\" and " "\"external\" " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1898,7 +1854,9 @@ irc_config_server_new_option (struct t_config_file *config_file, config_file, section, option_name, "string", N_("nicknames to use on server (separated by comma) " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1935,7 +1893,9 @@ irc_config_server_new_option (struct t_config_file *config_file, config_file, section, option_name, "string", N_("user name to use on server " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1952,7 +1912,9 @@ irc_config_server_new_option (struct t_config_file *config_file, config_file, section, option_name, "string", N_("real name to use on server " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1989,7 +1951,10 @@ irc_config_server_new_option (struct t_config_file *config_file, "executing command and the auto-join of channels; examples: " "\"+R\" (to set mode \"R\"), \"+R-i\" (to set mode \"R\" " "and remove \"i\"); see /help mode for the complete mode " - "syntax (note: content is evaluated, see /help eval)"), + "syntax " + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -2009,7 +1974,9 @@ irc_config_server_new_option (struct t_config_file *config_file, "auto-join of channels (many commands can be separated by " "\";\", use \"\\;\" for a semicolon, special variables " "$nick, $channel and $server are replaced by their value) " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -2050,7 +2017,9 @@ irc_config_server_new_option (struct t_config_file *config_file, "channels (separated by a space) (example: \"#channel1," "#channel2,#channel3 key1,key2\" where #channel1 and " "#channel2 are protected by key1 and key2) " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -2264,6 +2233,29 @@ irc_config_server_new_option (struct t_config_file *config_file, callback_change_data, NULL, NULL, NULL); break; + case IRC_SERVER_OPTION_SPLIT_MSG_MAX_LENGTH: + new_option = weechat_config_new_option ( + config_file, section, + option_name, "integer", + N_("split outgoing IRC messages to fit in this number of chars; " + "the default value is 512, this is a safe and recommended " + "value; " + "value 0 disables the split (not recommended, unless you " + "know what you do); allowed values are 0 or " + "any integer between 128 and 4096; " + "this option should be changed only on non-standard IRC " + "servers, for example gateways like bitlbee"), + NULL, 0, 4096, + default_value, value, + null_value_allowed, + callback_check_value, + callback_check_value_pointer, + callback_check_value_data, + callback_change, + callback_change_pointer, + callback_change_data, + NULL, NULL, NULL); + break; case IRC_SERVER_NUM_OPTIONS: break; } @@ -2510,6 +2502,7 @@ irc_config_init () if (!ptr_section) { weechat_config_free (irc_config_file); + irc_config_file = NULL; return 0; } @@ -2816,9 +2809,10 @@ irc_config_init () irc_config_file, ptr_section, "notice_welcome_redirect", "boolean", N_("automatically redirect channel welcome notices to the channel " - "buffer; such notices have the nick as target but a channel name in " - "beginning of notice message, for example notices sent by freenode " - "server which look like: \"[#channel] Welcome to this channel...\""), + "buffer; such notices have the nick as target but a channel name " + "in beginning of notice message, for example the ENTRYMSG notices " + "sent by Atheme IRC Services which look like: " + "\"[#channel] Welcome to this channel...\""), NULL, 0, 0, "on", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); irc_config_look_notice_welcome_tags = weechat_config_new_option ( @@ -2968,6 +2962,7 @@ irc_config_init () if (!ptr_section) { weechat_config_free (irc_config_file); + irc_config_file = NULL; return 0; } @@ -3097,6 +3092,7 @@ irc_config_init () if (!ptr_section) { weechat_config_free (irc_config_file); + irc_config_file = NULL; return 0; } @@ -3242,6 +3238,7 @@ irc_config_init () if (!ptr_section) { weechat_config_free (irc_config_file); + irc_config_file = NULL; return 0; } irc_config_section_msgbuffer = ptr_section; @@ -3258,6 +3255,7 @@ irc_config_init () if (!ptr_section) { weechat_config_free (irc_config_file); + irc_config_file = NULL; return 0; } irc_config_section_ctcp = ptr_section; @@ -3274,6 +3272,7 @@ irc_config_init () if (!ptr_section) { weechat_config_free (irc_config_file); + irc_config_file = NULL; return 0; } @@ -3289,6 +3288,7 @@ irc_config_init () if (!ptr_section) { weechat_config_free (irc_config_file); + irc_config_file = NULL; return 0; } irc_config_section_server_default = ptr_section; @@ -3307,6 +3307,7 @@ irc_config_init () if (!ptr_section) { weechat_config_free (irc_config_file); + irc_config_file = NULL; return 0; } irc_config_section_server = ptr_section; diff --git a/src/plugins/irc/irc-config.h b/src/plugins/irc/irc-config.h index ab745e702..e27313614 100644 --- a/src/plugins/irc/irc-config.h +++ b/src/plugins/irc/irc-config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_CONFIG_H -#define WEECHAT_IRC_CONFIG_H 1 +#ifndef WEECHAT_PLUGIN_IRC_CONFIG_H +#define WEECHAT_PLUGIN_IRC_CONFIG_H #define IRC_CONFIG_NAME "irc" @@ -215,4 +215,4 @@ extern int irc_config_read (); extern int irc_config_write (int write_temp_servers); extern void irc_config_free (); -#endif /* WEECHAT_IRC_CONFIG_H */ +#endif /* WEECHAT_PLUGIN_IRC_CONFIG_H */ diff --git a/src/plugins/irc/irc-ctcp.c b/src/plugins/irc/irc-ctcp.c index 8afee681c..112e842cb 100644 --- a/src/plugins/irc/irc-ctcp.c +++ b/src/plugins/irc/irc-ctcp.c @@ -1,7 +1,7 @@ /* * irc-ctcp.c - IRC CTCP protocol * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -452,9 +452,10 @@ irc_ctcp_replace_variables (struct t_irc_server *server, const char *format) now = time (NULL); local_time = localtime (&now); setlocale (LC_ALL, "C"); - strftime (buf, sizeof (buf), - weechat_config_string (irc_config_look_ctcp_time_format), - local_time); + if (strftime (buf, sizeof (buf), + weechat_config_string (irc_config_look_ctcp_time_format), + local_time) == 0) + buf[0] = '\0'; setlocale (LC_ALL, ""); temp = weechat_string_replace (res, "$time", buf); free (res); @@ -466,9 +467,9 @@ irc_ctcp_replace_variables (struct t_irc_server *server, const char *format) * $username: user name, example: * name */ - username = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME), - NULL, NULL, NULL); + username = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME)); if (username) { temp = weechat_string_replace (res, "$username", username); @@ -483,9 +484,9 @@ irc_ctcp_replace_variables (struct t_irc_server *server, const char *format) * $realname: real name, example: * John doe */ - realname = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME), - NULL, NULL, NULL); + realname = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME)); if (realname) { temp = weechat_string_replace (res, "$realname", realname); @@ -1084,8 +1085,21 @@ irc_ctcp_recv (struct t_irc_server *server, time_t date, const char *command, address, arguments + 1, pos_args, reply); if (!reply || reply[0]) { - irc_ctcp_reply_to_nick (server, command, channel, nick, - arguments + 1, pos_args); + if (reply) + { + decoded_reply = irc_ctcp_replace_variables (server, reply); + if (decoded_reply) + { + irc_ctcp_reply_to_nick (server, command, channel, nick, + arguments + 1, decoded_reply); + free (decoded_reply); + } + } + else + { + irc_ctcp_reply_to_nick (server, command, channel, nick, + arguments + 1, pos_args); + } } } /* CTCP DCC */ diff --git a/src/plugins/irc/irc-ctcp.h b/src/plugins/irc/irc-ctcp.h index 6fe8b6999..8478bfbe3 100644 --- a/src/plugins/irc/irc-ctcp.h +++ b/src/plugins/irc/irc-ctcp.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_CTCP_H -#define WEECHAT_IRC_CTCP_H 1 +#ifndef WEECHAT_PLUGIN_IRC_CTCP_H +#define WEECHAT_PLUGIN_IRC_CTCP_H #include <time.h> @@ -44,4 +44,4 @@ extern void irc_ctcp_recv (struct t_irc_server *server, time_t date, const char *remote_nick, char *arguments, char *message); -#endif /* WEECHAT_IRC_CTCP_H */ +#endif /* WEECHAT_PLUGIN_IRC_CTCP_H */ diff --git a/src/plugins/irc/irc-debug.c b/src/plugins/irc/irc-debug.c index 64e1de89e..79e9ac7f0 100644 --- a/src/plugins/irc/irc-debug.c +++ b/src/plugins/irc/irc-debug.c @@ -1,7 +1,7 @@ /* * irc-debug.c - debug functions for IRC plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/irc/irc-debug.h b/src/plugins/irc/irc-debug.h index 5305487df..b7fb094dc 100644 --- a/src/plugins/irc/irc-debug.h +++ b/src/plugins/irc/irc-debug.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_DEBUG_H -#define WEECHAT_IRC_DEBUG_H 1 +#ifndef WEECHAT_PLUGIN_IRC_DEBUG_H +#define WEECHAT_PLUGIN_IRC_DEBUG_H extern void irc_debug_init (); -#endif /* WEECHAT_IRC_DEBUG_H */ +#endif /* WEECHAT_PLUGIN_IRC_DEBUG_H */ diff --git a/src/plugins/irc/irc-ignore.c b/src/plugins/irc/irc-ignore.c index cfc45d6c6..c96777cb0 100644 --- a/src/plugins/irc/irc-ignore.c +++ b/src/plugins/irc/irc-ignore.c @@ -1,7 +1,7 @@ /* * irc-ignore.c - ignore (nicks/hosts) management for IRC plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/irc/irc-ignore.h b/src/plugins/irc/irc-ignore.h index 887342cb1..072345f10 100644 --- a/src/plugins/irc/irc-ignore.h +++ b/src/plugins/irc/irc-ignore.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_IGNORE_H -#define WEECHAT_IRC_IGNORE_H 1 +#ifndef WEECHAT_PLUGIN_IRC_IGNORE_H +#define WEECHAT_PLUGIN_IRC_IGNORE_H #include <regex.h> @@ -58,4 +58,4 @@ extern int irc_ignore_add_to_infolist (struct t_infolist *infolist, struct t_irc_ignore *ignore); extern void irc_ignore_print_log (); -#endif /* WEECHAT_IRC_IGNORE_H */ +#endif /* WEECHAT_PLUGIN_IRC_IGNORE_H */ diff --git a/src/plugins/irc/irc-info.c b/src/plugins/irc/irc-info.c index b8dc6f6e1..9ba65334c 100644 --- a/src/plugins/irc/irc-info.c +++ b/src/plugins/irc/irc-info.c @@ -1,7 +1,7 @@ /* * irc-info.c - info, infolist and hdata hooks for IRC plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -30,6 +30,7 @@ #include "irc-config.h" #include "irc-ignore.h" #include "irc-message.h" +#include "irc-modelist.h" #include "irc-nick.h" #include "irc-notify.h" #include "irc-protocol.h" @@ -574,6 +575,211 @@ irc_info_infolist_irc_channel_cb (const void *pointer, void *data, } /* + * Returns IRC infolist "irc_modelist". + */ + +struct t_infolist * +irc_info_infolist_irc_modelist_cb (const void *pointer, void *data, + const char *infolist_name, + void *obj_pointer, const char *arguments) +{ + struct t_infolist *ptr_infolist; + struct t_irc_server *ptr_server; + struct t_irc_channel *ptr_channel; + struct t_irc_modelist *ptr_modelist; + char **argv; + int argc; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) infolist_name; + + if (!arguments || !arguments[0]) + return NULL; + + ptr_server = NULL; + ptr_channel = NULL; + argv = weechat_string_split (arguments, ",", 0, 0, &argc); + if (!argv) + return NULL; + + if (argc >= 2) + { + ptr_server = irc_server_search (argv[0]); + if (!ptr_server) + { + weechat_string_free_split (argv); + return NULL; + } + ptr_channel = irc_channel_search (ptr_server, argv[1]); + if (!ptr_channel) + { + weechat_string_free_split (argv); + return NULL; + } + if (!obj_pointer && (argc >= 3)) + { + obj_pointer = irc_modelist_search (ptr_channel, argv[2][0]); + + if (!obj_pointer) + { + weechat_string_free_split (argv); + return NULL; + } + } + } + weechat_string_free_split (argv); + + if (!ptr_server || !ptr_channel) + return NULL; + + if (obj_pointer && !irc_modelist_valid (ptr_channel, obj_pointer)) + return NULL; + + ptr_infolist = weechat_infolist_new (); + if (!ptr_infolist) + return NULL; + + if (obj_pointer) + { + /* build list with only one modelist */ + if (!irc_modelist_add_to_infolist (ptr_infolist, obj_pointer)) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + return ptr_infolist; + } + else + { + /* build list with all modelists of channel */ + for (ptr_modelist = ptr_channel->modelists; ptr_modelist; + ptr_modelist = ptr_modelist->next_modelist) + { + if (!irc_modelist_add_to_infolist (ptr_infolist, ptr_modelist)) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + } + return ptr_infolist; + } + + return NULL; +} + +/* + * Returns IRC infolist "irc_modelist_item". + */ + +struct t_infolist * +irc_info_infolist_irc_modelist_item_cb (const void *pointer, void *data, + const char *infolist_name, + void *obj_pointer, const char *arguments) +{ + struct t_infolist *ptr_infolist; + struct t_irc_server *ptr_server; + struct t_irc_channel *ptr_channel; + struct t_irc_modelist *ptr_modelist; + struct t_irc_modelist_item *ptr_item; + char **argv, *error; + int argc; + long number; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) infolist_name; + + if (!arguments || !arguments[0]) + return NULL; + + ptr_server = NULL; + ptr_channel = NULL; + argv = weechat_string_split (arguments, ",", 0, 0, &argc); + if (!argv) + return NULL; + + if (argc >= 3) + { + ptr_server = irc_server_search (argv[0]); + if (!ptr_server) + { + weechat_string_free_split (argv); + return NULL; + } + ptr_channel = irc_channel_search (ptr_server, argv[1]); + if (!ptr_channel) + { + weechat_string_free_split (argv); + return NULL; + } + ptr_modelist = irc_modelist_search (ptr_channel, argv[2][0]); + if (!ptr_modelist) + { + weechat_string_free_split (argv); + return NULL; + } + if (!obj_pointer && (argc >= 4)) + { + error = NULL; + number = strtol (argv[3], &error, 10); + if (!error || error[0] || (number < 0)) + { + weechat_string_free_split (argv); + return NULL; + } + obj_pointer = irc_modelist_item_search_number (ptr_modelist, + (int)number); + if (!obj_pointer) + { + weechat_string_free_split (argv); + return NULL; + } + } + } + weechat_string_free_split (argv); + + if (!ptr_server || !ptr_channel || !ptr_modelist) + return NULL; + + if (obj_pointer && !irc_modelist_item_valid (ptr_modelist, obj_pointer)) + return NULL; + + ptr_infolist = weechat_infolist_new (); + if (!ptr_infolist) + return NULL; + + if (obj_pointer) + { + /* build list with only one modelist item */ + if (!irc_modelist_item_add_to_infolist (ptr_infolist, obj_pointer)) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + return ptr_infolist; + } + else + { + /* build list with all modelist items of modelist */ + for (ptr_item = ptr_modelist->items; ptr_item; + ptr_item = ptr_item->next_item) + { + if (!irc_modelist_item_add_to_infolist (ptr_infolist, ptr_item)) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + } + return ptr_infolist; + } + + return NULL; +} + +/* * Returns IRC infolist "irc_nick". */ @@ -898,7 +1104,7 @@ irc_info_init () &irc_info_info_hashtable_irc_message_parse_cb, NULL, NULL); weechat_hook_info_hashtable ( "irc_message_split", - N_("split an IRC message (to fit in 512 bytes)"), + N_("split an IRC message (to fit in 512 bytes by default)"), N_("\"message\": IRC message, \"server\": server name (optional)"), /* TRANSLATORS: please do not translate key names (enclosed by quotes) */ N_("\"msg1\" ... \"msgN\": messages to send (without final \"\\r\\n\"), " @@ -920,6 +1126,18 @@ irc_info_init () N_("server,channel (channel is optional)"), &irc_info_infolist_irc_channel_cb, NULL, NULL); weechat_hook_infolist ( + "irc_modelist", + N_("list of channel mode lists for an IRC channel"), + N_("mode list pointer (optional)"), + N_("server,channel,type (type is optional)"), + &irc_info_infolist_irc_modelist_cb, NULL, NULL); + weechat_hook_infolist ( + "irc_modelist_item", + N_("list of items in a channel mode list"), + N_("mode list item pointer (optional)"), + N_("server,channel,type,number (number is optional)"), + &irc_info_infolist_irc_modelist_item_cb, NULL, NULL); + weechat_hook_infolist ( "irc_nick", N_("list of nicks for an IRC channel"), N_("nick pointer (optional)"), @@ -949,6 +1167,12 @@ irc_info_init () "irc_nick", N_("irc nick"), &irc_nick_hdata_nick_cb, NULL, NULL); weechat_hook_hdata ( + "irc_modelist", N_("irc modelist"), + &irc_modelist_hdata_modelist_cb, NULL, NULL); + weechat_hook_hdata ( + "irc_modelist_item", N_("irc modelist item"), + &irc_modelist_hdata_item_cb, NULL, NULL); + weechat_hook_hdata ( "irc_channel", N_("irc channel"), &irc_channel_hdata_channel_cb, NULL, NULL); weechat_hook_hdata ( diff --git a/src/plugins/irc/irc-info.h b/src/plugins/irc/irc-info.h index abe44cfb7..765f058c3 100644 --- a/src/plugins/irc/irc-info.h +++ b/src/plugins/irc/irc-info.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_INFO_H -#define WEECHAT_IRC_INFO_H 1 +#ifndef WEECHAT_PLUGIN_IRC_INFO_H +#define WEECHAT_PLUGIN_IRC_INFO_H extern void irc_info_init (); -#endif /* WEECHAT_IRC_INFO_H */ +#endif /* WEECHAT_PLUGIN_IRC_INFO_H */ diff --git a/src/plugins/irc/irc-input.c b/src/plugins/irc/irc-input.c index 850642139..e2139c898 100644 --- a/src/plugins/irc/irc-input.c +++ b/src/plugins/irc/irc-input.c @@ -1,7 +1,7 @@ /* * irc-input.c - input data management for IRC buffers * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -139,7 +139,8 @@ irc_input_user_message_display (struct t_gui_buffer *buffer, int action, } /* - * Sends a PRIVMSG message, and split it if message size is > 512 bytes. + * Sends a PRIVMSG message, and split it if message size is > 512 bytes + * (by default). * * Warning: this function makes temporary changes in "message". */ diff --git a/src/plugins/irc/irc-input.h b/src/plugins/irc/irc-input.h index 023aba39d..542340ef1 100644 --- a/src/plugins/irc/irc-input.h +++ b/src/plugins/irc/irc-input.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_INPUT_H -#define WEECHAT_IRC_INPUT_H 1 +#ifndef WEECHAT_PLUGIN_IRC_INPUT_H +#define WEECHAT_PLUGIN_IRC_INPUT_H struct t_gui_buffer; @@ -31,4 +31,4 @@ extern int irc_input_send_cb (const void *pointer, void *data, const char *signal, const char *type_data, void *signal_data); -#endif /* WEECHAT_IRC_INPUT_H */ +#endif /* WEECHAT_PLUGIN_IRC_INPUT_H */ diff --git a/src/plugins/irc/irc-message.c b/src/plugins/irc/irc-message.c index 1d377c701..2df6ab2e8 100644 --- a/src/plugins/irc/irc-message.c +++ b/src/plugins/irc/irc-message.c @@ -1,7 +1,7 @@ /* * irc-message.c - functions for IRC messages * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -20,13 +20,15 @@ */ #include <stdlib.h> +#include <limits.h> #include <stdio.h> #include <string.h> #include "../weechat-plugin.h" #include "irc.h" -#include "irc-server.h" #include "irc-channel.h" +#include "irc-config.h" +#include "irc-server.h" /* @@ -111,9 +113,9 @@ irc_message_parse (struct t_irc_server *server, const char *message, if (ptr_message[0] == '@') { /* - * read tags (they are optional and enabled only if client enabled - * a server capability, see: - * http://ircv3.atheme.org/specification/message-tags-3.2) + * Read tags: they are optional and enabled only if client enabled + * a server capability. + * See: https://ircv3.github.io/specs/core/message-tags-3.2.html */ pos = strchr (ptr_message, ' '); if (pos) @@ -653,13 +655,14 @@ irc_message_split_string (struct t_hashtable *hashtable, const char *arguments, const char *suffix, const char delimiter, - int max_length_host) + int max_length_host, + int max_length) { const char *pos, *pos_max, *pos_next, *pos_last_delim; - char message[1024], *dup_arguments; - int max_length, number; + char message[8192], *dup_arguments; + int number; - max_length = 510; + max_length -= 2; /* by default: 512 - 2 = 510 bytes */ if (max_length_host >= 0) max_length -= max_length_host; else @@ -707,7 +710,7 @@ irc_message_split_string (struct t_hashtable *hashtable, pos = arguments; pos_max = pos + max_length; pos_last_delim = NULL; - while (pos && pos[0]) + while (pos[0]) { if (pos[0] == delimiter) pos_last_delim = pos; @@ -753,12 +756,15 @@ irc_message_split_string (struct t_hashtable *hashtable, int irc_message_split_join (struct t_hashtable *hashtable, const char *tags, const char *host, - const char *arguments) + const char *arguments, + int max_length) { int number, channels_count, keys_count, length, length_no_channel; int length_to_add, index_channel; char **channels, **keys, *pos, *str; - char msg_to_send[2048], keys_to_add[2048]; + char msg_to_send[16384], keys_to_add[16384]; + + max_length -= 2; /* by default: 512 - 2 = 510 bytes */ number = 1; @@ -799,7 +805,8 @@ irc_message_split_join (struct t_hashtable *hashtable, length_to_add = 1 + strlen (channels[index_channel]); if (index_channel < keys_count) length_to_add += 1 + strlen (keys[index_channel]); - if ((length + length_to_add < 510) || (length == length_no_channel)) + if ((length + length_to_add < max_length) + || (length == length_no_channel)) { if (length + length_to_add < (int)sizeof (msg_to_send)) { @@ -864,9 +871,10 @@ int irc_message_split_privmsg_notice (struct t_hashtable *hashtable, char *tags, char *host, char *command, char *target, char *arguments, - int max_length_host) + int max_length_host, + int max_length) { - char prefix[512], suffix[2], *pos, saved_char; + char prefix[4096], suffix[2], *pos, saved_char; int length, rc; /* @@ -903,7 +911,7 @@ irc_message_split_privmsg_notice (struct t_hashtable *hashtable, rc = irc_message_split_string (hashtable, tags, host, command, target, prefix, arguments, suffix, - ' ', max_length_host); + ' ', max_length_host, max_length); return rc; } @@ -919,9 +927,9 @@ irc_message_split_privmsg_notice (struct t_hashtable *hashtable, int irc_message_split_005 (struct t_hashtable *hashtable, char *tags, char *host, char *command, char *target, - char *arguments) + char *arguments, int max_length) { - char *pos, suffix[512]; + char *pos, suffix[4096]; /* * 005 message looks like: @@ -941,7 +949,8 @@ irc_message_split_005 (struct t_hashtable *hashtable, } return irc_message_split_string (hashtable, tags, host, command, target, - NULL, arguments, suffix, ' ', -1); + NULL, arguments, suffix, ' ', -1, + max_length); } /* @@ -951,6 +960,10 @@ irc_message_split_005 (struct t_hashtable *hashtable, * "\r\n", so full size is 512 bytes (the user data does not include the * optional tags before the host). * + * The 512 max length is the default (recommended) and can be changed with the + * server option called "split_msg_max_length" (0 to disable completely the + * split). + * * The split takes care about type of message to do a split at best place in * message. * @@ -972,9 +985,10 @@ struct t_hashtable * irc_message_split (struct t_irc_server *server, const char *message) { struct t_hashtable *hashtable; - char **argv, **argv_eol, *tags, *host, *command, *arguments, target[512]; + char **argv, **argv_eol, *tags, *host, *command, *arguments, target[4096]; char *pos, monitor_action[3]; int split_ok, argc, index_args, max_length_nick, max_length_host; + int split_msg_max_length; split_ok = 0; tags = NULL; @@ -984,9 +998,29 @@ irc_message_split (struct t_irc_server *server, const char *message) argv = NULL; argv_eol = NULL; + if (server) + { + split_msg_max_length = IRC_SERVER_OPTION_INTEGER( + server, IRC_SERVER_OPTION_SPLIT_MSG_MAX_LENGTH); + + /* + * split disabled? use a very high max_length so the message should + * never be split + */ + if (split_msg_max_length == 0) + split_msg_max_length = INT_MAX - 16; + } + else + { + split_msg_max_length = 512; /* max length by default */ + } + /* debug message */ if (weechat_irc_plugin->debug >= 2) - weechat_printf (NULL, "irc_message_split: message='%s'", message); + { + weechat_printf (NULL, "irc_message_split: message='%s', max length=%d", + message, split_msg_max_length); + } hashtable = weechat_hashtable_new (32, WEECHAT_HASHTABLE_STRING, @@ -1049,7 +1083,7 @@ irc_message_split (struct t_irc_server *server, const char *message) hashtable, tags, host, command, NULL, ":", (argv_eol[index_args][0] == ':') ? argv_eol[index_args] + 1 : argv_eol[index_args], - NULL, ' ', max_length_host); + NULL, ' ', max_length_host, split_msg_max_length); } else if (weechat_strcasecmp (command, "monitor") == 0) { @@ -1064,7 +1098,8 @@ irc_message_split (struct t_irc_server *server, const char *message) "%c ", argv_eol[index_args][0]); split_ok = irc_message_split_string ( hashtable, tags, host, command, NULL, monitor_action, - argv_eol[index_args] + 2, NULL, ',', max_length_host); + argv_eol[index_args] + 2, NULL, ',', max_length_host, + split_msg_max_length); } else { @@ -1072,17 +1107,17 @@ irc_message_split (struct t_irc_server *server, const char *message) hashtable, tags, host, command, NULL, ":", (argv_eol[index_args][0] == ':') ? argv_eol[index_args] + 1 : argv_eol[index_args], - NULL, ',', max_length_host); + NULL, ',', max_length_host, split_msg_max_length); } } else if (weechat_strcasecmp (command, "join") == 0) { /* JOIN #channel1,#channel2,#channel3 key1,key2 */ - if (strlen (message) > 510) + if ((int)strlen (message) > split_msg_max_length - 2) { - /* split join if it's more than 510 bytes */ + /* split join if it's too long */ split_ok = irc_message_split_join (hashtable, tags, host, - arguments); + arguments, split_msg_max_length); } } else if ((weechat_strcasecmp (command, "privmsg") == 0) @@ -1098,7 +1133,7 @@ irc_message_split (struct t_irc_server *server, const char *message) hashtable, tags, host, command, argv[index_args], (argv_eol[index_args + 1][0] == ':') ? argv_eol[index_args + 1] + 1 : argv_eol[index_args + 1], - max_length_host); + max_length_host, split_msg_max_length); } } else if (weechat_strcasecmp (command, "005") == 0) @@ -1109,7 +1144,8 @@ irc_message_split (struct t_irc_server *server, const char *message) split_ok = irc_message_split_005 ( hashtable, tags, host, command, argv[index_args], (argv_eol[index_args + 1][0] == ':') ? - argv_eol[index_args + 1] + 1 : argv_eol[index_args + 1]); + argv_eol[index_args + 1] + 1 : argv_eol[index_args + 1], + split_msg_max_length); } } else if (weechat_strcasecmp (command, "353") == 0) @@ -1128,7 +1164,7 @@ irc_message_split (struct t_irc_server *server, const char *message) hashtable, tags, host, command, target, ":", (argv_eol[index_args + 2][0] == ':') ? argv_eol[index_args + 2] + 1 : argv_eol[index_args + 2], - NULL, ' ', -1); + NULL, ' ', -1, split_msg_max_length); } else { @@ -1141,7 +1177,7 @@ irc_message_split (struct t_irc_server *server, const char *message) hashtable, tags, host, command, target, ":", (argv_eol[index_args + 3][0] == ':') ? argv_eol[index_args + 3] + 1 : argv_eol[index_args + 3], - NULL, ' ', -1); + NULL, ' ', -1, split_msg_max_length); } } } diff --git a/src/plugins/irc/irc-message.h b/src/plugins/irc/irc-message.h index b1fa63e30..cbf2d331d 100644 --- a/src/plugins/irc/irc-message.h +++ b/src/plugins/irc/irc-message.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_MESSAGE_H -#define WEECHAT_IRC_MESSAGE_H 1 +#ifndef WEECHAT_PLUGIN_IRC_MESSAGE_H +#define WEECHAT_PLUGIN_IRC_MESSAGE_H struct t_irc_server; struct t_irc_channel; @@ -43,4 +43,4 @@ extern char *irc_message_replace_vars (struct t_irc_server *server, extern struct t_hashtable *irc_message_split (struct t_irc_server *server, const char *message); -#endif /* WEECHAT_IRC_MESSAGE_H */ +#endif /* WEECHAT_PLUGIN_IRC_MESSAGE_H */ diff --git a/src/plugins/irc/irc-mode.c b/src/plugins/irc/irc-mode.c index d828a13a4..b5d525c6c 100644 --- a/src/plugins/irc/irc-mode.c +++ b/src/plugins/irc/irc-mode.c @@ -1,7 +1,7 @@ /* * irc-mode.c - IRC channel/user modes management * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -22,6 +22,7 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <time.h> #include "../weechat-plugin.h" #include "irc.h" @@ -30,6 +31,7 @@ #include "irc-server.h" #include "irc-channel.h" #include "irc-nick.h" +#include "irc-modelist.h" /* @@ -317,12 +319,15 @@ irc_mode_smart_filtered (struct t_irc_server *server, char mode) int irc_mode_channel_set (struct t_irc_server *server, struct t_irc_channel *channel, + const char *host, const char *modes) { char *pos_args, *str_modes, set_flag, **argv, *pos, *ptr_arg, chanmode_type; int argc, current_arg, update_channel_modes, channel_modes_updated; int smart_filter; struct t_irc_nick *ptr_nick; + struct t_irc_modelist *ptr_modelist; + struct t_irc_modelist_item *ptr_item; if (!server || !channel || !modes) return 0; @@ -464,6 +469,27 @@ irc_mode_channel_set (struct t_irc_server *server, } } } + else if (chanmode_type == 'A') + { + /* modelist modes */ + ptr_modelist = irc_modelist_search (channel, pos[0]); + if (ptr_modelist) + { + if (set_flag == '+') + { + irc_modelist_item_new (ptr_modelist, ptr_arg, + host, time (NULL)); + } + else if (set_flag == '-') + { + ptr_item = irc_modelist_item_search_mask ( + ptr_modelist, ptr_arg); + if (ptr_item) + irc_modelist_item_free (ptr_modelist, ptr_item); + } + } + } + if (update_channel_modes) { irc_mode_channel_update (server, channel, set_flag, diff --git a/src/plugins/irc/irc-mode.h b/src/plugins/irc/irc-mode.h index 03313d983..857a8a8fc 100644 --- a/src/plugins/irc/irc-mode.h +++ b/src/plugins/irc/irc-mode.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_MODE_H -#define WEECHAT_IRC_MODE_H 1 +#ifndef WEECHAT_PLUGIN_IRC_MODE_H +#define WEECHAT_PLUGIN_IRC_MODE_H struct t_irc_server; struct t_irc_channel; @@ -27,8 +27,9 @@ extern char irc_mode_get_chanmode_type (struct t_irc_server *server, char chanmode); extern int irc_mode_channel_set (struct t_irc_server *server, struct t_irc_channel *channel, + const char *host, const char *modes); extern void irc_mode_user_set (struct t_irc_server *server, const char *modes, int reset_modes); -#endif /* WEECHAT_IRC_MODE_H */ +#endif /* WEECHAT_PLUGIN_IRC_MODE_H */ diff --git a/src/plugins/irc/irc-modelist.c b/src/plugins/irc/irc-modelist.c new file mode 100644 index 000000000..d21b34971 --- /dev/null +++ b/src/plugins/irc/irc-modelist.c @@ -0,0 +1,505 @@ +/* + * irc-modelist.c - channel mode list management for IRC plugin + * + * Copyright (C) 2015 Simmo Saan <simmo.saan@gmail.com> + * Copyright (C) 2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stddef.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <time.h> + +#include "../weechat-plugin.h" +#include "irc.h" +#include "irc-channel.h" +#include "irc-modelist.h" + + +/* + * Checks if a modelist pointer is valid for a channel. + * + * Returns: + * 1: modelist exists for channel + * 0: modelist does not exist for channel + */ + +int +irc_modelist_valid (struct t_irc_channel *channel, + struct t_irc_modelist *modelist) +{ + struct t_irc_modelist *ptr_modelist; + + if (!channel || !modelist) + return 0; + + for (ptr_modelist = channel->modelists; ptr_modelist; + ptr_modelist = ptr_modelist->next_modelist) + { + if (ptr_modelist == modelist) + return 1; + } + + /* modelist not found */ + return 0; +} + +/* + * Searches for a modelist by type. + * + * Returns pointer to modelist found, NULL if not found. + */ + +struct t_irc_modelist * +irc_modelist_search (struct t_irc_channel *channel, char type) +{ + struct t_irc_modelist *ptr_modelist; + + if (!channel) + return NULL; + + for (ptr_modelist = channel->modelists; ptr_modelist; + ptr_modelist = ptr_modelist->next_modelist) + { + if (ptr_modelist->type == type) + return ptr_modelist; + } + return NULL; +} + +/* + * Creates a new modelist in a channel. + * + * Returns pointer to new modelist, NULL if error. + */ + +struct t_irc_modelist * +irc_modelist_new (struct t_irc_channel *channel, char type) +{ + struct t_irc_modelist *new_modelist; + + /* alloc memory for new modelist */ + if ((new_modelist = malloc (sizeof (*new_modelist))) == NULL) + { + weechat_printf (NULL, + _("%s%s: cannot allocate new modelist"), + weechat_prefix ("error"), IRC_PLUGIN_NAME); + return NULL; + } + + /* initialize new modelist */ + new_modelist->type = type; + new_modelist->state = IRC_MODELIST_STATE_EMPTY; + new_modelist->items = NULL; + new_modelist->last_item = NULL; + + /* add new modelist to channel */ + new_modelist->prev_modelist = channel->last_modelist; + new_modelist->next_modelist = NULL; + if (channel->modelists) + (channel->last_modelist)->next_modelist = new_modelist; + else + channel->modelists = new_modelist; + channel->last_modelist = new_modelist; + + /* all is OK, return address of new modelist */ + return new_modelist; +} + +/* + * Frees a modelist and remove it from channel. + */ + +void +irc_modelist_free (struct t_irc_channel *channel, + struct t_irc_modelist *modelist) +{ + struct t_irc_modelist *new_modelists; + + if (!channel || !modelist) + return; + + /* remove modelist from channel modelists */ + if (channel->last_modelist == modelist) + channel->last_modelist = modelist->prev_modelist; + if (modelist->prev_modelist) + { + (modelist->prev_modelist)->next_modelist = modelist->next_modelist; + new_modelists = channel->modelists; + } + else + new_modelists = modelist->next_modelist; + + if (modelist->next_modelist) + (modelist->next_modelist)->prev_modelist = modelist->prev_modelist; + + /* free linked lists */ + irc_modelist_item_free_all (modelist); + + free (modelist); + + channel->modelists = new_modelists; +} + +/* + * Frees all modelists for a channel. + */ + +void +irc_modelist_free_all (struct t_irc_channel *channel) +{ + while (channel->modelists) + { + irc_modelist_free (channel, channel->modelists); + } +} + +/* + * Checks if a modelist item pointer is valid for a modelist. + * + * Returns: + * 1: item exists for modelist + * 0: item does not exist for modelist + */ + +int +irc_modelist_item_valid (struct t_irc_modelist *modelist, + struct t_irc_modelist_item *item) +{ + struct t_irc_modelist_item *ptr_item; + + if (!modelist || !item) + return 0; + + for (ptr_item = modelist->items; ptr_item; + ptr_item = ptr_item->next_item) + { + if (ptr_item == item) + return 1; + } + + /* item not found */ + return 0; +} + +/* + * Searches for an item by mask. + * + * Returns pointer to item found, NULL if not found. + */ + +struct t_irc_modelist_item * +irc_modelist_item_search_mask (struct t_irc_modelist *modelist, const char *mask) +{ + struct t_irc_modelist_item *ptr_item; + + if (!modelist || !mask) + return NULL; + + for (ptr_item = modelist->items; ptr_item; + ptr_item = ptr_item->next_item) + { + if (strcmp (ptr_item->mask, mask) == 0) + return ptr_item; + } + return NULL; +} + +/* + * Searches for an item by number. + * + * Returns pointer to item found, NULL if not found. + */ + +struct t_irc_modelist_item * +irc_modelist_item_search_number (struct t_irc_modelist *modelist, int number) +{ + struct t_irc_modelist_item *ptr_item; + + if (!modelist) + return NULL; + + for (ptr_item = modelist->items; ptr_item; + ptr_item = ptr_item->next_item) + { + if (ptr_item->number == number) + return ptr_item; + } + return NULL; +} + +/* + * Creates a new item in a modelist. + * + * Returns pointer to new item, NULL if error. + */ + +struct t_irc_modelist_item * +irc_modelist_item_new (struct t_irc_modelist *modelist, + const char *mask, const char *setter, time_t datetime) +{ + struct t_irc_modelist_item *new_item; + + /* alloc memory for new item */ + if ((new_item = malloc (sizeof (*new_item))) == NULL) + { + weechat_printf (NULL, + _("%s%s: cannot allocate new modelist item"), + weechat_prefix ("error"), IRC_PLUGIN_NAME); + return NULL; + } + + /* initialize new item */ + new_item->number = (modelist->last_item) ? + modelist->last_item->number + 1 : 0; + new_item->mask = strdup (mask); + new_item->setter = (setter) ? strdup (setter) : NULL; + new_item->datetime = datetime; + + /* add new item to modelist */ + new_item->prev_item = modelist->last_item; + new_item->next_item = NULL; + if (modelist->items) + (modelist->last_item)->next_item = new_item; + else + modelist->items = new_item; + modelist->last_item = new_item; + + if ((modelist->state == IRC_MODELIST_STATE_EMPTY) || + (modelist->state == IRC_MODELIST_STATE_RECEIVED)) + { + modelist->state = IRC_MODELIST_STATE_MODIFIED; + } + + /* all is OK, return address of new item */ + return new_item; +} + +/* + * Frees an item and remove it from modelist. + */ + +void +irc_modelist_item_free (struct t_irc_modelist *modelist, + struct t_irc_modelist_item *item) +{ + struct t_irc_modelist_item *new_items; + + if (!modelist || !item) + return; + + /* remove item from modelist list */ + if (modelist->last_item == item) + modelist->last_item = item->prev_item; + if (item->prev_item) + { + (item->prev_item)->next_item = item->next_item; + new_items = modelist->items; + } + else + new_items = item->next_item; + + if (item->next_item) + (item->next_item)->prev_item = item->prev_item; + + /* free item data */ + if (item->mask) + free (item->mask); + if (item->setter) + free (item->setter); + free (item); + + modelist->items = new_items; + + if (modelist->state == IRC_MODELIST_STATE_RECEIVED) + modelist->state = IRC_MODELIST_STATE_MODIFIED; +} + +/* + * Frees all items for a modelist. + */ + +void +irc_modelist_item_free_all (struct t_irc_modelist *modelist) +{ + while (modelist->items) + { + irc_modelist_item_free (modelist, modelist->items); + } + modelist->state = IRC_MODELIST_STATE_EMPTY; +} + +/* + * Returns hdata for modelist item. + */ + +struct t_hdata * +irc_modelist_hdata_item_cb (const void *pointer, void *data, + const char *hdata_name) +{ + struct t_hdata *hdata; + + /* make C compiler happy */ + (void) pointer; + (void) data; + + hdata = weechat_hdata_new (hdata_name, "prev_item", "next_item", + 0, 0, NULL, NULL); + if (hdata) + { + WEECHAT_HDATA_VAR(struct t_irc_modelist_item, number, INTEGER, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_irc_modelist_item, mask, STRING, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_irc_modelist_item, setter, STRING, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_irc_modelist_item, datetime, TIME, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_irc_modelist_item, prev_item, POINTER, 0, NULL, hdata_name); + WEECHAT_HDATA_VAR(struct t_irc_modelist_item, next_item, POINTER, 0, NULL, hdata_name); + } + return hdata; +} + +/* + * Returns hdata for modelist. + */ + +struct t_hdata * +irc_modelist_hdata_modelist_cb (const void *pointer, void *data, const char *hdata_name) +{ + struct t_hdata *hdata; + + /* make C compiler happy */ + (void) pointer; + (void) data; + + hdata = weechat_hdata_new (hdata_name, "prev_modelist", "next_modelist", + 0, 0, NULL, NULL); + if (hdata) + { + WEECHAT_HDATA_VAR(struct t_irc_modelist, type, CHAR, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_irc_modelist, state, INTEGER, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_irc_modelist, items, POINTER, 0, NULL, "irc_modelist_item"); + WEECHAT_HDATA_VAR(struct t_irc_modelist, last_item, POINTER, 0, NULL, "irc_modelist_item"); + WEECHAT_HDATA_VAR(struct t_irc_modelist, prev_modelist, POINTER, 0, NULL, hdata_name); + WEECHAT_HDATA_VAR(struct t_irc_modelist, next_modelist, POINTER, 0, NULL, hdata_name); + } + return hdata; +} + +/* + * Adds a modelist item in an infolist. + * + * Returns: + * 1: OK + * 0: error + */ + +int +irc_modelist_item_add_to_infolist (struct t_infolist *infolist, + struct t_irc_modelist_item *item) +{ + struct t_infolist_item *ptr_item; + + if (!infolist || !item) + return 0; + + ptr_item = weechat_infolist_new_item (infolist); + if (!ptr_item) + return 0; + + if (!weechat_infolist_new_var_integer (ptr_item, "number", item->number)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "mask", item->mask)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "setter", item->setter)) + return 0; + if (!weechat_infolist_new_var_time (ptr_item, "datetime", item->datetime)) + return 0; + + return 1; +} + +/* + * Adds a modelist in an infolist. + * + * Returns: + * 1: OK + * 0: error + */ + +int +irc_modelist_add_to_infolist (struct t_infolist *infolist, + struct t_irc_modelist *modelist) +{ + struct t_infolist_item *ptr_item; + char str_type[2]; + + if (!infolist || !modelist) + return 0; + + ptr_item = weechat_infolist_new_item (infolist); + if (!ptr_item) + return 0; + + str_type[0] = modelist->type; + str_type[1] = '\0'; + + if (!weechat_infolist_new_var_string (ptr_item, "type", str_type)) + return 0; + if (!weechat_infolist_new_var_integer (ptr_item, "state", modelist->state)) + return 0; + + return 1; +} + +/* + * Prints modelist item infos in WeeChat log file (usually for crash dump). + */ + +void +irc_modelist_item_print_log (struct t_irc_modelist_item *item) +{ + weechat_log_printf (""); + weechat_log_printf (" => modelist item %d (addr:0x%lx):", item->number, item); + weechat_log_printf (" mask . . . . . . . . . . : '%s'", item->mask); + weechat_log_printf (" setter . . . . . . . . . : '%s'", item->setter); + weechat_log_printf (" datetime . . . . . . . . : %lld", + (long long)(item->datetime)); + weechat_log_printf (" prev_item . . . . . . . : 0x%lx", item->prev_item); + weechat_log_printf (" next_item . . . . . . . : 0x%lx", item->next_item); +} + +/* + * Prints modelist infos in WeeChat log file (usually for crash dump). + */ + +void +irc_modelist_print_log (struct t_irc_modelist *modelist) +{ + struct t_irc_modelist_item *ptr_item; + + weechat_log_printf (""); + weechat_log_printf (" => modelist \"%c\" (addr:0x%lx):", modelist->type, modelist); + weechat_log_printf (" state. . . . . . . . . . : %d", modelist->state); + weechat_log_printf (" prev_modelist . . . . . : 0x%lx", modelist->prev_modelist); + weechat_log_printf (" next_modelist . . . . . : 0x%lx", modelist->next_modelist); + for (ptr_item = modelist->items; ptr_item; ptr_item = ptr_item->next_item) + { + irc_modelist_item_print_log (ptr_item); + } +} diff --git a/src/plugins/irc/irc-modelist.h b/src/plugins/irc/irc-modelist.h new file mode 100644 index 000000000..1648ef9eb --- /dev/null +++ b/src/plugins/irc/irc-modelist.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2015 Simmo Saan <simmo.saan@gmail.com> + * Copyright (C) 2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef WEECHAT_PLUGIN_IRC_MODELIST_H +#define WEECHAT_PLUGIN_IRC_MODELIST_H + +#include <time.h> + +/* modelist states */ +#define IRC_MODELIST_STATE_EMPTY 0 +#define IRC_MODELIST_STATE_RECEIVING 1 +#define IRC_MODELIST_STATE_RECEIVED 2 +#define IRC_MODELIST_STATE_MODIFIED 3 + +struct t_irc_server; + +struct t_irc_modelist_item +{ + int number; /* item number */ + char *mask; /* modelist mask */ + char *setter; /* hostmask of setter (optional) */ + time_t datetime; /* datetime of setting (optional)*/ + + struct t_irc_modelist_item *prev_item; /* pointer to previous item */ + struct t_irc_modelist_item *next_item; /* pointer to next item */ +}; + +struct t_irc_modelist +{ + char type; /* mode list channel A type */ + int state; /* state */ + + struct t_irc_modelist_item *items; /* items in modelist */ + struct t_irc_modelist_item *last_item; /* last item in modelist */ + + struct t_irc_modelist *prev_modelist; /* pointer to previous modelist */ + struct t_irc_modelist *next_modelist; /* pointer to next modelist */ +}; + +extern int irc_modelist_valid (struct t_irc_channel *channel, + struct t_irc_modelist *modelist); +extern struct t_irc_modelist *irc_modelist_search (struct t_irc_channel *channel, + char type); +extern struct t_irc_modelist *irc_modelist_new (struct t_irc_channel *channel, + char type); +extern void irc_modelist_free (struct t_irc_channel *channel, + struct t_irc_modelist *modelist); +extern void irc_modelist_free_all (struct t_irc_channel *channel); + +extern int irc_modelist_item_valid (struct t_irc_modelist *modelist, + struct t_irc_modelist_item *item); +extern struct t_irc_modelist_item *irc_modelist_item_search_mask (struct t_irc_modelist *modelist, + const char *mask); +extern struct t_irc_modelist_item *irc_modelist_item_search_number (struct t_irc_modelist *modelist, + int number); +extern struct t_irc_modelist_item *irc_modelist_item_new (struct t_irc_modelist *modelist, + const char *mask, + const char *setter, + time_t datetime); +extern void irc_modelist_item_free (struct t_irc_modelist *modelist, + struct t_irc_modelist_item *item); +extern void irc_modelist_item_free_all (struct t_irc_modelist *modelist); + +extern struct t_hdata *irc_modelist_hdata_item_cb (const void *pointer, + void *data, + const char *hdata_name); +extern struct t_hdata *irc_modelist_hdata_modelist_cb (const void *pointer, + void *data, + const char *hdata_name); +extern int irc_modelist_item_add_to_infolist (struct t_infolist *infolist, + struct t_irc_modelist_item *item); +extern int irc_modelist_add_to_infolist (struct t_infolist *infolist, + struct t_irc_modelist *modelist); +extern void irc_modelist_item_print_log (struct t_irc_modelist_item *item); +extern void irc_modelist_print_log (struct t_irc_modelist *modelist); + +#endif /* WEECHAT_PLUGIN_IRC_MODELIST_H */ diff --git a/src/plugins/irc/irc-msgbuffer.c b/src/plugins/irc/irc-msgbuffer.c index 21339e7bc..ad57ecdb2 100644 --- a/src/plugins/irc/irc-msgbuffer.c +++ b/src/plugins/irc/irc-msgbuffer.c @@ -1,7 +1,7 @@ /* * irc-msgbuffer.c - target buffer for IRC messages * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/irc/irc-msgbuffer.h b/src/plugins/irc/irc-msgbuffer.h index c2e72fe05..c96bfa23a 100644 --- a/src/plugins/irc/irc-msgbuffer.h +++ b/src/plugins/irc/irc-msgbuffer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_MSGBUFFER_H -#define WEECHAT_IRC_MSGBUFFER_H 1 +#ifndef WEECHAT_PLUGIN_IRC_MSGBUFFER_H +#define WEECHAT_PLUGIN_IRC_MSGBUFFER_H enum t_irc_msgbuffer_target { @@ -38,4 +38,4 @@ extern struct t_gui_buffer *irc_msgbuffer_get_target_buffer (struct t_irc_server const char *alias, struct t_gui_buffer *default_buffer); -#endif /* WEECHAT_IRC_MSGBUFFER_H */ +#endif /* WEECHAT_PLUGIN_IRC_MSGBUFFER_H */ diff --git a/src/plugins/irc/irc-nick.c b/src/plugins/irc/irc-nick.c index 6559fc2ca..22e89da26 100644 --- a/src/plugins/irc/irc-nick.c +++ b/src/plugins/irc/irc-nick.c @@ -1,7 +1,7 @@ /* * irc-nick.c - nick management for IRC plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -320,7 +320,7 @@ irc_nick_get_color_for_nicklist (struct t_irc_server *server, if (nick->away) return nick_color_away; - if (weechat_config_boolean(irc_config_look_color_nicks_in_nicklist)) + if (weechat_config_boolean (irc_config_look_color_nicks_in_nicklist)) { if (irc_server_strcasecmp (server, nick->name, server->nick) == 0) return nick_color_self; @@ -470,15 +470,8 @@ irc_nick_new (struct t_irc_server *server, struct t_irc_channel *channel, /* remove old nick from nicklist */ irc_nick_nicklist_remove (server, channel, ptr_nick); - /* update nick */ + /* update nick prefixes */ irc_nick_set_prefixes (server, ptr_nick, prefixes); - ptr_nick->away = away; - if (ptr_nick->account) - free (ptr_nick->account); - ptr_nick->account = (account) ? strdup (account) : NULL; - if (ptr_nick->realname) - free (ptr_nick->realname); - ptr_nick->realname = (realname) ? strdup (realname) : NULL; /* add new nick in nicklist */ irc_nick_nicklist_add (server, channel, ptr_nick); @@ -497,7 +490,8 @@ irc_nick_new (struct t_irc_server *server, struct t_irc_channel *channel, new_nick->realname = (realname) ? strdup (realname) : NULL; length = strlen (irc_server_get_prefix_chars (server)); new_nick->prefixes = malloc (length + 1); - if (!new_nick->name || !new_nick->prefixes) + new_nick->prefix = malloc (2); + if (!new_nick->name || !new_nick->prefixes || !new_nick->prefix) { if (new_nick->name) free (new_nick->name); @@ -509,14 +503,13 @@ irc_nick_new (struct t_irc_server *server, struct t_irc_channel *channel, free (new_nick->realname); if (new_nick->prefixes) free (new_nick->prefixes); + if (new_nick->prefix) + free (new_nick->prefix); free (new_nick); return NULL; } - if (new_nick->prefixes) - { - memset (new_nick->prefixes, ' ', length); - new_nick->prefixes[length] = '\0'; - } + memset (new_nick->prefixes, ' ', length); + new_nick->prefixes[length] = '\0'; new_nick->prefix[0] = ' '; new_nick->prefix[1] = '\0'; irc_nick_set_prefixes (server, new_nick, prefixes); @@ -647,6 +640,8 @@ irc_nick_free (struct t_irc_server *server, struct t_irc_channel *channel, free (nick->host); if (nick->prefixes) free (nick->prefixes); + if (nick->prefix) + free (nick->prefix); if (nick->account) free (nick->account); if (nick->realname) @@ -754,18 +749,11 @@ void irc_nick_set_away (struct t_irc_server *server, struct t_irc_channel *channel, struct t_irc_nick *nick, int is_away) { - if (!is_away - || weechat_hashtable_has_key (server->cap_list, "away-notify") - || ((IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_AWAY_CHECK) > 0) - && ((IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_AWAY_CHECK_MAX_NICKS) == 0) - || (channel->nicks_count <= IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_AWAY_CHECK_MAX_NICKS))))) + if (is_away != nick->away) { - if ((is_away && !nick->away) || (!is_away && nick->away)) - { - nick->away = is_away; - irc_nick_nicklist_set (channel, nick, "color", - irc_nick_get_color_for_nicklist (server, nick)); - } + nick->away = is_away; + irc_nick_nicklist_set (channel, nick, "color", + irc_nick_get_color_for_nicklist (server, nick)); } } diff --git a/src/plugins/irc/irc-nick.h b/src/plugins/irc/irc-nick.h index f67ee6656..92ef6f199 100644 --- a/src/plugins/irc/irc-nick.h +++ b/src/plugins/irc/irc-nick.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_NICK_H -#define WEECHAT_IRC_NICK_H 1 +#ifndef WEECHAT_PLUGIN_IRC_NICK_H +#define WEECHAT_PLUGIN_IRC_NICK_H #define IRC_NICK_VALID_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHI" \ "JKLMNOPQRSTUVWXYZ0123456789-[]\\`_^{|}" @@ -35,8 +35,8 @@ struct t_irc_nick char *name; /* nickname */ char *host; /* full hostname */ char *prefixes; /* string with prefixes enabled for nick */ - char prefix[2]; /* current prefix (higher prefix set in */ - /* prefixes) */ + char *prefix; /* current prefix (higher prefix set in */ + /* prefixes); string with just one char */ int away; /* 1 if nick is away */ char *account; /* account name of the user */ char *realname; /* realname (aka gecos) of the user */ @@ -109,4 +109,4 @@ extern int irc_nick_add_to_infolist (struct t_infolist *infolist, struct t_irc_nick *nick); extern void irc_nick_print_log (struct t_irc_nick *nick); -#endif /* WEECHAT_IRC_NICK_H */ +#endif /* WEECHAT_PLUGIN_IRC_NICK_H */ diff --git a/src/plugins/irc/irc-notify.c b/src/plugins/irc/irc-notify.c index 579046b29..be847c100 100644 --- a/src/plugins/irc/irc-notify.c +++ b/src/plugins/irc/irc-notify.c @@ -1,7 +1,7 @@ /* * irc-notify.c - notify lists for IRC plugin * - * Copyright (C) 2010-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2010-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/irc/irc-notify.h b/src/plugins/irc/irc-notify.h index 0f6778b7e..81322778c 100644 --- a/src/plugins/irc/irc-notify.h +++ b/src/plugins/irc/irc-notify.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2010-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_NOTIFY_H -#define WEECHAT_IRC_NOTIFY_H 1 +#ifndef WEECHAT_PLUGIN_IRC_NOTIFY_H +#define WEECHAT_PLUGIN_IRC_NOTIFY_H struct t_irc_server; @@ -75,4 +75,4 @@ extern void irc_notify_hook_timer_whois (); extern void irc_notify_init (); extern void irc_notify_end (); -#endif /* WEECHAT_IRC_NOTIFY_H */ +#endif /* WEECHAT_PLUGIN_IRC_NOTIFY_H */ diff --git a/src/plugins/irc/irc-protocol.c b/src/plugins/irc/irc-protocol.c index 1b4fce045..340eb6589 100644 --- a/src/plugins/irc/irc-protocol.c +++ b/src/plugins/irc/irc-protocol.c @@ -1,7 +1,7 @@ /* * irc-protocol.c - implementation of IRC protocol (RFCs 1459/2810/2811/2812/2813) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> * Copyright (C) 2014 Shawn Smith <ShawnSmith0828@gmail.com> * @@ -50,6 +50,7 @@ #include "irc-ignore.h" #include "irc-message.h" #include "irc-mode.h" +#include "irc-modelist.h" #include "irc-msgbuffer.h" #include "irc-nick.h" #include "irc-sasl.h" @@ -252,12 +253,12 @@ IRC_PROTOCOL_CALLBACK(authenticate) { sasl_mechanism = IRC_SERVER_OPTION_INTEGER( server, IRC_SERVER_OPTION_SASL_MECHANISM); - sasl_username = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_USERNAME), - NULL, NULL, NULL); - sasl_password = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_PASSWORD), - NULL, NULL, NULL); + sasl_username = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_USERNAME)); + sasl_password = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_PASSWORD)); sasl_key = IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_KEY); answer = NULL; switch (sasl_mechanism) @@ -697,7 +698,7 @@ IRC_PROTOCOL_CALLBACK(cap) snprintf (str_msg_auth, sizeof (str_msg_auth), "AUTHENTICATE %s", irc_sasl_mechanism_string[sasl_mechanism]); - weechat_string_toupper(str_msg_auth); + weechat_string_toupper (str_msg_auth); irc_server_sendf (server, 0, NULL, str_msg_auth); if (server->hook_timer_sasl) weechat_unhook (server->hook_timer_sasl); @@ -1162,6 +1163,9 @@ IRC_PROTOCOL_CALLBACK(kick) */ irc_nick_free_all (server, ptr_channel); + irc_channel_modelist_set_state (ptr_channel, + IRC_MODELIST_STATE_MODIFIED); + /* read option "autorejoin" in server */ rejoin = IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_AUTOREJOIN); @@ -1276,6 +1280,9 @@ IRC_PROTOCOL_CALLBACK(kill) */ irc_nick_free_all (server, ptr_channel); + irc_channel_modelist_set_state (ptr_channel, + IRC_MODELIST_STATE_MODIFIED); + irc_bar_item_update_channel (); } else @@ -1318,7 +1325,7 @@ IRC_PROTOCOL_CALLBACK(mode) ptr_channel = irc_channel_search (server, argv[2]); if (ptr_channel) { - smart_filter = irc_mode_channel_set (server, ptr_channel, + smart_filter = irc_mode_channel_set (server, ptr_channel, host, pos_modes); } local_mode = (irc_server_strcasecmp (server, nick, server->nick) == 0); @@ -1504,7 +1511,7 @@ IRC_PROTOCOL_CALLBACK(nick) address), _("%s%s%s%s is now known as %s%s%s"), weechat_prefix ("network"), - weechat_config_boolean(irc_config_look_color_nicks_in_server_messages) ? + weechat_config_boolean (irc_config_look_color_nicks_in_server_messages) ? old_color : IRC_COLOR_CHAT_NICK, nick, IRC_COLOR_RESET, @@ -1913,6 +1920,9 @@ IRC_PROTOCOL_CALLBACK(part) { irc_nick_free_all (server, ptr_channel); + irc_channel_modelist_set_state (ptr_channel, + IRC_MODELIST_STATE_MODIFIED); + /* cycling ? => rejoin channel immediately */ if (ptr_channel->cycle) { @@ -2652,9 +2662,9 @@ IRC_PROTOCOL_CALLBACK(001) WEECHAT_HOOK_SIGNAL_STRING, server->name); /* set usermode when connected */ - usermode = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERMODE), - NULL, NULL, NULL); + usermode = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERMODE)); if (usermode && usermode[0]) { irc_server_sendf (server, @@ -2666,9 +2676,9 @@ IRC_PROTOCOL_CALLBACK(001) free (usermode); /* execute command when connected */ - server_command = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_COMMAND), - NULL, NULL, NULL); + server_command = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_COMMAND)); if (server_command && server_command[0]) { /* split command on ';' which can be escaped with '\;' */ @@ -3450,7 +3460,7 @@ IRC_PROTOCOL_CALLBACK(324) irc_channel_set_modes (ptr_channel, ptr_modes); if (argc > 4) { - (void) irc_mode_channel_set (server, ptr_channel, + (void) irc_mode_channel_set (server, ptr_channel, host, ptr_channel->modes); } } @@ -4034,14 +4044,36 @@ IRC_PROTOCOL_CALLBACK(346) { struct t_irc_channel *ptr_channel; struct t_gui_buffer *ptr_buffer; + struct t_irc_modelist *ptr_modelist; time_t datetime; const char *nick_address; + char str_number[64]; IRC_PROTOCOL_MIN_ARGS(5); ptr_channel = irc_channel_search (server, argv[3]); ptr_buffer = (ptr_channel && ptr_channel->nicks) ? ptr_channel->buffer : server->buffer; + ptr_modelist = irc_modelist_search (ptr_channel, 'I'); + + if (ptr_modelist) + { + /* start receiving new list */ + if (ptr_modelist->state != IRC_MODELIST_STATE_RECEIVING) + { + irc_modelist_item_free_all (ptr_modelist); + ptr_modelist->state = IRC_MODELIST_STATE_RECEIVING; + } + + sprintf (str_number, "%s[%s%d%s] ", + IRC_COLOR_CHAT_DELIMITERS, + IRC_COLOR_RESET, + ((ptr_modelist->last_item) ? ptr_modelist->last_item->number + 1 : 0) + 1, + IRC_COLOR_CHAT_DELIMITERS); + } + else + str_number[0] = '\0'; + if (argc >= 6) { nick_address = irc_protocol_nick_address ( @@ -4050,18 +4082,21 @@ IRC_PROTOCOL_CALLBACK(346) if (argc >= 7) { datetime = (time_t)(atol (argv[6])); + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[4], argv[5], datetime); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "invitelist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), /* TRANSLATORS: "%s" after "on" is a date */ - _("%s%s[%s%s%s] %s%s%s invited by %s on %s"), + _("%s%s[%s%s%s] %s%s%s%s invited by %s on %s"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_CHAT_HOST, argv[4], IRC_COLOR_RESET, @@ -4070,17 +4105,20 @@ IRC_PROTOCOL_CALLBACK(346) } else { + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[4], argv[5], 0); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "invitelist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), - _("%s%s[%s%s%s] %s%s%s invited by %s"), + _("%s%s[%s%s%s] %s%s%s%s invited by %s"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_CHAT_HOST, argv[4], IRC_COLOR_RESET, @@ -4089,17 +4127,20 @@ IRC_PROTOCOL_CALLBACK(346) } else { + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[4], NULL, 0); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "invitelist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), - _("%s%s[%s%s%s] %s%s%s invited"), + _("%s%s[%s%s%s] %s%s%s%s invited"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_CHAT_HOST, argv[4], IRC_COLOR_RESET); @@ -4120,6 +4161,7 @@ IRC_PROTOCOL_CALLBACK(347) char *pos_args; struct t_irc_channel *ptr_channel; struct t_gui_buffer *ptr_buffer; + struct t_irc_modelist *ptr_modelist; IRC_PROTOCOL_MIN_ARGS(4); @@ -4129,6 +4171,19 @@ IRC_PROTOCOL_CALLBACK(347) ptr_channel = irc_channel_search (server, argv[3]); ptr_buffer = (ptr_channel && ptr_channel->nicks) ? ptr_channel->buffer : server->buffer; + ptr_modelist = irc_modelist_search (ptr_channel, 'I'); + if (ptr_modelist) + { + if (ptr_modelist->state != IRC_MODELIST_STATE_RECEIVING) + { + /* + * remove all items if no invite was received before + * the end of invite list + */ + irc_modelist_item_free_all (ptr_modelist); + } + ptr_modelist->state = IRC_MODELIST_STATE_RECEIVED; + } weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "invitelist", ptr_buffer), @@ -4159,14 +4214,36 @@ IRC_PROTOCOL_CALLBACK(348) { struct t_irc_channel *ptr_channel; struct t_gui_buffer *ptr_buffer; + struct t_irc_modelist *ptr_modelist; time_t datetime; const char *nick_address; + char str_number[64]; IRC_PROTOCOL_MIN_ARGS(5); ptr_channel = irc_channel_search (server, argv[3]); ptr_buffer = (ptr_channel && ptr_channel->nicks) ? ptr_channel->buffer : server->buffer; + ptr_modelist = irc_modelist_search (ptr_channel, 'e'); + + if (ptr_modelist) + { + /* start receiving new list */ + if (ptr_modelist->state != IRC_MODELIST_STATE_RECEIVING) + { + irc_modelist_item_free_all (ptr_modelist); + ptr_modelist->state = IRC_MODELIST_STATE_RECEIVING; + } + + sprintf (str_number, " %s[%s%d%s]", + IRC_COLOR_CHAT_DELIMITERS, + IRC_COLOR_RESET, + ((ptr_modelist->last_item) ? ptr_modelist->last_item->number + 1 : 0) + 1, + IRC_COLOR_CHAT_DELIMITERS); + } + else + str_number[0] = '\0'; + if (argc >= 6) { nick_address = irc_protocol_nick_address ( @@ -4175,18 +4252,21 @@ IRC_PROTOCOL_CALLBACK(348) if (argc >= 7) { datetime = (time_t)(atol (argv[6])); + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[4], argv[5], datetime); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "exceptionlist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), /* TRANSLATORS: "%s" after "on" is a date */ - _("%s%s[%s%s%s]%s exception %s%s%s by %s on %s"), + _("%s%s[%s%s%s]%s%s exception %s%s%s by %s on %s"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_RESET, IRC_COLOR_CHAT_HOST, argv[4], @@ -4196,17 +4276,20 @@ IRC_PROTOCOL_CALLBACK(348) } else { + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[4], argv[5], 0); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "exceptionlist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), - _("%s%s[%s%s%s]%s exception %s%s%s by %s"), + _("%s%s[%s%s%s]%s%s exception %s%s%s by %s"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_RESET, IRC_COLOR_CHAT_HOST, argv[4], @@ -4216,17 +4299,20 @@ IRC_PROTOCOL_CALLBACK(348) } else { + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[4], NULL, 0); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "exceptionlist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), - _("%s%s[%s%s%s]%s exception %s%s"), + _("%s%s[%s%s%s]%s%s exception %s%s"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_RESET, IRC_COLOR_CHAT_HOST, argv[4]); @@ -4247,6 +4333,7 @@ IRC_PROTOCOL_CALLBACK(349) char *pos_args; struct t_irc_channel *ptr_channel; struct t_gui_buffer *ptr_buffer; + struct t_irc_modelist *ptr_modelist; IRC_PROTOCOL_MIN_ARGS(4); @@ -4256,6 +4343,19 @@ IRC_PROTOCOL_CALLBACK(349) ptr_channel = irc_channel_search (server, argv[3]); ptr_buffer = (ptr_channel && ptr_channel->nicks) ? ptr_channel->buffer : server->buffer; + ptr_modelist = irc_modelist_search (ptr_channel, 'e'); + if (ptr_modelist) + { + if (ptr_modelist->state != IRC_MODELIST_STATE_RECEIVING) + { + /* + * remove all items if no exception was received before + * the end of exception list + */ + irc_modelist_item_free_all (ptr_modelist); + } + ptr_modelist->state = IRC_MODELIST_STATE_RECEIVED; + } weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "exceptionlist", ptr_buffer), @@ -4612,22 +4712,8 @@ IRC_PROTOCOL_CALLBACK(354) /* update away flag in nick */ if (ptr_channel && ptr_nick) { - if (pos_attr - && (weechat_hashtable_has_key (server->cap_list, "away-notify") - || ((IRC_SERVER_OPTION_INTEGER( - server, IRC_SERVER_OPTION_AWAY_CHECK) > 0) - && ((IRC_SERVER_OPTION_INTEGER( - server, IRC_SERVER_OPTION_AWAY_CHECK_MAX_NICKS) == 0) - || (ptr_channel->nicks_count <= IRC_SERVER_OPTION_INTEGER( - server, IRC_SERVER_OPTION_AWAY_CHECK_MAX_NICKS)))))) - { - irc_nick_set_away (server, ptr_channel, ptr_nick, - (pos_attr[0] == 'G') ? 1 : 0); - } - else - { - irc_nick_set_away (server, ptr_channel, ptr_nick, 0); - } + irc_nick_set_away (server, ptr_channel, ptr_nick, + (pos_attr && (pos_attr[0] == 'G')) ? 1 : 0); } /* update account flag in nick */ @@ -4659,7 +4745,7 @@ IRC_PROTOCOL_CALLBACK(354) date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), "%s%s[%s%s%s] %s%s %s%s%s%s%s%s(%s%s@%s%s)%s %s%s%s%s(%s)", - weechat_prefix("network"), + weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], @@ -4918,14 +5004,35 @@ IRC_PROTOCOL_CALLBACK(367) { struct t_irc_channel *ptr_channel; struct t_gui_buffer *ptr_buffer; + struct t_irc_modelist *ptr_modelist; time_t datetime; const char *nick_address; + char str_number[64]; IRC_PROTOCOL_MIN_ARGS(5); ptr_channel = irc_channel_search (server, argv[3]); ptr_buffer = (ptr_channel && ptr_channel->nicks) ? ptr_channel->buffer : server->buffer; + ptr_modelist = irc_modelist_search (ptr_channel, 'b'); + + if (ptr_modelist) + { + /* start receiving new list */ + if (ptr_modelist->state != IRC_MODELIST_STATE_RECEIVING) + { + irc_modelist_item_free_all (ptr_modelist); + ptr_modelist->state = IRC_MODELIST_STATE_RECEIVING; + } + + sprintf (str_number, "%s[%s%d%s] ", + IRC_COLOR_CHAT_DELIMITERS, + IRC_COLOR_RESET, + ((ptr_modelist->last_item) ? ptr_modelist->last_item->number + 1 : 0) + 1, + IRC_COLOR_CHAT_DELIMITERS); + } + else + str_number[0] = '\0'; if (argc >= 6) { @@ -4935,18 +5042,21 @@ IRC_PROTOCOL_CALLBACK(367) if (argc >= 7) { datetime = (time_t)(atol (argv[6])); + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[4], argv[5], datetime); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "banlist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), /* TRANSLATORS: "%s" after "on" is a date */ - _("%s%s[%s%s%s] %s%s%s banned by %s on %s"), + _("%s%s[%s%s%s] %s%s%s%s banned by %s on %s"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_CHAT_HOST, argv[4], IRC_COLOR_RESET, @@ -4955,17 +5065,20 @@ IRC_PROTOCOL_CALLBACK(367) } else { + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[4], argv[5], 0); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "banlist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), - _("%s%s[%s%s%s] %s%s%s banned by %s"), + _("%s%s[%s%s%s] %s%s%s%s banned by %s"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_CHAT_HOST, argv[4], IRC_COLOR_RESET, @@ -4974,17 +5087,20 @@ IRC_PROTOCOL_CALLBACK(367) } else { + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[4], NULL, 0); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "banlist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), - _("%s%s[%s%s%s] %s%s%s banned"), + _("%s%s[%s%s%s] %s%s%s%s banned"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_CHAT_HOST, argv[4], IRC_COLOR_RESET); @@ -5005,6 +5121,7 @@ IRC_PROTOCOL_CALLBACK(368) char *pos_args; struct t_irc_channel *ptr_channel; struct t_gui_buffer *ptr_buffer; + struct t_irc_modelist *ptr_modelist; IRC_PROTOCOL_MIN_ARGS(4); @@ -5014,6 +5131,19 @@ IRC_PROTOCOL_CALLBACK(368) ptr_channel = irc_channel_search (server, argv[3]); ptr_buffer = (ptr_channel && ptr_channel->nicks) ? ptr_channel->buffer : server->buffer; + ptr_modelist = irc_modelist_search (ptr_channel, 'b'); + if (ptr_modelist) + { + if (ptr_modelist->state != IRC_MODELIST_STATE_RECEIVING) + { + /* + * remove all items if no ban was received before + * the end of ban list + */ + irc_modelist_item_free_all (ptr_modelist); + } + ptr_modelist->state = IRC_MODELIST_STATE_RECEIVED; + } weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "banlist", ptr_buffer), @@ -5345,14 +5475,35 @@ IRC_PROTOCOL_CALLBACK(728) { struct t_irc_channel *ptr_channel; struct t_gui_buffer *ptr_buffer; + struct t_irc_modelist *ptr_modelist; time_t datetime; const char *nick_address; + char str_number[64]; IRC_PROTOCOL_MIN_ARGS(6); ptr_channel = irc_channel_search (server, argv[3]); ptr_buffer = (ptr_channel && ptr_channel->nicks) ? ptr_channel->buffer : server->buffer; + ptr_modelist = irc_modelist_search (ptr_channel, argv[4][0]); + + if (ptr_modelist) + { + /* start receiving new list */ + if (ptr_modelist->state != IRC_MODELIST_STATE_RECEIVING) + { + irc_modelist_item_free_all (ptr_modelist); + ptr_modelist->state = IRC_MODELIST_STATE_RECEIVING; + } + + sprintf (str_number, "%s[%s%d%s] ", + IRC_COLOR_CHAT_DELIMITERS, + IRC_COLOR_RESET, + ((ptr_modelist->last_item) ? ptr_modelist->last_item->number + 1 : 0) + 1, + IRC_COLOR_CHAT_DELIMITERS); + } + else + str_number[0] = '\0'; if (argc >= 7) { @@ -5362,18 +5513,21 @@ IRC_PROTOCOL_CALLBACK(728) if (argc >= 8) { datetime = (time_t)(atol (argv[7])); + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[5], argv[6], datetime); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "quietlist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), /* TRANSLATORS: "%s" after "on" is a date */ - _("%s%s[%s%s%s] %s%s%s quieted by %s on %s"), + _("%s%s[%s%s%s] %s%s%s%s quieted by %s on %s"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_CHAT_HOST, argv[5], IRC_COLOR_RESET, @@ -5382,17 +5536,20 @@ IRC_PROTOCOL_CALLBACK(728) } else { + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[5], argv[6], 0); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "quietlist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), - _("%s%s[%s%s%s] %s%s%s quieted by %s"), + _("%s%s[%s%s%s] %s%s%s%s quieted by %s"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_CHAT_HOST, argv[5], IRC_COLOR_RESET, @@ -5401,17 +5558,20 @@ IRC_PROTOCOL_CALLBACK(728) } else { + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[5], NULL, 0); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "quietlist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), - _("%s%s[%s%s%s] %s%s%s quieted"), + _("%s%s[%s%s%s] %s%s%s%s quieted"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_CHAT_HOST, argv[5], IRC_COLOR_RESET); @@ -5432,6 +5592,7 @@ IRC_PROTOCOL_CALLBACK(729) char *pos_args; struct t_irc_channel *ptr_channel; struct t_gui_buffer *ptr_buffer; + struct t_irc_modelist *ptr_modelist; IRC_PROTOCOL_MIN_ARGS(5); @@ -5441,6 +5602,19 @@ IRC_PROTOCOL_CALLBACK(729) ptr_channel = irc_channel_search (server, argv[3]); ptr_buffer = (ptr_channel && ptr_channel->nicks) ? ptr_channel->buffer : server->buffer; + ptr_modelist = irc_modelist_search (ptr_channel, argv[4][0]); + if (ptr_modelist) + { + if (ptr_modelist->state != IRC_MODELIST_STATE_RECEIVING) + { + /* + * remove all items if no quiet was received before + * the end of quiet list + */ + irc_modelist_item_free_all (ptr_modelist); + } + ptr_modelist->state = IRC_MODELIST_STATE_RECEIVED; + } weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "quietlist", ptr_buffer), @@ -5843,16 +6017,15 @@ irc_protocol_get_message_tag_time (struct t_hashtable *tags) void irc_protocol_recv_command (struct t_irc_server *server, const char *irc_message, - const char *msg_tags, const char *msg_command, const char *msg_channel) { int i, cmd_found, return_code, argc, decode_color, keep_trailing_spaces; int message_ignored; - char *dup_irc_message, *pos_space; + char *message_colors_decoded, *pos_space, *tags; struct t_irc_channel *ptr_channel; t_irc_recv_func *cmd_recv_func; - const char *cmd_name; + const char *cmd_name, *ptr_msg_after_tags; time_t date; const char *nick1, *address1, *host1; char *nick, *address, *address_color, *host, *host_no_color, *host_color; @@ -6014,29 +6187,48 @@ irc_protocol_recv_command (struct t_irc_server *server, if (!msg_command) return; - dup_irc_message = NULL; + message_colors_decoded = NULL; argv = NULL; argv_eol = NULL; hash_tags = NULL; date = 0; + ptr_msg_after_tags = irc_message; + /* get tags as hashtable */ - if (msg_tags) + if (irc_message && (irc_message[0] == '@')) { - hash_tags = irc_protocol_get_message_tags (msg_tags); - if (hash_tags) - date = irc_protocol_get_message_tag_time (hash_tags); + pos_space = strchr (irc_message, ' '); + if (pos_space) + { + tags = weechat_strndup (irc_message + 1, + pos_space - (irc_message + 1)); + if (tags) + { + hash_tags = irc_protocol_get_message_tags (tags); + if (hash_tags) + date = irc_protocol_get_message_tag_time (hash_tags); + free (tags); + } + ptr_msg_after_tags = pos_space; + while (ptr_msg_after_tags[0] == ' ') + { + ptr_msg_after_tags++; + } + } + else + ptr_msg_after_tags = NULL; } /* get nick/host/address from IRC message */ nick1 = NULL; address1 = NULL; host1 = NULL; - if (irc_message && (irc_message[0] == ':')) + if (ptr_msg_after_tags && (ptr_msg_after_tags[0] == ':')) { - nick1 = irc_message_get_nick_from_host (irc_message); - address1 = irc_message_get_address_from_host (irc_message); - host1 = irc_message + 1; + nick1 = irc_message_get_nick_from_host (ptr_msg_after_tags); + address1 = irc_message_get_address_from_host (ptr_msg_after_tags); + host1 = ptr_msg_after_tags + 1; } nick = (nick1) ? strdup (nick1) : NULL; address = (address1) ? strdup (address1) : NULL; @@ -6124,23 +6316,23 @@ irc_protocol_recv_command (struct t_irc_server *server, if (cmd_recv_func != NULL) { - if (irc_message) + if (ptr_msg_after_tags) { if (decode_color) { - dup_irc_message = irc_color_decode ( - irc_message, + message_colors_decoded = irc_color_decode ( + ptr_msg_after_tags, weechat_config_boolean (irc_config_network_colors_receive)); } else { - dup_irc_message = strdup (irc_message); + message_colors_decoded = strdup (ptr_msg_after_tags); } } else - dup_irc_message = NULL; - argv = weechat_string_split (dup_irc_message, " ", 0, 0, &argc); - argv_eol = weechat_string_split (dup_irc_message, " ", + message_colors_decoded = NULL; + argv = weechat_string_split (message_colors_decoded, " ", 0, 0, &argc); + argv_eol = weechat_string_split (message_colors_decoded, " ", 1 + keep_trailing_spaces, 0, NULL); return_code = (int) (cmd_recv_func) (server, @@ -6186,8 +6378,8 @@ end: free (host_no_color); if (host_color) free (host_color); - if (dup_irc_message) - free (dup_irc_message); + if (message_colors_decoded) + free (message_colors_decoded); if (argv) weechat_string_free_split (argv); if (argv_eol) diff --git a/src/plugins/irc/irc-protocol.h b/src/plugins/irc/irc-protocol.h index a890fd866..e45b6977b 100644 --- a/src/plugins/irc/irc-protocol.h +++ b/src/plugins/irc/irc-protocol.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_PROTOCOL_H -#define WEECHAT_IRC_PROTOCOL_H 1 +#ifndef WEECHAT_PLUGIN_IRC_PROTOCOL_H +#define WEECHAT_PLUGIN_IRC_PROTOCOL_H #include <time.h> @@ -87,8 +87,7 @@ extern const char *irc_protocol_tags (const char *command, const char *tags, const char *nick, const char *address); extern void irc_protocol_recv_command (struct t_irc_server *server, const char *irc_message, - const char *msg_tags, const char *msg_command, const char *msg_channel); -#endif /* WEECHAT_IRC_PROTOCOL_H */ +#endif /* WEECHAT_PLUGIN_IRC_PROTOCOL_H */ diff --git a/src/plugins/irc/irc-raw.c b/src/plugins/irc/irc-raw.c index d669aed10..ace1de3d8 100644 --- a/src/plugins/irc/irc-raw.c +++ b/src/plugins/irc/irc-raw.c @@ -1,7 +1,7 @@ /* * irc-raw.c - functions for IRC raw data messages * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/irc/irc-raw.h b/src/plugins/irc/irc-raw.h index d0601a10c..3ac0b04ad 100644 --- a/src/plugins/irc/irc-raw.h +++ b/src/plugins/irc/irc-raw.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_RAW_H -#define WEECHAT_IRC_RAW_H 1 +#ifndef WEECHAT_PLUGIN_IRC_RAW_H +#define WEECHAT_PLUGIN_IRC_RAW_H #include <time.h> @@ -61,4 +61,4 @@ extern void irc_raw_message_free_all (); extern int irc_raw_add_to_infolist (struct t_infolist *infolist, struct t_irc_raw_message *raw_message); -#endif /* WEECHAT_IRC_RAW_H */ +#endif /* WEECHAT_PLUGIN_IRC_RAW_H */ diff --git a/src/plugins/irc/irc-redirect.c b/src/plugins/irc/irc-redirect.c index 44648a00d..64fc30ac6 100644 --- a/src/plugins/irc/irc-redirect.c +++ b/src/plugins/irc/irc-redirect.c @@ -1,7 +1,7 @@ /* * irc-redirect.c - redirection of IRC command output * - * Copyright (C) 2010-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2010-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -686,7 +686,7 @@ irc_redirect_message_add (struct t_irc_redirect *redirect, const char *message, /* add message to output */ if (redirect->output) { - redirect->output_size += strlen("\n") + strlen (message); + redirect->output_size += strlen ("\n") + strlen (message); output2 = realloc (redirect->output, redirect->output_size); if (!output2) { @@ -1209,7 +1209,7 @@ irc_redirect_print_log (struct t_irc_server *server) weechat_log_printf (" timeout . . . . . . : %d", ptr_redirect->timeout); weechat_log_printf (" command . . . . . . : '%s'", ptr_redirect->command); weechat_log_printf (" assigned_to_command : %d", ptr_redirect->assigned_to_command); - weechat_log_printf (" start_time. . . . . : %ld", ptr_redirect->start_time); + weechat_log_printf (" start_time. . . . . : %lld", (long long)ptr_redirect->start_time); weechat_log_printf (" cmd_start . . . . . : 0x%lx (hashtable: '%s')", ptr_redirect->cmd_start, weechat_hashtable_get_string (ptr_redirect->cmd_start, "keys_values")); diff --git a/src/plugins/irc/irc-redirect.h b/src/plugins/irc/irc-redirect.h index 3d3e09f9e..f94e6ad07 100644 --- a/src/plugins/irc/irc-redirect.h +++ b/src/plugins/irc/irc-redirect.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2010-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_REDIRECT_H -#define WEECHAT_IRC_REDIRECT_H 1 +#ifndef WEECHAT_PLUGIN_IRC_REDIRECT_H +#define WEECHAT_PLUGIN_IRC_REDIRECT_H #include <time.h> @@ -132,4 +132,4 @@ extern int irc_redirect_command_hsignal_cb (const void *pointer, void *data, extern void irc_redirect_init (); extern void irc_redirect_end (); -#endif /* WEECHAT_IRC_REDIRECT_H */ +#endif /* WEECHAT_PLUGIN_IRC_REDIRECT_H */ diff --git a/src/plugins/irc/irc-sasl.c b/src/plugins/irc/irc-sasl.c index f397a656a..689e7ecb8 100644 --- a/src/plugins/irc/irc-sasl.c +++ b/src/plugins/irc/irc-sasl.c @@ -1,7 +1,7 @@ /* * irc-sasl.c - SASL authentication with IRC server * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -493,7 +493,7 @@ irc_sasl_mechanism_dh_blowfish (const char *data_base64, length_answer = 2 + length_key + length_username + length_password; answer = malloc (length_answer); ptr_answer = answer; - *((unsigned int *)ptr_answer) = htons(length_key); + *((unsigned int *)ptr_answer) = htons (length_key); ptr_answer += 2; memcpy (ptr_answer, public_bin, length_key); ptr_answer += length_key; @@ -554,7 +554,7 @@ irc_sasl_mechanism_dh_aes (const char *data_base64, secret_bin = NULL; public_bin = NULL; - if (irc_sasl_dh(data_base64, &public_bin, &secret_bin, &length_key) == 0) + if (irc_sasl_dh (data_base64, &public_bin, &secret_bin, &length_key) == 0) goto aesend; /* Select cipher algorithm: key length * 8 = cipher bit size */ @@ -596,7 +596,7 @@ irc_sasl_mechanism_dh_aes (const char *data_base64, goto aesend; if (gcry_cipher_setkey (gcrypt_handle, secret_bin, length_key) != 0) goto aesend; - if (gcry_cipher_setiv (gcrypt_handle, iv, sizeof(iv)) != 0) + if (gcry_cipher_setiv (gcrypt_handle, iv, sizeof (iv)) != 0) goto aesend; if (gcry_cipher_encrypt (gcrypt_handle, userpass_crypted, length_userpass, @@ -615,7 +615,7 @@ irc_sasl_mechanism_dh_aes (const char *data_base64, length_answer = 2 + length_key + sizeof (iv) + length_userpass; answer = malloc (length_answer); ptr_answer = answer; - *((unsigned int *)ptr_answer) = htons(length_key); + *((unsigned int *)ptr_answer) = htons (length_key); ptr_answer += 2; memcpy (ptr_answer, public_bin, length_key); ptr_answer += length_key; diff --git a/src/plugins/irc/irc-sasl.h b/src/plugins/irc/irc-sasl.h index 5c2eb1604..38a930fa6 100644 --- a/src/plugins/irc/irc-sasl.h +++ b/src/plugins/irc/irc-sasl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_SASL_H -#define WEECHAT_IRC_SASL_H 1 +#ifndef WEECHAT_PLUGIN_IRC_SASL_H +#define WEECHAT_PLUGIN_IRC_SASL_H struct t_irc_server; @@ -50,4 +50,4 @@ extern char *irc_sasl_mechanism_dh_aes (const char *data_base64, const char *sasl_username, const char *sasl_password); -#endif /* WEECHAT_IRC_SASL_H */ +#endif /* WEECHAT_PLUGIN_IRC_SASL_H */ diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c index dd785c29a..2e43afab5 100644 --- a/src/plugins/irc/irc-server.c +++ b/src/plugins/irc/irc-server.c @@ -1,7 +1,7 @@ /* * irc-server.c - I/O communication with IRC servers * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2010 Emmanuel Bouthenot <kolter@openics.org> * Copyright (C) 2012 Simon Arlott * @@ -29,6 +29,7 @@ #include <stdio.h> #include <stdarg.h> #include <string.h> +#include <ctype.h> #include <time.h> #ifdef _WIN32 #include <winsock.h> @@ -117,6 +118,7 @@ char *irc_server_options[IRC_SERVER_NUM_OPTIONS][2] = { "msg_part", "WeeChat ${info:version}" }, { "msg_quit", "WeeChat ${info:version}" }, { "notify", "" }, + { "split_msg_max_length", "512" }, }; char *irc_server_casemapping_string[IRC_SERVER_NUM_CASEMAPPING] = @@ -337,6 +339,152 @@ irc_server_strncasecmp (struct t_irc_server *server, } /* + * Evaluates a string using the server as context: + * ${irc_server.xxx} and ${server} are replaced by a server option and the + * server name. + * + * Returns the evaluated string. + * + * Note: result must be freed after use. + */ + +char * +irc_server_eval_expression (struct t_irc_server *server, const char *string) +{ + struct t_hashtable *pointers, *extra_vars; + char *value; + + pointers = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, + NULL, NULL); + extra_vars = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + + if (server) + { + if (pointers) + weechat_hashtable_set (pointers, "irc_server", server); + if (extra_vars) + weechat_hashtable_set (extra_vars, "server", server->name); + } + + value = weechat_string_eval_expression (string, + pointers, extra_vars, NULL); + + if (pointers) + weechat_hashtable_free (pointers); + if (extra_vars) + weechat_hashtable_free (extra_vars); + + return value; +} + +/* + * Evaluates and returns the fingerprint. + * + * Returns the evaluated fingerprint, NULL if the fingerprint option is + * invalid. + * + * Note: result must be freed after use. + */ + +char * +irc_server_eval_fingerprint (struct t_irc_server *server) +{ +#ifdef HAVE_GNUTLS + const char *ptr_fingerprint; + char *fingerprint_eval, **fingerprints, *str_sizes; + int i, j, rc, algo, length; + + ptr_fingerprint = IRC_SERVER_OPTION_STRING(server, + IRC_SERVER_OPTION_SSL_FINGERPRINT); + + /* empty fingerprint is just ignored (considered OK) */ + if (!ptr_fingerprint || !ptr_fingerprint[0]) + return strdup (""); + + /* evaluate fingerprint */ + fingerprint_eval = irc_server_eval_expression (server, ptr_fingerprint); + if (!fingerprint_eval || !fingerprint_eval[0]) + { + weechat_printf ( + server->buffer, + _("%s%s: the evaluated fingerprint for server \"%s\" must not be " + "empty"), + weechat_prefix ("error"), + IRC_PLUGIN_NAME, + server->name); + if (fingerprint_eval) + free (fingerprint_eval); + return NULL; + } + + /* split fingerprint */ + fingerprints = weechat_string_split (fingerprint_eval, ",", 0, 0, NULL); + if (!fingerprints) + return fingerprint_eval; + + rc = 0; + for (i = 0; fingerprints[i]; i++) + { + length = strlen (fingerprints[i]); + algo = irc_server_fingerprint_search_algo_with_size (length * 4); + if (algo < 0) + { + rc = -1; + break; + } + for (j = 0; j < length; j++) + { + if (!isxdigit ((unsigned char)fingerprints[i][j])) + { + rc = -2; + break; + } + } + if (rc < 0) + break; + } + weechat_string_free_split (fingerprints); + switch (rc) + { + case -1: /* invalid size */ + str_sizes = irc_server_fingerprint_str_sizes (); + weechat_printf ( + server->buffer, + _("%s%s: invalid fingerprint size for server \"%s\", the " + "number of hexadecimal digits must be " + "one of: %s"), + weechat_prefix ("error"), + IRC_PLUGIN_NAME, + server->name, + (str_sizes) ? str_sizes : "?"); + if (str_sizes) + free (str_sizes); + free (fingerprint_eval); + return NULL; + case -2: /* invalid content */ + weechat_printf ( + server->buffer, + _("%s%s: invalid fingerprint for server \"%s\", it must " + "contain only hexadecimal digits (0-9, " + "a-f)"), + weechat_prefix ("error"), IRC_PLUGIN_NAME, server->name); + free (fingerprint_eval); + return NULL; + } + return fingerprint_eval; +#else + return strdup (""); +#endif /* HAVE_GNUTLS */ +} + +/* * Checks if SASL is enabled on server. * * Returns: @@ -353,12 +501,12 @@ irc_server_sasl_enabled (struct t_irc_server *server) sasl_mechanism = IRC_SERVER_OPTION_INTEGER( server, IRC_SERVER_OPTION_SASL_MECHANISM); - sasl_username = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_USERNAME), - NULL, NULL, NULL); - sasl_password = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_PASSWORD), - NULL, NULL, NULL); + sasl_username = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_USERNAME)); + sasl_password = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_PASSWORD)); sasl_key = IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_KEY); /* @@ -422,8 +570,7 @@ irc_server_set_addresses (struct t_irc_server *server, const char *addresses) if (addresses && addresses[0]) { - addresses_eval = weechat_string_eval_expression (addresses, - NULL, NULL, NULL); + addresses_eval = irc_server_eval_expression (server, addresses); if (server->addresses_eval && (strcmp (server->addresses_eval, addresses_eval) == 0)) { @@ -550,7 +697,7 @@ irc_server_set_nicks (struct t_irc_server *server, const char *nicks) } /* evaluate value */ - nicks2 = weechat_string_eval_expression (nicks, NULL, NULL, NULL); + nicks2 = irc_server_eval_expression (server, nicks); /* set new nicks */ server->nicks_array = weechat_string_split ( @@ -2498,7 +2645,10 @@ irc_server_sendf (struct t_irc_server *server, int flags, const char *tags, (new_msg) ? new_msg : items[i], NULL); - /* split message if needed (max is 512 bytes including final "\r\n") */ + /* + * split message if needed (max is 512 bytes by default, + * including the final "\r\n") + */ hashtable = irc_message_split (server, (new_msg) ? new_msg : items[i]); if (hashtable) @@ -2707,8 +2857,8 @@ void irc_server_msgq_flush () { struct t_irc_message *next; - char *ptr_data, *new_msg, *new_msg2, *ptr_msg, *ptr_msg2, *ptr_msg3, *pos; - char *tags, *nick, *host, *command, *channel, *arguments; + char *ptr_data, *new_msg, *new_msg2, *ptr_msg, *ptr_msg2, *pos; + char *nick, *host, *command, *channel, *arguments; char *msg_decoded, *msg_decoded_without_color; char str_modifier[128], modifier_data[256]; int pos_channel, pos_text, pos_decode; @@ -2773,7 +2923,7 @@ irc_server_msgq_flush () } irc_message_parse (irc_recv_msgq->server, ptr_msg, - &tags, NULL, &nick, &host, + NULL, NULL, &nick, &host, &command, &channel, &arguments, NULL, NULL, NULL, &pos_channel, &pos_text); @@ -2860,25 +3010,9 @@ irc_server_msgq_flush () else { /* message not redirected, display it */ - ptr_msg3 = ptr_msg2; - if (ptr_msg3[0] == '@') - { - /* skip tags in message */ - ptr_msg3 = strchr (ptr_msg3, ' '); - if (ptr_msg3) - { - while (ptr_msg3[0] == ' ') - { - ptr_msg3++; - } - } - else - ptr_msg3 = ptr_msg2; - } irc_protocol_recv_command ( irc_recv_msgq->server, - ptr_msg3, - tags, + ptr_msg2, command, channel); } @@ -3508,15 +3642,15 @@ irc_server_login (struct t_irc_server *server) const char *capabilities; char *password, *username, *realname, *username2; - password = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_PASSWORD), - NULL, NULL, NULL); - username = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME), - NULL, NULL, NULL); - realname = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME), - NULL, NULL, NULL); + password = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_PASSWORD)); + username = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME)); + realname = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME)); capabilities = IRC_SERVER_OPTION_STRING( server, IRC_SERVER_OPTION_CAPABILITIES); @@ -4235,8 +4369,12 @@ irc_server_gnutls_callback (const void *pointer, void *data, /* get fingerprint option in server */ ptr_fingerprint = IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SSL_FINGERPRINT); - fingerprint_eval = weechat_string_eval_expression (ptr_fingerprint, - NULL, NULL, NULL); + fingerprint_eval = irc_server_eval_fingerprint (server); + if (!fingerprint_eval) + { + rc = -1; + goto end; + } /* set match options */ fingerprint_match = (ptr_fingerprint && ptr_fingerprint[0]) ? 0 : 1; @@ -4969,9 +5107,9 @@ irc_server_autojoin_create_buffers (struct t_irc_server *server) return; /* evaluate server option "autojoin" */ - autojoin = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN), - NULL, NULL, NULL); + autojoin = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN)); /* extract channel names from autojoin option */ if (autojoin && autojoin[0]) @@ -5042,9 +5180,9 @@ irc_server_autojoin_channels (struct t_irc_server *server) else { /* auto-join when connecting to server for first time */ - autojoin = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN), - NULL, NULL, NULL); + autojoin = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN)); if (!server->disable_autojoin && autojoin && autojoin[0]) irc_command_join_server (server, autojoin, 0, 0); if (autojoin) @@ -6079,26 +6217,26 @@ irc_server_print_log () weechat_log_printf (" chantypes. . . . . . : '%s'", ptr_server->chantypes); weechat_log_printf (" chanmodes. . . . . . : '%s'", ptr_server->chanmodes); weechat_log_printf (" monitor. . . . . . . : %d", ptr_server->monitor); - weechat_log_printf (" monitor_time . . . . : %ld", ptr_server->monitor_time); + weechat_log_printf (" monitor_time . . . . : %lld", (long long)ptr_server->monitor_time); weechat_log_printf (" reconnect_delay. . . : %d", ptr_server->reconnect_delay); - weechat_log_printf (" reconnect_start. . . : %ld", ptr_server->reconnect_start); - weechat_log_printf (" command_time . . . . : %ld", ptr_server->command_time); + weechat_log_printf (" reconnect_start. . . : %lld", (long long)ptr_server->reconnect_start); + weechat_log_printf (" command_time . . . . : %lld", (long long)ptr_server->command_time); weechat_log_printf (" reconnect_join . . . : %d", ptr_server->reconnect_join); weechat_log_printf (" disable_autojoin . . : %d", ptr_server->disable_autojoin); weechat_log_printf (" is_away. . . . . . . : %d", ptr_server->is_away); weechat_log_printf (" away_message . . . . : '%s'", ptr_server->away_message); - weechat_log_printf (" away_time. . . . . . : %ld", ptr_server->away_time); + weechat_log_printf (" away_time. . . . . . : %lld", (long long)ptr_server->away_time); weechat_log_printf (" lag. . . . . . . . . : %d", ptr_server->lag); weechat_log_printf (" lag_displayed. . . . : %d", ptr_server->lag_displayed); weechat_log_printf (" lag_check_time . . . : tv_sec:%d, tv_usec:%d", ptr_server->lag_check_time.tv_sec, ptr_server->lag_check_time.tv_usec); - weechat_log_printf (" lag_next_check . . . : %ld", ptr_server->lag_next_check); - weechat_log_printf (" lag_last_refresh . . : %ld", ptr_server->lag_last_refresh); + weechat_log_printf (" lag_next_check . . . : %lld", (long long)ptr_server->lag_next_check); + weechat_log_printf (" lag_last_refresh . . : %lld", (long long)ptr_server->lag_last_refresh); weechat_log_printf (" cmd_list_regexp. . . : 0x%lx", ptr_server->cmd_list_regexp); - weechat_log_printf (" last_user_message. . : %ld", ptr_server->last_user_message); - weechat_log_printf (" last_away_check. . . : %ld", ptr_server->last_away_check); - weechat_log_printf (" last_data_purge. . . : %ld", ptr_server->last_data_purge); + weechat_log_printf (" last_user_message. . : %lld", (long long)ptr_server->last_user_message); + weechat_log_printf (" last_away_check. . . : %lld", (long long)ptr_server->last_away_check); + weechat_log_printf (" last_data_purge. . . : %lld", (long long)ptr_server->last_data_purge); for (i = 0; i < IRC_SERVER_NUM_OUTQUEUES_PRIO; i++) { weechat_log_printf (" outqueue[%02d] . . . . : 0x%lx", i, ptr_server->outqueue[i]); diff --git a/src/plugins/irc/irc-server.h b/src/plugins/irc/irc-server.h index 74987e675..401f627bb 100644 --- a/src/plugins/irc/irc-server.h +++ b/src/plugins/irc/irc-server.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2012 Simon Arlott * * This file is part of WeeChat, the extensible chat client. @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_SERVER_H -#define WEECHAT_IRC_SERVER_H 1 +#ifndef WEECHAT_PLUGIN_IRC_SERVER_H +#define WEECHAT_PLUGIN_IRC_SERVER_H #include <time.h> #include <sys/time.h> @@ -84,6 +84,7 @@ enum t_irc_server_option IRC_SERVER_OPTION_MSG_PART, /* default part message */ IRC_SERVER_OPTION_MSG_QUIT, /* default quit message */ IRC_SERVER_OPTION_NOTIFY, /* notify list */ + IRC_SERVER_OPTION_SPLIT_MSG_MAX_LENGTH, /* max length of messages */ /* number of server options */ IRC_SERVER_NUM_OPTIONS, }; @@ -283,6 +284,8 @@ extern int irc_server_strcasecmp (struct t_irc_server *server, extern int irc_server_strncasecmp (struct t_irc_server *server, const char *string1, const char *string2, int max); +extern char *irc_server_eval_expression (struct t_irc_server *server, + const char *string); extern int irc_server_sasl_enabled (struct t_irc_server *server); extern char *irc_server_get_name_without_port (const char *name); extern int irc_server_set_addresses (struct t_irc_server *server, @@ -381,4 +384,4 @@ extern int irc_server_add_to_infolist (struct t_infolist *infolist, struct t_irc_server *server); extern void irc_server_print_log (); -#endif /* WEECHAT_IRC_SERVER_H */ +#endif /* WEECHAT_PLUGIN_IRC_SERVER_H */ diff --git a/src/plugins/irc/irc-upgrade.c b/src/plugins/irc/irc-upgrade.c index 098132514..107981609 100644 --- a/src/plugins/irc/irc-upgrade.c +++ b/src/plugins/irc/irc-upgrade.c @@ -1,7 +1,7 @@ /* * irc-upgrade.c - save/restore IRC plugin data when upgrading WeeChat * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -30,6 +30,7 @@ #include "irc-channel.h" #include "irc-config.h" #include "irc-input.h" +#include "irc-modelist.h" #include "irc-nick.h" #include "irc-notify.h" #include "irc-raw.h" @@ -39,6 +40,7 @@ struct t_irc_server *irc_upgrade_current_server = NULL; struct t_irc_channel *irc_upgrade_current_channel = NULL; +struct t_irc_modelist *irc_upgrade_current_modelist = NULL; /* @@ -59,6 +61,8 @@ irc_upgrade_save_all_data (struct t_upgrade_file *upgrade_file) struct t_irc_redirect *ptr_redirect; struct t_irc_redirect_pattern *ptr_redirect_pattern; struct t_irc_notify *ptr_notify; + struct t_irc_modelist *ptr_modelist; + struct t_irc_modelist_item *ptr_item; struct t_irc_raw_message *ptr_raw_message; int rc; @@ -120,6 +124,46 @@ irc_upgrade_save_all_data (struct t_upgrade_file *upgrade_file) if (!rc) return 0; } + + for (ptr_modelist = ptr_channel->modelists; ptr_modelist; + ptr_modelist = ptr_modelist->next_modelist) + { + /* save modelist */ + infolist = weechat_infolist_new (); + if (!infolist) + return 0; + if (!irc_modelist_add_to_infolist (infolist, ptr_modelist)) + { + weechat_infolist_free (infolist); + return 0; + } + rc = weechat_upgrade_write_object (upgrade_file, + IRC_UPGRADE_TYPE_MODELIST, + infolist); + weechat_infolist_free (infolist); + if (!rc) + return 0; + + for (ptr_item = ptr_modelist->items; ptr_item; + ptr_item = ptr_item->next_item) + { + /* save modelist item */ + infolist = weechat_infolist_new (); + if (!infolist) + return 0; + if (!irc_modelist_item_add_to_infolist (infolist, ptr_item)) + { + weechat_infolist_free (infolist); + return 0; + } + rc = weechat_upgrade_write_object (upgrade_file, + IRC_UPGRADE_TYPE_MODELIST_ITEM, + infolist); + weechat_infolist_free (infolist); + if (!rc) + return 0; + } + } } /* save server redirects */ @@ -304,6 +348,7 @@ irc_upgrade_read_cb (const void *pointer, void *data, struct t_irc_nick *ptr_nick; struct t_irc_redirect *ptr_redirect; struct t_irc_notify *ptr_notify; + struct t_irc_modelist_item *ptr_item; struct t_gui_buffer *ptr_buffer; /* make C compiler happy */ @@ -675,6 +720,33 @@ irc_upgrade_read_cb (const void *pointer, void *data, } } break; + case IRC_UPGRADE_TYPE_MODELIST: + if (irc_upgrade_current_server && irc_upgrade_current_channel) + { + /* modelists are already created by the channel */ + irc_upgrade_current_modelist = irc_modelist_search ( + irc_upgrade_current_channel, + weechat_infolist_string (infolist, "type")[0]); + if (irc_upgrade_current_modelist) + { + irc_upgrade_current_modelist->state = weechat_infolist_integer (infolist, "state"); + } + } + break; + case IRC_UPGRADE_TYPE_MODELIST_ITEM: + if (irc_upgrade_current_server && irc_upgrade_current_channel && irc_upgrade_current_modelist) + { + ptr_item = irc_modelist_item_new ( + irc_upgrade_current_modelist, + weechat_infolist_string (infolist, "mask"), + weechat_infolist_string (infolist, "setter"), + weechat_infolist_time (infolist, "datetime")); + if (ptr_item) + { + ptr_item->number = weechat_infolist_integer (infolist, "number"); + } + } + break; case IRC_UPGRADE_TYPE_REDIRECT: if (irc_upgrade_current_server) { diff --git a/src/plugins/irc/irc-upgrade.h b/src/plugins/irc/irc-upgrade.h index 5b8c32729..fa2a0734c 100644 --- a/src/plugins/irc/irc-upgrade.h +++ b/src/plugins/irc/irc-upgrade.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_UPGRADE_H -#define WEECHAT_IRC_UPGRADE_H 1 +#ifndef WEECHAT_PLUGIN_IRC_UPGRADE_H +#define WEECHAT_PLUGIN_IRC_UPGRADE_H #define IRC_UPGRADE_FILENAME "irc" @@ -33,9 +33,11 @@ enum t_irc_upgrade_type IRC_UPGRADE_TYPE_REDIRECT_PATTERN, IRC_UPGRADE_TYPE_REDIRECT, IRC_UPGRADE_TYPE_NOTIFY, + IRC_UPGRADE_TYPE_MODELIST, + IRC_UPGRADE_TYPE_MODELIST_ITEM, }; extern int irc_upgrade_save (); extern int irc_upgrade_load (); -#endif /* WEECHAT_IRC_UPGRADE_H */ +#endif /* WEECHAT_PLUGIN_IRC_UPGRADE_H */ diff --git a/src/plugins/irc/irc.c b/src/plugins/irc/irc.c index 8a1531575..3163e74b0 100644 --- a/src/plugins/irc/irc.c +++ b/src/plugins/irc/irc.c @@ -1,7 +1,7 @@ /* * irc.c - IRC (Internet Relay Chat) plugin for WeeChat * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -50,7 +50,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("IRC (Internet Relay Chat) protocol")); WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(5000); +WEECHAT_PLUGIN_PRIORITY(6000); struct t_weechat_plugin *weechat_irc_plugin = NULL; diff --git a/src/plugins/irc/irc.h b/src/plugins/irc/irc.h index 63befef64..2d22aa583 100644 --- a/src/plugins/irc/irc.h +++ b/src/plugins/irc/irc.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_H -#define WEECHAT_IRC_H 1 +#ifndef WEECHAT_PLUGIN_IRC_H +#define WEECHAT_PLUGIN_IRC_H #define weechat_plugin weechat_irc_plugin #define IRC_PLUGIN_NAME "irc" @@ -28,4 +28,4 @@ extern struct t_weechat_plugin *weechat_irc_plugin; extern int irc_signal_upgrade_received; -#endif /* WEECHAT_IRC_H */ +#endif /* WEECHAT_PLUGIN_IRC_H */ diff --git a/src/plugins/javascript/CMakeLists.txt b/src/plugins/javascript/CMakeLists.txt index b0b654a52..6b368d4a6 100644 --- a/src/plugins/javascript/CMakeLists.txt +++ b/src/plugins/javascript/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2015-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2015-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/javascript/Makefile.am b/src/plugins/javascript/Makefile.am index 996dd2881..8da6d1874 100644 --- a/src/plugins/javascript/Makefile.am +++ b/src/plugins/javascript/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2015-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2015-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/javascript/weechat-js-api.cpp b/src/plugins/javascript/weechat-js-api.cpp index ee3cfdbbf..de00752e4 100644 --- a/src/plugins/javascript/weechat-js-api.cpp +++ b/src/plugins/javascript/weechat-js-api.cpp @@ -2,7 +2,7 @@ * weechat-js-api.cpp - javascript API functions * * Copyright (C) 2013 Koka El Kiwi <kokakiwi@kokakiwi.net> - * Copyright (C) 2015-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2015-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -74,6 +74,7 @@ extern "C" { \ if (((js_args[num] == 's') && (!args[num]->IsString())) \ || ((js_args[num] == 'i') && (!args[num]->IsInt32())) \ + || ((js_args[num] == 'n') && (!args[num]->IsNumber())) \ || ((js_args[num] == 'h') && (!args[num]->IsObject()))) \ { \ WEECHAT_SCRIPT_MSG_WRONG_ARGS(JS_CURRENT_SCRIPT_NAME, \ @@ -94,7 +95,8 @@ extern "C" plugin_script_str2ptr (weechat_js_plugin, \ JS_CURRENT_SCRIPT_NAME, \ js_function_name.c_str(), __string) - +#define API_STATIC_STRING(__string) \ + plugin_script_get_static_string(&js_data, __string); #define API_RETURN_OK return v8::True(); #define API_RETURN_ERROR return v8::False(); #define API_RETURN_EMPTY \ @@ -160,7 +162,7 @@ API_FUNC(register) /* register script */ js_current_script = plugin_script_add (weechat_js_plugin, - &js_scripts, &last_js_script, + &js_data, (js_current_script_filename) ? js_current_script_filename : "", *name, *author, *version, @@ -344,6 +346,20 @@ API_FUNC(string_mask_to_regex) API_RETURN_STRING_FREE(result); } +API_FUNC(string_format_size) +{ + unsigned long long size; + char *result; + + API_INIT_FUNC(1, "string_format_size", "n", API_RETURN_EMPTY); + + size = args[0]->IntegerValue(); + + result = weechat_string_format_size (size); + + API_RETURN_STRING_FREE(result); +} + API_FUNC(string_remove_color) { char *result; @@ -505,18 +521,18 @@ API_FUNC(mkdir_parents) API_FUNC(list_new) { - char *result; + const char *result; API_INIT_FUNC(1, "list_new", "", API_RETURN_EMPTY); result = API_PTR2STR(weechat_list_new ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_add) { - char *result; + const char *result; API_INIT_FUNC(1, "list_add", "ssss", API_RETURN_EMPTY); @@ -531,12 +547,12 @@ API_FUNC(list_add) *where, API_STR2PTR(*user_data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_search) { - char *result; + const char *result; API_INIT_FUNC(1, "list_search", "ss", API_RETURN_EMPTY); @@ -547,7 +563,7 @@ API_FUNC(list_search) weechat_list_search ( (struct t_weelist *)API_STR2PTR(*weelist), *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_search_pos) @@ -567,7 +583,7 @@ API_FUNC(list_search_pos) API_FUNC(list_casesearch) { - char *result; + const char *result; API_INIT_FUNC(1, "list_casesearch", "ss", API_RETURN_EMPTY); @@ -578,7 +594,7 @@ API_FUNC(list_casesearch) weechat_list_casesearch ( (struct t_weelist *)API_STR2PTR(*weelist), *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_casesearch_pos) @@ -599,7 +615,7 @@ API_FUNC(list_casesearch_pos) API_FUNC(list_get) { int position; - char *result; + const char *result; API_INIT_FUNC(1, "list_get", "si", API_RETURN_EMPTY); @@ -610,7 +626,7 @@ API_FUNC(list_get) weechat_list_get ((struct t_weelist *)API_STR2PTR(*weelist), position)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_set) @@ -627,7 +643,7 @@ API_FUNC(list_set) API_FUNC(list_next) { - char *result; + const char *result; API_INIT_FUNC(1, "list_next", "s", API_RETURN_EMPTY); @@ -636,12 +652,12 @@ API_FUNC(list_next) result = API_PTR2STR( weechat_list_next ((struct t_weelist_item *)API_STR2PTR(*item))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_prev) { - char *result; + const char *result; API_INIT_FUNC(1, "list_prev", "s", API_RETURN_EMPTY); @@ -650,7 +666,7 @@ API_FUNC(list_prev) result = API_PTR2STR( weechat_list_prev ((struct t_weelist_item *)API_STR2PTR(*item))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_string) @@ -733,7 +749,7 @@ weechat_js_api_config_reload_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); rc = (int *)weechat_js_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -747,8 +763,6 @@ weechat_js_api_config_reload_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -758,7 +772,7 @@ weechat_js_api_config_reload_cb (const void *pointer, void *data, API_FUNC(config_new) { - char *result; + const char *result; API_INIT_FUNC(1, "config_new", "sss", API_RETURN_EMPTY); @@ -774,7 +788,7 @@ API_FUNC(config_new) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -795,8 +809,8 @@ weechat_js_api_config_read_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); func_argv[3] = (option_name) ? (char *)option_name : empty_arg; func_argv[4] = (value) ? (char *)value : empty_arg; @@ -812,10 +826,6 @@ weechat_js_api_config_read_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); return ret; } @@ -840,7 +850,7 @@ weechat_js_api_config_section_write_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); func_argv[2] = (section_name) ? (char *)section_name : empty_arg; rc = (int *)weechat_js_exec (script, @@ -855,8 +865,6 @@ weechat_js_api_config_section_write_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -881,7 +889,7 @@ weechat_js_api_config_section_write_default_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); func_argv[2] = (section_name) ? (char *)section_name : empty_arg; rc = (int *)weechat_js_exec (script, @@ -896,8 +904,6 @@ weechat_js_api_config_section_write_default_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -924,8 +930,8 @@ weechat_js_api_config_section_create_option_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); func_argv[3] = (option_name) ? (char *)option_name : empty_arg; func_argv[4] = (value) ? (char *)value : empty_arg; @@ -941,10 +947,6 @@ weechat_js_api_config_section_create_option_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); return ret; } @@ -970,9 +972,9 @@ weechat_js_api_config_section_delete_option_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); - func_argv[3] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); + func_argv[3] = (char *)API_PTR2STR(option); rc = (int *)weechat_js_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -986,12 +988,6 @@ weechat_js_api_config_section_delete_option_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -1002,7 +998,7 @@ weechat_js_api_config_section_delete_option_cb (const void *pointer, void *data, API_FUNC(config_new_section) { int user_can_add_options, user_can_delete_options; - char *result; + const char *result; API_INIT_FUNC(1, "config_new_section", "ssiissssssssss", API_RETURN_EMPTY); @@ -1045,12 +1041,12 @@ API_FUNC(config_new_section) *function_delete_option, *data_delete_option)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_search_section) { - char *result; + const char *result; API_INIT_FUNC(1, "config_search_section", "ss", API_RETURN_EMPTY); @@ -1062,7 +1058,7 @@ API_FUNC(config_search_section) (struct t_config_file *) API_STR2PTR(*config_file), *section_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -1082,7 +1078,7 @@ weechat_js_api_config_option_check_value_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); func_argv[2] = (value) ? (char *)value : empty_arg; rc = (int *)weechat_js_exec (script, @@ -1097,8 +1093,6 @@ weechat_js_api_config_option_check_value_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -1122,16 +1116,13 @@ weechat_js_api_config_option_change_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); rc = (int *)weechat_js_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, "ss", func_argv); - if (func_argv[1]) - free (func_argv[1]); - if (rc) free (rc); } @@ -1153,16 +1144,13 @@ weechat_js_api_config_option_delete_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); rc = (int *)weechat_js_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, "ss", func_argv); - if (func_argv[1]) - free (func_argv[1]); - if (rc) free (rc); } @@ -1171,7 +1159,7 @@ weechat_js_api_config_option_delete_cb (const void *pointer, void *data, API_FUNC(config_new_option) { int min, max, null_value_allowed; - char *result; + const char *result; API_INIT_FUNC(1, "config_new_option", "ssssssiississssss", API_RETURN_EMPTY); @@ -1218,12 +1206,12 @@ API_FUNC(config_new_option) *function_delete, *data_delete)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_search_option) { - char *result; + const char *result; API_INIT_FUNC(1, "config_search_option", "sss", API_RETURN_EMPTY); @@ -1237,7 +1225,7 @@ API_FUNC(config_search_option) (struct t_config_section *)API_STR2PTR(*section), *option_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_string_to_boolean) @@ -1588,7 +1576,7 @@ API_FUNC(config_free) API_FUNC(config_get) { - char *result; + const char *result; API_INIT_FUNC(1, "config_get", "s", API_RETURN_EMPTY); @@ -1596,7 +1584,7 @@ API_FUNC(config_get) result = API_PTR2STR(weechat_config_get (*option)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_get_plugin) @@ -1828,7 +1816,7 @@ weechat_js_api_hook_command_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (argc > 1) ? argv_eol[1] : empty_arg; rc = (int *)weechat_js_exec (script, @@ -1843,8 +1831,6 @@ weechat_js_api_hook_command_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -1854,7 +1840,7 @@ weechat_js_api_hook_command_cb (const void *pointer, void *data, API_FUNC(hook_command) { - char *result; + const char *result; API_INIT_FUNC(1, "hook_command", "sssssss", API_RETURN_EMPTY); @@ -1878,7 +1864,7 @@ API_FUNC(hook_command) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -1900,8 +1886,8 @@ weechat_js_api_hook_completion_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (completion_item) ? (char *)completion_item : empty_arg; - func_argv[2] = API_PTR2STR(buffer); - func_argv[3] = API_PTR2STR(completion); + func_argv[2] = (char *)API_PTR2STR(buffer); + func_argv[3] = (char *)API_PTR2STR(completion); rc = (int *)weechat_js_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -1915,10 +1901,6 @@ weechat_js_api_hook_completion_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -1928,7 +1910,7 @@ weechat_js_api_hook_completion_cb (const void *pointer, void *data, API_FUNC(hook_completion) { - char *result; + const char *result; API_INIT_FUNC(1, "hook_completion", "ssss", API_RETURN_EMPTY); @@ -1947,7 +1929,7 @@ API_FUNC(hook_completion) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_completion_get_string) @@ -2003,7 +1985,7 @@ weechat_js_api_hook_command_run_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (command) ? (char *)command : empty_arg; rc = (int *)weechat_js_exec (script, @@ -2018,8 +2000,6 @@ weechat_js_api_hook_command_run_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -2029,7 +2009,7 @@ weechat_js_api_hook_command_run_cb (const void *pointer, void *data, API_FUNC(hook_command_run) { - char *result; + const char *result; API_INIT_FUNC(1, "hook_command_run", "sss", API_RETURN_EMPTY); @@ -2046,7 +2026,7 @@ API_FUNC(hook_command_run) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2092,7 +2072,7 @@ weechat_js_api_hook_timer_cb (const void *pointer, void *data, API_FUNC(hook_timer) { int interval, align_second, max_calls; - char *result; + const char *result; API_INIT_FUNC(1, "hook_timer", "iiiss", API_RETURN_EMPTY); @@ -2113,7 +2093,7 @@ API_FUNC(hook_timer) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2121,7 +2101,7 @@ weechat_js_api_hook_fd_cb (const void *pointer, void *data, int fd) { struct t_plugin_script *script; void *func_argv[2]; - char str_fd[32], empty_arg[1] = { '\0' }; + char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; int *rc, ret; @@ -2130,15 +2110,13 @@ weechat_js_api_hook_fd_cb (const void *pointer, void *data, int fd) if (ptr_function && ptr_function[0]) { - snprintf (str_fd, sizeof (str_fd), "%d", fd); - func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = str_fd; + func_argv[1] = &fd; rc = (int *)weechat_js_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "ss", func_argv); + "si", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2157,7 +2135,7 @@ weechat_js_api_hook_fd_cb (const void *pointer, void *data, int fd) API_FUNC(hook_fd) { int fd, read, write, exception; - char *result; + const char *result; API_INIT_FUNC(1, "hook_fd", "iiiiss", API_RETURN_EMPTY); @@ -2180,7 +2158,7 @@ API_FUNC(hook_fd) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2246,7 +2224,7 @@ weechat_js_api_hook_process_cb (const void *pointer, void *data, API_FUNC(hook_process) { int timeout; - char *result; + const char *result; API_INIT_FUNC(1, "hook_process", "siss", API_RETURN_EMPTY); @@ -2265,14 +2243,14 @@ API_FUNC(hook_process) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_process_hashtable) { struct t_hashtable *options; int timeout; - char *result; + const char *result; API_INIT_FUNC(1, "hook_process_hashtable", "shiss", API_RETURN_EMPTY); @@ -2300,7 +2278,7 @@ API_FUNC(hook_process_hashtable) if (options) weechat_hashtable_free (options); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2311,7 +2289,6 @@ weechat_js_api_hook_connect_cb (const void *pointer, void *data, { struct t_plugin_script *script; void *func_argv[6]; - char str_status[32], str_gnutls_rc[32], str_sock[32]; char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; int *rc, ret; @@ -2321,21 +2298,17 @@ weechat_js_api_hook_connect_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { - snprintf (str_status, sizeof (str_status), "%d", status); - snprintf (str_gnutls_rc, sizeof (str_gnutls_rc), "%d", gnutls_rc); - snprintf (str_sock, sizeof (str_sock), "%d", sock); - func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = str_status; - func_argv[2] = str_gnutls_rc; - func_argv[3] = str_sock; + func_argv[1] = &status; + func_argv[2] = &gnutls_rc; + func_argv[3] = &sock; func_argv[4] = (ip_address) ? (char *)ip_address : empty_arg; func_argv[5] = (error) ? (char *)error : empty_arg; rc = (int *)weechat_js_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "ssssss", func_argv); + "siiiss", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2354,7 +2327,7 @@ weechat_js_api_hook_connect_cb (const void *pointer, void *data, API_FUNC(hook_connect) { int port, ipv6, retry; - char *result; + const char *result; API_INIT_FUNC(1, "hook_connect", "ssiiisss", API_RETURN_EMPTY); @@ -2385,7 +2358,7 @@ API_FUNC(hook_connect) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2414,7 +2387,7 @@ weechat_js_api_hook_print_cb (const void *pointer, void *data, snprintf (timebuffer, sizeof (timebuffer), "%ld", (long int)date); func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = timebuffer; func_argv[3] = weechat_string_build_with_split_string (tags, ","); if (!func_argv[3]) @@ -2436,8 +2409,6 @@ weechat_js_api_hook_print_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); if (func_argv[3]) free (func_argv[3]); @@ -2450,7 +2421,7 @@ weechat_js_api_hook_print_cb (const void *pointer, void *data, API_FUNC(hook_print) { int strip_colors; - char *result; + const char *result; API_INIT_FUNC(1, "hook_print", "sssiss", API_RETURN_EMPTY); @@ -2473,7 +2444,7 @@ API_FUNC(hook_print) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2486,7 +2457,7 @@ weechat_js_api_hook_signal_cb (const void *pointer, void *data, char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; static char str_value[64]; - int *rc, ret, free_needed; + int *rc, ret; script = (struct t_plugin_script *)pointer; plugin_script_get_function_and_data (data, &ptr_function, &ptr_data); @@ -2495,7 +2466,6 @@ weechat_js_api_hook_signal_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (signal) ? (char *)signal : empty_arg; - free_needed = 0; if (strcmp (type_data, WEECHAT_HOOK_SIGNAL_STRING) == 0) { func_argv[2] = (signal_data) ? (char *)signal_data : empty_arg; @@ -2512,8 +2482,7 @@ weechat_js_api_hook_signal_cb (const void *pointer, void *data, } else if (strcmp (type_data, WEECHAT_HOOK_SIGNAL_POINTER) == 0) { - func_argv[2] = API_PTR2STR(signal_data); - free_needed = 1; + func_argv[2] = (char *)API_PTR2STR(signal_data); } else func_argv[2] = empty_arg; @@ -2530,8 +2499,6 @@ weechat_js_api_hook_signal_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (free_needed && func_argv[2]) - free (func_argv[2]); return ret; } @@ -2541,7 +2508,7 @@ weechat_js_api_hook_signal_cb (const void *pointer, void *data, API_FUNC(hook_signal) { - char *result; + const char *result; API_INIT_FUNC(1, "hook_signal", "sss", API_RETURN_EMPTY); @@ -2558,7 +2525,7 @@ API_FUNC(hook_signal) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_signal_send) @@ -2638,7 +2605,7 @@ weechat_js_api_hook_hsignal_cb (const void *pointer, void *data, API_FUNC(hook_hsignal) { - char *result; + const char *result; API_INIT_FUNC(1, "hook_hsignal", "sss", API_RETURN_EMPTY); @@ -2655,7 +2622,7 @@ API_FUNC(hook_hsignal) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_hsignal_send) @@ -2720,7 +2687,7 @@ weechat_js_api_hook_config_cb (const void *pointer, void *data, API_FUNC(hook_config) { - char *result; + const char *result; API_INIT_FUNC(1, "hook_config", "sss", API_RETURN_EMPTY); @@ -2737,7 +2704,7 @@ API_FUNC(hook_config) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } char * @@ -2771,7 +2738,7 @@ weechat_js_api_hook_modifier_cb (const void *pointer, void *data, API_FUNC(hook_modifier) { - char *result; + const char *result; API_INIT_FUNC(1, "hook_modifier", "sss", API_RETURN_EMPTY); @@ -2788,7 +2755,7 @@ API_FUNC(hook_modifier) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_modifier_exec) @@ -2813,7 +2780,7 @@ weechat_js_api_hook_info_cb (const void *pointer, void *data, { struct t_plugin_script *script; void *func_argv[3]; - char empty_arg[1] = { '\0' }; + char empty_arg[1] = { '\0' }, *result; const char *ptr_function, *ptr_data; script = (struct t_plugin_script *)pointer; @@ -2825,10 +2792,12 @@ weechat_js_api_hook_info_cb (const void *pointer, void *data, func_argv[1] = (info_name) ? (char *)info_name : empty_arg; func_argv[2] = (arguments) ? (char *)arguments : empty_arg; - return (const char *)weechat_js_exec (script, - WEECHAT_SCRIPT_EXEC_STRING, - ptr_function, - "sss", func_argv); + result = (char *)weechat_js_exec (script, + WEECHAT_SCRIPT_EXEC_STRING, + ptr_function, + "sss", func_argv); + + return API_STATIC_STRING(result); } return NULL; @@ -2836,7 +2805,7 @@ weechat_js_api_hook_info_cb (const void *pointer, void *data, API_FUNC(hook_info) { - char *result; + const char *result; API_INIT_FUNC(1, "hook_info", "sssss", API_RETURN_EMPTY); @@ -2857,7 +2826,7 @@ API_FUNC(hook_info) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_hashtable * @@ -2894,7 +2863,7 @@ weechat_js_api_hook_info_hashtable_cb (const void *pointer, void *data, API_FUNC(hook_info_hashtable) { - char *result; + const char *result; API_INIT_FUNC(1, "hook_info_hashtable", "ssssss", API_RETURN_EMPTY); @@ -2917,7 +2886,7 @@ API_FUNC(hook_info_hashtable) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_infolist * @@ -2938,18 +2907,15 @@ weechat_js_api_hook_infolist_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (infolist_name) ? (char *)infolist_name : empty_arg; - func_argv[2] = API_PTR2STR(obj_pointer); + func_argv[2] = (char *)API_PTR2STR(obj_pointer); func_argv[3] = (arguments) ? (char *)arguments : empty_arg; result = (struct t_infolist *)weechat_js_exec ( script, - WEECHAT_SCRIPT_EXEC_STRING, + WEECHAT_SCRIPT_EXEC_POINTER, ptr_function, "ssss", func_argv); - if (func_argv[2]) - free (func_argv[2]); - return result; } @@ -2958,7 +2924,7 @@ weechat_js_api_hook_infolist_cb (const void *pointer, void *data, API_FUNC(hook_infolist) { - char *result; + const char *result; API_INIT_FUNC(1, "hook_infolist", "ssssss", API_RETURN_EMPTY); @@ -2981,7 +2947,7 @@ API_FUNC(hook_infolist) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_hashtable * @@ -3016,7 +2982,7 @@ weechat_js_api_hook_focus_cb (const void *pointer, void *data, API_FUNC(hook_focus) { - char *result; + const char *result; API_INIT_FUNC(1, "hook_focus", "sss", API_RETURN_EMPTY); @@ -3033,7 +2999,7 @@ API_FUNC(hook_focus) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_set) @@ -3088,7 +3054,7 @@ weechat_js_api_buffer_input_data_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (input_data) ? (char *)input_data : empty_arg; rc = (int *)weechat_js_exec (script, @@ -3104,9 +3070,6 @@ weechat_js_api_buffer_input_data_cb (const void *pointer, void *data, free (rc); } - if (func_argv[1]) - free (func_argv[1]); - return ret; } @@ -3129,7 +3092,7 @@ weechat_js_api_buffer_close_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); rc = (int *)weechat_js_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -3144,9 +3107,6 @@ weechat_js_api_buffer_close_cb (const void *pointer, void *data, free (rc); } - if (func_argv[1]) - free (func_argv[1]); - return ret; } @@ -3155,7 +3115,7 @@ weechat_js_api_buffer_close_cb (const void *pointer, void *data, API_FUNC(buffer_new) { - char *result; + const char *result; API_INIT_FUNC(1, "buffer_new", "sssss", API_RETURN_EMPTY); @@ -3177,12 +3137,12 @@ API_FUNC(buffer_new) *function_close, *data_close)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_search) { - char *result; + const char *result; API_INIT_FUNC(1, "buffer_search", "ss", API_RETURN_EMPTY); @@ -3191,29 +3151,29 @@ API_FUNC(buffer_search) result = API_PTR2STR(weechat_buffer_search (*plugin, *name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_search_main) { - char *result; + const char *result; API_INIT_FUNC(1, "buffer_search_main", "", API_RETURN_EMPTY); result = API_PTR2STR(weechat_buffer_search_main ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(current_buffer) { - char *result; + const char *result; API_INIT_FUNC(1, "current_buffer", "", API_RETURN_EMPTY); result = API_PTR2STR(weechat_current_buffer ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_clear) @@ -3300,7 +3260,7 @@ API_FUNC(buffer_get_string) API_FUNC(buffer_get_pointer) { - char *result; + const char *result; API_INIT_FUNC(1, "buffer_get_pointer", "ss", API_RETURN_EMPTY); @@ -3312,7 +3272,7 @@ API_FUNC(buffer_get_pointer) (struct t_gui_buffer *)API_STR2PTR(*buffer), *property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_set) @@ -3365,18 +3325,18 @@ API_FUNC(buffer_match_list) API_FUNC(current_window) { - char *result; + const char *result; API_INIT_FUNC(1, "current_window", "", API_RETURN_EMPTY); result = API_PTR2STR(weechat_current_window ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(window_search_with_buffer) { - char *result; + const char *result; API_INIT_FUNC(1, "window_search_with_buffer", "s", API_RETURN_EMPTY); @@ -3386,7 +3346,7 @@ API_FUNC(window_search_with_buffer) weechat_window_search_with_buffer ( (struct t_gui_buffer *)API_STR2PTR(*buffer))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(window_get_integer) @@ -3423,7 +3383,7 @@ API_FUNC(window_get_string) API_FUNC(window_get_pointer) { - char *result; + const char *result; API_INIT_FUNC(1, "window_get_pointer", "ss", API_RETURN_EMPTY); @@ -3435,7 +3395,7 @@ API_FUNC(window_get_pointer) (struct t_gui_window *)API_STR2PTR(*window), *property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(window_set_title) @@ -3452,7 +3412,7 @@ API_FUNC(window_set_title) API_FUNC(nicklist_add_group) { int visible; - char *result; + const char *result; API_INIT_FUNC(1, "nicklist_add_group", "ssssi", API_RETURN_EMPTY); @@ -3470,12 +3430,12 @@ API_FUNC(nicklist_add_group) *color, visible)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_search_group) { - char *result; + const char *result; API_INIT_FUNC(1, "nicklist_search_group", "sss", API_RETURN_EMPTY); @@ -3489,13 +3449,13 @@ API_FUNC(nicklist_search_group) (struct t_gui_nick_group *)API_STR2PTR(*from_group), *name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_add_nick) { int visible; - char *result; + const char *result; API_INIT_FUNC(1, "nicklist_add_nick", "ssssssi", API_RETURN_EMPTY); @@ -3517,12 +3477,12 @@ API_FUNC(nicklist_add_nick) *prefix_color, visible)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_search_nick) { - char *result; + const char *result; API_INIT_FUNC(1, "nicklist_search_nick", "sss", API_RETURN_EMPTY); @@ -3536,7 +3496,7 @@ API_FUNC(nicklist_search_nick) (struct t_gui_nick_group *)API_STR2PTR(*from_group), *name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_remove_group) @@ -3616,7 +3576,7 @@ API_FUNC(nicklist_group_get_string) API_FUNC(nicklist_group_get_pointer) { - char *result; + const char *result; API_INIT_FUNC(1, "nicklist_group_get_pointer", "sss", API_RETURN_EMPTY); @@ -3630,7 +3590,7 @@ API_FUNC(nicklist_group_get_pointer) (struct t_gui_nick_group *)API_STR2PTR(*group), *property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_group_set) @@ -3689,7 +3649,7 @@ API_FUNC(nicklist_nick_get_string) API_FUNC(nicklist_nick_get_pointer) { - char *result; + const char *result; API_INIT_FUNC(1, "nicklist_nick_get_pointer", "sss", API_RETURN_EMPTY); @@ -3703,7 +3663,7 @@ API_FUNC(nicklist_nick_get_pointer) (struct t_gui_nick *)API_STR2PTR(*nick), *property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_nick_set) @@ -3726,7 +3686,7 @@ API_FUNC(nicklist_nick_set) API_FUNC(bar_item_search) { - char *result; + const char *result; API_INIT_FUNC(1, "bar_item_search", "s", API_RETURN_EMPTY); @@ -3734,7 +3694,7 @@ API_FUNC(bar_item_search) result = API_PTR2STR(weechat_bar_item_search (*name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } char * @@ -3758,39 +3718,27 @@ weechat_js_api_bar_item_build_cb (const void *pointer, void *data, { /* new callback: data, item, window, buffer, extra_info */ func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(item); - func_argv[2] = API_PTR2STR(window); - func_argv[3] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(item); + func_argv[2] = (char *)API_PTR2STR(window); + func_argv[3] = (char *)API_PTR2STR(buffer); func_argv[4] = extra_info; ret = (char *)weechat_js_exec (script, WEECHAT_SCRIPT_EXEC_STRING, ptr_function + 7, "ssssh", func_argv); - - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); } else { /* old callback: data, item, window */ func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(item); - func_argv[2] = API_PTR2STR(window); + func_argv[1] = (char *)API_PTR2STR(item); + func_argv[2] = (char *)API_PTR2STR(window); ret = (char *)weechat_js_exec (script, WEECHAT_SCRIPT_EXEC_STRING, ptr_function, "sss", func_argv); - - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); } return ret; @@ -3801,7 +3749,7 @@ weechat_js_api_bar_item_build_cb (const void *pointer, void *data, API_FUNC(bar_item_new) { - char *result; + const char *result; API_INIT_FUNC(1, "bar_item_new", "sss", API_RETURN_EMPTY); @@ -3818,7 +3766,7 @@ API_FUNC(bar_item_new) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(bar_item_update) @@ -3845,7 +3793,7 @@ API_FUNC(bar_item_remove) API_FUNC(bar_search) { - char *result; + const char *result; API_INIT_FUNC(1, "bar_search", "s", API_RETURN_EMPTY); @@ -3853,12 +3801,12 @@ API_FUNC(bar_search) result = API_PTR2STR(weechat_bar_search (*name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(bar_new) { - char *result; + const char *result; API_INIT_FUNC(1, "bar_new", "sssssssssssssss", API_RETURN_EMPTY); @@ -3894,7 +3842,7 @@ API_FUNC(bar_new) *separator, *items)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(bar_set) @@ -3996,18 +3944,18 @@ API_FUNC(info_get_hashtable) API_FUNC(infolist_new) { - char *result; + const char *result; API_INIT_FUNC(1, "infolist_new", "", API_RETURN_EMPTY); result = API_PTR2STR(weechat_infolist_new ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_item) { - char *result; + const char *result; API_INIT_FUNC(1, "infolist_new_item", "s", API_RETURN_EMPTY); @@ -4017,13 +3965,13 @@ API_FUNC(infolist_new_item) weechat_infolist_new_item ( (struct t_infolist *)API_STR2PTR(*infolist))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_integer) { int value; - char *result; + const char *result; API_INIT_FUNC(1, "infolist_new_var_integer", "ssi", API_RETURN_EMPTY); @@ -4037,12 +3985,12 @@ API_FUNC(infolist_new_var_integer) *name, value)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_string) { - char *result; + const char *result; API_INIT_FUNC(1, "infolist_new_var_string", "sss", API_RETURN_EMPTY); @@ -4056,12 +4004,12 @@ API_FUNC(infolist_new_var_string) *name, *value)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_pointer) { - char *result; + const char *result; API_INIT_FUNC(1, "infolist_new_var_pointer", "sss", API_RETURN_EMPTY); @@ -4075,13 +4023,13 @@ API_FUNC(infolist_new_var_pointer) *name, API_STR2PTR(*value))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_time) { int value; - char *result; + const char *result; API_INIT_FUNC(1, "infolist_new_var_time", "ssi", API_RETURN_EMPTY); @@ -4095,12 +4043,12 @@ API_FUNC(infolist_new_var_time) *name, value)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_search_var) { - char *result; + const char *result; API_INIT_FUNC(1, "infolist_search_var", "ss", API_RETURN_EMPTY); @@ -4112,12 +4060,12 @@ API_FUNC(infolist_search_var) (struct t_infolist *)API_STR2PTR(*infolist), *name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_get) { - char *result; + const char *result; API_INIT_FUNC(1, "infolist_get", "sss", API_RETURN_EMPTY); @@ -4131,7 +4079,7 @@ API_FUNC(infolist_get) API_STR2PTR(*pointer), *arguments)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_next) @@ -4234,16 +4182,14 @@ API_FUNC(infolist_pointer) (struct t_infolist *)API_STR2PTR(*infolist), *variable)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_time) { - char timebuffer[64], *result; time_t time; - struct tm *date_tmp; - API_INIT_FUNC(1, "infolist_time", "ss", API_RETURN_EMPTY); + API_INIT_FUNC(1, "infolist_time", "ss", API_RETURN_LONG(0)); v8::String::Utf8Value infolist(args[0]); v8::String::Utf8Value variable(args[1]); @@ -4251,12 +4197,8 @@ API_FUNC(infolist_time) time = weechat_infolist_time ( (struct t_infolist *)API_STR2PTR(*infolist), *variable); - date_tmp = localtime (&time); - if (date_tmp) - strftime (timebuffer, sizeof (timebuffer), "%F %T", date_tmp); - result = strdup (timebuffer); - API_RETURN_STRING_FREE(result); + API_RETURN_LONG(time); } API_FUNC(infolist_free) @@ -4272,7 +4214,7 @@ API_FUNC(infolist_free) API_FUNC(hdata_get) { - char *result; + const char *result; API_INIT_FUNC(1, "hdata_get", "s", API_RETURN_EMPTY); @@ -4280,7 +4222,7 @@ API_FUNC(hdata_get) result = API_PTR2STR(weechat_hdata_get (*name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_get_var_offset) @@ -4369,7 +4311,7 @@ API_FUNC(hdata_get_var_hdata) API_FUNC(hdata_get_list) { - char *result; + const char *result; API_INIT_FUNC(1, "hdata_get_list", "s", API_RETURN_EMPTY); @@ -4381,7 +4323,7 @@ API_FUNC(hdata_get_list) (struct t_hdata *)API_STR2PTR(*hdata), *name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_check_pointer) @@ -4405,7 +4347,7 @@ API_FUNC(hdata_check_pointer) API_FUNC(hdata_move) { int count; - char *result; + const char *result; API_INIT_FUNC(1, "hdata_move", "ssi", API_RETURN_EMPTY); @@ -4419,13 +4361,13 @@ API_FUNC(hdata_move) API_STR2PTR(*pointer), count)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_search) { int move; - char *result; + const char *result; API_INIT_FUNC(1, "hdata_search", "sssi", API_RETURN_EMPTY); @@ -4441,7 +4383,7 @@ API_FUNC(hdata_search) *search, move)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_char) @@ -4518,7 +4460,7 @@ API_FUNC(hdata_string) API_FUNC(hdata_pointer) { - char *result; + const char *result; API_INIT_FUNC(1, "hdata_pointer", "sss", API_RETURN_EMPTY); @@ -4532,7 +4474,7 @@ API_FUNC(hdata_pointer) API_STR2PTR(*pointer), *name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_time) @@ -4656,9 +4598,9 @@ weechat_js_api_upgrade_read_cb (const void *pointer, void *data, snprintf (str_object_id, sizeof (str_object_id), "%d", object_id); func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(upgrade_file); + func_argv[1] = (char *)API_PTR2STR(upgrade_file); func_argv[2] = str_object_id; - func_argv[3] = API_PTR2STR(infolist); + func_argv[3] = (char *)API_PTR2STR(infolist); rc = (int *)weechat_js_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -4672,10 +4614,6 @@ weechat_js_api_upgrade_read_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -4685,7 +4623,7 @@ weechat_js_api_upgrade_read_cb (const void *pointer, void *data, API_FUNC(upgrade_new) { - char *result; + const char *result; API_INIT_FUNC(1, "upgrade_new", "sss", API_RETURN_EMPTY); @@ -4702,7 +4640,7 @@ API_FUNC(upgrade_new) *function, *data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(upgrade_write_object) @@ -4815,6 +4753,7 @@ WeechatJsV8::loadLibs() API_DEF_FUNC(string_has_highlight); API_DEF_FUNC(string_has_highlight_regex); API_DEF_FUNC(string_mask_to_regex); + API_DEF_FUNC(string_format_size); API_DEF_FUNC(string_remove_color); API_DEF_FUNC(string_is_command_char); API_DEF_FUNC(string_input_for_buffer); diff --git a/src/plugins/javascript/weechat-js-api.h b/src/plugins/javascript/weechat-js-api.h index e2d70690e..030c448b3 100644 --- a/src/plugins/javascript/weechat-js-api.h +++ b/src/plugins/javascript/weechat-js-api.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2013 Koka El Kiwi <kokakiwi@kokakiwi.net> - * Copyright (C) 2015-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2015-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_JS_API_H -#define WEECHAT_JS_API_H 1 +#ifndef WEECHAT_PLUGIN_JS_API_H +#define WEECHAT_PLUGIN_JS_API_H extern int weechat_js_api_buffer_input_data_cb (const void *pointer, void *data, @@ -29,4 +29,4 @@ extern int weechat_js_api_buffer_close_cb (const void *pointer, void *data, struct t_gui_buffer *buffer); -#endif /* WEECHAT_JS_API_H */ +#endif /* WEECHAT_PLUGIN_JS_API_H */ diff --git a/src/plugins/javascript/weechat-js-v8.cpp b/src/plugins/javascript/weechat-js-v8.cpp index bafa2fc8d..09da5b0d9 100644 --- a/src/plugins/javascript/weechat-js-v8.cpp +++ b/src/plugins/javascript/weechat-js-v8.cpp @@ -2,7 +2,7 @@ * weechat-js-v8.cpp - v8 javascript functions * * Copyright (C) 2013 Koka El Kiwi <kokakiwi@kokakiwi.net> - * Copyright (C) 2015-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2015-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/javascript/weechat-js-v8.h b/src/plugins/javascript/weechat-js-v8.h index cb897e105..078042548 100644 --- a/src/plugins/javascript/weechat-js-v8.h +++ b/src/plugins/javascript/weechat-js-v8.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2013 Koka El Kiwi <kokakiwi@kokakiwi.net> - * Copyright (C) 2015-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2015-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_JS_V8_H -#define WEECHAT_JS_V8_H 1 +#ifndef WEECHAT_PLUGIN_JS_V8_H +#define WEECHAT_PLUGIN_JS_V8_H #include <cstdio> #include <v8.h> @@ -27,21 +27,21 @@ class WeechatJsV8 { public: - WeechatJsV8(void); - ~WeechatJsV8(void); + WeechatJsV8 (void); + ~WeechatJsV8 (void); - bool load(v8::Handle<v8::String>); - bool load(const char *); + bool load (v8::Handle<v8::String>); + bool load (const char *); - bool execScript(void); - bool functionExists(const char *); - v8::Handle<v8::Value> execFunction(const char *, - int argc, v8::Handle<v8::Value> *); + bool execScript (void); + bool functionExists (const char *); + v8::Handle<v8::Value> execFunction (const char *, + int argc, v8::Handle<v8::Value> *); - void addGlobal(v8::Handle<v8::String>, v8::Handle<v8::Template>); - void addGlobal(const char *, v8::Handle<v8::Template>); + void addGlobal (v8::Handle<v8::String>, v8::Handle<v8::Template>); + void addGlobal (const char *, v8::Handle<v8::Template>); - void loadLibs(void); + void loadLibs (void); private: v8::HandleScope handle_scope; @@ -51,4 +51,4 @@ private: v8::Handle<v8::String> source; }; -#endif /* WEECHAT_JS_V8_H */ +#endif /* WEECHAT_PLUGIN_JS_V8_H */ diff --git a/src/plugins/javascript/weechat-js.cpp b/src/plugins/javascript/weechat-js.cpp index 930ef1ba4..4c9e244ad 100644 --- a/src/plugins/javascript/weechat-js.cpp +++ b/src/plugins/javascript/weechat-js.cpp @@ -2,7 +2,7 @@ * weechat-js.cpp - javascript plugin for WeeChat * * Copyright (C) 2013 Koka El Kiwi <kokakiwi@kokakiwi.net> - * Copyright (C) 2015-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2015-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -39,11 +39,25 @@ WEECHAT_PLUGIN_DESCRIPTION("Support of javascript scripts"); WEECHAT_PLUGIN_AUTHOR("Koka El Kiwi <kokakiwi@kokakiwi.net>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(3000); +WEECHAT_PLUGIN_PRIORITY(4000); -struct t_weechat_plugin *weechat_js_plugin; +struct t_weechat_plugin *weechat_js_plugin = NULL; + +struct t_plugin_script_data js_data; + +struct t_config_file *js_config_file = NULL; +struct t_config_option *js_config_look_check_license = NULL; +struct t_config_option *js_config_look_eval_keep_context = NULL; int js_quiet = 0; + +struct t_plugin_script *js_script_eval = NULL; +int js_eval_mode = 0; +int js_eval_send_input = 0; +int js_eval_exec_commands = 0; +struct t_gui_buffer *js_eval_buffer = NULL; +char *js_eval_output = NULL; + struct t_plugin_script *js_scripts = NULL; struct t_plugin_script *last_js_script = NULL; struct t_plugin_script *js_current_script = NULL; @@ -217,6 +231,20 @@ weechat_js_exec (struct t_plugin_script *script, v8::String::Utf8Value temp_str(ret_js); ret_value = (*temp_str) ? strdup(*temp_str) : NULL; } + else if ((ret_type == WEECHAT_SCRIPT_EXEC_POINTER) && (ret_js->IsString())) + { + v8::String::Utf8Value temp_str(ret_js); + if (*temp_str) + { + ret_value = plugin_script_str2ptr (weechat_js_plugin, + script->name, function, + *temp_str); + } + else + { + ret_value = NULL; + } + } else if ((ret_type == WEECHAT_SCRIPT_EXEC_INT) && (ret_js->IsInt32())) { ret_int = (int *)malloc (sizeof (*ret_int)); @@ -235,15 +263,18 @@ weechat_js_exec (struct t_plugin_script *script, } else { - weechat_printf (NULL, - weechat_gettext ("%s%s: function \"%s\" must " - "return a valid value"), - weechat_prefix ("error"), JS_PLUGIN_NAME, - function); + if (ret_type != WEECHAT_SCRIPT_EXEC_IGNORE) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: function \"%s\" must " + "return a valid value"), + weechat_prefix ("error"), JS_PLUGIN_NAME, + function); + } } } - if (!ret_value) + if ((ret_type != WEECHAT_SCRIPT_EXEC_IGNORE) && !ret_value) { weechat_printf (NULL, weechat_gettext ("%s%s: error in function \"%s\""), @@ -259,23 +290,28 @@ end: /* * Loads a javascript script. * - * Returns: - * 1: OK - * 0: error + * If code is NULL, the content of filename is read and executed. + * If code is not NULL, it is executed (the file is not read). + * + * Returns pointer to new registered script, NULL if error. */ -int -weechat_js_load (const char *filename) +struct t_plugin_script * +weechat_js_load (const char *filename, const char *code) { char *source; + /* make C compiler happy */ + /* TODO: implement load of code in Javascript */ + (void) code; + source = weechat_file_get_content (filename); if (!source) { weechat_printf (NULL, weechat_gettext ("%s%s: script \"%s\" not found"), weechat_prefix ("error"), JS_PLUGIN_NAME, filename); - return 0; + return NULL; } if ((weechat_js_plugin->debug >= 2) || !js_quiet) @@ -297,7 +333,7 @@ weechat_js_load (const char *filename) "sub-interpreter"), weechat_prefix ("error"), JS_PLUGIN_NAME); free (source); - return 0; + return NULL; } /* load libs */ @@ -322,7 +358,7 @@ weechat_js_load (const char *filename) js_current_script = NULL; } - return 0; + return NULL; } free (source); @@ -343,7 +379,7 @@ weechat_js_load (const char *filename) js_current_script); js_current_script = NULL; } - return 0; + return NULL; } if (!js_registered_script) @@ -353,7 +389,7 @@ weechat_js_load (const char *filename) "found (or failed) in file \"%s\""), weechat_prefix ("error"), JS_PLUGIN_NAME, filename); delete js_current_interpreter; - return 0; + return NULL; } js_current_script = js_registered_script; @@ -372,7 +408,7 @@ weechat_js_load (const char *filename) WEECHAT_HOOK_SIGNAL_STRING, js_current_script->filename); - return 1; + return js_current_script; } /* @@ -385,7 +421,7 @@ weechat_js_load_cb (void *data, const char *filename) /* make C++ compiler happy */ (void) data; - weechat_js_load (filename); + weechat_js_load (filename, NULL); } /* @@ -499,7 +535,7 @@ weechat_js_reload_name (const char *name) weechat_gettext ("%s: script \"%s\" unloaded"), JS_PLUGIN_NAME, name); } - weechat_js_load (filename); + weechat_js_load (filename, NULL); free (filename); } } @@ -512,6 +548,27 @@ weechat_js_reload_name (const char *name) } /* + * Evaluates javascript source code. + * + * Returns: + * 1: OK + * 0: error + */ + +int +weechat_js_eval (struct t_gui_buffer *buffer, int send_to_buffer_as_input, + int exec_commands, const char *code) +{ + /* TODO: implement javascript eval */ + (void) buffer; + (void) send_to_buffer_as_input; + (void) exec_commands; + (void) code; + + return 1; +} + +/* * Callback for command "/javascript". */ @@ -520,12 +577,12 @@ weechat_js_command_cb (const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { - char *ptr_name, *path_script; + char *ptr_name, *ptr_code, *path_script; + int i, send_to_buffer_as_input, exec_commands; /* make C++ compiler happy */ (void) pointer; (void) data; - (void) buffer; if (argc == 1) { @@ -553,10 +610,16 @@ weechat_js_command_cb (const void *pointer, void *data, weechat_js_unload_all (); plugin_script_auto_load (weechat_js_plugin, &weechat_js_load_cb); } - else if (weechat_strcasecmp(argv[1], "unload")) + else if (weechat_strcasecmp(argv[1], "unload") == 0) { weechat_js_unload_all (); } + else if (weechat_strcasecmp (argv[1], "version") == 0) + { + plugin_script_display_interpreter (weechat_js_plugin, 0); + } + else + WEECHAT_COMMAND_ERROR; } else { @@ -589,7 +652,8 @@ weechat_js_command_cb (const void *pointer, void *data, /* load javascript script */ path_script = plugin_script_search_path (weechat_js_plugin, ptr_name); - weechat_js_load ((path_script) ? path_script : ptr_name); + weechat_js_load ((path_script) ? path_script : ptr_name, + NULL); if (path_script) free (path_script); } @@ -605,6 +669,44 @@ weechat_js_command_cb (const void *pointer, void *data, } js_quiet = 0; } + else if (weechat_strcasecmp (argv[1], "eval") == 0) + { + send_to_buffer_as_input = 0; + exec_commands = 0; + ptr_code = argv_eol[2]; + for (i = 2; i < argc; i++) + { + if (argv[i][0] == '-') + { + if (strcmp (argv[i], "-o") == 0) + { + if (i + 1 >= argc) + WEECHAT_COMMAND_ERROR; + send_to_buffer_as_input = 1; + exec_commands = 0; + ptr_code = argv_eol[i + 1]; + } + else if (strcmp (argv[i], "-oc") == 0) + { + if (i + 1 >= argc) + WEECHAT_COMMAND_ERROR; + send_to_buffer_as_input = 1; + exec_commands = 1; + ptr_code = argv_eol[i + 1]; + } + } + else + break; + } + if (!weechat_js_eval (buffer, send_to_buffer_as_input, + exec_commands, ptr_code)) + WEECHAT_COMMAND_ERROR; + /* TODO: implement /javascript eval */ + weechat_printf (NULL, + _("%sCommand \"/%s eval\" is not yet implemented"), + weechat_prefix ("error"), + weechat_js_plugin->name); + } else WEECHAT_COMMAND_ERROR; } @@ -651,6 +753,26 @@ weechat_js_hdata_cb (const void *pointer, void *data, } /* + * Returns javascript info "javascript_eval". + */ + +const char * +weechat_js_info_eval_cb (const void *pointer, void *data, + const char *info_name, + const char *arguments) +{ + static const char *not_implemented = "not yet implemented"; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) info_name; + (void) arguments; + + return not_implemented; +} + +/* * Returns infolist with javascript scripts. */ @@ -701,28 +823,6 @@ weechat_js_signal_debug_dump_cb (const void *pointer, void *data, } /* - * Display infos about external libraries used. - */ - -int -weechat_js_signal_debug_libs_cb (const void *pointer, void *data, - const char *signal, - const char *type_data, void *signal_data) -{ - /* make C++ compiler happy */ - (void) pointer; - (void) data; - (void) signal; - (void) type_data; - (void) signal_data; - - weechat_printf (NULL, " %s (v8): %s", - JS_PLUGIN_NAME, v8::V8::GetVersion()); - - return WEECHAT_RC_OK; -} - -/* * Timer for executing actions. */ @@ -817,21 +917,35 @@ weechat_js_signal_script_action_cb (const void *pointer, void *data, EXPORT int weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) { - struct t_plugin_script_init init; + char str_interpreter[64]; weechat_js_plugin = plugin; - init.callback_command = &weechat_js_command_cb; - init.callback_completion = &weechat_js_completion_cb; - init.callback_hdata = &weechat_js_hdata_cb; - init.callback_infolist = &weechat_js_infolist_cb; - init.callback_signal_debug_dump = &weechat_js_signal_debug_dump_cb; - init.callback_signal_debug_libs = &weechat_js_signal_debug_libs_cb; - init.callback_signal_script_action = &weechat_js_signal_script_action_cb; - init.callback_load_file = &weechat_js_load_cb; + /* set interpreter name and version */ + snprintf (str_interpreter, sizeof (str_interpreter), + "%s (v8)", plugin->name); + weechat_hashtable_set (plugin->variables, "interpreter_name", + str_interpreter); + weechat_hashtable_set (plugin->variables, "interpreter_version", + v8::V8::GetVersion()); + + js_data.config_file = &js_config_file; + js_data.config_look_check_license = &js_config_look_check_license; + js_data.config_look_eval_keep_context = &js_config_look_eval_keep_context; + js_data.scripts = &js_scripts; + js_data.last_script = &last_js_script; + js_data.callback_command = &weechat_js_command_cb; + js_data.callback_completion = &weechat_js_completion_cb; + js_data.callback_hdata = &weechat_js_hdata_cb; + js_data.callback_info_eval = &weechat_js_info_eval_cb; + js_data.callback_infolist = &weechat_js_infolist_cb; + js_data.callback_signal_debug_dump = &weechat_js_signal_debug_dump_cb; + js_data.callback_signal_script_action = &weechat_js_signal_script_action_cb; + js_data.callback_load_file = &weechat_js_load_cb; + js_data.unload_all = &weechat_js_unload_all; js_quiet = 1; - plugin_script_init (plugin, argc, argv, &init); + plugin_script_init (plugin, argc, argv, &js_data); js_quiet = 0; plugin_script_display_short_list (weechat_js_plugin, js_scripts); @@ -847,7 +961,12 @@ EXPORT int weechat_plugin_end (struct t_weechat_plugin *plugin) { js_quiet = 1; - plugin_script_end (plugin, &js_scripts, &weechat_js_unload_all); + if (js_script_eval) + { + weechat_js_unload (js_script_eval); + js_script_eval = NULL; + } + plugin_script_end (plugin, &js_data); js_quiet = 0; /* free some data */ @@ -857,6 +976,9 @@ weechat_plugin_end (struct t_weechat_plugin *plugin) free (js_action_remove_list); if (js_action_autoload_list) free (js_action_autoload_list); + /* weechat_string_dyn_free (js_buffer_output, 1); */ + if (js_eval_output) + free (js_eval_output); return WEECHAT_RC_OK; } diff --git a/src/plugins/javascript/weechat-js.h b/src/plugins/javascript/weechat-js.h index 02f31d4de..abeb54b73 100644 --- a/src/plugins/javascript/weechat-js.h +++ b/src/plugins/javascript/weechat-js.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2013 Koka El Kiwi <kokakiwi@kokakiwi.net> - * Copyright (C) 2015-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2015-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_JS_H -#define WEECHAT_JS_H 1 +#ifndef WEECHAT_PLUGIN_JS_H +#define WEECHAT_PLUGIN_JS_H #include <v8.h> @@ -42,6 +42,8 @@ class WeechatJsV8; extern struct t_weechat_plugin *weechat_js_plugin; +extern struct t_plugin_script_data js_data; + extern int js_quiet; extern struct t_plugin_script *js_scripts; extern struct t_plugin_script *last_js_script; @@ -59,4 +61,4 @@ extern void *weechat_js_exec (struct t_plugin_script *script, int ret_type, const char *function, const char *format, void **argv); -#endif /* WEECHAT_JS_H */ +#endif /* WEECHAT_PLUGIN_JS_H */ diff --git a/src/plugins/logger/CMakeLists.txt b/src/plugins/logger/CMakeLists.txt index 4f3d51527..c889a333f 100644 --- a/src/plugins/logger/CMakeLists.txt +++ b/src/plugins/logger/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/logger/Makefile.am b/src/plugins/logger/Makefile.am index a06a9be44..d7dc276cf 100644 --- a/src/plugins/logger/Makefile.am +++ b/src/plugins/logger/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/logger/logger-buffer.c b/src/plugins/logger/logger-buffer.c index ef2363935..95e4fa78c 100644 --- a/src/plugins/logger/logger-buffer.c +++ b/src/plugins/logger/logger-buffer.c @@ -1,7 +1,7 @@ /* * logger-buffer.c - logger buffer list management * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/logger/logger-buffer.h b/src/plugins/logger/logger-buffer.h index b0ba6d9f6..8e7933ad2 100644 --- a/src/plugins/logger/logger-buffer.h +++ b/src/plugins/logger/logger-buffer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,10 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_LOGGER_BUFFER_H -#define WEECHAT_LOGGER_BUFFER_H 1 +#ifndef WEECHAT_PLUGIN_LOGGER_BUFFER_H +#define WEECHAT_PLUGIN_LOGGER_BUFFER_H + +#include <stdio.h> struct t_infolist; @@ -48,4 +50,4 @@ extern void logger_buffer_free (struct t_logger_buffer *logger_buffer); extern int logger_buffer_add_to_infolist (struct t_infolist *infolist, struct t_logger_buffer *logger_buffer); -#endif /* WEECHAT_LOGGER_BUFFER_H */ +#endif /* WEECHAT_PLUGIN_LOGGER_BUFFER_H */ diff --git a/src/plugins/logger/logger-config.c b/src/plugins/logger/logger-config.c index 0c51f7ed4..51672b68b 100644 --- a/src/plugins/logger/logger-config.c +++ b/src/plugins/logger/logger-config.c @@ -1,7 +1,7 @@ /* * logger-config.c - logger configuration options (file logger.conf) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -36,6 +36,7 @@ int logger_config_loading = 0; /* logger config, look section */ struct t_config_option *logger_config_look_backlog; +struct t_config_option *logger_config_look_backlog_conditions; /* logger config, color section */ @@ -46,6 +47,7 @@ struct t_config_option *logger_config_color_backlog_line; struct t_config_option *logger_config_file_auto_log; struct t_config_option *logger_config_file_flush_delay; +struct t_config_option *logger_config_file_fsync; struct t_config_option *logger_config_file_info_lines; struct t_config_option *logger_config_file_mask; struct t_config_option *logger_config_file_name_lower_case; @@ -387,6 +389,7 @@ logger_config_init () if (!ptr_section) { weechat_config_free (logger_config_file); + logger_config_file = NULL; return 0; } @@ -397,6 +400,16 @@ logger_config_init () "new buffer (0 = no backlog)"), NULL, 0, INT_MAX, "20", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + logger_config_look_backlog_conditions = weechat_config_new_option ( + logger_config_file, ptr_section, + "backlog_conditions", "string", + N_("conditions to display the backlog " + "(note: content is evaluated, see /help eval); " + "empty value displays the backlog on all buffers; " + "for example to display backlog on private buffers only: " + "\"${type} == private\""), + NULL, 0, 0, "", NULL, 0, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); /* color */ ptr_section = weechat_config_new_section (logger_config_file, "color", @@ -409,6 +422,7 @@ logger_config_init () if (!ptr_section) { weechat_config_free (logger_config_file); + logger_config_file = NULL; return 0; } @@ -436,6 +450,7 @@ logger_config_init () if (!ptr_section) { weechat_config_free (logger_config_file); + logger_config_file = NULL; return 0; } @@ -455,6 +470,15 @@ logger_config_init () NULL, NULL, NULL, &logger_config_flush_delay_change, NULL, NULL, NULL, NULL, NULL); + logger_config_file_fsync = weechat_config_new_option ( + logger_config_file, ptr_section, + "fsync", "boolean", + N_("use fsync to synchronize the log file with the storage device " + "after the flush (see man fsync); this is slower but should " + "prevent any data loss in case of power failure during the save of " + "log file"), + NULL, 0, 0, "off", NULL, 0, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); logger_config_file_info_lines = weechat_config_new_option ( logger_config_file, ptr_section, "info_lines", "boolean", @@ -536,6 +560,7 @@ logger_config_init () if (!ptr_section) { weechat_config_free (logger_config_file); + logger_config_file = NULL; return 0; } @@ -553,6 +578,7 @@ logger_config_init () if (!ptr_section) { weechat_config_free (logger_config_file); + logger_config_file = NULL; return 0; } diff --git a/src/plugins/logger/logger-config.h b/src/plugins/logger/logger-config.h index 37259630c..50cbc647f 100644 --- a/src/plugins/logger/logger-config.h +++ b/src/plugins/logger/logger-config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,19 +17,21 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_LOGGER_CONFIG_H -#define WEECHAT_LOGGER_CONFIG_H 1 +#ifndef WEECHAT_PLUGIN_LOGGER_CONFIG_H +#define WEECHAT_PLUGIN_LOGGER_CONFIG_H #define LOGGER_CONFIG_NAME "logger" extern struct t_config_option *logger_config_look_backlog; +extern struct t_config_option *logger_config_look_backlog_conditions; extern struct t_config_option *logger_config_color_backlog_end; extern struct t_config_option *logger_config_color_backlog_line; extern struct t_config_option *logger_config_file_auto_log; extern struct t_config_option *logger_config_file_flush_delay; +extern struct t_config_option *logger_config_file_fsync; extern struct t_config_option *logger_config_file_info_lines; extern struct t_config_option *logger_config_file_mask; extern struct t_config_option *logger_config_file_name_lower_case; @@ -47,4 +49,4 @@ extern int logger_config_read (); extern int logger_config_write (); extern void logger_config_free (); -#endif /* WEECHAT_LOGGER_CONFIG_H */ +#endif /* WEECHAT_PLUGIN_LOGGER_CONFIG_H */ diff --git a/src/plugins/logger/logger-info.c b/src/plugins/logger/logger-info.c index 558070d25..847076843 100644 --- a/src/plugins/logger/logger-info.c +++ b/src/plugins/logger/logger-info.c @@ -1,7 +1,7 @@ /* * logger-info.c - info and infolist hooks for logger plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/logger/logger-info.h b/src/plugins/logger/logger-info.h index 168880fdb..7804d8623 100644 --- a/src/plugins/logger/logger-info.h +++ b/src/plugins/logger/logger-info.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_LOGGER_INFO_H -#define WEECHAT_LOGGER_INFO_H 1 +#ifndef WEECHAT_PLUGIN_LOGGER_INFO_H +#define WEECHAT_PLUGIN_LOGGER_INFO_H extern void logger_info_init (); -#endif /* WEECHAT_LOGGER_INFO_H */ +#endif /* WEECHAT_PLUGIN_LOGGER_INFO_H */ diff --git a/src/plugins/logger/logger-tail.c b/src/plugins/logger/logger-tail.c index 6b4a028bb..b25436cf8 100644 --- a/src/plugins/logger/logger-tail.c +++ b/src/plugins/logger/logger-tail.c @@ -1,7 +1,7 @@ /* * logger-tail.c - return last lines of a file * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/logger/logger-tail.h b/src/plugins/logger/logger-tail.h index 395039c4c..e2628ec7f 100644 --- a/src/plugins/logger/logger-tail.h +++ b/src/plugins/logger/logger-tail.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_LOGGER_TAIL_H -#define WEECHAT_LOGGER_TAIL_H 1 +#ifndef WEECHAT_PLUGIN_LOGGER_TAIL_H +#define WEECHAT_PLUGIN_LOGGER_TAIL_H struct t_logger_line { @@ -30,4 +30,4 @@ extern struct t_logger_line *logger_tail_file (const char *filename, int n_lines); extern void logger_tail_free (struct t_logger_line *lines); -#endif /* WEECHAT_LOGGER_TAIL_H */ +#endif /* WEECHAT_PLUGIN_LOGGER_TAIL_H */ diff --git a/src/plugins/logger/logger.c b/src/plugins/logger/logger.c index 1abc3efc7..a6014464a 100644 --- a/src/plugins/logger/logger.c +++ b/src/plugins/logger/logger.c @@ -1,7 +1,7 @@ /* * logger.c - logger plugin for WeeChat: save buffer lines to disk files * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -50,7 +50,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(13000); +WEECHAT_PLUGIN_PRIORITY(14000); struct t_weechat_plugin *weechat_logger_plugin = NULL; @@ -93,7 +93,8 @@ logger_get_file_path () seconds = time (NULL); date_tmp = localtime (&seconds); path2[0] = '\0'; - strftime (path2, length - 1, path, date_tmp); + if (strftime (path2, length - 1, path, date_tmp) == 0) + path2[0] = '\0'; if (weechat_logger_plugin->debug) { @@ -295,71 +296,71 @@ logger_get_mask_for_buffer (struct t_gui_buffer *buffer) char * logger_get_mask_expanded (struct t_gui_buffer *buffer, const char *mask) { - char *mask2, *mask_decoded, *mask_decoded2, *mask_decoded3, *mask_decoded4; - char *mask_decoded5; + char *mask2, *mask3, *mask4, *mask5, *mask6, *mask7; const char *dir_separator; int length; time_t seconds; struct tm *date_tmp; mask2 = NULL; - mask_decoded = NULL; - mask_decoded2 = NULL; - mask_decoded3 = NULL; - mask_decoded4 = NULL; - mask_decoded5 = NULL; + mask3 = NULL; + mask4 = NULL; + mask5 = NULL; + mask6 = NULL; + mask7 = NULL; dir_separator = weechat_info_get ("dir_separator", ""); if (!dir_separator) return NULL; + /* replace date/time specifiers in mask */ + length = strlen (mask) + 256 + 1; + mask2 = malloc (length); + if (!mask2) + goto end; + seconds = time (NULL); + date_tmp = localtime (&seconds); + mask2[0] = '\0'; + if (strftime (mask2, length - 1, mask, date_tmp) == 0) + mask2[0] = '\0'; + /* * we first replace directory separator (commonly '/') by \01 because * buffer mask can contain this char, and will be replaced by replacement * char ('_' by default) */ - mask2 = weechat_string_replace (mask, dir_separator, "\01"); - if (!mask2) + mask3 = weechat_string_replace (mask2, dir_separator, "\01"); + if (!mask3) goto end; - mask_decoded = weechat_buffer_string_replace_local_var (buffer, mask2); - if (!mask_decoded) + mask4 = weechat_buffer_string_replace_local_var (buffer, mask3); + if (!mask4) goto end; - mask_decoded2 = weechat_string_replace (mask_decoded, - dir_separator, - weechat_config_string (logger_config_file_replacement_char)); - if (!mask_decoded2) + mask5 = weechat_string_replace (mask4, + dir_separator, + weechat_config_string (logger_config_file_replacement_char)); + if (!mask5) goto end; #ifdef __CYGWIN__ - mask_decoded3 = weechat_string_replace (mask_decoded2, "\\", - weechat_config_string (logger_config_file_replacement_char)); + mask6 = weechat_string_replace (mask5, "\\", + weechat_config_string (logger_config_file_replacement_char)); #else - mask_decoded3 = strdup (mask_decoded2); + mask6 = strdup (mask5); #endif /* __CYGWIN__ */ - if (!mask_decoded3) + if (!mask6) goto end; /* restore directory separator */ - mask_decoded4 = weechat_string_replace (mask_decoded3, - "\01", dir_separator); - if (!mask_decoded4) + mask7 = weechat_string_replace (mask6, + "\01", dir_separator); + if (!mask7) goto end; - /* replace date/time specifiers in mask */ - length = strlen (mask_decoded4) + 256 + 1; - mask_decoded5 = malloc (length); - if (!mask_decoded5) - goto end; - seconds = time (NULL); - date_tmp = localtime (&seconds); - mask_decoded5[0] = '\0'; - strftime (mask_decoded5, length - 1, mask_decoded4, date_tmp); - /* convert to lower case? */ if (weechat_config_boolean (logger_config_file_name_lower_case)) - weechat_string_tolower (mask_decoded5); + weechat_string_tolower (mask7); if (weechat_logger_plugin->debug) { @@ -368,22 +369,22 @@ logger_get_mask_expanded (struct t_gui_buffer *buffer, const char *mask) "decoded mask = \"%s\"", LOGGER_PLUGIN_NAME, weechat_buffer_get_string (buffer, "name"), - mask, mask_decoded5); + mask, mask7); } end: if (mask2) free (mask2); - if (mask_decoded) - free (mask_decoded); - if (mask_decoded2) - free (mask_decoded2); - if (mask_decoded3) - free (mask_decoded3); - if (mask_decoded4) - free (mask_decoded4); - - return mask_decoded5; + if (mask3) + free (mask3); + if (mask4) + free (mask4); + if (mask5) + free (mask5); + if (mask6) + free (mask6); + + return mask7; } /* @@ -573,9 +574,10 @@ logger_write_line (struct t_logger_buffer *logger_buffer, date_tmp = localtime (&seconds); if (date_tmp) { - strftime (buf_time, sizeof (buf_time) - 1, - weechat_config_string (logger_config_file_time_format), - date_tmp); + if (strftime (buf_time, sizeof (buf_time) - 1, + weechat_config_string (logger_config_file_time_format), + date_tmp) == 0) + buf_time[0] = '\0'; } snprintf (buf_beginning, sizeof (buf_beginning), _("%s\t**** Beginning of log ****"), @@ -604,6 +606,8 @@ logger_write_line (struct t_logger_buffer *logger_buffer, if (!logger_timer) { fflush (logger_buffer->log_file); + if (weechat_config_boolean (logger_config_file_fsync)) + fsync (fileno (logger_buffer->log_file)); logger_buffer->flush_needed = 0; } free (vbuffer); @@ -633,9 +637,10 @@ logger_stop (struct t_logger_buffer *logger_buffer, int write_info_line) date_tmp = localtime (&seconds); if (date_tmp) { - strftime (buf_time, sizeof (buf_time) - 1, - weechat_config_string (logger_config_file_time_format), - date_tmp); + if (strftime (buf_time, sizeof (buf_time) - 1, + weechat_config_string (logger_config_file_time_format), + date_tmp) == 0) + buf_time[0] = '\0'; } logger_write_line (logger_buffer, _("%s\t**** End of log ****"), @@ -770,15 +775,15 @@ logger_list () } weechat_printf (NULL, " %s[%s%d%s]%s (%s) %s%s%s: %s%s%s%s", - weechat_color("chat_delimiters"), - weechat_color("chat"), + weechat_color ("chat_delimiters"), + weechat_color ("chat"), weechat_infolist_integer (ptr_infolist, "number"), - weechat_color("chat_delimiters"), - weechat_color("chat"), + weechat_color ("chat_delimiters"), + weechat_color ("chat"), weechat_infolist_string (ptr_infolist, "plugin_name"), - weechat_color("chat_buffer"), + weechat_color ("chat_buffer"), weechat_infolist_string (ptr_infolist, "name"), - weechat_color("chat"), + weechat_color ("chat"), status, (ptr_logger_buffer) ? " (" : "", (ptr_logger_buffer) ? @@ -841,6 +846,8 @@ logger_flush () ptr_logger_buffer->log_filename); } fflush (ptr_logger_buffer->log_file); + if (weechat_config_boolean (logger_config_file_fsync)) + fsync (fileno (ptr_logger_buffer->log_file)); ptr_logger_buffer->flush_needed = 0; } } @@ -951,6 +958,62 @@ logger_buffer_renamed_signal_cb (const void *pointer, void *data, } /* + * Checks conditions to display the backlog. + * + * Returns: + * 1: conditions OK (backlog is displayed) + * 0: conditions not OK (backlog is NOT displayed) + */ + +int +logger_backlog_check_conditions (struct t_gui_buffer *buffer) +{ + struct t_hashtable *pointers, *options; + const char *ptr_condition; + char *result; + int condition_ok; + + ptr_condition = weechat_config_string (logger_config_look_backlog_conditions); + + /* empty condition displays the backlog everywhere */ + if (!ptr_condition || !ptr_condition[0]) + return 1; + + pointers = weechat_hashtable_new (32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, + NULL, + NULL); + if (pointers) + { + weechat_hashtable_set (pointers, "window", + weechat_window_search_with_buffer (buffer)); + weechat_hashtable_set (pointers, "buffer", buffer); + } + + options = weechat_hashtable_new (32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, + NULL); + if (options) + weechat_hashtable_set (options, "type", "condition"); + + result = weechat_string_eval_expression (ptr_condition, + pointers, NULL, options); + condition_ok = (result && (strcmp (result, "1") == 0)); + if (result) + free (result); + + if (pointers) + weechat_hashtable_free (pointers); + if (options) + weechat_hashtable_free (options); + + return condition_ok; +} + +/* * Displays backlog for a buffer (by reading end of log file). */ @@ -1050,24 +1113,24 @@ logger_backlog_signal_cb (const void *pointer, void *data, (void) signal; (void) type_data; - if (weechat_config_integer (logger_config_look_backlog) >= 0) - { - ptr_logger_buffer = logger_buffer_search_buffer (signal_data); - if (ptr_logger_buffer && ptr_logger_buffer->log_enabled) - { - if (!ptr_logger_buffer->log_filename) - logger_set_log_filename (ptr_logger_buffer); - - if (ptr_logger_buffer->log_filename) - { - ptr_logger_buffer->log_enabled = 0; + if (weechat_config_integer (logger_config_look_backlog) == 0) + return WEECHAT_RC_OK; - logger_backlog (signal_data, - ptr_logger_buffer->log_filename, - weechat_config_integer (logger_config_look_backlog)); + if (!logger_backlog_check_conditions (signal_data)) + return WEECHAT_RC_OK; - ptr_logger_buffer->log_enabled = 1; - } + ptr_logger_buffer = logger_buffer_search_buffer (signal_data); + if (ptr_logger_buffer && ptr_logger_buffer->log_enabled) + { + if (!ptr_logger_buffer->log_filename) + logger_set_log_filename (ptr_logger_buffer); + if (ptr_logger_buffer->log_filename) + { + ptr_logger_buffer->log_enabled = 0; + logger_backlog (signal_data, + ptr_logger_buffer->log_filename, + weechat_config_integer (logger_config_look_backlog)); + ptr_logger_buffer->log_enabled = 1; } } @@ -1268,9 +1331,10 @@ logger_print_cb (const void *pointer, void *data, date_tmp = localtime (&date); if (date_tmp) { - strftime (buf_time, sizeof (buf_time) - 1, - weechat_config_string (logger_config_file_time_format), - date_tmp); + if (strftime (buf_time, sizeof (buf_time) - 1, + weechat_config_string (logger_config_file_time_format), + date_tmp) == 0) + buf_time[0] = '\0'; } logger_write_line (ptr_logger_buffer, diff --git a/src/plugins/logger/logger.h b/src/plugins/logger/logger.h index ace818216..e1992bda2 100644 --- a/src/plugins/logger/logger.h +++ b/src/plugins/logger/logger.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_LOGGER_H -#define WEECHAT_LOGGER_H 1 +#ifndef WEECHAT_PLUGIN_LOGGER_H +#define WEECHAT_PLUGIN_LOGGER_H #define weechat_plugin weechat_logger_plugin #define LOGGER_PLUGIN_NAME "logger" @@ -35,4 +35,4 @@ extern void logger_adjust_log_filenames (); extern int logger_timer_cb (const void *pointer, void *data, int remaining_calls); -#endif /* WEECHAT_LOGGER_H */ +#endif /* WEECHAT_PLUGIN_LOGGER_H */ diff --git a/src/plugins/lua/CMakeLists.txt b/src/plugins/lua/CMakeLists.txt index 9c0f5c865..21303a486 100644 --- a/src/plugins/lua/CMakeLists.txt +++ b/src/plugins/lua/CMakeLists.txt @@ -1,6 +1,6 @@ # # Copyright (C) 2006-2007 Emmanuel Bouthenot <kolter@openics.org> -# Copyright (C) 2006-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2006-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/lua/Makefile.am b/src/plugins/lua/Makefile.am index 89856e544..27f8f5fc6 100644 --- a/src/plugins/lua/Makefile.am +++ b/src/plugins/lua/Makefile.am @@ -1,6 +1,6 @@ # # Copyright (C) 2006-2007 Emmanuel Bouthenot <kolter@openics.org> -# Copyright (C) 2006-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2006-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/lua/weechat-lua-api.c b/src/plugins/lua/weechat-lua-api.c index c09f09676..1224042de 100644 --- a/src/plugins/lua/weechat-lua-api.c +++ b/src/plugins/lua/weechat-lua-api.c @@ -2,7 +2,7 @@ * weechat-lua-api.c - lua API functions * * Copyright (C) 2006-2007 Emmanuel Bouthenot <kolter@openics.org> - * Copyright (C) 2006-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2006-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2012 Simon Arlott * * This file is part of WeeChat, the extensible chat client. @@ -67,8 +67,14 @@ plugin_script_str2ptr (weechat_lua_plugin, \ LUA_CURRENT_SCRIPT_NAME, \ lua_function_name, __string) -#define API_RETURN_OK return 1 -#define API_RETURN_ERROR return 0 +#define API_STATIC_STRING(__string) \ + plugin_script_get_static_string(&lua_data, __string); +#define API_RETURN_OK \ + lua_pushinteger (L, 1); \ + return 1 +#define API_RETURN_ERROR \ + lua_pushinteger (L, 0); \ + return 1 #define API_RETURN_EMPTY \ lua_pushstring (L, ""); \ return 0 @@ -145,7 +151,7 @@ API_FUNC(register) /* register script */ lua_current_script = plugin_script_add (weechat_lua_plugin, - &lua_scripts, &last_lua_script, + &lua_data, (lua_current_script_filename) ? lua_current_script_filename : "", name, @@ -364,6 +370,22 @@ API_FUNC(string_mask_to_regex) API_RETURN_STRING_FREE(result); } +API_FUNC(string_format_size) +{ + unsigned long long size; + char *result; + + API_INIT_FUNC(1, "string_format_size", API_RETURN_EMPTY); + if (lua_gettop (L) < 1) + API_WRONG_ARGS(API_RETURN_EMPTY); + + size = lua_tonumber (L, -1); + + result = weechat_string_format_size (size); + + API_RETURN_STRING_FREE(result); +} + API_FUNC(string_remove_color) { const char *string, *replacement; @@ -542,19 +564,19 @@ API_FUNC(mkdir_parents) API_FUNC(list_new) { - char *result; + const char *result; API_INIT_FUNC(1, "list_new", API_RETURN_EMPTY); result = API_PTR2STR(weechat_list_new ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_add) { const char *weelist, *data, *where, *user_data; - char *result; + const char *result; API_INIT_FUNC(1, "list_add", API_RETURN_EMPTY); if (lua_gettop (L) < 4) @@ -570,13 +592,13 @@ API_FUNC(list_add) where, API_STR2PTR(user_data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_search) { const char *weelist, *data; - char *result; + const char *result; API_INIT_FUNC(1, "list_search", API_RETURN_EMPTY); if (lua_gettop (L) < 2) @@ -588,7 +610,7 @@ API_FUNC(list_search) result = API_PTR2STR(weechat_list_search (API_STR2PTR(weelist), data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_search_pos) @@ -611,7 +633,7 @@ API_FUNC(list_search_pos) API_FUNC(list_casesearch) { const char *weelist, *data; - char *result; + const char *result; API_INIT_FUNC(1, "list_casesearch", API_RETURN_EMPTY); if (lua_gettop (L) < 2) @@ -623,7 +645,7 @@ API_FUNC(list_casesearch) result = API_PTR2STR(weechat_list_casesearch (API_STR2PTR(weelist), data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_casesearch_pos) @@ -646,7 +668,7 @@ API_FUNC(list_casesearch_pos) API_FUNC(list_get) { const char *weelist; - char *result; + const char *result; int position; API_INIT_FUNC(1, "list_get", API_RETURN_EMPTY); @@ -659,7 +681,7 @@ API_FUNC(list_get) result = API_PTR2STR(weechat_list_get (API_STR2PTR(weelist), position)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_set) @@ -682,7 +704,7 @@ API_FUNC(list_set) API_FUNC(list_next) { const char *item; - char *result; + const char *result; API_INIT_FUNC(1, "list_next", API_RETURN_EMPTY); if (lua_gettop (L) < 1) @@ -692,13 +714,13 @@ API_FUNC(list_next) result = API_PTR2STR(weechat_list_next (API_STR2PTR(item))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_prev) { const char *item; - char *result; + const char *result; API_INIT_FUNC(1, "list_prev", API_RETURN_EMPTY); if (lua_gettop (L) < 1) @@ -708,7 +730,7 @@ API_FUNC(list_prev) result = API_PTR2STR(weechat_list_prev (API_STR2PTR(item))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_string) @@ -805,7 +827,7 @@ weechat_lua_api_config_reload_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); rc = (int *) weechat_lua_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -819,8 +841,6 @@ weechat_lua_api_config_reload_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -831,7 +851,7 @@ weechat_lua_api_config_reload_cb (const void *pointer, void *data, API_FUNC(config_new) { const char *name, *function, *data; - char *result; + const char *result; API_INIT_FUNC(1, "config_new", API_RETURN_EMPTY); if (lua_gettop (L) < 3) @@ -848,7 +868,7 @@ API_FUNC(config_new) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -869,8 +889,8 @@ weechat_lua_api_config_read_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); func_argv[3] = (option_name) ? (char *)option_name : empty_arg; func_argv[4] = (value) ? (char *)value : empty_arg; @@ -886,10 +906,6 @@ weechat_lua_api_config_read_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); return ret; } @@ -914,7 +930,7 @@ weechat_lua_api_config_section_write_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); func_argv[2] = (section_name) ? (char *)section_name : empty_arg; rc = (int *) weechat_lua_exec (script, @@ -929,8 +945,6 @@ weechat_lua_api_config_section_write_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -955,7 +969,7 @@ weechat_lua_api_config_section_write_default_cb (const void *pointer, void *data if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); func_argv[2] = (section_name) ? (char *)section_name : empty_arg; rc = (int *) weechat_lua_exec (script, @@ -970,8 +984,6 @@ weechat_lua_api_config_section_write_default_cb (const void *pointer, void *data ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -998,8 +1010,8 @@ weechat_lua_api_config_section_create_option_cb (const void *pointer, void *data if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); func_argv[3] = (option_name) ? (char *)option_name : empty_arg; func_argv[4] = (value) ? (char *)value : empty_arg; @@ -1015,10 +1027,6 @@ weechat_lua_api_config_section_create_option_cb (const void *pointer, void *data ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); return ret; } @@ -1044,9 +1052,9 @@ weechat_lua_api_config_section_delete_option_cb (const void *pointer, void *data if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); - func_argv[3] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); + func_argv[3] = (char *)API_PTR2STR(option); rc = (int *) weechat_lua_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -1060,12 +1068,6 @@ weechat_lua_api_config_section_delete_option_cb (const void *pointer, void *data ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -1080,7 +1082,7 @@ API_FUNC(config_new_section) const char *data_write_default, *function_create_option; const char *data_create_option, *function_delete_option; const char *data_delete_option; - char *result; + const char *result; int user_can_add_options, user_can_delete_options; API_INIT_FUNC(1, "config_new_section", API_RETURN_EMPTY); @@ -1126,13 +1128,13 @@ API_FUNC(config_new_section) function_delete_option, data_delete_option)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_search_section) { const char *config_file, *section_name; - char *result; + const char *result; API_INIT_FUNC(1, "config_search_section", API_RETURN_EMPTY); if (lua_gettop (L) < 2) @@ -1144,7 +1146,7 @@ API_FUNC(config_search_section) result = API_PTR2STR(weechat_config_search_section (API_STR2PTR(config_file), section_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -1164,7 +1166,7 @@ weechat_lua_api_config_option_check_value_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); func_argv[2] = (value) ? (char *)value : empty_arg; rc = (int *) weechat_lua_exec (script, @@ -1179,8 +1181,6 @@ weechat_lua_api_config_option_check_value_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -1204,16 +1204,13 @@ weechat_lua_api_config_option_change_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); rc = (int *) weechat_lua_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, "ss", func_argv); - if (func_argv[1]) - free (func_argv[1]); - if (rc) free (rc); } @@ -1235,16 +1232,13 @@ weechat_lua_api_config_option_delete_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); rc = (int *) weechat_lua_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, "ss", func_argv); - if (func_argv[1]) - free (func_argv[1]); - if (rc) free (rc); } @@ -1256,7 +1250,7 @@ API_FUNC(config_new_option) const char *string_values, *default_value, *value; const char *function_check_value, *data_check_value, *function_change; const char *data_change, *function_delete, *data_delete; - char *result; + const char *result; int min, max, null_value_allowed; API_INIT_FUNC(1, "config_new_option", API_RETURN_EMPTY); @@ -1304,13 +1298,13 @@ API_FUNC(config_new_option) function_delete, data_delete)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_search_option) { const char *config_file, *section, *option_name; - char *result; + const char *result; API_INIT_FUNC(1, "config_search_option", API_RETURN_EMPTY); if (lua_gettop (L) < 3) @@ -1324,7 +1318,7 @@ API_FUNC(config_search_option) API_STR2PTR(section), option_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_string_to_boolean) @@ -1736,7 +1730,7 @@ API_FUNC(config_free) API_FUNC(config_get) { const char *option; - char *result; + const char *result; API_INIT_FUNC(1, "config_get", API_RETURN_EMPTY); if (lua_gettop (L) < 1) @@ -1746,7 +1740,7 @@ API_FUNC(config_get) result = API_PTR2STR(weechat_config_get (option)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_get_plugin) @@ -2014,7 +2008,7 @@ weechat_lua_api_hook_command_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (argc > 1) ? argv_eol[1] : empty_arg; rc = (int *) weechat_lua_exec (script, @@ -2029,8 +2023,6 @@ weechat_lua_api_hook_command_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -2042,7 +2034,7 @@ API_FUNC(hook_command) { const char *command, *description, *args, *args_description, *completion; const char *function, *data; - char *result; + const char *result; API_INIT_FUNC(1, "hook_command", API_RETURN_EMPTY); if (lua_gettop (L) < 7) @@ -2067,7 +2059,7 @@ API_FUNC(hook_command) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2089,8 +2081,8 @@ weechat_lua_api_hook_completion_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (completion_item) ? (char *)completion_item : empty_arg; - func_argv[2] = API_PTR2STR(buffer); - func_argv[3] = API_PTR2STR(completion); + func_argv[2] = (char *)API_PTR2STR(buffer); + func_argv[3] = (char *)API_PTR2STR(completion); rc = (int *) weechat_lua_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -2104,10 +2096,6 @@ weechat_lua_api_hook_completion_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -2118,7 +2106,7 @@ weechat_lua_api_hook_completion_cb (const void *pointer, void *data, API_FUNC(hook_completion) { const char *completion, *description, *function, *data; - char *result; + const char *result; API_INIT_FUNC(1, "hook_completion", API_RETURN_EMPTY); if (lua_gettop (L) < 4) @@ -2137,7 +2125,7 @@ API_FUNC(hook_completion) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_completion_get_string) @@ -2196,7 +2184,7 @@ weechat_lua_api_hook_command_run_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (command) ? (char *)command : empty_arg; rc = (int *) weechat_lua_exec (script, @@ -2211,8 +2199,6 @@ weechat_lua_api_hook_command_run_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -2223,7 +2209,7 @@ weechat_lua_api_hook_command_run_cb (const void *pointer, void *data, API_FUNC(hook_command_run) { const char *command, *function, *data; - char *result; + const char *result; API_INIT_FUNC(1, "hook_command_run", API_RETURN_EMPTY); if (lua_gettop (L) < 3) @@ -2240,7 +2226,7 @@ API_FUNC(hook_command_run) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2287,7 +2273,7 @@ API_FUNC(hook_timer) { int interval, align_second, max_calls; const char *function, *data; - char *result; + const char *result; API_INIT_FUNC(1, "hook_timer", API_RETURN_EMPTY); if (lua_gettop (L) < 5) @@ -2308,7 +2294,7 @@ API_FUNC(hook_timer) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2316,7 +2302,7 @@ weechat_lua_api_hook_fd_cb (const void *pointer, void *data, int fd) { struct t_plugin_script *script; void *func_argv[2]; - char str_fd[32], empty_arg[1] = { '\0' }; + char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; int *rc, ret; @@ -2325,15 +2311,13 @@ weechat_lua_api_hook_fd_cb (const void *pointer, void *data, int fd) if (ptr_function && ptr_function[0]) { - snprintf (str_fd, sizeof (str_fd), "%d", fd); - func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = str_fd; + func_argv[1] = &fd; rc = (int *) weechat_lua_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "ss", func_argv); + "si", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2353,7 +2337,7 @@ API_FUNC(hook_fd) { int fd, read, write, exception; const char *function, *data; - char *result; + const char *result; API_INIT_FUNC(1, "hook_fd", API_RETURN_EMPTY); if (lua_gettop (L) < 6) @@ -2376,7 +2360,7 @@ API_FUNC(hook_fd) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2443,7 +2427,7 @@ API_FUNC(hook_process) { const char *command, *function, *data; int timeout; - char *result; + const char *result; API_INIT_FUNC(1, "hook_process", API_RETURN_EMPTY); if (lua_gettop (L) < 4) @@ -2462,7 +2446,7 @@ API_FUNC(hook_process) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_process_hashtable) @@ -2470,7 +2454,7 @@ API_FUNC(hook_process_hashtable) const char *command, *function, *data; struct t_hashtable *options; int timeout; - char *result; + const char *result; API_INIT_FUNC(1, "hook_process_hashtable", API_RETURN_EMPTY); if (lua_gettop (L) < 5) @@ -2497,7 +2481,7 @@ API_FUNC(hook_process_hashtable) if (options) weechat_hashtable_free (options); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2508,7 +2492,6 @@ weechat_lua_api_hook_connect_cb (const void *pointer, void *data, { struct t_plugin_script *script; void *func_argv[6]; - char str_status[32], str_gnutls_rc[32], str_sock[32]; char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; int *rc, ret; @@ -2518,21 +2501,17 @@ weechat_lua_api_hook_connect_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { - snprintf (str_status, sizeof (str_status), "%d", status); - snprintf (str_gnutls_rc, sizeof (str_gnutls_rc), "%d", gnutls_rc); - snprintf (str_sock, sizeof (str_sock), "%d", sock); - func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = str_status; - func_argv[2] = str_gnutls_rc; - func_argv[3] = str_sock; + func_argv[1] = &status; + func_argv[2] = &gnutls_rc; + func_argv[3] = &sock; func_argv[4] = (ip_address) ? (char *)ip_address : empty_arg; func_argv[5] = (error) ? (char *)error : empty_arg; rc = (int *) weechat_lua_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "ssssss", func_argv); + "siiiss", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2552,7 +2531,7 @@ API_FUNC(hook_connect) { const char *proxy, *address, *local_hostname, *function, *data; int port, ipv6, retry; - char *result; + const char *result; API_INIT_FUNC(1, "hook_connect", API_RETURN_EMPTY); if (lua_gettop (L) < 8) @@ -2583,7 +2562,7 @@ API_FUNC(hook_connect) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2609,10 +2588,10 @@ weechat_lua_api_hook_print_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { - snprintf (timebuffer, sizeof (timebuffer), "%ld", (long int)date); + snprintf (timebuffer, sizeof (timebuffer), "%lld", (long long)date); func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = timebuffer; func_argv[3] = weechat_string_build_with_split_string (tags, ","); if (!func_argv[3]) @@ -2634,8 +2613,6 @@ weechat_lua_api_hook_print_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); if (func_argv[3]) free (func_argv[3]); @@ -2648,7 +2625,7 @@ weechat_lua_api_hook_print_cb (const void *pointer, void *data, API_FUNC(hook_print) { const char *buffer, *tags, *message, *function, *data; - char *result; + const char *result; int strip_colors; API_INIT_FUNC(1, "hook_print", API_RETURN_EMPTY); @@ -2672,7 +2649,7 @@ API_FUNC(hook_print) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2685,7 +2662,7 @@ weechat_lua_api_hook_signal_cb (const void *pointer, void *data, char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; static char str_value[64]; - int *rc, ret, free_needed; + int *rc, ret; script = (struct t_plugin_script *)pointer; plugin_script_get_function_and_data (data, &ptr_function, &ptr_data); @@ -2694,7 +2671,6 @@ weechat_lua_api_hook_signal_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (signal) ? (char *)signal : empty_arg; - free_needed = 0; if (strcmp (type_data, WEECHAT_HOOK_SIGNAL_STRING) == 0) { func_argv[2] = (signal_data) ? (char *)signal_data : empty_arg; @@ -2711,8 +2687,7 @@ weechat_lua_api_hook_signal_cb (const void *pointer, void *data, } else if (strcmp (type_data, WEECHAT_HOOK_SIGNAL_POINTER) == 0) { - func_argv[2] = API_PTR2STR(signal_data); - free_needed = 1; + func_argv[2] = (char *)API_PTR2STR(signal_data); } else func_argv[2] = empty_arg; @@ -2729,8 +2704,6 @@ weechat_lua_api_hook_signal_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (free_needed && func_argv[2]) - free (func_argv[2]); return ret; } @@ -2741,7 +2714,7 @@ weechat_lua_api_hook_signal_cb (const void *pointer, void *data, API_FUNC(hook_signal) { const char *signal, *function, *data; - char *result; + const char *result; API_INIT_FUNC(1, "hook_signal", API_RETURN_EMPTY); if (lua_gettop (L) < 3) @@ -2758,7 +2731,7 @@ API_FUNC(hook_signal) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_signal_send) @@ -2840,7 +2813,7 @@ weechat_lua_api_hook_hsignal_cb (const void *pointer, void *data, API_FUNC(hook_hsignal) { const char *signal, *function, *data; - char *result; + const char *result; API_INIT_FUNC(1, "hook_hsignal", API_RETURN_EMPTY); if (lua_gettop (L) < 3) @@ -2857,7 +2830,7 @@ API_FUNC(hook_hsignal) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_hsignal_send) @@ -2925,7 +2898,7 @@ weechat_lua_api_hook_config_cb (const void *pointer, void *data, API_FUNC(hook_config) { const char *option, *function, *data; - char *result; + const char *result; API_INIT_FUNC(1, "hook_config", API_RETURN_EMPTY); if (lua_gettop (L) < 3) @@ -2942,7 +2915,7 @@ API_FUNC(hook_config) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } char * @@ -2978,7 +2951,7 @@ weechat_lua_api_hook_modifier_cb (const void *pointer, void *data, API_FUNC(hook_modifier) { const char *modifier, *function, *data; - char *result; + const char *result; API_INIT_FUNC(1, "hook_modifier", API_RETURN_EMPTY); if (lua_gettop (L) < 3) @@ -2995,7 +2968,7 @@ API_FUNC(hook_modifier) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_modifier_exec) @@ -3023,7 +2996,7 @@ weechat_lua_api_hook_info_cb (const void *pointer, void *data, { struct t_plugin_script *script; void *func_argv[3]; - char empty_arg[1] = { '\0' }; + char empty_arg[1] = { '\0' }, *result; const char *ptr_function, *ptr_data; script = (struct t_plugin_script *)pointer; @@ -3035,10 +3008,12 @@ weechat_lua_api_hook_info_cb (const void *pointer, void *data, func_argv[1] = (info_name) ? (char *)info_name : empty_arg; func_argv[2] = (arguments) ? (char *)arguments : empty_arg; - return (const char *)weechat_lua_exec (script, - WEECHAT_SCRIPT_EXEC_STRING, - ptr_function, - "sss", func_argv); + result = (char *)weechat_lua_exec (script, + WEECHAT_SCRIPT_EXEC_STRING, + ptr_function, + "sss", func_argv); + + return API_STATIC_STRING(result); } return NULL; @@ -3047,7 +3022,7 @@ weechat_lua_api_hook_info_cb (const void *pointer, void *data, API_FUNC(hook_info) { const char *info_name, *description, *args_description, *function, *data; - char *result; + const char *result; API_INIT_FUNC(1, "hook_info", API_RETURN_EMPTY); if (lua_gettop (L) < 5) @@ -3068,7 +3043,7 @@ API_FUNC(hook_info) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_hashtable * @@ -3104,7 +3079,7 @@ API_FUNC(hook_info_hashtable) { const char *info_name, *description, *args_description; const char *output_description, *function, *data; - char *result; + const char *result; API_INIT_FUNC(1, "hook_info_hashtable", API_RETURN_EMPTY); if (lua_gettop (L) < 6) @@ -3127,7 +3102,7 @@ API_FUNC(hook_info_hashtable) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_infolist * @@ -3148,18 +3123,15 @@ weechat_lua_api_hook_infolist_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (info_name) ? (char *)info_name : empty_arg; - func_argv[2] = API_PTR2STR(obj_pointer); + func_argv[2] = (char *)API_PTR2STR(obj_pointer); func_argv[3] = (arguments) ? (char *)arguments : empty_arg; result = (struct t_infolist *)weechat_lua_exec ( script, - WEECHAT_SCRIPT_EXEC_STRING, + WEECHAT_SCRIPT_EXEC_POINTER, ptr_function, "ssss", func_argv); - if (func_argv[2]) - free (func_argv[2]); - return result; } @@ -3170,7 +3142,7 @@ API_FUNC(hook_infolist) { const char *infolist_name, *description, *pointer_description; const char *args_description, *function, *data; - char *result; + const char *result; API_INIT_FUNC(1, "hook_infolist", API_RETURN_EMPTY); if (lua_gettop (L) < 6) @@ -3193,7 +3165,7 @@ API_FUNC(hook_infolist) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_hashtable * @@ -3226,7 +3198,7 @@ weechat_lua_api_hook_focus_cb (const void *pointer, void *data, API_FUNC(hook_focus) { const char *area, *function, *data; - char *result; + const char *result; API_INIT_FUNC(1, "hook_focus", API_RETURN_EMPTY); if (lua_gettop (L) < 3) @@ -3243,7 +3215,7 @@ API_FUNC(hook_focus) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_set) @@ -3304,7 +3276,7 @@ weechat_lua_api_buffer_input_data_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (input_data) ? (char *)input_data : empty_arg; rc = (int *) weechat_lua_exec (script, @@ -3319,8 +3291,6 @@ weechat_lua_api_buffer_input_data_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -3344,7 +3314,7 @@ weechat_lua_api_buffer_close_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); rc = (int *) weechat_lua_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -3358,8 +3328,6 @@ weechat_lua_api_buffer_close_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -3371,7 +3339,7 @@ API_FUNC(buffer_new) { const char *name, *function_input, *data_input, *function_close; const char *data_close; - char *result; + const char *result; API_INIT_FUNC(1, "buffer_new", API_RETURN_EMPTY); if (lua_gettop (L) < 5) @@ -3393,13 +3361,13 @@ API_FUNC(buffer_new) function_close, data_close)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_search) { const char *plugin, *name; - char *result; + const char *result; API_INIT_FUNC(1, "buffer_search", API_RETURN_EMPTY); if (lua_gettop (L) < 2) @@ -3410,29 +3378,29 @@ API_FUNC(buffer_search) result = API_PTR2STR(weechat_buffer_search (plugin, name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_search_main) { - char *result; + const char *result; API_INIT_FUNC(1, "buffer_search_main", API_RETURN_EMPTY); result = API_PTR2STR(weechat_buffer_search_main ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(current_buffer) { - char *result; + const char *result; API_INIT_FUNC(1, "current_buffer", API_RETURN_EMPTY); result = API_PTR2STR(weechat_current_buffer ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_clear) @@ -3537,7 +3505,7 @@ API_FUNC(buffer_get_string) API_FUNC(buffer_get_pointer) { const char *buffer, *property; - char *result; + const char *result; API_INIT_FUNC(1, "buffer_get_pointer", API_RETURN_EMPTY); if (lua_gettop (L) < 2) @@ -3549,7 +3517,7 @@ API_FUNC(buffer_get_pointer) result = API_PTR2STR(weechat_buffer_get_pointer (API_STR2PTR(buffer), property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_set) @@ -3606,19 +3574,19 @@ API_FUNC(buffer_match_list) API_FUNC(current_window) { - char *result; + const char *result; API_INIT_FUNC(1, "current_window", API_RETURN_EMPTY); result = API_PTR2STR(weechat_current_window ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(window_search_with_buffer) { const char *buffer; - char *result; + const char *result; API_INIT_FUNC(1, "window_search_with_buffer", API_RETURN_EMPTY); if (lua_gettop (L) < 1) @@ -3628,7 +3596,7 @@ API_FUNC(window_search_with_buffer) result = API_PTR2STR(weechat_window_search_with_buffer (API_STR2PTR(buffer))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(window_get_integer) @@ -3669,7 +3637,7 @@ API_FUNC(window_get_string) API_FUNC(window_get_pointer) { const char *window, *property; - char *result; + const char *result; API_INIT_FUNC(1, "window_get_pointer", API_RETURN_EMPTY); if (lua_gettop (L) < 2) @@ -3681,7 +3649,7 @@ API_FUNC(window_get_pointer) result = API_PTR2STR(weechat_window_get_pointer (API_STR2PTR(window), property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(window_set_title) @@ -3702,7 +3670,7 @@ API_FUNC(window_set_title) API_FUNC(nicklist_add_group) { const char *buffer, *parent_group, *name, *color; - char *result; + const char *result; int visible; API_INIT_FUNC(1, "nicklist_add_group", API_RETURN_EMPTY); @@ -3721,13 +3689,13 @@ API_FUNC(nicklist_add_group) color, visible)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_search_group) { const char *buffer, *from_group, *name; - char *result; + const char *result; API_INIT_FUNC(1, "nicklist_search_group", API_RETURN_EMPTY); if (lua_gettop (L) < 3) @@ -3741,13 +3709,13 @@ API_FUNC(nicklist_search_group) API_STR2PTR(from_group), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_add_nick) { const char *buffer, *group, *name, *color, *prefix, *prefix_color; - char *result; + const char *result; int visible; API_INIT_FUNC(1, "nicklist_add_nick", API_RETURN_EMPTY); @@ -3770,13 +3738,13 @@ API_FUNC(nicklist_add_nick) prefix_color, visible)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_search_nick) { const char *buffer, *from_group, *name; - char *result; + const char *result; API_INIT_FUNC(1, "nicklist_search_nick", API_RETURN_EMPTY); if (lua_gettop (L) < 3) @@ -3790,7 +3758,7 @@ API_FUNC(nicklist_search_nick) API_STR2PTR(from_group), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_remove_group) @@ -3884,7 +3852,7 @@ API_FUNC(nicklist_group_get_string) API_FUNC(nicklist_group_get_pointer) { const char *buffer, *group, *property; - char *result; + const char *result; API_INIT_FUNC(1, "nicklist_group_get_pointer", API_RETURN_EMPTY); if (lua_gettop (L) < 3) @@ -3898,7 +3866,7 @@ API_FUNC(nicklist_group_get_pointer) API_STR2PTR(group), property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_group_set) @@ -3964,7 +3932,7 @@ API_FUNC(nicklist_nick_get_string) API_FUNC(nicklist_nick_get_pointer) { const char *buffer, *nick, *property; - char *result; + const char *result; API_INIT_FUNC(1, "nicklist_nick_get_pointer", API_RETURN_EMPTY); if (lua_gettop (L) < 3) @@ -3978,7 +3946,7 @@ API_FUNC(nicklist_nick_get_pointer) API_STR2PTR(nick), property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_nick_set) @@ -4005,7 +3973,7 @@ API_FUNC(nicklist_nick_set) API_FUNC(bar_item_search) { const char *name; - char *result; + const char *result; API_INIT_FUNC(1, "bar_item_search", API_RETURN_EMPTY); if (lua_gettop (L) < 1) @@ -4015,7 +3983,7 @@ API_FUNC(bar_item_search) result = API_PTR2STR(weechat_bar_item_search (name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } char * @@ -4039,39 +4007,27 @@ weechat_lua_api_bar_item_build_cb (const void *pointer, void *data, { /* new callback: data, item, window, buffer, extra_info */ func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(item); - func_argv[2] = API_PTR2STR(window); - func_argv[3] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(item); + func_argv[2] = (char *)API_PTR2STR(window); + func_argv[3] = (char *)API_PTR2STR(buffer); func_argv[4] = extra_info; ret = (char *)weechat_lua_exec (script, WEECHAT_SCRIPT_EXEC_STRING, ptr_function + 7, "ssssh", func_argv); - - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); } else { /* old callback: data, item, window */ func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(item); - func_argv[2] = API_PTR2STR(window); + func_argv[1] = (char *)API_PTR2STR(item); + func_argv[2] = (char *)API_PTR2STR(window); ret = (char *)weechat_lua_exec (script, WEECHAT_SCRIPT_EXEC_STRING, ptr_function, "sss", func_argv); - - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); } return ret; @@ -4083,7 +4039,7 @@ weechat_lua_api_bar_item_build_cb (const void *pointer, void *data, API_FUNC(bar_item_new) { const char *name, *function, *data; - char *result; + const char *result; API_INIT_FUNC(1, "bar_item_new", API_RETURN_EMPTY); if (lua_gettop (L) < 3) @@ -4100,7 +4056,7 @@ API_FUNC(bar_item_new) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(bar_item_update) @@ -4136,7 +4092,7 @@ API_FUNC(bar_item_remove) API_FUNC(bar_search) { const char *name; - char *result; + const char *result; API_INIT_FUNC(1, "bar_search", API_RETURN_EMPTY); if (lua_gettop (L) < 1) @@ -4146,7 +4102,7 @@ API_FUNC(bar_search) result = API_PTR2STR(weechat_bar_search (name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(bar_new) @@ -4154,7 +4110,7 @@ API_FUNC(bar_new) const char *name, *hidden, *priority, *type, *conditions, *position; const char *filling_top_bottom, *filling_left_right, *size, *size_max; const char *color_fg, *color_delim, *color_bg, *separator, *items; - char *result; + const char *result; API_INIT_FUNC(1, "bar_new", API_RETURN_EMPTY); if (lua_gettop (L) < 15) @@ -4192,7 +4148,7 @@ API_FUNC(bar_new) separator, items)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(bar_set) @@ -4308,19 +4264,19 @@ API_FUNC(info_get_hashtable) API_FUNC(infolist_new) { - char *result; + const char *result; API_INIT_FUNC(1, "infolist_new", API_RETURN_EMPTY); result = API_PTR2STR(weechat_infolist_new ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_item) { const char *infolist; - char *result; + const char *result; API_INIT_FUNC(1, "infolist_new_item", API_RETURN_EMPTY); if (lua_gettop (L) < 1) @@ -4330,13 +4286,13 @@ API_FUNC(infolist_new_item) result = API_PTR2STR(weechat_infolist_new_item (API_STR2PTR(infolist))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_integer) { const char *item, *name; - char *result; + const char *result; int value; API_INIT_FUNC(1, "infolist_new_var_integer", API_RETURN_EMPTY); @@ -4351,13 +4307,13 @@ API_FUNC(infolist_new_var_integer) name, value)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_string) { const char *item, *name, *value; - char *result; + const char *result; API_INIT_FUNC(1, "infolist_new_var_string", API_RETURN_EMPTY); if (lua_gettop (L) < 3) @@ -4371,13 +4327,13 @@ API_FUNC(infolist_new_var_string) name, value)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_pointer) { const char *item, *name, *value; - char *result; + const char *result; API_INIT_FUNC(1, "infolist_new_var_pointer", API_RETURN_EMPTY); if (lua_gettop (L) < 3) @@ -4391,13 +4347,13 @@ API_FUNC(infolist_new_var_pointer) name, API_STR2PTR(value))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_time) { const char *item, *name; - char *result; + const char *result; int value; API_INIT_FUNC(1, "infolist_new_var_time", API_RETURN_EMPTY); @@ -4412,13 +4368,13 @@ API_FUNC(infolist_new_var_time) name, value)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_search_var) { const char *infolist, *name; - char *result; + const char *result; API_INIT_FUNC(1, "infolist_search_var", API_RETURN_EMPTY); if (lua_gettop (L) < 2) @@ -4430,13 +4386,13 @@ API_FUNC(infolist_search_var) result = API_PTR2STR(weechat_infolist_search_var (API_STR2PTR(infolist), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_get) { const char *name, *pointer, *arguments; - char *result; + const char *result; API_INIT_FUNC(1, "infolist_get", API_RETURN_EMPTY); if (lua_gettop (L) < 3) @@ -4450,7 +4406,7 @@ API_FUNC(infolist_get) API_STR2PTR(pointer), arguments)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_next) @@ -4553,7 +4509,7 @@ API_FUNC(infolist_string) API_FUNC(infolist_pointer) { const char *infolist, *variable; - char *result; + const char *result; API_INIT_FUNC(1, "infolist_pointer", API_RETURN_EMPTY); if (lua_gettop (L) < 2) @@ -4565,32 +4521,24 @@ API_FUNC(infolist_pointer) result = API_PTR2STR(weechat_infolist_pointer (API_STR2PTR(infolist), variable)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_time) { const char *infolist, *variable; time_t time; - struct tm *date_tmp; - char timebuffer[64], *result; - API_INIT_FUNC(1, "infolist_time", API_RETURN_EMPTY); + API_INIT_FUNC(1, "infolist_time", API_RETURN_LONG(0)); if (lua_gettop (L) < 2) - API_WRONG_ARGS(API_RETURN_EMPTY); + API_WRONG_ARGS(API_RETURN_LONG(0)); infolist = lua_tostring (L, -2); variable = lua_tostring (L, -1); - timebuffer[0] = '\0'; - time = weechat_infolist_time (API_STR2PTR(infolist), - variable); - date_tmp = localtime (&time); - if (date_tmp) - strftime (timebuffer, sizeof (timebuffer), "%F %T", date_tmp); - result = strdup (timebuffer); + time = weechat_infolist_time (API_STR2PTR(infolist), variable); - API_RETURN_STRING_FREE(result); + API_RETURN_LONG(time); } API_FUNC(infolist_free) @@ -4611,7 +4559,7 @@ API_FUNC(infolist_free) API_FUNC(hdata_get) { const char *name; - char *result; + const char *result; API_INIT_FUNC(1, "hdata_get", API_RETURN_EMPTY); if (lua_gettop (L) < 1) @@ -4621,7 +4569,7 @@ API_FUNC(hdata_get) result = API_PTR2STR(weechat_hdata_get (name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_get_var_offset) @@ -4715,7 +4663,7 @@ API_FUNC(hdata_get_var_hdata) API_FUNC(hdata_get_list) { const char *hdata, *name; - char *result; + const char *result; API_INIT_FUNC(1, "hdata_get_list", API_RETURN_EMPTY); if (lua_gettop (L) < 2) @@ -4727,7 +4675,7 @@ API_FUNC(hdata_get_list) result = API_PTR2STR(weechat_hdata_get_list (API_STR2PTR(hdata), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_check_pointer) @@ -4753,7 +4701,7 @@ API_FUNC(hdata_check_pointer) API_FUNC(hdata_move) { const char *hdata, *pointer; - char *result; + const char *result; int count; API_INIT_FUNC(1, "hdata_move", API_RETURN_EMPTY); @@ -4768,13 +4716,13 @@ API_FUNC(hdata_move) API_STR2PTR(pointer), count)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_search) { const char *hdata, *pointer, *search; - char *result; + const char *result; int move; API_INIT_FUNC(1, "hdata_search", API_RETURN_EMPTY); @@ -4791,7 +4739,7 @@ API_FUNC(hdata_search) search, move)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_char) @@ -4876,7 +4824,7 @@ API_FUNC(hdata_string) API_FUNC(hdata_pointer) { const char *hdata, *pointer, *name; - char *result; + const char *result; API_INIT_FUNC(1, "hdata_pointer", API_RETURN_EMPTY); if (lua_gettop (L) < 3) @@ -4890,7 +4838,7 @@ API_FUNC(hdata_pointer) API_STR2PTR(pointer), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_time) @@ -5020,9 +4968,9 @@ weechat_lua_api_upgrade_read_cb (const void *pointer, void *data, snprintf (str_object_id, sizeof (str_object_id), "%d", object_id); func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(upgrade_file); + func_argv[1] = (char *)API_PTR2STR(upgrade_file); func_argv[2] = str_object_id; - func_argv[3] = API_PTR2STR(infolist); + func_argv[3] = (char *)API_PTR2STR(infolist); rc = (int *) weechat_lua_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -5036,10 +4984,6 @@ weechat_lua_api_upgrade_read_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -5050,7 +4994,7 @@ weechat_lua_api_upgrade_read_cb (const void *pointer, void *data, API_FUNC(upgrade_new) { const char *filename, *function, *data; - char *result; + const char *result; API_INIT_FUNC(1, "upgrade_new", API_RETURN_EMPTY); if (lua_gettop (L) < 3) @@ -5069,7 +5013,7 @@ API_FUNC(upgrade_new) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(upgrade_write_object) @@ -5128,6 +5072,7 @@ API_FUNC(upgrade_close) */ const struct luaL_Reg weechat_lua_api_funcs[] = { + { "__output__", weechat_lua_output }, API_DEF_FUNC(register), API_DEF_FUNC(plugin_get_name), API_DEF_FUNC(charset_set), @@ -5140,6 +5085,7 @@ const struct luaL_Reg weechat_lua_api_funcs[] = { API_DEF_FUNC(string_has_highlight), API_DEF_FUNC(string_has_highlight_regex), API_DEF_FUNC(string_mask_to_regex), + API_DEF_FUNC(string_format_size), API_DEF_FUNC(string_remove_color), API_DEF_FUNC(string_is_command_char), API_DEF_FUNC(string_input_for_buffer), diff --git a/src/plugins/lua/weechat-lua-api.h b/src/plugins/lua/weechat-lua-api.h index c6401bcda..00b374a0a 100644 --- a/src/plugins/lua/weechat-lua-api.h +++ b/src/plugins/lua/weechat-lua-api.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2006-2007 Emmanuel Bouthenot <kolter@openics.org> - * Copyright (C) 2006-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2006-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_LUA_API_H -#define WEECHAT_LUA_API_H 1 +#ifndef WEECHAT_PLUGIN_LUA_API_H +#define WEECHAT_PLUGIN_LUA_API_H extern struct luaL_Reg weechat_lua_api_funcs[]; extern struct t_lua_const weechat_lua_api_consts[]; @@ -32,4 +32,4 @@ extern int weechat_lua_api_buffer_close_cb (const void *pointer, void *data, struct t_gui_buffer *buffer); -#endif /* WEECHAT_LUA_API_H */ +#endif /* WEECHAT_PLUGIN_LUA_API_H */ diff --git a/src/plugins/lua/weechat-lua.c b/src/plugins/lua/weechat-lua.c index 379e99ff6..124ccbdab 100644 --- a/src/plugins/lua/weechat-lua.c +++ b/src/plugins/lua/weechat-lua.c @@ -2,7 +2,7 @@ * weechat-lua.c - lua plugin for WeeChat * * Copyright (C) 2006-2007 Emmanuel Bouthenot <kolter@openics.org> - * Copyright (C) 2006-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2006-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -26,6 +26,7 @@ #include <lualib.h> #include <lauxlib.h> #include <stdlib.h> +#include <stdio.h> #include <string.h> #include "../weechat-plugin.h" @@ -39,17 +40,44 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Support of lua scripts")); WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(3000); +WEECHAT_PLUGIN_PRIORITY(4000); -struct t_weechat_plugin *weechat_lua_plugin; +struct t_weechat_plugin *weechat_lua_plugin = NULL; + +struct t_plugin_script_data lua_data; + +struct t_config_file *lua_config_file = NULL; +struct t_config_option *lua_config_look_check_license = NULL; +struct t_config_option *lua_config_look_eval_keep_context = NULL; int lua_quiet = 0; + +struct t_plugin_script *lua_script_eval = NULL; +int lua_eval_mode = 0; +int lua_eval_send_input = 0; +int lua_eval_exec_commands = 0; +struct t_gui_buffer *lua_eval_buffer = NULL; +char *lua_eval_output = NULL; +#if LUA_VERSION_NUM >= 502 +#define LUA_LOAD "load" +#else +#define LUA_LOAD "loadstring" +#endif /* LUA_VERSION_NUM >= 502 */ +#define LUA_EVAL_SCRIPT \ + "function script_lua_eval(code)\n" \ + " assert(" LUA_LOAD "(code))()\n" \ + "end\n" \ + "\n" \ + "weechat.register('" WEECHAT_SCRIPT_EVAL_NAME "', '', '1.0', " \ + "'" WEECHAT_LICENSE "', 'Evaluation of source code', '', '')\n" + struct t_plugin_script *lua_scripts = NULL; struct t_plugin_script *last_lua_script = NULL; struct t_plugin_script *lua_current_script = NULL; struct t_plugin_script *lua_registered_script = NULL; const char *lua_current_script_filename = NULL; lua_State *lua_current_interpreter = NULL; +char **lua_buffer_output = NULL; /* * string used to execute action "install": @@ -155,6 +183,98 @@ weechat_lua_tohashtable (lua_State *interpreter, int index, int size, } /* + * Flushes output. + */ + +void +weechat_lua_output_flush () +{ + const char *ptr_command; + char *command; + int length; + + if (!*lua_buffer_output[0]) + return; + + if (lua_eval_mode) + { + /* if there's no buffer, we catch the output, so there's no flush */ + if (!lua_eval_buffer) + return; + + if (lua_eval_send_input) + { + if (lua_eval_exec_commands) + ptr_command = *lua_buffer_output; + else + ptr_command = weechat_string_input_for_buffer (*lua_buffer_output); + if (ptr_command) + { + weechat_command (lua_eval_buffer, *lua_buffer_output); + } + else + { + length = 1 + strlen (*lua_buffer_output) + 1; + command = malloc (length); + if (command) + { + snprintf (command, length, "%c%s", + *lua_buffer_output[0], *lua_buffer_output); + weechat_command (lua_eval_buffer, + (command[0]) ? command : " "); + free (command); + } + } + } + else + { + weechat_printf (lua_eval_buffer, "%s", *lua_buffer_output); + } + } + else + { + /* script (no eval mode) */ + weechat_printf ( + NULL, + weechat_gettext ("%s: stdout/stderr (%s): %s"), + LUA_PLUGIN_NAME, + (lua_current_script) ? lua_current_script->name : "?", + *lua_buffer_output); + } + + weechat_string_dyn_copy (lua_buffer_output, NULL); +} + +/* + * Redirection for stdout and stderr. + */ + +int +weechat_lua_output (lua_State *L) +{ + const char *msg, *ptr_msg, *ptr_newline; + char *message; + + if (lua_gettop (L) < 1) + return 0; + + msg = lua_tostring (L, -1); + ptr_msg = msg; + while ((ptr_newline = strchr (ptr_msg, '\n')) != NULL) + { + message = weechat_strndup (ptr_msg, ptr_newline - ptr_msg); + weechat_string_dyn_concat (lua_buffer_output, message); + if (message) + free (message); + weechat_lua_output_flush (); + ptr_msg = ++ptr_newline; + } + weechat_string_dyn_concat (lua_buffer_output, ptr_msg); + + return 0; +} + +/* * Executes a lua function. */ @@ -163,7 +283,7 @@ weechat_lua_exec (struct t_plugin_script *script, int ret_type, const char *function, const char *format, void **argv) { void *ret_value; - int argc, i, *ret_i; + int argc, i, *ret_i, rc; lua_State *old_lua_current_interpreter; struct t_plugin_script *old_lua_current_script; @@ -204,7 +324,11 @@ weechat_lua_exec (struct t_plugin_script *script, int ret_type, ret_value = NULL; - if (lua_pcall (lua_current_interpreter, argc, 1, 0) == 0) + rc = lua_pcall (lua_current_interpreter, argc, 1, 0); + + weechat_lua_output_flush (); + + if (rc == 0) { if (ret_type == WEECHAT_SCRIPT_EXEC_STRING) { @@ -222,6 +346,24 @@ weechat_lua_exec (struct t_plugin_script *script, int ret_type, function); } } + else if (ret_type == WEECHAT_SCRIPT_EXEC_POINTER) + { + ret_value = (char *) lua_tostring (lua_current_interpreter, -1); + if (ret_value) + { + ret_value = plugin_script_str2ptr (weechat_lua_plugin, + script->name, function, + ret_value); + } + else + { + weechat_printf (NULL, + weechat_gettext ("%s%s: function \"%s\" must " + "return a valid value"), + weechat_prefix ("error"), LUA_PLUGIN_NAME, + function); + } + } else if (ret_type == WEECHAT_SCRIPT_EXEC_INT) { ret_i = malloc (sizeof (*ret_i)); @@ -238,7 +380,14 @@ weechat_lua_exec (struct t_plugin_script *script, int ret_type, } else { - WEECHAT_SCRIPT_MSG_WRONG_ARGS(LUA_CURRENT_SCRIPT_NAME, function); + if (ret_type != WEECHAT_SCRIPT_EXEC_IGNORE) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: function \"%s\" must " + "return a valid value"), + weechat_prefix ("error"), LUA_PLUGIN_NAME, + function); + } } } else @@ -252,6 +401,13 @@ weechat_lua_exec (struct t_plugin_script *script, int ret_type, lua_tostring (lua_current_interpreter, -1)); } + if ((ret_type != WEECHAT_SCRIPT_EXEC_IGNORE) && !ret_value) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: error in function \"%s\""), + weechat_prefix ("error"), LUA_PLUGIN_NAME, function); + } + lua_pop (lua_current_interpreter, 1); lua_current_script = old_lua_current_script; @@ -276,7 +432,7 @@ weechat_lua_add_constant (lua_State *L, struct t_lua_const *ptr_const) #else lua_pushnumber (L, ptr_const->int_value); #endif /* LUA_VERSION_NUM >= 503 */ - lua_settable(L, -3); + lua_settable (L, -3); } /* @@ -286,7 +442,7 @@ weechat_lua_add_constant (lua_State *L, struct t_lua_const *ptr_const) int weechat_lua_newindex (lua_State *L) { - luaL_error(L, "Error: read-only constant"); + luaL_error (L, "Error: read-only constant"); return 0; } @@ -337,31 +493,42 @@ weechat_lua_register_lib (lua_State *L, const char *libname, /* * Loads a lua script. * - * Returns: - * 1: OK - * 0: error + * If code is NULL, the content of filename is read and executed. + * If code is not NULL, it is executed (the file is not read). + * + * Returns pointer to new registered script, NULL if error. */ -int -weechat_lua_load (const char *filename) +struct t_plugin_script * +weechat_lua_load (const char *filename, const char *code) { FILE *fp; - char *weechat_lua_code = { + char *lua_redirect_output = { + "function weechat_output_string(str)\n" + " weechat.__output__(str)\n" + "end\n" "weechat_outputs = {\n" - " write = function (self, str)\n" - " weechat.print(\"\", \"lua: stdout/stderr: \" .. str)\n" - " end\n" + " write = weechat_output_string\n" "}\n" "io.stdout = weechat_outputs\n" "io.stderr = weechat_outputs\n" + "io.write = weechat_output_string\n" + "print = weechat_output_string\n" }; - if ((fp = fopen (filename, "r")) == NULL) + fp = NULL; + + if (!code) { - weechat_printf (NULL, - weechat_gettext ("%s%s: script \"%s\" not found"), - weechat_prefix ("error"), LUA_PLUGIN_NAME, filename); - return 0; + fp = fopen (filename, "r"); + if (!fp) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: script \"%s\" not found"), + weechat_prefix ("error"), LUA_PLUGIN_NAME, + filename); + return NULL; + } } if ((weechat_lua_plugin->debug >= 2) || !lua_quiet) @@ -374,7 +541,7 @@ weechat_lua_load (const char *filename) lua_current_script = NULL; lua_registered_script = NULL; - lua_current_interpreter = luaL_newstate(); + lua_current_interpreter = luaL_newstate (); if (lua_current_interpreter == NULL) { @@ -382,8 +549,9 @@ weechat_lua_load (const char *filename) weechat_gettext ("%s%s: unable to create new " "sub-interpreter"), weechat_prefix ("error"), LUA_PLUGIN_NAME); - fclose (fp); - return 0; + if (fp) + fclose (fp); + return NULL; } #ifdef LUA_VERSION_NUM /* LUA_VERSION_NUM is defined only in lua >= 5.1.0 */ @@ -402,9 +570,9 @@ weechat_lua_load (const char *filename) weechat_lua_api_consts); #ifdef LUA_VERSION_NUM - if (luaL_dostring (lua_current_interpreter, weechat_lua_code) != 0) + if (luaL_dostring (lua_current_interpreter, lua_redirect_output) != 0) #else - if (lua_dostring (lua_current_interpreter, weechat_lua_code) != 0) + if (lua_dostring (lua_current_interpreter, lua_redirect_output) != 0) #endif /* LUA_VERSION_NUM */ { weechat_printf (NULL, @@ -415,32 +583,65 @@ weechat_lua_load (const char *filename) lua_current_script_filename = filename; - if (luaL_loadfile (lua_current_interpreter, filename) != 0) + if (code) { - weechat_printf (NULL, - weechat_gettext ("%s%s: unable to load file \"%s\""), - weechat_prefix ("error"), LUA_PLUGIN_NAME, filename); - weechat_printf (NULL, - weechat_gettext ("%s%s: error: %s"), - weechat_prefix ("error"), LUA_PLUGIN_NAME, - lua_tostring (lua_current_interpreter, -1)); - lua_close (lua_current_interpreter); - fclose (fp); - return 0; + /* execute code without reading file */ + if (luaL_loadstring (lua_current_interpreter, code) != 0) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: unable to load source " + "code"), + weechat_prefix ("error"), LUA_PLUGIN_NAME); + weechat_printf (NULL, + weechat_gettext ("%s%s: error: %s"), + weechat_prefix ("error"), LUA_PLUGIN_NAME, + lua_tostring (lua_current_interpreter, -1)); + lua_close (lua_current_interpreter); + return NULL; + } + } + else + { + /* read and execute code from file */ + if (luaL_loadfile (lua_current_interpreter, filename) != 0) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: unable to load file \"%s\""), + weechat_prefix ("error"), LUA_PLUGIN_NAME, filename); + weechat_printf (NULL, + weechat_gettext ("%s%s: error: %s"), + weechat_prefix ("error"), LUA_PLUGIN_NAME, + lua_tostring (lua_current_interpreter, -1)); + lua_close (lua_current_interpreter); + fclose (fp); + return NULL; + } } if (lua_pcall (lua_current_interpreter, 0, 0, 0) != 0) { - weechat_printf (NULL, - weechat_gettext ("%s%s: unable to execute file " - "\"%s\""), - weechat_prefix ("error"), LUA_PLUGIN_NAME, filename); + if (code) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: unable to execute source " + "code"), + weechat_prefix ("error"), LUA_PLUGIN_NAME); + } + else + { + weechat_printf (NULL, + weechat_gettext ("%s%s: unable to execute file " + "\"%s\""), + weechat_prefix ("error"), LUA_PLUGIN_NAME, + filename); + } weechat_printf (NULL, weechat_gettext ("%s%s: error: %s"), weechat_prefix ("error"), LUA_PLUGIN_NAME, lua_tostring (lua_current_interpreter, -1)); lua_close (lua_current_interpreter); - fclose (fp); + if (fp) + fclose (fp); /* if script was registered, remove it from list */ if (lua_current_script) @@ -451,9 +652,11 @@ weechat_lua_load (const char *filename) lua_current_script = NULL; } - return 0; + return NULL; } - fclose (fp); + + if (fp) + fclose (fp); if (!lua_registered_script) { @@ -462,7 +665,7 @@ weechat_lua_load (const char *filename) "found (or failed) in file \"%s\""), weechat_prefix ("error"), LUA_PLUGIN_NAME, filename); lua_close (lua_current_interpreter); - return 0; + return NULL; } lua_current_script = lua_registered_script; @@ -480,7 +683,7 @@ weechat_lua_load (const char *filename) WEECHAT_HOOK_SIGNAL_STRING, lua_current_script->filename); - return 1; + return lua_current_script; } /* @@ -493,7 +696,7 @@ weechat_lua_load_cb (void *data, const char *filename) /* make C compiler happy */ (void) data; - weechat_lua_load (filename); + weechat_lua_load (filename, NULL); } /* @@ -596,7 +799,7 @@ weechat_lua_reload_name (const char *name) weechat_gettext ("%s: script \"%s\" unloaded"), LUA_PLUGIN_NAME, name); } - weechat_lua_load (filename); + weechat_lua_load (filename, NULL); free (filename); } } @@ -622,6 +825,64 @@ weechat_lua_unload_all () } /* + * Evaluates lua source code. + * + * Returns: + * 1: OK + * 0: error + */ + +int +weechat_lua_eval (struct t_gui_buffer *buffer, int send_to_buffer_as_input, + int exec_commands, const char *code) +{ + void *func_argv[1], *result; + + if (!lua_script_eval) + { + lua_quiet = 1; + lua_script_eval = weechat_lua_load (WEECHAT_SCRIPT_EVAL_NAME, + LUA_EVAL_SCRIPT); + lua_quiet = 0; + if (!lua_script_eval) + return 0; + } + + weechat_lua_output_flush (); + + lua_eval_mode = 1; + lua_eval_send_input = send_to_buffer_as_input; + lua_eval_exec_commands = exec_commands; + lua_eval_buffer = buffer; + + func_argv[0] = (char *)code; + result = weechat_lua_exec (lua_script_eval, + WEECHAT_SCRIPT_EXEC_IGNORE, + "script_lua_eval", + "s", func_argv); + /* result is ignored */ + if (result) + free (result); + + weechat_lua_output_flush (); + + lua_eval_mode = 0; + lua_eval_send_input = 0; + lua_eval_exec_commands = 0; + lua_eval_buffer = NULL; + + if (!weechat_config_boolean (lua_config_look_eval_keep_context)) + { + lua_quiet = 1; + weechat_lua_unload (lua_script_eval); + lua_quiet = 0; + lua_script_eval = NULL; + } + + return 1; +} + +/* * Callback for command "/lua". */ @@ -630,12 +891,12 @@ weechat_lua_command_cb (const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { - char *ptr_name, *path_script; + char *ptr_name, *ptr_code, *path_script; + int i, send_to_buffer_as_input, exec_commands; /* make C compiler happy */ (void) pointer; (void) data; - (void) buffer; if (argc == 1) { @@ -667,6 +928,10 @@ weechat_lua_command_cb (const void *pointer, void *data, { weechat_lua_unload_all (); } + else if (weechat_strcasecmp (argv[1], "version") == 0) + { + plugin_script_display_interpreter (weechat_lua_plugin, 0); + } else WEECHAT_COMMAND_ERROR; } @@ -701,7 +966,8 @@ weechat_lua_command_cb (const void *pointer, void *data, /* load lua script */ path_script = plugin_script_search_path (weechat_lua_plugin, ptr_name); - weechat_lua_load ((path_script) ? path_script : ptr_name); + weechat_lua_load ((path_script) ? path_script : ptr_name, + NULL); if (path_script) free (path_script); } @@ -717,6 +983,39 @@ weechat_lua_command_cb (const void *pointer, void *data, } lua_quiet = 0; } + else if (weechat_strcasecmp (argv[1], "eval") == 0) + { + send_to_buffer_as_input = 0; + exec_commands = 0; + ptr_code = argv_eol[2]; + for (i = 2; i < argc; i++) + { + if (argv[i][0] == '-') + { + if (strcmp (argv[i], "-o") == 0) + { + if (i + 1 >= argc) + WEECHAT_COMMAND_ERROR; + send_to_buffer_as_input = 1; + exec_commands = 0; + ptr_code = argv_eol[i + 1]; + } + else if (strcmp (argv[i], "-oc") == 0) + { + if (i + 1 >= argc) + WEECHAT_COMMAND_ERROR; + send_to_buffer_as_input = 1; + exec_commands = 1; + ptr_code = argv_eol[i + 1]; + } + } + else + break; + } + if (!weechat_lua_eval (buffer, send_to_buffer_as_input, + exec_commands, ptr_code)) + WEECHAT_COMMAND_ERROR; + } else WEECHAT_COMMAND_ERROR; } @@ -763,6 +1062,29 @@ weechat_lua_hdata_cb (const void *pointer, void *data, } /* + * Returns lua info "lua_eval". + */ + +const char * +weechat_lua_info_eval_cb (const void *pointer, void *data, + const char *info_name, + const char *arguments) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) info_name; + + weechat_lua_eval (NULL, 0, 0, (arguments) ? arguments : ""); + if (lua_eval_output) + free (lua_eval_output); + lua_eval_output = strdup (*lua_buffer_output); + weechat_string_dyn_copy (lua_buffer_output, NULL); + + return lua_eval_output; +} + +/* * Returns infolist with lua scripts. */ @@ -813,31 +1135,6 @@ weechat_lua_signal_debug_dump_cb (const void *pointer, void *data, } /* - * Display infos about external libraries used. - */ - -int -weechat_lua_signal_debug_libs_cb (const void *pointer, void *data, - const char *signal, - const char *type_data, void *signal_data) -{ - /* make C compiler happy */ - (void) pointer; - (void) data; - (void) signal; - (void) type_data; - (void) signal_data; - -#ifdef LUA_VERSION - weechat_printf (NULL, " %s: %s", LUA_PLUGIN_NAME, LUA_VERSION); -#else - weechat_printf (NULL, " %s: (?)", LUA_PLUGIN_NAME); -#endif /* LUA_VERSION */ - - return WEECHAT_RC_OK; -} - -/* * Timer for executing actions. */ @@ -931,21 +1228,41 @@ weechat_lua_signal_script_action_cb (const void *pointer, void *data, int weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) { - struct t_plugin_script_init init; - weechat_lua_plugin = plugin; - init.callback_command = &weechat_lua_command_cb; - init.callback_completion = &weechat_lua_completion_cb; - init.callback_hdata = &weechat_lua_hdata_cb; - init.callback_infolist = &weechat_lua_infolist_cb; - init.callback_signal_debug_dump = &weechat_lua_signal_debug_dump_cb; - init.callback_signal_debug_libs = &weechat_lua_signal_debug_libs_cb; - init.callback_signal_script_action = &weechat_lua_signal_script_action_cb; - init.callback_load_file = &weechat_lua_load_cb; + /* set interpreter name and version */ + weechat_hashtable_set (plugin->variables, "interpreter_name", + plugin->name); +#ifdef LUA_VERSION + weechat_hashtable_set (plugin->variables, "interpreter_version", + LUA_VERSION); +#else + weechat_hashtable_set (plugin->variables, "interpreter_version", + ""); +#endif /* LUA_VERSION */ + + /* init stdout/stderr buffer */ + lua_buffer_output = weechat_string_dyn_alloc (256); + if (!lua_buffer_output) + return WEECHAT_RC_ERROR; + + lua_data.config_file = &lua_config_file; + lua_data.config_look_check_license = &lua_config_look_check_license; + lua_data.config_look_eval_keep_context = &lua_config_look_eval_keep_context; + lua_data.scripts = &lua_scripts; + lua_data.last_script = &last_lua_script; + lua_data.callback_command = &weechat_lua_command_cb; + lua_data.callback_completion = &weechat_lua_completion_cb; + lua_data.callback_hdata = &weechat_lua_hdata_cb; + lua_data.callback_info_eval = &weechat_lua_info_eval_cb; + lua_data.callback_infolist = &weechat_lua_infolist_cb; + lua_data.callback_signal_debug_dump = &weechat_lua_signal_debug_dump_cb; + lua_data.callback_signal_script_action = &weechat_lua_signal_script_action_cb; + lua_data.callback_load_file = &weechat_lua_load_cb; + lua_data.unload_all = &weechat_lua_unload_all; lua_quiet = 1; - plugin_script_init (weechat_lua_plugin, argc, argv, &init); + plugin_script_init (weechat_lua_plugin, argc, argv, &lua_data); lua_quiet = 0; plugin_script_display_short_list (weechat_lua_plugin, @@ -964,7 +1281,12 @@ weechat_plugin_end (struct t_weechat_plugin *plugin) { /* unload all scripts */ lua_quiet = 1; - plugin_script_end (plugin, &lua_scripts, &weechat_lua_unload_all); + if (lua_script_eval) + { + weechat_lua_unload (lua_script_eval); + lua_script_eval = NULL; + } + plugin_script_end (plugin, &lua_data); lua_quiet = 0; /* free some data */ @@ -974,6 +1296,9 @@ weechat_plugin_end (struct t_weechat_plugin *plugin) free (lua_action_remove_list); if (lua_action_autoload_list) free (lua_action_autoload_list); + weechat_string_dyn_free (lua_buffer_output, 1); + if (lua_eval_output) + free (lua_eval_output); return WEECHAT_RC_OK; } diff --git a/src/plugins/lua/weechat-lua.h b/src/plugins/lua/weechat-lua.h index 7a3f73cda..ffc004b10 100644 --- a/src/plugins/lua/weechat-lua.h +++ b/src/plugins/lua/weechat-lua.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2006-2007 Emmanuel Bouthenot <kolter@openics.org> - * Copyright (C) 2006-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2006-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_LUA_H -#define WEECHAT_LUA_H 1 +#ifndef WEECHAT_PLUGIN_LUA_H +#define WEECHAT_PLUGIN_LUA_H #define weechat_plugin weechat_lua_plugin #define LUA_PLUGIN_NAME "lua" @@ -35,6 +35,8 @@ struct t_lua_const extern struct t_weechat_plugin *weechat_lua_plugin; +extern struct t_plugin_script_data lua_data; + extern int lua_quiet; extern struct t_plugin_script *lua_scripts; extern struct t_plugin_script *last_lua_script; @@ -50,12 +52,13 @@ extern struct t_hashtable *weechat_lua_tohashtable (lua_State *interpreter, int size, const char *type_keys, const char *type_values); +extern int weechat_lua_output (lua_State *L); extern void *weechat_lua_exec (struct t_plugin_script *script, int ret_type, const char *function, const char *format, void **argv); -extern void weechat_lua_register_lib(lua_State *L, const char *libname, - const luaL_Reg *lua_api_funcs, - struct t_lua_const lua_api_consts[]); +extern void weechat_lua_register_lib (lua_State *L, const char *libname, + const luaL_Reg *lua_api_funcs, + struct t_lua_const lua_api_consts[]); -#endif /* WEECHAT_LUA_H */ +#endif /* WEECHAT_PLUGIN_LUA_H */ diff --git a/src/plugins/perl/CMakeLists.txt b/src/plugins/perl/CMakeLists.txt index ff9ced167..18eec779f 100644 --- a/src/plugins/perl/CMakeLists.txt +++ b/src/plugins/perl/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/perl/Makefile.am b/src/plugins/perl/Makefile.am index c52ac4b78..aa2270082 100644 --- a/src/plugins/perl/Makefile.am +++ b/src/plugins/perl/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/perl/weechat-perl-api.c b/src/plugins/perl/weechat-perl-api.c index 8e7b19569..a92f9e93b 100644 --- a/src/plugins/perl/weechat-perl-api.c +++ b/src/plugins/perl/weechat-perl-api.c @@ -1,7 +1,7 @@ /* * weechat-perl-api.c - perl API functions * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2008 Emmanuel Bouthenot <kolter@openics.org> * Copyright (C) 2012 Simon Arlott * @@ -60,6 +60,8 @@ plugin_script_str2ptr (weechat_perl_plugin, \ PERL_CURRENT_SCRIPT_NAME, \ perl_function_name, __string) +#define API_STATIC_STRING(__string) \ + plugin_script_get_static_string(&perl_data, __string); #define API_RETURN_OK XSRETURN_YES #define API_RETURN_ERROR XSRETURN_NO #define API_RETURN_EMPTY XSRETURN_EMPTY @@ -108,9 +110,6 @@ API_FUNC(register) char *charset; dXSARGS; - /* make C compiler happy */ - (void) items; - API_INIT_FUNC(0, "register", API_RETURN_ERROR); if (perl_registered_script) { @@ -149,7 +148,7 @@ API_FUNC(register) /* register script */ perl_current_script = plugin_script_add (weechat_perl_plugin, - &perl_scripts, &last_perl_script, + &perl_data, (perl_current_script_filename) ? perl_current_script_filename : "", name, author, version, license, @@ -354,6 +353,20 @@ API_FUNC(string_mask_to_regex) API_RETURN_STRING_FREE(result); } +API_FUNC(string_format_size) +{ + char *result; + dXSARGS; + + API_INIT_FUNC(1, "string_format_size", API_RETURN_EMPTY); + if (items < 1) + API_WRONG_ARGS(API_RETURN_EMPTY); + + result = weechat_string_format_size (SvUV (ST (0))); + + API_RETURN_STRING_FREE(result); +} + API_FUNC(string_remove_color) { char *result, *string, *replacement; @@ -520,7 +533,7 @@ API_FUNC(mkdir_parents) API_FUNC(list_new) { - char *result; + const char *result; dXSARGS; /* make C compiler happy */ @@ -531,12 +544,13 @@ API_FUNC(list_new) result = API_PTR2STR(weechat_list_new ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_add) { - char *result, *weelist, *data, *where, *user_data; + char *weelist, *data, *where, *user_data; + const char *result; dXSARGS; API_INIT_FUNC(1, "list_add", API_RETURN_EMPTY); @@ -553,12 +567,13 @@ API_FUNC(list_add) where, API_STR2PTR(user_data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_search) { - char *result, *weelist, *data; + char *weelist, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "list_search", API_RETURN_EMPTY); @@ -571,7 +586,7 @@ API_FUNC(list_search) result = API_PTR2STR(weechat_list_search (API_STR2PTR(weelist), data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_search_pos) @@ -594,7 +609,8 @@ API_FUNC(list_search_pos) API_FUNC(list_casesearch) { - char *result, *weelist, *data; + char *weelist, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "list_casesearch", API_RETURN_EMPTY); @@ -607,7 +623,7 @@ API_FUNC(list_casesearch) result = API_PTR2STR(weechat_list_casesearch (API_STR2PTR(weelist), data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_casesearch_pos) @@ -630,7 +646,7 @@ API_FUNC(list_casesearch_pos) API_FUNC(list_get) { - char *result; + const char *result; dXSARGS; API_INIT_FUNC(1, "list_get", API_RETURN_EMPTY); @@ -640,7 +656,7 @@ API_FUNC(list_get) result = API_PTR2STR(weechat_list_get (API_STR2PTR(SvPV_nolen (ST (0))), /* weelist */ SvIV (ST (1)))); /* position */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_set) @@ -662,7 +678,7 @@ API_FUNC(list_set) API_FUNC(list_next) { - char *result; + const char *result; dXSARGS; API_INIT_FUNC(1, "list_next", API_RETURN_EMPTY); @@ -671,12 +687,12 @@ API_FUNC(list_next) result = API_PTR2STR(weechat_list_next (API_STR2PTR(SvPV_nolen (ST (0))))); /* item */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_prev) { - char *result; + const char *result; dXSARGS; API_INIT_FUNC(1, "list_prev", API_RETURN_EMPTY); @@ -685,7 +701,7 @@ API_FUNC(list_prev) result = API_PTR2STR(weechat_list_prev (API_STR2PTR(SvPV_nolen (ST (0))))); /* item */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_string) @@ -776,7 +792,7 @@ weechat_perl_api_config_reload_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); rc = (int *) weechat_perl_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -790,8 +806,6 @@ weechat_perl_api_config_reload_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -801,7 +815,8 @@ weechat_perl_api_config_reload_cb (const void *pointer, void *data, API_FUNC(config_new) { - char *result, *name, *function, *data; + char *name, *function, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "config_new", API_RETURN_EMPTY); @@ -819,7 +834,7 @@ API_FUNC(config_new) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -841,8 +856,8 @@ weechat_perl_api_config_section_read_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); func_argv[3] = (option_name) ? (char *)option_name : empty_arg; func_argv[4] = (value) ? (char *)value : empty_arg; @@ -858,10 +873,6 @@ weechat_perl_api_config_section_read_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); return ret; } @@ -886,7 +897,7 @@ weechat_perl_api_config_section_write_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); func_argv[2] = (section_name) ? (char *)section_name : empty_arg; rc = (int *) weechat_perl_exec (script, @@ -901,8 +912,6 @@ weechat_perl_api_config_section_write_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -927,7 +936,7 @@ weechat_perl_api_config_section_write_default_cb (const void *pointer, void *dat if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); func_argv[2] = (section_name) ? (char *)section_name : empty_arg; rc = (int *) weechat_perl_exec (script, @@ -942,8 +951,6 @@ weechat_perl_api_config_section_write_default_cb (const void *pointer, void *dat ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -970,8 +977,8 @@ weechat_perl_api_config_section_create_option_cb (const void *pointer, void *dat if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); func_argv[3] = (option_name) ? (char *)option_name : empty_arg; func_argv[4] = (value) ? (char *)value : empty_arg; @@ -987,10 +994,6 @@ weechat_perl_api_config_section_create_option_cb (const void *pointer, void *dat ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); return ret; } @@ -1016,9 +1019,9 @@ weechat_perl_api_config_section_delete_option_cb (const void *pointer, void *dat if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); - func_argv[3] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); + func_argv[3] = (char *)API_PTR2STR(option); rc = (int *) weechat_perl_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -1032,12 +1035,6 @@ weechat_perl_api_config_section_delete_option_cb (const void *pointer, void *dat ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -1047,10 +1044,11 @@ weechat_perl_api_config_section_delete_option_cb (const void *pointer, void *dat API_FUNC(config_new_section) { - char *result, *cfg_file, *name, *function_read, *data_read; + char *cfg_file, *name, *function_read, *data_read; char *function_write, *data_write, *function_write_default; char *data_write_default, *function_create_option, *data_create_option; char *function_delete_option, *data_delete_option; + const char *result; dXSARGS; @@ -1095,12 +1093,13 @@ API_FUNC(config_new_section) function_delete_option, data_delete_option)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_search_section) { - char *result, *config_file, *section_name; + char *config_file, *section_name; + const char *result; dXSARGS; API_INIT_FUNC(1, "config_search_section", API_RETURN_EMPTY); @@ -1113,7 +1112,7 @@ API_FUNC(config_search_section) result = API_PTR2STR(weechat_config_search_section (API_STR2PTR(config_file), section_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -1133,7 +1132,7 @@ weechat_perl_api_config_option_check_value_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); func_argv[2] = (value) ? (char *)value : empty_arg; rc = (int *) weechat_perl_exec (script, @@ -1148,8 +1147,6 @@ weechat_perl_api_config_option_check_value_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -1173,16 +1170,13 @@ weechat_perl_api_config_option_change_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); rc = (int *) weechat_perl_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, "ss", func_argv); - if (func_argv[1]) - free (func_argv[1]); - if (rc) free (rc); } @@ -1204,16 +1198,13 @@ weechat_perl_api_config_option_delete_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); rc = (int *) weechat_perl_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, "ss", func_argv); - if (func_argv[1]) - free (func_argv[1]); - if (rc) free (rc); } @@ -1221,10 +1212,11 @@ weechat_perl_api_config_option_delete_cb (const void *pointer, void *data, API_FUNC(config_new_option) { - char *result, *config_file, *section, *name, *type; + char *config_file, *section, *name, *type; char *description, *string_values, *default_value, *value; char *function_check_value, *data_check_value, *function_change; char *data_change, *function_delete, *data_delete; + const char *result; dXSARGS; API_INIT_FUNC(1, "config_new_option", API_RETURN_EMPTY); @@ -1269,12 +1261,13 @@ API_FUNC(config_new_option) function_delete, data_delete)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_search_option) { - char *result, *config_file, *section, *option_name; + char *config_file, *section, *option_name; + const char *result; dXSARGS; API_INIT_FUNC(1, "config_search_option", API_RETURN_EMPTY); @@ -1289,7 +1282,7 @@ API_FUNC(config_search_option) API_STR2PTR(section), option_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_string_to_boolean) @@ -1672,7 +1665,7 @@ API_FUNC(config_free) API_FUNC(config_get) { - char *result; + const char *result; dXSARGS; API_INIT_FUNC(1, "config_get", API_RETURN_EMPTY); @@ -1681,7 +1674,7 @@ API_FUNC(config_get) result = API_PTR2STR(weechat_config_get (SvPV_nolen (ST (0)))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_get_plugin) @@ -1950,7 +1943,7 @@ weechat_perl_api_hook_command_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (argc > 1) ? argv_eol[1] : empty_arg; rc = (int *) weechat_perl_exec (script, @@ -1965,8 +1958,6 @@ weechat_perl_api_hook_command_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -1976,8 +1967,9 @@ weechat_perl_api_hook_command_cb (const void *pointer, void *data, API_FUNC(hook_command) { - char *result, *command, *description, *args, *args_description; + char *command, *description, *args, *args_description; char *completion, *function, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "hook_command", API_RETURN_EMPTY); @@ -2003,7 +1995,7 @@ API_FUNC(hook_command) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2025,8 +2017,8 @@ weechat_perl_api_hook_completion_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (completion_item) ? (char *)completion_item : empty_arg; - func_argv[2] = API_PTR2STR(buffer); - func_argv[3] = API_PTR2STR(completion); + func_argv[2] = (char *)API_PTR2STR(buffer); + func_argv[3] = (char *)API_PTR2STR(completion); rc = (int *) weechat_perl_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -2040,10 +2032,6 @@ weechat_perl_api_hook_completion_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -2053,7 +2041,8 @@ weechat_perl_api_hook_completion_cb (const void *pointer, void *data, API_FUNC(hook_completion) { - char *result, *completion, *description, *function, *data; + char *completion, *description, *function, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "hook_completion", API_RETURN_EMPTY); @@ -2073,7 +2062,7 @@ API_FUNC(hook_completion) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_completion_get_string) @@ -2133,7 +2122,7 @@ weechat_perl_api_hook_command_run_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (command) ? (char *)command : empty_arg; rc = (int *) weechat_perl_exec (script, @@ -2148,8 +2137,6 @@ weechat_perl_api_hook_command_run_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -2159,7 +2146,8 @@ weechat_perl_api_hook_command_run_cb (const void *pointer, void *data, API_FUNC(hook_command_run) { - char *result, *command, *function, *data; + char *command, *function, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "hook_command_run", API_RETURN_EMPTY); @@ -2177,7 +2165,7 @@ API_FUNC(hook_command_run) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2222,7 +2210,7 @@ weechat_perl_api_hook_timer_cb (const void *pointer, void *data, API_FUNC(hook_timer) { - char *result; + const char *result; dXSARGS; API_INIT_FUNC(1, "hook_timer", API_RETURN_EMPTY); @@ -2238,7 +2226,7 @@ API_FUNC(hook_timer) SvPV_nolen (ST (3)), /* perl function */ SvPV_nolen (ST (4)))); /* data */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2246,7 +2234,7 @@ weechat_perl_api_hook_fd_cb (const void *pointer, void *data, int fd) { struct t_plugin_script *script; void *func_argv[2]; - char str_fd[32], empty_arg[1] = { '\0' }; + char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; int *rc, ret; @@ -2255,15 +2243,13 @@ weechat_perl_api_hook_fd_cb (const void *pointer, void *data, int fd) if (ptr_function && ptr_function[0]) { - snprintf (str_fd, sizeof (str_fd), "%d", fd); - func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = str_fd; + func_argv[1] = &fd; rc = (int *) weechat_perl_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "ss", func_argv); + "si", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2281,7 +2267,7 @@ weechat_perl_api_hook_fd_cb (const void *pointer, void *data, int fd) API_FUNC(hook_fd) { - char *result; + const char *result; dXSARGS; API_INIT_FUNC(1, "hook_fd", API_RETURN_EMPTY); @@ -2298,7 +2284,7 @@ API_FUNC(hook_fd) SvPV_nolen (ST (4)), /* perl function */ SvPV_nolen (ST (5)))); /* data */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2363,7 +2349,8 @@ weechat_perl_api_hook_process_cb (const void *pointer, void *data, API_FUNC(hook_process) { - char *command, *function, *data, *result; + char *command, *function, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "hook_process", API_RETURN_EMPTY); @@ -2382,12 +2369,13 @@ API_FUNC(hook_process) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_process_hashtable) { - char *command, *function, *data, *result; + char *command, *function, *data; + const char *result; struct t_hashtable *options; dXSARGS; @@ -2415,7 +2403,7 @@ API_FUNC(hook_process_hashtable) if (options) weechat_hashtable_free (options); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2426,7 +2414,6 @@ weechat_perl_api_hook_connect_cb (const void *pointer, void *data, { struct t_plugin_script *script; void *func_argv[6]; - char str_status[32], str_gnutls_rc[32], str_sock[32]; char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; int *rc, ret; @@ -2436,21 +2423,17 @@ weechat_perl_api_hook_connect_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { - snprintf (str_status, sizeof (str_status), "%d", status); - snprintf (str_gnutls_rc, sizeof (str_gnutls_rc), "%d", gnutls_rc); - snprintf (str_sock, sizeof (str_sock), "%d", sock); - func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = str_status; - func_argv[2] = str_gnutls_rc; - func_argv[3] = str_sock; + func_argv[1] = &status; + func_argv[2] = &gnutls_rc; + func_argv[3] = &sock; func_argv[4] = (ip_address) ? (char *)ip_address : empty_arg; func_argv[5] = (error) ? (char *)error : empty_arg; rc = (int *) weechat_perl_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "ssssss", func_argv); + "siiiss", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2468,7 +2451,8 @@ weechat_perl_api_hook_connect_cb (const void *pointer, void *data, API_FUNC(hook_connect) { - char *proxy, *address, *local_hostname, *function, *data, *result; + char *proxy, *address, *local_hostname, *function, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "hook_connect", API_RETURN_EMPTY); @@ -2497,7 +2481,7 @@ API_FUNC(hook_connect) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2523,10 +2507,10 @@ weechat_perl_api_hook_print_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { - snprintf (timebuffer, sizeof (timebuffer), "%ld", (long int)date); + snprintf (timebuffer, sizeof (timebuffer), "%lld", (long long)date); func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = timebuffer; func_argv[3] = weechat_string_build_with_split_string (tags, ","); if (!func_argv[3]) @@ -2548,8 +2532,6 @@ weechat_perl_api_hook_print_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); if (func_argv[3]) free (func_argv[3]); @@ -2561,7 +2543,8 @@ weechat_perl_api_hook_print_cb (const void *pointer, void *data, API_FUNC(hook_print) { - char *result, *buffer, *tags, *message, *function, *data; + char *buffer, *tags, *message, *function, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "hook_print", API_RETURN_EMPTY); @@ -2584,7 +2567,7 @@ API_FUNC(hook_print) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2597,7 +2580,7 @@ weechat_perl_api_hook_signal_cb (const void *pointer, void *data, char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; static char str_value[64]; - int *rc, ret, free_needed; + int *rc, ret; script = (struct t_plugin_script *)pointer; plugin_script_get_function_and_data (data, &ptr_function, &ptr_data); @@ -2606,7 +2589,6 @@ weechat_perl_api_hook_signal_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (signal) ? (char *)signal : empty_arg; - free_needed = 0; if (strcmp (type_data, WEECHAT_HOOK_SIGNAL_STRING) == 0) { func_argv[2] = (signal_data) ? (char *)signal_data : empty_arg; @@ -2623,8 +2605,7 @@ weechat_perl_api_hook_signal_cb (const void *pointer, void *data, } else if (strcmp (type_data, WEECHAT_HOOK_SIGNAL_POINTER) == 0) { - func_argv[2] = API_PTR2STR(signal_data); - free_needed = 1; + func_argv[2] = (char *)API_PTR2STR(signal_data); } else func_argv[2] = empty_arg; @@ -2641,8 +2622,6 @@ weechat_perl_api_hook_signal_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (free_needed && func_argv[2]) - free (func_argv[2]); return ret; } @@ -2652,7 +2631,8 @@ weechat_perl_api_hook_signal_cb (const void *pointer, void *data, API_FUNC(hook_signal) { - char *result, *signal, *function, *data; + char *signal, *function, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "hook_signal", API_RETURN_EMPTY); @@ -2670,7 +2650,7 @@ API_FUNC(hook_signal) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_signal_send) @@ -2752,7 +2732,8 @@ weechat_perl_api_hook_hsignal_cb (const void *pointer, void *data, API_FUNC(hook_hsignal) { - char *result, *signal, *function, *data; + char *signal, *function, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "hook_hsignal", API_RETURN_EMPTY); @@ -2770,7 +2751,7 @@ API_FUNC(hook_hsignal) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_hsignal_send) @@ -2838,7 +2819,8 @@ weechat_perl_api_hook_config_cb (const void *pointer, void *data, API_FUNC(hook_config) { - char *result, *option, *function, *data; + char *option, *function, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "hook_config", API_RETURN_EMPTY); @@ -2856,7 +2838,7 @@ API_FUNC(hook_config) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } char * @@ -2891,7 +2873,8 @@ weechat_perl_api_hook_modifier_cb (const void *pointer, void *data, API_FUNC(hook_modifier) { - char *result, *modifier, *function, *data; + char *modifier, *function, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "hook_modifier", API_RETURN_EMPTY); @@ -2909,7 +2892,7 @@ API_FUNC(hook_modifier) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_modifier_exec) @@ -2937,7 +2920,7 @@ weechat_perl_api_hook_info_cb (const void *pointer, void *data, { struct t_plugin_script *script; void *func_argv[3]; - char empty_arg[1] = { '\0' }; + char empty_arg[1] = { '\0' }, *result; const char *ptr_function, *ptr_data; script = (struct t_plugin_script *)pointer; @@ -2949,10 +2932,12 @@ weechat_perl_api_hook_info_cb (const void *pointer, void *data, func_argv[1] = (info_name) ? (char *)info_name : empty_arg; func_argv[2] = (arguments) ? (char *)arguments : empty_arg; - return (const char *)weechat_perl_exec (script, - WEECHAT_SCRIPT_EXEC_STRING, - ptr_function, - "sss", func_argv); + result = (char *)weechat_perl_exec (script, + WEECHAT_SCRIPT_EXEC_STRING, + ptr_function, + "sss", func_argv); + + return API_STATIC_STRING(result); } return NULL; @@ -2960,7 +2945,8 @@ weechat_perl_api_hook_info_cb (const void *pointer, void *data, API_FUNC(hook_info) { - char *result, *info_name, *description, *args_description, *function, *data; + char *info_name, *description, *args_description, *function, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "hook_info", API_RETURN_EMPTY); @@ -2982,7 +2968,7 @@ API_FUNC(hook_info) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_hashtable * @@ -3016,8 +3002,9 @@ weechat_perl_api_hook_info_hashtable_cb (const void *pointer, void *data, API_FUNC(hook_info_hashtable) { - char *result, *info_name, *description, *args_description; + char *info_name, *description, *args_description; char *output_description, *function, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "hook_info_hashtable", API_RETURN_EMPTY); @@ -3041,7 +3028,7 @@ API_FUNC(hook_info_hashtable) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_infolist * @@ -3062,18 +3049,15 @@ weechat_perl_api_hook_infolist_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (infolist_name) ? (char *)infolist_name : empty_arg; - func_argv[2] = API_PTR2STR(obj_pointer); + func_argv[2] = (char *)API_PTR2STR(obj_pointer); func_argv[3] = (arguments) ? (char *)arguments : empty_arg; result = (struct t_infolist *)weechat_perl_exec ( script, - WEECHAT_SCRIPT_EXEC_STRING, + WEECHAT_SCRIPT_EXEC_POINTER, ptr_function, "ssss", func_argv); - if (func_argv[2]) - free (func_argv[2]); - return result; } @@ -3082,8 +3066,9 @@ weechat_perl_api_hook_infolist_cb (const void *pointer, void *data, API_FUNC(hook_infolist) { - char *result, *infolist_name, *description, *pointer_description; + char *infolist_name, *description, *pointer_description; char *args_description, *function, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "hook_infolist", API_RETURN_EMPTY); @@ -3107,7 +3092,7 @@ API_FUNC(hook_infolist) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_hashtable * @@ -3139,7 +3124,8 @@ weechat_perl_api_hook_focus_cb (const void *pointer, void *data, API_FUNC(hook_focus) { - char *result, *area, *function, *data; + char *area, *function, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "hook_focus", API_RETURN_EMPTY); @@ -3157,7 +3143,7 @@ API_FUNC(hook_focus) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_set) @@ -3223,7 +3209,7 @@ weechat_perl_api_buffer_input_data_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (input_data) ? (char *)input_data : empty_arg; rc = (int *) weechat_perl_exec (script, @@ -3237,8 +3223,6 @@ weechat_perl_api_buffer_input_data_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -3262,7 +3246,7 @@ weechat_perl_api_buffer_close_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); rc = (int *) weechat_perl_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -3275,8 +3259,6 @@ weechat_perl_api_buffer_close_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -3286,8 +3268,8 @@ weechat_perl_api_buffer_close_cb (const void *pointer, void *data, API_FUNC(buffer_new) { - char *result, *name, *function_input, *data_input, *function_close; - char *data_close; + char *name, *function_input, *data_input, *function_close, *data_close; + const char *result; dXSARGS; API_INIT_FUNC(1, "buffer_new", API_RETURN_EMPTY); @@ -3310,12 +3292,13 @@ API_FUNC(buffer_new) function_close, data_close)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_search) { - char *result, *plugin, *name; + char *plugin, *name; + const char *result; dXSARGS; API_INIT_FUNC(1, "buffer_search", API_RETURN_EMPTY); @@ -3327,12 +3310,12 @@ API_FUNC(buffer_search) result = API_PTR2STR(weechat_buffer_search (plugin, name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_search_main) { - char *result; + const char *result; dXSARGS; /* make C compiler happy */ @@ -3343,12 +3326,12 @@ API_FUNC(buffer_search_main) result = API_PTR2STR(weechat_buffer_search_main ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(current_buffer) { - char *result; + const char *result; dXSARGS; /* make C compiler happy */ @@ -3359,7 +3342,7 @@ API_FUNC(current_buffer) result = API_PTR2STR(weechat_current_buffer ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_clear) @@ -3454,7 +3437,8 @@ API_FUNC(buffer_get_string) API_FUNC(buffer_get_pointer) { - char *result, *buffer, *property; + char *buffer, *property; + const char *result; dXSARGS; API_INIT_FUNC(1, "buffer_get_pointer", API_RETURN_EMPTY); @@ -3467,7 +3451,7 @@ API_FUNC(buffer_get_pointer) result = API_PTR2STR(weechat_buffer_get_pointer (API_STR2PTR(buffer), property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_set) @@ -3525,7 +3509,7 @@ API_FUNC(buffer_match_list) API_FUNC(current_window) { - char *result; + const char *result; dXSARGS; /* make C compiler happy */ @@ -3536,12 +3520,12 @@ API_FUNC(current_window) result = API_PTR2STR(weechat_current_window ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(window_search_with_buffer) { - char *result; + const char *result; dXSARGS; API_INIT_FUNC(1, "window_search_with_buffer", API_RETURN_EMPTY); @@ -3550,7 +3534,7 @@ API_FUNC(window_search_with_buffer) result = API_PTR2STR(weechat_window_search_with_buffer (API_STR2PTR(SvPV_nolen (ST (0))))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } @@ -3592,7 +3576,8 @@ API_FUNC(window_get_string) API_FUNC(window_get_pointer) { - char *result, *window, *property; + char *window, *property; + const char *result; dXSARGS; API_INIT_FUNC(1, "window_get_pointer", API_RETURN_EMPTY); @@ -3605,7 +3590,7 @@ API_FUNC(window_get_pointer) result = API_PTR2STR(weechat_window_get_pointer (API_STR2PTR(window), property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(window_set_title) @@ -3623,7 +3608,8 @@ API_FUNC(window_set_title) API_FUNC(nicklist_add_group) { - char *result, *buffer, *parent_group, *name, *color; + char *buffer, *parent_group, *name, *color; + const char *result; dXSARGS; API_INIT_FUNC(1, "nicklist_add_group", API_RETURN_EMPTY); @@ -3641,12 +3627,13 @@ API_FUNC(nicklist_add_group) color, SvIV (ST (4)))); /* visible */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_search_group) { - char *result, *buffer, *from_group, *name; + char *buffer, *from_group, *name; + const char *result; dXSARGS; API_INIT_FUNC(1, "nicklist_search_group", API_RETURN_EMPTY); @@ -3661,12 +3648,13 @@ API_FUNC(nicklist_search_group) API_STR2PTR(from_group), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_add_nick) { - char *result, *buffer, *group, *name, *color, *prefix, *prefix_color; + char *buffer, *group, *name, *color, *prefix, *prefix_color; + const char *result; dXSARGS; API_INIT_FUNC(1, "nicklist_add_nick", API_RETURN_EMPTY); @@ -3688,12 +3676,13 @@ API_FUNC(nicklist_add_nick) prefix_color, SvIV (ST (6)))); /* visible */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_search_nick) { - char *result, *buffer, *from_group, *name; + char *buffer, *from_group, *name; + const char *result; dXSARGS; API_INIT_FUNC(1, "nicklist_search_nick", API_RETURN_EMPTY); @@ -3708,7 +3697,7 @@ API_FUNC(nicklist_search_nick) API_STR2PTR(from_group), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_remove_group) @@ -3804,7 +3793,8 @@ API_FUNC(nicklist_group_get_string) API_FUNC(nicklist_group_get_pointer) { - char *result, *buffer, *group, *property; + char *buffer, *group, *property; + const char *result; dXSARGS; API_INIT_FUNC(1, "nicklist_group_get_pointer", API_RETURN_EMPTY); @@ -3819,7 +3809,7 @@ API_FUNC(nicklist_group_get_pointer) API_STR2PTR(group), property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_group_set) @@ -3888,7 +3878,8 @@ API_FUNC(nicklist_nick_get_string) API_FUNC(nicklist_nick_get_pointer) { - char *result, *buffer, *nick, *property; + char *buffer, *nick, *property; + const char *result; dXSARGS; API_INIT_FUNC(1, "nicklist_nick_get_pointer", API_RETURN_EMPTY); @@ -3903,7 +3894,7 @@ API_FUNC(nicklist_nick_get_pointer) API_STR2PTR(nick), property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_nick_set) @@ -3930,7 +3921,7 @@ API_FUNC(nicklist_nick_set) API_FUNC(bar_item_search) { - char *result; + const char *result; dXSARGS; API_INIT_FUNC(1, "bar_item_search", API_RETURN_EMPTY); @@ -3939,7 +3930,7 @@ API_FUNC(bar_item_search) result = API_PTR2STR(weechat_bar_item_search (SvPV_nolen (ST (0)))); /* name */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } char * @@ -3963,39 +3954,27 @@ weechat_perl_api_bar_item_build_cb (const void *pointer, void *data, { /* new callback: data, item, window, buffer, extra_info */ func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(item); - func_argv[2] = API_PTR2STR(window); - func_argv[3] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(item); + func_argv[2] = (char *)API_PTR2STR(window); + func_argv[3] = (char *)API_PTR2STR(buffer); func_argv[4] = extra_info; ret = (char *)weechat_perl_exec (script, WEECHAT_SCRIPT_EXEC_STRING, ptr_function + 7, "ssssh", func_argv); - - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); } else { /* old callback: data, item, window */ func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(item); - func_argv[2] = API_PTR2STR(window); + func_argv[1] = (char *)API_PTR2STR(item); + func_argv[2] = (char *)API_PTR2STR(window); ret = (char *)weechat_perl_exec (script, WEECHAT_SCRIPT_EXEC_STRING, ptr_function, "sss", func_argv); - - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); } return ret; @@ -4006,7 +3985,8 @@ weechat_perl_api_bar_item_build_cb (const void *pointer, void *data, API_FUNC(bar_item_new) { - char *result, *name, *function, *data; + char *name, *function, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "bar_item_new", API_RETURN_EMPTY); @@ -4024,7 +4004,7 @@ API_FUNC(bar_item_new) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(bar_item_update) @@ -4055,7 +4035,7 @@ API_FUNC(bar_item_remove) API_FUNC(bar_search) { - char *result; + const char *result; dXSARGS; API_INIT_FUNC(1, "bar_search", API_RETURN_EMPTY); @@ -4064,14 +4044,15 @@ API_FUNC(bar_search) result = API_PTR2STR(weechat_bar_search (SvPV_nolen (ST (0)))); /* name */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(bar_new) { - char *result, *name, *hidden, *priority, *type, *conditions, *position; + char *name, *hidden, *priority, *type, *conditions, *position; char *filling_top_bottom, *filling_left_right, *size, *size_max, *color_fg; char *color_delim, *color_bg, *separator, *bar_items; + const char *result; dXSARGS; API_INIT_FUNC(1, "bar_new", API_RETURN_EMPTY); @@ -4110,7 +4091,7 @@ API_FUNC(bar_new) separator, bar_items)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(bar_set) @@ -4227,7 +4208,7 @@ API_FUNC(info_get_hashtable) API_FUNC(infolist_new) { - char *result; + const char *result; dXSARGS; /* make C compiler happy */ @@ -4238,12 +4219,13 @@ API_FUNC(infolist_new) result = API_PTR2STR(weechat_infolist_new ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_item) { - char *infolist, *result; + char *infolist; + const char *result; dXSARGS; API_INIT_FUNC(1, "infolist_new_item", API_RETURN_EMPTY); @@ -4254,12 +4236,13 @@ API_FUNC(infolist_new_item) result = API_PTR2STR(weechat_infolist_new_item (API_STR2PTR(infolist))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_integer) { - char *item, *name, *result; + char *item, *name; + const char *result; dXSARGS; API_INIT_FUNC(1, "infolist_new_var_integer", API_RETURN_EMPTY); @@ -4273,12 +4256,13 @@ API_FUNC(infolist_new_var_integer) name, SvIV (ST (2)))); /* value */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_string) { - char *item, *name, *value, *result; + char *item, *name, *value; + const char *result; dXSARGS; API_INIT_FUNC(1, "infolist_new_var_string", API_RETURN_EMPTY); @@ -4293,12 +4277,13 @@ API_FUNC(infolist_new_var_string) name, value)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_pointer) { - char *item, *name, *value, *result; + char *item, *name, *value; + const char *result; dXSARGS; API_INIT_FUNC(1, "infolist_new_var_pointer", API_RETURN_EMPTY); @@ -4313,12 +4298,13 @@ API_FUNC(infolist_new_var_pointer) name, API_STR2PTR(value))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_time) { - char *item, *name, *result; + char *item, *name; + const char *result; dXSARGS; API_INIT_FUNC(1, "infolist_new_var_time", API_RETURN_EMPTY); @@ -4332,12 +4318,13 @@ API_FUNC(infolist_new_var_time) name, SvIV (ST (2)))); /* value */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_search_var) { - char *infolist, *name, *result; + char *infolist, *name; + const char *result; dXSARGS; API_INIT_FUNC(1, "infolist_search_var", API_RETURN_EMPTY); @@ -4350,12 +4337,13 @@ API_FUNC(infolist_search_var) result = API_PTR2STR(weechat_infolist_search_var (API_STR2PTR(infolist), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_get) { - char *result, *name, *pointer, *arguments; + char *name, *pointer, *arguments; + const char *result; dXSARGS; API_INIT_FUNC(1, "infolist_get", API_RETURN_EMPTY); @@ -4370,7 +4358,7 @@ API_FUNC(infolist_get) API_STR2PTR(pointer), arguments)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_next) @@ -4467,7 +4455,7 @@ API_FUNC(infolist_string) API_FUNC(infolist_pointer) { char *infolist, *variable; - char *result; + const char *result; dXSARGS; API_INIT_FUNC(1, "infolist_pointer", API_RETURN_EMPTY); @@ -4479,31 +4467,25 @@ API_FUNC(infolist_pointer) result = API_PTR2STR(weechat_infolist_pointer (API_STR2PTR(infolist), variable)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_time) { time_t time; - struct tm *date_tmp; - char timebuffer[64], *result, *infolist, *variable; + char *infolist, *variable; dXSARGS; - API_INIT_FUNC(1, "infolist_time", API_RETURN_EMPTY); + API_INIT_FUNC(1, "infolist_time", API_RETURN_LONG(0)); if (items < 2) - API_WRONG_ARGS(API_RETURN_EMPTY); + API_WRONG_ARGS(API_RETURN_LONG(0)); infolist = SvPV_nolen (ST (0)); variable = SvPV_nolen (ST (1)); - timebuffer[0] = '\0'; time = weechat_infolist_time (API_STR2PTR(infolist), variable); - date_tmp = localtime (&time); - if (date_tmp) - strftime (timebuffer, sizeof (timebuffer), "%F %T", date_tmp); - result = strdup (timebuffer); - API_RETURN_STRING_FREE(result); + API_RETURN_LONG(time); } API_FUNC(infolist_free) @@ -4521,7 +4503,8 @@ API_FUNC(infolist_free) API_FUNC(hdata_get) { - char *result, *name; + char *name; + const char *result; dXSARGS; API_INIT_FUNC(1, "hdata_get", API_RETURN_EMPTY); @@ -4532,7 +4515,7 @@ API_FUNC(hdata_get) result = API_PTR2STR(weechat_hdata_get (name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_get_var_offset) @@ -4634,7 +4617,7 @@ API_FUNC(hdata_get_var_hdata) API_FUNC(hdata_get_list) { char *hdata, *name; - char *result; + const char *result; dXSARGS; API_INIT_FUNC(1, "hdata_get_list", API_RETURN_EMPTY); @@ -4647,7 +4630,7 @@ API_FUNC(hdata_get_list) result = API_PTR2STR(weechat_hdata_get_list (API_STR2PTR(hdata), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_check_pointer) @@ -4673,7 +4656,8 @@ API_FUNC(hdata_check_pointer) API_FUNC(hdata_move) { - char *result, *hdata, *pointer; + char *hdata, *pointer; + const char *result; int count; dXSARGS; @@ -4689,12 +4673,13 @@ API_FUNC(hdata_move) API_STR2PTR(pointer), count)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_search) { - char *result, *hdata, *pointer, *search; + char *hdata, *pointer, *search; + const char *result; int move; dXSARGS; @@ -4712,7 +4697,7 @@ API_FUNC(hdata_search) search, move)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_char) @@ -4802,7 +4787,7 @@ API_FUNC(hdata_string) API_FUNC(hdata_pointer) { char *hdata, *pointer, *name; - char *result; + const char *result; dXSARGS; API_INIT_FUNC(1, "hdata_pointer", API_RETURN_EMPTY); @@ -4817,7 +4802,7 @@ API_FUNC(hdata_pointer) API_STR2PTR(pointer), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_time) @@ -4952,9 +4937,9 @@ weechat_perl_api_upgrade_read_cb (const void *pointer, void *data, snprintf (str_object_id, sizeof (str_object_id), "%d", object_id); func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(upgrade_file); + func_argv[1] = (char *)API_PTR2STR(upgrade_file); func_argv[2] = str_object_id; - func_argv[3] = API_PTR2STR(infolist); + func_argv[3] = (char *)API_PTR2STR(infolist); rc = (int *) weechat_perl_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -4968,10 +4953,6 @@ weechat_perl_api_upgrade_read_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -4981,7 +4962,8 @@ weechat_perl_api_upgrade_read_cb (const void *pointer, void *data, API_FUNC(upgrade_new) { - char *result, *filename, *function, *data; + char *filename, *function, *data; + const char *result; dXSARGS; API_INIT_FUNC(1, "upgrade_new", API_RETURN_EMPTY); @@ -5001,7 +4983,7 @@ API_FUNC(upgrade_new) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(upgrade_write_object) @@ -5067,6 +5049,7 @@ weechat_perl_api_init (pTHX) HV *stash; newXS ("DynaLoader::boot_DynaLoader", boot_DynaLoader, __FILE__); + newXS ("weechat::__output__", weechat_perl_output, "weechat"); /* interface functions */ API_DEF_FUNC(register); @@ -5081,6 +5064,7 @@ weechat_perl_api_init (pTHX) API_DEF_FUNC(string_has_highlight); API_DEF_FUNC(string_has_highlight_regex); API_DEF_FUNC(string_mask_to_regex); + API_DEF_FUNC(string_format_size); API_DEF_FUNC(string_remove_color); API_DEF_FUNC(string_is_command_char); API_DEF_FUNC(string_input_for_buffer); diff --git a/src/plugins/perl/weechat-perl-api.h b/src/plugins/perl/weechat-perl-api.h index b37b95db0..bd9012487 100644 --- a/src/plugins/perl/weechat-perl-api.h +++ b/src/plugins/perl/weechat-perl-api.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_PERL_API_H -#define WEECHAT_PERL_API_H 1 +#ifndef WEECHAT_PLUGIN_PERL_API_H +#define WEECHAT_PLUGIN_PERL_API_H extern int weechat_perl_api_buffer_input_data_cb (const void *pointer, void *data, @@ -29,4 +29,4 @@ extern int weechat_perl_api_buffer_close_cb (const void *pointer, struct t_gui_buffer *buffer); extern void weechat_perl_api_init (pTHX); -#endif /* WEECHAT_PERL_API_H */ +#endif /* WEECHAT_PLUGIN_PERL_API_H */ diff --git a/src/plugins/perl/weechat-perl.c b/src/plugins/perl/weechat-perl.c index dda133d5e..846a0ae6f 100644 --- a/src/plugins/perl/weechat-perl.c +++ b/src/plugins/perl/weechat-perl.c @@ -1,7 +1,7 @@ /* * weechat-perl.c - perl plugin for WeeChat * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2008 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -37,11 +37,31 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Support of perl scripts")); WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(3000); +WEECHAT_PLUGIN_PRIORITY(4000); struct t_weechat_plugin *weechat_perl_plugin = NULL; +struct t_plugin_script_data perl_data; + +struct t_config_file *perl_config_file = NULL; +struct t_config_option *perl_config_look_check_license = NULL; +struct t_config_option *perl_config_look_eval_keep_context = NULL; + int perl_quiet = 0; + +struct t_plugin_script *perl_script_eval = NULL; +int perl_eval_mode = 0; +int perl_eval_send_input = 0; +int perl_eval_exec_commands = 0; +struct t_gui_buffer *perl_eval_buffer = NULL; +char *perl_eval_output = NULL; +#define PERL_EVAL_SCRIPT \ + "sub script_perl_eval {\n" \ + " eval \"$_[0]\";\n" \ + "}\n" \ + "weechat::register('" WEECHAT_SCRIPT_EVAL_NAME "', '', '1.0', " \ + "'" WEECHAT_LICENSE "', 'Evaluation of source code', '', '');\n" + struct t_plugin_script *perl_scripts = NULL; struct t_plugin_script *last_perl_script = NULL; struct t_plugin_script *perl_current_script = NULL; @@ -51,6 +71,7 @@ const char *perl_current_script_filename = NULL; PerlInterpreter *perl_current_interpreter = NULL; #endif /* MULTIPLICITY */ int perl_quit_or_upgrade = 0; +char **perl_buffer_output = NULL; /* * string used to execute action "install": @@ -94,9 +115,21 @@ char *perl_weechat_code = #ifndef MULTIPLICITY "package %s;" #endif /* MULTIPLICITY */ - "$SIG{__WARN__} = sub { weechat::print('', 'perl\twarning: '.$_[0]) };" - "$SIG{__DIE__} = sub { weechat::print('', 'perl\terror: '.$_[0]) };" - "do '%s';" + "$SIG{__WARN__} = sub { weechat::print('', '%s '.$_[0]); };" + "$SIG{__DIE__} = sub { weechat::print('', '%s '.$_[0]); };" + "tie(*STDOUT, 'weechat_output');" + "tie(*STDERR, 'weechat_output');" + "do %s%s%s" + "package weechat_output;" + "sub TIEHANDLE { bless {}; }" + "sub PRINT {" + " weechat::__output__($_[1]);" + "}" + "sub PRINTF {" + " my $self = shift;" + " my $fmt = shift;" + " weechat::__output__(sprintf($fmt, @_));" + "}" }; /* @@ -186,6 +219,95 @@ weechat_perl_hash_to_hashtable (SV *hash, int size, const char *type_keys, } /* + * Flushes output. + */ + +void +weechat_perl_output_flush () +{ + const char *ptr_command; + char *command; + int length; + + if (!*perl_buffer_output[0]) + return; + + if (perl_eval_mode) + { + /* if there's no buffer, we catch the output, so there's no flush */ + if (!perl_eval_buffer) + return; + + if (perl_eval_send_input) + { + if (perl_eval_exec_commands) + ptr_command = *perl_buffer_output; + else + ptr_command = weechat_string_input_for_buffer (*perl_buffer_output); + if (ptr_command) + { + weechat_command (perl_eval_buffer, *perl_buffer_output); + } + else + { + length = 1 + strlen (*perl_buffer_output) + 1; + command = malloc (length); + if (command) + { + snprintf (command, length, "%c%s", + *perl_buffer_output[0], *perl_buffer_output); + weechat_command (perl_eval_buffer, + (command[0]) ? command : " "); + free (command); + } + } + } + else + { + weechat_printf (perl_eval_buffer, "%s", *perl_buffer_output); + } + } + else + { + /* script (no eval mode) */ + weechat_printf ( + NULL, + weechat_gettext ("%s: stdout/stderr (%s): %s"), + PERL_PLUGIN_NAME, + (perl_current_script) ? perl_current_script->name : "?", + *perl_buffer_output); + } + + weechat_string_dyn_copy (perl_buffer_output, NULL); +} + +/* + * Redirection for stdout and stderr. + */ + +XS (weechat_perl_output) +{ + char *msg, *ptr_msg, *ptr_newline, *message; + dXSARGS; + + if (items < 1) + return; + + msg = SvPV_nolen (ST (0)); + ptr_msg = msg; + while ((ptr_newline = strchr (ptr_msg, '\n')) != NULL) + { + message = weechat_strndup (ptr_msg, ptr_newline - ptr_msg); + weechat_string_dyn_concat (perl_buffer_output, message); + if (message) + free (message); + weechat_perl_output_flush (); + ptr_msg = ++ptr_newline; + } + weechat_string_dyn_concat (perl_buffer_output, ptr_msg); +} + +/* * Executes a perl function. */ @@ -238,14 +360,14 @@ weechat_perl_exec (struct t_plugin_script *script, switch (format[i]) { case 's': /* string */ - XPUSHs(sv_2mortal(newSVpv((char *)argv[i], 0))); + XPUSHs (sv_2mortal(newSVpv((char *)argv[i], 0))); break; case 'i': /* integer */ - XPUSHs(sv_2mortal(newSViv(*((int *)argv[i])))); + XPUSHs (sv_2mortal(newSViv(*((int *)argv[i])))); break; case 'h': /* hash */ hash = weechat_perl_hashtable_to_hash (argv[i]); - XPUSHs(sv_2mortal(newRV_inc((SV *)hash))); + XPUSHs (sv_2mortal(newRV_inc((SV *)hash))); break; } } @@ -258,34 +380,47 @@ weechat_perl_exec (struct t_plugin_script *script, SPAGAIN; + weechat_perl_output_flush (); + if (SvTRUE (ERRSV)) { weechat_printf (NULL, weechat_gettext ("%s%s: error: %s"), weechat_prefix ("error"), PERL_PLUGIN_NAME, SvPV_nolen (ERRSV)); - (void) POPs; /* poping the 'undef' */ + (void) POPs; /* pop the "undef" */ mem_err = 0; } else { if (count != 1) { - weechat_printf (NULL, - weechat_gettext ("%s%s: function \"%s\" must " - "return one valid value (%d)"), - weechat_prefix ("error"), PERL_PLUGIN_NAME, - function, count); + if (ret_type != WEECHAT_SCRIPT_EXEC_IGNORE) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: function \"%s\" must " + "return a valid value"), + weechat_prefix ("error"), PERL_PLUGIN_NAME, + function); + } mem_err = 0; } else { if (ret_type == WEECHAT_SCRIPT_EXEC_STRING) { - ret_s = newSVsv(POPs); + ret_s = newSVsv (POPs); ret_value = strdup (SvPV_nolen (ret_s)); SvREFCNT_dec (ret_s); } + else if (ret_type == WEECHAT_SCRIPT_EXEC_POINTER) + { + ret_s = newSVsv (POPs); + ret_value = plugin_script_str2ptr (weechat_perl_plugin, + script->name, function, + SvPV_nolen (ret_s)); + SvREFCNT_dec (ret_s); + } else if (ret_type == WEECHAT_SCRIPT_EXEC_INT) { ret_i = malloc (sizeof (*ret_i)); @@ -302,16 +437,27 @@ weechat_perl_exec (struct t_plugin_script *script, } else { - weechat_printf (NULL, - weechat_gettext ("%s%s: function \"%s\" is " - "internally misused"), - weechat_prefix ("error"), PERL_PLUGIN_NAME, - function); + if (ret_type != WEECHAT_SCRIPT_EXEC_IGNORE) + { + weechat_printf ( + NULL, + weechat_gettext ("%s%s: function \"%s\" must return " + "a valid value"), + weechat_prefix ("error"), PERL_PLUGIN_NAME, + function); + } mem_err = 0; } } } + if ((ret_type != WEECHAT_SCRIPT_EXEC_IGNORE) && !ret_value) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: error in function \"%s\""), + weechat_prefix ("error"), PERL_PLUGIN_NAME, function); + } + PUTBACK; FREETMPS; LEAVE; @@ -338,14 +484,17 @@ weechat_perl_exec (struct t_plugin_script *script, /* * Loads a perl script. * - * Returns: - * 1: OK - * 0: error + * If code is NULL, the content of filename is read and executed. + * If code is not NULL, it is executed (the file is not read). + * + * Returns pointer to new registered script, NULL if error. */ -int -weechat_perl_load (const char *filename) +struct t_plugin_script * +weechat_perl_load (const char *filename, const char *code) { + char str_warning[512], str_error[512]; + struct t_plugin_script temp_script; struct stat buf; char *perl_code; @@ -364,12 +513,16 @@ weechat_perl_load (const char *filename) temp_script.shutdown_func = NULL; temp_script.charset = NULL; - if (stat (filename, &buf) != 0) + if (!code) { - weechat_printf (NULL, - weechat_gettext ("%s%s: script \"%s\" not found"), - weechat_prefix ("error"), PERL_PLUGIN_NAME, filename); - return 0; + if (stat (filename, &buf) != 0) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: script \"%s\" not found"), + weechat_prefix ("error"), PERL_PLUGIN_NAME, + filename); + return NULL; + } } if ((weechat_perl_plugin->debug >= 2) || !perl_quiet) @@ -384,7 +537,7 @@ weechat_perl_load (const char *filename) perl_registered_script = NULL; #ifdef MULTIPLICITY - perl_current_interpreter = perl_alloc(); + perl_current_interpreter = perl_alloc (); if (!perl_current_interpreter) { @@ -392,27 +545,48 @@ weechat_perl_load (const char *filename) weechat_gettext ("%s%s: unable to create new " "sub-interpreter"), weechat_prefix ("error"), PERL_PLUGIN_NAME); - return 0; + return NULL; } + snprintf (str_warning, sizeof (str_warning), + weechat_gettext ("%s: warning:"), + PERL_PLUGIN_NAME); + snprintf (str_error, sizeof (str_error), + weechat_gettext ("%s: error:"), + PERL_PLUGIN_NAME); + PERL_SET_CONTEXT (perl_current_interpreter); perl_construct (perl_current_interpreter); temp_script.interpreter = (PerlInterpreter *) perl_current_interpreter; perl_parse (perl_current_interpreter, weechat_perl_api_init, perl_args_count, perl_args, NULL); - length = strlen (perl_weechat_code) - 2 + strlen (filename) + 1; + length = strlen (perl_weechat_code) + strlen (str_warning) + + strlen (str_error) - 2 + 4 + strlen ((code) ? code : filename) + 4 + 1; perl_code = malloc (length); if (!perl_code) - return 0; - snprintf (perl_code, length, perl_weechat_code, filename); + return NULL; + snprintf (perl_code, length, perl_weechat_code, + str_warning, + str_error, + (code) ? "{\n" : "'", + (code) ? code : filename, + (code) ? "\n};\n" : "';"); #else snprintf (pkgname, sizeof (pkgname), "%s%d", PKG_NAME_PREFIX, perl_num); perl_num++; - length = strlen (perl_weechat_code) - 4 + strlen (pkgname) + strlen (filename) + 1; + length = strlen (perl_weechat_code) + strlen (str_warning) + + strlen (str_error) - 4 + strlen (pkgname) + 4 + + strlen ((code) ? code : filename) + 4 + 1; perl_code = malloc (length); if (!perl_code) - return 0; - snprintf (perl_code, length, perl_weechat_code, pkgname, filename); + return NULL; + snprintf (perl_code, length, perl_weechat_code, + pkgname, + str_warning, + str_error, + (code) ? "{\n" : "'", + (code) ? code : filename, + (code) ? "\n};\n" : "';"); #endif /* MULTIPLICITY */ eval_pv (perl_code, TRUE); free (perl_code); @@ -427,7 +601,7 @@ weechat_perl_load (const char *filename) weechat_printf (NULL, weechat_gettext ("%s%s: error: %s"), weechat_prefix ("error"), PERL_PLUGIN_NAME, - SvPV_nolen(ERRSV)); + SvPV_nolen (ERRSV)); #ifdef MULTIPLICITY perl_destruct (perl_current_interpreter); perl_free (perl_current_interpreter); @@ -440,7 +614,7 @@ weechat_perl_load (const char *filename) perl_current_script = NULL; } - return 0; + return NULL; } if (!perl_registered_script) @@ -453,7 +627,7 @@ weechat_perl_load (const char *filename) perl_destruct (perl_current_interpreter); perl_free (perl_current_interpreter); #endif /* MULTIPLICITY */ - return 0; + return NULL; } perl_current_script = perl_registered_script; @@ -475,7 +649,7 @@ weechat_perl_load (const char *filename) WEECHAT_HOOK_SIGNAL_STRING, perl_current_script->filename); - return 1; + return perl_current_script; } /* @@ -488,7 +662,7 @@ weechat_perl_load_cb (void *data, const char *filename) /* make C compiler happy */ (void) data; - weechat_perl_load (filename); + weechat_perl_load (filename, NULL); } /* @@ -620,7 +794,7 @@ weechat_perl_reload_name (const char *name) weechat_gettext ("%s: script \"%s\" unloaded"), PERL_PLUGIN_NAME, name); } - weechat_perl_load (filename); + weechat_perl_load (filename, NULL); free (filename); } } @@ -633,6 +807,64 @@ weechat_perl_reload_name (const char *name) } /* + * Evaluates perl source code. + * + * Returns: + * 1: OK + * 0: error + */ + +int +weechat_perl_eval (struct t_gui_buffer *buffer, int send_to_buffer_as_input, + int exec_commands, const char *code) +{ + void *func_argv[1], *result; + + if (!perl_script_eval) + { + perl_quiet = 1; + perl_script_eval = weechat_perl_load (WEECHAT_SCRIPT_EVAL_NAME, + PERL_EVAL_SCRIPT); + perl_quiet = 0; + if (!perl_script_eval) + return 0; + } + + weechat_perl_output_flush (); + + perl_eval_mode = 1; + perl_eval_send_input = send_to_buffer_as_input; + perl_eval_exec_commands = exec_commands; + perl_eval_buffer = buffer; + + func_argv[0] = (char *)code; + result = weechat_perl_exec (perl_script_eval, + WEECHAT_SCRIPT_EXEC_IGNORE, + "script_perl_eval", + "s", func_argv); + /* result is ignored */ + if (result) + free (result); + + weechat_perl_output_flush (); + + perl_eval_mode = 0; + perl_eval_send_input = 0; + perl_eval_exec_commands = 0; + perl_eval_buffer = NULL; + + if (!weechat_config_boolean (perl_config_look_eval_keep_context)) + { + perl_quiet = 1; + weechat_perl_unload (perl_script_eval); + perl_quiet = 0; + perl_script_eval = NULL; + } + + return 1; +} + +/* * Callback for command "/perl". */ @@ -641,12 +873,12 @@ weechat_perl_command_cb (const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { - char *ptr_name, *path_script; + char *ptr_name, *ptr_code, *path_script; + int i, send_to_buffer_as_input, exec_commands; /* make C compiler happy */ (void) pointer; (void) data; - (void) buffer; if (argc == 1) { @@ -678,6 +910,10 @@ weechat_perl_command_cb (const void *pointer, void *data, { weechat_perl_unload_all (); } + else if (weechat_strcasecmp (argv[1], "version") == 0) + { + plugin_script_display_interpreter (weechat_perl_plugin, 0); + } else WEECHAT_COMMAND_ERROR; } @@ -712,7 +948,8 @@ weechat_perl_command_cb (const void *pointer, void *data, /* load perl script */ path_script = plugin_script_search_path (weechat_perl_plugin, ptr_name); - weechat_perl_load ((path_script) ? path_script : ptr_name); + weechat_perl_load ((path_script) ? path_script : ptr_name, + NULL); if (path_script) free (path_script); } @@ -728,6 +965,39 @@ weechat_perl_command_cb (const void *pointer, void *data, } perl_quiet = 0; } + else if (weechat_strcasecmp (argv[1], "eval") == 0) + { + send_to_buffer_as_input = 0; + exec_commands = 0; + ptr_code = argv_eol[2]; + for (i = 2; i < argc; i++) + { + if (argv[i][0] == '-') + { + if (strcmp (argv[i], "-o") == 0) + { + if (i + 1 >= argc) + WEECHAT_COMMAND_ERROR; + send_to_buffer_as_input = 1; + exec_commands = 0; + ptr_code = argv_eol[i + 1]; + } + else if (strcmp (argv[i], "-oc") == 0) + { + if (i + 1 >= argc) + WEECHAT_COMMAND_ERROR; + send_to_buffer_as_input = 1; + exec_commands = 1; + ptr_code = argv_eol[i + 1]; + } + } + else + break; + } + if (!weechat_perl_eval (buffer, send_to_buffer_as_input, + exec_commands, ptr_code)) + WEECHAT_COMMAND_ERROR; + } else WEECHAT_COMMAND_ERROR; } @@ -774,6 +1044,29 @@ weechat_perl_hdata_cb (const void *pointer, void *data, } /* + * Returns perl info "perl_eval". + */ + +const char * +weechat_perl_info_eval_cb (const void *pointer, void *data, + const char *info_name, + const char *arguments) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) info_name; + + weechat_perl_eval (NULL, 0, 0, (arguments) ? arguments : ""); + if (perl_eval_output) + free (perl_eval_output); + perl_eval_output = strdup (*perl_buffer_output); + weechat_string_dyn_copy (perl_buffer_output, NULL); + + return perl_eval_output; +} + +/* * Returns infolist with perl scripts. */ @@ -824,31 +1117,6 @@ weechat_perl_signal_debug_dump_cb (const void *pointer, void *data, } /* - * Display infos about external libraries used. - */ - -int -weechat_perl_signal_debug_libs_cb (const void *pointer, void *data, - const char *signal, - const char *type_data, void *signal_data) -{ - /* make C compiler happy */ - (void) pointer; - (void) data; - (void) signal; - (void) type_data; - (void) signal_data; - -#ifdef PERL_VERSION_STRING - weechat_printf (NULL, " %s: %s", PERL_PLUGIN_NAME, PERL_VERSION_STRING); -#else - weechat_printf (NULL, " %s: (?)", PERL_PLUGIN_NAME); -#endif /* PERL_VERSION_STRING */ - - return WEECHAT_RC_OK; -} - -/* * Timer for executing actions. */ @@ -964,7 +1232,6 @@ weechat_perl_signal_quit_upgrade_cb (const void *pointer, void *data, int weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) { - struct t_plugin_script_init init; #ifdef PERL_SYS_INIT3 int a; char **perl_args_local; @@ -977,6 +1244,22 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) weechat_perl_plugin = plugin; + /* set interpreter name and version */ + weechat_hashtable_set (plugin->variables, "interpreter_name", + plugin->name); +#ifdef PERL_VERSION_STRING + weechat_hashtable_set (plugin->variables, "interpreter_version", + PERL_VERSION_STRING); +#else + weechat_hashtable_set (plugin->variables, "interpreter_version", + ""); +#endif /* PERL_VERSION_STRING */ + + /* init stdout/stderr buffer */ + perl_buffer_output = weechat_string_dyn_alloc (256); + if (!perl_buffer_output) + return WEECHAT_RC_ERROR; + #ifndef MULTIPLICITY perl_main = perl_alloc (); @@ -994,17 +1277,23 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) perl_args, NULL); #endif /* MULTIPLICITY */ - init.callback_command = &weechat_perl_command_cb; - init.callback_completion = &weechat_perl_completion_cb; - init.callback_hdata = &weechat_perl_hdata_cb; - init.callback_infolist = &weechat_perl_infolist_cb; - init.callback_signal_debug_dump = &weechat_perl_signal_debug_dump_cb; - init.callback_signal_debug_libs = &weechat_perl_signal_debug_libs_cb; - init.callback_signal_script_action = &weechat_perl_signal_script_action_cb; - init.callback_load_file = &weechat_perl_load_cb; + perl_data.config_file = &perl_config_file; + perl_data.config_look_check_license = &perl_config_look_check_license; + perl_data.config_look_eval_keep_context = &perl_config_look_eval_keep_context; + perl_data.scripts = &perl_scripts; + perl_data.last_script = &last_perl_script; + perl_data.callback_command = &weechat_perl_command_cb; + perl_data.callback_completion = &weechat_perl_completion_cb; + perl_data.callback_hdata = &weechat_perl_hdata_cb; + perl_data.callback_info_eval = &weechat_perl_info_eval_cb; + perl_data.callback_infolist = &weechat_perl_infolist_cb; + perl_data.callback_signal_debug_dump = &weechat_perl_signal_debug_dump_cb; + perl_data.callback_signal_script_action = &weechat_perl_signal_script_action_cb; + perl_data.callback_load_file = &weechat_perl_load_cb; + perl_data.unload_all = &weechat_perl_unload_all; perl_quiet = 1; - plugin_script_init (weechat_perl_plugin, argc, argv, &init); + plugin_script_init (weechat_perl_plugin, argc, argv, &perl_data); perl_quiet = 0; plugin_script_display_short_list (weechat_perl_plugin, @@ -1028,7 +1317,12 @@ weechat_plugin_end (struct t_weechat_plugin *plugin) { /* unload all scripts */ perl_quiet = 1; - plugin_script_end (plugin, &perl_scripts, &weechat_perl_unload_all); + if (perl_script_eval) + { + weechat_perl_unload (perl_script_eval); + perl_script_eval = NULL; + } + plugin_script_end (plugin, &perl_data); perl_quiet = 0; #ifndef MULTIPLICITY @@ -1057,6 +1351,9 @@ weechat_plugin_end (struct t_weechat_plugin *plugin) free (perl_action_remove_list); if (perl_action_autoload_list) free (perl_action_autoload_list); + weechat_string_dyn_free (perl_buffer_output, 1); + if (perl_eval_output) + free (perl_eval_output); return WEECHAT_RC_OK; } diff --git a/src/plugins/perl/weechat-perl.h b/src/plugins/perl/weechat-perl.h index d40e22938..84914ae72 100644 --- a/src/plugins/perl/weechat-perl.h +++ b/src/plugins/perl/weechat-perl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_PERL_H -#define WEECHAT_PERL_H 1 +#ifndef WEECHAT_PLUGIN_PERL_H +#define WEECHAT_PLUGIN_PERL_H #define weechat_plugin weechat_perl_plugin #define PERL_PLUGIN_NAME "perl" @@ -27,6 +27,8 @@ extern struct t_weechat_plugin *weechat_perl_plugin; +extern struct t_plugin_script_data perl_data; + extern int perl_quiet; extern struct t_plugin_script *perl_scripts; extern struct t_plugin_script *last_perl_script; @@ -41,8 +43,9 @@ extern HV *weechat_perl_hashtable_to_hash (struct t_hashtable *hashtable); extern struct t_hashtable *weechat_perl_hash_to_hashtable (SV *hash, int size, const char *type_keys, const char *type_values); +extern XS (weechat_perl_output); extern void *weechat_perl_exec (struct t_plugin_script *script, int ret_type, const char *function, const char *format, void **argv); -#endif /* WEECHAT_PERL_H */ +#endif /* WEECHAT_PLUGIN_PERL_H */ diff --git a/src/plugins/php/CMakeLists.txt b/src/plugins/php/CMakeLists.txt new file mode 100644 index 000000000..5931d2371 --- /dev/null +++ b/src/plugins/php/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2006-2017 Adam Saponara <as@php.net> +# +# This file is part of WeeChat, the extensible chat client. +# +# WeeChat is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# WeeChat is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with WeeChat. If not, see <http://www.gnu.org/licenses/>. +# + +add_library(php MODULE weechat-php.c weechat-php.h weechat-php-api.c +weechat-php-api.h) + +set_target_properties(php PROPERTIES PREFIX "") + +if(PHP_FOUND) + include_directories(${PHP_INCLUDE_DIRS}) + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${PHP_LDFLAGS}") + target_link_libraries(php ${PHP_LIB} weechat_plugins_scripts) +endif() + +install(TARGETS php LIBRARY DESTINATION ${LIBDIR}/plugins) diff --git a/src/plugins/php/Makefile.am b/src/plugins/php/Makefile.am new file mode 100644 index 000000000..cb4b9fa64 --- /dev/null +++ b/src/plugins/php/Makefile.am @@ -0,0 +1,33 @@ +# +# Copyright (C) 2006-2017 Adam Saponara <as@php.net> +# +# This file is part of WeeChat, the extensible chat client. +# +# WeeChat is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# WeeChat is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with WeeChat. If not, see <http://www.gnu.org/licenses/>. +# + +AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/locale\" $(PHP_CFLAGS) + +libdir = ${weechat_libdir}/plugins + +lib_LTLIBRARIES = php.la + +php_la_SOURCES = weechat-php.c \ + weechat-php.h \ + weechat-php-api.c \ + weechat-php-api.h +php_la_LDFLAGS = -module -no-undefined +php_la_LIBADD = ../lib_weechat_plugins_scripts.la $(PHP_LFLAGS) + +EXTRA_DIST = CMakeLists.txt diff --git a/src/plugins/php/weechat-php-api.c b/src/plugins/php/weechat-php-api.c new file mode 100644 index 000000000..e821dfd44 --- /dev/null +++ b/src/plugins/php/weechat-php-api.c @@ -0,0 +1,5028 @@ +/* + * weechat-php-api.c - PHP API functions + * + * Copyright (C) 2006-2017 Adam Saponara <as@php.net> + * Copyright (C) 2017 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + * + * OpenSSL licensing: + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify the Program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, the licensors of the Program + * grant you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#include <sapi/embed/php_embed.h> +#include <php.h> +#include <php_ini.h> +#include <ext/standard/info.h> + +#include "../weechat-plugin.h" +#include "../plugin-script.h" +#include "../plugin-script-api.h" +#include "weechat-php.h" + + +#define API_FUNC(__name) \ + PHP_FUNCTION(weechat_##__name) +#define API_INIT_FUNC(__init, __name, __ret) \ + char *php_function_name = __name; \ + if (__init \ + && (!php_current_script || !php_current_script->name)) \ + { \ + WEECHAT_SCRIPT_MSG_NOT_INIT(PHP_CURRENT_SCRIPT_NAME, \ + php_function_name); \ + __ret; \ + } +#define API_WRONG_ARGS(__ret) \ + { \ + WEECHAT_SCRIPT_MSG_WRONG_ARGS(PHP_CURRENT_SCRIPT_NAME, \ + php_function_name); \ + __ret; \ + } +#define API_PTR2STR(__pointer) \ + plugin_script_ptr2str (__pointer) +#define API_STR2PTR(__string) \ + plugin_script_str2ptr (weechat_php_plugin, \ + PHP_CURRENT_SCRIPT_NAME, \ + php_function_name, __string) +#define API_STATIC_STRING(__string) \ + plugin_script_get_static_string(&php_data, __string); +#define API_RETURN_OK RETURN_LONG((long)1) +#define API_RETURN_ERROR RETURN_LONG((long)0) +#define API_RETURN_EMPTY RETURN_NULL() +#define API_RETURN_STRING(__string) \ + RETURN_STRING((__string) ? (__string) : "") +#define API_RETURN_STRING_FREE(__string) \ + if (__string) \ + { \ + RETVAL_STRING(__string); \ + free (__string); \ + return; \ + } \ + RETURN_STRING(""); +#define API_RETURN_INT(__int) RETURN_LONG(__int) +#define API_RETURN_LONG(__long) RETURN_LONG(__long) +#define weechat_php_get_function_name(__zfunc, __str) \ + const char *(__str); \ + do \ + { \ + if (!zend_is_callable (__zfunc, 0, NULL)) \ + { \ + php_error_docref (NULL, E_WARNING, "Expected callable"); \ + RETURN_FALSE; \ + } \ + (__str) = weechat_php_func_map_add (__zfunc); \ + } \ + while (0) + +static char weechat_php_empty_arg[1] = { '\0' }; + + +/* + * Registers a PHP script. + */ + +API_FUNC(register) +{ + zend_string *name, *author, *version, *license, *description, *charset; + zval *shutdown_func; + const char *shutdown_func_name; + + API_INIT_FUNC(0, "register", API_RETURN_ERROR); + if (php_registered_script) + { + /* script already registered */ + weechat_printf (NULL, + weechat_gettext ("%s%s: script \"%s\" already " + "registered (register ignored)"), + weechat_prefix ("error"), PHP_PLUGIN_NAME, + php_registered_script->name); + API_RETURN_ERROR; + } + if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, "SSSSSzS", + &name, &author, &version, &license, &description, + &shutdown_func, &charset) == FAILURE) + { + API_WRONG_ARGS(API_RETURN_ERROR); + } + + php_current_script = NULL; + php_registered_script = NULL; + + if (plugin_script_search (weechat_php_plugin, php_scripts, ZSTR_VAL(name))) + { + /* another script already exists with same name */ + weechat_printf (NULL, + weechat_gettext ("%s%s: unable to register script " + "\"%s\" (another script already " + "exists with this name)"), + weechat_prefix ("error"), PHP_PLUGIN_NAME, + ZSTR_VAL(name)); + API_RETURN_ERROR; + } + + /* resolve shutdown func */ + shutdown_func_name = NULL; + if (zend_is_callable (shutdown_func, 0, NULL)) + { + weechat_php_get_function_name (shutdown_func, shutdown_func_name_tmp); + shutdown_func_name = shutdown_func_name_tmp; + } + + /* register script */ + php_current_script = plugin_script_add (weechat_php_plugin, + &php_data, + (php_current_script_filename) ? + php_current_script_filename : "", + ZSTR_VAL(name), + ZSTR_VAL(author), + ZSTR_VAL(version), + ZSTR_VAL(license), + ZSTR_VAL(description), + shutdown_func_name, + ZSTR_VAL(charset)); + if (php_current_script) + { + php_registered_script = php_current_script; + if ((weechat_php_plugin->debug >= 2) || !php_quiet) + { + weechat_printf (NULL, + weechat_gettext ("%s: registered script \"%s\", " + "version %s (%s)"), + PHP_PLUGIN_NAME, ZSTR_VAL(name), ZSTR_VAL(version), + ZSTR_VAL(description)); + } + } + else + { + API_RETURN_ERROR; + } + + API_RETURN_OK; +} + +/* + * Generic PHP callback function. + */ + +static void +weechat_php_cb (const void *pointer, void *data, void **func_argv, + const char *func_types, int func_type, void *rc) +{ + struct t_plugin_script *script; + const char *ptr_function, *ptr_data; + void *ret; + + script = (struct t_plugin_script *)pointer; + plugin_script_get_function_and_data (data, &ptr_function, &ptr_data); + + func_argv[0] = ptr_data ? (char *)ptr_data : weechat_php_empty_arg; + + if (!ptr_function || !ptr_function[0]) + { + goto weechat_php_cb_err; + } + + ret = weechat_php_exec (script, func_type, ptr_function, + func_types, func_argv); + + if (!ret) + { + goto weechat_php_cb_err; + } + + if (func_type == WEECHAT_SCRIPT_EXEC_INT) + { + *((int *)rc) = *((int *)ret); + free (ret); + } + else if (func_type == WEECHAT_SCRIPT_EXEC_HASHTABLE) + { + *((struct t_hashtable **)rc) = (struct t_hashtable *)ret; + } + else + { + *((char **)rc) = (char *)ret; + } + return; + +weechat_php_cb_err: + if (func_type == WEECHAT_SCRIPT_EXEC_INT) + { + *((int *)rc) = WEECHAT_RC_ERROR; + } + else if (func_type == WEECHAT_SCRIPT_EXEC_HASHTABLE) + { + *((struct t_hashtable **)rc) = NULL; + } + else + { + *((char **)rc) = NULL; + } +} + +/* + * Wrappers for functions in scripting API. + * + * For more info about these functions, look at their implementation in WeeChat + * core. + */ + +API_FUNC(plugin_get_name) +{ + zend_string *z_plugin; + struct t_weechat_plugin *plugin; + const char *result; + + API_INIT_FUNC(1, "plugin_get_name", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_plugin) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + plugin = API_STR2PTR(ZSTR_VAL(z_plugin)); + + result = weechat_plugin_get_name (plugin); + + API_RETURN_STRING(result); +} + +API_FUNC(charset_set) +{ + zend_string *z_charset; + char *charset; + + API_INIT_FUNC(1, "charset_set", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_charset) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + charset = ZSTR_VAL(z_charset); + plugin_script_api_charset_set (php_current_script, (const char *)charset); + + API_RETURN_OK; +} + +API_FUNC(iconv_to_internal) +{ + zend_string *z_charset, *z_string; + char *charset, *string, *result; + + API_INIT_FUNC(1, "iconv_to_internal", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_charset, &z_string) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + charset = ZSTR_VAL(z_charset); + string = ZSTR_VAL(z_string); + result = weechat_iconv_to_internal ((const char *)charset, + (const char *)string); + + API_RETURN_STRING_FREE(result); +} + +API_FUNC(iconv_from_internal) +{ + zend_string *z_charset, *z_string; + char *charset, *string, *result; + + API_INIT_FUNC(1, "iconv_from_internal", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_charset, &z_string) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + charset = ZSTR_VAL(z_charset); + string = ZSTR_VAL(z_string); + result = weechat_iconv_from_internal ((const char *)charset, + (const char *)string); + + API_RETURN_STRING_FREE(result); +} + +API_FUNC(gettext) +{ + zend_string *z_string; + char *string; + const char *result; + + API_INIT_FUNC(1, "gettext", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_string) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + string = ZSTR_VAL(z_string); + result = weechat_gettext ((const char *)string); + + API_RETURN_STRING(result); +} + +API_FUNC(ngettext) +{ + zend_string *z_single, *z_plural; + zend_long z_count; + char *single, *plural; + int count; + const char *result; + + API_INIT_FUNC(1, "ngettext", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSl", &z_single, &z_plural, + &z_count) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + single = ZSTR_VAL(z_single); + plural = ZSTR_VAL(z_plural); + count = (int)z_count; + result = weechat_ngettext ((const char *)single, + (const char *)plural, + count); + + API_RETURN_STRING(result); +} + +API_FUNC(strlen_screen) +{ + zend_string *z_string; + char *string; + int result; + + API_INIT_FUNC(1, "strlen_screen", API_RETURN_INT(0)); + + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_string) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + string = ZSTR_VAL(z_string); + result = weechat_strlen_screen ((const char *)string); + + API_RETURN_INT(result); +} + +API_FUNC(string_match) +{ + zend_string *z_string, *z_mask; + zend_long z_case_sensitive; + int case_sensitive, result; + char *string, *mask; + + API_INIT_FUNC(1, "string_match", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSl", &z_string, &z_mask, + &z_case_sensitive) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + string = ZSTR_VAL(z_string); + mask = ZSTR_VAL(z_mask); + case_sensitive = (int)z_case_sensitive; + result = weechat_string_match ((const char *)string, + (const char *)mask, + case_sensitive); + + API_RETURN_INT(result); +} + +API_FUNC(string_has_highlight) +{ + zend_string *z_string, *z_highlight_words; + char *string, *highlight_words; + int result; + + API_INIT_FUNC(1, "string_has_highlight", API_RETURN_INT(0)); + + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_string, &z_highlight_words) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + string = ZSTR_VAL(z_string); + highlight_words = ZSTR_VAL(z_highlight_words); + result = weechat_string_has_highlight ((const char *)string, + (const char *)highlight_words); + + API_RETURN_INT(result); +} + +API_FUNC(string_has_highlight_regex) +{ + zend_string *z_string, *z_regex; + char *string, *regex; + int result; + + API_INIT_FUNC(1, "string_has_highlight_regex", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_string, &z_regex) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + string = ZSTR_VAL(z_string); + regex = ZSTR_VAL(z_regex); + result = weechat_string_has_highlight_regex ((const char *)string, + (const char *)regex); + + API_RETURN_INT(result); +} + +API_FUNC(string_mask_to_regex) +{ + zend_string *z_mask; + char *mask, *result; + + API_INIT_FUNC(1, "string_mask_to_regex", API_RETURN_EMPTY); + + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_mask) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + mask = ZSTR_VAL(z_mask); + result = weechat_string_mask_to_regex ((const char *)mask); + + API_RETURN_STRING_FREE(result); +} + +API_FUNC(string_format_size) +{ + zend_long z_size; + char *result; + + API_INIT_FUNC(1, "string_format_size", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "l", &z_size) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + result = weechat_string_format_size ((unsigned long long)z_size); + + API_RETURN_STRING_FREE(result); +} + +API_FUNC(string_remove_color) +{ + zend_string *z_string, *z_replacement; + char *string, *replacement, *result; + + API_INIT_FUNC(1, "string_remove_color", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_string, &z_replacement) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + string = ZSTR_VAL(z_string); + replacement = ZSTR_VAL(z_replacement); + result = weechat_string_remove_color ((const char *)string, + (const char *)replacement); + + API_RETURN_STRING_FREE(result); +} + +API_FUNC(string_is_command_char) +{ + zend_string *z_string; + char *string; + int result; + + API_INIT_FUNC(1, "string_is_command_char", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_string) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + string = ZSTR_VAL(z_string); + result = weechat_string_is_command_char ((const char *)string); + + API_RETURN_INT(result); +} + +API_FUNC(string_input_for_buffer) +{ + zend_string *z_string; + char *string; + const char *result; + + API_INIT_FUNC(1, "string_input_for_buffer", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_string) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + string = ZSTR_VAL(z_string); + result = weechat_string_input_for_buffer ((const char *)string); + + API_RETURN_STRING(result); +} + +API_FUNC(string_eval_expression) +{ + zend_string *z_expr; + zval *z_pointers, *z_extra_vars, *z_options; + char *expr, *result; + struct t_hashtable *pointers, *extra_vars, *options; + + API_INIT_FUNC(1, "string_eval_expression", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "Saaa", &z_expr, &z_pointers, &z_extra_vars, + &z_options) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + expr = ZSTR_VAL(z_expr); + pointers = weechat_php_array_to_hashtable ( + z_pointers, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER); + extra_vars = weechat_php_array_to_hashtable ( + z_extra_vars, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING); + options = weechat_php_array_to_hashtable ( + z_options, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING); + result = weechat_string_eval_expression ((const char *)expr, + pointers, + extra_vars, + options); + + API_RETURN_STRING_FREE(result); +} + +API_FUNC(string_eval_path_home) +{ + zend_string *z_path; + zval *z_pointers, *z_extra_vars, *z_options; + char *path, *result; + struct t_hashtable *pointers, *extra_vars, *options; + + API_INIT_FUNC(1, "string_eval_path_home", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "Saaa", &z_path, &z_pointers, &z_extra_vars, + &z_options) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + path = ZSTR_VAL(z_path); + pointers = weechat_php_array_to_hashtable ( + z_pointers, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER); + extra_vars = weechat_php_array_to_hashtable ( + z_extra_vars, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING); + options = weechat_php_array_to_hashtable ( + z_options, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING); + result = weechat_string_eval_path_home ((const char *)path, + pointers, + extra_vars, + options); + + API_RETURN_STRING_FREE(result); +} + +API_FUNC(mkdir_home) +{ + zend_string *z_directory; + zend_long z_mode; + char *directory; + int mode; + + API_INIT_FUNC(1, "mkdir_home", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "Sl", &z_directory, &z_mode) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + directory = ZSTR_VAL(z_directory); + mode = (int)z_mode; + if (weechat_mkdir_home ((const char *)directory, mode)) + API_RETURN_OK; + + API_RETURN_ERROR; +} + +API_FUNC(mkdir) +{ + zend_string *z_directory; + zend_long z_mode; + char *directory; + int mode; + + API_INIT_FUNC(1, "mkdir", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "Sl", &z_directory, &z_mode) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + directory = ZSTR_VAL(z_directory); + mode = (int)z_mode; + if (weechat_mkdir ((const char *)directory, mode)) + API_RETURN_OK; + + API_RETURN_ERROR; +} + +API_FUNC(mkdir_parents) +{ + zend_string *z_directory; + zend_long z_mode; + char *directory; + int mode; + + API_INIT_FUNC(1, "mkdir_parents", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "Sl", &z_directory, &z_mode) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + directory = ZSTR_VAL(z_directory); + mode = (int)z_mode; + if (weechat_mkdir_parents ((const char *)directory, mode)) + API_RETURN_OK; + + API_RETURN_ERROR; +} + +API_FUNC(list_new) +{ + const char *result; + + API_INIT_FUNC(1, "list_new", API_RETURN_EMPTY); + if (zend_parse_parameters_none () == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + result = API_PTR2STR(weechat_list_new ()); + + API_RETURN_STRING(result); +} + +API_FUNC(list_add) +{ + zend_string *z_weelist, *z_data, *z_where, *z_user_data; + struct t_weelist *weelist; + char *data, *where; + void *user_data; + const char *result; + + API_INIT_FUNC(1, "list_add", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSSS", &z_weelist, &z_data, &z_where, + &z_user_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + weelist = (struct t_weelist *)API_STR2PTR(ZSTR_VAL(z_weelist)); + data = ZSTR_VAL(z_data); + where = ZSTR_VAL(z_where); + user_data = (void *)API_STR2PTR(ZSTR_VAL(z_user_data)); + + result = API_PTR2STR(weechat_list_add (weelist, + (const char *)data, + (const char *)where, + user_data)); + + API_RETURN_STRING(result); +} + +API_FUNC(list_search) +{ + zend_string *z_weelist, *z_data; + struct t_weelist *weelist; + char *data; + const char *result; + + API_INIT_FUNC(1, "list_search", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_weelist, &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + weelist = (struct t_weelist *)API_STR2PTR(ZSTR_VAL(z_weelist)); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR(weechat_list_search (weelist, (const char *)data)); + + API_RETURN_STRING(result); +} + +API_FUNC(list_search_pos) +{ + zend_string *z_weelist, *z_data; + struct t_weelist *weelist; + char *data; + int result; + + API_INIT_FUNC(1, "list_search_pos", API_RETURN_INT(-1)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_weelist, &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(-1)); + + weelist = (struct t_weelist *)API_STR2PTR(ZSTR_VAL(z_weelist)); + data = ZSTR_VAL(z_data); + result = weechat_list_search_pos (weelist, (const char *)data); + + API_RETURN_INT(result); +} + +API_FUNC(list_casesearch) +{ + zend_string *z_weelist, *z_data; + struct t_weelist *weelist; + char *data; + const char *result; + + API_INIT_FUNC(1, "list_casesearch", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_weelist, &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + weelist = (struct t_weelist *)API_STR2PTR(ZSTR_VAL(z_weelist)); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR( + weechat_list_casesearch (weelist, (const char *)data)); + + API_RETURN_STRING(result); +} + +API_FUNC(list_casesearch_pos) +{ + zend_string *z_weelist, *z_data; + struct t_weelist *weelist; + char *data; + int result; + + API_INIT_FUNC(1, "list_casesearch_pos", API_RETURN_INT(-1)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_weelist, &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(-1)); + + weelist = (struct t_weelist *)API_STR2PTR(ZSTR_VAL(z_weelist)); + data = ZSTR_VAL(z_data); + result = weechat_list_casesearch_pos (weelist, (const char *)data); + + API_RETURN_INT(result); +} + +API_FUNC(list_get) +{ + zend_string *z_weelist; + zend_long z_position; + struct t_weelist *weelist; + int position; + const char *result; + + API_INIT_FUNC(1, "list_get", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "Sl", &z_weelist, &z_position) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + weelist = (struct t_weelist *)API_STR2PTR(ZSTR_VAL(z_weelist)); + position = (int)z_position; + + result = API_PTR2STR(weechat_list_get (weelist, position)); + + API_RETURN_STRING(result); +} + +API_FUNC(list_set) +{ + zend_string *z_item, *z_value; + struct t_weelist_item *item; + char *value; + + API_INIT_FUNC(1, "list_set", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_item, &z_value) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + item = (struct t_weelist_item *)API_STR2PTR(ZSTR_VAL(z_item)); + value = ZSTR_VAL(z_value); + weechat_list_set (item, (const char *)value); + + API_RETURN_OK; +} + +API_FUNC(list_next) +{ + zend_string *z_item; + struct t_weelist_item *item; + const char *result; + + API_INIT_FUNC(1, "list_next", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_item) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + item = (struct t_weelist_item *)API_STR2PTR(ZSTR_VAL(z_item)); + + result = API_PTR2STR(weechat_list_next (item)); + + API_RETURN_STRING(result); +} + +API_FUNC(list_prev) +{ + zend_string *z_item; + struct t_weelist_item *item; + const char *result; + + API_INIT_FUNC(1, "list_prev", API_RETURN_EMPTY); + + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_item) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + item = (struct t_weelist_item *)API_STR2PTR(ZSTR_VAL(z_item)); + + result = API_PTR2STR(weechat_list_prev (item)); + + API_RETURN_STRING(result); +} + +API_FUNC(list_string) +{ + zend_string *z_item; + const char *result; + struct t_weelist_item *item; + + API_INIT_FUNC(1, "list_string", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_item) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + item = (struct t_weelist_item *)API_STR2PTR(ZSTR_VAL(z_item)); + result = weechat_list_string (item); + + API_RETURN_STRING(result); +} + +API_FUNC(list_size) +{ + zend_string *z_weelist; + struct t_weelist *weelist; + int result; + + API_INIT_FUNC(1, "list_size", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_weelist) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + weelist = (struct t_weelist *)API_STR2PTR(ZSTR_VAL(z_weelist)); + result = weechat_list_size (weelist); + + API_RETURN_INT(result); +} + +API_FUNC(list_remove) +{ + zend_string *z_weelist, *z_item; + struct t_weelist *weelist; + struct t_weelist_item *item; + + API_INIT_FUNC(1, "list_remove", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_weelist, &z_item) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + weelist = (struct t_weelist *)API_STR2PTR(ZSTR_VAL(z_weelist)); + item = (struct t_weelist_item *)API_STR2PTR(ZSTR_VAL(z_item)); + weechat_list_remove (weelist, item); + + API_RETURN_OK; +} + +API_FUNC(list_remove_all) +{ + zend_string *z_weelist; + struct t_weelist *weelist; + + API_INIT_FUNC(1, "list_remove_all", API_RETURN_ERROR); + + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_weelist) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + weelist = (struct t_weelist *)API_STR2PTR(ZSTR_VAL(z_weelist)); + weechat_list_remove_all (weelist); + + API_RETURN_OK; +} + +API_FUNC(list_free) +{ + zend_string *z_weelist; + struct t_weelist *weelist; + + API_INIT_FUNC(1, "list_free", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_weelist) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + weelist = (struct t_weelist *)API_STR2PTR(ZSTR_VAL(z_weelist)); + weechat_list_free (weelist); + + API_RETURN_OK; +} + +static int +weechat_php_api_config_reload_cb (const void *pointer, void *data, + struct t_config_file *config_file) +{ + int rc; + void *func_argv[2]; + + func_argv[1] = (char *)API_PTR2STR(config_file); + + weechat_php_cb (pointer, data, func_argv, "ss", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +API_FUNC(config_new) +{ + zend_string *z_name; + zval *z_callback_reload; + zend_string *z_data; + char *name, *data; + const char *result; + + API_INIT_FUNC(1, "config_new", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SzS", &z_name, &z_callback_reload, + &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + name = ZSTR_VAL(z_name); + weechat_php_get_function_name (z_callback_reload, callback_reload_name); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR( + plugin_script_api_config_new ( + weechat_php_plugin, + php_current_script, + (const char *)name, + &weechat_php_api_config_reload_cb, + (const char *)callback_reload_name, + (const char *)data)); + + API_RETURN_STRING(result); +} + +static int +weechat_php_api_config_section_read_cb (const void *pointer, void *data, + struct t_config_file *config_file, + struct t_config_section *section, + const char *option_name, + const char *value) +{ + int rc; + void *func_argv[5]; + + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); + func_argv[3] = option_name ? (char *)option_name : weechat_php_empty_arg; + func_argv[4] = value ? (char *)value : weechat_php_empty_arg; + + weechat_php_cb (pointer, data, func_argv, "sssss", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +static int +weechat_php_api_config_section_write_cb (const void *pointer, void *data, + struct t_config_file *config_file, + const char *section_name) +{ + int rc; + void *func_argv[3]; + + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = section_name ? (char *)section_name : weechat_php_empty_arg; + + weechat_php_cb (pointer, data, func_argv, "sss", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +static int +weechat_php_api_config_section_write_default_cb (const void *pointer, + void *data, + struct t_config_file *config_file, + const char *section_name) +{ + int rc; + void *func_argv[3]; + + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = section_name ? (char *)section_name : weechat_php_empty_arg; + + weechat_php_cb (pointer, data, func_argv, "sss", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +static int +weechat_php_api_config_section_create_option_cb (const void *pointer, + void *data, + struct t_config_file *config_file, + struct t_config_section *section, + const char *option_name, + const char *value) +{ + int rc; + void *func_argv[5]; + + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); + func_argv[3] = option_name ? (char *)option_name : weechat_php_empty_arg; + func_argv[4] = value ? (char *)value : weechat_php_empty_arg; + + weechat_php_cb (pointer, data, func_argv, "sssss", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +static int +weechat_php_api_config_section_delete_option_cb (const void *pointer, + void *data, + struct t_config_file *config_file, + struct t_config_section *section, + struct t_config_option *option) +{ + int rc; + void *func_argv[4]; + + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); + func_argv[3] = (char *)API_PTR2STR(option); + + weechat_php_cb (pointer, data, func_argv, "ssss", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +API_FUNC(config_new_section) +{ + zend_string *z_config_file, *z_name; + zend_long z_user_can_add_options, z_user_can_delete_options; + zval *z_callback_read, *z_callback_write, *z_callback_write_default; + zval *z_callback_create_option, *z_callback_delete_option; + zend_string *z_data_read, *z_data_write, *z_data_write_default; + zend_string *z_data_create_option, *z_data_delete_option; + struct t_config_file *config_file; + char *name; + int user_can_add_options, user_can_delete_options; + char *data_read, *data_write, *data_write_default; + char *data_create_option, *data_delete_option; + const char *result; + + API_INIT_FUNC(1, "config_new_section", API_RETURN_EMPTY); + if (zend_parse_parameters ( + ZEND_NUM_ARGS(), "SSllzSzSzSzSzS", &z_config_file, &z_name, + &z_user_can_add_options, &z_user_can_delete_options, + &z_callback_read, &z_data_read, &z_callback_write, &z_data_write, + &z_callback_write_default, &z_data_write_default, + &z_callback_create_option, &z_data_create_option, + &z_callback_delete_option, &z_data_delete_option) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + config_file = (struct t_config_file *)API_STR2PTR(ZSTR_VAL(z_config_file)); + name = ZSTR_VAL(z_name); + user_can_add_options = (int)z_user_can_add_options; + user_can_delete_options = (int)z_user_can_delete_options; + weechat_php_get_function_name (z_callback_read, callback_read_name); + data_read = ZSTR_VAL(z_data_read); + weechat_php_get_function_name (z_callback_write, callback_write_name); + data_write = ZSTR_VAL(z_data_write); + weechat_php_get_function_name (z_callback_write_default, + callback_write_default_name); + data_write_default = ZSTR_VAL(z_data_write_default); + weechat_php_get_function_name (z_callback_create_option, + callback_create_option_name); + data_create_option = ZSTR_VAL(z_data_create_option); + weechat_php_get_function_name (z_callback_delete_option, + callback_delete_option_name); + data_delete_option = ZSTR_VAL(z_data_delete_option); + + result = API_PTR2STR( + plugin_script_api_config_new_section ( + weechat_php_plugin, + php_current_script, + config_file, + (const char *)name, + user_can_add_options, + user_can_delete_options, + &weechat_php_api_config_section_read_cb, + (const char *)callback_read_name, + (const char *)data_read, + &weechat_php_api_config_section_write_cb, + (const char *)callback_write_name, + (const char *)data_write, + &weechat_php_api_config_section_write_default_cb, + (const char *)callback_write_default_name, + (const char *)data_write_default, + &weechat_php_api_config_section_create_option_cb, + (const char *)callback_create_option_name, + (const char *)data_create_option, + &weechat_php_api_config_section_delete_option_cb, + (const char *)callback_delete_option_name, + (const char *)data_delete_option)); + + API_RETURN_STRING(result); +} + +API_FUNC(config_search_section) +{ + zend_string *z_config_file, *z_section_name; + struct t_config_file *config_file; + char *section_name; + const char *result; + + API_INIT_FUNC(1, "config_search_section", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_config_file, + &z_section_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + config_file = (struct t_config_file *)API_STR2PTR(ZSTR_VAL(z_config_file)); + section_name = ZSTR_VAL(z_section_name); + + result = API_PTR2STR( + weechat_config_search_section (config_file, + (const char *)section_name)); + + API_RETURN_STRING(result); +} + +static int +weechat_php_api_config_option_check_value_cb (const void *pointer, + void *data, + struct t_config_option *option, + const char *value) +{ + int rc; + void *func_argv[3]; + + func_argv[1] = (char *)API_PTR2STR(option); + func_argv[2] = value ? (char *)value : weechat_php_empty_arg; + + weechat_php_cb (pointer, data, func_argv, "sss", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +static void +weechat_php_api_config_option_change_cb (const void *pointer, + void *data, + struct t_config_option *option) +{ + int *rc; + void *func_argv[2]; + + func_argv[1] = (char *)API_PTR2STR(option); + + weechat_php_cb (pointer, data, func_argv, "ss", + WEECHAT_SCRIPT_EXEC_INT, &rc); +} + +static void +weechat_php_api_config_option_delete_cb (const void *pointer, + void *data, + struct t_config_option *option) +{ + int rc; + void *func_argv[2]; + + func_argv[1] = (char *)API_PTR2STR(option); + + weechat_php_cb (pointer, data, func_argv, "ss", + WEECHAT_SCRIPT_EXEC_INT, &rc); +} + +API_FUNC(config_new_option) +{ + zend_string *z_config_file, *z_section, *z_name, *z_type, *z_description; + zend_string *z_string_values, *z_default_value, *z_value; + zend_string *z_data_check_value, *z_data_change, *z_data_delete; + zend_long z_min, z_max, z_null_value_allowed; + zval *z_callback_check_value, *z_callback_change, *z_callback_delete; + struct t_config_file *config_file; + struct t_config_section *section; + char *name, *type, *description, *string_values, *default_value, *value; + char *data_check_value, *data_change, *data_delete; + int min, max, null_value_allowed; + const char *result; + + API_INIT_FUNC(1, "config_new_option", API_RETURN_EMPTY); + if (zend_parse_parameters ( + ZEND_NUM_ARGS(), "SSSSSSllSSlzSzSzS", &z_config_file, &z_section, + &z_name, &z_type, &z_description, &z_string_values, &z_min, &z_max, + &z_default_value, &z_value, &z_null_value_allowed, + &z_callback_check_value, &z_data_check_value, &z_callback_change, + &z_data_change, &z_callback_delete, &z_data_delete) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + config_file = (struct t_config_file *)API_STR2PTR(ZSTR_VAL(z_config_file)); + section = (struct t_config_section *)API_STR2PTR(ZSTR_VAL(z_section)); + name = ZSTR_VAL(z_name); + type = ZSTR_VAL(z_type); + description = ZSTR_VAL(z_description); + string_values = ZSTR_VAL(z_string_values); + min = (int)z_min; + max = (int)z_max; + default_value = ZSTR_VAL(z_default_value); + value = ZSTR_VAL(z_value); + null_value_allowed = (int)z_null_value_allowed; + weechat_php_get_function_name (z_callback_check_value, + callback_check_value_name); + data_check_value = ZSTR_VAL(z_data_check_value); + weechat_php_get_function_name (z_callback_change, callback_change_name); + data_change = ZSTR_VAL(z_data_change); + weechat_php_get_function_name (z_callback_delete, callback_delete_name); + data_delete = ZSTR_VAL(z_data_delete); + + result = API_PTR2STR( + plugin_script_api_config_new_option ( + weechat_php_plugin, + php_current_script, + config_file, + section, + (const char *)name, + (const char *)type, + (const char *)description, + (const char *)string_values, + min, + max, + (const char *)default_value, + (const char *)value, + null_value_allowed, + &weechat_php_api_config_option_check_value_cb, + (const char *)callback_check_value_name, + (const char *)data_check_value, + &weechat_php_api_config_option_change_cb, + (const char *)callback_change_name, + (const char *)data_change, + &weechat_php_api_config_option_delete_cb, + (const char *)callback_delete_name, + (const char *)data_delete)); + + API_RETURN_STRING(result); +} + +API_FUNC(config_search_option) +{ + zend_string *z_config_file, *z_section, *z_option_name; + struct t_config_file *config_file; + struct t_config_section *section; + char *option_name; + const char *result; + + API_INIT_FUNC(1, "config_search_option", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_config_file, &z_section, + &z_option_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + config_file = (struct t_config_file *)API_STR2PTR(ZSTR_VAL(z_config_file)); + section = (struct t_config_section *)API_STR2PTR(ZSTR_VAL(z_section)); + option_name = ZSTR_VAL(z_option_name); + + result = API_PTR2STR( + weechat_config_search_option (config_file, section, + (const char *)option_name)); + + API_RETURN_STRING(result); +} + +API_FUNC(config_string_to_boolean) +{ + zend_string *z_text; + char *text; + int result; + + API_INIT_FUNC(1, "config_string_to_boolean", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_text) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + text = ZSTR_VAL(z_text); + result = weechat_config_string_to_boolean ((const char *)text); + + API_RETURN_INT(result); +} + +API_FUNC(config_option_reset) +{ + zend_string *z_option; + zend_long z_run_callback; + struct t_config_option *option; + int run_callback, result; + + API_INIT_FUNC(1, "config_option_reset", API_RETURN_INT(WEECHAT_CONFIG_OPTION_SET_ERROR)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "Sl", &z_option, &z_run_callback) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(WEECHAT_CONFIG_OPTION_SET_ERROR)); + + option = (struct t_config_option *)API_STR2PTR(ZSTR_VAL(z_option)); + run_callback = (int)z_run_callback; + result = weechat_config_option_reset (option, run_callback); + + API_RETURN_INT(result); +} + +API_FUNC(config_option_set) +{ + zend_string *z_option, *z_value; + zend_long z_run_callback; + struct t_config_option *option; + char *value; + int run_callback, result; + + API_INIT_FUNC(1, "config_option_set", API_RETURN_INT(WEECHAT_CONFIG_OPTION_SET_ERROR)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSl", &z_option, &z_value, + &z_run_callback) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(WEECHAT_CONFIG_OPTION_SET_ERROR)); + + option = (struct t_config_option *)API_STR2PTR(ZSTR_VAL(z_option)); + value = ZSTR_VAL(z_value); + run_callback = (int)z_run_callback; + result = weechat_config_option_set (option, (const char *)value, + run_callback); + + API_RETURN_INT(result); +} + +API_FUNC(config_option_set_null) +{ + zend_string *z_option; + zend_long z_run_callback; + struct t_config_option *option; + int run_callback, result; + + API_INIT_FUNC(1, "config_option_set_null", API_RETURN_INT(WEECHAT_CONFIG_OPTION_SET_ERROR)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "Sl", &z_option, &z_run_callback) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(WEECHAT_CONFIG_OPTION_SET_ERROR)); + + option = (struct t_config_option *)API_STR2PTR(ZSTR_VAL(z_option)); + run_callback = (int)z_run_callback; + result = weechat_config_option_set_null (option, run_callback); + + API_RETURN_INT(result); +} + +API_FUNC(config_option_unset) +{ + zend_string *z_option; + struct t_config_option *option; + int result; + + API_INIT_FUNC(1, "config_option_unset", API_RETURN_INT(WEECHAT_CONFIG_OPTION_UNSET_ERROR)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_option) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(WEECHAT_CONFIG_OPTION_UNSET_ERROR)); + + option = (struct t_config_option *)API_STR2PTR(ZSTR_VAL(z_option)); + result = weechat_config_option_unset (option); + + API_RETURN_INT(result); +} + +API_FUNC(config_option_rename) +{ + zend_string *z_option, *z_new_name; + struct t_config_option *option; + char *new_name; + + API_INIT_FUNC(1, "config_option_rename", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_option, &z_new_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + option = (struct t_config_option *)API_STR2PTR(ZSTR_VAL(z_option)); + new_name = ZSTR_VAL(z_new_name); + weechat_config_option_rename (option, (const char *)new_name); + + API_RETURN_OK; +} + +API_FUNC(config_option_is_null) +{ + zend_string *z_option; + struct t_config_option *option; + int result; + + API_INIT_FUNC(1, "config_option_is_null", API_RETURN_INT(1)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_option) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(1)); + + option = (struct t_config_option *)API_STR2PTR(ZSTR_VAL(z_option)); + result = weechat_config_option_is_null (option); + + API_RETURN_INT(result); +} + +API_FUNC(config_option_default_is_null) +{ + zend_string *z_option; + struct t_config_option *option; + int result; + + API_INIT_FUNC(1, "config_option_default_is_null", API_RETURN_INT(1)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_option) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(1)); + + option = (struct t_config_option *)API_STR2PTR(ZSTR_VAL(z_option)); + result = weechat_config_option_default_is_null (option); + + API_RETURN_INT(result); +} + +API_FUNC(config_boolean) +{ + zend_string *z_option; + struct t_config_option *option; + int result; + + API_INIT_FUNC(1, "config_boolean", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_option) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + option = (struct t_config_option *)API_STR2PTR(ZSTR_VAL(z_option)); + result = weechat_config_boolean (option); + + API_RETURN_INT(result); +} + +API_FUNC(config_boolean_default) +{ + zend_string *z_option; + struct t_config_option *option; + int result; + + API_INIT_FUNC(1, "config_boolean_default", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_option) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + option = (struct t_config_option *)API_STR2PTR(ZSTR_VAL(z_option)); + result = weechat_config_boolean_default (option); + + API_RETURN_INT(result); +} + +API_FUNC(config_integer) +{ + zend_string *z_option; + struct t_config_option *option; + int result; + + API_INIT_FUNC(1, "config_integer", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_option) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + option = (struct t_config_option *)API_STR2PTR(ZSTR_VAL(z_option)); + result = weechat_config_integer (option); + + API_RETURN_INT(result); +} + +API_FUNC(config_integer_default) +{ + zend_string *z_option; + struct t_config_option *option; + int result; + + API_INIT_FUNC(1, "config_integer_default", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_option) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + option = (struct t_config_option *)API_STR2PTR(ZSTR_VAL(z_option)); + result = weechat_config_integer_default (option); + + API_RETURN_INT(result); +} + +API_FUNC(config_string) +{ + zend_string *z_option; + struct t_config_option *option; + const char *result; + + API_INIT_FUNC(1, "config_string", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_option) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + option = (struct t_config_option *)API_STR2PTR(ZSTR_VAL(z_option)); + result = weechat_config_string (option); + + API_RETURN_STRING(result); +} + +API_FUNC(config_string_default) +{ + zend_string *z_option; + struct t_config_option *option; + const char *result; + + API_INIT_FUNC(1, "config_string_default", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_option) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + option = (struct t_config_option *)API_STR2PTR(ZSTR_VAL(z_option)); + result = weechat_config_string_default (option); + + API_RETURN_STRING(result); +} + +API_FUNC(config_color) +{ + zend_string *z_option; + struct t_config_option *option; + const char *result; + + API_INIT_FUNC(1, "config_color", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_option) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + option = (struct t_config_option *)API_STR2PTR(ZSTR_VAL(z_option)); + result = weechat_config_color (option); + + API_RETURN_STRING(result); +} + +API_FUNC(config_color_default) +{ + zend_string *z_option; + struct t_config_option *option; + const char *result; + + API_INIT_FUNC(1, "config_color_default", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_option) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + option = (struct t_config_option *)API_STR2PTR(ZSTR_VAL(z_option)); + result = weechat_config_color_default (option); + + API_RETURN_STRING(result); +} + +API_FUNC(config_write_option) +{ + zend_string *z_config_file, *z_option; + struct t_config_file *config_file; + struct t_config_option *option; + + API_INIT_FUNC(1, "config_write_option", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_config_file, &z_option) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + config_file = (struct t_config_file *)API_STR2PTR(ZSTR_VAL(z_config_file)); + option = (struct t_config_option *)API_STR2PTR(ZSTR_VAL(z_option)); + + weechat_config_write_option (config_file, option); + + API_RETURN_OK; +} + +API_FUNC(config_write_line) +{ + zend_string *z_config_file, *z_option_name, *z_value; + struct t_config_file *config_file; + char *option_name, *value; + + API_INIT_FUNC(1, "config_write_line", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_config_file, &z_option_name, + &z_value) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + config_file = (struct t_config_file *)API_STR2PTR(ZSTR_VAL(z_config_file)); + option_name = ZSTR_VAL(z_option_name); + value = ZSTR_VAL(z_value); + + weechat_config_write_line (config_file, + (const char *)option_name, + (const char *)value); + + API_RETURN_OK; +} + +API_FUNC(config_write) +{ + zend_string *z_config_file; + struct t_config_file *config_file; + int result; + + API_INIT_FUNC(1, "config_write", API_RETURN_INT(WEECHAT_CONFIG_WRITE_ERROR)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "S", &z_config_file) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(WEECHAT_CONFIG_WRITE_ERROR)); + + config_file = (struct t_config_file *)API_STR2PTR(ZSTR_VAL(z_config_file)); + result = weechat_config_write (config_file); + + API_RETURN_INT(result); +} + +API_FUNC(config_read) +{ + zend_string *z_config_file; + struct t_config_file *config_file; + int result; + + API_INIT_FUNC(1, "config_read", API_RETURN_INT(WEECHAT_CONFIG_READ_FILE_NOT_FOUND)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "S", &z_config_file) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(WEECHAT_CONFIG_READ_FILE_NOT_FOUND)); + + config_file = (struct t_config_file *)API_STR2PTR(ZSTR_VAL(z_config_file)); + result = weechat_config_read (config_file); + + API_RETURN_INT(result); +} + +API_FUNC(config_reload) +{ + zend_string *z_config_file; + struct t_config_file *config_file; + int result; + + API_INIT_FUNC(1, "config_reload", API_RETURN_INT(WEECHAT_CONFIG_READ_FILE_NOT_FOUND)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "S", &z_config_file) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(WEECHAT_CONFIG_READ_FILE_NOT_FOUND)); + + config_file = (struct t_config_file *)API_STR2PTR(ZSTR_VAL(z_config_file)); + result = weechat_config_reload (config_file); + + API_RETURN_INT(result); +} + +API_FUNC(config_option_free) +{ + zend_string *z_option; + struct t_config_option *option; + + API_INIT_FUNC(1, "config_option_free", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_option) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + option = (struct t_config_option *)API_STR2PTR(ZSTR_VAL(z_option)); + weechat_config_option_free (option); + + API_RETURN_OK; +} + +API_FUNC(config_section_free_options) +{ + zend_string *z_section; + struct t_config_section *section; + + API_INIT_FUNC(1, "config_section_free_options", API_RETURN_ERROR); + + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_section) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + section = (struct t_config_section *)API_STR2PTR(ZSTR_VAL(z_section)); + weechat_config_section_free_options (section); + + API_RETURN_OK; +} + +API_FUNC(config_section_free) +{ + zend_string *z_section; + struct t_config_section *section; + + API_INIT_FUNC(1, "config_section_free", API_RETURN_ERROR); + + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_section) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + section = (struct t_config_section *)API_STR2PTR(ZSTR_VAL(z_section)); + weechat_config_section_free (section); + + API_RETURN_OK; +} + +API_FUNC(config_free) +{ + zend_string *z_config_file; + struct t_config_file *config_file; + + API_INIT_FUNC(1, "config_free", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "S", &z_config_file) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + config_file = (struct t_config_file *)API_STR2PTR(ZSTR_VAL(z_config_file)); + weechat_config_free (config_file); + + API_RETURN_OK; +} + +API_FUNC(config_get) +{ + zend_string *z_option_name; + char *option_name; + const char *result; + + API_INIT_FUNC(1, "config_get", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "S", &z_option_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + option_name = ZSTR_VAL(z_option_name); + + result = API_PTR2STR(weechat_config_get ((const char *)option_name)); + + API_RETURN_STRING(result); +} + +API_FUNC(config_get_plugin) +{ + zend_string *z_option; + char *option; + const char *result; + + API_INIT_FUNC(1, "config_get_plugin", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_option) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + option = ZSTR_VAL(z_option); + result = plugin_script_api_config_get_plugin (weechat_php_plugin, + php_current_script, + (const char *)option); + + API_RETURN_STRING(result); +} + +API_FUNC(config_is_set_plugin) +{ + zend_string *z_option; + char *option; + int result; + + API_INIT_FUNC(1, "config_is_set_plugin", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_option) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + option = ZSTR_VAL(z_option); + result = plugin_script_api_config_is_set_plugin (weechat_php_plugin, + php_current_script, + (const char *)option); + + API_RETURN_INT(result); +} + +API_FUNC(config_set_plugin) +{ + zend_string *z_option, *z_value; + char *option, *value; + int result; + + API_INIT_FUNC(1, "config_set_plugin", API_RETURN_INT(WEECHAT_CONFIG_OPTION_SET_ERROR)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_option, &z_value) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(WEECHAT_CONFIG_OPTION_SET_ERROR)); + + option = ZSTR_VAL(z_option); + value = ZSTR_VAL(z_value); + result = plugin_script_api_config_set_plugin (weechat_php_plugin, + php_current_script, + (const char *)option, + (const char *)value); + + API_RETURN_INT(result); +} + +API_FUNC(config_set_desc_plugin) +{ + zend_string *z_option, *z_description; + char *option, *description; + + API_INIT_FUNC(1, "config_set_desc_plugin", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_option, &z_description) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + option = ZSTR_VAL(z_option); + description = ZSTR_VAL(z_description); + plugin_script_api_config_set_desc_plugin (weechat_php_plugin, + php_current_script, + (const char *)option, + (const char *)description); + + API_RETURN_OK; +} + +API_FUNC(config_unset_plugin) +{ + zend_string *z_option; + char *option; + int result; + + API_INIT_FUNC(1, "config_unset_plugin", API_RETURN_INT(WEECHAT_CONFIG_OPTION_UNSET_ERROR)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_option) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(WEECHAT_CONFIG_OPTION_UNSET_ERROR)); + + option = ZSTR_VAL(z_option); + result = plugin_script_api_config_unset_plugin (weechat_php_plugin, + php_current_script, + (const char *)option); + + API_RETURN_INT(result); +} + +API_FUNC(key_bind) +{ + zend_string *z_context; + zval *z_keys; + char *context; + struct t_hashtable *keys; + int result; + + API_INIT_FUNC(1, "key_bind", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "Sa", &z_context, &z_keys) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + context = ZSTR_VAL(z_context); + keys = weechat_php_array_to_hashtable (z_keys, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING); + result = weechat_key_bind ((const char *)context, keys); + + API_RETURN_INT(result); +} + +API_FUNC(key_unbind) +{ + zend_string *z_context, *z_key; + int result; + char *context, *key; + + API_INIT_FUNC(1, "key_unbind", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_context, &z_key) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + context = ZSTR_VAL(z_context); + key = ZSTR_VAL(z_key); + result = weechat_key_unbind ((const char *)context, (const char *)key); + + API_RETURN_INT(result); +} + +API_FUNC(prefix) +{ + zend_string *z_prefix; + char *prefix; + const char *result; + + API_INIT_FUNC(0, "prefix", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_prefix) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + prefix = ZSTR_VAL(z_prefix); + result = weechat_prefix ((const char *)prefix); + + API_RETURN_STRING(result); +} + +API_FUNC(color) +{ + zend_string *z_color_name; + char *color_name; + const char *result; + + API_INIT_FUNC(0, "color", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_color_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + color_name = ZSTR_VAL(z_color_name); + result = weechat_color ((const char *)color_name); + + API_RETURN_STRING(result); +} + +API_FUNC(print) +{ + zend_string *z_buffer, *z_message; + struct t_gui_buffer *buffer; + char *message; + + API_INIT_FUNC(0, "print", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_buffer, &z_message) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + message = ZSTR_VAL(z_message); + plugin_script_api_printf (weechat_php_plugin, php_current_script, buffer, + "%s", message); + + API_RETURN_OK; +} + +API_FUNC(print_date_tags) +{ + zend_string *z_buffer, *z_tags, *z_message; + zend_long z_date; + struct t_gui_buffer *buffer; + time_t date; + char *tags, *message; + + API_INIT_FUNC(1, "print_date_tags", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SlSS", &z_buffer, &z_date, &z_tags, + &z_message) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + date = (time_t)z_date; + tags = ZSTR_VAL(z_tags); + message = ZSTR_VAL(z_message); + plugin_script_api_printf_date_tags (weechat_php_plugin, + php_current_script, + buffer, + date, + (const char *)tags, + "%s", + message); + + API_RETURN_OK; +} + +API_FUNC(print_y) +{ + zend_string *z_buffer, *z_message; + zend_long z_y; + struct t_gui_buffer *buffer; + int y; + char *message; + + API_INIT_FUNC(1, "print_y", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SlS", &z_buffer, &z_y, &z_message) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + y = (int)z_y; + message = ZSTR_VAL(z_message); + plugin_script_api_printf_y (weechat_php_plugin, + php_current_script, + buffer, + y, + "%s", + message); + + API_RETURN_OK; +} + +API_FUNC(log_print) +{ + zend_string *z_message; + char *message; + + API_INIT_FUNC(1, "log_print", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_message) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + message = ZSTR_VAL(z_message); + plugin_script_api_log_printf (weechat_php_plugin, php_current_script, + "%s", message); + + API_RETURN_OK; +} + +static int +weechat_php_api_hook_command_cb (const void *pointer, void *data, + struct t_gui_buffer *buffer, + int argc, char **argv, char **argv_eol) +{ + int rc; + void *func_argv[3]; + + /* make C compiler happy */ + (void) argv; + + func_argv[1] = (char *)API_PTR2STR(buffer); + func_argv[2] = (argc > 1) ? argv_eol[1] : weechat_php_empty_arg; + + weechat_php_cb (pointer, data, func_argv, "sss", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +API_FUNC(hook_command) +{ + zend_string *z_command, *z_description, *z_args, *z_args_description; + zend_string *z_completion, *z_data; + zval *z_callback; + char *command, *description, *args, *args_description, *completion, *data; + const char *result; + + API_INIT_FUNC(1, "hook_command", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSSSSzS", &z_command, &z_description, &z_args, + &z_args_description, &z_completion, &z_callback, + &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + command = ZSTR_VAL(z_command); + description = ZSTR_VAL(z_description); + args = ZSTR_VAL(z_args); + args_description = ZSTR_VAL(z_args_description); + completion = ZSTR_VAL(z_completion); + weechat_php_get_function_name (z_callback, callback_name); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR( + plugin_script_api_hook_command ( + weechat_php_plugin, + php_current_script, + (const char *)command, + (const char *)description, + (const char *)args, + (const char *)args_description, + (const char *)completion, + &weechat_php_api_hook_command_cb, + (const char *)callback_name, + (const char *)data)); + + API_RETURN_STRING(result); +} + +static int +weechat_php_api_hook_completion_cb (const void *pointer, void *data, + const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion) +{ + int rc; + void *func_argv[4]; + + func_argv[1] = completion_item ? (char *)completion_item : weechat_php_empty_arg; + func_argv[2] = (char *)API_PTR2STR(buffer); + func_argv[3] = (char *)API_PTR2STR(completion); + + weechat_php_cb (pointer, data, func_argv, "ssss", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +API_FUNC(hook_completion) +{ + zend_string *z_completion, *z_description, *z_data; + zval *z_callback; + char *completion, *description, *data; + const char *result; + + API_INIT_FUNC(1, "hook_completion", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSzS", &z_completion, &z_description, + &z_callback, &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + completion = ZSTR_VAL(z_completion); + description = ZSTR_VAL(z_description); + weechat_php_get_function_name (z_callback, callback_name); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR( + plugin_script_api_hook_completion ( + weechat_php_plugin, + php_current_script, + (const char *)completion, + (const char *)description, + &weechat_php_api_hook_completion_cb, + (const char *)callback_name, + (const char *)data)); + + API_RETURN_STRING(result); +} + +API_FUNC(hook_completion_get_string) +{ + zend_string *z_completion, *z_property; + struct t_gui_completion *completion; + char *property; + const char *result; + + API_INIT_FUNC(1, "hook_completion_get_string", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_completion, &z_property) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + completion = (struct t_gui_completion *)API_STR2PTR(ZSTR_VAL(z_completion)); + property = ZSTR_VAL(z_property); + result = weechat_hook_completion_get_string (completion, + (const char *)property); + + API_RETURN_STRING(result); +} + +API_FUNC(hook_completion_list_add) +{ + zend_string *z_completion, *z_word, *z_where; + zend_long z_nick_completion; + struct t_gui_completion *completion; + char *word, *where; + int nick_completion; + + API_INIT_FUNC(1, "hook_completion_list_add", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSlS", &z_completion, &z_word, + &z_nick_completion, &z_where) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + completion = (struct t_gui_completion *)API_STR2PTR(ZSTR_VAL(z_completion)); + word = ZSTR_VAL(z_word); + nick_completion = (int)z_nick_completion; + where = ZSTR_VAL(z_where); + weechat_hook_completion_list_add (completion, + (const char *)word, + nick_completion, + (const char *)where); + + API_RETURN_OK; +} + +static int +weechat_php_api_hook_command_run_cb (const void *pointer, void *data, + struct t_gui_buffer *buffer, + const char *command) +{ + int rc; + void *func_argv[3]; + + func_argv[1] = (char *)API_PTR2STR(buffer); + func_argv[2] = command ? (char *)command : weechat_php_empty_arg; + + weechat_php_cb (pointer, data, func_argv, "sss", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +API_FUNC(hook_command_run) +{ + zend_string *z_command, *z_data; + zval *z_callback; + char *command, *data; + const char *result; + + API_INIT_FUNC(1, "hook_command_run", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SzS", &z_command, &z_callback, + &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + command = ZSTR_VAL(z_command); + weechat_php_get_function_name (z_callback, callback_name); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR( + plugin_script_api_hook_command_run ( + weechat_php_plugin, + php_current_script, + (const char *)command, + &weechat_php_api_hook_command_run_cb, + (const char *)callback_name, + (const char *)data)); + + API_RETURN_STRING(result); +} + +static int +weechat_php_api_hook_timer_cb (const void *pointer, void *data, + int remaining_calls) +{ + int rc; + void *func_argv[2]; + + func_argv[1] = &remaining_calls; + + weechat_php_cb (pointer, data, func_argv, "si", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +API_FUNC(hook_timer) +{ + zend_long z_interval, z_align_second, z_max_calls; + zval *z_callback; + zend_string *z_data; + int interval, align_second, max_calls; + char *data; + const char *result; + + API_INIT_FUNC(1, "hook_timer", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "lllzS", &z_interval, &z_align_second, + &z_max_calls, &z_callback, &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + interval = (int)z_interval; + align_second = (int)z_align_second; + max_calls = (int)z_max_calls; + weechat_php_get_function_name (z_callback, callback_name); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR( + plugin_script_api_hook_timer ( + weechat_php_plugin, + php_current_script, + interval, + align_second, + max_calls, + &weechat_php_api_hook_timer_cb, + (const char *)callback_name, + (const char *)data)); + + API_RETURN_STRING(result); +} + +static int +weechat_php_api_hook_fd_cb (const void *pointer, void *data, + int fd) +{ + int rc; + void *func_argv[2]; + + func_argv[1] = &fd; + + weechat_php_cb (pointer, data, func_argv, "si", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +API_FUNC(hook_fd) +{ + zend_long z_fd, z_flag_read, z_flag_write, z_flag_exception; + zval *z_callback; + zend_string *z_data; + int fd, flag_read, flag_write, flag_exception; + char *data; + const char *result; + + API_INIT_FUNC(1, "hook_fd", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "llllzS", &z_fd, &z_flag_read, &z_flag_write, + &z_flag_exception, &z_callback, + &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + fd = (int)z_fd; + flag_read = (int)z_flag_read; + flag_write = (int)z_flag_write; + flag_exception = (int)z_flag_exception; + weechat_php_get_function_name (z_callback, callback_name); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR( + plugin_script_api_hook_fd ( + weechat_php_plugin, + php_current_script, fd, + flag_read, + flag_write, + flag_exception, + &weechat_php_api_hook_fd_cb, + (const char *)callback_name, + (const char *)data)); + + API_RETURN_STRING(result); +} + +static int +weechat_php_api_hook_process_cb (const void *pointer, void *data, + const char *command, int return_code, + const char *out, const char *err) +{ + int rc; + void *func_argv[5]; + + func_argv[1] = command ? (char *)command : weechat_php_empty_arg; + func_argv[2] = &return_code; + func_argv[3] = out ? (char *)out : weechat_php_empty_arg; + func_argv[4] = err ? (char *)err : weechat_php_empty_arg; + + weechat_php_cb (pointer, data, func_argv, "ssiss", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +API_FUNC(hook_process) +{ + zend_string *z_command, *z_data; + zend_long z_timeout; + zval *z_callback; + char *command, *data; + int timeout; + const char *result; + + API_INIT_FUNC(1, "hook_process", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SlzS", &z_command, &z_timeout, &z_callback, + &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + command = ZSTR_VAL(z_command); + timeout = (int)z_timeout; + weechat_php_get_function_name (z_callback, callback_name); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR( + plugin_script_api_hook_process ( + weechat_php_plugin, + php_current_script, + (const char *)command, + timeout, + &weechat_php_api_hook_process_cb, + (const char *)callback_name, + (const char *)data)); + + API_RETURN_STRING(result); +} + +static int +weechat_php_api_hook_process_hashtable_cb (const void *pointer, void *data, + const char *command, + int return_code, + const char *out, const char *err) +{ + int rc; + void *func_argv[5]; + + func_argv[1] = command ? (char *)command : weechat_php_empty_arg; + func_argv[2] = &return_code; + func_argv[3] = out ? (char *)out : weechat_php_empty_arg; + func_argv[4] = err ? (char *)err : weechat_php_empty_arg; + + weechat_php_cb (pointer, data, func_argv, "ssiss", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +API_FUNC(hook_process_hashtable) +{ + zend_string *z_command, *z_data; + zval *z_options, *z_callback; + zend_long z_timeout; + char *command, *data; + struct t_hashtable *options; + int timeout; + const char *result; + + API_INIT_FUNC(1, "hook_process_hashtable", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SalzS", &z_command, &z_options, &z_timeout, + &z_callback, &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + command = ZSTR_VAL(z_command); + options = weechat_php_array_to_hashtable ( + z_options, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING); + timeout = (int)z_timeout; + weechat_php_get_function_name (z_callback, callback_name); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR( + plugin_script_api_hook_process_hashtable ( + weechat_php_plugin, + php_current_script, + (const char *)command, + options, + timeout, + &weechat_php_api_hook_process_hashtable_cb, + (const char *)callback_name, + (const char *)data)); + + API_RETURN_STRING(result); +} + +static int +weechat_php_api_hook_connect_cb (const void *pointer, void *data, int status, + int gnutls_rc, int sock, const char *error, + const char *ip_address) +{ + int rc; + void *func_argv[6]; + + func_argv[1] = &status; + func_argv[2] = &gnutls_rc; + func_argv[3] = &sock; + func_argv[4] = error ? (char *)error : weechat_php_empty_arg; + func_argv[5] = ip_address ? (char *)ip_address : weechat_php_empty_arg; + + weechat_php_cb (pointer, data, func_argv, "siiiss", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +API_FUNC(hook_connect) +{ + zend_string *z_proxy, *z_address, *z_gnutls_sess, *z_gnutls_cb; + zend_string *z_gnutls_priorities, *z_local_hostname, *z_data; + zend_long z_port, z_ipv6, z_retry, z_gnutls_dhkey_size; + zval *z_callback; + char *proxy, *address, *gnutls_priorities, *local_hostname, *data; + int port, ipv6, retry; + void *gnutls_sess, *gnutls_cb; + int gnutls_dhkey_size; + const char *result; + + API_INIT_FUNC(1, "hook_connect", API_RETURN_EMPTY); + if (zend_parse_parameters ( + ZEND_NUM_ARGS(), "SSlllSSlSSzS", &z_proxy, &z_address, &z_port, + &z_ipv6, &z_retry, &z_gnutls_sess, &z_gnutls_cb, + &z_gnutls_dhkey_size, &z_gnutls_priorities, &z_local_hostname, + &z_callback, &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + proxy = ZSTR_VAL(z_proxy); + address = ZSTR_VAL(z_address); + port = (int)z_port; + ipv6 = (int)z_ipv6; + retry = (int)z_retry; + gnutls_sess = (void *)API_STR2PTR(ZSTR_VAL(z_gnutls_sess)); + gnutls_cb = (void *)API_STR2PTR(ZSTR_VAL(z_gnutls_cb)); + gnutls_dhkey_size = (int)z_gnutls_dhkey_size; + gnutls_priorities = ZSTR_VAL(z_gnutls_priorities); + local_hostname = ZSTR_VAL(z_local_hostname); + weechat_php_get_function_name (z_callback, callback_name); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR( + plugin_script_api_hook_connect ( + weechat_php_plugin, + php_current_script, + (const char *)proxy, + (const char *)address, + port, + ipv6, + retry, + gnutls_sess, + gnutls_cb, + gnutls_dhkey_size, + (const char *)gnutls_priorities, + (const char *)local_hostname, + &weechat_php_api_hook_connect_cb, + (const char *)callback_name, + (const char *)data)); + + API_RETURN_STRING(result); +} + +static int +weechat_php_api_hook_print_cb (const void *pointer, void *data, + struct t_gui_buffer *buffer, time_t date, + int tags_count, const char **tags, + int displayed, int highlight, + const char *prefix, const char *message) +{ + int rc; + void *func_argv[9]; + + func_argv[1] = (char *)API_PTR2STR(buffer); + func_argv[2] = &date; + func_argv[3] = &tags_count; + func_argv[4] = tags ? (char *)tags : weechat_php_empty_arg; + func_argv[5] = &displayed; + func_argv[6] = &highlight; + func_argv[7] = prefix ? (char *)prefix : weechat_php_empty_arg; + func_argv[8] = message ? (char *)message : weechat_php_empty_arg; + + weechat_php_cb (pointer, data, func_argv, "ssiisiiss", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +API_FUNC(hook_print) +{ + zend_string *z_buffer, *z_tags, *z_message, *z_data; + zend_long z_strip_colors; + zval *z_callback; + struct t_gui_buffer *buffer; + char *tags, *message, *data; + int strip_colors; + const char *result; + + API_INIT_FUNC(1, "hook_print", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSSlzS", &z_buffer, &z_tags, &z_message, + &z_strip_colors, &z_callback, + &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + tags = ZSTR_VAL(z_tags); + message = ZSTR_VAL(z_message); + strip_colors = (int)z_strip_colors; + weechat_php_get_function_name (z_callback, callback_name); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR( + plugin_script_api_hook_print ( + weechat_php_plugin, + php_current_script, buffer, + (const char *)tags, + (const char *)message, + strip_colors, + &weechat_php_api_hook_print_cb, + (const char *)callback_name, + (const char *)data)); + + API_RETURN_STRING(result); +} + +static int +weechat_php_api_hook_signal_cb (const void *pointer, void *data, + const char *signal, const char *type_data, + void *signal_data) +{ + int rc; + void *func_argv[4]; + + func_argv[1] = signal ? (char *)signal : weechat_php_empty_arg; + func_argv[2] = type_data ? (char *)type_data : weechat_php_empty_arg; + func_argv[3] = signal_data ? (char *)signal_data : weechat_php_empty_arg; + + weechat_php_cb (pointer, data, func_argv, "ssss", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +API_FUNC(hook_signal) +{ + zend_string *z_signal, *z_data; + zval *z_callback; + char *signal, *data; + const char *result; + + API_INIT_FUNC(1, "hook_signal", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SzS", &z_signal, &z_callback, + &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + signal = ZSTR_VAL(z_signal); + weechat_php_get_function_name (z_callback, callback_name); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR( + plugin_script_api_hook_signal ( + weechat_php_plugin, + php_current_script, + (const char *)signal, + &weechat_php_api_hook_signal_cb, + (const char *)callback_name, + (const char *)data)); + + API_RETURN_STRING(result); +} + +API_FUNC(hook_signal_send) +{ + zend_string *z_signal, *z_type_data, *z_signal_data; + char *signal, *type_data; + void *signal_data; + int result; + + API_INIT_FUNC(1, "hook_signal_send", API_RETURN_INT(WEECHAT_RC_ERROR)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_signal, &z_type_data, + &z_signal_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(WEECHAT_RC_ERROR)); + + signal = ZSTR_VAL(z_signal); + type_data = ZSTR_VAL(z_type_data); + signal_data = (void *)API_STR2PTR(ZSTR_VAL(z_signal_data)); + result = weechat_hook_signal_send ((const char *)signal, + (const char *)type_data, signal_data); + + API_RETURN_INT(result); +} + +static int +weechat_php_api_hook_hsignal_cb (const void *pointer, void *data, + const char *signal, + struct t_hashtable *hashtable) +{ + int rc; + void *func_argv[3]; + + func_argv[1] = signal ? (char *)signal : weechat_php_empty_arg; + func_argv[2] = hashtable; + + weechat_php_cb (pointer, data, func_argv, "ssh", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +API_FUNC(hook_hsignal) +{ + zend_string *z_signal, *z_data; + zval *z_callback; + char *signal, *data; + const char *result; + + API_INIT_FUNC(1, "hook_hsignal", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SzS", &z_signal, &z_callback, + &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + signal = ZSTR_VAL(z_signal); + weechat_php_get_function_name (z_callback, callback_name); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR( + plugin_script_api_hook_hsignal ( + weechat_php_plugin, + php_current_script, + (const char *)signal, + &weechat_php_api_hook_hsignal_cb, + (const char *)callback_name, + (const char *)data)); + + API_RETURN_STRING(result); +} + +API_FUNC(hook_hsignal_send) +{ + zend_string *z_signal; + zval *z_hashtable; + char *signal; + struct t_hashtable *hashtable; + int result; + + API_INIT_FUNC(1, "hook_hsignal_send", API_RETURN_INT(WEECHAT_RC_ERROR)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "Sa", &z_signal, &z_hashtable) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(WEECHAT_RC_ERROR)); + + signal = ZSTR_VAL(z_signal); + hashtable = weechat_php_array_to_hashtable ( + z_hashtable, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING); + result = weechat_hook_hsignal_send ((const char *)signal, hashtable); + + API_RETURN_INT(result); +} + +static int +weechat_php_api_hook_config_cb (const void *pointer, void *data, + const char *option, const char *value) +{ + int rc; + void *func_argv[3]; + + func_argv[1] = option ? (char *)option : weechat_php_empty_arg; + func_argv[2] = value ? (char *)value : weechat_php_empty_arg; + + weechat_php_cb (pointer, data, func_argv, "sss", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +API_FUNC(hook_config) +{ + zend_string *z_option, *z_data; + zval *z_callback; + char *option, *data; + const char *result; + + API_INIT_FUNC(1, "hook_config", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SzS", &z_option, &z_callback, + &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + option = ZSTR_VAL(z_option); + weechat_php_get_function_name (z_callback, callback_name); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR( + plugin_script_api_hook_config ( + weechat_php_plugin, + php_current_script, + (const char *)option, + &weechat_php_api_hook_config_cb, + (const char *)callback_name, + (const char *)data)); + + API_RETURN_STRING(result); +} + +static char * +weechat_php_api_hook_modifier_cb (const void *pointer, void *data, + const char *modifier, + const char *modifier_data, + const char *string) +{ + char *rc; + void *func_argv[4]; + + func_argv[1] = modifier ? (char *)modifier : weechat_php_empty_arg; + func_argv[2] = modifier_data ? (char *)modifier_data : weechat_php_empty_arg; + func_argv[3] = string ? (char *)string : weechat_php_empty_arg; + + weechat_php_cb (pointer, data, func_argv, "ssss", + WEECHAT_SCRIPT_EXEC_STRING, &rc); + + return rc; +} + +API_FUNC(hook_modifier) +{ + zend_string *z_modifier, *z_data; + zval *z_callback; + char *modifier, *data; + const char *result; + + API_INIT_FUNC(1, "hook_modifier", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SzS", &z_modifier, &z_callback, + &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + modifier = ZSTR_VAL(z_modifier); + weechat_php_get_function_name (z_callback, callback_name); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR( + plugin_script_api_hook_modifier ( + weechat_php_plugin, + php_current_script, + (const char *)modifier, + &weechat_php_api_hook_modifier_cb, + (const char *)callback_name, + (const char *)data)); + + API_RETURN_STRING(result); +} + +API_FUNC(hook_modifier_exec) +{ + zend_string *z_modifier, *z_modifier_data, *z_string; + char *modifier, *modifier_data, *string, *result; + + API_INIT_FUNC(1, "hook_modifier_exec", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_modifier, &z_modifier_data, + &z_string) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + modifier = ZSTR_VAL(z_modifier); + modifier_data = ZSTR_VAL(z_modifier_data); + string = ZSTR_VAL(z_string); + result = weechat_hook_modifier_exec ((const char *)modifier, + (const char *)modifier_data, + (const char *)string); + + API_RETURN_STRING_FREE(result); +} + +static const char * +weechat_php_api_hook_info_cb (const void *pointer, + void *data, + const char *info_name, + const char *arguments) +{ + char *rc; + void *func_argv[3]; + + func_argv[1] = info_name ? (char *)info_name : weechat_php_empty_arg; + func_argv[2] = arguments ? (char *)arguments : weechat_php_empty_arg; + + weechat_php_cb (pointer, data, func_argv, "sss", + WEECHAT_SCRIPT_EXEC_STRING, &rc); + + return API_STATIC_STRING(rc); +} + +API_FUNC(hook_info) +{ + zend_string *z_info_name, *z_description, *z_args_description, *z_data; + zval *z_callback; + char *info_name, *description, *args_description, *data; + const char *result; + + API_INIT_FUNC(1, "hook_info", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSSzS", &z_info_name, &z_description, + &z_args_description, &z_callback, + &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + info_name = ZSTR_VAL(z_info_name); + description = ZSTR_VAL(z_description); + args_description = ZSTR_VAL(z_args_description); + weechat_php_get_function_name (z_callback, callback_name); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR( + plugin_script_api_hook_info ( + weechat_php_plugin, + php_current_script, + (const char *)info_name, + (const char *)description, + (const char *)args_description, + &weechat_php_api_hook_info_cb, + (const char *)callback_name, + (const char *)data)); + + API_RETURN_STRING(result); +} + +struct t_hashtable * +weechat_php_api_hook_info_hashtable_cb (const void *pointer, void *data, + const char *info_name, + struct t_hashtable *hashtable) +{ + struct t_hashtable *rc; + void *func_argv[3]; + + func_argv[1] = (info_name) ? (char *)info_name : weechat_php_empty_arg; + func_argv[2] = hashtable; + + weechat_php_cb (pointer, data, func_argv, "ssh", + WEECHAT_SCRIPT_EXEC_HASHTABLE, &rc); + + return rc; +} + +API_FUNC(hook_info_hashtable) +{ + zend_string *z_info_name, *z_description, *z_args_description; + zend_string *z_output_description, *z_data; + zval *z_callback; + char *info_name, *description, *args_description, *output_description; + char *data; + const char *result; + + API_INIT_FUNC(1, "hook_info_hashtable", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSSSSzS", &z_info_name, &z_description, + &z_args_description, &z_output_description, + &z_callback, &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + info_name = ZSTR_VAL(z_info_name); + description = ZSTR_VAL(z_description); + args_description = ZSTR_VAL(z_args_description); + output_description = ZSTR_VAL(z_output_description); + data = ZSTR_VAL(z_data); + weechat_php_get_function_name (z_callback, callback_name); + + result = API_PTR2STR( + plugin_script_api_hook_info_hashtable ( + weechat_php_plugin, + php_current_script, + info_name, + description, + args_description, + output_description, + &weechat_php_api_hook_info_hashtable_cb, + callback_name, + data)); + + API_RETURN_STRING(result); +} + +struct t_infolist * +weechat_php_api_hook_infolist_cb (const void *pointer, void *data, + const char *info_name, + void *obj_pointer, + const char *arguments) +{ + struct t_infolist *rc; + void *func_argv[4]; + + func_argv[1] = (info_name) ? (char *)info_name : weechat_php_empty_arg; + func_argv[2] = (char *)API_PTR2STR(obj_pointer); + func_argv[3] = (arguments) ? (char *)arguments : weechat_php_empty_arg; + + weechat_php_cb (pointer, data, func_argv, "ssss", + WEECHAT_SCRIPT_EXEC_POINTER, &rc); + + return rc; +} + +API_FUNC(hook_infolist) +{ + zend_string *z_infolist_name, *z_description, *z_pointer_description; + zend_string *z_args_description, *z_data; + zval *z_callback; + char *infolist_name, *description, *pointer_description, *args_description; + char *data; + const char *result; + + API_INIT_FUNC(1, "hook_infolist", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSSSzS", &z_infolist_name, &z_description, + &z_pointer_description, &z_args_description, + &z_callback, &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + infolist_name = ZSTR_VAL(z_infolist_name); + description = ZSTR_VAL(z_description); + pointer_description = ZSTR_VAL(z_pointer_description); + args_description = ZSTR_VAL(z_args_description); + data = ZSTR_VAL(z_data); + weechat_php_get_function_name (z_callback, callback_name); + + result = API_PTR2STR( + plugin_script_api_hook_infolist ( + weechat_php_plugin, + php_current_script, + infolist_name, + description, + pointer_description, + args_description, + &weechat_php_api_hook_infolist_cb, + callback_name, + data)); + + API_RETURN_STRING(result); +} + +struct t_hashtable * +weechat_php_api_hook_focus_cb (const void *pointer, void *data, + struct t_hashtable *info) +{ + struct t_hashtable *rc; + void *func_argv[2]; + + func_argv[1] = info; + + weechat_php_cb (pointer, data, func_argv, "sh", + WEECHAT_SCRIPT_EXEC_HASHTABLE, &rc); + + return rc; +} + +API_FUNC(hook_focus) +{ + zend_string *z_area, *z_data; + zval *z_callback; + char *area, *data; + const char *result; + + API_INIT_FUNC(1, "hook_focus", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "SzS", &z_area, &z_callback, + &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + area = ZSTR_VAL(z_area); + data = ZSTR_VAL(z_data); + weechat_php_get_function_name (z_callback, callback_name); + + result = API_PTR2STR( + plugin_script_api_hook_focus ( + weechat_php_plugin, + php_current_script, + area, + &weechat_php_api_hook_focus_cb, + callback_name, + data)); + + API_RETURN_STRING(result); +} + +API_FUNC(hook_set) +{ + zend_string *z_hook, *z_property, *z_value; + struct t_hook *hook; + char *property, *value; + + API_INIT_FUNC(1, "hook_set", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "SSS", &z_hook, &z_property, + &z_value) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + hook = (struct t_hook *)API_STR2PTR(ZSTR_VAL(z_hook)); + property = ZSTR_VAL(z_property); + value = ZSTR_VAL(z_value); + weechat_hook_set (hook, (const char *)property, (const char *)value); + + API_RETURN_OK; +} + +API_FUNC(unhook) +{ + zend_string *z_hook; + struct t_hook *hook; + + API_INIT_FUNC(1, "unhook", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_hook) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + hook = (struct t_hook *)API_STR2PTR(ZSTR_VAL(z_hook)); + weechat_unhook (hook); + + API_RETURN_OK; +} + +API_FUNC(unhook_all) +{ + zend_string *z_subplugin; + char *subplugin; + + API_INIT_FUNC(1, "unhook_all", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_subplugin) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + subplugin = ZSTR_VAL(z_subplugin); + weechat_unhook_all ((const char *)subplugin); + + API_RETURN_OK; +} + +int +weechat_php_api_buffer_input_data_cb (const void *pointer, void *data, + struct t_gui_buffer *buffer, + const char *input_data) +{ + int rc; + void *func_argv[3]; + + func_argv[1] = (char *)API_PTR2STR(buffer); + func_argv[2] = input_data ? (char *)input_data : weechat_php_empty_arg; + + weechat_php_cb (pointer, data, func_argv, "sss", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +int +weechat_php_api_buffer_close_cb (const void *pointer, void *data, + struct t_gui_buffer *buffer) +{ + int rc; + void *func_argv[2]; + + func_argv[1] = (char *)API_PTR2STR(buffer); + + weechat_php_cb (pointer, data, func_argv, "ss", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +API_FUNC(buffer_new) +{ + zend_string *z_name, *z_data_input, *z_data_close; + zval *z_input_callback, *z_close_callback; + char *name, *data_input, *data_close; + const char *result; + + API_INIT_FUNC(1, "buffer_new", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SzSzS", &z_name, &z_input_callback, + &z_data_input, &z_close_callback, + &z_data_close) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + name = ZSTR_VAL(z_name); + weechat_php_get_function_name (z_input_callback, input_callback_name); + data_input = ZSTR_VAL(z_data_input); + weechat_php_get_function_name (z_close_callback, close_callback_name); + data_close = ZSTR_VAL(z_data_close); + + result = API_PTR2STR( + plugin_script_api_buffer_new ( + weechat_php_plugin, + php_current_script, + (const char *)name, + &weechat_php_api_buffer_input_data_cb, + (const char *)input_callback_name, + (const char *)data_input, + &weechat_php_api_buffer_close_cb, + (const char *)close_callback_name, + (const char *)data_close)); + + API_RETURN_STRING(result); +} + +API_FUNC(buffer_search) +{ + zend_string *z_plugin, *z_name; + char *plugin, *name; + const char *result; + + API_INIT_FUNC(1, "buffer_search", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_plugin, &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + plugin = ZSTR_VAL(z_plugin); + name = ZSTR_VAL(z_name); + + result = API_PTR2STR( + weechat_buffer_search ((const char *)plugin, (const char *)name)); + + API_RETURN_STRING(result); +} + +API_FUNC(buffer_search_main) +{ + const char *result; + + API_INIT_FUNC(1, "buffer_search_main", API_RETURN_EMPTY); + if (zend_parse_parameters_none () == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + result = API_PTR2STR(weechat_buffer_search_main ()); + + API_RETURN_STRING(result); +} + +API_FUNC(current_buffer) +{ + const char *result; + + API_INIT_FUNC(1, "current_buffer", API_RETURN_EMPTY); + if (zend_parse_parameters_none () == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + result = API_PTR2STR(weechat_current_buffer ()); + + API_RETURN_STRING(result); +} + +API_FUNC(buffer_clear) +{ + zend_string *z_buffer; + struct t_gui_buffer *buffer; + + API_INIT_FUNC(1, "buffer_clear", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_buffer) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + weechat_buffer_clear (buffer); + + API_RETURN_OK; +} + +API_FUNC(buffer_close) +{ + zend_string *z_buffer; + struct t_gui_buffer *buffer; + + API_INIT_FUNC(1, "buffer_close", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_buffer) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + weechat_buffer_close (buffer); + + API_RETURN_OK; +} + +API_FUNC(buffer_merge) +{ + zend_string *z_buffer; + zend_string *z_target_buffer; + struct t_gui_buffer *buffer; + struct t_gui_buffer *target_buffer; + + API_INIT_FUNC(1, "buffer_merge", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_buffer, &z_target_buffer) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + target_buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_target_buffer)); + weechat_buffer_merge (buffer, target_buffer); + + API_RETURN_OK; +} + +API_FUNC(buffer_unmerge) +{ + zend_string *z_buffer; + zend_long z_number; + struct t_gui_buffer *buffer; + int number; + + API_INIT_FUNC(1, "buffer_unmerge", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "Sl", &z_buffer, &z_number) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + number = (int)z_number; + weechat_buffer_unmerge (buffer, number); + + API_RETURN_OK; +} + +API_FUNC(buffer_get_integer) +{ + zend_string *z_buffer, *z_property; + struct t_gui_buffer *buffer; + char *property; + int result; + + API_INIT_FUNC(1, "buffer_get_integer", API_RETURN_INT(-1)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_buffer, &z_property) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(-1)); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + property = ZSTR_VAL(z_property); + result = weechat_buffer_get_integer (buffer, (const char *)property); + + API_RETURN_INT(result); +} + +API_FUNC(buffer_get_string) +{ + zend_string *z_buffer, *z_property; + const char *result; + struct t_gui_buffer *buffer; + char *property; + + API_INIT_FUNC(1, "buffer_get_string", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_buffer, &z_property) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + property = ZSTR_VAL(z_property); + result = weechat_buffer_get_string (buffer, (const char *)property); + + API_RETURN_STRING(result); +} + +API_FUNC(buffer_get_pointer) +{ + zend_string *z_buffer, *z_property; + struct t_gui_buffer *buffer; + char *property; + const char *result; + + API_INIT_FUNC(1, "buffer_get_pointer", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_buffer, &z_property) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + property = ZSTR_VAL(z_property); + + result = API_PTR2STR( + weechat_buffer_get_pointer (buffer, (const char *)property)); + + API_RETURN_STRING(result); +} + +API_FUNC(buffer_set) +{ + zend_string *z_buffer, *z_property, *z_value; + struct t_gui_buffer *buffer; + char *property, *value; + + API_INIT_FUNC(1, "buffer_set", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_buffer, &z_property, + &z_value) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + property = ZSTR_VAL(z_property); + value = ZSTR_VAL(z_value); + weechat_buffer_set (buffer, (const char *)property, (const char *)value); + + API_RETURN_OK; +} + +API_FUNC(buffer_string_replace_local_var) +{ + zend_string *z_buffer, *z_string; + struct t_gui_buffer *buffer; + char *string, *result; + + API_INIT_FUNC(1, "buffer_string_replace_local_var", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_buffer, &z_string) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + string = ZSTR_VAL(z_string); + result = weechat_buffer_string_replace_local_var (buffer, + (const char *)string); + + API_RETURN_STRING_FREE(result); +} + +API_FUNC(buffer_match_list) +{ + zend_string *z_buffer, *z_string; + struct t_gui_buffer *buffer; + char *string; + int result; + + API_INIT_FUNC(1, "buffer_match_list", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_buffer, &z_string) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + string = ZSTR_VAL(z_string); + result = weechat_buffer_match_list (buffer, (const char *)string); + + API_RETURN_INT(result); +} + +API_FUNC(current_window) +{ + const char *result; + + API_INIT_FUNC(1, "current_window", API_RETURN_EMPTY); + if (zend_parse_parameters_none () == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + result = API_PTR2STR(weechat_current_window ()); + + API_RETURN_STRING(result); +} + +API_FUNC(window_search_with_buffer) +{ + zend_string *z_buffer; + struct t_gui_buffer *buffer; + const char *result; + + API_INIT_FUNC(1, "window_search_with_buffer", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_buffer) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + + result = API_PTR2STR(weechat_window_search_with_buffer (buffer)); + + API_RETURN_STRING(result); +} + +API_FUNC(window_get_integer) +{ + zend_string *z_window, *z_property; + struct t_gui_window *window; + char *property; + int result; + + API_INIT_FUNC(1, "window_get_integer", API_RETURN_INT(-1)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_window, &z_property) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(-1)); + + window = (struct t_gui_window *)API_STR2PTR(ZSTR_VAL(z_window)); + property = ZSTR_VAL(z_property); + result = weechat_window_get_integer (window, (const char *)property); + + API_RETURN_INT(result); +} + +API_FUNC(window_get_string) +{ + zend_string *z_window, *z_property; + struct t_gui_window *window; + char *property; + const char *result; + + API_INIT_FUNC(1, "window_get_string", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_window, &z_property) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + window = (struct t_gui_window *)API_STR2PTR(ZSTR_VAL(z_window)); + property = ZSTR_VAL(z_property); + result = weechat_window_get_string (window, (const char *)property); + + API_RETURN_STRING(result); +} + +API_FUNC(window_get_pointer) +{ + zend_string *z_window, *z_property; + struct t_gui_window *window; + char *property; + const char *result; + + API_INIT_FUNC(1, "window_get_pointer", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_window, &z_property) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + window = (struct t_gui_window *)API_STR2PTR(ZSTR_VAL(z_window)); + property = ZSTR_VAL(z_property); + + result = API_PTR2STR( + weechat_window_get_pointer (window, (const char *)property)); + + API_RETURN_STRING(result); +} + +API_FUNC(window_set_title) +{ + zend_string *z_title; + char *title; + + API_INIT_FUNC(1, "window_set_title", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_title) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + title = ZSTR_VAL(z_title); + weechat_window_set_title ((const char *)title); + + API_RETURN_OK; +} + +API_FUNC(nicklist_add_group) +{ + zend_string *z_buffer, *z_parent_group, *z_name, *z_color; + zend_long z_visible; + struct t_gui_buffer *buffer; + struct t_gui_nick_group *parent_group; + char *name, *color; + int visible; + const char *result; + + API_INIT_FUNC(1, "nicklist_add_group", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSSSl", &z_buffer, &z_parent_group, &z_name, + &z_color, &z_visible) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + parent_group = (struct t_gui_nick_group *)API_STR2PTR(ZSTR_VAL(z_parent_group)); + name = ZSTR_VAL(z_name); + color = ZSTR_VAL(z_color); + visible = (int)z_visible; + + result = API_PTR2STR(weechat_nicklist_add_group (buffer, + parent_group, + (const char *)name, + (const char *)color, + visible)); + + API_RETURN_STRING(result); +} + +API_FUNC(nicklist_search_group) +{ + zend_string *z_buffer, *z_from_group, *z_name; + struct t_gui_buffer *buffer; + struct t_gui_nick_group *from_group; + char *name; + const char *result; + + API_INIT_FUNC(1, "nicklist_search_group", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_buffer, &z_from_group, + &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + from_group = (struct t_gui_nick_group *)API_STR2PTR(ZSTR_VAL(z_from_group)); + name = ZSTR_VAL(z_name); + + result = API_PTR2STR(weechat_nicklist_search_group (buffer, + from_group, + (const char *)name)); + + API_RETURN_STRING(result); +} + +API_FUNC(nicklist_add_nick) +{ + zend_string *z_buffer, *z_group, *z_name, *z_color, *z_prefix; + zend_string *z_prefix_color; + zend_long z_visible; + struct t_gui_buffer *buffer; + struct t_gui_nick_group *group; + char *name, *color, *prefix, *prefix_color; + int visible; + const char *result; + + API_INIT_FUNC(1, "nicklist_add_nick", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSSSSSl", &z_buffer, &z_group, &z_name, + &z_color, &z_prefix, &z_prefix_color, + &z_visible) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + group = (struct t_gui_nick_group *)API_STR2PTR(ZSTR_VAL(z_group)); + name = ZSTR_VAL(z_name); + color = ZSTR_VAL(z_color); + prefix = ZSTR_VAL(z_prefix); + prefix_color = ZSTR_VAL(z_prefix_color); + visible = (int)z_visible; + + result = API_PTR2STR( + weechat_nicklist_add_nick ( + buffer, + group, + (const char *)name, + (const char *)color, + (const char *)prefix, + (const char *)prefix_color, + visible)); + + API_RETURN_STRING(result); +} + +API_FUNC(nicklist_search_nick) +{ + zend_string *z_buffer, *z_from_group, *z_name; + struct t_gui_buffer *buffer; + struct t_gui_nick_group *from_group; + char *name; + const char *result; + + API_INIT_FUNC(1, "nicklist_search_nick", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_buffer, &z_from_group, + &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + from_group = (struct t_gui_nick_group *)API_STR2PTR(ZSTR_VAL(z_from_group)); + name = ZSTR_VAL(z_name); + + result = API_PTR2STR(weechat_nicklist_search_nick (buffer, + from_group, + (const char *)name)); + + API_RETURN_STRING(result); +} + +API_FUNC(nicklist_remove_group) +{ + zend_string *z_buffer, *z_group; + struct t_gui_buffer *buffer; + struct t_gui_nick_group *group; + + API_INIT_FUNC(1, "nicklist_remove_group", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_buffer, &z_group) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + group = (struct t_gui_nick_group *)API_STR2PTR(ZSTR_VAL(z_group)); + weechat_nicklist_remove_group (buffer, group); + + API_RETURN_OK; +} + +API_FUNC(nicklist_remove_nick) +{ + zend_string *z_buffer, *z_nick; + struct t_gui_buffer *buffer; + struct t_gui_nick *nick; + + API_INIT_FUNC(1, "nicklist_remove_nick", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_buffer, &z_nick) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + nick = (struct t_gui_nick *)API_STR2PTR(ZSTR_VAL(z_nick)); + weechat_nicklist_remove_nick (buffer, nick); + + API_RETURN_OK; +} + +API_FUNC(nicklist_remove_all) +{ + zend_string *z_buffer; + struct t_gui_buffer *buffer; + + API_INIT_FUNC(1, "nicklist_remove_all", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_buffer) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + weechat_nicklist_remove_all (buffer); + + API_RETURN_OK; +} + +API_FUNC(nicklist_group_get_integer) +{ + zend_string *z_buffer, *z_group, *z_property; + struct t_gui_buffer *buffer; + struct t_gui_nick_group *group; + char *property; + int result; + + API_INIT_FUNC(1, "nicklist_group_get_integer", API_RETURN_INT(-1)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_buffer, &z_group, + &z_property) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(-1)); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + group = (struct t_gui_nick_group *)API_STR2PTR(ZSTR_VAL(z_group)); + property = ZSTR_VAL(z_property); + result = weechat_nicklist_group_get_integer (buffer, + group, + (const char *)property); + + API_RETURN_INT(result); +} + +API_FUNC(nicklist_group_get_string) +{ + zend_string *z_buffer, *z_group, *z_property; + struct t_gui_buffer *buffer; + struct t_gui_nick_group *group; + char *property; + const char *result; + + API_INIT_FUNC(1, "nicklist_group_get_string", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_buffer, &z_group, + &z_property) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + group = (struct t_gui_nick_group *)API_STR2PTR(ZSTR_VAL(z_group)); + property = ZSTR_VAL(z_property); + result = weechat_nicklist_group_get_string (buffer, + group, + (const char *)property); + + API_RETURN_STRING(result); +} + +API_FUNC(nicklist_group_get_pointer) +{ + zend_string *z_buffer, *z_group, *z_property; + struct t_gui_buffer *buffer; + struct t_gui_nick_group *group; + char *property; + const char *result; + + API_INIT_FUNC(1, "nicklist_group_get_pointer", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_buffer, &z_group, + &z_property) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + group = (struct t_gui_nick_group *)API_STR2PTR(ZSTR_VAL(z_group)); + property = ZSTR_VAL(z_property); + + result = API_PTR2STR( + weechat_nicklist_group_get_pointer (buffer, + group, + (const char *)property)); + + API_RETURN_STRING(result); +} + +API_FUNC(nicklist_group_set) +{ + zend_string *z_buffer, *z_group, *z_property, *z_value; + struct t_gui_buffer *buffer; + struct t_gui_nick_group *group; + char *property, *value; + + API_INIT_FUNC(1, "nicklist_group_set", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSSS", &z_buffer, &z_group, &z_property, + &z_value) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + group = (struct t_gui_nick_group *)API_STR2PTR(ZSTR_VAL(z_group)); + property = ZSTR_VAL(z_property); + value = ZSTR_VAL(z_value); + weechat_nicklist_group_set (buffer, + group, + (const char *)property, + (const char *)value); + + API_RETURN_OK; +} + +API_FUNC(nicklist_nick_get_integer) +{ + zend_string *z_buffer, *z_nick, *z_property; + struct t_gui_buffer *buffer; + struct t_gui_nick *nick; + char *property; + int result; + + API_INIT_FUNC(1, "nicklist_nick_get_integer", API_RETURN_INT(-1)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_buffer, &z_nick, + &z_property) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(-1)); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + nick = (struct t_gui_nick *)API_STR2PTR(ZSTR_VAL(z_nick)); + property = ZSTR_VAL(z_property); + result = weechat_nicklist_nick_get_integer (buffer, + nick, + (const char *)property); + + API_RETURN_INT(result); +} + +API_FUNC(nicklist_nick_get_string) +{ + zend_string *z_buffer, *z_nick, *z_property; + struct t_gui_buffer *buffer; + struct t_gui_nick *nick; + char *property; + const char *result; + + API_INIT_FUNC(1, "nicklist_nick_get_string", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_buffer, &z_nick, + &z_property) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + nick = (struct t_gui_nick *)API_STR2PTR(ZSTR_VAL(z_nick)); + property = ZSTR_VAL(z_property); + result = weechat_nicklist_nick_get_string (buffer, + nick, + (const char *)property); + + API_RETURN_STRING(result); +} + +API_FUNC(nicklist_nick_get_pointer) +{ + zend_string *z_buffer, *z_nick, *z_property; + struct t_gui_buffer *buffer; + struct t_gui_nick *nick; + char *property; + const char *result; + + API_INIT_FUNC(1, "nicklist_nick_get_pointer", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_buffer, &z_nick, + &z_property) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + nick = (struct t_gui_nick *)API_STR2PTR(ZSTR_VAL(z_nick)); + property = ZSTR_VAL(z_property); + + result = API_PTR2STR( + weechat_nicklist_nick_get_pointer (buffer, + nick, + (const char *)property)); + + API_RETURN_STRING(result); +} + +API_FUNC(nicklist_nick_set) +{ + zend_string *z_buffer, *z_nick, *z_property, *z_value; + struct t_gui_buffer *buffer; + struct t_gui_nick *nick; + char *property, *value; + + API_INIT_FUNC(1, "nicklist_nick_set", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSSS", &z_buffer, &z_nick, &z_property, + &z_value) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + nick = (struct t_gui_nick *)API_STR2PTR(ZSTR_VAL(z_nick)); + property = ZSTR_VAL(z_property); + value = ZSTR_VAL(z_value); + weechat_nicklist_nick_set (buffer, + nick, + (const char *)property, + (const char *)value); + + API_RETURN_OK; +} + +API_FUNC(bar_item_search) +{ + zend_string *z_name; + char *name; + const char *result; + + API_INIT_FUNC(1, "bar_item_search", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + name = ZSTR_VAL(z_name); + + result = API_PTR2STR(weechat_bar_item_search ((const char *)name)); + + API_RETURN_STRING(result); +} + +static char * +weechat_php_api_bar_item_new_build_cb (const void *pointer, void *data, + struct t_gui_bar_item *item, + struct t_gui_window *window, + struct t_gui_buffer *buffer, + struct t_hashtable *extra_info) +{ + char *rc; + void *func_argv[5]; + + func_argv[1] = (char *)API_PTR2STR(item); + func_argv[2] = (char *)API_PTR2STR(window); + func_argv[3] = (char *)API_PTR2STR(buffer); + func_argv[4] = extra_info; + + weechat_php_cb (pointer, data, func_argv, "ssssh", + WEECHAT_SCRIPT_EXEC_STRING, &rc); + + return rc; +} + +API_FUNC(bar_item_new) +{ + zend_string *z_name, *z_data; + zval *z_build_callback; + char *name, *data; + const char *result; + + API_INIT_FUNC(1, "bar_item_new", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SzS", &z_name, &z_build_callback, + &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + name = ZSTR_VAL(z_name); + weechat_php_get_function_name (z_build_callback, build_callback_name); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR( + plugin_script_api_bar_item_new ( + weechat_php_plugin, + php_current_script, + (const char *)name, + &weechat_php_api_bar_item_new_build_cb, + (const char *)build_callback_name, + (const char *)data)); + + API_RETURN_STRING(result); +} + +API_FUNC(bar_item_update) +{ + zend_string *z_name; + char *name; + + API_INIT_FUNC(1, "bar_item_update", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + name = ZSTR_VAL(z_name); + weechat_bar_item_update ((const char *)name); + + API_RETURN_OK; +} + +API_FUNC(bar_item_remove) +{ + zend_string *z_item; + struct t_gui_bar_item *item; + + API_INIT_FUNC(1, "bar_item_remove", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_item) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + item = (struct t_gui_bar_item *)API_STR2PTR(ZSTR_VAL(z_item)); + weechat_bar_item_remove (item); + + API_RETURN_OK; +} + +API_FUNC(bar_search) +{ + zend_string *z_name; + char *name; + const char *result; + + API_INIT_FUNC(1, "bar_search", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + name = ZSTR_VAL(z_name); + + result = API_PTR2STR(weechat_bar_search ((const char *)name)); + + API_RETURN_STRING(result); +} + +API_FUNC(bar_new) +{ + zend_string *z_name, *z_hidden, *z_priority, *z_type, *z_condition; + zend_string *z_position, *z_filling_top_bottom, *z_filling_left_right; + zend_string *z_size, *z_size_max, *z_color_fg, *z_color_delim, *z_color_bg; + zend_string *z_separator, *z_items; + char *name, *hidden, *priority, *type, *condition, *position; + char *filling_top_bottom, *filling_left_right, *size, *size_max, *color_fg; + char *color_delim, *color_bg, *separator, *items; + const char *result; + + API_INIT_FUNC(1, "bar_new", API_RETURN_EMPTY); + if (zend_parse_parameters ( + ZEND_NUM_ARGS(), "SSSSSSSSSSSSSSS", &z_name, &z_hidden, + &z_priority, &z_type, &z_condition, &z_position, + &z_filling_top_bottom, &z_filling_left_right, &z_size, &z_size_max, + &z_color_fg, &z_color_delim, &z_color_bg, &z_separator, + &z_items) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + name = ZSTR_VAL(z_name); + hidden = ZSTR_VAL(z_hidden); + priority = ZSTR_VAL(z_priority); + type = ZSTR_VAL(z_type); + condition = ZSTR_VAL(z_condition); + position = ZSTR_VAL(z_position); + filling_top_bottom = ZSTR_VAL(z_filling_top_bottom); + filling_left_right = ZSTR_VAL(z_filling_left_right); + size = ZSTR_VAL(z_size); + size_max = ZSTR_VAL(z_size_max); + color_fg = ZSTR_VAL(z_color_fg); + color_delim = ZSTR_VAL(z_color_delim); + color_bg = ZSTR_VAL(z_color_bg); + separator = ZSTR_VAL(z_separator); + items = ZSTR_VAL(z_items); + + result = API_PTR2STR( + weechat_bar_new ( + (const char *)name, + (const char *)hidden, + (const char *)priority, + (const char *)type, + (const char *)condition, + (const char *)position, + (const char *)filling_top_bottom, + (const char *)filling_left_right, + (const char *)size, + (const char *)size_max, + (const char *)color_fg, + (const char *)color_delim, + (const char *)color_bg, + (const char *)separator, + (const char *)items)); + + API_RETURN_STRING(result); +} + +API_FUNC(bar_set) +{ + zend_string *z_bar, *z_property, *z_value; + struct t_gui_bar *bar; + char *property, *value; + int result; + + API_INIT_FUNC(1, "bar_set", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_bar, &z_property, &z_value) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + bar = (struct t_gui_bar *)API_STR2PTR(ZSTR_VAL(z_bar)); + property = ZSTR_VAL(z_property); + value = ZSTR_VAL(z_value); + result = weechat_bar_set (bar, (const char *)property, (const char *)value); + + API_RETURN_INT(result); +} + +API_FUNC(bar_update) +{ + zend_string *z_name; + char *name; + + API_INIT_FUNC(1, "bar_update", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + name = ZSTR_VAL(z_name); + weechat_bar_update ((const char *)name); + + API_RETURN_OK; +} + +API_FUNC(bar_remove) +{ + zend_string *z_bar; + struct t_gui_bar *bar; + + API_INIT_FUNC(1, "bar_remove", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_bar) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + bar = (struct t_gui_bar *)API_STR2PTR(ZSTR_VAL(z_bar)); + weechat_bar_remove (bar); + + API_RETURN_OK; +} + +API_FUNC(command) +{ + zend_string *z_buffer, *z_command; + struct t_gui_buffer *buffer; + char *command; + int result; + + API_INIT_FUNC(1, "command", API_RETURN_INT(WEECHAT_RC_ERROR)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_buffer, &z_command) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(WEECHAT_RC_ERROR)); + + buffer = (struct t_gui_buffer *)API_STR2PTR(ZSTR_VAL(z_buffer)); + command = ZSTR_VAL(z_command); + result = plugin_script_api_command (weechat_php_plugin, + php_current_script, + buffer, + (const char *)command); + + API_RETURN_INT(result); +} + +API_FUNC(info_get) +{ + zend_string *z_info_name, *z_arguments; + char *info_name, *arguments; + const char *result; + + API_INIT_FUNC(1, "info_get", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_info_name, &z_arguments) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + info_name = ZSTR_VAL(z_info_name); + arguments = ZSTR_VAL(z_arguments); + result = weechat_info_get ((const char *)info_name, + (const char *)arguments); + + API_RETURN_STRING(result); +} + +API_FUNC(info_get_hashtable) +{ + zend_string *z_info_name; + zval *z_hashtable; + char *info_name; + struct t_hashtable *hashtable, *result; + + API_INIT_FUNC(1, "info_get_hashtable", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "Sa", &z_info_name, &z_hashtable) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + info_name = ZSTR_VAL(z_info_name); + hashtable = weechat_php_array_to_hashtable ( + z_hashtable, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING); + result = weechat_info_get_hashtable ((const char *)info_name, hashtable); + + weechat_php_hashtable_to_array (result, return_value); +} + +API_FUNC(infolist_new) +{ + const char *result; + + API_INIT_FUNC(1, "infolist_new", API_RETURN_EMPTY); + if (zend_parse_parameters_none () == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + result = API_PTR2STR(weechat_infolist_new ()); + + API_RETURN_STRING(result); +} + +API_FUNC(infolist_new_item) +{ + zend_string *z_infolist; + struct t_infolist *infolist; + const char *result; + + API_INIT_FUNC(1, "infolist_new_item", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_infolist) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + infolist = (struct t_infolist *)API_STR2PTR(ZSTR_VAL(z_infolist)); + + result = API_PTR2STR(weechat_infolist_new_item (infolist)); + + API_RETURN_STRING(result); +} + +API_FUNC(infolist_new_var_integer) +{ + zend_string *z_item, *z_name; + zend_long z_value; + struct t_infolist_item *item; + char *name; + int value; + const char *result; + + API_INIT_FUNC(1, "infolist_new_var_integer", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSl", &z_item, &z_name, &z_value) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + item = (struct t_infolist_item *)API_STR2PTR(ZSTR_VAL(z_item)); + name = ZSTR_VAL(z_name); + value = (int)z_value; + + result = API_PTR2STR(weechat_infolist_new_var_integer (item, + (const char *)name, + value)); + + API_RETURN_STRING(result); +} + +API_FUNC(infolist_new_var_string) +{ + zend_string *z_item, *z_name, *z_value; + struct t_infolist_item *item; + char *name, *value; + const char *result; + + API_INIT_FUNC(1, "infolist_new_var_string", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_item, &z_name, &z_value) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + item = (struct t_infolist_item *)API_STR2PTR(ZSTR_VAL(z_item)); + name = ZSTR_VAL(z_name); + value = ZSTR_VAL(z_value); + + result = API_PTR2STR( + weechat_infolist_new_var_string (item, + (const char *)name, + (const char *)value)); + + API_RETURN_STRING(result); +} + +API_FUNC(infolist_new_var_pointer) +{ + zend_string *z_item, *z_name, *z_pointer; + struct t_infolist_item *item; + char *name; + void *pointer; + const char *result; + + API_INIT_FUNC(1, "infolist_new_var_pointer", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_item, &z_name, &z_pointer) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + item = (struct t_infolist_item *)API_STR2PTR(ZSTR_VAL(z_item)); + name = ZSTR_VAL(z_name); + pointer = (void *)API_STR2PTR(ZSTR_VAL(z_pointer)); + + result = API_PTR2STR( + weechat_infolist_new_var_pointer (item, + (const char *)name, + pointer)); + + API_RETURN_STRING(result); +} + +API_FUNC(infolist_new_var_time) +{ + zend_string *z_item, *z_name; + zend_long z_time; + struct t_infolist_item *item; + char *name; + time_t time; + const char *result; + + API_INIT_FUNC(1, "infolist_new_var_time", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSl", &z_item, &z_name, &z_time) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + item = (struct t_infolist_item *)API_STR2PTR(ZSTR_VAL(z_item)); + name = ZSTR_VAL(z_name); + time = (time_t)z_time; + + result = API_PTR2STR( + weechat_infolist_new_var_time (item, (const char *)name, time)); + + API_RETURN_STRING(result); +} + +API_FUNC(infolist_search_var) +{ + zend_string *z_infolist, *z_name; + struct t_infolist *infolist; + char *name; + const char *result; + + API_INIT_FUNC(1, "infolist_search_var", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_infolist, &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + infolist = (struct t_infolist *)API_STR2PTR(ZSTR_VAL(z_infolist)); + name = ZSTR_VAL(z_name); + + result = API_PTR2STR( + weechat_infolist_search_var (infolist, (const char *)name)); + + API_RETURN_STRING(result); +} + +API_FUNC(infolist_get) +{ + zend_string *z_infolist_name, *z_pointer, *z_arguments; + char *infolist_name, *arguments; + void *pointer; + const char *result; + + API_INIT_FUNC(1, "infolist_get", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_infolist_name, &z_pointer, + &z_arguments) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + infolist_name = ZSTR_VAL(z_infolist_name); + pointer = (void *)API_STR2PTR(ZSTR_VAL(z_pointer)); + arguments = ZSTR_VAL(z_arguments); + + result = API_PTR2STR( + weechat_infolist_get ((const char *)infolist_name, + pointer, + (const char *)arguments)); + + API_RETURN_STRING(result); +} + +API_FUNC(infolist_next) +{ + zend_string *z_infolist; + struct t_infolist *infolist; + int result; + + API_INIT_FUNC(1, "infolist_next", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_infolist) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + infolist = (struct t_infolist *)API_STR2PTR(ZSTR_VAL(z_infolist)); + result = weechat_infolist_next (infolist); + + API_RETURN_INT(result); +} + +API_FUNC(infolist_prev) +{ + zend_string *z_infolist; + struct t_infolist *infolist; + int result; + + API_INIT_FUNC(1, "infolist_prev", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_infolist) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + infolist = (struct t_infolist *)API_STR2PTR(ZSTR_VAL(z_infolist)); + result = weechat_infolist_prev (infolist); + + API_RETURN_INT(result); +} + +API_FUNC(infolist_reset_item_cursor) +{ + zend_string *z_infolist; + struct t_infolist *infolist; + + API_INIT_FUNC(1, "infolist_reset_item_cursor", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_infolist) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + infolist = (struct t_infolist *)API_STR2PTR(ZSTR_VAL(z_infolist)); + weechat_infolist_reset_item_cursor (infolist); + + API_RETURN_OK; +} + +API_FUNC(infolist_fields) +{ + zend_string *z_infolist; + struct t_infolist *infolist; + const char *result; + + API_INIT_FUNC(1, "infolist_fields", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_infolist) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + infolist = (struct t_infolist *)API_STR2PTR(ZSTR_VAL(z_infolist)); + result = weechat_infolist_fields (infolist); + + API_RETURN_STRING(result); +} + +API_FUNC(infolist_integer) +{ + zend_string *z_infolist, *z_var; + struct t_infolist *infolist; + char *var; + int result; + + API_INIT_FUNC(1, "infolist_integer", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_infolist, &z_var) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + infolist = (struct t_infolist *)API_STR2PTR(ZSTR_VAL(z_infolist)); + var = ZSTR_VAL(z_var); + result = weechat_infolist_integer (infolist, (const char *)var); + + API_RETURN_INT(result); +} + +API_FUNC(infolist_string) +{ + zend_string *z_infolist, *z_var; + struct t_infolist *infolist; + char *var; + const char *result; + + API_INIT_FUNC(1, "infolist_string", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_infolist, &z_var) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + infolist = (struct t_infolist *)API_STR2PTR(ZSTR_VAL(z_infolist)); + var = ZSTR_VAL(z_var); + result = weechat_infolist_string (infolist, (const char *)var); + + API_RETURN_STRING(result); +} + +API_FUNC(infolist_pointer) +{ + zend_string *z_infolist, *z_var; + struct t_infolist *infolist; + char *var; + const char *result; + + API_INIT_FUNC(1, "infolist_pointer", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_infolist, &z_var) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + infolist = (struct t_infolist *)API_STR2PTR(ZSTR_VAL(z_infolist)); + var = ZSTR_VAL(z_var); + + result = API_PTR2STR( + weechat_infolist_pointer (infolist, (const char *)var)); + + API_RETURN_STRING(result); +} + +API_FUNC(infolist_time) +{ + zend_string *z_infolist, *z_var; + struct t_infolist *infolist; + char *var; + time_t time; + + API_INIT_FUNC(1, "infolist_time", API_RETURN_LONG(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_infolist, &z_var) == FAILURE) + API_WRONG_ARGS(API_RETURN_LONG(0)); + + infolist = (struct t_infolist *)API_STR2PTR(ZSTR_VAL(z_infolist)); + var = ZSTR_VAL(z_var); + + time = weechat_infolist_time (infolist, (const char *)var); + + API_RETURN_LONG(time); +} + +API_FUNC(infolist_free) +{ + zend_string *z_infolist; + struct t_infolist *infolist; + + API_INIT_FUNC(1, "infolist_free", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_infolist) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + infolist = (struct t_infolist *)API_STR2PTR(ZSTR_VAL(z_infolist)); + weechat_infolist_free (infolist); + + API_RETURN_OK; +} + +API_FUNC(hdata_get) +{ + zend_string *z_hdata_name; + char *hdata_name; + const char *result; + + API_INIT_FUNC(1, "hdata_get", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &z_hdata_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + hdata_name = ZSTR_VAL(z_hdata_name); + + result = API_PTR2STR(weechat_hdata_get ((const char *)hdata_name)); + + API_RETURN_STRING(result); +} + +API_FUNC(hdata_get_var_offset) +{ + zend_string *z_hdata, *z_name; + struct t_hdata *hdata; + char *name; + int result; + + API_INIT_FUNC(1, "hdata_get_var_offset", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_hdata, &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + name = ZSTR_VAL(z_name); + result = weechat_hdata_get_var_offset (hdata, (const char *)name); + + API_RETURN_INT(result); +} + +API_FUNC(hdata_get_var_type_string) +{ + zend_string *z_hdata, *z_name; + struct t_hdata *hdata; + char *name; + const char *result; + + API_INIT_FUNC(1, "hdata_get_var_type_string", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_hdata, &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + name = ZSTR_VAL(z_name); + result = weechat_hdata_get_var_type_string (hdata, (const char *)name); + + API_RETURN_STRING(result); +} + +API_FUNC(hdata_get_var_array_size) +{ + zend_string *z_hdata, *z_pointer, *z_name; + struct t_hdata *hdata; + void *pointer; + char *name; + int result; + + API_INIT_FUNC(1, "hdata_get_var_array_size", API_RETURN_INT(-1)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_hdata, &z_pointer, &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(-1)); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + pointer = (void *)API_STR2PTR(ZSTR_VAL(z_pointer)); + name = ZSTR_VAL(z_name); + result = weechat_hdata_get_var_array_size (hdata, + pointer, + (const char *)name); + + API_RETURN_INT(result); +} + +API_FUNC(hdata_get_var_array_size_string) +{ + zend_string *z_hdata, *z_pointer, *z_name; + struct t_hdata *hdata; + void *pointer; + char *name; + const char *result; + + API_INIT_FUNC(1, "hdata_get_var_array_size_string", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_hdata, &z_pointer, &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + pointer = (void *)API_STR2PTR(ZSTR_VAL(z_pointer)); + name = ZSTR_VAL(z_name); + result = weechat_hdata_get_var_array_size_string (hdata, + pointer, + (const char *)name); + + API_RETURN_STRING(result); +} + +API_FUNC(hdata_get_var_hdata) +{ + zend_string *z_hdata, *z_name; + struct t_hdata *hdata; + char *name; + const char *result; + + API_INIT_FUNC(1, "hdata_get_var_hdata", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_hdata, &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + name = ZSTR_VAL(z_name); + result = weechat_hdata_get_var_hdata (hdata, (const char *)name); + + API_RETURN_STRING(result); +} + +API_FUNC(hdata_get_list) +{ + zend_string *z_hdata, *z_name; + struct t_hdata *hdata; + char *name; + const char *result; + + API_INIT_FUNC(1, "hdata_get_list", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_hdata, &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + name = ZSTR_VAL(z_name); + + result = API_PTR2STR( + weechat_hdata_get_list (hdata, (const char *)name)); + + API_RETURN_STRING(result); +} + +API_FUNC(hdata_check_pointer) +{ + zend_string *z_hdata, *z_list, *z_pointer; + struct t_hdata *hdata; + void *list, *pointer; + int result; + + API_INIT_FUNC(1, "hdata_check_pointer", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_hdata, &z_list, &z_pointer) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + list = (void *)API_STR2PTR(ZSTR_VAL(z_list)); + pointer = (void *)API_STR2PTR(ZSTR_VAL(z_pointer)); + result = weechat_hdata_check_pointer (hdata, list, pointer); + + API_RETURN_INT(result); +} + +API_FUNC(hdata_move) +{ + zend_string *z_hdata, *z_pointer; + zend_long z_count; + struct t_hdata *hdata; + void *pointer; + int count; + const char *result; + + API_INIT_FUNC(1, "hdata_move", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSl", &z_hdata, &z_pointer, &z_count) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + pointer = (void *)API_STR2PTR(ZSTR_VAL(z_pointer)); + count = (int)z_count; + + result = API_PTR2STR(weechat_hdata_move (hdata, pointer, count)); + + API_RETURN_STRING(result); +} + +API_FUNC(hdata_search) +{ + zend_string *z_hdata, *z_pointer, *z_search; + zend_long z_move; + struct t_hdata *hdata; + void *pointer; + char *search; + int move; + const char *result; + + API_INIT_FUNC(1, "hdata_search", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSSl", &z_hdata, &z_pointer, &z_search, + &z_move) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + pointer = (void *)API_STR2PTR(ZSTR_VAL(z_pointer)); + search = ZSTR_VAL(z_search); + move = (int)z_move; + + result = API_PTR2STR( + weechat_hdata_search (hdata, pointer, (const char *)search, move)); + + API_RETURN_STRING(result); +} + +API_FUNC(hdata_char) +{ + zend_string *z_hdata, *z_pointer, *z_name; + struct t_hdata *hdata; + void *pointer; + char *name, result; + + API_INIT_FUNC(1, "hdata_char", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_hdata, &z_pointer, &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + pointer = (void *)API_STR2PTR(ZSTR_VAL(z_pointer)); + name = ZSTR_VAL(z_name); + result = weechat_hdata_char (hdata, pointer, (const char *)name); + + API_RETURN_INT((int)result); +} + +API_FUNC(hdata_integer) +{ + zend_string *z_hdata, *z_pointer, *z_name; + struct t_hdata *hdata; + void *pointer; + char *name; + int result; + + API_INIT_FUNC(1, "hdata_integer", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_hdata, &z_pointer, &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + pointer = (void *)API_STR2PTR(ZSTR_VAL(z_pointer)); + name = ZSTR_VAL(z_name); + result = weechat_hdata_integer (hdata, pointer, (const char *)name); + + API_RETURN_INT(result); +} + +API_FUNC(hdata_long) +{ + zend_string *z_hdata, *z_pointer, *z_name; + struct t_hdata *hdata; + void *pointer; + char *name; + long result; + + API_INIT_FUNC(1, "hdata_long", API_RETURN_LONG(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_hdata, &z_pointer, &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_LONG(0)); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + pointer = (void *)API_STR2PTR(ZSTR_VAL(z_pointer)); + name = ZSTR_VAL(z_name); + result = weechat_hdata_long (hdata, pointer, (const char *)name); + + API_RETURN_LONG(result); +} + +API_FUNC(hdata_string) +{ + zend_string *z_hdata, *z_pointer, *z_name; + struct t_hdata *hdata; + void *pointer; + char *name; + const char *result; + + API_INIT_FUNC(1, "hdata_string", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_hdata, &z_pointer, &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + pointer = (void *)API_STR2PTR(ZSTR_VAL(z_pointer)); + name = ZSTR_VAL(z_name); + result = weechat_hdata_string (hdata, pointer, (const char *)name); + + API_RETURN_STRING(result); +} + +API_FUNC(hdata_pointer) +{ + zend_string *z_hdata, *z_pointer, *z_name; + struct t_hdata *hdata; + void *pointer; + char *name; + const char *result; + + API_INIT_FUNC(1, "hdata_pointer", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_hdata, &z_pointer, &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + pointer = (void *)API_STR2PTR(ZSTR_VAL(z_pointer)); + name = ZSTR_VAL(z_name); + + result = API_PTR2STR( + weechat_hdata_pointer (hdata, pointer, (const char *)name)); + + API_RETURN_STRING(result); +} + +API_FUNC(hdata_time) +{ + zend_string *z_hdata, *z_pointer, *z_name; + struct t_hdata *hdata; + void *pointer; + char *name; + time_t result; + + API_INIT_FUNC(1, "hdata_time", API_RETURN_LONG(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_hdata, &z_pointer, &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_LONG(0)); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + pointer = (void *)API_STR2PTR(ZSTR_VAL(z_pointer)); + name = ZSTR_VAL(z_name); + result = weechat_hdata_time (hdata, pointer, (const char *)name); + + API_RETURN_LONG(result); +} + +API_FUNC(hdata_hashtable) +{ + zend_string *z_hdata, *z_pointer, *z_name; + struct t_hdata *hdata; + void *pointer; + char *name; + struct t_hashtable *result; + + API_INIT_FUNC(1, "hdata_hashtable", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSS", &z_hdata, &z_pointer, &z_name) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + pointer = (void *)API_STR2PTR(ZSTR_VAL(z_pointer)); + name = ZSTR_VAL(z_name); + result = weechat_hdata_hashtable (hdata, pointer, (const char *)name); + + weechat_php_hashtable_to_array (result, return_value); +} + +API_FUNC(hdata_compare) +{ + zend_string *z_hdata, *z_pointer1, *z_pointer2, *z_name; + zend_long z_case_sensitive; + struct t_hdata *hdata; + void *pointer1, *pointer2; + char *name; + int case_sensitive, result; + + API_INIT_FUNC(1, "hdata_compare", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSSSl", &z_hdata, &z_pointer1, &z_pointer2, + &z_name, &z_case_sensitive) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + pointer1 = (void *)API_STR2PTR(ZSTR_VAL(z_pointer1)); + pointer2 = (void *)API_STR2PTR(ZSTR_VAL(z_pointer2)); + name = (void *)API_STR2PTR(ZSTR_VAL(z_name)); + case_sensitive = (int)z_case_sensitive; + result = weechat_hdata_compare (hdata, pointer1, pointer2, name, + case_sensitive); + + API_RETURN_INT(result); +} + +API_FUNC(hdata_update) +{ + zend_string *z_hdata, *z_pointer; + zval *z_hashtable; + int result; + struct t_hdata *hdata; + void *pointer; + struct t_hashtable *hashtable; + + API_INIT_FUNC(1, "hdata_update", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SSa", &z_hdata, &z_pointer, + &z_hashtable) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + pointer = (void *)API_STR2PTR(ZSTR_VAL(z_pointer)); + hashtable = weechat_php_array_to_hashtable ( + z_hashtable, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING); + result = weechat_hdata_update (hdata, pointer, hashtable); + + API_RETURN_INT(result); +} + +API_FUNC(hdata_get_string) +{ + zend_string *z_hdata, *z_property; + struct t_hdata *hdata; + char *property; + const char *result; + + API_INIT_FUNC(1, "hdata_get_string", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SS", &z_hdata, &z_property) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + hdata = (struct t_hdata *)API_STR2PTR(ZSTR_VAL(z_hdata)); + property = ZSTR_VAL(z_property); + result = weechat_hdata_get_string (hdata, (const char *)property); + + API_RETURN_STRING(result); +} + +static int +weechat_php_api_upgrade_read_cb (const void *pointer, void *data, + struct t_upgrade_file *upgrade_file, + int object_id, + struct t_infolist *infolist) +{ + int rc; + void *func_argv[4]; + + func_argv[1] = (char *)API_PTR2STR(upgrade_file); + func_argv[2] = &object_id; + func_argv[3] = (char *)API_PTR2STR(infolist); + + weechat_php_cb (pointer, data, func_argv, "ssis", + WEECHAT_SCRIPT_EXEC_INT, &rc); + + return rc; +} + +API_FUNC(upgrade_new) +{ + zend_string *z_filename, *z_data; + zval *z_callback_read; + char *filename; + char *data; + const char *result; + + API_INIT_FUNC(1, "upgrade_new", API_RETURN_EMPTY); + if (zend_parse_parameters (ZEND_NUM_ARGS(), "SzS", &z_filename, + &z_callback_read, &z_data) == FAILURE) + API_WRONG_ARGS(API_RETURN_EMPTY); + + filename = ZSTR_VAL(z_filename); + weechat_php_get_function_name (z_callback_read, callback_read_name); + data = ZSTR_VAL(z_data); + + result = API_PTR2STR( + plugin_script_api_upgrade_new ( + weechat_php_plugin, + php_current_script, + (const char *)filename, + &weechat_php_api_upgrade_read_cb, + (const char *)callback_read_name, + (const char *)data)); + + API_RETURN_STRING(result); +} + +API_FUNC(upgrade_write_object) +{ + zend_string *z_upgrade_file, *z_infolist; + zend_long z_object_id; + struct t_upgrade_file *upgrade_file; + int object_id; + struct t_infolist *infolist; + int result; + + API_INIT_FUNC(1, "upgrade_write_object", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "SlS", &z_upgrade_file, &z_object_id, + &z_infolist) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + upgrade_file = (struct t_upgrade_file *)API_STR2PTR(ZSTR_VAL(z_upgrade_file)); + object_id = (int)z_object_id; + infolist = (struct t_infolist *)API_STR2PTR(ZSTR_VAL(z_infolist)); + result = weechat_upgrade_write_object (upgrade_file, object_id, infolist); + + API_RETURN_INT(result); +} + +API_FUNC(upgrade_read) +{ + zend_string *z_upgrade_file; + struct t_upgrade_file *upgrade_file; + int result; + + API_INIT_FUNC(1, "upgrade_read", API_RETURN_INT(0)); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "S", &z_upgrade_file) == FAILURE) + API_WRONG_ARGS(API_RETURN_INT(0)); + + upgrade_file = (struct t_upgrade_file *)API_STR2PTR(ZSTR_VAL(z_upgrade_file)); + result = weechat_upgrade_read (upgrade_file); + + API_RETURN_INT(result); +} + +API_FUNC(upgrade_close) +{ + zend_string *z_upgrade_file; + struct t_upgrade_file *upgrade_file; + + API_INIT_FUNC(1, "upgrade_close", API_RETURN_ERROR); + if (zend_parse_parameters (ZEND_NUM_ARGS(), + "S", &z_upgrade_file) == FAILURE) + API_WRONG_ARGS(API_RETURN_ERROR); + + upgrade_file = (struct t_upgrade_file *)API_STR2PTR(ZSTR_VAL(z_upgrade_file)); + weechat_upgrade_close (upgrade_file); + + API_RETURN_OK; +} + +static void +forget_hash_entry (HashTable *ht, INTERNAL_FUNCTION_PARAMETERS) +{ + zend_string *class_name; + zend_string *lc_name; + int re; + if (zend_parse_parameters (ZEND_NUM_ARGS(), "S", &class_name) == FAILURE) + { + return; + } + if (ZSTR_VAL(class_name)[0] == '\\') + { + lc_name = zend_string_alloc (ZSTR_LEN(class_name) - 1, 0); + zend_str_tolower_copy (ZSTR_VAL(lc_name), ZSTR_VAL(class_name) + 1, ZSTR_LEN(class_name) - 1); + } + else + { + lc_name = zend_string_tolower (class_name); + } + re = zend_hash_del (ht, lc_name); + zend_string_release (lc_name); + if (re == SUCCESS) + { + RETURN_TRUE; + } + RETURN_FALSE; +} + +PHP_FUNCTION(forget_class) +{ + forget_hash_entry (EG(class_table), INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +PHP_FUNCTION(forget_function) +{ + forget_hash_entry (EG(function_table), INTERNAL_FUNCTION_PARAM_PASSTHRU); +} diff --git a/src/plugins/php/weechat-php-api.h b/src/plugins/php/weechat-php-api.h new file mode 100644 index 000000000..eb0e5db69 --- /dev/null +++ b/src/plugins/php/weechat-php-api.h @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2006-2017 Adam Saponara <as@php.net> + * Copyright (C) 2017 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + * + * OpenSSL licensing: + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify the Program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, the licensors of the Program + * grant you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#ifndef WEECHAT_PLUGIN_PHP_API_H +#define WEECHAT_PLUGIN_PHP_API_H 1 + +extern struct zval* weechat_php_api_funcs[]; +extern struct t_php_const weechat_php_api_consts[]; + +extern int weechat_php_api_buffer_input_data_cb (const void *pointer, + void *data, + struct t_gui_buffer *buffer, + const char *input_data); +extern int weechat_php_api_buffer_close_cb (const void *pointer, + void *data, + struct t_gui_buffer *buffer); + +PHP_FUNCTION(weechat_register); +PHP_FUNCTION(weechat_plugin_get_name); +PHP_FUNCTION(weechat_charset_set); +PHP_FUNCTION(weechat_iconv_to_internal); +PHP_FUNCTION(weechat_iconv_from_internal); +PHP_FUNCTION(weechat_gettext); +PHP_FUNCTION(weechat_ngettext); +PHP_FUNCTION(weechat_strlen_screen); +PHP_FUNCTION(weechat_string_match); +PHP_FUNCTION(weechat_string_has_highlight); +PHP_FUNCTION(weechat_string_has_highlight_regex); +PHP_FUNCTION(weechat_string_mask_to_regex); +PHP_FUNCTION(weechat_string_format_size); +PHP_FUNCTION(weechat_string_remove_color); +PHP_FUNCTION(weechat_string_is_command_char); +PHP_FUNCTION(weechat_string_input_for_buffer); +PHP_FUNCTION(weechat_string_eval_expression); +PHP_FUNCTION(weechat_string_eval_path_home); +PHP_FUNCTION(weechat_mkdir_home); +PHP_FUNCTION(weechat_mkdir); +PHP_FUNCTION(weechat_mkdir_parents); +PHP_FUNCTION(weechat_list_new); +PHP_FUNCTION(weechat_list_add); +PHP_FUNCTION(weechat_list_search); +PHP_FUNCTION(weechat_list_search_pos); +PHP_FUNCTION(weechat_list_casesearch); +PHP_FUNCTION(weechat_list_casesearch_pos); +PHP_FUNCTION(weechat_list_get); +PHP_FUNCTION(weechat_list_set); +PHP_FUNCTION(weechat_list_next); +PHP_FUNCTION(weechat_list_prev); +PHP_FUNCTION(weechat_list_string); +PHP_FUNCTION(weechat_list_size); +PHP_FUNCTION(weechat_list_remove); +PHP_FUNCTION(weechat_list_remove_all); +PHP_FUNCTION(weechat_list_free); +PHP_FUNCTION(weechat_config_new); +PHP_FUNCTION(weechat_config_new_section); +PHP_FUNCTION(weechat_config_search_section); +PHP_FUNCTION(weechat_config_new_option); +PHP_FUNCTION(weechat_config_search_option); +PHP_FUNCTION(weechat_config_string_to_boolean); +PHP_FUNCTION(weechat_config_option_reset); +PHP_FUNCTION(weechat_config_option_set); +PHP_FUNCTION(weechat_config_option_set_null); +PHP_FUNCTION(weechat_config_option_unset); +PHP_FUNCTION(weechat_config_option_rename); +PHP_FUNCTION(weechat_config_option_is_null); +PHP_FUNCTION(weechat_config_option_default_is_null); +PHP_FUNCTION(weechat_config_boolean); +PHP_FUNCTION(weechat_config_boolean_default); +PHP_FUNCTION(weechat_config_integer); +PHP_FUNCTION(weechat_config_integer_default); +PHP_FUNCTION(weechat_config_string); +PHP_FUNCTION(weechat_config_string_default); +PHP_FUNCTION(weechat_config_color); +PHP_FUNCTION(weechat_config_color_default); +PHP_FUNCTION(weechat_config_write_option); +PHP_FUNCTION(weechat_config_write_line); +PHP_FUNCTION(weechat_config_write); +PHP_FUNCTION(weechat_config_read); +PHP_FUNCTION(weechat_config_reload); +PHP_FUNCTION(weechat_config_option_free); +PHP_FUNCTION(weechat_config_section_free_options); +PHP_FUNCTION(weechat_config_section_free); +PHP_FUNCTION(weechat_config_free); +PHP_FUNCTION(weechat_config_get); +PHP_FUNCTION(weechat_config_get_plugin); +PHP_FUNCTION(weechat_config_is_set_plugin); +PHP_FUNCTION(weechat_config_set_plugin); +PHP_FUNCTION(weechat_config_set_desc_plugin); +PHP_FUNCTION(weechat_config_unset_plugin); +PHP_FUNCTION(weechat_key_bind); +PHP_FUNCTION(weechat_key_unbind); +PHP_FUNCTION(weechat_prefix); +PHP_FUNCTION(weechat_color); +PHP_FUNCTION(weechat_print); +PHP_FUNCTION(weechat_print_date_tags); +PHP_FUNCTION(weechat_print_y); +PHP_FUNCTION(weechat_log_print); +PHP_FUNCTION(weechat_hook_command); +PHP_FUNCTION(weechat_hook_completion); +PHP_FUNCTION(weechat_hook_completion_get_string); +PHP_FUNCTION(weechat_hook_completion_list_add); +PHP_FUNCTION(weechat_hook_command_run); +PHP_FUNCTION(weechat_hook_timer); +PHP_FUNCTION(weechat_hook_fd); +PHP_FUNCTION(weechat_hook_process); +PHP_FUNCTION(weechat_hook_process_hashtable); +PHP_FUNCTION(weechat_hook_connect); +PHP_FUNCTION(weechat_hook_print); +PHP_FUNCTION(weechat_hook_signal); +PHP_FUNCTION(weechat_hook_signal_send); +PHP_FUNCTION(weechat_hook_hsignal); +PHP_FUNCTION(weechat_hook_hsignal_send); +PHP_FUNCTION(weechat_hook_config); +PHP_FUNCTION(weechat_hook_modifier); +PHP_FUNCTION(weechat_hook_modifier_exec); +PHP_FUNCTION(weechat_hook_info); +PHP_FUNCTION(weechat_hook_info_hashtable); +PHP_FUNCTION(weechat_hook_infolist); +PHP_FUNCTION(weechat_hook_focus); +PHP_FUNCTION(weechat_hook_set); +PHP_FUNCTION(weechat_unhook); +PHP_FUNCTION(weechat_unhook_all); +PHP_FUNCTION(weechat_buffer_new); +PHP_FUNCTION(weechat_buffer_search); +PHP_FUNCTION(weechat_buffer_search_main); +PHP_FUNCTION(weechat_current_buffer); +PHP_FUNCTION(weechat_buffer_clear); +PHP_FUNCTION(weechat_buffer_close); +PHP_FUNCTION(weechat_buffer_merge); +PHP_FUNCTION(weechat_buffer_unmerge); +PHP_FUNCTION(weechat_buffer_get_integer); +PHP_FUNCTION(weechat_buffer_get_string); +PHP_FUNCTION(weechat_buffer_get_pointer); +PHP_FUNCTION(weechat_buffer_set); +PHP_FUNCTION(weechat_buffer_string_replace_local_var); +PHP_FUNCTION(weechat_buffer_match_list); +PHP_FUNCTION(weechat_current_window); +PHP_FUNCTION(weechat_window_search_with_buffer); +PHP_FUNCTION(weechat_window_get_integer); +PHP_FUNCTION(weechat_window_get_string); +PHP_FUNCTION(weechat_window_get_pointer); +PHP_FUNCTION(weechat_window_set_title); +PHP_FUNCTION(weechat_nicklist_add_group); +PHP_FUNCTION(weechat_nicklist_search_group); +PHP_FUNCTION(weechat_nicklist_add_nick); +PHP_FUNCTION(weechat_nicklist_search_nick); +PHP_FUNCTION(weechat_nicklist_remove_group); +PHP_FUNCTION(weechat_nicklist_remove_nick); +PHP_FUNCTION(weechat_nicklist_remove_all); +PHP_FUNCTION(weechat_nicklist_group_get_integer); +PHP_FUNCTION(weechat_nicklist_group_get_string); +PHP_FUNCTION(weechat_nicklist_group_get_pointer); +PHP_FUNCTION(weechat_nicklist_group_set); +PHP_FUNCTION(weechat_nicklist_nick_get_integer); +PHP_FUNCTION(weechat_nicklist_nick_get_string); +PHP_FUNCTION(weechat_nicklist_nick_get_pointer); +PHP_FUNCTION(weechat_nicklist_nick_set); +PHP_FUNCTION(weechat_bar_item_search); +PHP_FUNCTION(weechat_bar_item_new); +PHP_FUNCTION(weechat_bar_item_update); +PHP_FUNCTION(weechat_bar_item_remove); +PHP_FUNCTION(weechat_bar_search); +PHP_FUNCTION(weechat_bar_new); +PHP_FUNCTION(weechat_bar_set); +PHP_FUNCTION(weechat_bar_update); +PHP_FUNCTION(weechat_bar_remove); +PHP_FUNCTION(weechat_command); +PHP_FUNCTION(weechat_info_get); +PHP_FUNCTION(weechat_info_get_hashtable); +PHP_FUNCTION(weechat_infolist_new); +PHP_FUNCTION(weechat_infolist_new_item); +PHP_FUNCTION(weechat_infolist_new_var_integer); +PHP_FUNCTION(weechat_infolist_new_var_string); +PHP_FUNCTION(weechat_infolist_new_var_pointer); +PHP_FUNCTION(weechat_infolist_new_var_time); +PHP_FUNCTION(weechat_infolist_search_var); +PHP_FUNCTION(weechat_infolist_get); +PHP_FUNCTION(weechat_infolist_next); +PHP_FUNCTION(weechat_infolist_prev); +PHP_FUNCTION(weechat_infolist_reset_item_cursor); +PHP_FUNCTION(weechat_infolist_fields); +PHP_FUNCTION(weechat_infolist_integer); +PHP_FUNCTION(weechat_infolist_string); +PHP_FUNCTION(weechat_infolist_pointer); +PHP_FUNCTION(weechat_infolist_time); +PHP_FUNCTION(weechat_infolist_free); +PHP_FUNCTION(weechat_hdata_get); +PHP_FUNCTION(weechat_hdata_get_var_offset); +PHP_FUNCTION(weechat_hdata_get_var_type_string); +PHP_FUNCTION(weechat_hdata_get_var_array_size); +PHP_FUNCTION(weechat_hdata_get_var_array_size_string); +PHP_FUNCTION(weechat_hdata_get_var_hdata); +PHP_FUNCTION(weechat_hdata_get_list); +PHP_FUNCTION(weechat_hdata_check_pointer); +PHP_FUNCTION(weechat_hdata_move); +PHP_FUNCTION(weechat_hdata_search); +PHP_FUNCTION(weechat_hdata_char); +PHP_FUNCTION(weechat_hdata_integer); +PHP_FUNCTION(weechat_hdata_long); +PHP_FUNCTION(weechat_hdata_string); +PHP_FUNCTION(weechat_hdata_pointer); +PHP_FUNCTION(weechat_hdata_time); +PHP_FUNCTION(weechat_hdata_hashtable); +PHP_FUNCTION(weechat_hdata_compare); +PHP_FUNCTION(weechat_hdata_update); +PHP_FUNCTION(weechat_hdata_get_string); +PHP_FUNCTION(weechat_upgrade_new); +PHP_FUNCTION(weechat_upgrade_write_object); +PHP_FUNCTION(weechat_upgrade_read); +PHP_FUNCTION(weechat_upgrade_close); +PHP_FUNCTION(forget_class); +PHP_FUNCTION(forget_function); + +#endif /* WEECHAT_PLUGIN_PHP_API_H */ diff --git a/src/plugins/php/weechat-php.c b/src/plugins/php/weechat-php.c new file mode 100644 index 000000000..1e2bdc6c8 --- /dev/null +++ b/src/plugins/php/weechat-php.c @@ -0,0 +1,1355 @@ +/* + * weechat-php.c - PHP plugin for WeeChat + * + * Copyright (C) 2006-2017 Adam Saponara <as@php.net> + * Copyright (C) 2017 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + * + * OpenSSL licensing: + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify the Program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, the licensors of the Program + * grant you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#include <sapi/embed/php_embed.h> +#include <php.h> +#include <php_ini.h> +#include <ext/standard/info.h> + +#include "../weechat-plugin.h" +#include "../plugin-script.h" +#include "weechat-php.h" +#include "weechat-php-api.h" + +WEECHAT_PLUGIN_NAME(PHP_PLUGIN_NAME); +WEECHAT_PLUGIN_DESCRIPTION(N_("Support of PHP scripts")); +WEECHAT_PLUGIN_AUTHOR("Adam Saponara <as@php.net>"); +WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); +WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); +WEECHAT_PLUGIN_PRIORITY(4000); + +struct t_weechat_plugin *weechat_php_plugin = NULL; + +struct t_plugin_script_data php_data; + +struct t_config_file *php_config_file = NULL; +struct t_config_option *php_config_look_check_license = NULL; +struct t_config_option *php_config_look_eval_keep_context = NULL; + +int php_quiet = 0; + +struct t_plugin_script *php_script_eval = NULL; +int php_eval_mode = 0; +int php_eval_send_input = 0; +int php_eval_exec_commands = 0; +struct t_gui_buffer *php_eval_buffer = NULL; +char *php_eval_output = NULL; + +struct t_plugin_script *php_scripts = NULL; +struct t_plugin_script *last_php_script = NULL; +struct t_plugin_script *php_current_script = NULL; +struct t_plugin_script *php_registered_script = NULL; +const char *php_current_script_filename = NULL; +struct t_hashtable *weechat_php_func_map = NULL; + +/* + * string used to execute action "install": + * when signal "php_script_install" is received, name of string + * is added to this string, to be installed later by a timer (when nothing is + * running in script) + */ +char *php_action_install_list = NULL; + +/* + * string used to execute action "remove": + * when signal "php_script_remove" is received, name of string + * is added to this string, to be removed later by a timer (when nothing is + * running in script) + */ +char *php_action_remove_list = NULL; + +/* + * string used to execute action "autoload": + * when signal "php_script_autoload" is received, name of string + * is added to this string, to autoload or disable autoload later by a timer + * (when nothing is running in script) + */ +char *php_action_autoload_list = NULL; + +const zend_function_entry weechat_functions[] = { + PHP_FE(weechat_register, NULL) + PHP_FE(weechat_plugin_get_name, NULL) + PHP_FE(weechat_charset_set, NULL) + PHP_FE(weechat_iconv_to_internal, NULL) + PHP_FE(weechat_iconv_from_internal, NULL) + PHP_FE(weechat_gettext, NULL) + PHP_FE(weechat_ngettext, NULL) + PHP_FE(weechat_strlen_screen, NULL) + PHP_FE(weechat_string_match, NULL) + PHP_FE(weechat_string_has_highlight, NULL) + PHP_FE(weechat_string_has_highlight_regex, NULL) + PHP_FE(weechat_string_mask_to_regex, NULL) + PHP_FE(weechat_string_format_size, NULL) + PHP_FE(weechat_string_remove_color, NULL) + PHP_FE(weechat_string_is_command_char, NULL) + PHP_FE(weechat_string_input_for_buffer, NULL) + PHP_FE(weechat_string_eval_expression, NULL) + PHP_FE(weechat_string_eval_path_home, NULL) + PHP_FE(weechat_mkdir_home, NULL) + PHP_FE(weechat_mkdir, NULL) + PHP_FE(weechat_mkdir_parents, NULL) + PHP_FE(weechat_list_new, NULL) + PHP_FE(weechat_list_add, NULL) + PHP_FE(weechat_list_search, NULL) + PHP_FE(weechat_list_search_pos, NULL) + PHP_FE(weechat_list_casesearch, NULL) + PHP_FE(weechat_list_casesearch_pos, NULL) + PHP_FE(weechat_list_get, NULL) + PHP_FE(weechat_list_set, NULL) + PHP_FE(weechat_list_next, NULL) + PHP_FE(weechat_list_prev, NULL) + PHP_FE(weechat_list_string, NULL) + PHP_FE(weechat_list_size, NULL) + PHP_FE(weechat_list_remove, NULL) + PHP_FE(weechat_list_remove_all, NULL) + PHP_FE(weechat_list_free, NULL) + PHP_FE(weechat_config_new, NULL) + PHP_FE(weechat_config_new_section, NULL) + PHP_FE(weechat_config_search_section, NULL) + PHP_FE(weechat_config_new_option, NULL) + PHP_FE(weechat_config_search_option, NULL) + PHP_FE(weechat_config_string_to_boolean, NULL) + PHP_FE(weechat_config_option_reset, NULL) + PHP_FE(weechat_config_option_set, NULL) + PHP_FE(weechat_config_option_set_null, NULL) + PHP_FE(weechat_config_option_unset, NULL) + PHP_FE(weechat_config_option_rename, NULL) + PHP_FE(weechat_config_option_is_null, NULL) + PHP_FE(weechat_config_option_default_is_null, NULL) + PHP_FE(weechat_config_boolean, NULL) + PHP_FE(weechat_config_boolean_default, NULL) + PHP_FE(weechat_config_integer, NULL) + PHP_FE(weechat_config_integer_default, NULL) + PHP_FE(weechat_config_string, NULL) + PHP_FE(weechat_config_string_default, NULL) + PHP_FE(weechat_config_color, NULL) + PHP_FE(weechat_config_color_default, NULL) + PHP_FE(weechat_config_write_option, NULL) + PHP_FE(weechat_config_write_line, NULL) + PHP_FE(weechat_config_write, NULL) + PHP_FE(weechat_config_read, NULL) + PHP_FE(weechat_config_reload, NULL) + PHP_FE(weechat_config_option_free, NULL) + PHP_FE(weechat_config_section_free_options, NULL) + PHP_FE(weechat_config_section_free, NULL) + PHP_FE(weechat_config_free, NULL) + PHP_FE(weechat_config_get, NULL) + PHP_FE(weechat_config_get_plugin, NULL) + PHP_FE(weechat_config_is_set_plugin, NULL) + PHP_FE(weechat_config_set_plugin, NULL) + PHP_FE(weechat_config_set_desc_plugin, NULL) + PHP_FE(weechat_config_unset_plugin, NULL) + PHP_FE(weechat_key_bind, NULL) + PHP_FE(weechat_key_unbind, NULL) + PHP_FE(weechat_prefix, NULL) + PHP_FE(weechat_color, NULL) + PHP_FE(weechat_print, NULL) + PHP_FE(weechat_print_date_tags, NULL) + PHP_FE(weechat_print_y, NULL) + PHP_FE(weechat_log_print, NULL) + PHP_FE(weechat_hook_command, NULL) + PHP_FE(weechat_hook_completion, NULL) + PHP_FE(weechat_hook_completion_get_string, NULL) + PHP_FE(weechat_hook_completion_list_add, NULL) + PHP_FE(weechat_hook_command_run, NULL) + PHP_FE(weechat_hook_timer, NULL) + PHP_FE(weechat_hook_fd, NULL) + PHP_FE(weechat_hook_process, NULL) + PHP_FE(weechat_hook_process_hashtable, NULL) + PHP_FE(weechat_hook_connect, NULL) + PHP_FE(weechat_hook_print, NULL) + PHP_FE(weechat_hook_signal, NULL) + PHP_FE(weechat_hook_signal_send, NULL) + PHP_FE(weechat_hook_hsignal, NULL) + PHP_FE(weechat_hook_hsignal_send, NULL) + PHP_FE(weechat_hook_config, NULL) + PHP_FE(weechat_hook_modifier, NULL) + PHP_FE(weechat_hook_modifier_exec, NULL) + PHP_FE(weechat_hook_info, NULL) + PHP_FE(weechat_hook_info_hashtable, NULL) + PHP_FE(weechat_hook_infolist, NULL) + PHP_FE(weechat_hook_focus, NULL) + PHP_FE(weechat_hook_set, NULL) + PHP_FE(weechat_unhook, NULL) + PHP_FE(weechat_unhook_all, NULL) + PHP_FE(weechat_buffer_new, NULL) + PHP_FE(weechat_buffer_search, NULL) + PHP_FE(weechat_buffer_search_main, NULL) + PHP_FE(weechat_current_buffer, NULL) + PHP_FE(weechat_buffer_clear, NULL) + PHP_FE(weechat_buffer_close, NULL) + PHP_FE(weechat_buffer_merge, NULL) + PHP_FE(weechat_buffer_unmerge, NULL) + PHP_FE(weechat_buffer_get_integer, NULL) + PHP_FE(weechat_buffer_get_string, NULL) + PHP_FE(weechat_buffer_get_pointer, NULL) + PHP_FE(weechat_buffer_set, NULL) + PHP_FE(weechat_buffer_string_replace_local_var, NULL) + PHP_FE(weechat_buffer_match_list, NULL) + PHP_FE(weechat_current_window, NULL) + PHP_FE(weechat_window_search_with_buffer, NULL) + PHP_FE(weechat_window_get_integer, NULL) + PHP_FE(weechat_window_get_string, NULL) + PHP_FE(weechat_window_get_pointer, NULL) + PHP_FE(weechat_window_set_title, NULL) + PHP_FE(weechat_nicklist_add_group, NULL) + PHP_FE(weechat_nicklist_search_group, NULL) + PHP_FE(weechat_nicklist_add_nick, NULL) + PHP_FE(weechat_nicklist_search_nick, NULL) + PHP_FE(weechat_nicklist_remove_group, NULL) + PHP_FE(weechat_nicklist_remove_nick, NULL) + PHP_FE(weechat_nicklist_remove_all, NULL) + PHP_FE(weechat_nicklist_group_get_integer, NULL) + PHP_FE(weechat_nicklist_group_get_string, NULL) + PHP_FE(weechat_nicklist_group_get_pointer, NULL) + PHP_FE(weechat_nicklist_group_set, NULL) + PHP_FE(weechat_nicklist_nick_get_integer, NULL) + PHP_FE(weechat_nicklist_nick_get_string, NULL) + PHP_FE(weechat_nicklist_nick_get_pointer, NULL) + PHP_FE(weechat_nicklist_nick_set, NULL) + PHP_FE(weechat_bar_item_search, NULL) + PHP_FE(weechat_bar_item_new, NULL) + PHP_FE(weechat_bar_item_update, NULL) + PHP_FE(weechat_bar_item_remove, NULL) + PHP_FE(weechat_bar_search, NULL) + PHP_FE(weechat_bar_new, NULL) + PHP_FE(weechat_bar_set, NULL) + PHP_FE(weechat_bar_update, NULL) + PHP_FE(weechat_bar_remove, NULL) + PHP_FE(weechat_command, NULL) + PHP_FE(weechat_info_get, NULL) + PHP_FE(weechat_info_get_hashtable, NULL) + PHP_FE(weechat_infolist_new, NULL) + PHP_FE(weechat_infolist_new_item, NULL) + PHP_FE(weechat_infolist_new_var_integer, NULL) + PHP_FE(weechat_infolist_new_var_string, NULL) + PHP_FE(weechat_infolist_new_var_pointer, NULL) + PHP_FE(weechat_infolist_new_var_time, NULL) + PHP_FE(weechat_infolist_search_var, NULL) + PHP_FE(weechat_infolist_get, NULL) + PHP_FE(weechat_infolist_next, NULL) + PHP_FE(weechat_infolist_prev, NULL) + PHP_FE(weechat_infolist_reset_item_cursor, NULL) + PHP_FE(weechat_infolist_fields, NULL) + PHP_FE(weechat_infolist_integer, NULL) + PHP_FE(weechat_infolist_string, NULL) + PHP_FE(weechat_infolist_pointer, NULL) + PHP_FE(weechat_infolist_time, NULL) + PHP_FE(weechat_infolist_free, NULL) + PHP_FE(weechat_hdata_get, NULL) + PHP_FE(weechat_hdata_get_var_offset, NULL) + PHP_FE(weechat_hdata_get_var_type_string, NULL) + PHP_FE(weechat_hdata_get_var_array_size, NULL) + PHP_FE(weechat_hdata_get_var_array_size_string, NULL) + PHP_FE(weechat_hdata_get_var_hdata, NULL) + PHP_FE(weechat_hdata_get_list, NULL) + PHP_FE(weechat_hdata_check_pointer, NULL) + PHP_FE(weechat_hdata_move, NULL) + PHP_FE(weechat_hdata_search, NULL) + PHP_FE(weechat_hdata_char, NULL) + PHP_FE(weechat_hdata_integer, NULL) + PHP_FE(weechat_hdata_long, NULL) + PHP_FE(weechat_hdata_string, NULL) + PHP_FE(weechat_hdata_pointer, NULL) + PHP_FE(weechat_hdata_time, NULL) + PHP_FE(weechat_hdata_hashtable, NULL) + PHP_FE(weechat_hdata_compare, NULL) + PHP_FE(weechat_hdata_update, NULL) + PHP_FE(weechat_hdata_get_string, NULL) + PHP_FE(weechat_upgrade_new, NULL) + PHP_FE(weechat_upgrade_write_object, NULL) + PHP_FE(weechat_upgrade_read, NULL) + PHP_FE(weechat_upgrade_close, NULL) + PHP_FE(forget_class, NULL) + PHP_FE(forget_function, NULL) + PHP_FE_END +}; + +PHP_MINIT_FUNCTION(weechat) +{ + /* make C compiler happy */ + (void) type; + + /* Register integer constants */ + #define PHP_WEECHAT_CONSTANT(NAME) \ + zend_register_long_constant(#NAME, sizeof(#NAME)-1, (NAME), CONST_CS | CONST_PERSISTENT, module_number) + PHP_WEECHAT_CONSTANT(WEECHAT_RC_OK); + PHP_WEECHAT_CONSTANT(WEECHAT_RC_OK_EAT); + PHP_WEECHAT_CONSTANT(WEECHAT_RC_ERROR); + PHP_WEECHAT_CONSTANT(WEECHAT_CONFIG_READ_OK); + PHP_WEECHAT_CONSTANT(WEECHAT_CONFIG_READ_MEMORY_ERROR); + PHP_WEECHAT_CONSTANT(WEECHAT_CONFIG_READ_FILE_NOT_FOUND); + PHP_WEECHAT_CONSTANT(WEECHAT_CONFIG_WRITE_OK); + PHP_WEECHAT_CONSTANT(WEECHAT_CONFIG_WRITE_ERROR); + PHP_WEECHAT_CONSTANT(WEECHAT_CONFIG_WRITE_MEMORY_ERROR); + PHP_WEECHAT_CONSTANT(WEECHAT_CONFIG_OPTION_SET_OK_CHANGED); + PHP_WEECHAT_CONSTANT(WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE); + PHP_WEECHAT_CONSTANT(WEECHAT_CONFIG_OPTION_SET_ERROR); + PHP_WEECHAT_CONSTANT(WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND); + PHP_WEECHAT_CONSTANT(WEECHAT_CONFIG_OPTION_UNSET_OK_NO_RESET); + PHP_WEECHAT_CONSTANT(WEECHAT_CONFIG_OPTION_UNSET_OK_RESET); + PHP_WEECHAT_CONSTANT(WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED); + PHP_WEECHAT_CONSTANT(WEECHAT_CONFIG_OPTION_UNSET_ERROR); + PHP_WEECHAT_CONSTANT(WEECHAT_HDATA_OTHER); + PHP_WEECHAT_CONSTANT(WEECHAT_HDATA_CHAR); + PHP_WEECHAT_CONSTANT(WEECHAT_HDATA_INTEGER); + PHP_WEECHAT_CONSTANT(WEECHAT_HDATA_LONG); + PHP_WEECHAT_CONSTANT(WEECHAT_HDATA_STRING); + PHP_WEECHAT_CONSTANT(WEECHAT_HDATA_POINTER); + PHP_WEECHAT_CONSTANT(WEECHAT_HDATA_TIME); + PHP_WEECHAT_CONSTANT(WEECHAT_HDATA_HASHTABLE); + PHP_WEECHAT_CONSTANT(WEECHAT_HDATA_SHARED_STRING); + PHP_WEECHAT_CONSTANT(WEECHAT_HDATA_LIST_CHECK_POINTERS); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_PROCESS_RUNNING); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_PROCESS_ERROR); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_PROCESS_CHILD); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_CONNECT_OK); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_CONNECT_PROXY_ERROR); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_CONNECT_GNUTLS_INIT_ERROR); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_CONNECT_MEMORY_ERROR); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_CONNECT_TIMEOUT); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_CONNECT_SOCKET_ERROR); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_CONNECT_GNUTLS_CB_VERIFY_CERT); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_CONNECT_GNUTLS_CB_SET_CERT); + #undef PHP_WEECHAT_CONSTANT + + /* Register string constants */ + #define PHP_WEECHAT_CONSTANT(NAME) \ + zend_register_string_constant(#NAME, sizeof(#NAME)-1, (NAME), CONST_CS | CONST_PERSISTENT, module_number) + PHP_WEECHAT_CONSTANT(WEECHAT_PLUGIN_API_VERSION); + PHP_WEECHAT_CONSTANT(WEECHAT_CONFIG_OPTION_NULL); + PHP_WEECHAT_CONSTANT(WEECHAT_LIST_POS_SORT); + PHP_WEECHAT_CONSTANT(WEECHAT_LIST_POS_BEGINNING); + PHP_WEECHAT_CONSTANT(WEECHAT_LIST_POS_END); + PHP_WEECHAT_CONSTANT(WEECHAT_HASHTABLE_INTEGER); + PHP_WEECHAT_CONSTANT(WEECHAT_HASHTABLE_STRING); + PHP_WEECHAT_CONSTANT(WEECHAT_HASHTABLE_POINTER); + PHP_WEECHAT_CONSTANT(WEECHAT_HASHTABLE_BUFFER); + PHP_WEECHAT_CONSTANT(WEECHAT_HASHTABLE_TIME); + PHP_WEECHAT_CONSTANT(WEECHAT_HOTLIST_LOW); + PHP_WEECHAT_CONSTANT(WEECHAT_HOTLIST_MESSAGE); + PHP_WEECHAT_CONSTANT(WEECHAT_HOTLIST_PRIVATE); + PHP_WEECHAT_CONSTANT(WEECHAT_HOTLIST_HIGHLIGHT); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_SIGNAL_STRING); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_SIGNAL_INT); + PHP_WEECHAT_CONSTANT(WEECHAT_HOOK_SIGNAL_POINTER); + #undef PHP_WEECHAT_CONSTANT + return SUCCESS; +} + +zend_module_entry weechat_module_entry = { + STANDARD_MODULE_HEADER, + "weechat", + weechat_functions, + PHP_MINIT(weechat), + NULL, + NULL, + NULL, + NULL, + PHP_WEECHAT_VERSION, + STANDARD_MODULE_PROPERTIES +}; + +/* + * Callback called for each key/value in a hashtable. + */ + +void +weechat_php_hashtable_to_array_cb (void *data, + struct t_hashtable *hashtable, + const char *key, + const char *value) +{ + /* make C compiler happy */ + (void) hashtable; + + add_assoc_string ((zval*)data, key, (char*)value); +} + +/* + * Converts a WeeChat hashtable to a PHP array. + */ + +void +weechat_php_hashtable_to_array (struct t_hashtable *hashtable, zval *arr) +{ + array_init (arr); + weechat_hashtable_map_string (hashtable, + &weechat_php_hashtable_to_array_cb, + arr); +} + +/* + * Converts a PHP array to a WeeChat hashtable. + * + * Note: hashtable must be freed after use. + */ + +struct t_hashtable * +weechat_php_array_to_hashtable (zval *arr, + int size, + const char *type_keys, + const char *type_values) +{ + struct t_hashtable *hashtable; + zend_string *key; + zval *val; + + hashtable = weechat_hashtable_new (size, type_keys, type_values, + NULL, NULL); + if (!hashtable) + return NULL; + + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(arr), key, val) { + if (strcmp (type_values, WEECHAT_HASHTABLE_STRING) == 0) + { + weechat_hashtable_set (hashtable, + ZSTR_VAL(key), + Z_STRVAL_P(val)); + } + else if (strcmp (type_values, WEECHAT_HASHTABLE_POINTER) == 0) + { + weechat_hashtable_set (hashtable, + ZSTR_VAL(key), + plugin_script_str2ptr ( + weechat_php_plugin, + NULL, NULL, + Z_STRVAL_P(val))); + } + } ZEND_HASH_FOREACH_END(); + + return hashtable; +} + +static void +weechat_php_func_map_free_val (struct t_hashtable *hashtable, + const void *key, void *value) +{ + /* make C compiler happy */ + (void) hashtable; + (void) key; + + zval_dtor ((zval *)value); + efree ((zval *)value); +} + +static void +weechat_php_func_map_free_key (struct t_hashtable *hashtable, void *key) +{ + /* make C compiler happy */ + (void) hashtable; + + free ((char *)key); +} + +zval * +weechat_php_func_map_get (const char* func_name) +{ + if (!weechat_php_func_map) + return NULL; + + return weechat_hashtable_get (weechat_php_func_map, func_name); +} + +const char * +weechat_php_func_map_add (zval *ofunc) +{ + zval *func; + const char *func_name; + + if (!weechat_php_func_map) + { + weechat_php_func_map = weechat_hashtable_new (32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, + NULL, NULL); + weechat_hashtable_set_pointer (weechat_php_func_map, + "callback_free_value", + weechat_php_func_map_free_val); + weechat_hashtable_set_pointer (weechat_php_func_map, + "callback_free_key", + weechat_php_func_map_free_key); + } + + func = (zval *)safe_emalloc (sizeof (zval), 1, 0); + ZVAL_COPY(func, ofunc); + func_name = plugin_script_ptr2str (func); + + weechat_hashtable_set (weechat_php_func_map, func_name, func); + + return func_name; +} + +/* + * Executes a PHP function. + */ + +void * +weechat_php_exec (struct t_plugin_script *script, int ret_type, + const char *function, const char *format, void **argv) +{ + int argc, i; + zval *params; + zval zretval; + void *ret_value; + int *ret_i; + zend_fcall_info fci; + zend_fcall_info_cache fci_cache; + struct t_plugin_script *old_php_current_script; + zval *zfunc; + + /* Save old script */ + old_php_current_script = php_current_script; + php_current_script = script; + + /* Build func args */ + if (!format || !format[0]) + { + argc = 0; + params = NULL; + } + else + { + argc = strlen (format); + params = safe_emalloc (sizeof (zval), argc, 0); + + for (i = 0; i < argc; i++) + { + switch (format[i]) + { + case 's': /* string */ + ZVAL_STRING(¶ms[i], (char *)argv[i]); + break; + case 'i': /* integer */ + ZVAL_LONG(¶ms[i], *((int *)argv[i])); + break; + case 'h': /* hash */ + weechat_php_hashtable_to_array ((struct t_hashtable *)argv[i], + ¶ms[i]); + break; + } + } + } + + /* Invoke func */ + ret_value = NULL; + memset (&fci, 0, sizeof (zend_fcall_info)); + memset (&fci_cache, 0, sizeof (zend_fcall_info_cache)); + + zfunc = weechat_php_func_map_get (function); + if (zfunc && zend_fcall_info_init (zfunc, 0, &fci, &fci_cache, NULL, NULL) == SUCCESS) + { + fci.params = params; + fci.param_count = argc; + fci.retval = &zretval; + } + + zend_try + { + if (zfunc && zend_call_function (&fci, &fci_cache) == SUCCESS) + { + if (ret_type == WEECHAT_SCRIPT_EXEC_STRING) + { + convert_to_string (&zretval); + ret_value = strdup ((char *)Z_STRVAL(zretval)); + } + else if (ret_type == WEECHAT_SCRIPT_EXEC_POINTER) + { + convert_to_string (&zretval); + ret_value = plugin_script_str2ptr (weechat_php_plugin, + script->name, function, + (char *)Z_STRVAL(zretval)); + } + else if (ret_type == WEECHAT_SCRIPT_EXEC_INT) + { + convert_to_long (&zretval); + ret_i = malloc (sizeof (*ret_i)); + *ret_i = Z_LVAL(zretval); + ret_value = ret_i; + } + else if (ret_type == WEECHAT_SCRIPT_EXEC_HASHTABLE) + { + ret_value = weechat_php_array_to_hashtable (&zretval, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING); + } + else + { + if (ret_type != WEECHAT_SCRIPT_EXEC_IGNORE) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: function \"%s\" " + "must return a valid " + "value"), + weechat_prefix ("error"), PHP_PLUGIN_NAME, + function); + } + } + } + else + { + weechat_printf (NULL, + weechat_gettext ("%s%s: unable to run function \"%s\""), + weechat_prefix ("error"), PHP_PLUGIN_NAME, function); + } + } + zend_end_try (); + + if ((ret_type != WEECHAT_SCRIPT_EXEC_IGNORE) && !ret_value) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: error in function \"%s\""), + weechat_prefix ("error"), PHP_PLUGIN_NAME, function); + } + + /* Cleanup */ + if (params) + { + for (i = 0; i < argc; i++) + { + zval_ptr_dtor (¶ms[i]); + } + efree (params); + } + + /* Restore old script */ + php_current_script = old_php_current_script; + + return ret_value; +} + +/* + * Loads a PHP script. + * + * If code is NULL, the content of filename is read and executed. + * If code is not NULL, it is executed (the file is not read). + * + * Returns pointer to new registered script, NULL if error. + */ + +struct t_plugin_script * +weechat_php_load (const char *filename, const char *code) +{ + zend_file_handle file_handle; + + /* make C compiler happy */ + /* TODO: implement load of code in PHP */ + (void) code; + + if ((weechat_php_plugin->debug >= 2) || !php_quiet) + { + weechat_printf (NULL, + weechat_gettext ("%s: loading script \"%s\""), + PHP_PLUGIN_NAME, filename); + } + + php_current_script = NULL; + php_registered_script = NULL; + php_current_script_filename = filename; + + file_handle.filename = filename; + file_handle.free_filename = 0; + file_handle.type = ZEND_HANDLE_FILENAME; + file_handle.opened_path = NULL; + file_handle.handle.fp = NULL; + + zend_try + { + php_execute_script (&file_handle); + } + zend_end_try (); + + if (!php_registered_script) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: function \"register\" not " + "found (or failed) in file \"%s\""), + weechat_prefix ("error"), PHP_PLUGIN_NAME, filename); + return NULL; + } + php_current_script = php_registered_script; + + plugin_script_set_buffer_callbacks (weechat_php_plugin, + php_scripts, + php_current_script, + &weechat_php_api_buffer_input_data_cb, + &weechat_php_api_buffer_close_cb); + + (void) weechat_hook_signal_send ("php_script_loaded", + WEECHAT_HOOK_SIGNAL_STRING, + php_current_script->filename); + + return php_current_script; +} + +/* + * Callback for script_auto_load() function. + */ + +void +weechat_php_load_cb (void *data, const char *filename) +{ + /* make C compiler happy */ + (void) data; + + weechat_php_load (filename, NULL); +} + +/* + * Unloads a PHP script. + */ + +void +weechat_php_unload (struct t_plugin_script *script) +{ + int *rc; + char *filename; + + if ((weechat_php_plugin->debug >= 2) || !php_quiet) + { + weechat_printf (NULL, + weechat_gettext ("%s: unloading script \"%s\""), + PHP_PLUGIN_NAME, script->name); + } + + if (script->shutdown_func && script->shutdown_func[0]) + { + rc = (int *)weechat_php_exec (script, + WEECHAT_SCRIPT_EXEC_INT, + script->shutdown_func, + NULL, NULL); + if (rc) + free (rc); + } + + filename = strdup (script->filename); + + if (php_current_script == script) + php_current_script = (php_current_script->prev_script) ? + php_current_script->prev_script : php_current_script->next_script; + + plugin_script_remove (weechat_php_plugin, &php_scripts, &last_php_script, script); + + (void) weechat_hook_signal_send ("php_script_unloaded", + WEECHAT_HOOK_SIGNAL_STRING, filename); + if (filename) + free (filename); +} + +/* + * Unloads a PHP script by name. + */ + +void +weechat_php_unload_name (const char *name) +{ + struct t_plugin_script *ptr_script; + + ptr_script = plugin_script_search (weechat_php_plugin, php_scripts, name); + if (ptr_script) + { + weechat_php_unload (ptr_script); + if (!php_quiet) + { + weechat_printf (NULL, + weechat_gettext ("%s: script \"%s\" unloaded"), + PHP_PLUGIN_NAME, name); + } + } + else + { + weechat_printf (NULL, + weechat_gettext ("%s%s: script \"%s\" not loaded"), + weechat_prefix ("error"), PHP_PLUGIN_NAME, name); + } +} + +/* + * Unloads all PHP scripts. + */ + +void +weechat_php_unload_all () +{ + while (php_scripts) + { + weechat_php_unload (php_scripts); + } +} + +/* + * Reloads a PHP script by name. + */ + +void +weechat_php_reload_name (const char *name) +{ + struct t_plugin_script *ptr_script; + char *filename; + + ptr_script = plugin_script_search (weechat_php_plugin, php_scripts, name); + if (ptr_script) + { + filename = strdup (ptr_script->filename); + if (filename) + { + weechat_php_unload (ptr_script); + if (!php_quiet) + { + weechat_printf (NULL, + weechat_gettext ("%s: script \"%s\" unloaded"), + PHP_PLUGIN_NAME, name); + } + weechat_php_load (filename, NULL); + free (filename); + } + } + else + { + weechat_printf (NULL, + weechat_gettext ("%s%s: script \"%s\" not loaded"), + weechat_prefix ("error"), PHP_PLUGIN_NAME, name); + } +} + +/* + * Evaluates PHP source code. + * + * Returns: + * 1: OK + * 0: error + */ + +int +weechat_php_eval (struct t_gui_buffer *buffer, int send_to_buffer_as_input, + int exec_commands, const char *code) +{ + /* TODO: implement PHP eval */ + (void) buffer; + (void) send_to_buffer_as_input; + (void) exec_commands; + (void) code; + + return 1; +} + +/* + * Callback for command "/php". + */ + +int +weechat_php_command_cb (const void *pointer, void *data, + struct t_gui_buffer *buffer, + int argc, char **argv, char **argv_eol) +{ + char *ptr_name, *ptr_code, *path_script; + int i, send_to_buffer_as_input, exec_commands; + + /* make C compiler happy */ + (void) pointer; + (void) data; + + if (argc == 1) + { + plugin_script_display_list (weechat_php_plugin, php_scripts, + NULL, 0); + } + else if (argc == 2) + { + if (weechat_strcasecmp (argv[1], "list") == 0) + { + plugin_script_display_list (weechat_php_plugin, php_scripts, + NULL, 0); + } + else if (weechat_strcasecmp (argv[1], "listfull") == 0) + { + plugin_script_display_list (weechat_php_plugin, php_scripts, + NULL, 1); + } + else if (weechat_strcasecmp (argv[1], "autoload") == 0) + { + plugin_script_auto_load (weechat_php_plugin, &weechat_php_load_cb); + } + else if (weechat_strcasecmp (argv[1], "reload") == 0) + { + weechat_php_unload_all (); + plugin_script_auto_load (weechat_php_plugin, &weechat_php_load_cb); + } + else if (weechat_strcasecmp (argv[1], "unload") == 0) + { + weechat_php_unload_all (); + } + else if (weechat_strcasecmp (argv[1], "version") == 0) + { + plugin_script_display_interpreter (weechat_php_plugin, 0); + } + else + WEECHAT_COMMAND_ERROR; + } + else + { + if (weechat_strcasecmp (argv[1], "list") == 0) + { + plugin_script_display_list (weechat_php_plugin, php_scripts, + argv_eol[2], 0); + } + else if (weechat_strcasecmp (argv[1], "listfull") == 0) + { + plugin_script_display_list (weechat_php_plugin, php_scripts, + argv_eol[2], 1); + } + else if ((weechat_strcasecmp (argv[1], "load") == 0) + || (weechat_strcasecmp (argv[1], "reload") == 0) + || (weechat_strcasecmp (argv[1], "unload") == 0)) + { + ptr_name = argv_eol[2]; + if (strncmp (ptr_name, "-q ", 3) == 0) + { + php_quiet = 1; + ptr_name += 3; + while (ptr_name[0] == ' ') + { + ptr_name++; + } + } + if (weechat_strcasecmp (argv[1], "load") == 0) + { + /* load PHP script */ + path_script = plugin_script_search_path (weechat_php_plugin, + ptr_name); + weechat_php_load ((path_script) ? path_script : ptr_name, + NULL); + if (path_script) + free (path_script); + } + else if (weechat_strcasecmp (argv[1], "reload") == 0) + { + /* reload one PHP script */ + weechat_php_reload_name (ptr_name); + } + else if (weechat_strcasecmp (argv[1], "unload") == 0) + { + /* unload PHP script */ + weechat_php_unload_name (ptr_name); + } + php_quiet = 0; + } + else if (weechat_strcasecmp (argv[1], "eval") == 0) + { + send_to_buffer_as_input = 0; + exec_commands = 0; + ptr_code = argv_eol[2]; + for (i = 2; i < argc; i++) + { + if (argv[i][0] == '-') + { + if (strcmp (argv[i], "-o") == 0) + { + if (i + 1 >= argc) + WEECHAT_COMMAND_ERROR; + send_to_buffer_as_input = 1; + exec_commands = 0; + ptr_code = argv_eol[i + 1]; + } + else if (strcmp (argv[i], "-oc") == 0) + { + if (i + 1 >= argc) + WEECHAT_COMMAND_ERROR; + send_to_buffer_as_input = 1; + exec_commands = 1; + ptr_code = argv_eol[i + 1]; + } + } + else + break; + } + if (!weechat_php_eval (buffer, send_to_buffer_as_input, + exec_commands, ptr_code)) + WEECHAT_COMMAND_ERROR; + /* TODO: implement /php eval */ + weechat_printf (NULL, + _("%sCommand \"/%s eval\" is not yet implemented"), + weechat_prefix ("error"), + weechat_php_plugin->name); + } + else + WEECHAT_COMMAND_ERROR; + } + + return WEECHAT_RC_OK; +} + +/* + * Adds PHP scripts to completion list. + */ + +int +weechat_php_completion_cb (const void *pointer, void *data, + const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) completion_item; + (void) buffer; + + plugin_script_completion (weechat_php_plugin, completion, php_scripts); + + return WEECHAT_RC_OK; +} + +/* + * Returns hdata for PHP scripts. + */ + +struct t_hdata * +weechat_php_hdata_cb (const void *pointer, void *data, + const char *hdata_name) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + + return plugin_script_hdata_script (weechat_plugin, + &php_scripts, &last_php_script, + hdata_name); +} + +/* + * Returns PHP info "php_eval". + */ + +const char * +weechat_php_info_eval_cb (const void *pointer, void *data, + const char *info_name, + const char *arguments) +{ + static const char *not_implemented = "not yet implemented"; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) info_name; + (void) arguments; + + return not_implemented; +} + +/* + * Returns infolist with PHP scripts. + */ + +struct t_infolist * +weechat_php_infolist_cb (const void *pointer, void *data, + const char *infolist_name, + void *obj_pointer, const char *arguments) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + + if (!infolist_name || !infolist_name[0]) + return NULL; + + if (weechat_strcasecmp (infolist_name, "php_script") == 0) + { + return plugin_script_infolist_list_scripts (weechat_php_plugin, + php_scripts, obj_pointer, + arguments); + } + + return NULL; +} + +/* + * Dumps PHP plugin data in WeeChat log file. + */ + +int +weechat_php_signal_debug_dump_cb (const void *pointer, void *data, + const char *signal, + const char *type_data, void *signal_data) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) signal; + (void) type_data; + + if (!signal_data + || (weechat_strcasecmp ((char *)signal_data, PHP_PLUGIN_NAME) == 0)) + { + plugin_script_print_log (weechat_php_plugin, php_scripts); + } + + return WEECHAT_RC_OK; +} + +/* + * Timer for executing actions. + */ + +int +weechat_php_timer_action_cb (const void *pointer, void *data, + int remaining_calls) +{ + /* make C compiler happy */ + (void) data; + (void) remaining_calls; + + if (pointer) + { + if (pointer == &php_action_install_list) + { + plugin_script_action_install (weechat_php_plugin, + php_scripts, + &weechat_php_unload, + &weechat_php_load, + &php_quiet, + &php_action_install_list); + } + else if (pointer == &php_action_remove_list) + { + plugin_script_action_remove (weechat_php_plugin, + php_scripts, + &weechat_php_unload, + &php_quiet, + &php_action_remove_list); + } + else if (pointer == &php_action_autoload_list) + { + plugin_script_action_autoload (weechat_php_plugin, + &php_quiet, + &php_action_autoload_list); + } + } + + return WEECHAT_RC_OK; +} + +/* + * Callback called when a script action is asked (install/remove/autoload a + * script). + */ + +int +weechat_php_signal_script_action_cb (const void *pointer, void *data, + const char *signal, + const char *type_data, + void *signal_data) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + + if (strcmp (type_data, WEECHAT_HOOK_SIGNAL_STRING) == 0) + { + if (strcmp (signal, "php_script_install") == 0) + { + plugin_script_action_add (&php_action_install_list, + (const char *)signal_data); + weechat_hook_timer (1, 0, 1, + &weechat_php_timer_action_cb, + &php_action_install_list, NULL); + } + else if (strcmp (signal, "php_script_remove") == 0) + { + plugin_script_action_add (&php_action_remove_list, + (const char *)signal_data); + weechat_hook_timer (1, 0, 1, + &weechat_php_timer_action_cb, + &php_action_remove_list, NULL); + } + else if (strcmp (signal, "php_script_autoload") == 0) + { + plugin_script_action_add (&php_action_autoload_list, + (const char *)signal_data); + weechat_hook_timer (1, 0, 1, + &weechat_php_timer_action_cb, + &php_action_autoload_list, NULL); + } + } + + return WEECHAT_RC_OK; +} + +int +php_weechat_startup (sapi_module_struct *sapi_module) +{ + return php_module_startup (sapi_module, &weechat_module_entry, 1); +} + +size_t +php_weechat_ub_write (const char *str, size_t str_length) +{ + weechat_printf (NULL, "php: %s", str); + return str_length + 5; +} + +void +php_weechat_sapi_error (int type, const char *format, ...) +{ + /* make C compiler happy */ + (void) type; + + weechat_va_format (format); + if (vbuffer) + { + php_weechat_ub_write (vbuffer, strlen (vbuffer)); + free (vbuffer); + } +} + +#if PHP_VERSION_ID >= 70100 +/* PHP >= 7.1 */ +void +php_weechat_log_message (char *message, int syslog_type_int) +{ + /* make C compiler happy */ + (void) syslog_type_int; + + php_weechat_ub_write (message, strlen (message)); +} +#else +/* PHP 7.0 */ +void +php_weechat_log_message (char *message) +{ + php_weechat_ub_write (message, strlen (message)); +} +#endif + +/* + * Initializes PHP plugin. + */ + +int +weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) +{ + weechat_php_plugin = plugin; + + /* set interpreter name and version */ + weechat_hashtable_set (plugin->variables, "interpreter_name", + plugin->name); +#ifdef PHP_VERSION + weechat_hashtable_set (plugin->variables, "interpreter_version", + PHP_VERSION); +#else + weechat_hashtable_set (plugin->variables, "interpreter_version", + ""); +#endif /* PHP_VERSION */ + + php_data.config_file = &php_config_file; + php_data.config_look_check_license = &php_config_look_check_license; + php_data.config_look_eval_keep_context = &php_config_look_eval_keep_context; + php_data.scripts = &php_scripts; + php_data.last_script = &last_php_script; + php_data.callback_command = &weechat_php_command_cb; + php_data.callback_completion = &weechat_php_completion_cb; + php_data.callback_hdata = &weechat_php_hdata_cb; + php_data.callback_info_eval = &weechat_php_info_eval_cb; + php_data.callback_infolist = &weechat_php_infolist_cb; + php_data.callback_signal_debug_dump = &weechat_php_signal_debug_dump_cb; + php_data.callback_signal_script_action = &weechat_php_signal_script_action_cb; + php_data.callback_load_file = &weechat_php_load_cb; + php_data.unload_all = &weechat_php_unload_all; + + php_embed_module.startup = php_weechat_startup; + php_embed_module.ub_write = php_weechat_ub_write; + php_embed_module.flush = NULL; + php_embed_module.sapi_error = php_weechat_sapi_error; + php_embed_module.log_message = php_weechat_log_message; + + php_embed_init (0, NULL); + + PG(report_zend_debug) = 0; /* Turn off --enable-debug output */ + + php_quiet = 1; + plugin_script_init (weechat_php_plugin, argc, argv, &php_data); + php_quiet = 0; + + plugin_script_display_short_list (weechat_php_plugin, + php_scripts); + + /* init OK */ + return WEECHAT_RC_OK; +} + +/* + * Ends PHP plugin. + */ + +int +weechat_plugin_end (struct t_weechat_plugin *plugin) +{ + /* unload all scripts */ + php_quiet = 1; + if (php_script_eval) + { + weechat_php_unload (php_script_eval); + php_script_eval = NULL; + } + plugin_script_end (plugin, &php_data); + php_quiet = 0; + + if (weechat_php_func_map) + { + weechat_hashtable_remove_all (weechat_php_func_map); + weechat_hashtable_free (weechat_php_func_map); + weechat_php_func_map = NULL; + } + + php_embed_shutdown (); + + if (php_action_install_list) + free (php_action_install_list); + if (php_action_remove_list) + free (php_action_remove_list); + if (php_action_autoload_list) + free (php_action_autoload_list); + /* weechat_string_dyn_free (php_buffer_output, 1); */ + if (php_eval_output) + free (php_eval_output); + + return WEECHAT_RC_OK; +} diff --git a/src/plugins/php/weechat-php.h b/src/plugins/php/weechat-php.h new file mode 100644 index 000000000..333840745 --- /dev/null +++ b/src/plugins/php/weechat-php.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2006-2017 Adam Saponara <as@php.net> + * Copyright (C) 2017 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + * + * OpenSSL licensing: + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify the Program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, the licensors of the Program + * grant you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#ifndef WEECHAT_PLUGIN_PHP_H +#define WEECHAT_PLUGIN_PHP_H 1 + +#define weechat_plugin weechat_php_plugin +#define PHP_PLUGIN_NAME "php" +#define PHP_WEECHAT_VERSION "0.1" + +#define PHP_CURRENT_SCRIPT_NAME ((php_current_script) ? php_current_script->name : "-") + +struct t_php_const +{ + char *name; + int int_value; + char *str_value; +}; + +extern struct t_weechat_plugin *weechat_php_plugin; + +extern struct t_plugin_script_data php_data; + +extern struct t_hashtable *weechat_php_function_map; + +extern int php_quiet; +extern struct t_plugin_script *php_scripts; +extern struct t_plugin_script *last_php_script; +extern struct t_plugin_script *php_current_script; +extern struct t_plugin_script *php_registered_script; +extern const char *php_current_script_filename; + +extern void weechat_php_hashtable_to_array (struct t_hashtable *hashtable, + zval *arr); +extern struct t_hashtable *weechat_php_array_to_hashtable (zval* arr, + int size, + const char *type_keys, + const char *type_values); +extern zval *weechat_php_func_map_get (const char *func_name); +extern const char *weechat_php_func_map_add (zval *ofunc); +extern void *weechat_php_exec (struct t_plugin_script *script, + int ret_type, + const char *function, + const char *format, void **argv); + +#endif /* WEECHAT_PLUGIN_PHP_H */ diff --git a/src/plugins/plugin-api.c b/src/plugins/plugin-api.c index f5958a4af..e2702eeef 100644 --- a/src/plugins/plugin-api.c +++ b/src/plugins/plugin-api.c @@ -1,7 +1,7 @@ /* * plugin-api.c - extra functions for plugin API * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -108,6 +108,16 @@ plugin_api_ngettext (const char *single, const char *plural, int count) } /* + * Frees an option. + */ + +void +plugin_api_config_file_option_free (struct t_config_option *option) +{ + config_file_option_free (option, 1); +} + +/* * Gets pointer on an option. */ @@ -378,7 +388,7 @@ plugin_api_info_date_cb (const void *pointer, void *data, (void) info_name; (void) arguments; - return version_get_compilation_date (); + return version_get_compilation_date_time (); } /* @@ -633,7 +643,7 @@ plugin_api_info_inactivity_cb (const void *pointer, void *data, inactivity = 0; else inactivity = time (NULL) - gui_key_last_activity_time; - snprintf (value, sizeof (value), "%ld", (long int)inactivity); + snprintf (value, sizeof (value), "%lld", (long long)inactivity); return value; } @@ -880,7 +890,7 @@ plugin_api_info_uptime_cb (const void *pointer, void *data, { /* return the number of seconds */ util_get_uptime (&total_seconds, NULL, NULL, NULL, NULL); - snprintf (value, sizeof (value), "%ld", total_seconds); + snprintf (value, sizeof (value), "%lld", (long long)total_seconds); return value; } @@ -1895,7 +1905,7 @@ plugin_api_init () "release)"), NULL, &plugin_api_info_version_git_cb, NULL, NULL); hook_info (NULL, "date", - N_("WeeChat compilation date"), + N_("WeeChat compilation date/time"), NULL, &plugin_api_info_date_cb, NULL, NULL); hook_info (NULL, "pid", N_("WeeChat PID (process ID)"), diff --git a/src/plugins/plugin-api.h b/src/plugins/plugin-api.h index e7f8f1ca2..c754fe243 100644 --- a/src/plugins/plugin-api.h +++ b/src/plugins/plugin-api.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_PLUGIN_API_H -#define WEECHAT_PLUGIN_API_H 1 +#ifndef WEECHAT_PLUGIN_PLUGIN_API_H +#define WEECHAT_PLUGIN_PLUGIN_API_H #include <time.h> @@ -30,6 +30,7 @@ extern const char *plugin_api_ngettext (const char *single, const char *plural, int count); /* config */ +extern void plugin_api_config_file_option_free (struct t_config_option *option); extern struct t_config_option *plugin_api_config_get (const char *option_name); extern const char *plugin_api_config_get_plugin (struct t_weechat_plugin *plugin, const char *option_name); @@ -72,4 +73,4 @@ extern void plugin_api_infolist_free (struct t_infolist *infolist); extern void plugin_api_init (); -#endif /* WEECHAT_PLUGIN_API_H */ +#endif /* WEECHAT_PLUGIN_PLUGIN_API_H */ diff --git a/src/plugins/plugin-config.c b/src/plugins/plugin-config.c index 9f2710678..01516a9ca 100644 --- a/src/plugins/plugin-config.c +++ b/src/plugins/plugin-config.c @@ -1,7 +1,7 @@ /* * plugin-config.c - plugin configuration options (file plugins.conf) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -335,7 +335,7 @@ plugin_config_delete_desc (const void *pointer, void *data, } } - config_file_option_free (option); + config_file_option_free (option, 1); return WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED; } diff --git a/src/plugins/plugin-config.h b/src/plugins/plugin-config.h index ee9fe83b7..b9be2217f 100644 --- a/src/plugins/plugin-config.h +++ b/src/plugins/plugin-config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_PLUGIN_CONFIG_H -#define WEECHAT_PLUGIN_CONFIG_H 1 +#ifndef WEECHAT_PLUGIN_PLUGIN_CONFIG_H +#define WEECHAT_PLUGIN_PLUGIN_CONFIG_H #define PLUGIN_CONFIG_NAME "plugins" @@ -37,4 +37,4 @@ extern int plugin_config_read (); extern int plugin_config_write (); extern void plugin_config_end (); -#endif /* WEECHAT_PLUGIN_CONFIG_H */ +#endif /* WEECHAT_PLUGIN_PLUGIN_CONFIG_H */ diff --git a/src/plugins/plugin-script-api.c b/src/plugins/plugin-script-api.c index 2f3031943..d922df411 100644 --- a/src/plugins/plugin-script-api.c +++ b/src/plugins/plugin-script-api.c @@ -1,7 +1,7 @@ /* * script-api.c - script API functions, used by script plugins * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2012 Simon Arlott * * This file is part of WeeChat, the extensible chat client. @@ -38,6 +38,9 @@ void plugin_script_api_charset_set (struct t_plugin_script *script, const char *charset) { + if (!script) + return; + if (script->charset) free (script->charset); @@ -63,13 +66,16 @@ plugin_script_api_config_new (struct t_weechat_plugin *weechat_plugin, char *function_and_data; struct t_config_file *new_config_file; + if (!script) + return NULL; + function_and_data = plugin_script_build_function_and_data (function, data); - new_config_file = weechat_config_new - (name, - (function_and_data) ? callback_reload : NULL, - script, - function_and_data); + new_config_file = weechat_config_new ( + name, + (function_and_data) ? callback_reload : NULL, + script, + function_and_data); if (!new_config_file) { @@ -134,6 +140,9 @@ plugin_script_api_config_new_section (struct t_weechat_plugin *weechat_plugin, char *function_and_data_delete_option; struct t_config_section *new_section; + if (!script) + return NULL; + function_and_data_read = plugin_script_build_function_and_data ( function_read, data_read); function_and_data_write = plugin_script_build_function_and_data ( @@ -221,6 +230,9 @@ plugin_script_api_config_new_option (struct t_weechat_plugin *weechat_plugin, char *function_and_data_delete; struct t_config_option *new_option; + if (!script) + return NULL; + function_and_data_check_value = plugin_script_build_function_and_data ( function_check_value, data_check_value); function_and_data_change = plugin_script_build_function_and_data ( @@ -297,7 +309,7 @@ plugin_script_api_printf_date_tags (struct t_weechat_plugin *weechat_plugin, if (!vbuffer) return; - buf2 = (script->charset && script->charset[0]) ? + buf2 = (script && script->charset && script->charset[0]) ? weechat_iconv_to_internal (script->charset, vbuffer) : NULL; weechat_printf_date_tags (buffer, date, tags, "%s", (buf2) ? buf2 : vbuffer); @@ -323,7 +335,7 @@ plugin_script_api_printf_y (struct t_weechat_plugin *weechat_plugin, if (!vbuffer) return; - buf2 = (script->charset && script->charset[0]) ? + buf2 = (script && script->charset && script->charset[0]) ? weechat_iconv_to_internal (script->charset, vbuffer) : NULL; weechat_printf_y (buffer, y, "%s", (buf2) ? buf2 : vbuffer); if (buf2) @@ -347,7 +359,7 @@ plugin_script_api_log_printf (struct t_weechat_plugin *weechat_plugin, if (!vbuffer) return; - buf2 = (script->charset && script->charset[0]) ? + buf2 = (script && script->charset && script->charset[0]) ? weechat_iconv_to_internal (script->charset, vbuffer) : NULL; weechat_log_printf ("%s", (buf2) ? buf2 : vbuffer); if (buf2) @@ -379,6 +391,9 @@ plugin_script_api_hook_command (struct t_weechat_plugin *weechat_plugin, char *function_and_data; struct t_hook *new_hook; + if (!script) + return NULL; + function_and_data = plugin_script_build_function_and_data (function, data); new_hook = weechat_hook_command (command, description, args, @@ -418,6 +433,9 @@ plugin_script_api_hook_command_run (struct t_weechat_plugin *weechat_plugin, char *function_and_data; struct t_hook *new_hook; + if (!script) + return NULL; + function_and_data = plugin_script_build_function_and_data (function, data); new_hook = weechat_hook_command_run (command, @@ -455,6 +473,9 @@ plugin_script_api_hook_timer (struct t_weechat_plugin *weechat_plugin, char *function_and_data; struct t_hook *new_hook; + if (!script) + return NULL; + function_and_data = plugin_script_build_function_and_data (function, data); new_hook = weechat_hook_timer (interval, align_second, max_calls, @@ -493,6 +514,9 @@ plugin_script_api_hook_fd (struct t_weechat_plugin *weechat_plugin, char *function_and_data; struct t_hook *new_hook; + if (!script) + return NULL; + function_and_data = plugin_script_build_function_and_data (function, data); new_hook = weechat_hook_fd (fd, flag_read, flag_write, flag_exception, @@ -535,6 +559,9 @@ plugin_script_api_hook_process_hashtable (struct t_weechat_plugin *weechat_plugi char *function_and_data; struct t_hook *new_hook; + if (!script) + return NULL; + function_and_data = plugin_script_build_function_and_data (function, data); new_hook = weechat_hook_process_hashtable (command, options, timeout, @@ -607,6 +634,9 @@ plugin_script_api_hook_connect (struct t_weechat_plugin *weechat_plugin, char *function_and_data; struct t_hook *new_hook; + if (!script) + return NULL; + function_and_data = plugin_script_build_function_and_data (function, data); new_hook = weechat_hook_connect (proxy, address, port, ipv6, retry, @@ -654,6 +684,9 @@ plugin_script_api_hook_print (struct t_weechat_plugin *weechat_plugin, char *function_and_data; struct t_hook *new_hook; + if (!script) + return NULL; + function_and_data = plugin_script_build_function_and_data (function, data); new_hook = weechat_hook_print (buffer, tags, message, strip_colors, @@ -693,6 +726,9 @@ plugin_script_api_hook_signal (struct t_weechat_plugin *weechat_plugin, char *function_and_data; struct t_hook *new_hook; + if (!script) + return NULL; + function_and_data = plugin_script_build_function_and_data (function, data); new_hook = weechat_hook_signal (signal, callback, script, @@ -731,6 +767,9 @@ plugin_script_api_hook_hsignal (struct t_weechat_plugin *weechat_plugin, char *function_and_data; struct t_hook *new_hook; + if (!script) + return NULL; + function_and_data = plugin_script_build_function_and_data (function, data); new_hook = weechat_hook_hsignal (signal, callback, script, @@ -769,6 +808,9 @@ plugin_script_api_hook_config (struct t_weechat_plugin *weechat_plugin, char *function_and_data; struct t_hook *new_hook; + if (!script) + return NULL; + function_and_data = plugin_script_build_function_and_data (function, data); new_hook = weechat_hook_config (option, callback, script, @@ -809,6 +851,9 @@ plugin_script_api_hook_completion (struct t_weechat_plugin *weechat_plugin, char *function_and_data; struct t_hook *new_hook; + if (!script) + return NULL; + function_and_data = plugin_script_build_function_and_data (function, data); new_hook = weechat_hook_completion (completion, description, @@ -848,6 +893,9 @@ plugin_script_api_hook_modifier (struct t_weechat_plugin *weechat_plugin, char *function_and_data; struct t_hook *new_hook; + if (!script) + return NULL; + function_and_data = plugin_script_build_function_and_data (function, data); new_hook = weechat_hook_modifier (modifier, @@ -888,6 +936,9 @@ plugin_script_api_hook_info (struct t_weechat_plugin *weechat_plugin, char *function_and_data; struct t_hook *new_hook; + if (!script) + return NULL; + function_and_data = plugin_script_build_function_and_data (function, data); new_hook = weechat_hook_info (info_name, description, args_description, @@ -929,6 +980,9 @@ plugin_script_api_hook_info_hashtable (struct t_weechat_plugin *weechat_plugin, char *function_and_data; struct t_hook *new_hook; + if (!script) + return NULL; + function_and_data = plugin_script_build_function_and_data (function, data); new_hook = weechat_hook_info_hashtable (info_name, description, @@ -974,6 +1028,9 @@ plugin_script_api_hook_infolist (struct t_weechat_plugin *weechat_plugin, char *function_and_data; struct t_hook *new_hook; + if (!script) + return NULL; + function_and_data = plugin_script_build_function_and_data (function, data); new_hook = weechat_hook_infolist (infolist_name, description, @@ -1012,6 +1069,9 @@ plugin_script_api_hook_focus (struct t_weechat_plugin *weechat_plugin, char *function_and_data; struct t_hook *new_hook; + if (!script) + return NULL; + function_and_data = plugin_script_build_function_and_data (function, data); new_hook = weechat_hook_focus (area, callback, script, function_and_data); @@ -1052,6 +1112,9 @@ plugin_script_api_buffer_new (struct t_weechat_plugin *weechat_plugin, char *function_and_data_input, *function_and_data_close; struct t_gui_buffer *new_buffer; + if (!script) + return NULL; + function_and_data_input = plugin_script_build_function_and_data ( function_input, data_input); function_and_data_close = plugin_script_build_function_and_data ( @@ -1114,6 +1177,9 @@ plugin_script_api_bar_item_new (struct t_weechat_plugin *weechat_plugin, char str_function[1024], *function_and_data;; int new_callback; + if (!script) + return NULL; + new_callback = 0; if (strncmp (name, "(extra)", 7) == 0) { @@ -1153,7 +1219,7 @@ plugin_script_api_command (struct t_weechat_plugin *weechat_plugin, char *command2; int rc; - command2 = (script->charset && script->charset[0]) ? + command2 = (script && script->charset && script->charset[0]) ? weechat_iconv_to_internal (script->charset, command) : NULL; rc = weechat_command (buffer, (command2) ? command2 : command); @@ -1176,6 +1242,9 @@ plugin_script_api_config_get_plugin (struct t_weechat_plugin *weechat_plugin, char *option_fullname; const char *return_value; + if (!script) + return NULL; + option_fullname = malloc ((strlen (script->name) + strlen (option) + 2)); if (!option_fullname) @@ -1208,6 +1277,9 @@ plugin_script_api_config_is_set_plugin (struct t_weechat_plugin *weechat_plugin, char *option_fullname; int return_code; + if (!script) + return 0; + option_fullname = malloc ((strlen (script->name) + strlen (option) + 2)); if (!option_fullname) @@ -1236,6 +1308,9 @@ plugin_script_api_config_set_plugin (struct t_weechat_plugin *weechat_plugin, char *option_fullname; int return_code; + if (!script) + return 0; + option_fullname = malloc ((strlen (script->name) + strlen (option) + 2)); if (!option_fullname) @@ -1263,6 +1338,9 @@ plugin_script_api_config_set_desc_plugin (struct t_weechat_plugin *weechat_plugi { char *option_fullname; + if (!script) + return; + option_fullname = malloc ((strlen (script->name) + strlen (option) + 2)); if (!option_fullname) @@ -1289,6 +1367,9 @@ plugin_script_api_config_unset_plugin (struct t_weechat_plugin *weechat_plugin, char *option_fullname; int return_code; + if (!script) + return 0; + option_fullname = malloc ((strlen (script->name) + strlen (option) + 2)); if (!option_fullname) @@ -1328,6 +1409,9 @@ plugin_script_api_upgrade_new (struct t_weechat_plugin *weechat_plugin, char *function_and_data; struct t_upgrade_file *new_upgrade_file; + if (!script) + return NULL; + function_and_data = plugin_script_build_function_and_data (function, data); new_upgrade_file = weechat_upgrade_new ( diff --git a/src/plugins/plugin-script-api.h b/src/plugins/plugin-script-api.h index f49614d1c..58ef7edf6 100644 --- a/src/plugins/plugin-script-api.h +++ b/src/plugins/plugin-script-api.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2012 Simon Arlott * * This file is part of WeeChat, the extensible chat client. @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_PLUGIN_SCRIPT_API_H -#define WEECHAT_PLUGIN_SCRIPT_API_H 1 +#ifndef WEECHAT_PLUGIN_PLUGIN_SCRIPT_API_H +#define WEECHAT_PLUGIN_PLUGIN_SCRIPT_API_H #include <time.h> @@ -370,4 +370,4 @@ extern struct t_upgrade_file *plugin_script_api_upgrade_new (struct t_weechat_pl const char *function, const char *data); -#endif /* WEECHAT_PLUGIN_SCRIPT_API_H */ +#endif /* WEECHAT_PLUGIN_PLUGIN_SCRIPT_API_H */ diff --git a/src/plugins/plugin-script-config.c b/src/plugins/plugin-script-config.c new file mode 100644 index 000000000..8f8f97b48 --- /dev/null +++ b/src/plugins/plugin-script-config.c @@ -0,0 +1,83 @@ +/* + * plugin-script-config.c - configuration options, used by script plugins + * + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> + +#include "weechat-plugin.h" +#include "plugin-script.h" + + +/* + * Initializes script configuration. + * + * Returns: + * 1: OK + * 0: error + */ + +int +plugin_script_config_init (struct t_weechat_plugin *weechat_plugin, + struct t_plugin_script_data *plugin_data) +{ + struct t_config_section *ptr_section; + + *(plugin_data->config_file) = weechat_config_new (weechat_plugin->name, + NULL, NULL, NULL); + if (!(*plugin_data->config_file)) + return 0; + + /* look */ + ptr_section = weechat_config_new_section (*(plugin_data->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 (*(plugin_data->config_file)); + *(plugin_data->config_file) = NULL; + return 0; + } + + *(plugin_data->config_look_check_license) = weechat_config_new_option ( + *(plugin_data->config_file), ptr_section, + "check_license", "boolean", + N_("check the license of scripts when they are loaded: if the license " + "is different from the plugin license, a warning is displayed"), + NULL, 0, 0, "off", NULL, 0, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + *(plugin_data->config_look_eval_keep_context) = weechat_config_new_option ( + *(plugin_data->config_file), ptr_section, + "eval_keep_context", "boolean", + N_("keep context between two calls to the source code evaluation " + "(option \"eval\" of script command or info \"%s_eval\"); " + "a hidden script is used to eval script code; " + "if this option is disabled, this hidden script is unloaded after " + "each eval: this uses less memory, but is slower"), + NULL, 0, 0, "on", NULL, 0, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + return 1; +} diff --git a/src/plugins/plugin-script-config.h b/src/plugins/plugin-script-config.h new file mode 100644 index 000000000..59b4672cd --- /dev/null +++ b/src/plugins/plugin-script-config.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef WEECHAT_PLUGIN_PLUGIN_SCRIPT_CONFIG_H +#define WEECHAT_PLUGIN_PLUGIN_SCRIPT_CONFIG_H + +extern int plugin_script_config_init (struct t_weechat_plugin *plugin, + struct t_plugin_script_data *plugin_data); + +#endif /* WEECHAT_PLUGIN_PLUGIN_SCRIPT_CONFIG_H */ diff --git a/src/plugins/plugin-script.c b/src/plugins/plugin-script.c index 09202ccc7..ba1ad2a77 100644 --- a/src/plugins/plugin-script.c +++ b/src/plugins/plugin-script.c @@ -1,7 +1,7 @@ /* * plugin-script.c - common functions used by script plugins * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -33,57 +33,103 @@ #include "weechat-plugin.h" #include "plugin-script.h" - - -#define SCRIPT_OPTION_CHECK_LICENSE "check_license" - -int script_option_check_license = 0; +#include "plugin-script-config.h" /* - * Reads script configuration. + * Displays name and version of interpreter used. */ void -plugin_script_config_read (struct t_weechat_plugin *weechat_plugin) +plugin_script_display_interpreter (struct t_weechat_plugin *weechat_plugin, + int indent) { - const char *string; + const char *ptr_name, *ptr_version; - string = weechat_config_get_plugin (SCRIPT_OPTION_CHECK_LICENSE); - if (!string) + ptr_name = weechat_hashtable_get (weechat_plugin->variables, + "interpreter_name"); + ptr_version = weechat_hashtable_get (weechat_plugin->variables, + "interpreter_version"); + if (ptr_name) { - weechat_config_set_plugin (SCRIPT_OPTION_CHECK_LICENSE, "off"); - string = weechat_config_get_plugin (SCRIPT_OPTION_CHECK_LICENSE); + weechat_printf (NULL, + "%s%s: %s", + (indent) ? " " : "", + ptr_name, + (ptr_version && ptr_version[0]) ? ptr_version : "(?)"); } - if (string && (weechat_config_string_to_boolean (string) > 0)) - script_option_check_license = 1; - else - script_option_check_license = 0; } /* - * Callback for changes on configuration option. + * Callback for signal "debug_libs". */ int -plugin_script_config_cb (const void *pointer, void *data, - const char *option, const char *value) +plugin_script_signal_debug_libs_cb (const void *pointer, void *data, + const char *signal, + const char *type_data, + void *signal_data) { struct t_weechat_plugin *plugin; /* make C compiler happy */ (void) data; - (void) option; - (void) value; + (void) signal; + (void) type_data; + (void) signal_data; plugin = (struct t_weechat_plugin *)pointer; - plugin_script_config_read (plugin); + plugin_script_display_interpreter (plugin, 1); return WEECHAT_RC_OK; } /* + * Callback for info "xxx_interpreter". + */ + +const char * +plugin_script_info_interpreter_cb (const void *pointer, void *data, + const char *info_name, + const char *arguments) +{ + struct t_weechat_plugin *weechat_plugin; + + /* make C compiler happy */ + (void) data; + (void) info_name; + (void) arguments; + + weechat_plugin = (struct t_weechat_plugin *)pointer; + + return weechat_hashtable_get (weechat_plugin->variables, + "interpreter_name"); +} + +/* + * Callback for info "xxx_version". + */ + +const char * +plugin_script_info_version_cb (const void *pointer, void *data, + const char *info_name, + const char *arguments) +{ + struct t_weechat_plugin *weechat_plugin; + + /* make C compiler happy */ + (void) data; + (void) info_name; + (void) arguments; + + weechat_plugin = (struct t_weechat_plugin *)pointer; + + return weechat_hashtable_get (weechat_plugin->variables, + "interpreter_version"); +} + +/* * Creates directories for plugin in WeeChat home: * - ~/.weechat/XXX/ * - ~/.weechat/XXX/autoload/ @@ -119,54 +165,50 @@ plugin_script_create_dirs (struct t_weechat_plugin *weechat_plugin) void plugin_script_init (struct t_weechat_plugin *weechat_plugin, int argc, char *argv[], - struct t_plugin_script_init *init) + struct t_plugin_script_data *plugin_data) { - char *string, *completion, signal_name[128]; + char string[512], *completion; char *action_signals[] = { "install", "remove", "autoload", NULL }; - int length, i, auto_load_scripts; - - /* read script configuration */ - plugin_script_config_read (weechat_plugin); + int i, auto_load_scripts; - /* add hook for configuration option */ - length = strlen (weechat_plugin->name) + 64; - string = malloc (length); - if (string) + /* initialize static strings */ + plugin_data->index_static_string = 0; + for (i = 0; i < WEECHAT_SCRIPT_STATIC_STRINGS; i++) { - snprintf (string, length, "plugins.var.%s.%s", - weechat_plugin->name, SCRIPT_OPTION_CHECK_LICENSE); - weechat_hook_config (string, - &plugin_script_config_cb, weechat_plugin, NULL); - free (string); + plugin_data->static_string[i] = NULL; } + /* initialize script configuration file (file: "<language>.conf") */ + plugin_script_config_init (weechat_plugin, plugin_data); + + /* read configuration file */ + weechat_config_read (*plugin_data->config_file); + /* create directories in WeeChat home */ plugin_script_create_dirs (weechat_plugin); /* add command */ completion = NULL; - length = strlen (weechat_plugin->name) + 16; - string = malloc (length); - if (string) - { - snprintf (string, length, "%%(%s_script)", - weechat_plugin->name); - completion = weechat_string_replace ("list %s" - " || listfull %s" - " || load %(filename)" - " || autoload" - " || reload %s" - " || unload %s", - "%s", - string); - } + snprintf (string, sizeof (string), "%%(%s_script)", weechat_plugin->name); + completion = weechat_string_replace ("list %s" + " || listfull %s" + " || load %(filename)" + " || autoload" + " || reload %s" + " || unload %s" + " || eval" + " || version", + "%s", + string); weechat_hook_command ( weechat_plugin->name, N_("list/load/unload scripts"), N_("list|listfull [<name>]" " || load [-q] <filename>" " || autoload" - " || reload|unload [-q] [<name>]"), + " || reload|unload [-q] [<name>]" + " || eval [-o|-oc] <code>" + " || version"), N_(" list: list loaded scripts\n" "listfull: list loaded scripts (verbose)\n" " load: load a script\n" @@ -175,60 +217,75 @@ plugin_script_init (struct t_weechat_plugin *weechat_plugin, "then load all scripts in \"autoload\" directory)\n" " unload: unload a script (if no name given, unload all scripts)\n" "filename: script (file) to load\n" + " -q: quiet mode: do not display messages\n" " name: a script name (name used in call to \"register\" " "function)\n" - " -q: quiet mode: do not display messages\n" + " eval: evaluate source code and display result on current " + "buffer\n" + " -o: send evaluation result to the buffer without executing " + "commands\n" + " -oc: send evaluation result to the buffer and execute " + "commands\n" + " code: source code to evaluate\n" + " version: display the version of interpreter used\n" "\n" "Without argument, this command lists all loaded scripts."), completion, - init->callback_command, NULL, NULL); - if (string) - free (string); + plugin_data->callback_command, NULL, NULL); if (completion) free (completion); /* add completion, hdata and infolist */ - length = strlen (weechat_plugin->name) + 64; - string = malloc (length); - if (string) - { - snprintf (string, length, "%s_script", weechat_plugin->name); - weechat_hook_completion (string, N_("list of scripts"), - init->callback_completion, NULL, NULL); - weechat_hook_hdata (string, N_("list of scripts"), - init->callback_hdata, weechat_plugin, NULL); - weechat_hook_infolist (string, N_("list of scripts"), - N_("script pointer (optional)"), - N_("script name (wildcard \"*\" is allowed) " - "(optional)"), - init->callback_infolist, NULL, NULL); - free (string); - } + snprintf (string, sizeof (string), "%s_script", weechat_plugin->name); + weechat_hook_completion (string, N_("list of scripts"), + plugin_data->callback_completion, NULL, NULL); + weechat_hook_hdata (string, N_("list of scripts"), + plugin_data->callback_hdata, weechat_plugin, NULL); + weechat_hook_infolist (string, N_("list of scripts"), + N_("script pointer (optional)"), + N_("script name (wildcard \"*\" is allowed) " + "(optional)"), + plugin_data->callback_infolist, NULL, NULL); + snprintf (string, sizeof (string), "%s_eval", weechat_plugin->name); + weechat_hook_info (string, N_("evaluation of source code"), + N_("source code to execute"), + plugin_data->callback_info_eval, NULL, NULL); /* add signal for "debug_dump" */ weechat_hook_signal ("debug_dump", - init->callback_signal_debug_dump, NULL, NULL); + plugin_data->callback_signal_debug_dump, NULL, NULL); /* add signal for "debug_libs" */ weechat_hook_signal ("debug_libs", - init->callback_signal_debug_libs, NULL, NULL); + plugin_script_signal_debug_libs_cb, + weechat_plugin, NULL); /* add signals for script actions (install/remove/autoload) */ for (i = 0; action_signals[i]; i++) { - snprintf (signal_name, sizeof (signal_name), "%s_script_%s", - weechat_plugin->name, - action_signals[i]); - weechat_hook_signal (signal_name, - init->callback_signal_script_action, NULL, NULL); + snprintf (string, sizeof (string), + "%s_script_%s", weechat_plugin->name, action_signals[i]); + weechat_hook_signal ( + string, + plugin_data->callback_signal_script_action, NULL, NULL); } + /* add infos */ + snprintf (string, sizeof (string), "%s_interpreter", weechat_plugin->name); + weechat_hook_info (string, N_("name of the interpreter used"), NULL, + &plugin_script_info_interpreter_cb, + weechat_plugin, NULL); + snprintf (string, sizeof (string), "%s_version", weechat_plugin->name); + weechat_hook_info (string, N_("version of the interpreter used"), NULL, + &plugin_script_info_version_cb, + weechat_plugin, NULL); + /* parse arguments */ auto_load_scripts = 1; for (i = 0; i < argc; i++) { if ((strcmp (argv[i], "-s") == 0) - || (strcmp (argv[i], "--no-script") == 0)) + || (strcmp (argv[i], "--no-script") == 0)) { auto_load_scripts = 0; } @@ -237,7 +294,8 @@ plugin_script_init (struct t_weechat_plugin *weechat_plugin, /* autoload scripts */ if (auto_load_scripts) { - plugin_script_auto_load (weechat_plugin, init->callback_load_file); + plugin_script_auto_load (weechat_plugin, + plugin_data->callback_load_file); } } @@ -273,22 +331,24 @@ plugin_script_valid (struct t_plugin_script *scripts, * Converts a pointer to a string for usage in a script. * * Returns string with format "0x12345678". - * - * Note: result must be freed after use. */ -char * +const char * plugin_script_ptr2str (void *pointer) { - char pointer_str[128]; + static char str_pointer[32][32]; + static int index_pointer = 0; + + index_pointer = (index_pointer + 1) % 32; + str_pointer[index_pointer][0] = '\0'; if (!pointer) - return strdup (""); + return str_pointer[index_pointer]; - snprintf (pointer_str, sizeof (pointer_str), + snprintf (str_pointer[index_pointer], sizeof (str_pointer[index_pointer]), "0x%lx", (long unsigned int)pointer); - return strdup (pointer_str); + return str_pointer[index_pointer]; } /* @@ -335,6 +395,29 @@ invalid: } /* + * Gets a "static string": a string allocated that will be freed later + * (or when the plugin is unloaded). + * + * The "string" argument must have been allocated by free (or strdup, ...) + * and will be automatically freed later. + */ + +char * +plugin_script_get_static_string (struct t_plugin_script_data *plugin_data, + char *string) +{ + plugin_data->index_static_string = (plugin_data->index_static_string + 1) % + WEECHAT_SCRIPT_STATIC_STRINGS; + + if (plugin_data->static_string[plugin_data->index_static_string]) + free (plugin_data->static_string[plugin_data->index_static_string]); + + plugin_data->static_string[plugin_data->index_static_string] = string; + + return plugin_data->static_string[plugin_data->index_static_string]; +} + +/* * Builds concatenated function name and data (both are strings). * The result will be sent to callbacks. */ @@ -419,7 +502,7 @@ plugin_script_auto_load (struct t_weechat_plugin *weechat_plugin, snprintf (dir_name, dir_length, "%s/%s/autoload", dir_home, weechat_plugin->name); - weechat_exec_on_files (dir_name, 0, callback, NULL); + weechat_exec_on_files (dir_name, 0, 0, callback, NULL); free (dir_name); } @@ -448,7 +531,7 @@ plugin_script_search (struct t_weechat_plugin *weechat_plugin, } /* - * Searches for a script by full name (example: "iset.pl"). + * Searches for a script by full name (example: "go.py"). * * Returns pointer to script, NULL if not found. */ @@ -619,6 +702,41 @@ plugin_script_insert_sorted (struct t_weechat_plugin *weechat_plugin, } /* + * Allocates a new script. + * + * Returns pointer to new script, NULL if error. + */ + +struct t_plugin_script * +plugin_script_alloc (const char *filename, const char *name, + const char *author, const char *version, + const char *license, const char *description, + const char *shutdown_func, const char *charset) +{ + struct t_plugin_script *new_script; + + new_script = malloc (sizeof (*new_script)); + if (!new_script) + return NULL; + + new_script->filename = strdup (filename); + new_script->interpreter = NULL; + new_script->name = strdup (name); + new_script->author = strdup (author); + new_script->version = strdup (version); + new_script->license = strdup (license); + new_script->description = strdup (description); + new_script->shutdown_func = (shutdown_func) ? + strdup (shutdown_func) : NULL; + new_script->charset = (charset) ? strdup (charset) : NULL; + new_script->unloading = 0; + new_script->prev_script = NULL; + new_script->next_script = NULL; + + return new_script; +} + +/* * Adds a script to list of scripts. * * Returns pointer to new script, NULL if error. @@ -626,8 +744,7 @@ plugin_script_insert_sorted (struct t_weechat_plugin *weechat_plugin, struct t_plugin_script * plugin_script_add (struct t_weechat_plugin *weechat_plugin, - struct t_plugin_script **scripts, - struct t_plugin_script **last_script, + struct t_plugin_script_data *plugin_data, const char *filename, const char *name, const char *author, const char *version, const char *license, const char *description, const char *shutdown_func, @@ -644,7 +761,7 @@ plugin_script_add (struct t_weechat_plugin *weechat_plugin, return NULL; } - if (script_option_check_license + if (weechat_config_boolean (*(plugin_data->config_look_check_license)) && (weechat_strcmp_ignore_chars (weechat_plugin->license, license, "0123456789-.,/\\()[]{}", 0) != 0)) { @@ -655,32 +772,27 @@ plugin_script_add (struct t_weechat_plugin *weechat_plugin, license, name, weechat_plugin->license); } - new_script = malloc (sizeof (*new_script)); - if (new_script) + new_script = plugin_script_alloc (filename, name, author, version, license, + description, shutdown_func, charset); + if (!new_script) { - new_script->filename = strdup (filename); - new_script->interpreter = NULL; - new_script->name = strdup (name); - new_script->author = strdup (author); - new_script->version = strdup (version); - new_script->license = strdup (license); - new_script->description = strdup (description); - new_script->shutdown_func = (shutdown_func) ? - strdup (shutdown_func) : NULL; - new_script->charset = (charset) ? strdup (charset) : NULL; - new_script->unloading = 0; - - plugin_script_insert_sorted (weechat_plugin, scripts, last_script, - new_script); - - return new_script; + weechat_printf (NULL, + _("%s: error loading script \"%s\" " + "(not enough memory)"), + weechat_plugin->name, name); + return NULL; } - weechat_printf (NULL, - _("%s: error loading script \"%s\" (not enough memory)"), - weechat_plugin->name, name); + /* add script to the list (except the internal "eval" fake script) */ + if (strcmp (new_script->name, WEECHAT_SCRIPT_EVAL_NAME) != 0) + { + plugin_script_insert_sorted (weechat_plugin, + plugin_data->scripts, + plugin_data->last_script, + new_script); + } - return NULL; + return new_script; } /* @@ -910,27 +1022,12 @@ plugin_script_remove_configs (struct t_weechat_plugin *weechat_plugin, } /* - * Removes a script from list of scripts. + * Frees a script. */ void -plugin_script_remove (struct t_weechat_plugin *weechat_plugin, - struct t_plugin_script **scripts, - struct t_plugin_script **last_script, - struct t_plugin_script *script) +plugin_script_free (struct t_plugin_script *script) { - script->unloading = 1; - - plugin_script_close_buffers (weechat_plugin, script); - - plugin_script_remove_bar_items (weechat_plugin, script); - - plugin_script_remove_configs (weechat_plugin, script); - - /* remove all hooks created by this script */ - weechat_unhook_all (script->name); - - /* free data */ if (script->filename) free (script->filename); if (script->name) @@ -948,6 +1045,30 @@ plugin_script_remove (struct t_weechat_plugin *weechat_plugin, if (script->charset) free (script->charset); + free (script); +} + +/* + * Removes a script from list of scripts. + */ + +void +plugin_script_remove (struct t_weechat_plugin *weechat_plugin, + struct t_plugin_script **scripts, + struct t_plugin_script **last_script, + struct t_plugin_script *script) +{ + script->unloading = 1; + + plugin_script_close_buffers (weechat_plugin, script); + + plugin_script_remove_bar_items (weechat_plugin, script); + + plugin_script_remove_configs (weechat_plugin, script); + + /* remove all hooks created by this script */ + weechat_unhook_all (script->name); + /* remove script from list */ if (script->prev_script) (script->prev_script)->next_script = script->next_script; @@ -958,8 +1079,8 @@ plugin_script_remove (struct t_weechat_plugin *weechat_plugin, if (*last_script == script) *last_script = script->prev_script; - /* free script */ - free (script); + /* free data and script */ + plugin_script_free (script); } /* @@ -1101,7 +1222,8 @@ void plugin_script_action_install (struct t_weechat_plugin *weechat_plugin, struct t_plugin_script *scripts, void (*script_unload)(struct t_plugin_script *script), - int (*script_load)(const char *filename), + struct t_plugin_script *(*script_load)(const char *filename, + const char *code), int *quiet, char **list) { @@ -1214,7 +1336,7 @@ plugin_script_action_install (struct t_weechat_plugin *weechat_plugin, * - script was loaded */ if ((!existing_script && autoload) || script_loaded) - (*script_load) (new_path); + (*script_load) (new_path, NULL); } else { @@ -1648,20 +1770,32 @@ plugin_script_infolist_list_scripts (struct t_weechat_plugin *weechat_plugin, void plugin_script_end (struct t_weechat_plugin *weechat_plugin, - struct t_plugin_script **scripts, - void (*callback_unload_all)()) + struct t_plugin_script_data *plugin_data) { - int scripts_loaded; - - scripts_loaded = (*scripts) ? 1 : 0; - - (void)(callback_unload_all) (); + int scripts_loaded, i; + /* unload all scripts */ + scripts_loaded = (*(plugin_data->scripts)) ? 1 : 0; + (void)(plugin_data->unload_all) (); if (scripts_loaded) { weechat_printf (NULL, _("%s: scripts unloaded"), weechat_plugin->name); } + + /* write config file (file: "<language>.conf") */ + weechat_config_write (*(plugin_data->config_file)); + weechat_config_free (*(plugin_data->config_file)); + + /* free static strings */ + for (i = 0; i < WEECHAT_SCRIPT_STATIC_STRINGS; i++) + { + if (plugin_data->static_string[i]) + { + free (plugin_data->static_string[i]); + plugin_data->static_string[i] = NULL; + } + } } /* diff --git a/src/plugins/plugin-script.h b/src/plugins/plugin-script.h index 9202e5934..c797d9de8 100644 --- a/src/plugins/plugin-script.h +++ b/src/plugins/plugin-script.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_PLUGIN_SCRIPT_H -#define WEECHAT_PLUGIN_SCRIPT_H 1 +#ifndef WEECHAT_PLUGIN_PLUGIN_SCRIPT_H +#define WEECHAT_PLUGIN_PLUGIN_SCRIPT_H /* constants which defines return types for weechat_<lang>_exec functions */ @@ -26,11 +26,17 @@ enum t_weechat_script_exec_type { WEECHAT_SCRIPT_EXEC_INT = 0, WEECHAT_SCRIPT_EXEC_STRING, + WEECHAT_SCRIPT_EXEC_POINTER, WEECHAT_SCRIPT_EXEC_HASHTABLE, + WEECHAT_SCRIPT_EXEC_IGNORE, }; #define WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE 16 +#define WEECHAT_SCRIPT_STATIC_STRINGS 32 + +#define WEECHAT_SCRIPT_EVAL_NAME "__eval__" + #define WEECHAT_SCRIPT_MSG_NOT_INIT(__current_script, \ __function) \ weechat_printf (NULL, \ @@ -66,48 +72,65 @@ struct t_plugin_script struct t_plugin_script *next_script; /* link to next script */ }; -struct t_plugin_script_init +struct t_plugin_script_data { - int (*callback_command)(const void *pointer, void *data, - struct t_gui_buffer *buffer, - int argc, char **argv, char **argv_eol); - int (*callback_completion)(const void *pointer, void *data, - const char *completion_item, - struct t_gui_buffer *buffer, - struct t_gui_completion *completion); - struct t_hdata *(*callback_hdata)(const void *pointer, - void *data, - const char *hdata_name); - struct t_infolist *(*callback_infolist)(const void *pointer, - void *data, - const char *infolist_name, - void *obj_pointer, - const char *arguments); - int (*callback_signal_debug_dump)(const void *pointer, void *data, - const char *signal, - const char *type_data, - void *signal_data); - int (*callback_signal_debug_libs)(const void *pointer, void *data, - const char *signal, - const char *type_data, - void *signal_data); - int (*callback_signal_script_action)(const void *pointer, void *data, - const char *signal, - const char *type_data, - void *signal_data); - void (*callback_load_file)(void *data, const char *filename); + /* variables */ + struct t_config_file **config_file; + struct t_config_option **config_look_check_license; + struct t_config_option **config_look_eval_keep_context; + struct t_plugin_script **scripts; + struct t_plugin_script **last_script; + char *static_string[WEECHAT_SCRIPT_STATIC_STRINGS]; + int index_static_string; + + /* callbacks */ + int (*callback_command) (const void *pointer, void *data, + struct t_gui_buffer *buffer, + int argc, char **argv, char **argv_eol); + int (*callback_completion) (const void *pointer, void *data, + const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion); + struct t_hdata *(*callback_hdata) (const void *pointer, + void *data, + const char *hdata_name); + const char *(*callback_info_eval) (const void *pointer, + void *data, + const char *info_name, + const char *arguments); + struct t_infolist *(*callback_infolist) (const void *pointer, + void *data, + const char *infolist_name, + void *obj_pointer, + const char *arguments); + int (*callback_signal_debug_dump) (const void *pointer, void *data, + const char *signal, + const char *type_data, + void *signal_data); + int (*callback_signal_script_action) (const void *pointer, void *data, + const char *signal, + const char *type_data, + void *signal_data); + void (*callback_load_file) (void *data, const char *filename); + + /* functions */ + void (*unload_all) (); }; +extern void plugin_script_display_interpreter (struct t_weechat_plugin *plugin, + int indent); extern void plugin_script_init (struct t_weechat_plugin *weechat_plugin, int argc, char *argv[], - struct t_plugin_script_init *init); + struct t_plugin_script_data *plugin_data); extern int plugin_script_valid (struct t_plugin_script *scripts, struct t_plugin_script *script); -extern char *plugin_script_ptr2str (void *pointer); +extern const char *plugin_script_ptr2str (void *pointer); extern void *plugin_script_str2ptr (struct t_weechat_plugin *weechat_plugin, const char *script_name, const char *function_name, const char *pointer_str); +extern char *plugin_script_get_static_string (struct t_plugin_script_data *plugin_data, + char *string); extern char *plugin_script_build_function_and_data (const char *function, const char *data); extern void plugin_script_get_function_and_data (void *callback_data, @@ -121,13 +144,24 @@ extern struct t_plugin_script *plugin_script_search (struct t_weechat_plugin *we const char *name); extern char *plugin_script_search_path (struct t_weechat_plugin *weechat_plugin, const char *filename); +extern struct t_plugin_script *plugin_script_alloc (const char *filename, + const char *name, + const char *author, + const char *version, + const char *license, + const char *description, + const char *shutdown_func, + const char *charset); extern struct t_plugin_script *plugin_script_add (struct t_weechat_plugin *weechat_plugin, - struct t_plugin_script **scripts, - struct t_plugin_script **last_script, - const char *filename, const char *name, - const char *author, const char *version, - const char *license, const char *description, - const char *shutdown_func, const char *charset); + struct t_plugin_script_data *plugin_data, + const char *filename, + const char *name, + const char *author, + const char *version, + const char *license, + const char *description, + const char *shutdown_func, + const char *charset); extern void plugin_script_set_buffer_callbacks (struct t_weechat_plugin *weechat_plugin, struct t_plugin_script *scripts, struct t_plugin_script *script, @@ -138,6 +172,7 @@ extern void plugin_script_set_buffer_callbacks (struct t_weechat_plugin *weechat int (*callback_buffer_close) (const void *pointer, void *data, struct t_gui_buffer *buffer)); +extern void plugin_script_free (struct t_plugin_script *script); extern void plugin_script_remove (struct t_weechat_plugin *weechat_plugin, struct t_plugin_script **scripts, struct t_plugin_script **last_script, @@ -149,7 +184,8 @@ extern void plugin_script_action_add (char **action_list, const char *name); extern void plugin_script_action_install (struct t_weechat_plugin *weechat_plugin, struct t_plugin_script *scripts, void (*script_unload)(struct t_plugin_script *script), - int (*script_load)(const char *filename), + struct t_plugin_script *(*script_load)(const char *filename, + const char *code), int *quiet, char **list); extern void plugin_script_action_remove (struct t_weechat_plugin *weechat_plugin, @@ -177,9 +213,8 @@ extern struct t_infolist *plugin_script_infolist_list_scripts (struct t_weechat_ void *pointer, const char *arguments); extern void plugin_script_end (struct t_weechat_plugin *weechat_plugin, - struct t_plugin_script **scripts, - void (*callback_unload_all)()); + struct t_plugin_script_data *plugin_data); extern void plugin_script_print_log (struct t_weechat_plugin *weechat_plugin, struct t_plugin_script *scripts); -#endif /* WEECHAT_PLUGIN_SCRIPT_H */ +#endif /* WEECHAT_PLUGIN_PLUGIN_SCRIPT_H */ diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 1d4e104ee..0a49aa4e3 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -1,7 +1,7 @@ /* * plugin.c - WeeChat plugins management (load/unload dynamic C libraries) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -423,7 +423,7 @@ plugin_load (const char *filename, int init_plugin, int argc, char **argv) gui_chat_printf (NULL, _("%sError: unable to load plugin \"%s\": %s"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], - filename, dlerror()); + filename, dlerror ()); gui_chat_printf (NULL, _("%sIf you're trying to load a script and not a C " "plugin, try command to load scripts (/perl, " @@ -592,6 +592,10 @@ plugin_load (const char *filename, int init_plugin, int argc, char **argv) new_plugin->initialized = 0; ptr_option = config_weechat_debug_get (name); new_plugin->debug = (ptr_option) ? CONFIG_INTEGER(ptr_option) : 0; + new_plugin->variables = hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_STRING, + NULL, NULL); /* functions */ new_plugin->plugin_get_name = &plugin_get_name; @@ -746,7 +750,7 @@ plugin_load (const char *filename, int init_plugin, int argc, char **argv) new_plugin->config_write = &config_file_write; new_plugin->config_read = &config_file_read; new_plugin->config_reload = &config_file_reload; - new_plugin->config_option_free = &config_file_option_free; + new_plugin->config_option_free = &plugin_api_config_file_option_free; new_plugin->config_section_free_options = &config_file_section_free_options; new_plugin->config_section_free = &config_file_section_free; new_plugin->config_free = &config_file_free; @@ -993,9 +997,12 @@ plugin_arraylist_cmp_cb (void *data, */ void -plugin_auto_load (int argc, char **argv) +plugin_auto_load (int argc, char **argv, + int load_from_plugin_path, + int load_from_extra_lib_dir, + int load_from_lib_dir) { - char *dir_name, *plugin_path, *plugin_path2; + char *dir_name, *plugin_path, *plugin_path2, *extra_libdir; struct t_weechat_plugin *ptr_plugin; struct t_plugin_args plugin_args; struct t_arraylist *arraylist; @@ -1015,8 +1022,9 @@ plugin_auto_load (int argc, char **argv) &plugin_autoload_count); } - /* auto-load plugins in WeeChat home dir */ - if (CONFIG_STRING(config_plugin_path) + /* auto-load plugins in custom path */ + if (load_from_plugin_path + && CONFIG_STRING(config_plugin_path) && CONFIG_STRING(config_plugin_path)[0]) { plugin_path = string_expand_home (CONFIG_STRING(config_plugin_path)); @@ -1026,6 +1034,7 @@ plugin_auto_load (int argc, char **argv) util_exec_on_files ((plugin_path2) ? plugin_path2 : ((plugin_path) ? plugin_path : CONFIG_STRING(config_plugin_path)), + 1, 0, &plugin_auto_load_file, &plugin_args); if (plugin_path) @@ -1034,15 +1043,33 @@ plugin_auto_load (int argc, char **argv) free (plugin_path2); } + /* auto-load plugins in WEECHAT_EXTRA_LIBDIR environment variable */ + if (load_from_extra_lib_dir) + { + extra_libdir = getenv (WEECHAT_EXTRA_LIBDIR); + if (extra_libdir && extra_libdir[0]) + { + length = strlen (extra_libdir) + 16 + 1; + dir_name = malloc (length); + snprintf (dir_name, length, "%s/plugins", extra_libdir); + util_exec_on_files (dir_name, 1, 0, + &plugin_auto_load_file, &plugin_args); + free (dir_name); + } + } + /* auto-load plugins in WeeChat global lib dir */ - length = strlen (WEECHAT_LIBDIR) + 16 + 1; - dir_name = malloc (length); - if (dir_name) + if (load_from_lib_dir) { - snprintf (dir_name, length, "%s/plugins", WEECHAT_LIBDIR); - util_exec_on_files (dir_name, 0, - &plugin_auto_load_file, &plugin_args); - free (dir_name); + length = strlen (WEECHAT_LIBDIR) + 16 + 1; + dir_name = malloc (length); + if (dir_name) + { + snprintf (dir_name, length, "%s/plugins", WEECHAT_LIBDIR); + util_exec_on_files (dir_name, 1, 0, + &plugin_auto_load_file, &plugin_args); + free (dir_name); + } } /* free autoload array */ @@ -1152,6 +1179,7 @@ plugin_remove (struct t_weechat_plugin *plugin) free (plugin->license); if (plugin->charset) free (plugin->charset); + hashtable_free (plugin->variables); free (plugin); @@ -1332,7 +1360,7 @@ plugin_init (int auto_load, int argc, char *argv[]) if (auto_load) { plugin_quiet = 1; - plugin_auto_load (argc, argv); + plugin_auto_load (argc, argv, 1, 1, 1); plugin_display_short_list (); plugin_quiet = 0; } @@ -1384,6 +1412,7 @@ plugin_hdata_plugin_cb (const void *pointer, void *data, HDATA_VAR(struct t_weechat_plugin, priority, INTEGER, 0, NULL, NULL); HDATA_VAR(struct t_weechat_plugin, initialized, INTEGER, 0, NULL, NULL); HDATA_VAR(struct t_weechat_plugin, debug, INTEGER, 0, NULL, NULL); + HDATA_VAR(struct t_weechat_plugin, variables, HASHTABLE, 0, NULL, NULL); HDATA_VAR(struct t_weechat_plugin, prev_plugin, POINTER, 0, NULL, hdata_name); HDATA_VAR(struct t_weechat_plugin, next_plugin, POINTER, 0, NULL, hdata_name); HDATA_LIST(weechat_plugins, WEECHAT_HDATA_LIST_CHECK_POINTERS); @@ -1441,6 +1470,8 @@ plugin_add_to_infolist (struct t_infolist *infolist, return 0; if (!infolist_new_var_integer (ptr_item, "debug", plugin->debug)) return 0; + if (!hashtable_add_to_infolist (plugin->variables, ptr_item, "var")) + return 0; return 1; } @@ -1463,11 +1494,14 @@ plugin_print_log () log_printf (" handle . . . . . . . . : 0x%lx", ptr_plugin->handle); log_printf (" name . . . . . . . . . : '%s'", ptr_plugin->name); log_printf (" description. . . . . . : '%s'", ptr_plugin->description); + log_printf (" author . . . . . . . . : '%s'", ptr_plugin->author); log_printf (" version. . . . . . . . : '%s'", ptr_plugin->version); + log_printf (" license. . . . . . . . : '%s'", ptr_plugin->license); log_printf (" charset. . . . . . . . : '%s'", ptr_plugin->charset); log_printf (" priority . . . . . . . : %d", ptr_plugin->priority); log_printf (" initialized. . . . . . : %d", ptr_plugin->initialized); log_printf (" debug. . . . . . . . . : %d", ptr_plugin->debug); + hashtable_print_log (ptr_plugin->variables, "variables"); log_printf (" prev_plugin. . . . . . : 0x%lx", ptr_plugin->prev_plugin); log_printf (" next_plugin. . . . . . : 0x%lx", ptr_plugin->next_plugin); } diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h index 54df30aac..fa62cb4bb 100644 --- a/src/plugins/plugin.h +++ b/src/plugins/plugin.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_PLUGIN_H -#define WEECHAT_PLUGIN_H 1 +#ifndef WEECHAT_PLUGIN_PLUGIN_H +#define WEECHAT_PLUGIN_PLUGIN_H #include "weechat-plugin.h" @@ -39,7 +39,10 @@ extern const char *plugin_get_name (struct t_weechat_plugin *plugin); extern struct t_weechat_plugin *plugin_load (const char *filename, int init_plugin, int argc, char **argv); -extern void plugin_auto_load (int argc, char **argv); +extern void plugin_auto_load (int argc, char **argv, + int load_from_plugin_path, + int load_from_extra_lib_dir, + int load_from_lib_dir); extern void plugin_unload (struct t_weechat_plugin *plugin); extern void plugin_unload_name (const char *name); extern void plugin_unload_all (); @@ -53,4 +56,4 @@ extern int plugin_add_to_infolist (struct t_infolist *infolist, struct t_weechat_plugin *plugin); extern void plugin_print_log (); -#endif /* WEECHAT_PLUGIN_H */ +#endif /* WEECHAT_PLUGIN_PLUGIN_H */ diff --git a/src/plugins/python/CMakeLists.txt b/src/plugins/python/CMakeLists.txt index 3e263849c..3a0bd9f16 100644 --- a/src/plugins/python/CMakeLists.txt +++ b/src/plugins/python/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/python/Makefile.am b/src/plugins/python/Makefile.am index 005e650b4..dd6bccfa5 100644 --- a/src/plugins/python/Makefile.am +++ b/src/plugins/python/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/python/weechat-python-api.c b/src/plugins/python/weechat-python-api.c index 93e932a31..82399b494 100644 --- a/src/plugins/python/weechat-python-api.c +++ b/src/plugins/python/weechat-python-api.c @@ -1,7 +1,7 @@ /* * weechat-python-api.c - python API functions * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2007 Emmanuel Bouthenot <kolter@openics.org> * Copyright (C) 2012 Simon Arlott * @@ -59,6 +59,8 @@ plugin_script_str2ptr (weechat_python_plugin, \ PYTHON_CURRENT_SCRIPT_NAME, \ python_function_name, __string) +#define API_STATIC_STRING(__string) \ + plugin_script_get_static_string(&python_data, __string); #define API_RETURN_OK return PyLong_FromLong((long)1) #define API_RETURN_ERROR return PyLong_FromLong ((long)0) #define API_RETURN_EMPTY \ @@ -128,7 +130,7 @@ API_FUNC(register) /* register script */ python_current_script = plugin_script_add (weechat_python_plugin, - &python_scripts, &last_python_script, + &python_data, (python_current_script_filename) ? python_current_script_filename : "", name, author, version, license, @@ -333,6 +335,22 @@ API_FUNC(string_mask_to_regex) API_RETURN_STRING_FREE(result); } +API_FUNC(string_format_size) +{ + unsigned long long size; + char *result; + PyObject *return_value; + + API_INIT_FUNC(1, "string_format_size", API_RETURN_EMPTY); + size = 0; + if (!PyArg_ParseTuple (args, "K", &size)) + API_WRONG_ARGS(API_RETURN_EMPTY); + + result = weechat_string_format_size (size); + + API_RETURN_STRING_FREE(result); +} + API_FUNC(string_remove_color) { char *string, *replacement, *result; @@ -392,6 +410,7 @@ API_FUNC(string_eval_expression) options = NULL; if (!PyArg_ParseTuple (args, "sOOO", &expr, &dict, &dict2, &dict3)) API_WRONG_ARGS(API_RETURN_EMPTY); + pointers = weechat_python_dict_to_hashtable (dict, WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, WEECHAT_HASHTABLE_STRING, @@ -404,10 +423,8 @@ API_FUNC(string_eval_expression) WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_STRING); - result = weechat_string_eval_expression (expr, pointers, extra_vars, options); - if (pointers) weechat_hashtable_free (pointers); if (extra_vars) @@ -431,6 +448,7 @@ API_FUNC(string_eval_path_home) options = NULL; if (!PyArg_ParseTuple (args, "sOOO", &path, &dict, &dict2, &dict3)) API_WRONG_ARGS(API_RETURN_EMPTY); + pointers = weechat_python_dict_to_hashtable (dict, WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, WEECHAT_HASHTABLE_STRING, @@ -443,10 +461,8 @@ API_FUNC(string_eval_path_home) WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_STRING); - result = weechat_string_eval_path_home (path, pointers, extra_vars, options); - if (pointers) weechat_hashtable_free (pointers); if (extra_vars) @@ -510,8 +526,7 @@ API_FUNC(mkdir_parents) API_FUNC(list_new) { - char *result; - PyObject *return_value; + const char *result; /* make C compiler happy */ (void) args; @@ -520,13 +535,13 @@ API_FUNC(list_new) result = API_PTR2STR(weechat_list_new ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_add) { - char *weelist, *data, *where, *user_data, *result; - PyObject *return_value; + char *weelist, *data, *where, *user_data; + const char *result; API_INIT_FUNC(1, "list_add", API_RETURN_EMPTY); weelist = NULL; @@ -541,13 +556,13 @@ API_FUNC(list_add) where, API_STR2PTR(user_data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_search) { - char *weelist, *data, *result; - PyObject *return_value; + char *weelist, *data; + const char *result; API_INIT_FUNC(1, "list_search", API_RETURN_EMPTY); weelist = NULL; @@ -558,7 +573,7 @@ API_FUNC(list_search) result = API_PTR2STR(weechat_list_search (API_STR2PTR(weelist), data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_search_pos) @@ -579,8 +594,8 @@ API_FUNC(list_search_pos) API_FUNC(list_casesearch) { - char *weelist, *data, *result; - PyObject *return_value; + char *weelist, *data; + const char *result; API_INIT_FUNC(1, "list_casesearch", API_RETURN_EMPTY); weelist = NULL; @@ -591,7 +606,7 @@ API_FUNC(list_casesearch) result = API_PTR2STR(weechat_list_casesearch (API_STR2PTR(weelist), data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_casesearch_pos) @@ -612,9 +627,9 @@ API_FUNC(list_casesearch_pos) API_FUNC(list_get) { - char *weelist, *result; + char *weelist; + const char *result; int position; - PyObject *return_value; API_INIT_FUNC(1, "list_get", API_RETURN_EMPTY); weelist = NULL; @@ -624,7 +639,7 @@ API_FUNC(list_get) result = API_PTR2STR(weechat_list_get (API_STR2PTR(weelist), position)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_set) @@ -645,8 +660,8 @@ API_FUNC(list_set) API_FUNC(list_next) { - char *item, *result; - PyObject *return_value; + char *item; + const char *result; API_INIT_FUNC(1, "list_next", API_RETURN_EMPTY); item = NULL; @@ -655,13 +670,13 @@ API_FUNC(list_next) result = API_PTR2STR(weechat_list_next (API_STR2PTR(item))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_prev) { - char *item, *result; - PyObject *return_value; + char *item; + const char *result; API_INIT_FUNC(1, "list_prev", API_RETURN_EMPTY); item = NULL; @@ -670,7 +685,7 @@ API_FUNC(list_prev) result = API_PTR2STR(weechat_list_prev (API_STR2PTR(item))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_string) @@ -763,7 +778,7 @@ weechat_python_api_config_reload_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); rc = (int *) weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -777,8 +792,6 @@ weechat_python_api_config_reload_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -788,8 +801,8 @@ weechat_python_api_config_reload_cb (const void *pointer, void *data, API_FUNC(config_new) { - char *name, *function, *data, *result; - PyObject *return_value; + char *name, *function, *data; + const char *result; API_INIT_FUNC(1, "config_new", API_RETURN_EMPTY); name = NULL; @@ -805,7 +818,7 @@ API_FUNC(config_new) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -826,8 +839,8 @@ weechat_python_api_config_read_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); func_argv[3] = (option_name) ? (char *)option_name : empty_arg; func_argv[4] = (value) ? (char *)value : empty_arg; @@ -843,10 +856,6 @@ weechat_python_api_config_read_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); return ret; } @@ -871,7 +880,7 @@ weechat_python_api_config_section_write_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); func_argv[2] = (section_name) ? (char *)section_name : empty_arg; rc = (int *) weechat_python_exec (script, @@ -886,8 +895,6 @@ weechat_python_api_config_section_write_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -912,7 +919,7 @@ weechat_python_api_config_section_write_default_cb (const void *pointer, void *d if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); func_argv[2] = (section_name) ? (char *)section_name : empty_arg; rc = (int *) weechat_python_exec (script, @@ -927,8 +934,6 @@ weechat_python_api_config_section_write_default_cb (const void *pointer, void *d ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -955,8 +960,8 @@ weechat_python_api_config_section_create_option_cb (const void *pointer, void *d if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); func_argv[3] = (option_name) ? (char *)option_name : empty_arg; func_argv[4] = (value) ? (char *)value : empty_arg; @@ -972,10 +977,6 @@ weechat_python_api_config_section_create_option_cb (const void *pointer, void *d ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); return ret; } @@ -1001,9 +1002,9 @@ weechat_python_api_config_section_delete_option_cb (const void *pointer, void *d if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); - func_argv[3] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); + func_argv[3] = (char *)API_PTR2STR(option); rc = (int *) weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -1017,12 +1018,6 @@ weechat_python_api_config_section_delete_option_cb (const void *pointer, void *d ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -1035,9 +1030,9 @@ API_FUNC(config_new_section) char *config_file, *name, *function_read, *data_read, *function_write; char *data_write, *function_write_default, *data_write_default; char *function_create_option, *data_create_option, *function_delete_option; - char *data_delete_option, *result; + char *data_delete_option; + const char *result; int user_can_add_options, user_can_delete_options; - PyObject *return_value; API_INIT_FUNC(1, "config_new_section", API_RETURN_EMPTY); config_file = NULL; @@ -1087,13 +1082,13 @@ API_FUNC(config_new_section) function_delete_option, data_delete_option)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_search_section) { - char *config_file, *section_name, *result; - PyObject *return_value; + char *config_file, *section_name; + const char *result; API_INIT_FUNC(1, "config_search_section", API_RETURN_EMPTY); config_file = NULL; @@ -1104,7 +1099,7 @@ API_FUNC(config_search_section) result = API_PTR2STR(weechat_config_search_section (API_STR2PTR(config_file), section_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -1125,7 +1120,7 @@ weechat_python_api_config_option_check_value_cb (const void *pointer, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); func_argv[2] = (value) ? (char *)value : empty_arg; rc = (int *) weechat_python_exec (script, @@ -1140,8 +1135,6 @@ weechat_python_api_config_option_check_value_cb (const void *pointer, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -1165,16 +1158,13 @@ weechat_python_api_config_option_change_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); rc = (int *) weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, "ss", func_argv); - if (func_argv[1]) - free (func_argv[1]); - if (rc) free (rc); } @@ -1196,16 +1186,13 @@ weechat_python_api_config_option_delete_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); rc = (int *) weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, "ss", func_argv); - if (func_argv[1]) - free (func_argv[1]); - if (rc) free (rc); } @@ -1214,11 +1201,11 @@ weechat_python_api_config_option_delete_cb (const void *pointer, void *data, API_FUNC(config_new_option) { char *config_file, *section, *name, *type, *description, *string_values; - char *default_value, *value, *result; + char *default_value, *value; char *function_check_value, *data_check_value, *function_change; char *data_change, *function_delete, *data_delete; + const char *result; int min, max, null_value_allowed; - PyObject *return_value; API_INIT_FUNC(1, "config_new_option", API_RETURN_EMPTY); config_file = NULL; @@ -1266,13 +1253,13 @@ API_FUNC(config_new_option) function_delete, data_delete)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_search_option) { - char *config_file, *section, *option_name, *result; - PyObject *return_value; + char *config_file, *section, *option_name; + const char *result; API_INIT_FUNC(1, "config_search_option", API_RETURN_EMPTY); config_file = NULL; @@ -1285,7 +1272,7 @@ API_FUNC(config_search_option) API_STR2PTR(section), option_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_string_to_boolean) @@ -1675,8 +1662,8 @@ API_FUNC(config_free) API_FUNC(config_get) { - char *option, *result; - PyObject *return_value; + char *option; + const char *result; API_INIT_FUNC(1, "config_get", API_RETURN_EMPTY); option = NULL; @@ -1685,7 +1672,7 @@ API_FUNC(config_get) result = API_PTR2STR(weechat_config_get (option)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_get_plugin) @@ -1946,7 +1933,7 @@ weechat_python_api_hook_command_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (argc > 1) ? argv_eol[1] : empty_arg; rc = (int *) weechat_python_exec (script, @@ -1961,8 +1948,6 @@ weechat_python_api_hook_command_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -1973,8 +1958,8 @@ weechat_python_api_hook_command_cb (const void *pointer, void *data, API_FUNC(hook_command) { char *command, *description, *arguments, *args_description, *completion; - char *function, *data, *result; - PyObject *return_value; + char *function, *data; + const char *result; API_INIT_FUNC(1, "hook_command", API_RETURN_EMPTY); command = NULL; @@ -1999,7 +1984,7 @@ API_FUNC(hook_command) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2021,8 +2006,8 @@ weechat_python_api_hook_completion_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (completion_item) ? (char *)completion_item : empty_arg; - func_argv[2] = API_PTR2STR(buffer); - func_argv[3] = API_PTR2STR(completion); + func_argv[2] = (char *)API_PTR2STR(buffer); + func_argv[3] = (char *)API_PTR2STR(completion); rc = (int *) weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -2036,10 +2021,6 @@ weechat_python_api_hook_completion_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -2049,8 +2030,8 @@ weechat_python_api_hook_completion_cb (const void *pointer, void *data, API_FUNC(hook_completion) { - char *completion, *description, *function, *data, *result; - PyObject *return_value; + char *completion, *description, *function, *data; + const char *result; API_INIT_FUNC(1, "hook_completion", API_RETURN_EMPTY); completion = NULL; @@ -2069,7 +2050,7 @@ API_FUNC(hook_completion) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_completion_get_string) @@ -2128,7 +2109,7 @@ weechat_python_api_hook_command_run_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (command) ? (char *)command : empty_arg; rc = (int *) weechat_python_exec (script, @@ -2143,8 +2124,6 @@ weechat_python_api_hook_command_run_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -2154,8 +2133,8 @@ weechat_python_api_hook_command_run_cb (const void *pointer, void *data, API_FUNC(hook_command_run) { - char *command, *function, *data, *result; - PyObject *return_value; + char *command, *function, *data; + const char *result; API_INIT_FUNC(1, "hook_command_run", API_RETURN_EMPTY); command = NULL; @@ -2171,7 +2150,7 @@ API_FUNC(hook_command_run) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2217,8 +2196,8 @@ weechat_python_api_hook_timer_cb (const void *pointer, void *data, API_FUNC(hook_timer) { int interval, align_second, max_calls; - char *function, *data, *result; - PyObject *return_value; + char *function, *data; + const char *result; API_INIT_FUNC(1, "hook_timer", API_RETURN_EMPTY); interval = 10; @@ -2239,7 +2218,7 @@ API_FUNC(hook_timer) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2247,7 +2226,7 @@ weechat_python_api_hook_fd_cb (const void *pointer, void *data, int fd) { struct t_plugin_script *script; void *func_argv[2]; - char str_fd[32], empty_arg[1] = { '\0' }; + char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; int *rc, ret; @@ -2256,15 +2235,13 @@ weechat_python_api_hook_fd_cb (const void *pointer, void *data, int fd) if (ptr_function && ptr_function[0]) { - snprintf (str_fd, sizeof (str_fd), "%d", fd); - func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = str_fd; + func_argv[1] = PyLong_FromLong ((long)fd); rc = (int *) weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "ss", func_argv); + "sO", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2273,6 +2250,10 @@ weechat_python_api_hook_fd_cb (const void *pointer, void *data, int fd) ret = *rc; free (rc); } + if (func_argv[1]) + { + Py_XDECREF((PyObject *)func_argv[1]); + } return ret; } @@ -2283,8 +2264,8 @@ weechat_python_api_hook_fd_cb (const void *pointer, void *data, int fd) API_FUNC(hook_fd) { int fd, read, write, exception; - char *function, *data, *result; - PyObject *return_value; + char *function, *data; + const char *result; API_INIT_FUNC(1, "hook_fd", API_RETURN_EMPTY); fd = 0; @@ -2307,7 +2288,7 @@ API_FUNC(hook_fd) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2347,7 +2328,7 @@ weechat_python_api_hook_process_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (command) ? (char *)command : empty_arg; - func_argv[2] = PyLong_FromLong((long)return_code); + func_argv[2] = PyLong_FromLong ((long)return_code); func_argv[3] = (out) ? (char *)out : empty_arg; func_argv[4] = (err) ? (char *)err : empty_arg; @@ -2376,9 +2357,9 @@ weechat_python_api_hook_process_cb (const void *pointer, void *data, API_FUNC(hook_process) { - char *command, *function, *data, *result; + char *command, *function, *data; + const char *result; int timeout; - PyObject *return_value; API_INIT_FUNC(1, "hook_process", API_RETURN_EMPTY); command = NULL; @@ -2396,15 +2377,16 @@ API_FUNC(hook_process) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_process_hashtable) { - char *command, *function, *data, *result; + char *command, *function, *data; + const char *result; int timeout; struct t_hashtable *options; - PyObject *dict, *return_value; + PyObject *dict; API_INIT_FUNC(1, "hook_process_hashtable", API_RETURN_EMPTY); command = NULL; @@ -2416,11 +2398,11 @@ API_FUNC(hook_process_hashtable) if (!PyArg_ParseTuple (args, "sOiss", &command, &dict, &timeout, &function, &data)) API_WRONG_ARGS(API_RETURN_EMPTY); + options = weechat_python_dict_to_hashtable (dict, WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_STRING); - result = API_PTR2STR(plugin_script_api_hook_process_hashtable (weechat_python_plugin, python_current_script, command, @@ -2429,11 +2411,10 @@ API_FUNC(hook_process_hashtable) &weechat_python_api_hook_process_cb, function, data)); - if (options) weechat_hashtable_free (options); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2444,7 +2425,7 @@ weechat_python_api_hook_connect_cb (const void *pointer, void *data, { struct t_plugin_script *script; void *func_argv[6]; - char str_status[32], str_gnutls_rc[32], str_sock[32], empty_arg[1] = { '\0' }; + char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; int *rc, ret; @@ -2453,21 +2434,17 @@ weechat_python_api_hook_connect_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { - snprintf (str_status, sizeof (str_status), "%d", status); - snprintf (str_gnutls_rc, sizeof (str_gnutls_rc), "%d", gnutls_rc); - snprintf (str_sock, sizeof (str_sock), "%d", sock); - func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = str_status; - func_argv[2] = str_gnutls_rc; - func_argv[3] = str_sock; + func_argv[1] = PyLong_FromLong ((long)status); + func_argv[2] = PyLong_FromLong ((long)gnutls_rc); + func_argv[3] = PyLong_FromLong ((long)sock); func_argv[4] = (ip_address) ? (char *)ip_address : empty_arg; func_argv[5] = (error) ? (char *)error : empty_arg; rc = (int *) weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "ssssss", func_argv); + "sOOOss", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2476,6 +2453,18 @@ weechat_python_api_hook_connect_cb (const void *pointer, void *data, ret = *rc; free (rc); } + if (func_argv[1]) + { + Py_XDECREF((PyObject *)func_argv[1]); + } + if (func_argv[2]) + { + Py_XDECREF((PyObject *)func_argv[2]); + } + if (func_argv[3]) + { + Py_XDECREF((PyObject *)func_argv[3]); + } return ret; } @@ -2485,9 +2474,9 @@ weechat_python_api_hook_connect_cb (const void *pointer, void *data, API_FUNC(hook_connect) { - char *proxy, *address, *local_hostname, *function, *data, *result; + char *proxy, *address, *local_hostname, *function, *data; + const char *result; int port, ipv6, retry; - PyObject *return_value; API_INIT_FUNC(1, "hook_connect", API_RETURN_EMPTY); proxy = NULL; @@ -2518,7 +2507,7 @@ API_FUNC(hook_connect) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2544,16 +2533,16 @@ weechat_python_api_hook_print_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { - snprintf (timebuffer, sizeof (timebuffer), "%ld", (long int)date); + snprintf (timebuffer, sizeof (timebuffer), "%lld", (long long)date); func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = timebuffer; func_argv[3] = weechat_string_build_with_split_string (tags, ","); if (!func_argv[3]) func_argv[3] = strdup (""); - func_argv[4] = PyLong_FromLong((long)displayed); - func_argv[5] = PyLong_FromLong((long)highlight); + func_argv[4] = PyLong_FromLong ((long)displayed); + func_argv[5] = PyLong_FromLong ((long)highlight); func_argv[6] = (prefix) ? (char *)prefix : empty_arg; func_argv[7] = (message) ? (char *)message : empty_arg; @@ -2569,8 +2558,6 @@ weechat_python_api_hook_print_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); if (func_argv[3]) free (func_argv[3]); if (func_argv[4]) @@ -2590,9 +2577,9 @@ weechat_python_api_hook_print_cb (const void *pointer, void *data, API_FUNC(hook_print) { - char *buffer, *tags, *message, *function, *data, *result; + char *buffer, *tags, *message, *function, *data; + const char *result; int strip_colors; - PyObject *return_value; API_INIT_FUNC(1, "hook_print", API_RETURN_EMPTY); buffer = NULL; @@ -2615,7 +2602,7 @@ API_FUNC(hook_print) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2628,7 +2615,7 @@ weechat_python_api_hook_signal_cb (const void *pointer, void *data, char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; static char str_value[64]; - int *rc, ret, free_needed; + int *rc, ret; script = (struct t_plugin_script *)pointer; plugin_script_get_function_and_data (data, &ptr_function, &ptr_data); @@ -2637,7 +2624,6 @@ weechat_python_api_hook_signal_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (signal) ? (char *)signal : empty_arg; - free_needed = 0; if (strcmp (type_data, WEECHAT_HOOK_SIGNAL_STRING) == 0) { func_argv[2] = (signal_data) ? (char *)signal_data : empty_arg; @@ -2654,8 +2640,7 @@ weechat_python_api_hook_signal_cb (const void *pointer, void *data, } else if (strcmp (type_data, WEECHAT_HOOK_SIGNAL_POINTER) == 0) { - func_argv[2] = API_PTR2STR(signal_data); - free_needed = 1; + func_argv[2] = (char *)API_PTR2STR(signal_data); } else func_argv[2] = empty_arg; @@ -2672,8 +2657,6 @@ weechat_python_api_hook_signal_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (free_needed && func_argv[2]) - free (func_argv[2]); return ret; } @@ -2683,8 +2666,8 @@ weechat_python_api_hook_signal_cb (const void *pointer, void *data, API_FUNC(hook_signal) { - char *signal, *function, *data, *result; - PyObject *return_value; + char *signal, *function, *data; + const char *result; API_INIT_FUNC(1, "hook_signal", API_RETURN_EMPTY); signal = NULL; @@ -2700,7 +2683,7 @@ API_FUNC(hook_signal) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_signal_send) @@ -2785,8 +2768,8 @@ weechat_python_api_hook_hsignal_cb (const void *pointer, void *data, API_FUNC(hook_hsignal) { - char *signal, *function, *data, *result; - PyObject *return_value; + char *signal, *function, *data; + const char *result; API_INIT_FUNC(1, "hook_hsignal", API_RETURN_EMPTY); signal = NULL; @@ -2802,7 +2785,7 @@ API_FUNC(hook_hsignal) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_hsignal_send) @@ -2871,8 +2854,8 @@ weechat_python_api_hook_config_cb (const void *pointer, void *data, API_FUNC(hook_config) { - char *option, *function, *data, *result; - PyObject *return_value; + char *option, *function, *data; + const char *result; API_INIT_FUNC(1, "hook_config", API_RETURN_EMPTY); option = NULL; @@ -2888,7 +2871,7 @@ API_FUNC(hook_config) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } char * @@ -2923,8 +2906,8 @@ weechat_python_api_hook_modifier_cb (const void *pointer, void *data, API_FUNC(hook_modifier) { - char *modifier, *function, *data, *result; - PyObject *return_value; + char *modifier, *function, *data; + const char *result; API_INIT_FUNC(1, "hook_modifier", API_RETURN_EMPTY); modifier = NULL; @@ -2940,7 +2923,7 @@ API_FUNC(hook_modifier) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_modifier_exec) @@ -2967,7 +2950,7 @@ weechat_python_api_hook_info_cb (const void *pointer, void *data, { struct t_plugin_script *script; void *func_argv[3]; - char empty_arg[1] = { '\0' }; + char empty_arg[1] = { '\0' }, *result; const char *ptr_function, *ptr_data; script = (struct t_plugin_script *)pointer; @@ -2979,10 +2962,12 @@ weechat_python_api_hook_info_cb (const void *pointer, void *data, func_argv[1] = (info_name) ? (char *)info_name : empty_arg; func_argv[2] = (arguments) ? (char *)arguments : empty_arg; - return (const char *)weechat_python_exec (script, - WEECHAT_SCRIPT_EXEC_STRING, - ptr_function, - "sss", func_argv); + result = (char *)weechat_python_exec (script, + WEECHAT_SCRIPT_EXEC_STRING, + ptr_function, + "sss", func_argv); + + return API_STATIC_STRING(result); } return NULL; @@ -2990,8 +2975,8 @@ weechat_python_api_hook_info_cb (const void *pointer, void *data, API_FUNC(hook_info) { - char *info_name, *description, *args_description, *function, *data, *result; - PyObject *return_value; + char *info_name, *description, *args_description, *function, *data; + const char *result; API_INIT_FUNC(1, "hook_info", API_RETURN_EMPTY); info_name = NULL; @@ -3012,7 +2997,7 @@ API_FUNC(hook_info) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_hashtable * @@ -3054,8 +3039,8 @@ weechat_python_api_hook_info_hashtable_cb (const void *pointer, void *data, API_FUNC(hook_info_hashtable) { char *info_name, *description, *args_description, *output_description; - char *function, *data, *result; - PyObject *return_value; + char *function, *data; + const char *result; API_INIT_FUNC(1, "hook_info_hashtable", API_RETURN_EMPTY); info_name = NULL; @@ -3079,7 +3064,7 @@ API_FUNC(hook_info_hashtable) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_infolist * @@ -3100,18 +3085,15 @@ weechat_python_api_hook_infolist_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (infolist_name) ? (char *)infolist_name : empty_arg; - func_argv[2] = API_PTR2STR(obj_pointer); + func_argv[2] = (char *)API_PTR2STR(obj_pointer); func_argv[3] = (arguments) ? (char *)arguments : empty_arg; result = (struct t_infolist *)weechat_python_exec ( script, - WEECHAT_SCRIPT_EXEC_STRING, + WEECHAT_SCRIPT_EXEC_POINTER, ptr_function, "ssss", func_argv); - if (func_argv[2]) - free (func_argv[2]); - return result; } @@ -3121,8 +3103,8 @@ weechat_python_api_hook_infolist_cb (const void *pointer, void *data, API_FUNC(hook_infolist) { char *infolist_name, *description, *pointer_description, *args_description; - char *function, *data, *result; - PyObject *return_value; + char *function, *data; + const char *result; API_INIT_FUNC(1, "hook_infolist", API_RETURN_EMPTY); infolist_name = NULL; @@ -3146,7 +3128,7 @@ API_FUNC(hook_infolist) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_hashtable * @@ -3184,8 +3166,8 @@ weechat_python_api_hook_focus_cb (const void *pointer, void *data, API_FUNC(hook_focus) { - char *area, *function, *data, *result; - PyObject *return_value; + char *area, *function, *data; + const char *result; API_INIT_FUNC(1, "hook_focus", API_RETURN_EMPTY); area = NULL; @@ -3201,7 +3183,7 @@ API_FUNC(hook_focus) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_set) @@ -3265,7 +3247,7 @@ weechat_python_api_buffer_input_data_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (input_data) ? (char *)input_data : empty_arg; rc = (int *) weechat_python_exec (script, @@ -3279,8 +3261,6 @@ weechat_python_api_buffer_input_data_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -3304,7 +3284,7 @@ weechat_python_api_buffer_close_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); rc = (int *) weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -3317,8 +3297,6 @@ weechat_python_api_buffer_close_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -3329,8 +3307,7 @@ weechat_python_api_buffer_close_cb (const void *pointer, void *data, API_FUNC(buffer_new) { char *name, *function_input, *data_input, *function_close, *data_close; - char *result; - PyObject *return_value; + const char *result; API_INIT_FUNC(1, "buffer_new", API_RETURN_EMPTY); name = NULL; @@ -3352,14 +3329,13 @@ API_FUNC(buffer_new) function_close, data_close)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_search) { char *plugin, *name; - char *result; - PyObject *return_value; + const char *result; API_INIT_FUNC(1, "buffer_search", API_RETURN_EMPTY); plugin = NULL; @@ -3369,13 +3345,12 @@ API_FUNC(buffer_search) result = API_PTR2STR(weechat_buffer_search (plugin, name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_search_main) { - char *result; - PyObject *return_value; + const char *result; /* make C compiler happy */ (void) args; @@ -3384,13 +3359,12 @@ API_FUNC(buffer_search_main) result = API_PTR2STR(weechat_buffer_search_main ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(current_buffer) { - char *result; - PyObject *return_value; + const char *result; /* make C compiler happy */ (void) args; @@ -3399,7 +3373,7 @@ API_FUNC(current_buffer) result = API_PTR2STR(weechat_current_buffer ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_clear) @@ -3496,8 +3470,8 @@ API_FUNC(buffer_get_string) API_FUNC(buffer_get_pointer) { - char *buffer, *property, *result; - PyObject *return_value; + char *buffer, *property; + const char *result; API_INIT_FUNC(1, "buffer_get_pointer", API_RETURN_EMPTY); buffer = NULL; @@ -3508,7 +3482,7 @@ API_FUNC(buffer_get_pointer) result = API_PTR2STR(weechat_buffer_get_pointer (API_STR2PTR(buffer), property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_set) @@ -3563,8 +3537,7 @@ API_FUNC(buffer_match_list) API_FUNC(current_window) { - char *result; - PyObject *return_value; + const char *result; /* make C compiler happy */ (void) args; @@ -3573,13 +3546,13 @@ API_FUNC(current_window) result = API_PTR2STR(weechat_current_window ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(window_search_with_buffer) { - char *buffer, *result; - PyObject *return_value; + char *buffer; + const char *result; API_INIT_FUNC(1, "window_search_with_buffer", API_RETURN_EMPTY); buffer = NULL; @@ -3588,7 +3561,7 @@ API_FUNC(window_search_with_buffer) result = API_PTR2STR(weechat_window_search_with_buffer (API_STR2PTR(buffer))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(window_get_integer) @@ -3625,8 +3598,8 @@ API_FUNC(window_get_string) API_FUNC(window_get_pointer) { - char *window, *property, *result; - PyObject *return_value; + char *window, *property; + const char *result; API_INIT_FUNC(1, "window_get_pointer", API_RETURN_EMPTY); window = NULL; @@ -3637,7 +3610,7 @@ API_FUNC(window_get_pointer) result = API_PTR2STR(weechat_window_get_pointer (API_STR2PTR(window), property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(window_set_title) @@ -3656,9 +3629,9 @@ API_FUNC(window_set_title) API_FUNC(nicklist_add_group) { - char *buffer, *parent_group, *name, *color, *result; + char *buffer, *parent_group, *name, *color; + const char *result; int visible; - PyObject *return_value; API_INIT_FUNC(1, "nicklist_add_group", API_RETURN_EMPTY); buffer = NULL; @@ -3676,13 +3649,13 @@ API_FUNC(nicklist_add_group) color, visible)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_search_group) { - char *buffer, *from_group, *name, *result; - PyObject *return_value; + char *buffer, *from_group, *name; + const char *result; API_INIT_FUNC(1, "nicklist_search_group", API_RETURN_EMPTY); buffer = NULL; @@ -3695,14 +3668,14 @@ API_FUNC(nicklist_search_group) API_STR2PTR(from_group), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_add_nick) { - char *buffer, *group, *name, *color, *prefix, *prefix_color, *result; + char *buffer, *group, *name, *color, *prefix, *prefix_color; + const char *result; int visible; - PyObject *return_value; API_INIT_FUNC(1, "nicklist_add_nick", API_RETURN_EMPTY); buffer = NULL; @@ -3724,13 +3697,13 @@ API_FUNC(nicklist_add_nick) prefix_color, visible)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_search_nick) { - char *buffer, *from_group, *name, *result; - PyObject *return_value; + char *buffer, *from_group, *name; + const char *result; API_INIT_FUNC(1, "nicklist_search_nick", API_RETURN_EMPTY); buffer = NULL; @@ -3743,7 +3716,7 @@ API_FUNC(nicklist_search_nick) API_STR2PTR(from_group), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_remove_group) @@ -3832,8 +3805,8 @@ API_FUNC(nicklist_group_get_string) API_FUNC(nicklist_group_get_pointer) { - char *buffer, *group, *property, *result; - PyObject *return_value; + char *buffer, *group, *property; + const char *result; API_INIT_FUNC(1, "nicklist_group_get_pointer", API_RETURN_EMPTY); buffer = NULL; @@ -3846,7 +3819,7 @@ API_FUNC(nicklist_group_get_pointer) API_STR2PTR(group), property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_group_set) @@ -3909,8 +3882,8 @@ API_FUNC(nicklist_nick_get_string) API_FUNC(nicklist_nick_get_pointer) { - char *buffer, *nick, *property, *result; - PyObject *return_value; + char *buffer, *nick, *property; + const char *result; API_INIT_FUNC(1, "nicklist_nick_get_pointer", API_RETURN_EMPTY); buffer = NULL; @@ -3923,7 +3896,7 @@ API_FUNC(nicklist_nick_get_pointer) API_STR2PTR(nick), property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_nick_set) @@ -3948,8 +3921,8 @@ API_FUNC(nicklist_nick_set) API_FUNC(bar_item_search) { - char *name, *result; - PyObject *return_value; + char *name; + const char *result; API_INIT_FUNC(1, "bar_item_search", API_RETURN_EMPTY); name = NULL; @@ -3958,7 +3931,7 @@ API_FUNC(bar_item_search) result = API_PTR2STR(weechat_bar_item_search (name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } char * @@ -3982,9 +3955,9 @@ weechat_python_api_bar_item_build_cb (const void *pointer, void *data, { /* new callback: data, item, window, buffer, extra_info */ func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(item); - func_argv[2] = API_PTR2STR(window); - func_argv[3] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(item); + func_argv[2] = (char *)API_PTR2STR(window); + func_argv[3] = (char *)API_PTR2STR(buffer); func_argv[4] = weechat_python_hashtable_to_dict (extra_info); ret = (char *)weechat_python_exec (script, @@ -3992,12 +3965,6 @@ weechat_python_api_bar_item_build_cb (const void *pointer, void *data, ptr_function + 7, "ssssO", func_argv); - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); if (func_argv[4]) { Py_XDECREF((PyObject *)func_argv[4]); @@ -4007,18 +3974,13 @@ weechat_python_api_bar_item_build_cb (const void *pointer, void *data, { /* old callback: data, item, window */ func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(item); - func_argv[2] = API_PTR2STR(window); + func_argv[1] = (char *)API_PTR2STR(item); + func_argv[2] = (char *)API_PTR2STR(window); ret = (char *)weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_STRING, ptr_function, "sss", func_argv); - - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); } return ret; @@ -4029,8 +3991,8 @@ weechat_python_api_bar_item_build_cb (const void *pointer, void *data, API_FUNC(bar_item_new) { - char *name, *function, *data, *result; - PyObject *return_value; + char *name, *function, *data; + const char *result; API_INIT_FUNC(1, "bar_item_new", API_RETURN_EMPTY); name = NULL; @@ -4046,7 +4008,7 @@ API_FUNC(bar_item_new) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(bar_item_update) @@ -4079,8 +4041,8 @@ API_FUNC(bar_item_remove) API_FUNC(bar_search) { - char *name, *result; - PyObject *return_value; + char *name; + const char *result; API_INIT_FUNC(1, "bar_search", API_RETURN_EMPTY); name = NULL; @@ -4089,15 +4051,15 @@ API_FUNC(bar_search) result = API_PTR2STR(weechat_bar_search (name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(bar_new) { char *name, *hidden, *priority, *type, *conditions, *position; char *filling_top_bottom, *filling_left_right, *size, *size_max; - char *color_fg, *color_delim, *color_bg, *separator, *items, *result; - PyObject *return_value; + char *color_fg, *color_delim, *color_bg, *separator, *items; + const char *result; API_INIT_FUNC(1, "bar_new", API_RETURN_EMPTY); name = NULL; @@ -4137,7 +4099,7 @@ API_FUNC(bar_new) separator, items)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(bar_set) @@ -4231,6 +4193,7 @@ API_FUNC(info_get_hashtable) dict = NULL; if (!PyArg_ParseTuple (args, "sO", &info_name, &dict)) API_WRONG_ARGS(API_RETURN_EMPTY); + hashtable = weechat_python_dict_to_hashtable (dict, WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, WEECHAT_HASHTABLE_STRING, @@ -4249,8 +4212,7 @@ API_FUNC(info_get_hashtable) API_FUNC(infolist_new) { - char *result; - PyObject *return_value; + const char *result; /* make C compiler happy */ (void) args; @@ -4258,13 +4220,13 @@ API_FUNC(infolist_new) API_INIT_FUNC(1, "infolist_new", API_RETURN_EMPTY); result = API_PTR2STR(weechat_infolist_new ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_item) { - char *infolist, *result; - PyObject *return_value; + char *infolist; + const char *result; API_INIT_FUNC(1, "infolist_new_item", API_RETURN_EMPTY); infolist = NULL; @@ -4273,14 +4235,14 @@ API_FUNC(infolist_new_item) result = API_PTR2STR(weechat_infolist_new_item (API_STR2PTR(infolist))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_integer) { - char *item, *name, *result; + char *item, *name; + const char *result; int value; - PyObject *return_value; API_INIT_FUNC(1, "infolist_new_var_integer", API_RETURN_EMPTY); item = NULL; @@ -4293,13 +4255,13 @@ API_FUNC(infolist_new_var_integer) name, value)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_string) { - char *item, *name, *value, *result; - PyObject *return_value; + char *item, *name, *value; + const char *result; API_INIT_FUNC(1, "infolist_new_var_string", API_RETURN_EMPTY); item = NULL; @@ -4312,13 +4274,13 @@ API_FUNC(infolist_new_var_string) name, value)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_pointer) { - char *item, *name, *value, *result; - PyObject *return_value; + char *item, *name, *value; + const char *result; API_INIT_FUNC(1, "infolist_new_var_pointer", API_RETURN_EMPTY); item = NULL; @@ -4331,14 +4293,14 @@ API_FUNC(infolist_new_var_pointer) name, API_STR2PTR(value))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_time) { - char *item, *name, *result; + char *item, *name; + const char *result; int value; - PyObject *return_value; API_INIT_FUNC(1, "infolist_new_var_time", API_RETURN_EMPTY); item = NULL; @@ -4351,13 +4313,13 @@ API_FUNC(infolist_new_var_time) name, value)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_search_var) { - char *infolist, *name, *result; - PyObject *return_value; + char *infolist, *name; + const char *result; API_INIT_FUNC(1, "infolist_search_var", API_RETURN_EMPTY); infolist = NULL; @@ -4368,13 +4330,13 @@ API_FUNC(infolist_search_var) result = API_PTR2STR(weechat_infolist_search_var (API_STR2PTR(infolist), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_get) { - char *name, *pointer, *arguments, *result; - PyObject *return_value; + char *name, *pointer, *arguments; + const char *result; API_INIT_FUNC(1, "infolist_get", API_RETURN_EMPTY); name = NULL; @@ -4387,7 +4349,7 @@ API_FUNC(infolist_get) API_STR2PTR(pointer), arguments)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_next) @@ -4485,8 +4447,8 @@ API_FUNC(infolist_string) API_FUNC(infolist_pointer) { - char *infolist, *variable, *result; - PyObject *return_value; + char *infolist, *variable; + const char *result; API_INIT_FUNC(1, "infolist_pointer", API_RETURN_EMPTY); infolist = NULL; @@ -4497,31 +4459,23 @@ API_FUNC(infolist_pointer) result = API_PTR2STR(weechat_infolist_pointer (API_STR2PTR(infolist), variable)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_time) { - char *infolist, *variable, timebuffer[64], *result; + char *infolist, *variable; time_t time; - struct tm *date_tmp; - PyObject *return_value; - API_INIT_FUNC(1, "infolist_time", API_RETURN_EMPTY); + API_INIT_FUNC(1, "infolist_time", API_RETURN_LONG(0)); infolist = NULL; variable = NULL; if (!PyArg_ParseTuple (args, "ss", &infolist, &variable)) - API_WRONG_ARGS(API_RETURN_EMPTY); + API_WRONG_ARGS(API_RETURN_LONG(0)); - timebuffer[0] = '\0'; - time = weechat_infolist_time (API_STR2PTR(infolist), - variable); - date_tmp = localtime (&time); - if (date_tmp) - strftime (timebuffer, sizeof (timebuffer), "%F %T", date_tmp); - result = strdup (timebuffer); + time = weechat_infolist_time (API_STR2PTR(infolist), variable); - API_RETURN_STRING_FREE(result); + API_RETURN_LONG(time); } API_FUNC(infolist_free) @@ -4540,8 +4494,8 @@ API_FUNC(infolist_free) API_FUNC(hdata_get) { - char *name, *result; - PyObject *return_value; + char *name; + const char *result; API_INIT_FUNC(1, "hdata_get", API_RETURN_EMPTY); name = NULL; @@ -4550,7 +4504,7 @@ API_FUNC(hdata_get) result = API_PTR2STR(weechat_hdata_get (name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_get_var_offset) @@ -4641,8 +4595,8 @@ API_FUNC(hdata_get_var_hdata) API_FUNC(hdata_get_list) { - char *hdata, *name, *result; - PyObject *return_value; + char *hdata, *name; + const char *result; API_INIT_FUNC(1, "hdata_get_list", API_RETURN_EMPTY); hdata = NULL; @@ -4653,7 +4607,7 @@ API_FUNC(hdata_get_list) result = API_PTR2STR(weechat_hdata_get_list (API_STR2PTR(hdata), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_check_pointer) @@ -4677,9 +4631,9 @@ API_FUNC(hdata_check_pointer) API_FUNC(hdata_move) { - char *result, *hdata, *pointer; + char *hdata, *pointer; + const char *result; int count; - PyObject *return_value; API_INIT_FUNC(1, "hdata_move", API_RETURN_EMPTY); hdata = NULL; @@ -4692,14 +4646,14 @@ API_FUNC(hdata_move) API_STR2PTR(pointer), count)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_search) { - char *result, *hdata, *pointer, *search; + char *hdata, *pointer, *search; + const char *result; int move; - PyObject *return_value; API_INIT_FUNC(1, "hdata_search", API_RETURN_EMPTY); hdata = NULL; @@ -4714,7 +4668,7 @@ API_FUNC(hdata_search) search, move)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_char) @@ -4795,8 +4749,8 @@ API_FUNC(hdata_string) API_FUNC(hdata_pointer) { - char *hdata, *pointer, *name, *result; - PyObject *return_value; + char *hdata, *pointer, *name; + const char *result; API_INIT_FUNC(1, "hdata_pointer", API_RETURN_EMPTY); hdata = NULL; @@ -4809,7 +4763,7 @@ API_FUNC(hdata_pointer) API_STR2PTR(pointer), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_time) @@ -4939,9 +4893,9 @@ weechat_python_api_upgrade_read_cb (const void *pointer, void *data, snprintf (str_object_id, sizeof (str_object_id), "%d", object_id); func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(upgrade_file); + func_argv[1] = (char *)API_PTR2STR(upgrade_file); func_argv[2] = str_object_id; - func_argv[3] = API_PTR2STR(infolist); + func_argv[3] = (char *)API_PTR2STR(infolist); rc = (int *) weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -4955,10 +4909,6 @@ weechat_python_api_upgrade_read_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -4968,8 +4918,8 @@ weechat_python_api_upgrade_read_cb (const void *pointer, void *data, API_FUNC(upgrade_new) { - char *filename, *function, *data, *result; - PyObject *return_value; + char *filename, *function, *data; + const char *result; API_INIT_FUNC(1, "upgrade_new", API_RETURN_EMPTY); filename = NULL; @@ -4987,7 +4937,7 @@ API_FUNC(upgrade_new) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(upgrade_write_object) @@ -5056,6 +5006,7 @@ PyMethodDef weechat_python_funcs[] = API_DEF_FUNC(string_has_highlight), API_DEF_FUNC(string_has_highlight_regex), API_DEF_FUNC(string_mask_to_regex), + API_DEF_FUNC(string_format_size), API_DEF_FUNC(string_remove_color), API_DEF_FUNC(string_is_command_char), API_DEF_FUNC(string_input_for_buffer), diff --git a/src/plugins/python/weechat-python-api.h b/src/plugins/python/weechat-python-api.h index 86c1d198f..78c73c32f 100644 --- a/src/plugins/python/weechat-python-api.h +++ b/src/plugins/python/weechat-python-api.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2007 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_PYTHON_API_H -#define WEECHAT_PYTHON_API_H 1 +#ifndef WEECHAT_PLUGIN_PYTHON_API_H +#define WEECHAT_PLUGIN_PYTHON_API_H extern PyMethodDef weechat_python_funcs[]; @@ -31,4 +31,4 @@ extern int weechat_python_api_buffer_close_cb (const void *pointer, void *data, struct t_gui_buffer *buffer); -#endif /* WEECHAT_PYTHON_API_H */ +#endif /* WEECHAT_PLUGIN_PYTHON_API_H */ diff --git a/src/plugins/python/weechat-python.c b/src/plugins/python/weechat-python.c index 9cb63297f..bbb10e95f 100644 --- a/src/plugins/python/weechat-python.c +++ b/src/plugins/python/weechat-python.c @@ -1,7 +1,7 @@ /* * weechat-python.c - python plugin for WeeChat * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2007 Emmanuel Bouthenot <kolter@openics.org> * Copyright (C) 2012 Simon Arlott * @@ -24,6 +24,7 @@ #undef _ #include <Python.h> +#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> @@ -39,11 +40,33 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Support of python scripts")); WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(3000); +WEECHAT_PLUGIN_PRIORITY(4000); struct t_weechat_plugin *weechat_python_plugin = NULL; -int python_quiet; +struct t_plugin_script_data python_data; + +struct t_config_file *python_config_file = NULL; +struct t_config_option *python_config_look_check_license = NULL; +struct t_config_option *python_config_look_eval_keep_context = NULL; + +int python_quiet = 0; + +struct t_plugin_script *python_script_eval = NULL; +int python_eval_mode = 0; +int python_eval_send_input = 0; +int python_eval_exec_commands = 0; +struct t_gui_buffer *python_eval_buffer = NULL; +char *python_eval_output = NULL; +#define PYTHON_EVAL_SCRIPT \ + "import weechat\n" \ + "\n" \ + "def script_python_eval(code):\n" \ + " exec(code)\n" \ + "\n" \ + "weechat.register('" WEECHAT_SCRIPT_EVAL_NAME "', '', '1.0', " \ + "'" WEECHAT_LICENSE "', 'Evaluation of source code', '', '')\n" + struct t_plugin_script *python_scripts = NULL; struct t_plugin_script *last_python_script = NULL; struct t_plugin_script *python_current_script = NULL; @@ -52,6 +75,7 @@ const char *python_current_script_filename = NULL; PyThreadState *python_mainThreadState = NULL; PyThreadState *python_current_interpreter = NULL; char *python2_bin = NULL; +char **python_buffer_output = NULL; /* outputs subroutines */ static PyObject *weechat_python_output (PyObject *self, PyObject *args); @@ -110,8 +134,6 @@ char *python_action_remove_list = NULL; */ char *python_action_autoload_list = NULL; -char python_buffer_output[128]; - /* * Gets path to python 2.x interpreter. @@ -308,6 +330,105 @@ weechat_python_dict_to_hashtable (PyObject *dict, int size, } /* + * Flushes output. + */ + +void +weechat_python_output_flush () +{ + const char *ptr_command; + char *command; + int length; + + if (!*python_buffer_output[0]) + return; + + if (python_eval_mode) + { + /* if there's no buffer, we catch the output, so there's no flush */ + if (!python_eval_buffer) + return; + + if (python_eval_send_input) + { + if (python_eval_exec_commands) + ptr_command = *python_buffer_output; + else + ptr_command = weechat_string_input_for_buffer (*python_buffer_output); + if (ptr_command) + { + weechat_command (python_eval_buffer, *python_buffer_output); + } + else + { + length = 1 + strlen (*python_buffer_output) + 1; + command = malloc (length); + if (command) + { + snprintf (command, length, "%c%s", + *python_buffer_output[0], *python_buffer_output); + weechat_command (python_eval_buffer, + (command[0]) ? command : " "); + free (command); + } + } + } + else + { + weechat_printf (python_eval_buffer, "%s", *python_buffer_output); + } + } + else + { + /* script (no eval mode) */ + weechat_printf ( + NULL, + weechat_gettext ("%s: stdout/stderr (%s): %s"), + PYTHON_PLUGIN_NAME, + (python_current_script) ? python_current_script->name : "?", + *python_buffer_output); + } + + weechat_string_dyn_copy (python_buffer_output, NULL); +} + +/* + * Redirection for stdout and stderr. + */ + +static PyObject * +weechat_python_output (PyObject *self, PyObject *args) +{ + char *msg, *ptr_msg, *ptr_newline; + + /* make C compiler happy */ + (void) self; + + msg = NULL; + + if (!PyArg_ParseTuple (args, "s", &msg)) + { + weechat_python_output_flush (); + } + else + { + ptr_msg = msg; + while ((ptr_newline = strchr (ptr_msg, '\n')) != NULL) + { + ptr_newline[0] = '\0'; + weechat_string_dyn_concat (python_buffer_output, ptr_msg); + weechat_python_output_flush (); + ptr_newline[0] = '\n'; + ptr_msg = ++ptr_newline; + } + weechat_string_dyn_concat (python_buffer_output, ptr_msg); + } + + Py_INCREF(Py_None); + return Py_None; +} + +/* * Executes a python function. */ @@ -319,7 +440,7 @@ weechat_python_exec (struct t_plugin_script *script, struct t_plugin_script *old_python_current_script; PyThreadState *old_interpreter; PyObject *evMain, *evDict, *evFunc, *rc; - void *argv2[16], *ret_value; + void *argv2[16], *ret_value, *ret_temp; int i, argc, *ret_int; ret_value = NULL; @@ -370,6 +491,8 @@ weechat_python_exec (struct t_plugin_script *script, rc = PyObject_CallFunction (evFunc, NULL); } + weechat_python_output_flush (); + /* * ugly hack : rc = NULL while 'return weechat.WEECHAT_RC_OK .... * because of '#define WEECHAT_RC_OK 0' @@ -377,7 +500,7 @@ weechat_python_exec (struct t_plugin_script *script, if (rc == NULL) rc = PyLong_FromLong ((long)0); - if (PyErr_Occurred()) + if (PyErr_Occurred ()) { PyErr_Print (); Py_XDECREF(rc); @@ -395,6 +518,36 @@ weechat_python_exec (struct t_plugin_script *script, ret_value = NULL; Py_XDECREF(rc); } + else if ((ret_type == WEECHAT_SCRIPT_EXEC_POINTER) && (PyUnicode_Check (rc))) + { + ret_temp = weechat_python_unicode_to_string (rc); + if (ret_temp) + { + ret_value = plugin_script_str2ptr (weechat_python_plugin, + script->name, function, + ret_temp); + free (ret_temp); + } + else + { + ret_value = NULL; + } + Py_XDECREF(rc); + } + else if ((ret_type == WEECHAT_SCRIPT_EXEC_POINTER) && (PyBytes_Check (rc))) + { + if (PyBytes_AsString (rc)) + { + ret_value = plugin_script_str2ptr (weechat_python_plugin, + script->name, function, + PyBytes_AsString (rc)); + } + else + { + ret_value = NULL; + } + Py_XDECREF(rc); + } else if ((ret_type == WEECHAT_SCRIPT_EXEC_INT) && (PY_INTEGER_CHECK(rc))) { ret_int = malloc (sizeof (*ret_int)); @@ -413,17 +566,23 @@ weechat_python_exec (struct t_plugin_script *script, } else { - weechat_printf (NULL, - weechat_gettext ("%s%s: function \"%s\" must return " - "a valid value"), - weechat_prefix ("error"), PYTHON_PLUGIN_NAME, function); + if (ret_type != WEECHAT_SCRIPT_EXEC_IGNORE) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: function \"%s\" must " + "return a valid value"), + weechat_prefix ("error"), PYTHON_PLUGIN_NAME, + function); + } + Py_XDECREF(rc); } - if (!ret_value) + if ((ret_type != WEECHAT_SCRIPT_EXEC_IGNORE) && !ret_value) { weechat_printf (NULL, weechat_gettext ("%s%s: error in function \"%s\""), - weechat_prefix ("error"), PYTHON_PLUGIN_NAME, function); + weechat_prefix ("error"), PYTHON_PLUGIN_NAME, + function); } /* PyEval_ReleaseThread (python_current_script->interpreter); */ @@ -438,62 +597,6 @@ end: } /* - * Redirection for stdout and stderr. - */ - -static PyObject * -weechat_python_output (PyObject *self, PyObject *args) -{ - char *msg, *m, *p; - - /* make C compiler happy */ - (void) self; - - msg = NULL; - - if (!PyArg_ParseTuple (args, "s", &msg)) - { - if (strlen(python_buffer_output) > 0) - { - weechat_printf (NULL, - weechat_gettext ("%s: stdout/stderr: %s%s"), - PYTHON_PLUGIN_NAME, python_buffer_output, ""); - python_buffer_output[0] = '\0'; - } - } - else - { - m = msg; - while ((p = strchr (m, '\n')) != NULL) - { - *p = '\0'; - if (strlen (m) + strlen (python_buffer_output) > 0) - { - weechat_printf (NULL, - weechat_gettext ("%s: stdout/stderr: %s%s"), - PYTHON_PLUGIN_NAME, python_buffer_output, m); - } - *p = '\n'; - python_buffer_output[0] = '\0'; - m = ++p; - } - - if (strlen(m) + strlen(python_buffer_output) > sizeof(python_buffer_output)) - { - weechat_printf (NULL, - weechat_gettext ("%s: stdout/stderr: %s%s"), - PYTHON_PLUGIN_NAME, python_buffer_output, m); - python_buffer_output[0] = '\0'; - } - else - strcat (python_buffer_output, m); - } - - Py_INCREF(Py_None); - return Py_None; -} - -/* * Initializes the "weechat" module. */ @@ -527,53 +630,53 @@ void weechat_python_init_module_weechat () } /* define some constants */ - weechat_dict = PyModule_GetDict(weechat_module); - PyDict_SetItemString(weechat_dict, "WEECHAT_RC_OK", PyLong_FromLong((long) WEECHAT_RC_OK)); - PyDict_SetItemString(weechat_dict, "WEECHAT_RC_OK_EAT", PyLong_FromLong((long) WEECHAT_RC_OK_EAT)); - PyDict_SetItemString(weechat_dict, "WEECHAT_RC_ERROR", PyLong_FromLong((long) WEECHAT_RC_ERROR)); - - PyDict_SetItemString(weechat_dict, "WEECHAT_CONFIG_READ_OK", PyLong_FromLong((long) WEECHAT_CONFIG_READ_OK)); - PyDict_SetItemString(weechat_dict, "WEECHAT_CONFIG_READ_MEMORY_ERROR", PyLong_FromLong((long) WEECHAT_CONFIG_READ_MEMORY_ERROR)); - PyDict_SetItemString(weechat_dict, "WEECHAT_CONFIG_READ_FILE_NOT_FOUND", PyLong_FromLong((long) WEECHAT_CONFIG_READ_FILE_NOT_FOUND)); - PyDict_SetItemString(weechat_dict, "WEECHAT_CONFIG_WRITE_OK", PyLong_FromLong((long) WEECHAT_CONFIG_WRITE_OK)); - PyDict_SetItemString(weechat_dict, "WEECHAT_CONFIG_WRITE_ERROR", PyLong_FromLong((long) WEECHAT_CONFIG_WRITE_ERROR)); - PyDict_SetItemString(weechat_dict, "WEECHAT_CONFIG_WRITE_MEMORY_ERROR", PyLong_FromLong((long) WEECHAT_CONFIG_WRITE_MEMORY_ERROR)); - PyDict_SetItemString(weechat_dict, "WEECHAT_CONFIG_OPTION_SET_OK_CHANGED", PyLong_FromLong((long) WEECHAT_CONFIG_OPTION_SET_OK_CHANGED)); - PyDict_SetItemString(weechat_dict, "WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE", PyLong_FromLong((long) WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE)); - PyDict_SetItemString(weechat_dict, "WEECHAT_CONFIG_OPTION_SET_ERROR", PyLong_FromLong((long) WEECHAT_CONFIG_OPTION_SET_ERROR)); - PyDict_SetItemString(weechat_dict, "WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND", PyLong_FromLong((long) WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND)); - PyDict_SetItemString(weechat_dict, "WEECHAT_CONFIG_OPTION_UNSET_OK_NO_RESET", PyLong_FromLong((long) WEECHAT_CONFIG_OPTION_UNSET_OK_NO_RESET)); - PyDict_SetItemString(weechat_dict, "WEECHAT_CONFIG_OPTION_UNSET_OK_RESET", PyLong_FromLong((long) WEECHAT_CONFIG_OPTION_UNSET_OK_RESET)); - PyDict_SetItemString(weechat_dict, "WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED", PyLong_FromLong((long) WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED)); - PyDict_SetItemString(weechat_dict, "WEECHAT_CONFIG_OPTION_UNSET_ERROR", PyLong_FromLong((long) WEECHAT_CONFIG_OPTION_UNSET_ERROR)); - - PyDict_SetItemString(weechat_dict, "WEECHAT_LIST_POS_SORT", PyUnicode_FromString(WEECHAT_LIST_POS_SORT)); - PyDict_SetItemString(weechat_dict, "WEECHAT_LIST_POS_BEGINNING", PyUnicode_FromString(WEECHAT_LIST_POS_BEGINNING)); - PyDict_SetItemString(weechat_dict, "WEECHAT_LIST_POS_END", PyUnicode_FromString(WEECHAT_LIST_POS_END)); - - PyDict_SetItemString(weechat_dict, "WEECHAT_HOTLIST_LOW", PyUnicode_FromString(WEECHAT_HOTLIST_LOW)); - PyDict_SetItemString(weechat_dict, "WEECHAT_HOTLIST_MESSAGE", PyUnicode_FromString(WEECHAT_HOTLIST_MESSAGE)); - PyDict_SetItemString(weechat_dict, "WEECHAT_HOTLIST_PRIVATE", PyUnicode_FromString(WEECHAT_HOTLIST_PRIVATE)); - PyDict_SetItemString(weechat_dict, "WEECHAT_HOTLIST_HIGHLIGHT", PyUnicode_FromString(WEECHAT_HOTLIST_HIGHLIGHT)); - - PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_PROCESS_RUNNING", PyLong_FromLong((long) WEECHAT_HOOK_PROCESS_RUNNING)); - PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_PROCESS_ERROR", PyLong_FromLong((long) WEECHAT_HOOK_PROCESS_ERROR)); - - PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_CONNECT_OK", PyLong_FromLong((long) WEECHAT_HOOK_CONNECT_OK)); - PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND", PyLong_FromLong((long) WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND)); - PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND", PyLong_FromLong((long) WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND)); - PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED", PyLong_FromLong((long) WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED)); - PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_CONNECT_PROXY_ERROR", PyLong_FromLong((long) WEECHAT_HOOK_CONNECT_PROXY_ERROR)); - PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR", PyLong_FromLong((long) WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR)); - PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_CONNECT_GNUTLS_INIT_ERROR", PyLong_FromLong((long) WEECHAT_HOOK_CONNECT_GNUTLS_INIT_ERROR)); - PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR", PyLong_FromLong((long) WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR)); - PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_CONNECT_MEMORY_ERROR", PyLong_FromLong((long) WEECHAT_HOOK_CONNECT_MEMORY_ERROR)); - PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_CONNECT_TIMEOUT", PyLong_FromLong((long) WEECHAT_HOOK_CONNECT_TIMEOUT)); - PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_CONNECT_SOCKET_ERROR", PyLong_FromLong((long) WEECHAT_HOOK_CONNECT_SOCKET_ERROR)); - - PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_SIGNAL_STRING", PyUnicode_FromString(WEECHAT_HOOK_SIGNAL_STRING)); - PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_SIGNAL_INT", PyUnicode_FromString(WEECHAT_HOOK_SIGNAL_INT)); - PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_SIGNAL_POINTER", PyUnicode_FromString(WEECHAT_HOOK_SIGNAL_POINTER)); + weechat_dict = PyModule_GetDict (weechat_module); + PyDict_SetItemString (weechat_dict, "WEECHAT_RC_OK", PyLong_FromLong ((long)WEECHAT_RC_OK)); + PyDict_SetItemString (weechat_dict, "WEECHAT_RC_OK_EAT", PyLong_FromLong ((long)WEECHAT_RC_OK_EAT)); + PyDict_SetItemString (weechat_dict, "WEECHAT_RC_ERROR", PyLong_FromLong ((long)WEECHAT_RC_ERROR)); + + PyDict_SetItemString (weechat_dict, "WEECHAT_CONFIG_READ_OK", PyLong_FromLong ((long)WEECHAT_CONFIG_READ_OK)); + PyDict_SetItemString (weechat_dict, "WEECHAT_CONFIG_READ_MEMORY_ERROR", PyLong_FromLong ((long)WEECHAT_CONFIG_READ_MEMORY_ERROR)); + PyDict_SetItemString (weechat_dict, "WEECHAT_CONFIG_READ_FILE_NOT_FOUND", PyLong_FromLong ((long)WEECHAT_CONFIG_READ_FILE_NOT_FOUND)); + PyDict_SetItemString (weechat_dict, "WEECHAT_CONFIG_WRITE_OK", PyLong_FromLong ((long)WEECHAT_CONFIG_WRITE_OK)); + PyDict_SetItemString (weechat_dict, "WEECHAT_CONFIG_WRITE_ERROR", PyLong_FromLong ((long)WEECHAT_CONFIG_WRITE_ERROR)); + PyDict_SetItemString (weechat_dict, "WEECHAT_CONFIG_WRITE_MEMORY_ERROR", PyLong_FromLong ((long)WEECHAT_CONFIG_WRITE_MEMORY_ERROR)); + PyDict_SetItemString (weechat_dict, "WEECHAT_CONFIG_OPTION_SET_OK_CHANGED", PyLong_FromLong ((long)WEECHAT_CONFIG_OPTION_SET_OK_CHANGED)); + PyDict_SetItemString (weechat_dict, "WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE", PyLong_FromLong ((long)WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE)); + PyDict_SetItemString (weechat_dict, "WEECHAT_CONFIG_OPTION_SET_ERROR", PyLong_FromLong ((long)WEECHAT_CONFIG_OPTION_SET_ERROR)); + PyDict_SetItemString (weechat_dict, "WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND", PyLong_FromLong ((long)WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND)); + PyDict_SetItemString (weechat_dict, "WEECHAT_CONFIG_OPTION_UNSET_OK_NO_RESET", PyLong_FromLong ((long)WEECHAT_CONFIG_OPTION_UNSET_OK_NO_RESET)); + PyDict_SetItemString (weechat_dict, "WEECHAT_CONFIG_OPTION_UNSET_OK_RESET", PyLong_FromLong ((long)WEECHAT_CONFIG_OPTION_UNSET_OK_RESET)); + PyDict_SetItemString (weechat_dict, "WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED", PyLong_FromLong ((long)WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED)); + PyDict_SetItemString (weechat_dict, "WEECHAT_CONFIG_OPTION_UNSET_ERROR", PyLong_FromLong ((long)WEECHAT_CONFIG_OPTION_UNSET_ERROR)); + + PyDict_SetItemString (weechat_dict, "WEECHAT_LIST_POS_SORT", PyUnicode_FromString (WEECHAT_LIST_POS_SORT)); + PyDict_SetItemString (weechat_dict, "WEECHAT_LIST_POS_BEGINNING", PyUnicode_FromString (WEECHAT_LIST_POS_BEGINNING)); + PyDict_SetItemString (weechat_dict, "WEECHAT_LIST_POS_END", PyUnicode_FromString (WEECHAT_LIST_POS_END)); + + PyDict_SetItemString (weechat_dict, "WEECHAT_HOTLIST_LOW", PyUnicode_FromString (WEECHAT_HOTLIST_LOW)); + PyDict_SetItemString (weechat_dict, "WEECHAT_HOTLIST_MESSAGE", PyUnicode_FromString (WEECHAT_HOTLIST_MESSAGE)); + PyDict_SetItemString (weechat_dict, "WEECHAT_HOTLIST_PRIVATE", PyUnicode_FromString (WEECHAT_HOTLIST_PRIVATE)); + PyDict_SetItemString (weechat_dict, "WEECHAT_HOTLIST_HIGHLIGHT", PyUnicode_FromString (WEECHAT_HOTLIST_HIGHLIGHT)); + + PyDict_SetItemString (weechat_dict, "WEECHAT_HOOK_PROCESS_RUNNING", PyLong_FromLong ((long)WEECHAT_HOOK_PROCESS_RUNNING)); + PyDict_SetItemString (weechat_dict, "WEECHAT_HOOK_PROCESS_ERROR", PyLong_FromLong ((long)WEECHAT_HOOK_PROCESS_ERROR)); + + PyDict_SetItemString (weechat_dict, "WEECHAT_HOOK_CONNECT_OK", PyLong_FromLong ((long)WEECHAT_HOOK_CONNECT_OK)); + PyDict_SetItemString (weechat_dict, "WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND", PyLong_FromLong ((long)WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND)); + PyDict_SetItemString (weechat_dict, "WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND", PyLong_FromLong ((long)WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND)); + PyDict_SetItemString (weechat_dict, "WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED", PyLong_FromLong ((long)WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED)); + PyDict_SetItemString (weechat_dict, "WEECHAT_HOOK_CONNECT_PROXY_ERROR", PyLong_FromLong ((long)WEECHAT_HOOK_CONNECT_PROXY_ERROR)); + PyDict_SetItemString (weechat_dict, "WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR", PyLong_FromLong ((long)WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR)); + PyDict_SetItemString (weechat_dict, "WEECHAT_HOOK_CONNECT_GNUTLS_INIT_ERROR", PyLong_FromLong ((long)WEECHAT_HOOK_CONNECT_GNUTLS_INIT_ERROR)); + PyDict_SetItemString (weechat_dict, "WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR", PyLong_FromLong ((long)WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR)); + PyDict_SetItemString (weechat_dict, "WEECHAT_HOOK_CONNECT_MEMORY_ERROR", PyLong_FromLong ((long)WEECHAT_HOOK_CONNECT_MEMORY_ERROR)); + PyDict_SetItemString (weechat_dict, "WEECHAT_HOOK_CONNECT_TIMEOUT", PyLong_FromLong ((long)WEECHAT_HOOK_CONNECT_TIMEOUT)); + PyDict_SetItemString (weechat_dict, "WEECHAT_HOOK_CONNECT_SOCKET_ERROR", PyLong_FromLong ((long)WEECHAT_HOOK_CONNECT_SOCKET_ERROR)); + + PyDict_SetItemString (weechat_dict, "WEECHAT_HOOK_SIGNAL_STRING", PyUnicode_FromString (WEECHAT_HOOK_SIGNAL_STRING)); + PyDict_SetItemString (weechat_dict, "WEECHAT_HOOK_SIGNAL_INT", PyUnicode_FromString (WEECHAT_HOOK_SIGNAL_INT)); + PyDict_SetItemString (weechat_dict, "WEECHAT_HOOK_SIGNAL_POINTER", PyUnicode_FromString (WEECHAT_HOOK_SIGNAL_POINTER)); #if PY_MAJOR_VERSION >= 3 return weechat_module; @@ -581,32 +684,82 @@ void weechat_python_init_module_weechat () } /* + * Sets weechat output (to redirect stdout/stderr to WeeChat buffer). + */ + +void +weechat_python_set_output () +{ + PyObject *weechat_outputs; + +#if PY_MAJOR_VERSION >= 3 + /* python >= 3.x */ + weechat_outputs = PyModule_Create (&moduleDefOutputs); +#else + /* python <= 2.x */ + weechat_outputs = Py_InitModule ("weechatOutputs", + weechat_python_output_funcs); +#endif /* PY_MAJOR_VERSION >= 3 */ + + if (weechat_outputs) + { + if (PySys_SetObject ("stdout", weechat_outputs) == -1) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: unable to redirect stdout"), + weechat_prefix ("error"), PYTHON_PLUGIN_NAME); + } + if (PySys_SetObject ("stderr", weechat_outputs) == -1) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: unable to redirect stderr"), + weechat_prefix ("error"), PYTHON_PLUGIN_NAME); + } + } + else + { + weechat_printf (NULL, + weechat_gettext ("%s%s: unable to redirect stdout and " + "stderr"), + weechat_prefix ("error"), PYTHON_PLUGIN_NAME); + } +} + +/* * Loads a python script. * - * Returns: - * 1: OK - * 0: error + * If code is NULL, the content of filename is read and executed. + * If code is not NULL, it is executed (the file is not read). + * + * Returns pointer to new registered script, NULL if error. */ -int -weechat_python_load (const char *filename) +struct t_plugin_script * +weechat_python_load (const char *filename, const char *code) { char *argv[] = { "__weechat_plugin__" , NULL }; #if PY_MAJOR_VERSION >= 3 wchar_t *wargv[] = { NULL, NULL }; #endif /* PY_MAJOR_VERSION >= 3 */ FILE *fp; - PyObject *weechat_outputs, *python_path, *path; + PyObject *python_path, *path, *module_main, *globals, *rc; const char *weechat_home; char *str_home; int len; - if ((fp = fopen (filename, "r")) == NULL) + fp = NULL; + + if (!code) { - weechat_printf (NULL, - weechat_gettext ("%s%s: script \"%s\" not found"), - weechat_prefix ("error"), PYTHON_PLUGIN_NAME, filename); - return 0; + fp = fopen (filename, "r"); + if (!fp) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: script \"%s\" not found"), + weechat_prefix ("error"), PYTHON_PLUGIN_NAME, + filename); + return NULL; + } } if ((weechat_python_plugin->debug >= 2) || !python_quiet) @@ -632,13 +785,13 @@ weechat_python_load (const char *filename) free (wargv[0]); wargv[0] = NULL; } - PySys_SetArgv(1, wargv); + PySys_SetArgv (1, wargv); if (wargv[0]) free (wargv[0]); } #else /* python <= 2.x */ - PySys_SetArgv(1, argv); + PySys_SetArgv (1, argv); #endif /* PY_MAJOR_VERSION >= 3 */ if (!python_current_interpreter) @@ -647,9 +800,10 @@ weechat_python_load (const char *filename) weechat_gettext ("%s%s: unable to create new " "sub-interpreter"), weechat_prefix ("error"), PYTHON_PLUGIN_NAME); - fclose (fp); + if (fp) + fclose (fp); /* PyEval_ReleaseLock (); */ - return 0; + return NULL; } PyThreadState_Swap (python_current_interpreter); @@ -666,7 +820,7 @@ weechat_python_load (const char *filename) snprintf (str_home, len, "%s/python", weechat_home); #if PY_MAJOR_VERSION >= 3 /* python >= 3.x */ - path = PyUnicode_FromString(str_home); + path = PyUnicode_FromString (str_home); #else /* python <= 2.x */ path = PyBytes_FromString (str_home); @@ -680,70 +834,76 @@ weechat_python_load (const char *filename) } } -#if PY_MAJOR_VERSION >= 3 - /* python >= 3.x */ - weechat_outputs = PyModule_Create (&moduleDefOutputs); -#else - /* python <= 2.x */ - weechat_outputs = Py_InitModule("weechatOutputs", - weechat_python_output_funcs); -#endif /* PY_MAJOR_VERSION >= 3 */ + weechat_python_set_output (); - if (!weechat_outputs) - { - weechat_printf (NULL, - weechat_gettext ("%s%s: unable to redirect stdout and " - "stderr"), - weechat_prefix ("error"), PYTHON_PLUGIN_NAME); - } - else + python_current_script_filename = filename; + + if (code) { - if (PySys_SetObject("stdout", weechat_outputs) == -1) + /* execute code without reading file */ + module_main = PyImport_AddModule ("__main__"); + globals = PyModule_GetDict (module_main); + rc = PyRun_String (code, Py_file_input, globals, NULL); + if (PyErr_Occurred ()) { weechat_printf (NULL, - weechat_gettext ("%s%s: unable to redirect stdout"), + weechat_gettext ("%s%s: unable to execute source " + "code"), weechat_prefix ("error"), PYTHON_PLUGIN_NAME); + PyErr_Print (); + if (rc) + Py_XDECREF(rc); + + /* if script was registered, remove it from list */ + if (python_current_script) + { + plugin_script_remove (weechat_python_plugin, + &python_scripts, &last_python_script, + python_current_script); + python_current_script = NULL; + } + + Py_EndInterpreter (python_current_interpreter); + /* PyEval_ReleaseLock (); */ + + return NULL; } - if (PySys_SetObject("stderr", weechat_outputs) == -1) + if (rc) + Py_XDECREF(rc); + } + else + { + /* read and execute code from file */ + if (PyRun_SimpleFile (fp, filename) != 0) { weechat_printf (NULL, - weechat_gettext ("%s%s: unable to redirect stderr"), - weechat_prefix ("error"), PYTHON_PLUGIN_NAME); - } - } + weechat_gettext ("%s%s: unable to parse file \"%s\""), + weechat_prefix ("error"), PYTHON_PLUGIN_NAME, filename); + fclose (fp); - python_current_script_filename = filename; + if (PyErr_Occurred ()) + PyErr_Print (); - if (PyRun_SimpleFile (fp, filename) != 0) - { - weechat_printf (NULL, - weechat_gettext ("%s%s: unable to parse file \"%s\""), - weechat_prefix ("error"), PYTHON_PLUGIN_NAME, filename); - fclose (fp); + /* if script was registered, remove it from list */ + if (python_current_script) + { + plugin_script_remove (weechat_python_plugin, + &python_scripts, &last_python_script, + python_current_script); + python_current_script = NULL; + } - if (PyErr_Occurred ()) - PyErr_Print (); + Py_EndInterpreter (python_current_interpreter); + /* PyEval_ReleaseLock (); */ - /* if script was registered, remove it from list */ - if (python_current_script) - { - plugin_script_remove (weechat_python_plugin, - &python_scripts, &last_python_script, - python_current_script); - python_current_script = NULL; + return NULL; } - - Py_EndInterpreter (python_current_interpreter); - /* PyEval_ReleaseLock (); */ - - return 0; + fclose (fp); } if (PyErr_Occurred ()) PyErr_Print (); - fclose (fp); - if (!python_registered_script) { weechat_printf (NULL, @@ -756,7 +916,7 @@ weechat_python_load (const char *filename) Py_EndInterpreter (python_current_interpreter); /* PyEval_ReleaseLock (); */ - return 0; + return NULL; } python_current_script = python_registered_script; @@ -776,7 +936,7 @@ weechat_python_load (const char *filename) WEECHAT_HOOK_SIGNAL_STRING, python_current_script->filename); - return 1; + return python_current_script; } /* @@ -789,7 +949,7 @@ weechat_python_load_cb (void *data, const char *filename) /* make C compiler happy */ (void) data; - weechat_python_load (filename); + weechat_python_load (filename, NULL); } /* @@ -909,7 +1069,7 @@ weechat_python_reload_name (const char *name) weechat_gettext ("%s: script \"%s\" unloaded"), PYTHON_PLUGIN_NAME, name); } - weechat_python_load (filename); + weechat_python_load (filename, NULL); free (filename); } } @@ -922,6 +1082,64 @@ weechat_python_reload_name (const char *name) } /* + * Evaluates python source code. + * + * Returns: + * 1: OK + * 0: error + */ + +int +weechat_python_eval (struct t_gui_buffer *buffer, int send_to_buffer_as_input, + int exec_commands, const char *code) +{ + void *func_argv[1], *result; + + if (!python_script_eval) + { + python_quiet = 1; + python_script_eval = weechat_python_load (WEECHAT_SCRIPT_EVAL_NAME, + PYTHON_EVAL_SCRIPT); + python_quiet = 0; + if (!python_script_eval) + return 0; + } + + weechat_python_output_flush (); + + python_eval_mode = 1; + python_eval_send_input = send_to_buffer_as_input; + python_eval_exec_commands = exec_commands; + python_eval_buffer = buffer; + + func_argv[0] = (char *)code; + result = weechat_python_exec (python_script_eval, + WEECHAT_SCRIPT_EXEC_IGNORE, + "script_python_eval", + "s", func_argv); + /* result is ignored */ + if (result) + free (result); + + weechat_python_output_flush (); + + python_eval_mode = 0; + python_eval_send_input = 0; + python_eval_exec_commands = 0; + python_eval_buffer = NULL; + + if (!weechat_config_boolean (python_config_look_eval_keep_context)) + { + python_quiet = 1; + weechat_python_unload (python_script_eval); + python_quiet = 0; + python_script_eval = NULL; + } + + return 1; +} + +/* * Callback for command "/python". */ @@ -930,12 +1148,12 @@ weechat_python_command_cb (const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { - char *ptr_name, *path_script; + char *ptr_name, *ptr_code, *path_script; + int i, send_to_buffer_as_input, exec_commands; /* make C compiler happy */ (void) pointer; (void) data; - (void) buffer; if (argc == 1) { @@ -967,6 +1185,10 @@ weechat_python_command_cb (const void *pointer, void *data, { weechat_python_unload_all (); } + else if (weechat_strcasecmp (argv[1], "version") == 0) + { + plugin_script_display_interpreter (weechat_python_plugin, 0); + } else WEECHAT_COMMAND_ERROR; } @@ -1001,7 +1223,8 @@ weechat_python_command_cb (const void *pointer, void *data, /* load python script */ path_script = plugin_script_search_path (weechat_python_plugin, ptr_name); - weechat_python_load ((path_script) ? path_script : ptr_name); + weechat_python_load ((path_script) ? path_script : ptr_name, + NULL); if (path_script) free (path_script); } @@ -1017,6 +1240,39 @@ weechat_python_command_cb (const void *pointer, void *data, } python_quiet = 0; } + else if (weechat_strcasecmp (argv[1], "eval") == 0) + { + send_to_buffer_as_input = 0; + exec_commands = 0; + ptr_code = argv_eol[2]; + for (i = 2; i < argc; i++) + { + if (argv[i][0] == '-') + { + if (strcmp (argv[i], "-o") == 0) + { + if (i + 1 >= argc) + WEECHAT_COMMAND_ERROR; + send_to_buffer_as_input = 1; + exec_commands = 0; + ptr_code = argv_eol[i + 1]; + } + else if (strcmp (argv[i], "-oc") == 0) + { + if (i + 1 >= argc) + WEECHAT_COMMAND_ERROR; + send_to_buffer_as_input = 1; + exec_commands = 1; + ptr_code = argv_eol[i + 1]; + } + } + else + break; + } + if (!weechat_python_eval (buffer, send_to_buffer_as_input, + exec_commands, ptr_code)) + WEECHAT_COMMAND_ERROR; + } else WEECHAT_COMMAND_ERROR; } @@ -1046,13 +1302,30 @@ weechat_python_completion_cb (const void *pointer, void *data, } /* - * Returns python info. + * Returns hdata for python scripts. + */ + +struct t_hdata * +weechat_python_hdata_cb (const void *pointer, void *data, + const char *hdata_name) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + + return plugin_script_hdata_script (weechat_plugin, + &python_scripts, &last_python_script, + hdata_name); +} + +/* + * Returns python info "python2_bin". */ const char * -weechat_python_info_cb (const void *pointer, void *data, - const char *info_name, - const char *arguments) +weechat_python_info_python2_bin_cb (const void *pointer, void *data, + const char *info_name, + const char *arguments) { int rc; struct stat stat_buf; @@ -1060,40 +1333,42 @@ weechat_python_info_cb (const void *pointer, void *data, /* make C compiler happy */ (void) pointer; (void) data; + (void) info_name; (void) arguments; - if (weechat_strcasecmp (info_name, "python2_bin") == 0) + if (python2_bin && (strcmp (python2_bin, "python") != 0)) { - if (python2_bin && (strcmp (python2_bin, "python") != 0)) + rc = stat (python2_bin, &stat_buf); + if ((rc != 0) || (!S_ISREG(stat_buf.st_mode))) { - rc = stat (python2_bin, &stat_buf); - if ((rc != 0) || (!S_ISREG(stat_buf.st_mode))) - { - free (python2_bin); - python2_bin = weechat_python_get_python2_bin (); - } + free (python2_bin); + python2_bin = weechat_python_get_python2_bin (); } - return python2_bin; } - - return NULL; + return python2_bin; } /* - * Returns hdata for python scripts. + * Returns python info "python_eval". */ -struct t_hdata * -weechat_python_hdata_cb (const void *pointer, void *data, - const char *hdata_name) +const char * +weechat_python_info_eval_cb (const void *pointer, void *data, + const char *info_name, + const char *arguments) { /* make C compiler happy */ (void) pointer; (void) data; + (void) info_name; - return plugin_script_hdata_script (weechat_plugin, - &python_scripts, &last_python_script, - hdata_name); + weechat_python_eval (NULL, 0, 0, (arguments) ? arguments : ""); + if (python_eval_output) + free (python_eval_output); + python_eval_output = strdup (*python_buffer_output); + weechat_string_dyn_copy (python_buffer_output, NULL); + + return python_eval_output; } /* @@ -1148,31 +1423,6 @@ weechat_python_signal_debug_dump_cb (const void *pointer, void *data, } /* - * Display infos about external libraries used. - */ - -int -weechat_python_signal_debug_libs_cb (const void *pointer, void *data, - const char *signal, - const char *type_data, void *signal_data) -{ - /* make C compiler happy */ - (void) pointer; - (void) data; - (void) signal; - (void) type_data; - (void) signal_data; - -#ifdef PY_VERSION - weechat_printf (NULL, " %s: %s", PYTHON_PLUGIN_NAME, PY_VERSION); -#else - weechat_printf (NULL, " %s: (?)", PYTHON_PLUGIN_NAME); -#endif /* PY_VERSION */ - - return WEECHAT_RC_OK; -} - -/* * Timer for executing actions. */ @@ -1267,10 +1517,24 @@ weechat_python_signal_script_action_cb (const void *pointer, void *data, int weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) { - struct t_plugin_script_init init; - weechat_python_plugin = plugin; + /* set interpreter name and version */ + weechat_hashtable_set (plugin->variables, "interpreter_name", + plugin->name); +#ifdef PY_VERSION + weechat_hashtable_set (plugin->variables, "interpreter_version", + PY_VERSION); +#else + weechat_hashtable_set (plugin->variables, "interpreter_version", + ""); +#endif /* PY_VERSION */ + + /* init stdout/stderr buffer */ + python_buffer_output = weechat_string_dyn_alloc (256); + if (!python_buffer_output) + return WEECHAT_RC_ERROR; + /* * hook info to get path to python 2.x interpreter * (some scripts using hook_process need that) @@ -1279,13 +1543,10 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) weechat_hook_info ("python2_bin", N_("path to python 2.x interpreter"), NULL, - &weechat_python_info_cb, NULL, NULL); + &weechat_python_info_python2_bin_cb, NULL, NULL); - /* init stdout/stderr buffer */ - python_buffer_output[0] = '\0'; - - PyImport_AppendInittab("weechat", - &weechat_python_init_module_weechat); + PyImport_AppendInittab ("weechat", + &weechat_python_init_module_weechat); Py_Initialize (); if (Py_IsInitialized () == 0) @@ -1294,6 +1555,7 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) weechat_gettext ("%s%s: unable to launch global " "interpreter"), weechat_prefix ("error"), PYTHON_PLUGIN_NAME); + weechat_string_dyn_free (python_buffer_output, 1); return WEECHAT_RC_ERROR; } @@ -1308,20 +1570,27 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) weechat_gettext ("%s%s: unable to get current " "interpreter state"), weechat_prefix ("error"), PYTHON_PLUGIN_NAME); + weechat_string_dyn_free (python_buffer_output, 1); return WEECHAT_RC_ERROR; } - init.callback_command = &weechat_python_command_cb; - init.callback_completion = &weechat_python_completion_cb; - init.callback_hdata = &weechat_python_hdata_cb; - init.callback_infolist = &weechat_python_infolist_cb; - init.callback_signal_debug_dump = &weechat_python_signal_debug_dump_cb; - init.callback_signal_debug_libs = &weechat_python_signal_debug_libs_cb; - init.callback_signal_script_action = &weechat_python_signal_script_action_cb; - init.callback_load_file = &weechat_python_load_cb; + python_data.config_file = &python_config_file; + python_data.config_look_check_license = &python_config_look_check_license; + python_data.config_look_eval_keep_context = &python_config_look_eval_keep_context; + python_data.scripts = &python_scripts; + python_data.last_script = &last_python_script; + python_data.callback_command = &weechat_python_command_cb; + python_data.callback_completion = &weechat_python_completion_cb; + python_data.callback_hdata = &weechat_python_hdata_cb; + python_data.callback_info_eval = &weechat_python_info_eval_cb; + python_data.callback_infolist = &weechat_python_infolist_cb; + python_data.callback_signal_debug_dump = &weechat_python_signal_debug_dump_cb; + python_data.callback_signal_script_action = &weechat_python_signal_script_action_cb; + python_data.callback_load_file = &weechat_python_load_cb; + python_data.unload_all = &weechat_python_unload_all; python_quiet = 1; - plugin_script_init (weechat_python_plugin, argc, argv, &init); + plugin_script_init (weechat_python_plugin, argc, argv, &python_data); python_quiet = 0; plugin_script_display_short_list (weechat_python_plugin, @@ -1340,7 +1609,12 @@ weechat_plugin_end (struct t_weechat_plugin *plugin) { /* unload all scripts */ python_quiet = 1; - plugin_script_end (plugin, &python_scripts, &weechat_python_unload_all); + if (python_script_eval) + { + weechat_python_unload (python_script_eval); + python_script_eval = NULL; + } + plugin_script_end (plugin, &python_data); python_quiet = 0; /* free python interpreter */ @@ -1369,6 +1643,9 @@ weechat_plugin_end (struct t_weechat_plugin *plugin) free (python_action_remove_list); if (python_action_autoload_list) free (python_action_autoload_list); + weechat_string_dyn_free (python_buffer_output, 1); + if (python_eval_output) + free (python_eval_output); return WEECHAT_RC_OK; } diff --git a/src/plugins/python/weechat-python.h b/src/plugins/python/weechat-python.h index 29907c06f..af6a27984 100644 --- a/src/plugins/python/weechat-python.h +++ b/src/plugins/python/weechat-python.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2007 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_PYTHON_H -#define WEECHAT_PYTHON_H 1 +#ifndef WEECHAT_PLUGIN_PYTHON_H +#define WEECHAT_PLUGIN_PYTHON_H #define weechat_plugin weechat_python_plugin #define PYTHON_PLUGIN_NAME "python" @@ -44,6 +44,8 @@ extern struct t_weechat_plugin *weechat_python_plugin; +extern struct t_plugin_script_data python_data; + extern int python_quiet; extern struct t_plugin_script *python_scripts; extern struct t_plugin_script *last_python_script; @@ -61,4 +63,4 @@ extern void *weechat_python_exec (struct t_plugin_script *script, int ret_type, const char *function, char *format, void **argv); -#endif /* WEECHAT_PYTHON_H */ +#endif /* WEECHAT_PLUGIN_PYTHON_H */ diff --git a/src/plugins/relay/CMakeLists.txt b/src/plugins/relay/CMakeLists.txt index e3be724f8..26e98d33d 100644 --- a/src/plugins/relay/CMakeLists.txt +++ b/src/plugins/relay/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/relay/Makefile.am b/src/plugins/relay/Makefile.am index 3840f5847..d3e0e7a31 100644 --- a/src/plugins/relay/Makefile.am +++ b/src/plugins/relay/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/relay/irc/relay-irc.c b/src/plugins/relay/irc/relay-irc.c index 99fb0f32b..475f15ee0 100644 --- a/src/plugins/relay/irc/relay-irc.c +++ b/src/plugins/relay/irc/relay-irc.c @@ -1,7 +1,7 @@ /* * relay-irc.c - IRC protocol for relay to client: IRC proxy/bouncer * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -726,7 +726,8 @@ relay_irc_get_line_info (struct t_relay_client *client, && time_format && time_format[0]) { tm = localtime (&msg_date); - strftime (str_time, sizeof (str_time), time_format, tm); + if (strftime (str_time, sizeof (str_time), time_format, tm) == 0) + str_time[0] = '\0'; length = strlen (str_time) + strlen (pos) + 1; *message = malloc (length); if (*message) @@ -741,7 +742,8 @@ relay_irc_get_line_info (struct t_relay_client *client, && (RELAY_IRC_DATA(client, server_capabilities) & (1 << RELAY_IRC_CAPAB_SERVER_TIME))) { tm = gmtime (&msg_date); - strftime (str_time, sizeof (str_time), "%Y-%m-%dT%H:%M:%S", tm); + if (strftime (str_time, sizeof (str_time), "%Y-%m-%dT%H:%M:%S", tm) == 0) + str_time[0] = '\0'; snprintf (str_tag, sizeof (str_tag), "@time=%s.000Z ", str_time); *tags = strdup (str_tag); } @@ -906,6 +908,7 @@ relay_irc_send_channel_backlog (struct t_relay_client *client, (ptr_host) ? "!" : "", (ptr_host) ? ptr_host : "", channel); + break; case RELAY_IRC_CMD_QUIT: relay_irc_sendf (client, "%s:%s%s%s QUIT", @@ -1225,10 +1228,10 @@ relay_irc_hook_signals (struct t_relay_client *client) void relay_irc_recv_command_capab (struct t_relay_client *client, - int argc, char **argv) + int argc, char **argv, char **argv_eol) { - char str_capab[1024]; - int i, capability; + char str_capab[1024], *ptr_cap; + int i, capability, server_caps, num_caps_received, caps_ok; if (weechat_strcasecmp (argv[0], "ls") == 0) { @@ -1251,31 +1254,47 @@ relay_irc_recv_command_capab (struct t_relay_client *client, else if (weechat_strcasecmp (argv[0], "req") == 0) { /* client is asking for one or more server capabilities */ - str_capab[0] = '\0'; + num_caps_received = 0; + caps_ok = 0; + server_caps = RELAY_IRC_DATA(client, server_capabilities); for (i = 1; i < argc; i++) { - capability = relay_irc_search_server_capability ( - (argv[i][0] == ':') ? argv[i] + 1 : argv[i]); - if (capability >= 0) + ptr_cap = (argv[i][0] == ':') ? argv[i] + 1 : argv[i]; + if (ptr_cap[0]) { - if (str_capab[0]) - strcat (str_capab, " "); - strcat (str_capab, - relay_irc_server_capabilities[capability]); - RELAY_IRC_DATA(client, server_capabilities) |= 1 << capability; + num_caps_received++; + capability = relay_irc_search_server_capability (ptr_cap); + if (capability >= 0) + { + caps_ok = 1; + server_caps |= 1 << capability; + } + else + { + caps_ok = 0; + break; + } } } + if (caps_ok) + RELAY_IRC_DATA(client, server_capabilities) = server_caps; + relay_irc_sendf ( + client, + ":%s CAP %s %s :%s", + RELAY_IRC_DATA(client, address), + (RELAY_IRC_DATA(client, nick)) ? RELAY_IRC_DATA(client, nick) : "nick", + (caps_ok) ? "ACK" : "NAK", + (argc >= 2) ? ((argv_eol[1][0] == ':') ? argv_eol[1] + 1 : argv_eol[1]) : ""); + /* - * if at least one supported capability was enabled, send ACK to - * client + * if the CAP REQ command is received without arguments, we consider + * the CAP END is received; this is a workaround for clients like + * Atomic which are sending "CAP REQ :" (see issue #1040) */ - if (str_capab[0]) + if (num_caps_received == 0) { - relay_irc_sendf (client, - ":%s CAP %s ACK :%s", - RELAY_IRC_DATA(client, address), - (RELAY_IRC_DATA(client, nick)) ? RELAY_IRC_DATA(client, nick) : "nick", - str_capab); + if (!RELAY_IRC_DATA(client, connected)) + RELAY_IRC_DATA(client, cap_end_received) = 1; } } else if (weechat_strcasecmp (argv[0], "end") == 0) @@ -1293,7 +1312,7 @@ void relay_irc_recv (struct t_relay_client *client, const char *data) { char str_time[128], str_signal[128], str_server_channel[256]; - char str_command[128], *target, **irc_argv, *pos, *password; + char str_command[128], *target, **irc_argv, **irc_argv_eol, *pos, *password; const char *irc_command, *irc_channel, *irc_args, *irc_args2; int irc_argc, redirect_msg; const char *nick, *irc_is_channel, *isupport, *info, *pos_password; @@ -1302,6 +1321,7 @@ relay_irc_recv (struct t_relay_client *client, const char *data) hash_parsed = NULL; irc_argv = NULL; + irc_argv_eol = NULL; irc_argc = 0; /* display debug message */ @@ -1323,7 +1343,10 @@ relay_irc_recv (struct t_relay_client *client, const char *data) irc_channel = weechat_hashtable_get (hash_parsed, "channel"); irc_args = weechat_hashtable_get (hash_parsed, "arguments"); if (irc_args) + { irc_argv = weechat_string_split (irc_args, " ", 0, 0, &irc_argc); + irc_argv_eol = weechat_string_split (irc_args, " ", 1, 0, NULL); + } /* * first process the "nick" command (it will be processed again in this @@ -1341,8 +1364,11 @@ relay_irc_recv (struct t_relay_client *client, const char *data) /* server capabilities */ if (irc_command && (weechat_strcasecmp (irc_command, "cap") == 0)) { - if ((irc_argc > 0) && irc_argv) - relay_irc_recv_command_capab (client, irc_argc, irc_argv); + if (irc_argc > 0) + { + relay_irc_recv_command_capab (client, + irc_argc, irc_argv, irc_argv_eol); + } } /* if client is not yet "connected" */ if (!RELAY_IRC_DATA(client, connected)) @@ -1473,7 +1499,7 @@ relay_irc_recv (struct t_relay_client *client, const char *data) "weechat-relay-irc, running version %s", RELAY_IRC_DATA(client, address), RELAY_IRC_DATA(client, nick), - weechat_info_get("version", NULL)); + weechat_info_get ("version", NULL)); snprintf (str_time, sizeof (str_time), "%s", ctime (&client->listen_start_time)); if (str_time[0]) @@ -1488,7 +1514,7 @@ relay_irc_recv (struct t_relay_client *client, const char *data) RELAY_IRC_DATA(client, address), RELAY_IRC_DATA(client, nick), RELAY_IRC_DATA(client, address), - weechat_info_get("version", NULL)); + weechat_info_get ("version", NULL)); infolist_server = weechat_infolist_get ("irc_server", NULL, client->protocol_args); if (infolist_server) @@ -1733,6 +1759,8 @@ end: weechat_hashtable_free (hash_parsed); if (irc_argv) weechat_string_free_split (irc_argv); + if (irc_argv_eol) + weechat_string_free_split (irc_argv_eol); } /* diff --git a/src/plugins/relay/irc/relay-irc.h b/src/plugins/relay/irc/relay-irc.h index 0d02cf97a..186677c02 100644 --- a/src/plugins/relay/irc/relay-irc.h +++ b/src/plugins/relay/irc/relay-irc.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RELAY_IRC_H -#define WEECHAT_RELAY_IRC_H 1 +#ifndef WEECHAT_PLUGIN_RELAY_IRC_H +#define WEECHAT_PLUGIN_RELAY_IRC_H struct t_relay_client; @@ -74,4 +74,4 @@ extern int relay_irc_add_to_infolist (struct t_infolist_item *item, struct t_relay_client *client); extern void relay_irc_print_log (struct t_relay_client *client); -#endif /* WEECHAT_RELAY_IRC_H */ +#endif /* WEECHAT_PLUGIN_RELAY_IRC_H */ diff --git a/src/plugins/relay/relay-buffer.c b/src/plugins/relay/relay-buffer.c index 5a0f8f87b..1b9ab9153 100644 --- a/src/plugins/relay/relay-buffer.c +++ b/src/plugins/relay/relay-buffer.c @@ -1,7 +1,7 @@ /* * relay-buffer.c - display clients list on relay buffer * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -56,9 +56,9 @@ relay_buffer_refresh (const char *hotlist) client_selected = relay_client_search_by_number (relay_buffer_selected_line); weechat_printf_y (relay_buffer, 0, "%s%s%s%s%s%s%s", - weechat_color("green"), + weechat_color ("green"), _("Actions (letter+enter):"), - weechat_color("lightgreen"), + weechat_color ("lightgreen"), /* disconnect */ (client_selected && !RELAY_CLIENT_HAS_ENDED(client_selected)) ? @@ -96,8 +96,9 @@ relay_buffer_refresh (const char *hotlist) date_tmp = localtime (&(ptr_client->start_time)); if (date_tmp) { - strftime (str_date_start, sizeof (str_date_start), - "%a, %d %b %Y %H:%M:%S", date_tmp); + if (strftime (str_date_start, sizeof (str_date_start), + "%a, %d %b %Y %H:%M:%S", date_tmp) == 0) + str_date_start[0] = '\0'; } str_date_end[0] = '-'; str_date_end[1] = '\0'; @@ -106,8 +107,9 @@ relay_buffer_refresh (const char *hotlist) date_tmp = localtime (&(ptr_client->end_time)); if (date_tmp) { - strftime (str_date_end, sizeof (str_date_end), - "%a, %d %b %Y %H:%M:%S", date_tmp); + if (strftime (str_date_end, sizeof (str_date_end), + "%a, %d %b %Y %H:%M:%S", date_tmp) == 0) + str_date_end[0] = '\0'; } } @@ -117,9 +119,9 @@ relay_buffer_refresh (const char *hotlist) /* first line with status, description and bytes recv/sent */ weechat_printf_y (relay_buffer, (line * 2) + 2, _("%s%s[%s%s%s%s] %s, received: %s, sent: %s"), - weechat_color(str_color), + weechat_color (str_color), (line == relay_buffer_selected_line) ? "*** " : " ", - weechat_color(weechat_config_string (relay_config_color_status[ptr_client->status])), + weechat_color (weechat_config_string (relay_config_color_status[ptr_client->status])), str_status, weechat_color ("reset"), weechat_color (str_color), @@ -130,7 +132,7 @@ relay_buffer_refresh (const char *hotlist) /* second line with start/end time */ weechat_printf_y (relay_buffer, (line * 2) + 3, _("%s%-26s started on: %s, ended on: %s"), - weechat_color(str_color), + weechat_color (str_color), " ", str_date_start, str_date_end); diff --git a/src/plugins/relay/relay-buffer.h b/src/plugins/relay/relay-buffer.h index 98b388590..c81d9ee8d 100644 --- a/src/plugins/relay/relay-buffer.h +++ b/src/plugins/relay/relay-buffer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RELAY_BUFFER_H -#define WEECHAT_RELAY_BUFFER_H 1 +#ifndef WEECHAT_PLUGIN_RELAY_BUFFER_H +#define WEECHAT_PLUGIN_RELAY_BUFFER_H #define RELAY_BUFFER_NAME "relay.list" @@ -33,4 +33,4 @@ extern int relay_buffer_close_cb (const void *pointer, void *data, struct t_gui_buffer *buffer); extern void relay_buffer_open (); -#endif /* WEECHAT_RELAY_BUFFER_H */ +#endif /* WEECHAT_PLUGIN_RELAY_BUFFER_H */ diff --git a/src/plugins/relay/relay-client.c b/src/plugins/relay/relay-client.c index a334db02c..7878f595c 100644 --- a/src/plugins/relay/relay-client.c +++ b/src/plugins/relay/relay-client.c @@ -1,7 +1,7 @@ /* * relay-client.c - client functions for relay plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -1784,11 +1784,11 @@ relay_client_print_log () relay_protocol_string[ptr_client->protocol]); weechat_log_printf (" protocol_string . . . : '%s'", ptr_client->protocol_string); weechat_log_printf (" protocol_args . . . . : '%s'", ptr_client->protocol_args); - weechat_log_printf (" listen_start_time . . : %ld", ptr_client->listen_start_time); - weechat_log_printf (" start_time. . . . . . : %ld", ptr_client->start_time); - weechat_log_printf (" end_time. . . . . . . : %ld", ptr_client->end_time); + weechat_log_printf (" listen_start_time . . : %lld", (long long)ptr_client->listen_start_time); + weechat_log_printf (" start_time. . . . . . : %lld", (long long)ptr_client->start_time); + weechat_log_printf (" end_time. . . . . . . : %lld", (long long)ptr_client->end_time); weechat_log_printf (" hook_fd . . . . . . . : 0x%lx", ptr_client->hook_fd); - weechat_log_printf (" last_activity . . . . : %ld", ptr_client->last_activity); + weechat_log_printf (" last_activity . . . . : %lld", (long long)ptr_client->last_activity); weechat_log_printf (" bytes_recv. . . . . . : %llu", ptr_client->bytes_recv); weechat_log_printf (" bytes_sent. . . . . . : %llu", ptr_client->bytes_sent); weechat_log_printf (" recv_data_type. . . . : %d (%s)", diff --git a/src/plugins/relay/relay-client.h b/src/plugins/relay/relay-client.h index 4634d7c7a..e9c52ddf9 100644 --- a/src/plugins/relay/relay-client.h +++ b/src/plugins/relay/relay-client.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RELAY_CLIENT_H -#define WEECHAT_RELAY_CLIENT_H 1 +#ifndef WEECHAT_PLUGIN_RELAY_CLIENT_H +#define WEECHAT_PLUGIN_RELAY_CLIENT_H #include <time.h> @@ -153,4 +153,4 @@ extern int relay_client_add_to_infolist (struct t_infolist *infolist, struct t_relay_client *client); extern void relay_client_print_log (); -#endif /* WEECHAT_RELAY_CLIENT_H */ +#endif /* WEECHAT_PLUGIN_RELAY_CLIENT_H */ diff --git a/src/plugins/relay/relay-command.c b/src/plugins/relay/relay-command.c index 450187c3e..f5735bb0b 100644 --- a/src/plugins/relay/relay-command.c +++ b/src/plugins/relay/relay-command.c @@ -1,7 +1,7 @@ /* * relay-command.c - relay command * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -66,16 +66,18 @@ relay_command_client_list (int full) date_tmp = localtime (&(ptr_client->start_time)); if (date_tmp) { - strftime (date_start, sizeof (date_start), - "%a, %d %b %Y %H:%M:%S", date_tmp); + if (strftime (date_start, sizeof (date_start), + "%a, %d %b %Y %H:%M:%S", date_tmp) == 0) + date_start[0] = '\0'; } date_activity[0] = '\0'; date_tmp = localtime (&(ptr_client->last_activity)); if (date_tmp) { - strftime (date_activity, sizeof (date_activity), - "%a, %d %b %Y %H:%M:%S", date_tmp); + if (strftime (date_activity, sizeof (date_activity), + "%a, %d %b %Y %H:%M:%S", date_tmp) == 0) + date_activity[0] = '\0'; } if (full) @@ -156,8 +158,9 @@ relay_command_server_list () date_tmp = localtime (&(ptr_server->start_time)); if (date_tmp) { - strftime (date_start, sizeof (date_start), - "%a, %d %b %Y %H:%M:%S", date_tmp); + if (strftime (date_start, sizeof (date_start), + "%a, %d %b %Y %H:%M:%S", date_tmp) == 0) + date_start[0] = '\0'; } weechat_printf ( NULL, diff --git a/src/plugins/relay/relay-command.h b/src/plugins/relay/relay-command.h index c8f617e51..86be1b1bd 100644 --- a/src/plugins/relay/relay-command.h +++ b/src/plugins/relay/relay-command.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RELAY_COMMAND_H -#define WEECHAT_RELAY_COMMAND_H 1 +#ifndef WEECHAT_PLUGIN_RELAY_COMMAND_H +#define WEECHAT_PLUGIN_RELAY_COMMAND_H extern void relay_command_init (); -#endif /* WEECHAT_RELAY_COMMAND_H */ +#endif /* WEECHAT_PLUGIN_RELAY_COMMAND_H */ diff --git a/src/plugins/relay/relay-completion.c b/src/plugins/relay/relay-completion.c index ce7629232..f49cc7186 100644 --- a/src/plugins/relay/relay-completion.c +++ b/src/plugins/relay/relay-completion.c @@ -1,7 +1,7 @@ /* * relay-completion.c - completion for relay command * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -47,7 +47,7 @@ relay_completion_protocol_name_cb (const void *pointer, void *data, (void) buffer; (void) completion_item; - infolist = weechat_infolist_get("irc_server", NULL, NULL); + infolist = weechat_infolist_get ("irc_server", NULL, NULL); if (infolist) { while (weechat_infolist_next (infolist)) diff --git a/src/plugins/relay/relay-completion.h b/src/plugins/relay/relay-completion.h index cec77e59f..2b63f5f72 100644 --- a/src/plugins/relay/relay-completion.h +++ b/src/plugins/relay/relay-completion.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RELAY_COMPLETION_H -#define WEECHAT_RELAY_COMPLETION_H 1 +#ifndef WEECHAT_PLUGIN_RELAY_COMPLETION_H +#define WEECHAT_PLUGIN_RELAY_COMPLETION_H extern void relay_completion_init (); -#endif /* WEECHAT_RELAY_COMPLETION_H */ +#endif /* WEECHAT_PLUGIN_RELAY_COMPLETION_H */ diff --git a/src/plugins/relay/relay-config.c b/src/plugins/relay/relay-config.c index 6a050e5e8..27fa0974c 100644 --- a/src/plugins/relay/relay-config.c +++ b/src/plugins/relay/relay-config.c @@ -1,7 +1,7 @@ /* * relay-config.c - relay configuration options (file relay.conf) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -635,6 +635,7 @@ relay_config_init () if (!ptr_section) { weechat_config_free (relay_config_file); + relay_config_file = NULL; return 0; } @@ -663,6 +664,7 @@ relay_config_init () if (!ptr_section) { weechat_config_free (relay_config_file); + relay_config_file = NULL; return 0; } @@ -748,6 +750,7 @@ relay_config_init () if (!ptr_section) { weechat_config_free (relay_config_file); + relay_config_file = NULL; return 0; } @@ -862,6 +865,7 @@ relay_config_init () if (!ptr_section) { weechat_config_free (relay_config_file); + relay_config_file = NULL; return 0; } @@ -925,6 +929,7 @@ relay_config_init () if (!ptr_section) { weechat_config_free (relay_config_file); + relay_config_file = NULL; return 0; } diff --git a/src/plugins/relay/relay-config.h b/src/plugins/relay/relay-config.h index 2bd1c0545..0555bb88c 100644 --- a/src/plugins/relay/relay-config.h +++ b/src/plugins/relay/relay-config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RELAY_CONFIG_H -#define WEECHAT_RELAY_CONFIG_H 1 +#ifndef WEECHAT_PLUGIN_RELAY_CONFIG_H +#define WEECHAT_PLUGIN_RELAY_CONFIG_H #include <regex.h> @@ -69,4 +69,4 @@ extern int relay_config_read (); extern int relay_config_write (); extern void relay_config_free (); -#endif /* WEECHAT_RELAY_CONFIG_H */ +#endif /* WEECHAT_PLUGIN_RELAY_CONFIG_H */ diff --git a/src/plugins/relay/relay-info.c b/src/plugins/relay/relay-info.c index 317e7a86f..d669d4af4 100644 --- a/src/plugins/relay/relay-info.c +++ b/src/plugins/relay/relay-info.c @@ -1,7 +1,7 @@ /* * relay-info.c - info and infolist hooks for relay plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/relay/relay-info.h b/src/plugins/relay/relay-info.h index 175300bc1..25c2c3776 100644 --- a/src/plugins/relay/relay-info.h +++ b/src/plugins/relay/relay-info.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RELAY_INFO_H -#define WEECHAT_RELAY_INFO_H 1 +#ifndef WEECHAT_PLUGIN_RELAY_INFO_H +#define WEECHAT_PLUGIN_RELAY_INFO_H extern void relay_info_init (); -#endif /* WEECHAT_RELAY_INFO_H */ +#endif /* WEECHAT_PLUGIN_RELAY_INFO_H */ diff --git a/src/plugins/relay/relay-network.c b/src/plugins/relay/relay-network.c index a5ed02509..fa7d17c0b 100644 --- a/src/plugins/relay/relay-network.c +++ b/src/plugins/relay/relay-network.c @@ -1,7 +1,7 @@ /* * relay-network.c - network functions for relay plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/relay/relay-network.h b/src/plugins/relay/relay-network.h index aaf38df60..22a5cbb47 100644 --- a/src/plugins/relay/relay-network.h +++ b/src/plugins/relay/relay-network.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RELAY_NETWORK_H -#define WEECHAT_RELAY_NETWORK_H 1 +#ifndef WEECHAT_PLUGIN_RELAY_NETWORK_H +#define WEECHAT_PLUGIN_RELAY_NETWORK_H #ifdef HAVE_GNUTLS #include <gnutls/gnutls.h> @@ -38,4 +38,4 @@ extern void relay_network_set_priority (); extern void relay_network_init (); extern void relay_network_end (); -#endif /* WEECHAT_RELAY_NETWORK_H */ +#endif /* WEECHAT_PLUGIN_RELAY_NETWORK_H */ diff --git a/src/plugins/relay/relay-raw.c b/src/plugins/relay/relay-raw.c index 9efd72bec..b3f78e603 100644 --- a/src/plugins/relay/relay-raw.c +++ b/src/plugins/relay/relay-raw.c @@ -1,7 +1,7 @@ /* * relay-raw.c - functions for Relay raw data messages * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/relay/relay-raw.h b/src/plugins/relay/relay-raw.h index a2727d6c4..26316602c 100644 --- a/src/plugins/relay/relay-raw.h +++ b/src/plugins/relay/relay-raw.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RELAY_RAW_H -#define WEECHAT_RELAY_RAW_H 1 +#ifndef WEECHAT_PLUGIN_RELAY_RAW_H +#define WEECHAT_PLUGIN_RELAY_RAW_H #include <time.h> @@ -58,4 +58,4 @@ extern void relay_raw_message_free_all (); extern int relay_raw_add_to_infolist (struct t_infolist *infolist, struct t_relay_raw_message *raw_message); -#endif /* WEECHAT_RELAY_RAW_H */ +#endif /* WEECHAT_PLUGIN_RELAY_RAW_H */ diff --git a/src/plugins/relay/relay-server.c b/src/plugins/relay/relay-server.c index be377e383..73768e021 100644 --- a/src/plugins/relay/relay-server.c +++ b/src/plugins/relay/relay-server.c @@ -1,7 +1,7 @@ /* * relay-server.c - server functions for relay plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -761,8 +761,8 @@ relay_server_print_log () weechat_log_printf (" ssl . . . . . . . . . : %d", ptr_server->ssl); weechat_log_printf (" sock. . . . . . . . . : %d", ptr_server->sock); weechat_log_printf (" hook_fd . . . . . . . : 0x%lx", ptr_server->hook_fd); - weechat_log_printf (" start_time. . . . . . : %ld", ptr_server->start_time); - weechat_log_printf (" last_client_disconnect: %ld", ptr_server->last_client_disconnect); + weechat_log_printf (" start_time. . . . . . : %lld", (long long)ptr_server->start_time); + weechat_log_printf (" last_client_disconnect: %lld", (long long)ptr_server->last_client_disconnect); weechat_log_printf (" prev_server . . . . . : 0x%lx", ptr_server->prev_server); weechat_log_printf (" next_server . . . . . : 0x%lx", ptr_server->next_server); } diff --git a/src/plugins/relay/relay-server.h b/src/plugins/relay/relay-server.h index 826d0b160..5aab6b69f 100644 --- a/src/plugins/relay/relay-server.h +++ b/src/plugins/relay/relay-server.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RELAY_SERVER_H -#define WEECHAT_RELAY_SERVER_H 1 +#ifndef WEECHAT_PLUGIN_RELAY_SERVER_H +#define WEECHAT_PLUGIN_RELAY_SERVER_H #include <time.h> @@ -68,4 +68,4 @@ extern int relay_server_add_to_infolist (struct t_infolist *infolist, struct t_relay_server *server); extern void relay_server_print_log (); -#endif /* WEECHAT_RELAY_SERVER_H */ +#endif /* WEECHAT_PLUGIN_RELAY_SERVER_H */ diff --git a/src/plugins/relay/relay-upgrade.c b/src/plugins/relay/relay-upgrade.c index 539022b72..c9835119e 100644 --- a/src/plugins/relay/relay-upgrade.c +++ b/src/plugins/relay/relay-upgrade.c @@ -1,7 +1,7 @@ /* * relay-upgrade.c - save/restore relay plugin data when upgrading WeeChat * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/relay/relay-upgrade.h b/src/plugins/relay/relay-upgrade.h index 17a375700..0a778f284 100644 --- a/src/plugins/relay/relay-upgrade.h +++ b/src/plugins/relay/relay-upgrade.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RELAY_UPGRADE_H -#define WEECHAT_RELAY_UPGRADE_H 1 +#ifndef WEECHAT_PLUGIN_RELAY_UPGRADE_H +#define WEECHAT_PLUGIN_RELAY_UPGRADE_H #define RELAY_UPGRADE_FILENAME "relay" @@ -34,4 +34,4 @@ enum t_relay_upgrade_type extern int relay_upgrade_save (); extern int relay_upgrade_load (); -#endif /* WEECHAT_RELAY_UPGRADE_H */ +#endif /* WEECHAT_PLUGIN_RELAY_UPGRADE_H */ diff --git a/src/plugins/relay/relay-websocket.c b/src/plugins/relay/relay-websocket.c index b650f8442..6d31cb8c8 100644 --- a/src/plugins/relay/relay-websocket.c +++ b/src/plugins/relay/relay-websocket.c @@ -1,7 +1,7 @@ /* * relay-websocket.c - websocket server functions for relay plugin (RFC 6455) * - * Copyright (C) 2013-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2013-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/relay/relay-websocket.h b/src/plugins/relay/relay-websocket.h index 2a70ee566..91d601713 100644 --- a/src/plugins/relay/relay-websocket.h +++ b/src/plugins/relay/relay-websocket.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2013-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RELAY_WEBSOCKET_H -#define WEECHAT_RELAY_WEBSOCKET_H 1 +#ifndef WEECHAT_PLUGIN_RELAY_WEBSOCKET_H +#define WEECHAT_PLUGIN_RELAY_WEBSOCKET_H #define WEBSOCKET_FRAME_OPCODE_CONTINUATION 0x00 #define WEBSOCKET_FRAME_OPCODE_TEXT 0x01 @@ -43,4 +43,4 @@ extern char *relay_websocket_encode_frame (int opcode, unsigned long long length, unsigned long long *length_frame); -#endif /* WEECHAT_RELAY_WEBSOCKET_H */ +#endif /* WEECHAT_PLUGIN_RELAY_WEBSOCKET_H */ diff --git a/src/plugins/relay/relay.c b/src/plugins/relay/relay.c index 71b3faaeb..0d076fe80 100644 --- a/src/plugins/relay/relay.c +++ b/src/plugins/relay/relay.c @@ -1,7 +1,7 @@ /* * relay.c - network communication between WeeChat and remote client * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -42,7 +42,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Relay WeeChat data to remote application " WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(4000); +WEECHAT_PLUGIN_PRIORITY(5000); struct t_weechat_plugin *weechat_relay_plugin = NULL; diff --git a/src/plugins/relay/relay.h b/src/plugins/relay/relay.h index 10621016b..4b32abda5 100644 --- a/src/plugins/relay/relay.h +++ b/src/plugins/relay/relay.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RELAY_H -#define WEECHAT_RELAY_H 1 +#ifndef WEECHAT_PLUGIN_RELAY_H +#define WEECHAT_PLUGIN_RELAY_H #define weechat_plugin weechat_relay_plugin #define RELAY_PLUGIN_NAME "relay" @@ -46,4 +46,4 @@ extern char *relay_protocol_string[]; extern int relay_protocol_search (const char *name); -#endif /* WEECHAT_RELAY_H */ +#endif /* WEECHAT_PLUGIN_RELAY_H */ diff --git a/src/plugins/relay/weechat/relay-weechat-msg.c b/src/plugins/relay/weechat/relay-weechat-msg.c index 305823528..5352ef5e5 100644 --- a/src/plugins/relay/weechat/relay-weechat-msg.c +++ b/src/plugins/relay/weechat/relay-weechat-msg.c @@ -1,7 +1,7 @@ /* * relay-weechat-msg.c - build binary messages for WeeChat protocol * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -242,7 +242,7 @@ relay_weechat_msg_add_time (struct t_relay_weechat_msg *msg, time_t time) char str_time[128]; unsigned char length; - snprintf (str_time, sizeof (str_time), "%ld", (long)time); + snprintf (str_time, sizeof (str_time), "%lld", (long long)time); length = strlen (str_time); relay_weechat_msg_add_bytes (msg, &length, 1); relay_weechat_msg_add_bytes (msg, str_time, length); @@ -904,9 +904,9 @@ relay_weechat_msg_add_nicklist_buffer (struct t_relay_weechat_msg *msg, relay_weechat_msg_add_pointer (msg, ptr_nick); relay_weechat_msg_add_char (msg, 0); /* group */ relay_weechat_msg_add_char (msg, - (char)weechat_hdata_integer(ptr_hdata_nick, - ptr_nick, - "visible")); + (char)weechat_hdata_integer (ptr_hdata_nick, + ptr_nick, + "visible")); relay_weechat_msg_add_int (msg, 0); /* level */ relay_weechat_msg_add_string (msg, weechat_hdata_string (ptr_hdata_nick, @@ -932,9 +932,9 @@ relay_weechat_msg_add_nicklist_buffer (struct t_relay_weechat_msg *msg, relay_weechat_msg_add_pointer (msg, ptr_group); relay_weechat_msg_add_char (msg, 1); /* group */ relay_weechat_msg_add_char (msg, - (char)weechat_hdata_integer(ptr_hdata_group, - ptr_group, - "visible")); + (char)weechat_hdata_integer (ptr_hdata_group, + ptr_group, + "visible")); relay_weechat_msg_add_int (msg, weechat_hdata_integer (ptr_hdata_group, ptr_group, diff --git a/src/plugins/relay/weechat/relay-weechat-msg.h b/src/plugins/relay/weechat/relay-weechat-msg.h index bb012ebe5..5d1541dfd 100644 --- a/src/plugins/relay/weechat/relay-weechat-msg.h +++ b/src/plugins/relay/weechat/relay-weechat-msg.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RELAY_WEECHAT_MSG_H -#define WEECHAT_RELAY_WEECHAT_MSG_H 1 +#ifndef WEECHAT_PLUGIN_RELAY_WEECHAT_MSG_H +#define WEECHAT_PLUGIN_RELAY_WEECHAT_MSG_H #include <time.h> @@ -83,4 +83,4 @@ extern void relay_weechat_msg_send (struct t_relay_client *client, struct t_relay_weechat_msg *msg); extern void relay_weechat_msg_free (struct t_relay_weechat_msg *msg); -#endif /* WEECHAT_RELAY_WEECHAT_MSG_H */ +#endif /* WEECHAT_PLUGIN_RELAY_WEECHAT_MSG_H */ diff --git a/src/plugins/relay/weechat/relay-weechat-nicklist.c b/src/plugins/relay/weechat/relay-weechat-nicklist.c index 06d8f6a67..109598bcb 100644 --- a/src/plugins/relay/weechat/relay-weechat-nicklist.c +++ b/src/plugins/relay/weechat/relay-weechat-nicklist.c @@ -1,7 +1,7 @@ /* * relay-weechat-nicklist.c - nicklist functions for WeeChat protocol * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/relay/weechat/relay-weechat-nicklist.h b/src/plugins/relay/weechat/relay-weechat-nicklist.h index 5ed15644b..386fda67e 100644 --- a/src/plugins/relay/weechat/relay-weechat-nicklist.h +++ b/src/plugins/relay/weechat/relay-weechat-nicklist.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RELAY_WEECHAT_NICKLIST_H -#define WEECHAT_RELAY_WEECHAT_NICKLIST_H 1 +#ifndef WEECHAT_PLUGIN_RELAY_WEECHAT_NICKLIST_H +#define WEECHAT_PLUGIN_RELAY_WEECHAT_NICKLIST_H #define RELAY_WEECHAT_NICKLIST_DIFF_UNKNOWN ' ' #define RELAY_WEECHAT_NICKLIST_DIFF_PARENT '^' @@ -54,4 +54,4 @@ extern void relay_weechat_nicklist_add_item (struct t_relay_weechat_nicklist *ni struct t_gui_nick *nick); extern void relay_weechat_nicklist_free (struct t_relay_weechat_nicklist *nicklist); -#endif /* WEECHAT_RELAY_WEECHAT_NICKLIST_H */ +#endif /* WEECHAT_PLUGIN_RELAY_WEECHAT_NICKLIST_H */ diff --git a/src/plugins/relay/weechat/relay-weechat-protocol.c b/src/plugins/relay/weechat/relay-weechat-protocol.c index 8fb42ee9f..64f03fce7 100644 --- a/src/plugins/relay/weechat/relay-weechat-protocol.c +++ b/src/plugins/relay/weechat/relay-weechat-protocol.c @@ -1,7 +1,7 @@ /* * relay-weechat-protocol.c - WeeChat protocol for relay to client * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/relay/weechat/relay-weechat-protocol.h b/src/plugins/relay/weechat/relay-weechat-protocol.h index 323b68d50..821702a78 100644 --- a/src/plugins/relay/weechat/relay-weechat-protocol.h +++ b/src/plugins/relay/weechat/relay-weechat-protocol.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RELAY_WEECHAT_PROTOCOL_H -#define WEECHAT_RELAY_WEECHAT_PROTOCOL_H 1 +#ifndef WEECHAT_PLUGIN_RELAY_WEECHAT_PROTOCOL_H +#define WEECHAT_PLUGIN_RELAY_WEECHAT_PROTOCOL_H #define RELAY_WEECHAT_PROTOCOL_SYNC_BUFFER 1 #define RELAY_WEECHAT_PROTOCOL_SYNC_NICKLIST 2 @@ -101,4 +101,4 @@ extern int relay_weechat_protocol_timer_nicklist_cb (const void *pointer, extern void relay_weechat_protocol_recv (struct t_relay_client *client, const char *data); -#endif /* WEECHAT_RELAY_WEECHAT_PROTOCOL_H */ +#endif /* WEECHAT_PLUGIN_RELAY_WEECHAT_PROTOCOL_H */ diff --git a/src/plugins/relay/weechat/relay-weechat.c b/src/plugins/relay/weechat/relay-weechat.c index 84f1e73c4..8a7bd8d0f 100644 --- a/src/plugins/relay/weechat/relay-weechat.c +++ b/src/plugins/relay/weechat/relay-weechat.c @@ -1,7 +1,7 @@ /* * relay-weechat.c - WeeChat protocol for relay to client * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/relay/weechat/relay-weechat.h b/src/plugins/relay/weechat/relay-weechat.h index 9a1a7e440..75e8efe85 100644 --- a/src/plugins/relay/weechat/relay-weechat.h +++ b/src/plugins/relay/weechat/relay-weechat.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RELAY_WEECHAT_H -#define WEECHAT_RELAY_WEECHAT_H 1 +#ifndef WEECHAT_PLUGIN_RELAY_WEECHAT_H +#define WEECHAT_PLUGIN_RELAY_WEECHAT_H struct t_relay_client; @@ -63,4 +63,4 @@ extern int relay_weechat_add_to_infolist (struct t_infolist_item *item, struct t_relay_client *client); extern void relay_weechat_print_log (struct t_relay_client *client); -#endif /* WEECHAT_RELAY_WEECHAT_H */ +#endif /* WEECHAT_PLUGIN_RELAY_WEECHAT_H */ diff --git a/src/plugins/ruby/CMakeLists.txt b/src/plugins/ruby/CMakeLists.txt index 0149e8dbd..1f98b76f7 100644 --- a/src/plugins/ruby/CMakeLists.txt +++ b/src/plugins/ruby/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/ruby/Makefile.am b/src/plugins/ruby/Makefile.am index a85d9e7bf..fc4c4579d 100644 --- a/src/plugins/ruby/Makefile.am +++ b/src/plugins/ruby/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/ruby/weechat-ruby-api.c b/src/plugins/ruby/weechat-ruby-api.c index 639ec9eca..bfe889962 100644 --- a/src/plugins/ruby/weechat-ruby-api.c +++ b/src/plugins/ruby/weechat-ruby-api.c @@ -1,7 +1,7 @@ /* * weechat-ruby-api.c - ruby API functions * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2007 Emmanuel Bouthenot <kolter@openics.org> * Copyright (C) 2012 Simon Arlott * @@ -57,6 +57,8 @@ plugin_script_str2ptr (weechat_ruby_plugin, \ RUBY_CURRENT_SCRIPT_NAME, \ ruby_function_name, __string) +#define API_STATIC_STRING(__string) \ + plugin_script_get_static_string(&ruby_data, __string); #define API_RETURN_OK return INT2FIX (1) #define API_RETURN_ERROR return INT2FIX (0) #define API_RETURN_EMPTY return Qnil @@ -137,7 +139,7 @@ weechat_ruby_api_register (VALUE class, VALUE name, VALUE author, /* register script */ ruby_current_script = plugin_script_add (weechat_ruby_plugin, - &ruby_scripts, &last_ruby_script, + &ruby_data, (ruby_current_script_filename) ? ruby_current_script_filename : "", c_name, c_author, c_version, c_license, @@ -401,6 +403,26 @@ weechat_ruby_api_string_mask_to_regex (VALUE class, VALUE mask) } static VALUE +weechat_ruby_api_string_format_size (VALUE class, VALUE size) +{ + unsigned long long c_size; + char *result; + VALUE return_value; + + API_INIT_FUNC(1, "string_format_size", API_RETURN_EMPTY); + if (NIL_P (size)) + API_WRONG_ARGS(API_RETURN_EMPTY); + + Check_Type (size, T_FIXNUM); + + c_size = FIX2LONG (size); + + result = weechat_string_format_size (c_size); + + API_RETURN_STRING_FREE(result); +} + +static VALUE weechat_ruby_api_string_remove_color (VALUE class, VALUE string, VALUE replacement) { @@ -624,7 +646,7 @@ weechat_ruby_api_mkdir_parents (VALUE class, VALUE directory, VALUE mode) static VALUE weechat_ruby_api_list_new (VALUE class) { - char *result; + const char *result; API_INIT_FUNC(1, "list_new", API_RETURN_EMPTY); @@ -637,7 +659,8 @@ static VALUE weechat_ruby_api_list_add (VALUE class, VALUE weelist, VALUE data, VALUE where, VALUE user_data) { - char *c_weelist, *c_data, *c_where, *c_user_data, *result; + char *c_weelist, *c_data, *c_where, *c_user_data; + const char *result; API_INIT_FUNC(1, "list_add", API_RETURN_EMPTY); if (NIL_P (weelist) || NIL_P (data) || NIL_P (where) || NIL_P (user_data)) @@ -664,7 +687,8 @@ weechat_ruby_api_list_add (VALUE class, VALUE weelist, VALUE data, VALUE where, static VALUE weechat_ruby_api_list_search (VALUE class, VALUE weelist, VALUE data) { - char *c_weelist, *c_data, *result; + char *c_weelist, *c_data; + const char *result; API_INIT_FUNC(1, "list_search", API_RETURN_EMPTY); if (NIL_P (weelist) || NIL_P (data)) @@ -706,7 +730,8 @@ weechat_ruby_api_list_search_pos (VALUE class, VALUE weelist, VALUE data) static VALUE weechat_ruby_api_list_casesearch (VALUE class, VALUE weelist, VALUE data) { - char *c_weelist, *c_data, *result; + char *c_weelist, *c_data; + const char *result; API_INIT_FUNC(1, "list_casesearch", API_RETURN_EMPTY); if (NIL_P (weelist) || NIL_P (data)) @@ -748,7 +773,8 @@ weechat_ruby_api_list_casesearch_pos (VALUE class, VALUE weelist, VALUE data) static VALUE weechat_ruby_api_list_get (VALUE class, VALUE weelist, VALUE position) { - char *c_weelist, *result; + char *c_weelist; + const char *result; int c_position; API_INIT_FUNC(1, "list_get", API_RETURN_EMPTY); @@ -791,7 +817,8 @@ weechat_ruby_api_list_set (VALUE class, VALUE item, VALUE new_value) static VALUE weechat_ruby_api_list_next (VALUE class, VALUE item) { - char *c_item, *result; + char *c_item; + const char *result; API_INIT_FUNC(1, "list_next", API_RETURN_EMPTY); if (NIL_P (item)) @@ -809,7 +836,8 @@ weechat_ruby_api_list_next (VALUE class, VALUE item) static VALUE weechat_ruby_api_list_prev (VALUE class, VALUE item) { - char *c_item, *result; + char *c_item; + const char *result; API_INIT_FUNC(1, "list_prev", API_RETURN_EMPTY); if (NIL_P (item)) @@ -935,7 +963,7 @@ weechat_ruby_api_config_reload_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); rc = (int *) weechat_ruby_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -949,8 +977,6 @@ weechat_ruby_api_config_reload_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -962,8 +988,8 @@ static VALUE weechat_ruby_api_config_new (VALUE class, VALUE name, VALUE function, VALUE data) { - char *c_name, *c_function, *c_data, *result; - VALUE return_value; + char *c_name, *c_function, *c_data; + const char *result; API_INIT_FUNC(1, "config_new", API_RETURN_EMPTY); if (NIL_P (name) || NIL_P (function) || NIL_P (data)) @@ -984,7 +1010,7 @@ weechat_ruby_api_config_new (VALUE class, VALUE name, VALUE function, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -1005,8 +1031,8 @@ weechat_ruby_api_config_read_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); func_argv[3] = (option_name) ? (char *)option_name : empty_arg; func_argv[4] = (value) ? (char *)value : empty_arg; @@ -1022,10 +1048,6 @@ weechat_ruby_api_config_read_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); return ret; } @@ -1050,7 +1072,7 @@ weechat_ruby_api_config_section_write_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); func_argv[2] = (section_name) ? (char *)section_name : empty_arg; rc = (int *) weechat_ruby_exec (script, @@ -1065,8 +1087,6 @@ weechat_ruby_api_config_section_write_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -1091,7 +1111,7 @@ weechat_ruby_api_config_section_write_default_cb (const void *pointer, void *dat if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); func_argv[2] = (section_name) ? (char *)section_name : empty_arg; rc = (int *) weechat_ruby_exec (script, @@ -1106,8 +1126,6 @@ weechat_ruby_api_config_section_write_default_cb (const void *pointer, void *dat ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -1134,8 +1152,8 @@ weechat_ruby_api_config_section_create_option_cb (const void *pointer, void *dat if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); func_argv[3] = (option_name) ? (char *)option_name : empty_arg; func_argv[4] = (value) ? (char *)value : empty_arg; @@ -1151,10 +1169,6 @@ weechat_ruby_api_config_section_create_option_cb (const void *pointer, void *dat ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); return ret; } @@ -1180,9 +1194,9 @@ weechat_ruby_api_config_section_delete_option_cb (const void *pointer, void *dat if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); - func_argv[3] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); + func_argv[3] = (char *)API_PTR2STR(option); rc = (int *) weechat_ruby_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -1196,12 +1210,6 @@ weechat_ruby_api_config_section_delete_option_cb (const void *pointer, void *dat ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -1228,9 +1236,9 @@ weechat_ruby_api_config_new_section (VALUE class, VALUE config_file, char *c_function_write, *c_data_write, *c_function_write_default; char *c_data_write_default, *c_function_create_option; char *c_data_create_option, *c_function_delete_option; - char *c_data_delete_option, *result; + char *c_data_delete_option; + const char *result; int c_user_can_add_options, c_user_can_delete_options; - VALUE return_value; API_INIT_FUNC(1, "config_new_section", API_RETURN_EMPTY); if (NIL_P (config_file) || NIL_P (name) || NIL_P (user_can_add_options) @@ -1295,15 +1303,15 @@ weechat_ruby_api_config_new_section (VALUE class, VALUE config_file, c_function_delete_option, c_data_delete_option)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE weechat_ruby_api_config_search_section (VALUE class, VALUE config_file, VALUE section_name) { - char *c_config_file, *c_section_name, *result; - VALUE return_value; + char *c_config_file, *c_section_name; + const char *result; API_INIT_FUNC(1, "config_search_section", API_RETURN_EMPTY); if (NIL_P (config_file) || NIL_P (section_name)) @@ -1318,7 +1326,7 @@ weechat_ruby_api_config_search_section (VALUE class, VALUE config_file, result = API_PTR2STR(weechat_config_search_section (API_STR2PTR(c_config_file), c_section_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -1338,7 +1346,7 @@ weechat_ruby_api_config_option_check_value_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); func_argv[2] = (value) ? (char *)value : empty_arg; rc = (int *) weechat_ruby_exec (script, @@ -1353,8 +1361,6 @@ weechat_ruby_api_config_option_check_value_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -1378,16 +1384,13 @@ weechat_ruby_api_config_option_change_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); rc = (int *) weechat_ruby_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, "ss", func_argv); - if (func_argv[1]) - free (func_argv[1]); - if (rc) free (rc); } @@ -1409,16 +1412,13 @@ weechat_ruby_api_config_option_delete_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); rc = (int *) weechat_ruby_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, "ss", func_argv); - if (func_argv[1]) - free (func_argv[1]); - if (rc) free (rc); } @@ -1435,10 +1435,11 @@ weechat_ruby_api_config_new_option (VALUE class, VALUE config_file, char *c_config_file, *c_section, *c_name, *c_type, *c_description; char *c_string_values, *c_default_value, *c_value; char *c_function_check_value, *c_data_check_value, *c_function_change; - char *c_data_change, *c_function_delete, *c_data_delete, *result; + char *c_data_change, *c_function_delete, *c_data_delete; + const char *result; int c_min, c_max, c_null_value_allowed; VALUE function_check_value, data_check_value, function_change, data_change; - VALUE function_delete, data_delete, return_value; + VALUE function_delete, data_delete; API_INIT_FUNC(1, "config_new_option", API_RETURN_EMPTY); if (NIL_P (config_file) || NIL_P (section) || NIL_P (name) || NIL_P (type) @@ -1515,15 +1516,15 @@ weechat_ruby_api_config_new_option (VALUE class, VALUE config_file, c_function_delete, c_data_delete)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE weechat_ruby_api_config_search_option (VALUE class, VALUE config_file, VALUE section, VALUE option_name) { - char *c_config_file, *c_section, *c_option_name, *result; - VALUE return_value; + char *c_config_file, *c_section, *c_option_name; + const char *result; API_INIT_FUNC(1, "config_search_option", API_RETURN_EMPTY); if (NIL_P (config_file) || NIL_P (section) || NIL_P (option_name)) @@ -1541,7 +1542,7 @@ weechat_ruby_api_config_search_option (VALUE class, VALUE config_file, API_STR2PTR(c_section), c_option_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -2046,8 +2047,8 @@ weechat_ruby_api_config_free (VALUE class, VALUE config_file) static VALUE weechat_ruby_api_config_get (VALUE class, VALUE option) { - char *c_option, *result; - VALUE return_value; + char *c_option; + const char *result; API_INIT_FUNC(1, "config_get", API_RETURN_EMPTY); if (NIL_P (option)) @@ -2059,7 +2060,7 @@ weechat_ruby_api_config_get (VALUE class, VALUE option) result = API_PTR2STR(weechat_config_get (c_option)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -2381,7 +2382,7 @@ weechat_ruby_api_hook_command_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (argc > 1) ? argv_eol[1] : empty_arg; rc = (int *) weechat_ruby_exec (script, @@ -2396,8 +2397,6 @@ weechat_ruby_api_hook_command_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -2411,8 +2410,8 @@ weechat_ruby_api_hook_command (VALUE class, VALUE command, VALUE description, VALUE completion, VALUE function, VALUE data) { char *c_command, *c_description, *c_args, *c_args_description; - char *c_completion, *c_function, *c_data, *result; - VALUE return_value; + char *c_completion, *c_function, *c_data; + const char *result; API_INIT_FUNC(1, "hook_command", API_RETURN_EMPTY); if (NIL_P (command) || NIL_P (description) || NIL_P (args) @@ -2447,7 +2446,7 @@ weechat_ruby_api_hook_command (VALUE class, VALUE command, VALUE description, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2469,8 +2468,8 @@ weechat_ruby_api_hook_completion_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (completion_item) ? (char *)completion_item : empty_arg; - func_argv[2] = API_PTR2STR(buffer); - func_argv[3] = API_PTR2STR(completion); + func_argv[2] = (char *)API_PTR2STR(buffer); + func_argv[3] = (char *)API_PTR2STR(completion); rc = (int *) weechat_ruby_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -2484,10 +2483,6 @@ weechat_ruby_api_hook_completion_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -2500,8 +2495,8 @@ weechat_ruby_api_hook_completion (VALUE class, VALUE completion, VALUE description, VALUE function, VALUE data) { - char *c_completion, *c_description, *c_function, *c_data, *result; - VALUE return_value; + char *c_completion, *c_description, *c_function, *c_data; + const char *result; API_INIT_FUNC(1, "hook_completion", API_RETURN_EMPTY); if (NIL_P (completion) || NIL_P (description) || NIL_P (function) @@ -2526,7 +2521,7 @@ weechat_ruby_api_hook_completion (VALUE class, VALUE completion, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -2600,7 +2595,7 @@ weechat_ruby_api_hook_command_run_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (command) ? (char *)command : empty_arg; rc = (int *) weechat_ruby_exec (script, @@ -2615,8 +2610,6 @@ weechat_ruby_api_hook_command_run_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -2628,8 +2621,8 @@ static VALUE weechat_ruby_api_hook_command_run (VALUE class, VALUE command, VALUE function, VALUE data) { - char *c_command, *c_function, *c_data, *result; - VALUE return_value; + char *c_command, *c_function, *c_data; + const char *result; API_INIT_FUNC(1, "hook_command_run", API_RETURN_EMPTY); if (NIL_P (command) || NIL_P (function) || NIL_P (data)) @@ -2650,7 +2643,7 @@ weechat_ruby_api_hook_command_run (VALUE class, VALUE command, VALUE function, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2698,8 +2691,8 @@ weechat_ruby_api_hook_timer (VALUE class, VALUE interval, VALUE align_second, VALUE max_calls, VALUE function, VALUE data) { int c_interval, c_align_second, c_max_calls; - char *c_function, *c_data, *result; - VALUE return_value; + char *c_function, *c_data; + const char *result; API_INIT_FUNC(1, "hook_timer", API_RETURN_EMPTY); if (NIL_P (interval) || NIL_P (align_second) || NIL_P (max_calls) @@ -2727,7 +2720,7 @@ weechat_ruby_api_hook_timer (VALUE class, VALUE interval, VALUE align_second, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2735,7 +2728,7 @@ weechat_ruby_api_hook_fd_cb (const void *pointer, void *data, int fd) { struct t_plugin_script *script; void *func_argv[2]; - char str_fd[32], empty_arg[1] = { '\0' }; + char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; int *rc, ret; @@ -2744,15 +2737,13 @@ weechat_ruby_api_hook_fd_cb (const void *pointer, void *data, int fd) if (ptr_function && ptr_function[0]) { - snprintf (str_fd, sizeof (str_fd), "%d", fd); - func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = str_fd; + func_argv[1] = &fd; rc = (int *) weechat_ruby_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "ss", func_argv); + "si", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2773,8 +2764,8 @@ weechat_ruby_api_hook_fd (VALUE class, VALUE fd, VALUE read, VALUE write, VALUE exception, VALUE function, VALUE data) { int c_fd, c_read, c_write, c_exception; - char *c_function, *c_data, *result; - VALUE return_value; + char *c_function, *c_data; + const char *result; API_INIT_FUNC(1, "hook_fd", API_RETURN_EMPTY); if (NIL_P (fd) || NIL_P (read) || NIL_P (write) || NIL_P (exception) @@ -2805,7 +2796,7 @@ weechat_ruby_api_hook_fd (VALUE class, VALUE fd, VALUE read, VALUE write, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2872,9 +2863,9 @@ static VALUE weechat_ruby_api_hook_process (VALUE class, VALUE command, VALUE timeout, VALUE function, VALUE data) { - char *c_command, *c_function, *c_data, *result; + char *c_command, *c_function, *c_data; + const char *result; int c_timeout; - VALUE return_value; API_INIT_FUNC(1, "hook_process", API_RETURN_EMPTY); if (NIL_P (command) || NIL_P (timeout) || NIL_P (function) || NIL_P (data)) @@ -2898,7 +2889,7 @@ weechat_ruby_api_hook_process (VALUE class, VALUE command, VALUE timeout, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -2906,10 +2897,10 @@ weechat_ruby_api_hook_process_hashtable (VALUE class, VALUE command, VALUE options, VALUE timeout, VALUE function, VALUE data) { - char *c_command, *c_function, *c_data, *result; + char *c_command, *c_function, *c_data; + const char *result; struct t_hashtable *c_options; int c_timeout; - VALUE return_value; API_INIT_FUNC(1, "hook_process_hashtable", API_RETURN_EMPTY); if (NIL_P (command) || NIL_P (options) || NIL_P (timeout) @@ -2943,7 +2934,7 @@ weechat_ruby_api_hook_process_hashtable (VALUE class, VALUE command, if (c_options) weechat_hashtable_free (c_options); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2954,7 +2945,6 @@ weechat_ruby_api_hook_connect_cb (const void *pointer, void *data, { struct t_plugin_script *script; void *func_argv[6]; - char str_status[32], str_gnutls_rc[32], str_sock[32]; char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; int *rc, ret; @@ -2964,21 +2954,17 @@ weechat_ruby_api_hook_connect_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { - snprintf (str_status, sizeof (str_status), "%d", status); - snprintf (str_gnutls_rc, sizeof (str_gnutls_rc), "%d", gnutls_rc); - snprintf (str_sock, sizeof (str_sock), "%d", sock); - func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = str_status; - func_argv[2] = str_gnutls_rc; - func_argv[3] = str_sock; + func_argv[1] = &status; + func_argv[2] = &gnutls_rc; + func_argv[3] = &sock; func_argv[4] = (ip_address) ? (char *)ip_address : empty_arg; func_argv[5] = (error) ? (char *)error : empty_arg; rc = (int *) weechat_ruby_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "ssssss", func_argv); + "siiiss", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3000,9 +2986,9 @@ weechat_ruby_api_hook_connect (VALUE class, VALUE proxy, VALUE address, VALUE local_hostname, VALUE function, VALUE data) { - char *c_proxy, *c_address, *c_local_hostname, *c_function, *c_data, *result; + char *c_proxy, *c_address, *c_local_hostname, *c_function, *c_data; + const char *result; int c_port, c_ipv6, c_retry; - VALUE return_value; API_INIT_FUNC(1, "hook_connect", API_RETURN_EMPTY); if (NIL_P (proxy) || NIL_P (address) || NIL_P (port) || NIL_P (ipv6) @@ -3044,7 +3030,7 @@ weechat_ruby_api_hook_connect (VALUE class, VALUE proxy, VALUE address, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -3070,10 +3056,10 @@ weechat_ruby_api_hook_print_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { - snprintf (timebuffer, sizeof (timebuffer), "%ld", (long int)date); + snprintf (timebuffer, sizeof (timebuffer), "%lld", (long long)date); func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = timebuffer; func_argv[3] = weechat_string_build_with_split_string (tags, ","); if (!func_argv[3]) @@ -3095,8 +3081,6 @@ weechat_ruby_api_hook_print_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); if (func_argv[3]) free (func_argv[3]); @@ -3111,9 +3095,9 @@ weechat_ruby_api_hook_print (VALUE class, VALUE buffer, VALUE tags, VALUE message, VALUE strip_colors, VALUE function, VALUE data) { - char *c_buffer, *c_tags, *c_message, *c_function, *c_data, *result; + char *c_buffer, *c_tags, *c_message, *c_function, *c_data; + const char *result; int c_strip_colors; - VALUE return_value; API_INIT_FUNC(1, "hook_print", API_RETURN_EMPTY); if (NIL_P (buffer) || NIL_P (tags) || NIL_P (message) @@ -3144,7 +3128,7 @@ weechat_ruby_api_hook_print (VALUE class, VALUE buffer, VALUE tags, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -3157,7 +3141,7 @@ weechat_ruby_api_hook_signal_cb (const void *pointer, void *data, char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; static char str_value[64]; - int *rc, ret, free_needed; + int *rc, ret; script = (struct t_plugin_script *)pointer; plugin_script_get_function_and_data (data, &ptr_function, &ptr_data); @@ -3166,7 +3150,6 @@ weechat_ruby_api_hook_signal_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (signal) ? (char *)signal : empty_arg; - free_needed = 0; if (strcmp (type_data, WEECHAT_HOOK_SIGNAL_STRING) == 0) { func_argv[2] = (signal_data) ? (char *)signal_data : empty_arg; @@ -3183,8 +3166,7 @@ weechat_ruby_api_hook_signal_cb (const void *pointer, void *data, } else if (strcmp (type_data, WEECHAT_HOOK_SIGNAL_POINTER) == 0) { - func_argv[2] = API_PTR2STR(signal_data); - free_needed = 1; + func_argv[2] = (char *)API_PTR2STR(signal_data); } else func_argv[2] = empty_arg; @@ -3201,8 +3183,6 @@ weechat_ruby_api_hook_signal_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (free_needed && func_argv[2]) - free (func_argv[2]); return ret; } @@ -3214,8 +3194,8 @@ static VALUE weechat_ruby_api_hook_signal (VALUE class, VALUE signal, VALUE function, VALUE data) { - char *c_signal, *c_function, *c_data, *result; - VALUE return_value; + char *c_signal, *c_function, *c_data; + const char *result; API_INIT_FUNC(1, "hook_signal", API_RETURN_EMPTY); if (NIL_P (signal) || NIL_P (function) || NIL_P (data)) @@ -3236,7 +3216,7 @@ weechat_ruby_api_hook_signal (VALUE class, VALUE signal, VALUE function, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -3325,8 +3305,8 @@ static VALUE weechat_ruby_api_hook_hsignal (VALUE class, VALUE signal, VALUE function, VALUE data) { - char *c_signal, *c_function, *c_data, *result; - VALUE return_value; + char *c_signal, *c_function, *c_data; + const char *result; API_INIT_FUNC(1, "hook_hsignal", API_RETURN_EMPTY); if (NIL_P (signal) || NIL_P (function) || NIL_P (data)) @@ -3347,7 +3327,7 @@ weechat_ruby_api_hook_hsignal (VALUE class, VALUE signal, VALUE function, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -3420,8 +3400,8 @@ static VALUE weechat_ruby_api_hook_config (VALUE class, VALUE option, VALUE function, VALUE data) { - char *c_option, *c_function, *c_data, *result; - VALUE return_value; + char *c_option, *c_function, *c_data; + const char *result; API_INIT_FUNC(1, "hook_config", API_RETURN_EMPTY); if (NIL_P (option) || NIL_P (function) || NIL_P (data)) @@ -3442,7 +3422,7 @@ weechat_ruby_api_hook_config (VALUE class, VALUE option, VALUE function, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } char * @@ -3479,8 +3459,8 @@ static VALUE weechat_ruby_api_hook_modifier (VALUE class, VALUE modifier, VALUE function, VALUE data) { - char *c_modifier, *c_function, *c_data, *result; - VALUE return_value; + char *c_modifier, *c_function, *c_data; + const char *result; API_INIT_FUNC(1, "hook_modifier", API_RETURN_EMPTY); if (NIL_P (modifier) || NIL_P (function) || NIL_P (data)) @@ -3501,7 +3481,7 @@ weechat_ruby_api_hook_modifier (VALUE class, VALUE modifier, VALUE function, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -3535,7 +3515,7 @@ weechat_ruby_api_hook_info_cb (const void *pointer, void *data, { struct t_plugin_script *script; void *func_argv[3]; - char empty_arg[1] = { '\0' }; + char empty_arg[1] = { '\0' }, *result; const char *ptr_function, *ptr_data; script = (struct t_plugin_script *)pointer; @@ -3547,10 +3527,12 @@ weechat_ruby_api_hook_info_cb (const void *pointer, void *data, func_argv[1] = (info_name) ? (char *)info_name : empty_arg; func_argv[2] = (arguments) ? (char *)arguments : empty_arg; - return (const char *)weechat_ruby_exec (script, - WEECHAT_SCRIPT_EXEC_STRING, - ptr_function, - "sss", func_argv); + result = (char *)weechat_ruby_exec (script, + WEECHAT_SCRIPT_EXEC_STRING, + ptr_function, + "sss", func_argv); + + return API_STATIC_STRING(result); } return NULL; @@ -3561,8 +3543,8 @@ weechat_ruby_api_hook_info (VALUE class, VALUE info_name, VALUE description, VALUE args_description, VALUE function, VALUE data) { char *c_info_name, *c_description, *c_args_description, *c_function; - char *c_data, *result; - VALUE return_value; + char *c_data; + const char *result; API_INIT_FUNC(1, "hook_info", API_RETURN_EMPTY); if (NIL_P (info_name) || NIL_P (description) || NIL_P (args_description) @@ -3590,7 +3572,7 @@ weechat_ruby_api_hook_info (VALUE class, VALUE info_name, VALUE description, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_hashtable * @@ -3631,8 +3613,8 @@ weechat_ruby_api_hook_info_hashtable (VALUE class, VALUE info_name, { char *c_info_name, *c_description, *c_args_description; char *c_output_description, *c_function; - char *c_data, *result; - VALUE return_value; + char *c_data; + const char *result; API_INIT_FUNC(1, "hook_info_hashtable", API_RETURN_EMPTY); if (NIL_P (info_name) || NIL_P (description) || NIL_P (args_description) @@ -3663,7 +3645,7 @@ weechat_ruby_api_hook_info_hashtable (VALUE class, VALUE info_name, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_infolist * @@ -3684,18 +3666,15 @@ weechat_ruby_api_hook_infolist_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (infolist_name) ? (char *)infolist_name : empty_arg; - func_argv[2] = API_PTR2STR(obj_pointer); + func_argv[2] = (char *)API_PTR2STR(obj_pointer); func_argv[3] = (arguments) ? (char *)arguments : empty_arg; result = (struct t_infolist *)weechat_ruby_exec ( script, - WEECHAT_SCRIPT_EXEC_STRING, + WEECHAT_SCRIPT_EXEC_POINTER, ptr_function, "ssss", func_argv); - if (func_argv[2]) - free (func_argv[2]); - return result; } @@ -3709,8 +3688,8 @@ weechat_ruby_api_hook_infolist (VALUE class, VALUE infolist_name, VALUE data) { char *c_infolist_name, *c_description, *c_pointer_description; - char *c_args_description, *c_function, *c_data, *result; - VALUE return_value; + char *c_args_description, *c_function, *c_data; + const char *result; API_INIT_FUNC(1, "hook_infolist", API_RETURN_EMPTY); if (NIL_P (infolist_name) || NIL_P (description) @@ -3742,7 +3721,7 @@ weechat_ruby_api_hook_infolist (VALUE class, VALUE infolist_name, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_hashtable * @@ -3776,8 +3755,8 @@ static VALUE weechat_ruby_api_hook_focus (VALUE class, VALUE area, VALUE function, VALUE data) { - char *c_area, *c_function, *c_data, *result; - VALUE return_value; + char *c_area, *c_function, *c_data; + const char *result; API_INIT_FUNC(1, "hook_focus", API_RETURN_EMPTY); if (NIL_P (area) || NIL_P (function) || NIL_P (data)) @@ -3798,7 +3777,7 @@ weechat_ruby_api_hook_focus (VALUE class, VALUE area, VALUE function, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -3871,7 +3850,7 @@ weechat_ruby_api_buffer_input_data_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (input_data) ? (char *)input_data : empty_arg; rc = (int *) weechat_ruby_exec (script, @@ -3886,8 +3865,6 @@ weechat_ruby_api_buffer_input_data_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -3911,7 +3888,7 @@ weechat_ruby_api_buffer_close_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); rc = (int *) weechat_ruby_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -3925,8 +3902,6 @@ weechat_ruby_api_buffer_close_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -3940,8 +3915,8 @@ weechat_ruby_api_buffer_new (VALUE class, VALUE name, VALUE function_input, VALUE data_close) { char *c_name, *c_function_input, *c_data_input, *c_function_close; - char *c_data_close, *result; - VALUE return_value; + char *c_data_close; + const char *result; API_INIT_FUNC(1, "buffer_new", API_RETURN_EMPTY); if (NIL_P (name) || NIL_P (function_input) || NIL_P (data_input) @@ -3970,14 +3945,14 @@ weechat_ruby_api_buffer_new (VALUE class, VALUE name, VALUE function_input, c_function_close, c_data_close)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE weechat_ruby_api_buffer_search (VALUE class, VALUE plugin, VALUE name) { - char *c_plugin, *c_name, *result; - VALUE return_value; + char *c_plugin, *c_name; + const char *result; API_INIT_FUNC(1, "buffer_search", API_RETURN_EMPTY); if (NIL_P (plugin) || NIL_P (name)) @@ -3991,33 +3966,31 @@ weechat_ruby_api_buffer_search (VALUE class, VALUE plugin, VALUE name) result = API_PTR2STR(weechat_buffer_search (c_plugin, c_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE weechat_ruby_api_buffer_search_main (VALUE class) { - char *result; - VALUE return_value; + const char *result; API_INIT_FUNC(1, "buffer_search_main", API_RETURN_EMPTY); result = API_PTR2STR(weechat_buffer_search_main ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE weechat_ruby_api_current_buffer (VALUE class) { - char *result; - VALUE return_value; + const char *result; API_INIT_FUNC(1, "current_buffer", API_RETURN_EMPTY); result = API_PTR2STR(weechat_current_buffer ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -4145,8 +4118,8 @@ weechat_ruby_api_buffer_get_string (VALUE class, VALUE buffer, VALUE property) static VALUE weechat_ruby_api_buffer_get_pointer (VALUE class, VALUE buffer, VALUE property) { - char *c_buffer, *c_property, *result; - VALUE return_value; + char *c_buffer, *c_property; + const char *result; API_INIT_FUNC(1, "buffer_get_pointer", API_RETURN_EMPTY); if (NIL_P (buffer) || NIL_P (property)) @@ -4161,7 +4134,7 @@ weechat_ruby_api_buffer_get_pointer (VALUE class, VALUE buffer, VALUE property) result = API_PTR2STR(weechat_buffer_get_pointer (API_STR2PTR(c_buffer), c_property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -4235,21 +4208,20 @@ weechat_ruby_api_buffer_match_list (VALUE class, VALUE buffer, VALUE string) static VALUE weechat_ruby_api_current_window (VALUE class) { - char *result; - VALUE return_value; + const char *result; API_INIT_FUNC(1, "current_window", API_RETURN_EMPTY); result = API_PTR2STR(weechat_current_window ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE weechat_ruby_api_window_search_with_buffer (VALUE class, VALUE buffer) { - char *c_buffer, *result; - VALUE return_value; + char *c_buffer; + const char *result; API_INIT_FUNC(1, "window_search_with_buffer", API_RETURN_EMPTY); if (NIL_P (buffer)) @@ -4261,7 +4233,7 @@ weechat_ruby_api_window_search_with_buffer (VALUE class, VALUE buffer) result = API_PTR2STR(weechat_window_search_with_buffer (API_STR2PTR(c_buffer))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -4311,8 +4283,8 @@ weechat_ruby_api_window_get_string (VALUE class, VALUE window, VALUE property) static VALUE weechat_ruby_api_window_get_pointer (VALUE class, VALUE window, VALUE property) { - char *c_window, *c_property, *result; - VALUE return_value; + char *c_window, *c_property; + const char *result; API_INIT_FUNC(1, "window_get_pointer", API_RETURN_EMPTY); if (NIL_P (window) || NIL_P (property)) @@ -4327,7 +4299,7 @@ weechat_ruby_api_window_get_pointer (VALUE class, VALUE window, VALUE property) result = API_PTR2STR(weechat_window_get_pointer (API_STR2PTR(c_window), c_property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -4353,9 +4325,9 @@ weechat_ruby_api_nicklist_add_group (VALUE class, VALUE buffer, VALUE parent_group, VALUE name, VALUE color, VALUE visible) { - char *c_buffer, *c_parent_group, *c_name, *c_color, *result; + char *c_buffer, *c_parent_group, *c_name, *c_color; + const char *result; int c_visible; - VALUE return_value; API_INIT_FUNC(1, "nicklist_add_group", API_RETURN_EMPTY); if (NIL_P (buffer) || NIL_P (parent_group) || NIL_P (name) || NIL_P (color) @@ -4380,15 +4352,15 @@ weechat_ruby_api_nicklist_add_group (VALUE class, VALUE buffer, c_color, c_visible)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE weechat_ruby_api_nicklist_search_group (VALUE class, VALUE buffer, VALUE from_group, VALUE name) { - char *c_buffer, *c_from_group, *c_name, *result; - VALUE return_value; + char *c_buffer, *c_from_group, *c_name; + const char *result; API_INIT_FUNC(1, "nicklist_search_group", API_RETURN_EMPTY); if (NIL_P (buffer) || NIL_P (from_group) || NIL_P (name)) @@ -4406,7 +4378,7 @@ weechat_ruby_api_nicklist_search_group (VALUE class, VALUE buffer, API_STR2PTR(c_from_group), c_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -4415,9 +4387,8 @@ weechat_ruby_api_nicklist_add_nick (VALUE class, VALUE buffer, VALUE group, VALUE prefix_color, VALUE visible) { char *c_buffer, *c_group, *c_name, *c_color, *c_prefix, *c_prefix_color; - char *result; + const char *result; int c_visible; - VALUE return_value; API_INIT_FUNC(1, "nicklist_add_nick", API_RETURN_EMPTY); if (NIL_P (buffer) || NIL_P (group) || NIL_P (name) || NIL_P (color) @@ -4448,15 +4419,15 @@ weechat_ruby_api_nicklist_add_nick (VALUE class, VALUE buffer, VALUE group, c_prefix_color, c_visible)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE weechat_ruby_api_nicklist_search_nick (VALUE class, VALUE buffer, VALUE from_group, VALUE name) { - char *c_buffer, *c_from_group, *c_name, *result; - VALUE return_value; + char *c_buffer, *c_from_group, *c_name; + const char *result; API_INIT_FUNC(1, "nicklist_search_nick", API_RETURN_EMPTY); if (NIL_P (buffer) || NIL_P (from_group) || NIL_P (name)) @@ -4474,7 +4445,7 @@ weechat_ruby_api_nicklist_search_nick (VALUE class, VALUE buffer, API_STR2PTR(c_from_group), c_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -4593,8 +4564,8 @@ static VALUE weechat_ruby_api_nicklist_group_get_pointer (VALUE class, VALUE buffer, VALUE group, VALUE property) { - char *c_buffer, *c_group, *c_property, *result; - VALUE return_value; + char *c_buffer, *c_group, *c_property; + const char *result; API_INIT_FUNC(1, "nicklist_group_get_pointer", API_RETURN_EMPTY); if (NIL_P (buffer) || NIL_P (group) || NIL_P (property)) @@ -4612,7 +4583,7 @@ weechat_ruby_api_nicklist_group_get_pointer (VALUE class, VALUE buffer, API_STR2PTR(c_group), c_property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -4699,8 +4670,8 @@ static VALUE weechat_ruby_api_nicklist_nick_get_pointer (VALUE class, VALUE buffer, VALUE nick, VALUE property) { - char *c_buffer, *c_nick, *c_property, *result; - VALUE return_value; + char *c_buffer, *c_nick, *c_property; + const char *result; API_INIT_FUNC(1, "nicklist_nick_get_pointer", API_RETURN_EMPTY); if (NIL_P (buffer) || NIL_P (nick) || NIL_P (property)) @@ -4718,7 +4689,7 @@ weechat_ruby_api_nicklist_nick_get_pointer (VALUE class, VALUE buffer, API_STR2PTR(c_nick), c_property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -4752,8 +4723,8 @@ weechat_ruby_api_nicklist_nick_set (VALUE class, VALUE buffer, VALUE nick, static VALUE weechat_ruby_api_bar_item_search (VALUE class, VALUE name) { - char *c_name, *result; - VALUE return_value; + char *c_name; + const char *result; API_INIT_FUNC(1, "bar_item_search", API_RETURN_EMPTY); if (NIL_P (name)) @@ -4765,7 +4736,7 @@ weechat_ruby_api_bar_item_search (VALUE class, VALUE name) result = API_PTR2STR(weechat_bar_item_search (c_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } char * @@ -4789,39 +4760,27 @@ weechat_ruby_api_bar_item_build_cb (const void *pointer, void *data, { /* new callback: data, item, window, buffer, extra_info */ func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(item); - func_argv[2] = API_PTR2STR(window); - func_argv[3] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(item); + func_argv[2] = (char *)API_PTR2STR(window); + func_argv[3] = (char *)API_PTR2STR(buffer); func_argv[4] = extra_info; ret = (char *)weechat_ruby_exec (script, WEECHAT_SCRIPT_EXEC_STRING, ptr_function + 7, "ssssh", func_argv); - - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); } else { /* old callback: data, item, window */ func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(item); - func_argv[2] = API_PTR2STR(window); + func_argv[1] = (char *)API_PTR2STR(item); + func_argv[2] = (char *)API_PTR2STR(window); ret = (char *)weechat_ruby_exec (script, WEECHAT_SCRIPT_EXEC_STRING, ptr_function, "sss", func_argv); - - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); } return ret; @@ -4834,8 +4793,8 @@ static VALUE weechat_ruby_api_bar_item_new (VALUE class, VALUE name, VALUE function, VALUE data) { - char *c_name, *c_function, *c_data, *result; - VALUE return_value; + char *c_name, *c_function, *c_data; + const char *result; API_INIT_FUNC(1, "bar_item_new", API_RETURN_EMPTY); if (NIL_P (name) || NIL_P (function) || NIL_P (data)) @@ -4856,7 +4815,7 @@ weechat_ruby_api_bar_item_new (VALUE class, VALUE name, VALUE function, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -4898,8 +4857,8 @@ weechat_ruby_api_bar_item_remove (VALUE class, VALUE item) static VALUE weechat_ruby_api_bar_search (VALUE class, VALUE name) { - char *c_name, *result; - VALUE return_value; + char *c_name; + const char *result; API_INIT_FUNC(1, "bar_search", API_RETURN_EMPTY); if (NIL_P (name)) @@ -4911,7 +4870,7 @@ weechat_ruby_api_bar_search (VALUE class, VALUE name) result = API_PTR2STR(weechat_bar_search (c_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -4925,8 +4884,7 @@ weechat_ruby_api_bar_new (VALUE class, VALUE name, VALUE hidden, char *c_name, *c_hidden, *c_priority, *c_type, *c_conditions, *c_position; char *c_filling_top_bottom, *c_filling_left_right, *c_size, *c_size_max; char *c_color_fg, *c_color_delim, *c_color_bg, *c_separator, *c_items; - char *result; - VALUE return_value; + const char *result; API_INIT_FUNC(1, "bar_new", API_RETURN_EMPTY); if (NIL_P (name) || NIL_P (hidden) || NIL_P (priority) || NIL_P (type) @@ -4984,7 +4942,7 @@ weechat_ruby_api_bar_new (VALUE class, VALUE name, VALUE hidden, c_separator, c_items)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -5126,21 +5084,20 @@ weechat_ruby_api_info_get_hashtable (VALUE class, VALUE info_name, static VALUE weechat_ruby_api_infolist_new (VALUE class) { - char *result; - VALUE return_value; + const char *result; API_INIT_FUNC(1, "infolist_new", API_RETURN_EMPTY); result = API_PTR2STR(weechat_infolist_new ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE weechat_ruby_api_infolist_new_item (VALUE class, VALUE infolist) { - char *c_infolist, *result; - VALUE return_value; + char *c_infolist; + const char *result; API_INIT_FUNC(1, "infolist_new_item", API_RETURN_EMPTY); if (NIL_P (infolist)) @@ -5152,16 +5109,16 @@ weechat_ruby_api_infolist_new_item (VALUE class, VALUE infolist) result = API_PTR2STR(weechat_infolist_new_item (API_STR2PTR(c_infolist))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE weechat_ruby_api_infolist_new_var_integer (VALUE class, VALUE item, VALUE name, VALUE value) { - char *c_item, *c_name, *result; + char *c_item, *c_name; + const char *result; int c_value; - VALUE return_value; API_INIT_FUNC(1, "infolist_new_var_integer", API_RETURN_EMPTY); if (NIL_P (item) || NIL_P (name) || NIL_P (value)) @@ -5179,15 +5136,15 @@ weechat_ruby_api_infolist_new_var_integer (VALUE class, VALUE item, c_name, c_value)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE weechat_ruby_api_infolist_new_var_string (VALUE class, VALUE item, VALUE name, VALUE value) { - char *c_item, *c_name, *c_value, *result; - VALUE return_value; + char *c_item, *c_name, *c_value; + const char *result; API_INIT_FUNC(1, "infolist_new_var_string", API_RETURN_EMPTY); if (NIL_P (item) || NIL_P (name) || NIL_P (value)) @@ -5205,15 +5162,15 @@ weechat_ruby_api_infolist_new_var_string (VALUE class, VALUE item, c_name, c_value)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE weechat_ruby_api_infolist_new_var_pointer (VALUE class, VALUE item, VALUE name, VALUE value) { - char *c_item, *c_name, *c_value, *result; - VALUE return_value; + char *c_item, *c_name, *c_value; + const char *result; API_INIT_FUNC(1, "infolist_new_var_pointer", API_RETURN_EMPTY); if (NIL_P (item) || NIL_P (name) || NIL_P (value)) @@ -5231,16 +5188,16 @@ weechat_ruby_api_infolist_new_var_pointer (VALUE class, VALUE item, c_name, API_STR2PTR(c_value))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE weechat_ruby_api_infolist_new_var_time (VALUE class, VALUE item, VALUE name, VALUE value) { - char *c_item, *c_name, *result; + char *c_item, *c_name; + const char *result; int c_value; - VALUE return_value; API_INIT_FUNC(1, "infolist_new_var_time", API_RETURN_EMPTY); if (NIL_P (item) || NIL_P (name) || NIL_P (value)) @@ -5258,14 +5215,14 @@ weechat_ruby_api_infolist_new_var_time (VALUE class, VALUE item, c_name, c_value)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE weechat_ruby_api_infolist_search_var (VALUE class, VALUE infolist, VALUE name) { - char *c_infolist, *c_name, *result; - VALUE return_value; + char *c_infolist, *c_name; + const char *result; API_INIT_FUNC(1, "infolist_search_var", API_RETURN_EMPTY); if (NIL_P (infolist) || NIL_P (name)) @@ -5280,15 +5237,15 @@ weechat_ruby_api_infolist_search_var (VALUE class, VALUE infolist, VALUE name) result = API_PTR2STR(weechat_infolist_search_var (API_STR2PTR(c_infolist), c_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE weechat_ruby_api_infolist_get (VALUE class, VALUE name, VALUE pointer, VALUE arguments) { - char *c_name, *c_pointer, *c_arguments, *result; - VALUE return_value; + char *c_name, *c_pointer, *c_arguments; + const char *result; API_INIT_FUNC(1, "infolist_get", API_RETURN_EMPTY); if (NIL_P (name) || NIL_P (pointer) || NIL_P (arguments)) @@ -5306,7 +5263,7 @@ weechat_ruby_api_infolist_get (VALUE class, VALUE name, VALUE pointer, API_STR2PTR(c_pointer), c_arguments)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -5429,8 +5386,8 @@ weechat_ruby_api_infolist_string (VALUE class, VALUE infolist, VALUE variable) static VALUE weechat_ruby_api_infolist_pointer (VALUE class, VALUE infolist, VALUE variable) { - char *c_infolist, *c_variable, *result; - VALUE return_value; + char *c_infolist, *c_variable; + const char *result; API_INIT_FUNC(1, "infolist_pointer", API_RETURN_EMPTY); if (NIL_P (infolist) || NIL_P (variable)) @@ -5444,20 +5401,18 @@ weechat_ruby_api_infolist_pointer (VALUE class, VALUE infolist, VALUE variable) result = API_PTR2STR(weechat_infolist_pointer (API_STR2PTR(c_infolist), c_variable)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE weechat_ruby_api_infolist_time (VALUE class, VALUE infolist, VALUE variable) { - char *c_infolist, *c_variable, timebuffer[64], *result; + char *c_infolist, *c_variable; time_t time; - struct tm *date_tmp; - VALUE return_value; - API_INIT_FUNC(1, "infolist_time", API_RETURN_EMPTY); + API_INIT_FUNC(1, "infolist_time", API_RETURN_LONG(0)); if (NIL_P (infolist) || NIL_P (variable)) - API_WRONG_ARGS(API_RETURN_EMPTY); + API_WRONG_ARGS(API_RETURN_LONG(0)); Check_Type (infolist, T_STRING); Check_Type (variable, T_STRING); @@ -5465,14 +5420,9 @@ weechat_ruby_api_infolist_time (VALUE class, VALUE infolist, VALUE variable) c_infolist = StringValuePtr (infolist); c_variable = StringValuePtr (variable); - timebuffer[0] = '\0'; time = weechat_infolist_time (API_STR2PTR(c_infolist), c_variable); - date_tmp = localtime (&time); - if (date_tmp) - strftime (timebuffer, sizeof (timebuffer), "%F %T", date_tmp); - result = strdup (timebuffer); - API_RETURN_STRING_FREE(result); + API_RETURN_LONG(time); } static VALUE @@ -5496,8 +5446,8 @@ weechat_ruby_api_infolist_free (VALUE class, VALUE infolist) static VALUE weechat_ruby_api_hdata_get (VALUE class, VALUE name) { - char *c_name, *result; - VALUE return_value; + char *c_name; + const char *result; API_INIT_FUNC(1, "hdata_get", API_RETURN_EMPTY); if (NIL_P (name)) @@ -5509,7 +5459,7 @@ weechat_ruby_api_hdata_get (VALUE class, VALUE name) result = API_PTR2STR(weechat_hdata_get (c_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -5631,8 +5581,8 @@ weechat_ruby_api_hdata_get_var_hdata (VALUE class, VALUE hdata, VALUE name) static VALUE weechat_ruby_api_hdata_get_list (VALUE class, VALUE hdata, VALUE name) { - char *c_hdata, *c_name, *result; - VALUE return_value; + char *c_hdata, *c_name; + const char *result; API_INIT_FUNC(1, "hdata_get_list", API_RETURN_EMPTY); if (NIL_P (hdata) || NIL_P (name)) @@ -5647,7 +5597,7 @@ weechat_ruby_api_hdata_get_list (VALUE class, VALUE hdata, VALUE name) result = API_PTR2STR(weechat_hdata_get_list (API_STR2PTR(c_hdata), c_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -5680,9 +5630,9 @@ static VALUE weechat_ruby_api_hdata_move (VALUE class, VALUE hdata, VALUE pointer, VALUE count) { - char *c_hdata, *c_pointer, *result; + char *c_hdata, *c_pointer; + const char *result; int c_count; - VALUE return_value; API_INIT_FUNC(1, "hdata_move", API_RETURN_EMPTY); if (NIL_P (hdata) || NIL_P (pointer) || NIL_P (count)) @@ -5700,16 +5650,16 @@ weechat_ruby_api_hdata_move (VALUE class, VALUE hdata, VALUE pointer, API_STR2PTR(c_pointer), c_count)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE weechat_ruby_api_hdata_search (VALUE class, VALUE hdata, VALUE pointer, VALUE search, VALUE move) { - char *c_hdata, *c_pointer, *c_search, *result; + char *c_hdata, *c_pointer, *c_search; + const char *result; int c_move; - VALUE return_value; API_INIT_FUNC(1, "hdata_search", API_RETURN_EMPTY); if (NIL_P (hdata) || NIL_P (pointer) || NIL_P (search) || NIL_P (move)) @@ -5730,7 +5680,7 @@ weechat_ruby_api_hdata_search (VALUE class, VALUE hdata, VALUE pointer, c_search, c_move)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -5841,8 +5791,8 @@ static VALUE weechat_ruby_api_hdata_pointer (VALUE class, VALUE hdata, VALUE pointer, VALUE name) { - char *c_hdata, *c_pointer, *c_name, *result; - VALUE return_value; + char *c_hdata, *c_pointer, *c_name; + const char *result; API_INIT_FUNC(1, "hdata_pointer", API_RETURN_EMPTY); if (NIL_P (hdata) || NIL_P (pointer) || NIL_P (name)) @@ -5860,7 +5810,7 @@ weechat_ruby_api_hdata_pointer (VALUE class, VALUE hdata, VALUE pointer, API_STR2PTR(c_pointer), c_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -6025,9 +5975,9 @@ weechat_ruby_api_upgrade_read_cb (const void *pointer, void *data, snprintf (str_object_id, sizeof (str_object_id), "%d", object_id); func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(upgrade_file); + func_argv[1] = (char *)API_PTR2STR(upgrade_file); func_argv[2] = str_object_id; - func_argv[3] = API_PTR2STR(infolist); + func_argv[3] = (char *)API_PTR2STR(infolist); rc = (int *) weechat_ruby_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -6041,10 +5991,6 @@ weechat_ruby_api_upgrade_read_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -6056,8 +6002,8 @@ static VALUE weechat_ruby_api_upgrade_new (VALUE class, VALUE filename, VALUE function, VALUE data) { - char *c_filename, *c_function, *c_data, *result; - VALUE return_value; + char *c_filename, *c_function, *c_data; + const char *result; API_INIT_FUNC(1, "upgrade_new", API_RETURN_EMPTY); if (NIL_P (filename) || NIL_P (function) || NIL_P (data)) @@ -6080,7 +6026,7 @@ weechat_ruby_api_upgrade_new (VALUE class, VALUE filename, VALUE function, c_function, c_data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } static VALUE @@ -6153,52 +6099,52 @@ weechat_ruby_api_upgrade_close (VALUE class, VALUE upgrade_file) void weechat_ruby_api_init (VALUE ruby_mWeechat) { - rb_define_const(ruby_mWeechat, "WEECHAT_RC_OK", INT2NUM(WEECHAT_RC_OK)); - rb_define_const(ruby_mWeechat, "WEECHAT_RC_OK_EAT", INT2NUM(WEECHAT_RC_OK_EAT)); - rb_define_const(ruby_mWeechat, "WEECHAT_RC_ERROR", INT2NUM(WEECHAT_RC_ERROR)); - - rb_define_const(ruby_mWeechat, "WEECHAT_CONFIG_READ_OK", INT2NUM(WEECHAT_CONFIG_READ_OK)); - rb_define_const(ruby_mWeechat, "WEECHAT_CONFIG_READ_MEMORY_ERROR", INT2NUM(WEECHAT_CONFIG_READ_MEMORY_ERROR)); - rb_define_const(ruby_mWeechat, "WEECHAT_CONFIG_READ_FILE_NOT_FOUND", INT2NUM(WEECHAT_CONFIG_READ_FILE_NOT_FOUND)); - rb_define_const(ruby_mWeechat, "WEECHAT_CONFIG_WRITE_OK", INT2NUM(WEECHAT_CONFIG_WRITE_OK)); - rb_define_const(ruby_mWeechat, "WEECHAT_CONFIG_WRITE_ERROR", INT2NUM(WEECHAT_CONFIG_WRITE_ERROR)); - rb_define_const(ruby_mWeechat, "WEECHAT_CONFIG_WRITE_MEMORY_ERROR", INT2NUM(WEECHAT_CONFIG_WRITE_MEMORY_ERROR)); - rb_define_const(ruby_mWeechat, "WEECHAT_CONFIG_OPTION_SET_OK_CHANGED", INT2NUM(WEECHAT_CONFIG_OPTION_SET_OK_CHANGED)); - rb_define_const(ruby_mWeechat, "WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE", INT2NUM(WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE)); - rb_define_const(ruby_mWeechat, "WEECHAT_CONFIG_OPTION_SET_ERROR", INT2NUM(WEECHAT_CONFIG_OPTION_SET_ERROR)); - rb_define_const(ruby_mWeechat, "WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND", INT2NUM(WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND)); - rb_define_const(ruby_mWeechat, "WEECHAT_CONFIG_OPTION_UNSET_OK_NO_RESET", INT2NUM(WEECHAT_CONFIG_OPTION_UNSET_OK_NO_RESET)); - rb_define_const(ruby_mWeechat, "WEECHAT_CONFIG_OPTION_UNSET_OK_RESET", INT2NUM(WEECHAT_CONFIG_OPTION_UNSET_OK_RESET)); - rb_define_const(ruby_mWeechat, "WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED", INT2NUM(WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED)); - rb_define_const(ruby_mWeechat, "WEECHAT_CONFIG_OPTION_UNSET_ERROR", INT2NUM(WEECHAT_CONFIG_OPTION_UNSET_ERROR)); - - rb_define_const(ruby_mWeechat, "WEECHAT_LIST_POS_SORT", rb_str_new2(WEECHAT_LIST_POS_SORT)); - rb_define_const(ruby_mWeechat, "WEECHAT_LIST_POS_BEGINNING", rb_str_new2(WEECHAT_LIST_POS_BEGINNING)); - rb_define_const(ruby_mWeechat, "WEECHAT_LIST_POS_END", rb_str_new2(WEECHAT_LIST_POS_END)); - - rb_define_const(ruby_mWeechat, "WEECHAT_HOTLIST_LOW", rb_str_new2(WEECHAT_HOTLIST_LOW)); - rb_define_const(ruby_mWeechat, "WEECHAT_HOTLIST_MESSAGE", rb_str_new2(WEECHAT_HOTLIST_MESSAGE)); - rb_define_const(ruby_mWeechat, "WEECHAT_HOTLIST_PRIVATE", rb_str_new2(WEECHAT_HOTLIST_PRIVATE)); - rb_define_const(ruby_mWeechat, "WEECHAT_HOTLIST_HIGHLIGHT", rb_str_new2(WEECHAT_HOTLIST_HIGHLIGHT)); - - rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_PROCESS_RUNNING", INT2NUM(WEECHAT_HOOK_PROCESS_RUNNING)); - rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_PROCESS_ERROR", INT2NUM(WEECHAT_HOOK_PROCESS_ERROR)); - - rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_CONNECT_OK", INT2NUM(WEECHAT_HOOK_CONNECT_OK)); - rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND", INT2NUM(WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND)); - rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND", INT2NUM(WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND)); - rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED", INT2NUM(WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED)); - rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_CONNECT_PROXY_ERROR", INT2NUM(WEECHAT_HOOK_CONNECT_PROXY_ERROR)); - rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR", INT2NUM(WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR)); - rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_CONNECT_GNUTLS_INIT_ERROR", INT2NUM(WEECHAT_HOOK_CONNECT_GNUTLS_INIT_ERROR)); - rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR", INT2NUM(WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR)); - rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_CONNECT_MEMORY_ERROR", INT2NUM(WEECHAT_HOOK_CONNECT_MEMORY_ERROR)); - rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_CONNECT_TIMEOUT", INT2NUM(WEECHAT_HOOK_CONNECT_TIMEOUT)); - rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_CONNECT_SOCKET_ERROR", INT2NUM(WEECHAT_HOOK_CONNECT_SOCKET_ERROR)); - - rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_SIGNAL_STRING", rb_str_new2(WEECHAT_HOOK_SIGNAL_STRING)); - rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_SIGNAL_INT", rb_str_new2(WEECHAT_HOOK_SIGNAL_INT)); - rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_SIGNAL_POINTER", rb_str_new2(WEECHAT_HOOK_SIGNAL_POINTER)); + rb_define_const (ruby_mWeechat, "WEECHAT_RC_OK", INT2NUM(WEECHAT_RC_OK)); + rb_define_const (ruby_mWeechat, "WEECHAT_RC_OK_EAT", INT2NUM(WEECHAT_RC_OK_EAT)); + rb_define_const (ruby_mWeechat, "WEECHAT_RC_ERROR", INT2NUM(WEECHAT_RC_ERROR)); + + rb_define_const (ruby_mWeechat, "WEECHAT_CONFIG_READ_OK", INT2NUM(WEECHAT_CONFIG_READ_OK)); + rb_define_const (ruby_mWeechat, "WEECHAT_CONFIG_READ_MEMORY_ERROR", INT2NUM(WEECHAT_CONFIG_READ_MEMORY_ERROR)); + rb_define_const (ruby_mWeechat, "WEECHAT_CONFIG_READ_FILE_NOT_FOUND", INT2NUM(WEECHAT_CONFIG_READ_FILE_NOT_FOUND)); + rb_define_const (ruby_mWeechat, "WEECHAT_CONFIG_WRITE_OK", INT2NUM(WEECHAT_CONFIG_WRITE_OK)); + rb_define_const (ruby_mWeechat, "WEECHAT_CONFIG_WRITE_ERROR", INT2NUM(WEECHAT_CONFIG_WRITE_ERROR)); + rb_define_const (ruby_mWeechat, "WEECHAT_CONFIG_WRITE_MEMORY_ERROR", INT2NUM(WEECHAT_CONFIG_WRITE_MEMORY_ERROR)); + rb_define_const (ruby_mWeechat, "WEECHAT_CONFIG_OPTION_SET_OK_CHANGED", INT2NUM(WEECHAT_CONFIG_OPTION_SET_OK_CHANGED)); + rb_define_const (ruby_mWeechat, "WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE", INT2NUM(WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE)); + rb_define_const (ruby_mWeechat, "WEECHAT_CONFIG_OPTION_SET_ERROR", INT2NUM(WEECHAT_CONFIG_OPTION_SET_ERROR)); + rb_define_const (ruby_mWeechat, "WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND", INT2NUM(WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND)); + rb_define_const (ruby_mWeechat, "WEECHAT_CONFIG_OPTION_UNSET_OK_NO_RESET", INT2NUM(WEECHAT_CONFIG_OPTION_UNSET_OK_NO_RESET)); + rb_define_const (ruby_mWeechat, "WEECHAT_CONFIG_OPTION_UNSET_OK_RESET", INT2NUM(WEECHAT_CONFIG_OPTION_UNSET_OK_RESET)); + rb_define_const (ruby_mWeechat, "WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED", INT2NUM(WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED)); + rb_define_const (ruby_mWeechat, "WEECHAT_CONFIG_OPTION_UNSET_ERROR", INT2NUM(WEECHAT_CONFIG_OPTION_UNSET_ERROR)); + + rb_define_const (ruby_mWeechat, "WEECHAT_LIST_POS_SORT", rb_str_new2 (WEECHAT_LIST_POS_SORT)); + rb_define_const (ruby_mWeechat, "WEECHAT_LIST_POS_BEGINNING", rb_str_new2 (WEECHAT_LIST_POS_BEGINNING)); + rb_define_const (ruby_mWeechat, "WEECHAT_LIST_POS_END", rb_str_new2 (WEECHAT_LIST_POS_END)); + + rb_define_const (ruby_mWeechat, "WEECHAT_HOTLIST_LOW", rb_str_new2 (WEECHAT_HOTLIST_LOW)); + rb_define_const (ruby_mWeechat, "WEECHAT_HOTLIST_MESSAGE", rb_str_new2 (WEECHAT_HOTLIST_MESSAGE)); + rb_define_const (ruby_mWeechat, "WEECHAT_HOTLIST_PRIVATE", rb_str_new2 (WEECHAT_HOTLIST_PRIVATE)); + rb_define_const (ruby_mWeechat, "WEECHAT_HOTLIST_HIGHLIGHT", rb_str_new2 (WEECHAT_HOTLIST_HIGHLIGHT)); + + rb_define_const (ruby_mWeechat, "WEECHAT_HOOK_PROCESS_RUNNING", INT2NUM(WEECHAT_HOOK_PROCESS_RUNNING)); + rb_define_const (ruby_mWeechat, "WEECHAT_HOOK_PROCESS_ERROR", INT2NUM(WEECHAT_HOOK_PROCESS_ERROR)); + + rb_define_const (ruby_mWeechat, "WEECHAT_HOOK_CONNECT_OK", INT2NUM(WEECHAT_HOOK_CONNECT_OK)); + rb_define_const (ruby_mWeechat, "WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND", INT2NUM(WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND)); + rb_define_const (ruby_mWeechat, "WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND", INT2NUM(WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND)); + rb_define_const (ruby_mWeechat, "WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED", INT2NUM(WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED)); + rb_define_const (ruby_mWeechat, "WEECHAT_HOOK_CONNECT_PROXY_ERROR", INT2NUM(WEECHAT_HOOK_CONNECT_PROXY_ERROR)); + rb_define_const (ruby_mWeechat, "WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR", INT2NUM(WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR)); + rb_define_const (ruby_mWeechat, "WEECHAT_HOOK_CONNECT_GNUTLS_INIT_ERROR", INT2NUM(WEECHAT_HOOK_CONNECT_GNUTLS_INIT_ERROR)); + rb_define_const (ruby_mWeechat, "WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR", INT2NUM(WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR)); + rb_define_const (ruby_mWeechat, "WEECHAT_HOOK_CONNECT_MEMORY_ERROR", INT2NUM(WEECHAT_HOOK_CONNECT_MEMORY_ERROR)); + rb_define_const (ruby_mWeechat, "WEECHAT_HOOK_CONNECT_TIMEOUT", INT2NUM(WEECHAT_HOOK_CONNECT_TIMEOUT)); + rb_define_const (ruby_mWeechat, "WEECHAT_HOOK_CONNECT_SOCKET_ERROR", INT2NUM(WEECHAT_HOOK_CONNECT_SOCKET_ERROR)); + + rb_define_const (ruby_mWeechat, "WEECHAT_HOOK_SIGNAL_STRING", rb_str_new2 (WEECHAT_HOOK_SIGNAL_STRING)); + rb_define_const (ruby_mWeechat, "WEECHAT_HOOK_SIGNAL_INT", rb_str_new2 (WEECHAT_HOOK_SIGNAL_INT)); + rb_define_const (ruby_mWeechat, "WEECHAT_HOOK_SIGNAL_POINTER", rb_str_new2 (WEECHAT_HOOK_SIGNAL_POINTER)); API_DEF_FUNC(register, 7); API_DEF_FUNC(plugin_get_name, 1); @@ -6212,6 +6158,7 @@ weechat_ruby_api_init (VALUE ruby_mWeechat) API_DEF_FUNC(string_has_highlight, 2); API_DEF_FUNC(string_has_highlight_regex, 2); API_DEF_FUNC(string_mask_to_regex, 1); + API_DEF_FUNC(string_format_size, 1); API_DEF_FUNC(string_remove_color, 2); API_DEF_FUNC(string_is_command_char, 1); API_DEF_FUNC(string_input_for_buffer, 1); diff --git a/src/plugins/ruby/weechat-ruby-api.h b/src/plugins/ruby/weechat-ruby-api.h index 39e43ee06..2f3874427 100644 --- a/src/plugins/ruby/weechat-ruby-api.h +++ b/src/plugins/ruby/weechat-ruby-api.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2007 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RUBY_API_H -#define WEECHAT_RUBY_API_H 1 +#ifndef WEECHAT_PLUGIN_RUBY_API_H +#define WEECHAT_PLUGIN_RUBY_API_H extern int weechat_ruby_api_buffer_input_data_cb (const void *pointer, void *data, @@ -30,4 +30,4 @@ extern int weechat_ruby_api_buffer_close_cb (const void *pointer, struct t_gui_buffer *buffer); extern void weechat_ruby_api_init (VALUE ruby_mWeechat); -#endif /* WEECHAT_RUBY_API_H */ +#endif /* WEECHAT_PLUGIN_RUBY_API_H */ diff --git a/src/plugins/ruby/weechat-ruby.c b/src/plugins/ruby/weechat-ruby.c index 09462cd56..09aa122d5 100644 --- a/src/plugins/ruby/weechat-ruby.c +++ b/src/plugins/ruby/weechat-ruby.c @@ -1,7 +1,7 @@ /* * weechat-ruby.c - ruby plugin for WeeChat * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2007 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -61,18 +61,43 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Support of ruby scripts")); WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(3000); +WEECHAT_PLUGIN_PRIORITY(4000); struct t_weechat_plugin *weechat_ruby_plugin = NULL; +struct t_plugin_script_data ruby_data; + +struct t_config_file *ruby_config_file = NULL; +struct t_config_option *ruby_config_look_check_license = NULL; +struct t_config_option *ruby_config_look_eval_keep_context = NULL; + int ruby_quiet = 0; int ruby_hide_errors = 0; + +struct t_plugin_script *ruby_script_eval = NULL; +int ruby_eval_mode = 0; +int ruby_eval_send_input = 0; +int ruby_eval_exec_commands = 0; +struct t_gui_buffer *ruby_eval_buffer = NULL; +char *ruby_eval_output = NULL; +#define RUBY_EVAL_SCRIPT \ + "def weechat_init\n" \ + " Weechat.register('" WEECHAT_SCRIPT_EVAL_NAME "', '', '1.0', " \ + "'" WEECHAT_LICENSE "', 'Evaluation of source code', '', '')\n" \ + " return Weechat::WEECHAT_RC_OK\n" \ + "end\n" \ + "\n" \ + "def script_ruby_eval(code)\n" \ + " module_eval(code)\n" \ + "end\n" + struct t_plugin_script *ruby_scripts = NULL; struct t_plugin_script *last_ruby_script = NULL; struct t_plugin_script *ruby_current_script = NULL; struct t_plugin_script *ruby_registered_script = NULL; const char *ruby_current_script_filename = NULL; VALUE ruby_current_module; +char **ruby_buffer_output = NULL; /* * string used to execute action "install": @@ -103,8 +128,6 @@ VALUE ruby_mWeechat, ruby_mWeechatOutputs; #define MOD_NAME_PREFIX "WeechatRubyModule" int ruby_num = 0; -char ruby_buffer_output[128]; - typedef struct protect_call_arg { VALUE recv; ID mid; @@ -169,16 +192,16 @@ weechat_ruby_hash_foreach_cb (VALUE key, VALUE value, void *arg) type_values = weechat_hashtable_get_string (hashtable, "type_values"); if (strcmp (type_values, WEECHAT_HASHTABLE_STRING) == 0) { - weechat_hashtable_set (hashtable, StringValuePtr(key), - StringValuePtr(value)); + weechat_hashtable_set (hashtable, StringValuePtr (key), + StringValuePtr (value)); } else if (strcmp (type_values, WEECHAT_HASHTABLE_POINTER) == 0) { - weechat_hashtable_set (hashtable, StringValuePtr(key), + weechat_hashtable_set (hashtable, StringValuePtr (key), plugin_script_str2ptr ( weechat_ruby_plugin, NULL, NULL, - StringValuePtr(value))); + StringValuePtr (value))); } } @@ -252,30 +275,30 @@ weechat_ruby_print_exception (VALUE err) char* err_msg; char* err_class; - backtrace = rb_protect_funcall (err, rb_intern("backtrace"), + backtrace = rb_protect_funcall (err, rb_intern ("backtrace"), &ruby_error, 0, NULL); - tmp1 = rb_protect_funcall(err, rb_intern("message"), &ruby_error, 0, NULL); - err_msg = StringValueCStr(tmp1); + tmp1 = rb_protect_funcall(err, rb_intern ("message"), &ruby_error, 0, NULL); + err_msg = StringValueCStr (tmp1); - tmp2 = rb_protect_funcall(rb_protect_funcall(err, rb_intern("class"), - &ruby_error, 0, NULL), - rb_intern("name"), &ruby_error, 0, NULL); - err_class = StringValuePtr(tmp2); + tmp2 = rb_protect_funcall (rb_protect_funcall (err, rb_intern ("class"), + &ruby_error, 0, NULL), + rb_intern ("name"), &ruby_error, 0, NULL); + err_class = StringValuePtr (tmp2); if (strcmp (err_class, "SyntaxError") == 0) { - tmp3 = rb_inspect(err); + tmp3 = rb_inspect (err); weechat_printf (NULL, weechat_gettext ("%s%s: error: %s"), weechat_prefix ("error"), RUBY_PLUGIN_NAME, - StringValuePtr(tmp3)); + StringValuePtr (tmp3)); } else { for (i = 0; i < RARRAY_LEN(backtrace); i++) { - line = StringValuePtr(RARRAY_PTR(backtrace)[i]); + line = StringValuePtr (RARRAY_PTR(backtrace)[i]); cline = NULL; if (i == 0) { @@ -294,8 +317,8 @@ weechat_ruby_print_exception (VALUE err) } else { - cline = (char *)calloc(strlen (line) + strlen (" from ") + 1, - sizeof (char)); + cline = (char *)calloc (strlen (line) + strlen (" from ") + 1, + sizeof (char)); if (cline) { strcat (cline, " from "); @@ -319,6 +342,117 @@ weechat_ruby_print_exception (VALUE err) } /* + * Function used for compatibility. + */ + +static VALUE +weechat_ruby_output_flush_ruby (VALUE self) +{ + /* make C compiler happy */ + (void) self; + + return Qnil; +} + +/* + * Flushes output. + */ + +void +weechat_ruby_output_flush () +{ + const char *ptr_command; + char *command; + int length; + + if (!*ruby_buffer_output[0]) + return; + + if (ruby_eval_mode) + { + /* if there's no buffer, we catch the output, so there's no flush */ + if (!ruby_eval_buffer) + return; + + if (ruby_eval_send_input) + { + if (ruby_eval_exec_commands) + ptr_command = *ruby_buffer_output; + else + ptr_command = weechat_string_input_for_buffer (*ruby_buffer_output); + if (ptr_command) + { + weechat_command (ruby_eval_buffer, *ruby_buffer_output); + } + else + { + length = 1 + strlen (*ruby_buffer_output) + 1; + command = malloc (length); + if (command) + { + snprintf (command, length, "%c%s", + *ruby_buffer_output[0], *ruby_buffer_output); + weechat_command (ruby_eval_buffer, + (command[0]) ? command : " "); + free (command); + } + } + } + else + { + weechat_printf (ruby_eval_buffer, "%s", *ruby_buffer_output); + } + } + else + { + /* script (no eval mode) */ + weechat_printf ( + NULL, + weechat_gettext ("%s: stdout/stderr (%s): %s"), + RUBY_PLUGIN_NAME, + (ruby_current_script) ? ruby_current_script->name : "?", + *ruby_buffer_output); + } + + weechat_string_dyn_copy (ruby_buffer_output, NULL); +} + +/* + * Redirection for stdout and stderr. + */ + +static VALUE +weechat_ruby_output (VALUE self, VALUE str) +{ + char *msg, *m, *p; + + /* make C compiler happy */ + (void) self; + + if (ruby_hide_errors) + return Qnil; + + msg = strdup (StringValuePtr (str)); + + m = msg; + while ((p = strchr (m, '\n')) != NULL) + { + *p = '\0'; + weechat_string_dyn_concat (ruby_buffer_output, m); + weechat_ruby_output_flush (); + *p = '\n'; + m = ++p; + } + + weechat_string_dyn_concat (ruby_buffer_output, m); + + if (msg) + free (msg); + + return Qnil; +} + +/* * Executes a ruby function. */ @@ -333,6 +467,8 @@ weechat_ruby_exec (struct t_plugin_script *script, void *ret_value; struct t_plugin_script *old_ruby_current_script; + ret_value = NULL; + old_ruby_current_script = ruby_current_script; ruby_current_script = script; @@ -360,24 +496,26 @@ weechat_ruby_exec (struct t_plugin_script *script, if (argc > 0) { rc = rb_protect_funcall ((VALUE) script->interpreter, - rb_intern(function), + rb_intern (function), &ruby_error, argc, argv2); } else { rc = rb_protect_funcall ((VALUE) script->interpreter, - rb_intern(function), + rb_intern (function), &ruby_error, 0, NULL); } + weechat_ruby_output_flush (); + if (ruby_error) { weechat_printf (NULL, weechat_gettext ("%s%s: unable to run function \"%s\""), weechat_prefix ("error"), RUBY_PLUGIN_NAME, function); - err = rb_gv_get("$!"); - weechat_ruby_print_exception(err); + err = rb_gv_get ("$!"); + weechat_ruby_print_exception (err); return NULL; } @@ -389,6 +527,19 @@ weechat_ruby_exec (struct t_plugin_script *script, else ret_value = NULL; } + else if ((TYPE(rc) == T_STRING) && (ret_type == WEECHAT_SCRIPT_EXEC_POINTER)) + { + if (StringValuePtr (rc)) + { + ret_value = plugin_script_str2ptr (weechat_ruby_plugin, + script->name, function, + StringValuePtr (rc)); + } + else + { + ret_value = NULL; + } + } else if ((TYPE(rc) == T_FIXNUM) && (ret_type == WEECHAT_SCRIPT_EXEC_INT)) { ret_i = malloc (sizeof (*ret_i)); @@ -405,114 +556,55 @@ weechat_ruby_exec (struct t_plugin_script *script, } else { - weechat_printf (NULL, - weechat_gettext ("%s%s: function \"%s\" must return a " - "valid value"), - weechat_prefix ("error"), RUBY_PLUGIN_NAME, function); - ruby_current_script = old_ruby_current_script; - return WEECHAT_RC_OK; - } - - if (ret_value == NULL) - { - weechat_printf (NULL, - weechat_gettext ("%s%s: not enough memory in function " - "\"%s\""), - weechat_prefix ("error"), RUBY_PLUGIN_NAME, function); - ruby_current_script = old_ruby_current_script; - return NULL; - } - - ruby_current_script = old_ruby_current_script; - - return ret_value; -} - -/* - * Redirection for stdout and stderr. - */ - -static VALUE -weechat_ruby_output (VALUE self, VALUE str) -{ - char *msg, *p, *m; - - /* make C compiler happy */ - (void) self; - - if (ruby_hide_errors) - return Qnil; - - msg = strdup(StringValuePtr(str)); - - m = msg; - while ((p = strchr (m, '\n')) != NULL) - { - *p = '\0'; - if (strlen (m) + strlen (ruby_buffer_output) > 0) + if (ret_type != WEECHAT_SCRIPT_EXEC_IGNORE) { weechat_printf (NULL, - weechat_gettext ("%s%s: stdout/stderr: %s%s"), + weechat_gettext ("%s%s: function \"%s\" must " + "return a valid value"), weechat_prefix ("error"), RUBY_PLUGIN_NAME, - ruby_buffer_output, m); + function); } - *p = '\n'; - ruby_buffer_output[0] = '\0'; - m = ++p; } - if (strlen(m) + strlen(ruby_buffer_output) > sizeof(ruby_buffer_output)) + if ((ret_type != WEECHAT_SCRIPT_EXEC_IGNORE) && !ret_value) { weechat_printf (NULL, - weechat_gettext ("%s%s: stdout/stderr: %s%s"), - weechat_prefix ("error"), RUBY_PLUGIN_NAME, - ruby_buffer_output, m); - ruby_buffer_output[0] = '\0'; + weechat_gettext ("%s%s: error in function \"%s\""), + weechat_prefix ("error"), RUBY_PLUGIN_NAME, function); } - else - strcat (ruby_buffer_output, m); - - if (msg) - free (msg); - - return Qnil; -} - -/* - * Function used for compatibility. - */ -static VALUE -weechat_ruby_output_flush (VALUE self) -{ - /* make C compiler happy */ - (void) self; + ruby_current_script = old_ruby_current_script; - return Qnil; + return ret_value; } /* * Loads a ruby script. * - * Returns: - * 1: OK - * 0: error + * If code is NULL, the content of filename is read and executed. + * If code is not NULL, it is executed (the file is not read). + * + * Returns pointer to new registered script, NULL if error. */ -int -weechat_ruby_load (const char *filename) +struct t_plugin_script * +weechat_ruby_load (const char *filename, const char *code) { char modname[64]; - VALUE ruby_retcode, err, argv[1]; + VALUE ruby_retcode, err, argv[2]; int ruby_error; struct stat buf; - if (stat (filename, &buf) != 0) + if (!code) { - weechat_printf (NULL, - weechat_gettext ("%s%s: script \"%s\" not found"), - weechat_prefix ("error"), RUBY_PLUGIN_NAME, filename); - return 0; + if (stat (filename, &buf) != 0) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: script \"%s\" not found"), + weechat_prefix ("error"), RUBY_PLUGIN_NAME, + filename); + return NULL; + } } if ((weechat_ruby_plugin->debug >= 2) || !ruby_quiet) @@ -525,7 +617,7 @@ weechat_ruby_load (const char *filename) ruby_current_script = NULL; ruby_registered_script = NULL; - snprintf (modname, sizeof(modname), "%s%d", MOD_NAME_PREFIX, ruby_num); + snprintf (modname, sizeof (modname), "%s%d", MOD_NAME_PREFIX, ruby_num); ruby_num++; ruby_current_module = rb_define_module (modname); @@ -533,15 +625,16 @@ weechat_ruby_load (const char *filename) ruby_current_script_filename = filename; argv[0] = rb_str_new2 (filename); + argv[1] = rb_str_new2 ((code) ? code : ""); ruby_retcode = rb_protect_funcall (ruby_current_module, rb_intern ("load_eval_file"), - &ruby_error, 1, argv); + &ruby_error, 2, argv); if (ruby_retcode == Qnil) { - err = rb_gv_get("$!"); - weechat_ruby_print_exception(err); - return 0; + err = rb_gv_get ("$!"); + weechat_ruby_print_exception (err); + return NULL; } if (NUM2INT(ruby_retcode) != 0) @@ -578,7 +671,7 @@ weechat_ruby_load (const char *filename) "@load_eval_file_error")); } - return 0; + return NULL; } (void) rb_protect_funcall (ruby_current_module, rb_intern ("weechat_init"), @@ -591,8 +684,8 @@ weechat_ruby_load (const char *filename) "\"weechat_init\" in file \"%s\""), weechat_prefix ("error"), RUBY_PLUGIN_NAME, filename); - err = rb_gv_get("$!"); - weechat_ruby_print_exception(err); + err = rb_gv_get ("$!"); + weechat_ruby_print_exception (err); if (ruby_current_script) { @@ -602,7 +695,7 @@ weechat_ruby_load (const char *filename) ruby_current_script = NULL; } - return 0; + return NULL; } if (!ruby_registered_script) @@ -611,7 +704,7 @@ weechat_ruby_load (const char *filename) weechat_gettext ("%s%s: function \"register\" not " "found (or failed) in file \"%s\""), weechat_prefix ("error"), RUBY_PLUGIN_NAME, filename); - return 0; + return NULL; } ruby_current_script = ruby_registered_script; @@ -631,7 +724,7 @@ weechat_ruby_load (const char *filename) WEECHAT_HOOK_SIGNAL_STRING, ruby_current_script->filename); - return 1; + return ruby_current_script; } /* @@ -644,7 +737,7 @@ weechat_ruby_load_cb (void *data, const char *filename) /* make C compiler happy */ (void) data; - weechat_ruby_load (filename); + weechat_ruby_load (filename, NULL); } /* @@ -745,7 +838,7 @@ weechat_ruby_reload_name (const char *name) weechat_gettext ("%s: script \"%s\" unloaded"), RUBY_PLUGIN_NAME, name); } - weechat_ruby_load (filename); + weechat_ruby_load (filename, NULL); free (filename); } } @@ -771,6 +864,65 @@ weechat_ruby_unload_all () } /* + * Evaluates ruby source code. + * + * Returns: + * 1: OK + * 0: error + */ + +int +weechat_ruby_eval (struct t_gui_buffer *buffer, int send_to_buffer_as_input, + int exec_commands, const char *code) +{ + void *func_argv[1], *result; + char empty_arg[1] = { '\0' }; + + if (!ruby_script_eval) + { + ruby_quiet = 1; + ruby_script_eval = weechat_ruby_load (WEECHAT_SCRIPT_EVAL_NAME, + RUBY_EVAL_SCRIPT); + ruby_quiet = 0; + if (!ruby_script_eval) + return 0; + } + + weechat_ruby_output_flush (); + + ruby_eval_mode = 1; + ruby_eval_send_input = send_to_buffer_as_input; + ruby_eval_exec_commands = exec_commands; + ruby_eval_buffer = buffer; + + func_argv[0] = (code) ? (char *)code : empty_arg; + result = weechat_ruby_exec (ruby_script_eval, + WEECHAT_SCRIPT_EXEC_IGNORE, + "script_ruby_eval", + "s", func_argv); + /* result is ignored */ + if (result) + free (result); + + weechat_ruby_output_flush (); + + ruby_eval_mode = 0; + ruby_eval_send_input = 0; + ruby_eval_exec_commands = 0; + ruby_eval_buffer = NULL; + + if (!weechat_config_boolean (ruby_config_look_eval_keep_context)) + { + ruby_quiet = 1; + weechat_ruby_unload (ruby_script_eval); + ruby_quiet = 0; + ruby_script_eval = NULL; + } + + return 1; +} + +/* * Callback for command "/ruby". */ @@ -779,12 +931,12 @@ weechat_ruby_command_cb (const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { - char *ptr_name, *path_script; + char *ptr_name, *ptr_code, *path_script; + int i, send_to_buffer_as_input, exec_commands; /* make C compiler happy */ (void) pointer; (void) data; - (void) buffer; if (argc == 1) { @@ -816,6 +968,10 @@ weechat_ruby_command_cb (const void *pointer, void *data, { weechat_ruby_unload_all (); } + else if (weechat_strcasecmp (argv[1], "version") == 0) + { + plugin_script_display_interpreter (weechat_ruby_plugin, 0); + } else WEECHAT_COMMAND_ERROR; } @@ -850,7 +1006,8 @@ weechat_ruby_command_cb (const void *pointer, void *data, /* load ruby script */ path_script = plugin_script_search_path (weechat_ruby_plugin, ptr_name); - weechat_ruby_load ((path_script) ? path_script : ptr_name); + weechat_ruby_load ((path_script) ? path_script : ptr_name, + NULL); if (path_script) free (path_script); } @@ -866,6 +1023,39 @@ weechat_ruby_command_cb (const void *pointer, void *data, } ruby_quiet = 0; } + else if (weechat_strcasecmp (argv[1], "eval") == 0) + { + send_to_buffer_as_input = 0; + exec_commands = 0; + ptr_code = argv_eol[2]; + for (i = 2; i < argc; i++) + { + if (argv[i][0] == '-') + { + if (strcmp (argv[i], "-o") == 0) + { + if (i + 1 >= argc) + WEECHAT_COMMAND_ERROR; + send_to_buffer_as_input = 1; + exec_commands = 0; + ptr_code = argv_eol[i + 1]; + } + else if (strcmp (argv[i], "-oc") == 0) + { + if (i + 1 >= argc) + WEECHAT_COMMAND_ERROR; + send_to_buffer_as_input = 1; + exec_commands = 1; + ptr_code = argv_eol[i + 1]; + } + } + else + break; + } + if (!weechat_ruby_eval (buffer, send_to_buffer_as_input, + exec_commands, ptr_code)) + WEECHAT_COMMAND_ERROR; + } else WEECHAT_COMMAND_ERROR; } @@ -912,6 +1102,29 @@ weechat_ruby_hdata_cb (const void *pointer, void *data, } /* + * Returns ruby info "ruby_eval". + */ + +const char * +weechat_ruby_info_eval_cb (const void *pointer, void *data, + const char *info_name, + const char *arguments) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) info_name; + + weechat_ruby_eval (NULL, 0, 0, (arguments) ? arguments : ""); + if (ruby_eval_output) + free (ruby_eval_output); + ruby_eval_output = strdup (*ruby_buffer_output); + weechat_string_dyn_copy (ruby_buffer_output, NULL); + + return ruby_eval_output; +} + +/* * Returns infolist with ruby scripts. */ @@ -962,31 +1175,6 @@ weechat_ruby_signal_debug_dump_cb (const void *pointer, void *data, } /* - * Display infos about external libraries used. - */ - -int -weechat_ruby_signal_debug_libs_cb (const void *pointer, void *data, - const char *signal, - const char *type_data, void *signal_data) -{ - /* make C compiler happy */ - (void) pointer; - (void) data; - (void) signal; - (void) type_data; - (void) signal_data; - -#ifdef HAVE_RUBY_VERSION_H - weechat_printf (NULL, " %s: %s", RUBY_PLUGIN_NAME, ruby_version); -#else - weechat_printf (NULL, " %s: (?)", RUBY_PLUGIN_NAME); -#endif /* HAVE_RUBY_VERSION_H */ - - return WEECHAT_RC_OK; -} - -/* * Timer for executing actions. */ @@ -1080,8 +1268,8 @@ weechat_ruby_signal_script_action_cb (const void *pointer, void *data, int weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) { - struct t_plugin_script_init init; int ruby_error; + VALUE err; char *weechat_ruby_code = { "$stdout = WeechatOutputs\n" "$stderr = WeechatOutputs\n" @@ -1102,12 +1290,16 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) "\n" "class Module\n" "\n" - " def load_eval_file (file)\n" - " lines = ''\n" - " begin\n" - " lines = File.read(file)\n" - " rescue => e\n" - " return 1\n" + " def load_eval_file (file, code)\n" + " if !code.empty?\n" + " lines = code\n" + " else\n" + " lines = ''\n" + " begin\n" + " lines = File.read(file)\n" + " rescue => e\n" + " return 1\n" + " end\n" " end\n" "\n" " begin\n" @@ -1134,15 +1326,32 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) "\n" " return 0\n" " end\n" + "\n" + " def eval_code (code)\n" + " module_eval(code)\n" + " end\n" "end\n" }; weechat_ruby_plugin = plugin; + /* set interpreter name and version */ + weechat_hashtable_set (plugin->variables, "interpreter_name", + plugin->name); +#ifdef HAVE_RUBY_VERSION_H + weechat_hashtable_set (plugin->variables, "interpreter_version", + ruby_version); +#else + weechat_hashtable_set (plugin->variables, "interpreter_version", + ""); +#endif /* HAVE_RUBY_VERSION_H */ + ruby_error = 0; /* init stdout/stderr buffer */ - ruby_buffer_output[0] = '\0'; + ruby_buffer_output = weechat_string_dyn_alloc (256); + if (!ruby_buffer_output) + return WEECHAT_RC_ERROR; #if (defined(RUBY_API_VERSION_MAJOR) && defined(RUBY_API_VERSION_MINOR)) && (RUBY_API_VERSION_MAJOR >= 2 || (RUBY_API_VERSION_MAJOR == 1 && RUBY_API_VERSION_MINOR >= 9)) RUBY_INIT_STACK; @@ -1159,7 +1368,7 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) rb_define_singleton_method (ruby_mWeechatOutputs, "p", weechat_ruby_output, 1); rb_define_singleton_method (ruby_mWeechatOutputs, "flush", - weechat_ruby_output_flush, 0); + weechat_ruby_output_flush_ruby, 0); ruby_script ("__weechat_plugin__"); @@ -1173,24 +1382,31 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) weechat_gettext ("%s%s: unable to eval WeeChat ruby " "internal code"), weechat_prefix ("error"), RUBY_PLUGIN_NAME); - VALUE err = rb_gv_get ("$!"); + err = rb_gv_get ("$!"); weechat_ruby_print_exception (err); + weechat_string_dyn_free (ruby_buffer_output, 1); return WEECHAT_RC_ERROR; } ruby_init_loadpath (); - init.callback_command = &weechat_ruby_command_cb; - init.callback_completion = &weechat_ruby_completion_cb; - init.callback_hdata = &weechat_ruby_hdata_cb; - init.callback_infolist = &weechat_ruby_infolist_cb; - init.callback_signal_debug_dump = &weechat_ruby_signal_debug_dump_cb; - init.callback_signal_debug_libs = &weechat_ruby_signal_debug_libs_cb; - init.callback_signal_script_action = &weechat_ruby_signal_script_action_cb; - init.callback_load_file = &weechat_ruby_load_cb; + ruby_data.config_file = &ruby_config_file; + ruby_data.config_look_check_license = &ruby_config_look_check_license; + ruby_data.config_look_eval_keep_context = &ruby_config_look_eval_keep_context; + ruby_data.scripts = &ruby_scripts; + ruby_data.last_script = &last_ruby_script; + ruby_data.callback_command = &weechat_ruby_command_cb; + ruby_data.callback_completion = &weechat_ruby_completion_cb; + ruby_data.callback_hdata = &weechat_ruby_hdata_cb; + ruby_data.callback_info_eval = &weechat_ruby_info_eval_cb; + ruby_data.callback_infolist = &weechat_ruby_infolist_cb; + ruby_data.callback_signal_debug_dump = &weechat_ruby_signal_debug_dump_cb; + ruby_data.callback_signal_script_action = &weechat_ruby_signal_script_action_cb; + ruby_data.callback_load_file = &weechat_ruby_load_cb; + ruby_data.unload_all = &weechat_ruby_unload_all; ruby_quiet = 1; - plugin_script_init (weechat_ruby_plugin, argc, argv, &init); + plugin_script_init (weechat_ruby_plugin, argc, argv, &ruby_data); ruby_quiet = 0; plugin_script_display_short_list (weechat_ruby_plugin, @@ -1209,7 +1425,12 @@ weechat_plugin_end (struct t_weechat_plugin *plugin) { /* unload all scripts */ ruby_quiet = 1; - plugin_script_end (plugin, &ruby_scripts, &weechat_ruby_unload_all); + if (ruby_script_eval) + { + weechat_ruby_unload (ruby_script_eval); + ruby_script_eval = NULL; + } + plugin_script_end (plugin, &ruby_data); ruby_quiet = 0; ruby_cleanup (0); @@ -1221,6 +1442,9 @@ weechat_plugin_end (struct t_weechat_plugin *plugin) free (ruby_action_remove_list); if (ruby_action_autoload_list) free (ruby_action_autoload_list); + weechat_string_dyn_free (ruby_buffer_output, 1); + if (ruby_eval_output) + free (ruby_eval_output); return WEECHAT_RC_OK; } diff --git a/src/plugins/ruby/weechat-ruby.h b/src/plugins/ruby/weechat-ruby.h index 3cb8010af..938944759 100644 --- a/src/plugins/ruby/weechat-ruby.h +++ b/src/plugins/ruby/weechat-ruby.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2007 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_RUBY_H -#define WEECHAT_RUBY_H 1 +#ifndef WEECHAT_PLUGIN_RUBY_H +#define WEECHAT_PLUGIN_RUBY_H #define weechat_plugin weechat_ruby_plugin #define RUBY_PLUGIN_NAME "ruby" @@ -28,6 +28,8 @@ extern struct t_weechat_plugin *weechat_ruby_plugin; +extern struct t_plugin_script_data ruby_data; + extern int ruby_quiet; extern struct t_plugin_script *ruby_scripts; extern struct t_plugin_script *last_ruby_script; @@ -45,4 +47,4 @@ void *weechat_ruby_exec (struct t_plugin_script *script, int ret_type, const char *function, const char *format, void **argv); -#endif /* WEECHAT_RUBY_H */ +#endif /* WEECHAT_PLUGIN_RUBY_H */ diff --git a/src/plugins/script/CMakeLists.txt b/src/plugins/script/CMakeLists.txt index c0a5e5c63..36d71142a 100644 --- a/src/plugins/script/CMakeLists.txt +++ b/src/plugins/script/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/script/Makefile.am b/src/plugins/script/Makefile.am index a6507f8dd..8a788cbdf 100644 --- a/src/plugins/script/Makefile.am +++ b/src/plugins/script/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/script/script-action.c b/src/plugins/script/script-action.c index a76e81c64..4a6cea22c 100644 --- a/src/plugins/script/script-action.c +++ b/src/plugins/script/script-action.c @@ -1,7 +1,7 @@ /* * script-action.c - actions on scripts * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -186,7 +186,7 @@ script_action_load (const char *name, int quiet) return; } - /* execute command (for example: "/perl load iset.pl") */ + /* execute command (for example: "/python load go.py") */ snprintf (str_command, sizeof (str_command), "/%s load %s%s", script_language[language], @@ -211,7 +211,7 @@ script_action_unload (const char *name, int quiet) pos = strrchr (name, '.'); if (pos) { - /* unload script by using name + extension (example: "iset.pl") */ + /* unload script by using name + extension (example: "go.py") */ language = script_language_search_by_extension (pos + 1); if (language < 0) { @@ -225,7 +225,7 @@ script_action_unload (const char *name, int quiet) } /* * search registered name of script using name with extension, - * for example with "iset.pl" we should find "iset" + * for example with "go.py" we should find "go" */ snprintf (hdata_name, sizeof (hdata_name), "%s_script", script_language[language]); @@ -316,7 +316,7 @@ script_action_reload (const char *name, int quiet) pos = strrchr (name, '.'); if (pos) { - /* reload script by using name + extension (example: "iset.pl") */ + /* reload script by using name + extension (example: "go.py") */ language = script_language_search_by_extension (pos + 1); if (language < 0) { @@ -330,7 +330,7 @@ script_action_reload (const char *name, int quiet) } /* * search registered name of script using name with extension, - * for example with "iset.pl" we should find "iset" + * for example with "go.py" we should find "go" */ snprintf (hdata_name, sizeof (hdata_name), "%s_script", script_language[language]); diff --git a/src/plugins/script/script-action.h b/src/plugins/script/script-action.h index 792730cd0..bd26da84b 100644 --- a/src/plugins/script/script-action.h +++ b/src/plugins/script/script-action.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_SCRIPT_ACTION_H -#define WEECHAT_SCRIPT_ACTION_H 1 +#ifndef WEECHAT_PLUGIN_SCRIPT_ACTION_H +#define WEECHAT_PLUGIN_SCRIPT_ACTION_H extern char *script_actions; @@ -26,4 +26,4 @@ extern int script_action_run (); extern void script_action_schedule (const char *action, int need_repository, int quiet); -#endif /* WEECHAT_SCRIPT_ACTION_H */ +#endif /* WEECHAT_PLUGIN_SCRIPT_ACTION_H */ diff --git a/src/plugins/script/script-buffer.c b/src/plugins/script/script-buffer.c index 0d2461fc7..9fda0aa46 100644 --- a/src/plugins/script/script-buffer.c +++ b/src/plugins/script/script-buffer.c @@ -1,7 +1,7 @@ /* * script-buffer.c - display scripts on script buffer * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -117,8 +117,9 @@ script_buffer_display_line_script (int line, struct t_script_repo *script) if (script->date_added > 0) { tm = localtime (&script->date_added); - strftime (str_date, sizeof (str_date), - "%Y-%m-%d", tm); + if (strftime (str_date, sizeof (str_date), + "%Y-%m-%d", tm) == 0) + str_date[0] = '\0'; snprintf (str_item, sizeof (str_item), "%s%s", weechat_color ( @@ -232,8 +233,9 @@ script_buffer_display_line_script (int line, struct t_script_repo *script) if (script->date_updated > 0) { tm = localtime (&script->date_updated); - strftime (str_date, sizeof (str_date), - "%Y-%m-%d", tm); + if (strftime (str_date, sizeof (str_date), + "%Y-%m-%d", tm) == 0) + str_date[0] = '\0'; snprintf (str_item, sizeof (str_item), "%s%s", weechat_color ( @@ -672,14 +674,16 @@ script_buffer_display_detail_script (struct t_script_repo *script) } line++; tm = localtime (&script->date_added); - strftime (str_time, sizeof (str_time), "%Y-%m-%d %H:%M:%S", tm); + if (strftime (str_time, sizeof (str_time), "%Y-%m-%d %H:%M:%S", tm) == 0) + str_time[0] = '\0'; weechat_printf_y (script_buffer, line + 1, "%s: %s", script_buffer_detail_label (_(labels[line]), max_length), str_time); line++; tm = localtime (&script->date_updated); - strftime (str_time, sizeof (str_time), "%Y-%m-%d %H:%M:%S", tm); + if (strftime (str_time, sizeof (str_time), "%Y-%m-%d %H:%M:%S", tm) == 0) + str_time[0] = '\0'; weechat_printf_y (script_buffer, line + 1, "%s: %s", script_buffer_detail_label (_(labels[line]), max_length), @@ -1118,6 +1122,20 @@ script_buffer_set_keys () } /* + * Sets the local variable "filter" in the script buffer. + */ + +void +script_buffer_set_localvar_filter () +{ + if (!script_buffer) + return; + + weechat_buffer_set (script_buffer, "localvar_set_filter", + (script_repo_filter) ? script_repo_filter : "*"); +} + +/* * Opens script buffer. */ @@ -1139,6 +1157,7 @@ script_buffer_open () weechat_buffer_set (script_buffer, "title", _("Scripts")); script_buffer_set_keys (); weechat_buffer_set (script_buffer, "localvar_set_type", "script"); + script_buffer_set_localvar_filter (); script_buffer_selected_line = 0; script_buffer_detail_script = NULL; diff --git a/src/plugins/script/script-buffer.h b/src/plugins/script/script-buffer.h index 9e8b28839..569a88872 100644 --- a/src/plugins/script/script-buffer.h +++ b/src/plugins/script/script-buffer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_SCRIPT_BUFFER_H -#define WEECHAT_SCRIPT_BUFFER_H 1 +#ifndef WEECHAT_PLUGIN_SCRIPT_BUFFER_H +#define WEECHAT_PLUGIN_SCRIPT_BUFFER_H #define SCRIPT_BUFFER_NAME "scripts" @@ -47,6 +47,7 @@ extern int script_buffer_close_cb (const void *pointer, void *data, struct t_gui_buffer *buffer); extern void script_buffer_set_callbacks (); extern void script_buffer_set_keys (); +extern void script_buffer_set_localvar_filter (); extern void script_buffer_open (); -#endif /* WEECHAT_SCRIPT_BUFFER_H */ +#endif /* WEECHAT_PLUGIN_SCRIPT_BUFFER_H */ diff --git a/src/plugins/script/script-command.c b/src/plugins/script/script-command.c index 682e6e3bd..7b98ab427 100644 --- a/src/plugins/script/script-command.c +++ b/src/plugins/script/script-command.c @@ -1,7 +1,7 @@ /* * script-command.c - script command * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -289,7 +289,7 @@ script_command_init () { weechat_hook_command ( "script", - N_("WeeChat scripts manager"), + N_("WeeChat script manager"), N_("list [-o|-i]" " || search <text>" " || show <script>" @@ -363,8 +363,8 @@ script_command_init () "\n" "Examples:\n" " /script search url\n" - " /script install iset.pl buffers.pl\n" - " /script remove iset.pl\n" + " /script install go.py urlserver.py\n" + " /script remove go.py\n" " /script hold urlserver.py\n" " /script reload urlserver\n" " /script upgrade"), @@ -373,9 +373,11 @@ script_command_init () " || show %(script_scripts)" " || load %(script_files)|%*" " || unload %(python_script)|%(perl_script)|%(ruby_script)|" - "%(tcl_script)|%(lua_script)|%(guile_script)|%(javascript_script)|%*" + "%(tcl_script)|%(lua_script)|%(guile_script)|%(javascript_script)|" + "%(php_script)|%*" " || reload %(python_script)|%(perl_script)|%(ruby_script)|" - "%(tcl_script)|%(lua_script)|%(guile_script)|%(javascript_script)|%*" + "%(tcl_script)|%(lua_script)|%(guile_script)|%(javascript_script)|" + "%(php_script)|%*" " || autoload %(script_scripts_installed)|%*" " || noautoload %(script_scripts_installed)|%*" " || toggleautoload %(script_scripts_installed)|%*" diff --git a/src/plugins/script/script-command.h b/src/plugins/script/script-command.h index af995b970..ee4f4eb0f 100644 --- a/src/plugins/script/script-command.h +++ b/src/plugins/script/script-command.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_SCRIPT_COMMAND_H -#define WEECHAT_SCRIPT_COMMAND_H 1 +#ifndef WEECHAT_PLUGIN_SCRIPT_COMMAND_H +#define WEECHAT_PLUGIN_SCRIPT_COMMAND_H extern void script_command_init (); -#endif /* WEECHAT_SCRIPT_COMMAND_H */ +#endif /* WEECHAT_PLUGIN_SCRIPT_COMMAND_H */ diff --git a/src/plugins/script/script-completion.c b/src/plugins/script/script-completion.c index e889bb6a5..914627a51 100644 --- a/src/plugins/script/script-completion.c +++ b/src/plugins/script/script-completion.c @@ -1,7 +1,7 @@ /* * script-completion.c - completions for script command * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -214,14 +214,14 @@ script_completion_scripts_files_cb (const void *pointer, void *data, /* look for files in "~/.weechat/<language>/" */ snprintf (directory, length, "%s/%s", weechat_home, script_language[i]); - weechat_exec_on_files (directory, 0, + weechat_exec_on_files (directory, 0, 0, &script_completion_exec_file_cb, pointers); /* look for files in "~/.weechat/<language>/autoload/" */ snprintf (directory, length, "%s/%s/autoload", weechat_home, script_language[i]); - weechat_exec_on_files (directory, 0, + weechat_exec_on_files (directory, 0, 0, &script_completion_exec_file_cb, pointers); } diff --git a/src/plugins/script/script-completion.h b/src/plugins/script/script-completion.h index 04d5d32d4..a4ab2b2a6 100644 --- a/src/plugins/script/script-completion.h +++ b/src/plugins/script/script-completion.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_SCRIPT_COMPLETION_H -#define WEECHAT_SCRIPT_COMPLETION_H 1 +#ifndef WEECHAT_PLUGIN_SCRIPT_COMPLETION_H +#define WEECHAT_PLUGIN_SCRIPT_COMPLETION_H extern void script_completion_init (); -#endif /* WEECHAT_SCRIPT_COMPLETION_H */ +#endif /* WEECHAT_PLUGIN_SCRIPT_COMPLETION_H */ diff --git a/src/plugins/script/script-config.c b/src/plugins/script/script-config.c index f17e53739..9116ee0d7 100644 --- a/src/plugins/script/script-config.c +++ b/src/plugins/script/script-config.c @@ -1,7 +1,7 @@ /* * script-config.c - script configuration options (file script.conf) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -167,7 +167,7 @@ script_config_get_xml_filename () * * If suffix is not NULL, it is added to filename. * - * Example: "/home/xxx/.weechat/script/iset.pl" + * Example: "/home/xxx/.weechat/script/go.py" * * Note: result must be freed after use. */ @@ -398,6 +398,7 @@ script_config_init () if (!ptr_section) { weechat_config_free (script_config_file); + script_config_file = NULL; return 0; } @@ -454,7 +455,7 @@ script_config_init () "u=date updated; char \"-\" can be used before identifier to reverse " "order; example: \"i,u\": installed scripts first, sorted by update " "date"), - NULL, 0, 0, "p,n", NULL, 0, + NULL, 0, 0, "i,p,n", NULL, 0, NULL, NULL, NULL, &script_config_reload_scripts_cb, NULL, NULL, NULL, NULL, NULL); @@ -489,6 +490,7 @@ script_config_init () if (!ptr_section) { weechat_config_free (script_config_file); + script_config_file = NULL; return 0; } @@ -712,6 +714,7 @@ script_config_init () if (!ptr_section) { weechat_config_free (script_config_file); + script_config_file = NULL; return 0; } @@ -748,7 +751,7 @@ script_config_init () "hold", "string", N_("scripts to \"hold\": comma-separated list of scripts which will " "never been upgraded and can not be removed, for example: " - "\"buffers.pl,iset.pl\""), + "\"go.py,urlserver.py\""), NULL, 0, 0, "", NULL, 0, NULL, NULL, NULL, &script_config_change_hold_cb, NULL, NULL, diff --git a/src/plugins/script/script-config.h b/src/plugins/script/script-config.h index c078271ab..dae0e834e 100644 --- a/src/plugins/script/script-config.h +++ b/src/plugins/script/script-config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_SCRIPT_CONFIG_H -#define WEECHAT_SCRIPT_CONFIG_H 1 +#ifndef WEECHAT_PLUGIN_SCRIPT_CONFIG_H +#define WEECHAT_PLUGIN_SCRIPT_CONFIG_H #define SCRIPT_CONFIG_NAME "script" @@ -78,4 +78,4 @@ extern int script_config_read (); extern int script_config_write (); extern void script_config_free (); -#endif /* WEECHAT_SCRIPT_CONFIG_H */ +#endif /* WEECHAT_PLUGIN_SCRIPT_CONFIG_H */ diff --git a/src/plugins/script/script-info.c b/src/plugins/script/script-info.c index ac486aea4..7cd177dd0 100644 --- a/src/plugins/script/script-info.c +++ b/src/plugins/script/script-info.c @@ -1,7 +1,7 @@ /* * script-info.c - info, infolist and hdata hooks for script plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/script/script-info.h b/src/plugins/script/script-info.h index 675582c2b..b2eb5be98 100644 --- a/src/plugins/script/script-info.h +++ b/src/plugins/script/script-info.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_SCRIPT_INFO_H -#define WEECHAT_SCRIPT_INFO_H 1 +#ifndef WEECHAT_PLUGIN_SCRIPT_INFO_H +#define WEECHAT_PLUGIN_SCRIPT_INFO_H extern void script_info_init (); -#endif /* WEECHAT_SCRIPT_INFO_H */ +#endif /* WEECHAT_PLUGIN_SCRIPT_INFO_H */ diff --git a/src/plugins/script/script-mouse.c b/src/plugins/script/script-mouse.c index 534331697..8d1c6e4d4 100644 --- a/src/plugins/script/script-mouse.c +++ b/src/plugins/script/script-mouse.c @@ -1,7 +1,7 @@ /* * script-mouse.c - mouse actions for script * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -98,10 +98,12 @@ script_mouse_focus_chat_cb (const void *pointer, void *data, weechat_hashtable_set (info, "script_md5sum", ptr_script->md5sum); weechat_hashtable_set (info, "script_url", ptr_script->url); tm = localtime (&ptr_script->date_added); - strftime (str_date, sizeof (str_date), "%Y-%m-%d %H:%M:%S", tm); + if (strftime (str_date, sizeof (str_date), "%Y-%m-%d %H:%M:%S", tm) == 0) + str_date[0] = '\0'; weechat_hashtable_set (info, "script_date_added", str_date); tm = localtime (&ptr_script->date_updated); - strftime (str_date, sizeof (str_date), "%Y-%m-%d %H:%M:%S", tm); + if (strftime (str_date, sizeof (str_date), "%Y-%m-%d %H:%M:%S", tm) == 0) + str_date[0] = '\0'; weechat_hashtable_set (info, "script_date_updated", str_date); weechat_hashtable_set (info, "script_version_loaded", ptr_script->version_loaded); diff --git a/src/plugins/script/script-mouse.h b/src/plugins/script/script-mouse.h index dcfb1dea4..8addb07bf 100644 --- a/src/plugins/script/script-mouse.h +++ b/src/plugins/script/script-mouse.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,10 +17,10 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_SCRIPT_MOUSE_H -#define WEECHAT_SCRIPT_MOUSE_H 1 +#ifndef WEECHAT_PLUGIN_SCRIPT_MOUSE_H +#define WEECHAT_PLUGIN_SCRIPT_MOUSE_H extern int script_mouse_init (); extern void script_mouse_end (); -#endif /* WEECHAT_SCRIPT_MOUSE_H */ +#endif /* WEECHAT_PLUGIN_SCRIPT_MOUSE_H */ diff --git a/src/plugins/script/script-repo.c b/src/plugins/script/script-repo.c index c29e9876e..b2823c0a6 100644 --- a/src/plugins/script/script-repo.c +++ b/src/plugins/script/script-repo.c @@ -1,7 +1,7 @@ /* * script-repo.c - download and read repository file (plugins.xml.gz) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -135,7 +135,7 @@ script_repo_search_by_name (const char *name) } /* - * Searches for a script by name/extension (example: "iset.pl"). + * Searches for a script by name/extension (example: "go.py"). * * Returns pointer to script found, NULL if not found. */ @@ -910,6 +910,8 @@ script_repo_set_filter (const char *filter) if (script_repo_filter) free (script_repo_filter); script_repo_filter = (filter) ? strdup (filter) : NULL; + + script_buffer_set_localvar_filter (); } /* @@ -1037,7 +1039,7 @@ script_repo_file_exists () int rc; struct stat st; - filename = script_config_get_xml_filename(); + filename = script_config_get_xml_filename (); if (!filename) return 0; @@ -1409,6 +1411,8 @@ script_repo_file_read (int quiet) SCRIPT_PLUGIN_NAME); } + if (script) + script_repo_free (script); if (locale) free (locale); if (locale_language) @@ -1655,8 +1659,8 @@ script_repo_print_log () weechat_log_printf (" md5sum. . . . . . . . : '%s'", ptr_script->md5sum); weechat_log_printf (" url . . . . . . . . . : '%s'", ptr_script->url); weechat_log_printf (" popularity. . . . . . : %d", ptr_script->popularity); - weechat_log_printf (" date_added. . . . . . : %ld", ptr_script->date_added); - weechat_log_printf (" date_updated. . . . . : %ld", ptr_script->date_updated); + weechat_log_printf (" date_added. . . . . . : %lld", (long long)ptr_script->date_added); + weechat_log_printf (" date_updated. . . . . : %lld", (long long)ptr_script->date_updated); weechat_log_printf (" status. . . . . . . . : %d (%s%s%s%s%s )", ptr_script->status, (ptr_script->status & SCRIPT_STATUS_INSTALLED) ? " installed": "", diff --git a/src/plugins/script/script-repo.h b/src/plugins/script/script-repo.h index 555051020..5f318e5e5 100644 --- a/src/plugins/script/script-repo.h +++ b/src/plugins/script/script-repo.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_SCRIPT_REPO_H -#define WEECHAT_SCRIPT_REPO_H 1 +#ifndef WEECHAT_PLUGIN_SCRIPT_REPO_H +#define WEECHAT_PLUGIN_SCRIPT_REPO_H #include <time.h> @@ -88,4 +88,4 @@ extern int script_repo_add_to_infolist (struct t_infolist *infolist, struct t_script_repo *script); extern void script_repo_print_log (); -#endif /* WEECHAT_SCRIPT_REPO_H */ +#endif /* WEECHAT_PLUGIN_SCRIPT_REPO_H */ diff --git a/src/plugins/script/script.c b/src/plugins/script/script.c index 48d68eff5..e2f2a54f7 100644 --- a/src/plugins/script/script.c +++ b/src/plugins/script/script.c @@ -1,7 +1,7 @@ /* - * script.c - scripts manager for WeeChat + * script.c - script manager for WeeChat * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -37,18 +37,18 @@ WEECHAT_PLUGIN_NAME(SCRIPT_PLUGIN_NAME); -WEECHAT_PLUGIN_DESCRIPTION(N_("Scripts manager")); +WEECHAT_PLUGIN_DESCRIPTION(N_("Script manager")); WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(2000); +WEECHAT_PLUGIN_PRIORITY(3000); struct t_weechat_plugin *weechat_script_plugin = NULL; char *script_language[SCRIPT_NUM_LANGUAGES] = -{ "guile", "lua", "perl", "python", "ruby", "tcl", "javascript" }; +{ "guile", "lua", "perl", "python", "ruby", "tcl", "javascript", "php" }; char *script_extension[SCRIPT_NUM_LANGUAGES] = -{ "scm", "lua", "pl", "py", "rb", "tcl", "js" }; +{ "scm", "lua", "pl", "py", "rb", "tcl", "js", "php" }; int script_plugin_loaded[SCRIPT_NUM_LANGUAGES]; struct t_hashtable *script_loaded = NULL; diff --git a/src/plugins/script/script.h b/src/plugins/script/script.h index 497aa2142..ef51d6cd9 100644 --- a/src/plugins/script/script.h +++ b/src/plugins/script/script.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,13 +17,13 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_SCRIPT_H -#define WEECHAT_SCRIPT_H 1 +#ifndef WEECHAT_PLUGIN_SCRIPT_H +#define WEECHAT_PLUGIN_SCRIPT_H #define weechat_plugin weechat_script_plugin #define SCRIPT_PLUGIN_NAME "script" -#define SCRIPT_NUM_LANGUAGES 7 +#define SCRIPT_NUM_LANGUAGES 8 extern struct t_weechat_plugin *weechat_script_plugin; @@ -38,4 +38,4 @@ extern char *script_build_download_url (const char *url); extern void script_get_loaded_plugins (); extern void script_get_scripts (); -#endif /* WEECHAT_SCRIPT_H */ +#endif /* WEECHAT_PLUGIN_SCRIPT_H */ diff --git a/src/plugins/tcl/CMakeLists.txt b/src/plugins/tcl/CMakeLists.txt index 4a396d663..39c705ff8 100644 --- a/src/plugins/tcl/CMakeLists.txt +++ b/src/plugins/tcl/CMakeLists.txt @@ -1,7 +1,7 @@ # # Copyright (C) 2008-2010 Dmitry Kobylin <fnfal@academ.tsc.ru> # Copyright (C) 2008 Julien Louis <ptitlouis@sysif.net> -# Copyright (C) 2008-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2008-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/tcl/Makefile.am b/src/plugins/tcl/Makefile.am index 4bb48e77f..80ac1bda0 100644 --- a/src/plugins/tcl/Makefile.am +++ b/src/plugins/tcl/Makefile.am @@ -1,6 +1,6 @@ # # Copyright (C) 2008-2010 Dmitry Kobylin <fnfal@academ.tsc.ru> -# Copyright (C) 2008-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2008-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/tcl/weechat-tcl-api.c b/src/plugins/tcl/weechat-tcl-api.c index a7de9b353..2159ec645 100644 --- a/src/plugins/tcl/weechat-tcl-api.c +++ b/src/plugins/tcl/weechat-tcl-api.c @@ -3,7 +3,7 @@ * * Copyright (C) 2008-2010 Dmitry Kobylin <fnfal@academ.tsc.ru> * Copyright (C) 2008 Julien Louis <ptitlouis@sysif.net> - * Copyright (C) 2008-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2008-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2012 Simon Arlott * * This file is part of WeeChat, the extensible chat client. @@ -68,6 +68,8 @@ plugin_script_str2ptr (weechat_tcl_plugin, \ TCL_CURRENT_SCRIPT_NAME, \ tcl_function_name, __string) +#define API_STATIC_STRING(__string) \ + plugin_script_get_static_string(&tcl_data, __string); #define API_RETURN_OK \ { \ objp = Tcl_GetObjResult (interp); \ @@ -259,7 +261,7 @@ API_FUNC(register) /* register script */ tcl_current_script = plugin_script_add (weechat_tcl_plugin, - &tcl_scripts, &last_tcl_script, + &tcl_data, (tcl_current_script_filename) ? tcl_current_script_filename : "", name, author, version, license, @@ -488,6 +490,24 @@ API_FUNC(string_mask_to_regex) API_RETURN_STRING_FREE(result); } +API_FUNC(string_format_size) +{ + Tcl_Obj *objp; + char *result; + long size; + + API_INIT_FUNC(1, "string_format_size", API_RETURN_EMPTY); + if (objc < 2) + API_WRONG_ARGS(API_RETURN_EMPTY); + + if (Tcl_GetLongFromObj (interp, objv[1], &size) != TCL_OK) + API_WRONG_ARGS(API_RETURN_EMPTY); + + result = weechat_string_format_size ((unsigned long long)size); + + API_RETURN_STRING_FREE(result); +} + API_FUNC(string_remove_color) { Tcl_Obj *objp; @@ -674,7 +694,7 @@ API_FUNC(mkdir_parents) API_FUNC(list_new) { Tcl_Obj *objp; - char *result; + const char *result; /* make C compiler happy */ (void) clientData; @@ -685,13 +705,14 @@ API_FUNC(list_new) result = API_PTR2STR(weechat_list_new ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_add) { Tcl_Obj *objp; - char *result, *weelist, *data, *where, *user_data; + char *weelist, *data, *where, *user_data; + const char *result; int i; @@ -709,13 +730,14 @@ API_FUNC(list_add) where, API_STR2PTR(user_data))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_search) { Tcl_Obj *objp; - char *result, *weelist, *data; + char *weelist, *data; + const char *result; int i; API_INIT_FUNC(1, "list_search", API_RETURN_EMPTY); @@ -728,7 +750,7 @@ API_FUNC(list_search) result = API_PTR2STR(weechat_list_search (API_STR2PTR(weelist), data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_search_pos) @@ -752,7 +774,8 @@ API_FUNC(list_search_pos) API_FUNC(list_casesearch) { Tcl_Obj *objp; - char *result, *weelist, *data; + char *weelist, *data; + const char *result; int i; API_INIT_FUNC(1, "list_casesearch", API_RETURN_EMPTY); @@ -765,7 +788,7 @@ API_FUNC(list_casesearch) result = API_PTR2STR(weechat_list_casesearch (API_STR2PTR(weelist), data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_casesearch_pos) @@ -789,7 +812,7 @@ API_FUNC(list_casesearch_pos) API_FUNC(list_get) { Tcl_Obj *objp; - char *result; + const char *result; int i, position; API_INIT_FUNC(1, "list_get", API_RETURN_EMPTY); @@ -802,7 +825,7 @@ API_FUNC(list_get) result = API_PTR2STR(weechat_list_get (API_STR2PTR(Tcl_GetStringFromObj (objv[1], &i)), /* weelist */ position)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_set) @@ -826,7 +849,7 @@ API_FUNC(list_set) API_FUNC(list_next) { Tcl_Obj *objp; - char *result; + const char *result; int i; API_INIT_FUNC(1, "list_next", API_RETURN_EMPTY); @@ -835,13 +858,13 @@ API_FUNC(list_next) result = API_PTR2STR(weechat_list_next (API_STR2PTR(Tcl_GetStringFromObj (objv[1], &i)))); /* item */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_prev) { Tcl_Obj *objp; - char *result; + const char *result; int i; API_INIT_FUNC(1, "list_prev", API_RETURN_EMPTY); @@ -850,7 +873,7 @@ API_FUNC(list_prev) result = API_PTR2STR(weechat_list_prev (API_STR2PTR(Tcl_GetStringFromObj (objv[1], &i)))); /* item */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(list_string) @@ -949,7 +972,7 @@ weechat_tcl_api_config_reload_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); rc = (int *) weechat_tcl_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -963,8 +986,6 @@ weechat_tcl_api_config_reload_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -975,7 +996,8 @@ weechat_tcl_api_config_reload_cb (const void *pointer, void *data, API_FUNC(config_new) { Tcl_Obj *objp; - char *result, *name, *function, *data; + char *name, *function, *data; + const char *result; int i; API_INIT_FUNC(1, "config_new", API_RETURN_EMPTY); @@ -993,7 +1015,7 @@ API_FUNC(config_new) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -1014,8 +1036,8 @@ weechat_tcl_api_config_section_read_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); func_argv[3] = (option_name) ? (char *)option_name : empty_arg; func_argv[4] = (value) ? (char *)value : empty_arg; @@ -1031,10 +1053,6 @@ weechat_tcl_api_config_section_read_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); return ret; } @@ -1059,7 +1077,7 @@ weechat_tcl_api_config_section_write_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); func_argv[2] = (section_name) ? (char *)section_name : empty_arg; rc = (int *) weechat_tcl_exec (script, @@ -1074,8 +1092,6 @@ weechat_tcl_api_config_section_write_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -1100,7 +1116,7 @@ weechat_tcl_api_config_section_write_default_cb (const void *pointer, void *data if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); + func_argv[1] = (char *)API_PTR2STR(config_file); func_argv[2] = (section_name) ? (char *)section_name : empty_arg; rc = (int *) weechat_tcl_exec (script, @@ -1115,8 +1131,6 @@ weechat_tcl_api_config_section_write_default_cb (const void *pointer, void *data ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -1143,8 +1157,8 @@ weechat_tcl_api_config_section_create_option_cb (const void *pointer, void *data if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); func_argv[3] = (option_name) ? (char *)option_name : empty_arg; func_argv[4] = (value) ? (char *)value : empty_arg; @@ -1160,10 +1174,6 @@ weechat_tcl_api_config_section_create_option_cb (const void *pointer, void *data ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); return ret; } @@ -1189,9 +1199,9 @@ weechat_tcl_api_config_section_delete_option_cb (const void *pointer, void *data if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(config_file); - func_argv[2] = API_PTR2STR(section); - func_argv[3] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(config_file); + func_argv[2] = (char *)API_PTR2STR(section); + func_argv[3] = (char *)API_PTR2STR(option); rc = (int *) weechat_tcl_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -1205,12 +1215,6 @@ weechat_tcl_api_config_section_delete_option_cb (const void *pointer, void *data ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -1221,10 +1225,11 @@ weechat_tcl_api_config_section_delete_option_cb (const void *pointer, void *data API_FUNC(config_new_section) { Tcl_Obj *objp; - char *result, *cfg_file, *name, *function_read, *data_read; + char *cfg_file, *name, *function_read, *data_read; char *function_write, *data_write, *function_write_default; char *data_write_default, *function_create_option, *data_create_option; char *function_delete_option, *data_delete_option; + const char *result; int i, can_add, can_delete; /* make C compiler happy */ @@ -1275,13 +1280,14 @@ API_FUNC(config_new_section) function_delete_option, data_delete_option)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_search_section) { Tcl_Obj *objp; - char *result, *config_file, *section_name; + char *config_file, *section_name; + const char *result; int i; API_INIT_FUNC(1, "config_search_section", API_RETURN_EMPTY); @@ -1294,7 +1300,7 @@ API_FUNC(config_search_section) result = API_PTR2STR(weechat_config_search_section (API_STR2PTR(config_file), section_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } @@ -1315,7 +1321,7 @@ weechat_tcl_api_config_option_check_value_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); func_argv[2] = (value) ? (char *)value : empty_arg; rc = (int *) weechat_tcl_exec (script, @@ -1330,8 +1336,6 @@ weechat_tcl_api_config_option_check_value_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -1355,16 +1359,13 @@ weechat_tcl_api_config_option_change_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); rc = (int *) weechat_tcl_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, "ss", func_argv); - if (func_argv[1]) - free (func_argv[1]); - if (rc) free (rc); } @@ -1386,16 +1387,13 @@ weechat_tcl_api_config_option_delete_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(option); + func_argv[1] = (char *)API_PTR2STR(option); rc = (int *) weechat_tcl_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, "ss", func_argv); - if (func_argv[1]) - free (func_argv[1]); - if (rc) free (rc); } @@ -1404,10 +1402,11 @@ weechat_tcl_api_config_option_delete_cb (const void *pointer, void *data, API_FUNC(config_new_option) { Tcl_Obj *objp; - char *result, *config_file, *section, *name, *type; + char *config_file, *section, *name, *type; char *description, *string_values, *default_value, *value; char *function_check_value, *data_check_value, *function_change; char *data_change, *function_delete, *data_delete; + const char *result; int i, min, max, null_value_allowed; API_INIT_FUNC(1, "config_new_option", API_RETURN_EMPTY); @@ -1457,13 +1456,14 @@ API_FUNC(config_new_option) function_delete, data_delete)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_search_option) { Tcl_Obj *objp; - char *result, *config_file, *section, *option_name; + char *config_file, *section, *option_name; + const char *result; int i; API_INIT_FUNC(1, "config_search_option", API_RETURN_EMPTY); @@ -1478,7 +1478,7 @@ API_FUNC(config_search_option) API_STR2PTR(section), option_name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_string_to_boolean) @@ -1891,7 +1891,7 @@ API_FUNC(config_free) API_FUNC(config_get) { Tcl_Obj *objp; - char *result; + const char *result; int i; API_INIT_FUNC(1, "config_get", API_RETURN_EMPTY); @@ -1900,7 +1900,7 @@ API_FUNC(config_get) result = API_PTR2STR(weechat_config_get (Tcl_GetStringFromObj (objv[1], &i))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(config_get_plugin) @@ -2186,7 +2186,7 @@ weechat_tcl_api_hook_command_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (argc > 1) ? argv_eol[1] : empty_arg; rc = (int *) weechat_tcl_exec (script, @@ -2201,8 +2201,6 @@ weechat_tcl_api_hook_command_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -2213,8 +2211,9 @@ weechat_tcl_api_hook_command_cb (const void *pointer, void *data, API_FUNC(hook_command) { Tcl_Obj *objp; - char *result, *command, *description, *args, *args_description; + char *command, *description, *args, *args_description; char *completion, *function, *data; + const char *result; int i; API_INIT_FUNC(1, "hook_command", API_RETURN_EMPTY); @@ -2240,7 +2239,7 @@ API_FUNC(hook_command) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2262,8 +2261,8 @@ weechat_tcl_api_hook_completion_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (completion_item) ? (char *)completion_item : empty_arg; - func_argv[2] = API_PTR2STR(buffer); - func_argv[3] = API_PTR2STR(completion); + func_argv[2] = (char *)API_PTR2STR(buffer); + func_argv[3] = (char *)API_PTR2STR(completion); rc = (int *) weechat_tcl_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -2277,10 +2276,6 @@ weechat_tcl_api_hook_completion_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -2291,7 +2286,8 @@ weechat_tcl_api_hook_completion_cb (const void *pointer, void *data, API_FUNC(hook_completion) { Tcl_Obj *objp; - char *result, *completion, *description, *function, *data; + char *completion, *description, *function, *data; + const char *result; int i; API_INIT_FUNC(1, "hook_completion", API_RETURN_EMPTY); @@ -2311,7 +2307,7 @@ API_FUNC(hook_completion) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_completion_get_string) @@ -2376,7 +2372,7 @@ weechat_tcl_api_hook_command_run_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (command) ? (char *)command : empty_arg; rc = (int *) weechat_tcl_exec (script, @@ -2391,8 +2387,6 @@ weechat_tcl_api_hook_command_run_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -2403,7 +2397,8 @@ weechat_tcl_api_hook_command_run_cb (const void *pointer, void *data, API_FUNC(hook_command_run) { Tcl_Obj *objp; - char *result, *command, *function, *data; + char *command, *function, *data; + const char *result; int i; API_INIT_FUNC(1, "hook_command_run", API_RETURN_EMPTY); @@ -2421,7 +2416,7 @@ API_FUNC(hook_command_run) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2467,7 +2462,7 @@ weechat_tcl_api_hook_timer_cb (const void *pointer, void *data, API_FUNC(hook_timer) { Tcl_Obj *objp; - char *result; + const char *result; int i, interval, align_second, max_calls; API_INIT_FUNC(1, "hook_timer", API_RETURN_EMPTY); @@ -2489,7 +2484,7 @@ API_FUNC(hook_timer) Tcl_GetStringFromObj (objv[4], &i), /* tcl function */ Tcl_GetStringFromObj (objv[5], &i))); /* data */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2497,7 +2492,7 @@ weechat_tcl_api_hook_fd_cb (const void *pointer, void *data, int fd) { struct t_plugin_script *script; void *func_argv[2]; - char str_fd[32], empty_arg[1] = { '\0' }; + char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; int *rc, ret; @@ -2506,15 +2501,13 @@ weechat_tcl_api_hook_fd_cb (const void *pointer, void *data, int fd) if (ptr_function && ptr_function[0]) { - snprintf (str_fd, sizeof (str_fd), "%d", fd); - func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = str_fd; + func_argv[1] = &fd; rc = (int *) weechat_tcl_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "ss", func_argv); + "si", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2533,7 +2526,7 @@ weechat_tcl_api_hook_fd_cb (const void *pointer, void *data, int fd) API_FUNC(hook_fd) { Tcl_Obj *objp; - char *result; + const char *result; int i, fd, read, write, exception; API_INIT_FUNC(1, "hook_fd", API_RETURN_EMPTY); @@ -2556,7 +2549,7 @@ API_FUNC(hook_fd) Tcl_GetStringFromObj (objv[5], &i), /* tcl function */ Tcl_GetStringFromObj (objv[6], &i))); /* data */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2622,7 +2615,8 @@ weechat_tcl_api_hook_process_cb (const void *pointer, void *data, API_FUNC(hook_process) { Tcl_Obj *objp; - char *command, *function, *data, *result; + char *command, *function, *data; + const char *result; int i, timeout; API_INIT_FUNC(1, "hook_process", API_RETURN_EMPTY); @@ -2644,13 +2638,14 @@ API_FUNC(hook_process) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_process_hashtable) { Tcl_Obj *objp; - char *command, *function, *data, *result; + char *command, *function, *data; + const char *result; struct t_hashtable *options; int i, timeout; @@ -2681,7 +2676,7 @@ API_FUNC(hook_process_hashtable) if (options) weechat_hashtable_free (options); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2692,7 +2687,6 @@ weechat_tcl_api_hook_connect_cb (const void *pointer, void *data, { struct t_plugin_script *script; void *func_argv[6]; - char str_status[32], str_gnutls_rc[32], str_sock[32]; char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; int *rc, ret; @@ -2702,21 +2696,17 @@ weechat_tcl_api_hook_connect_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { - snprintf (str_status, sizeof (str_status), "%d", status); - snprintf (str_gnutls_rc, sizeof (str_gnutls_rc), "%d", gnutls_rc); - snprintf (str_sock, sizeof (str_sock), "%d", sock); - func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = str_status; - func_argv[2] = str_gnutls_rc; - func_argv[3] = str_sock; + func_argv[1] = &status; + func_argv[2] = &gnutls_rc; + func_argv[3] = &sock; func_argv[4] = (ip_address) ? (char *)ip_address : empty_arg; func_argv[5] = (error) ? (char *)error : empty_arg; rc = (int *) weechat_tcl_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "ssssss", func_argv); + "siiiss", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2735,7 +2725,8 @@ weechat_tcl_api_hook_connect_cb (const void *pointer, void *data, API_FUNC(hook_connect) { Tcl_Obj *objp; - char *proxy, *address, *local_hostname, *function, *data, *result; + char *proxy, *address, *local_hostname, *function, *data; + const char *result; int i, port, ipv6, retry; API_INIT_FUNC(1, "hook_connect", API_RETURN_EMPTY); @@ -2769,7 +2760,7 @@ API_FUNC(hook_connect) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2795,10 +2786,10 @@ weechat_tcl_api_hook_print_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { - snprintf (timebuffer, sizeof (timebuffer), "%ld", (long int)date); + snprintf (timebuffer, sizeof (timebuffer), "%lld", (long long)date); func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = timebuffer; func_argv[3] = weechat_string_build_with_split_string (tags, ","); if (!func_argv[3]) @@ -2820,8 +2811,6 @@ weechat_tcl_api_hook_print_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); if (func_argv[3]) free (func_argv[3]); @@ -2834,7 +2823,8 @@ weechat_tcl_api_hook_print_cb (const void *pointer, void *data, API_FUNC(hook_print) { Tcl_Obj *objp; - char *result, *buffer, *tags, *message, *function, *data; + char *buffer, *tags, *message, *function, *data; + const char *result; int i, strip_colors; API_INIT_FUNC(1, "hook_print", API_RETURN_EMPTY); @@ -2860,7 +2850,7 @@ API_FUNC(hook_print) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } int @@ -2873,7 +2863,7 @@ weechat_tcl_api_hook_signal_cb (const void *pointer, void *data, char empty_arg[1] = { '\0' }; const char *ptr_function, *ptr_data; static char str_value[64]; - int *rc, ret, free_needed; + int *rc, ret; script = (struct t_plugin_script *)pointer; plugin_script_get_function_and_data (data, &ptr_function, &ptr_data); @@ -2882,7 +2872,6 @@ weechat_tcl_api_hook_signal_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (signal) ? (char *)signal : empty_arg; - free_needed = 0; if (strcmp (type_data, WEECHAT_HOOK_SIGNAL_STRING) == 0) { func_argv[2] = (signal_data) ? (char *)signal_data : empty_arg; @@ -2899,8 +2888,7 @@ weechat_tcl_api_hook_signal_cb (const void *pointer, void *data, } else if (strcmp (type_data, WEECHAT_HOOK_SIGNAL_POINTER) == 0) { - func_argv[2] = API_PTR2STR(signal_data); - free_needed = 1; + func_argv[2] = (char *)API_PTR2STR(signal_data); } else func_argv[2] = empty_arg; @@ -2917,8 +2905,6 @@ weechat_tcl_api_hook_signal_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (free_needed && func_argv[2]) - free (func_argv[2]); return ret; } @@ -2929,7 +2915,8 @@ weechat_tcl_api_hook_signal_cb (const void *pointer, void *data, API_FUNC(hook_signal) { Tcl_Obj *objp; - char *result, *signal, *function, *data; + char *signal, *function, *data; + const char *result; int i; API_INIT_FUNC(1, "hook_signal", API_RETURN_EMPTY); @@ -2947,7 +2934,7 @@ API_FUNC(hook_signal) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_signal_send) @@ -3033,7 +3020,8 @@ weechat_tcl_api_hook_hsignal_cb (const void *pointer, void *data, API_FUNC(hook_hsignal) { Tcl_Obj *objp; - char *result, *signal, *function, *data; + char *signal, *function, *data; + const char *result; int i; API_INIT_FUNC(1, "hook_hsignal", API_RETURN_EMPTY); @@ -3051,7 +3039,7 @@ API_FUNC(hook_hsignal) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_hsignal_send) @@ -3120,7 +3108,8 @@ weechat_tcl_api_hook_config_cb (const void *pointer, void *data, API_FUNC(hook_config) { Tcl_Obj *objp; - char *result, *option, *function, *data; + char *option, *function, *data; + const char *result; int i; API_INIT_FUNC(1, "hook_config", API_RETURN_EMPTY); @@ -3138,7 +3127,7 @@ API_FUNC(hook_config) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } char * @@ -3174,7 +3163,8 @@ weechat_tcl_api_hook_modifier_cb (const void *pointer, void *data, API_FUNC(hook_modifier) { Tcl_Obj *objp; - char *result, *modifier, *function, *data; + char *modifier, *function, *data; + const char *result; int i; API_INIT_FUNC(1, "hook_modifier", API_RETURN_EMPTY); @@ -3192,7 +3182,7 @@ API_FUNC(hook_modifier) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_modifier_exec) @@ -3221,7 +3211,7 @@ weechat_tcl_api_hook_info_cb (const void *pointer, void *data, { struct t_plugin_script *script; void *func_argv[3]; - char empty_arg[1] = { '\0' }; + char empty_arg[1] = { '\0' }, *result; const char *ptr_function, *ptr_data; script = (struct t_plugin_script *)pointer; @@ -3233,10 +3223,12 @@ weechat_tcl_api_hook_info_cb (const void *pointer, void *data, func_argv[1] = (info_name) ? (char *)info_name : empty_arg; func_argv[2] = (arguments) ? (char *)arguments : empty_arg; - return (const char *)weechat_tcl_exec (script, - WEECHAT_SCRIPT_EXEC_STRING, - ptr_function, - "sss", func_argv); + result = (char *)weechat_tcl_exec (script, + WEECHAT_SCRIPT_EXEC_STRING, + ptr_function, + "sss", func_argv); + + return API_STATIC_STRING(result); } return NULL; @@ -3245,7 +3237,8 @@ weechat_tcl_api_hook_info_cb (const void *pointer, void *data, API_FUNC(hook_info) { Tcl_Obj *objp; - char *result, *info_name, *description, *args_description, *function, *data; + char *info_name, *description, *args_description, *function, *data; + const char *result; int i; API_INIT_FUNC(1, "hook_info", API_RETURN_EMPTY); @@ -3267,7 +3260,7 @@ API_FUNC(hook_info) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_hashtable * @@ -3302,8 +3295,9 @@ weechat_tcl_api_hook_info_hashtable_cb (const void *pointer, void *data, API_FUNC(hook_info_hashtable) { Tcl_Obj *objp; - char *result, *info_name, *description, *args_description; + char *info_name, *description, *args_description; char *output_description, *function, *data; + const char *result; int i; API_INIT_FUNC(1, "hook_info_hashtable", API_RETURN_EMPTY); @@ -3327,7 +3321,7 @@ API_FUNC(hook_info_hashtable) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_infolist * @@ -3348,18 +3342,15 @@ weechat_tcl_api_hook_infolist_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (infolist_name) ? (char *)infolist_name : empty_arg; - func_argv[2] = API_PTR2STR(obj_pointer); + func_argv[2] = (char *)API_PTR2STR(obj_pointer); func_argv[3] = (arguments) ? (char *)arguments : empty_arg; result = (struct t_infolist *)weechat_tcl_exec ( script, - WEECHAT_SCRIPT_EXEC_STRING, + WEECHAT_SCRIPT_EXEC_POINTER, ptr_function, "ssss", func_argv); - if (func_argv[2]) - free (func_argv[2]); - return result; } @@ -3369,8 +3360,9 @@ weechat_tcl_api_hook_infolist_cb (const void *pointer, void *data, API_FUNC(hook_infolist) { Tcl_Obj *objp; - char *result, *infolist_name, *description, *pointer_description; + char *infolist_name, *description, *pointer_description; char *args_description, *function, *data; + const char *result; int i; API_INIT_FUNC(1, "hook_infolist", API_RETURN_EMPTY); @@ -3394,7 +3386,7 @@ API_FUNC(hook_infolist) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } struct t_hashtable * @@ -3427,7 +3419,8 @@ weechat_tcl_api_hook_focus_cb (const void *pointer, void *data, API_FUNC(hook_focus) { Tcl_Obj *objp; - char *result, *area, *function, *data; + char *area, *function, *data; + const char *result; int i; API_INIT_FUNC(1, "hook_focus", API_RETURN_EMPTY); @@ -3445,7 +3438,7 @@ API_FUNC(hook_focus) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hook_set) @@ -3515,7 +3508,7 @@ weechat_tcl_api_buffer_input_data_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); func_argv[2] = (input_data) ? (char *)input_data : empty_arg; rc = (int *) weechat_tcl_exec (script, @@ -3529,8 +3522,6 @@ weechat_tcl_api_buffer_input_data_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -3554,7 +3545,7 @@ weechat_tcl_api_buffer_close_cb (const void *pointer, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(buffer); rc = (int *) weechat_tcl_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -3567,8 +3558,6 @@ weechat_tcl_api_buffer_close_cb (const void *pointer, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); return ret; } @@ -3579,8 +3568,8 @@ weechat_tcl_api_buffer_close_cb (const void *pointer, API_FUNC(buffer_new) { Tcl_Obj *objp; - char *result, *name, *function_input, *data_input, *function_close; - char *data_close; + char *name, *function_input, *data_input, *function_close, *data_close; + const char *result; int i; API_INIT_FUNC(1, "buffer_new", API_RETURN_EMPTY); @@ -3603,13 +3592,14 @@ API_FUNC(buffer_new) function_close, data_close)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_search) { Tcl_Obj *objp; - char *result, *plugin, *name; + char *plugin, *name; + const char *result; int i; API_INIT_FUNC(1, "buffer_search", API_RETURN_EMPTY); @@ -3621,13 +3611,13 @@ API_FUNC(buffer_search) result = API_PTR2STR(weechat_buffer_search (plugin, name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_search_main) { Tcl_Obj *objp; - char *result; + const char *result; /* make C compiler happy */ (void) clientData; @@ -3638,13 +3628,13 @@ API_FUNC(buffer_search_main) result = API_PTR2STR(weechat_buffer_search_main ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(current_buffer) { Tcl_Obj *objp; - char *result; + const char *result; /* make C compiler happy */ (void) clientData; @@ -3655,7 +3645,7 @@ API_FUNC(current_buffer) result = API_PTR2STR(weechat_current_buffer ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_clear) @@ -3761,7 +3751,8 @@ API_FUNC(buffer_get_string) API_FUNC(buffer_get_pointer) { Tcl_Obj *objp; - char *buffer, *property, *result; + char *buffer, *property; + const char *result; int i; API_INIT_FUNC(1, "buffer_get_pointer", API_RETURN_EMPTY); @@ -3774,7 +3765,7 @@ API_FUNC(buffer_get_pointer) result = API_PTR2STR(weechat_buffer_get_pointer (API_STR2PTR(buffer), property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(buffer_set) @@ -3836,7 +3827,7 @@ API_FUNC(buffer_match_list) API_FUNC(current_window) { Tcl_Obj *objp; - char *result; + const char *result; /* make C compiler happy */ (void) clientData; @@ -3847,13 +3838,14 @@ API_FUNC(current_window) result = API_PTR2STR(weechat_current_window ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(window_search_with_buffer) { Tcl_Obj *objp; - char *buffer, *result; + char *buffer; + const char *result; int i; API_INIT_FUNC(1, "window_search_with_buffer", API_RETURN_EMPTY); @@ -3864,7 +3856,7 @@ API_FUNC(window_search_with_buffer) result = API_PTR2STR(weechat_window_search_with_buffer (API_STR2PTR(buffer))); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(window_get_integer) @@ -3908,7 +3900,8 @@ API_FUNC(window_get_string) API_FUNC(window_get_pointer) { Tcl_Obj *objp; - char *window, *property, *result; + char *window, *property; + const char *result; int i; API_INIT_FUNC(1, "window_get_pointer", API_RETURN_EMPTY); @@ -3921,7 +3914,7 @@ API_FUNC(window_get_pointer) result = API_PTR2STR(weechat_window_get_pointer (API_STR2PTR(window), property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(window_set_title) @@ -3944,7 +3937,8 @@ API_FUNC(window_set_title) API_FUNC(nicklist_add_group) { Tcl_Obj *objp; - char *result, *buffer, *parent_group, *name, *color; + char *buffer, *parent_group, *name, *color; + const char *result; int i, visible; API_INIT_FUNC(1, "nicklist_add_group", API_RETURN_EMPTY); @@ -3965,13 +3959,14 @@ API_FUNC(nicklist_add_group) color, visible)); /* visible */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_search_group) { Tcl_Obj *objp; - char *result, *buffer, *from_group, *name; + char *buffer, *from_group, *name; + const char *result; int i; API_INIT_FUNC(1, "nicklist_search_group", API_RETURN_EMPTY); @@ -3986,13 +3981,14 @@ API_FUNC(nicklist_search_group) API_STR2PTR(from_group), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_add_nick) { Tcl_Obj *objp; - char *result, *buffer, *group, *name, *color, *prefix, *prefix_color; + char *buffer, *group, *name, *color, *prefix, *prefix_color; + const char *result; int i, visible; API_INIT_FUNC(1, "nicklist_add_nick", API_RETURN_EMPTY); @@ -4017,13 +4013,14 @@ API_FUNC(nicklist_add_nick) prefix_color, visible)); /* visible */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_search_nick) { Tcl_Obj *objp; - char *result, *buffer, *from_group, *name; + char *buffer, *from_group, *name; + const char *result; int i; API_INIT_FUNC(1, "nicklist_search_nick", API_RETURN_EMPTY); @@ -4038,7 +4035,7 @@ API_FUNC(nicklist_search_nick) API_STR2PTR(from_group), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_remove_group) @@ -4140,7 +4137,8 @@ API_FUNC(nicklist_group_get_string) API_FUNC(nicklist_group_get_pointer) { Tcl_Obj *objp; - char *buffer, *group, *property, *result; + char *buffer, *group, *property; + const char *result; int i; API_INIT_FUNC(1, "nicklist_group_get_pointer", API_RETURN_EMPTY); @@ -4155,7 +4153,7 @@ API_FUNC(nicklist_group_get_pointer) API_STR2PTR(group), property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_group_set) @@ -4228,7 +4226,8 @@ API_FUNC(nicklist_nick_get_string) API_FUNC(nicklist_nick_get_pointer) { Tcl_Obj *objp; - char *buffer, *nick, *property, *result; + char *buffer, *nick, *property; + const char *result; int i; API_INIT_FUNC(1, "nicklist_nick_get_pointer", API_RETURN_EMPTY); @@ -4243,7 +4242,7 @@ API_FUNC(nicklist_nick_get_pointer) API_STR2PTR(nick), property)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(nicklist_nick_set) @@ -4272,7 +4271,7 @@ API_FUNC(nicklist_nick_set) API_FUNC(bar_item_search) { Tcl_Obj *objp; - char *result; + const char *result; int i; API_INIT_FUNC(1, "bar_item_search", API_RETURN_EMPTY); @@ -4281,7 +4280,7 @@ API_FUNC(bar_item_search) result = API_PTR2STR(weechat_bar_item_search (Tcl_GetStringFromObj (objv[1], &i))); /* name */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } char * @@ -4305,39 +4304,27 @@ weechat_tcl_api_bar_item_build_cb (const void *pointer, void *data, { /* new callback: data, item, window, buffer, extra_info */ func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(item); - func_argv[2] = API_PTR2STR(window); - func_argv[3] = API_PTR2STR(buffer); + func_argv[1] = (char *)API_PTR2STR(item); + func_argv[2] = (char *)API_PTR2STR(window); + func_argv[3] = (char *)API_PTR2STR(buffer); func_argv[4] = extra_info; ret = (char *)weechat_tcl_exec (script, WEECHAT_SCRIPT_EXEC_STRING, ptr_function + 7, "ssssh", func_argv); - - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); - if (func_argv[3]) - free (func_argv[3]); } else { /* old callback: data, item, window */ func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(item); - func_argv[2] = API_PTR2STR(window); + func_argv[1] = (char *)API_PTR2STR(item); + func_argv[2] = (char *)API_PTR2STR(window); ret = (char *)weechat_tcl_exec (script, WEECHAT_SCRIPT_EXEC_STRING, ptr_function, "sss", func_argv); - - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[2]) - free (func_argv[2]); } return ret; @@ -4349,7 +4336,8 @@ weechat_tcl_api_bar_item_build_cb (const void *pointer, void *data, API_FUNC(bar_item_new) { Tcl_Obj *objp; - char *result, *name, *function, *data; + char *name, *function, *data; + const char *result; int i; API_INIT_FUNC(1, "bar_item_new", API_RETURN_EMPTY); @@ -4367,7 +4355,7 @@ API_FUNC(bar_item_new) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(bar_item_update) @@ -4402,7 +4390,7 @@ API_FUNC(bar_item_remove) API_FUNC(bar_search) { Tcl_Obj *objp; - char *result; + const char *result; int i; API_INIT_FUNC(1, "bar_search", API_RETURN_EMPTY); @@ -4411,15 +4399,16 @@ API_FUNC(bar_search) result = API_PTR2STR(weechat_bar_search (Tcl_GetStringFromObj (objv[1], &i))); /* name */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(bar_new) { Tcl_Obj *objp; - char *result, *name, *hidden, *priority, *type, *conditions, *position; + char *name, *hidden, *priority, *type, *conditions, *position; char *filling_top_bottom, *filling_left_right, *size, *size_max, *color_fg; char *color_delim, *color_bg, *separator, *bar_items; + const char *result; int i; API_INIT_FUNC(1, "bar_new", API_RETURN_EMPTY); @@ -4458,7 +4447,7 @@ API_FUNC(bar_new) separator, bar_items)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(bar_set) @@ -4575,7 +4564,7 @@ API_FUNC(info_get_hashtable) API_FUNC(infolist_new) { Tcl_Obj *objp; - char *result; + const char *result; /* make C compiler happy */ (void) clientData; @@ -4586,13 +4575,13 @@ API_FUNC(infolist_new) result = API_PTR2STR(weechat_infolist_new ()); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_item) { Tcl_Obj *objp; - char *result; + const char *result; int i; API_INIT_FUNC(1, "infolist_new_item", API_RETURN_EMPTY); @@ -4601,13 +4590,13 @@ API_FUNC(infolist_new_item) result = API_PTR2STR(weechat_infolist_new_item (API_STR2PTR(Tcl_GetStringFromObj (objv[1], &i)))); /* infolist */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_integer) { Tcl_Obj *objp; - char *result; + const char *result; int i, value; API_INIT_FUNC(1, "infolist_new_var_integer", API_RETURN_EMPTY); @@ -4621,13 +4610,13 @@ API_FUNC(infolist_new_var_integer) Tcl_GetStringFromObj (objv[2], &i), /* name */ value)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_string) { Tcl_Obj *objp; - char *result; + const char *result; int i; API_INIT_FUNC(1, "infolist_new_var_string", API_RETURN_EMPTY); @@ -4638,13 +4627,13 @@ API_FUNC(infolist_new_var_string) Tcl_GetStringFromObj (objv[2], &i), /* name */ Tcl_GetStringFromObj (objv[3], &i))); /* value */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_pointer) { Tcl_Obj *objp; - char *result; + const char *result; int i; API_INIT_FUNC(1, "infolist_new_var_pointer", API_RETURN_EMPTY); @@ -4655,13 +4644,13 @@ API_FUNC(infolist_new_var_pointer) Tcl_GetStringFromObj (objv[2], &i), /* name */ API_STR2PTR(Tcl_GetStringFromObj (objv[3], &i)))); /* value */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_new_var_time) { Tcl_Obj *objp; - char *result; + const char *result; int i, value; API_INIT_FUNC(1, "infolist_new_var_time", API_RETURN_EMPTY); @@ -4675,13 +4664,13 @@ API_FUNC(infolist_new_var_time) Tcl_GetStringFromObj (objv[2], &i), /* name */ value)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_search_var) { Tcl_Obj *objp; - char *result; + const char *result; int i; API_INIT_FUNC(1, "infolist_search_var", API_RETURN_EMPTY); @@ -4691,13 +4680,14 @@ API_FUNC(infolist_search_var) result = API_PTR2STR(weechat_infolist_search_var (API_STR2PTR(Tcl_GetStringFromObj (objv[1], &i)), /* infolist */ Tcl_GetStringFromObj (objv[2], &i))); /* name */ - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_get) { Tcl_Obj *objp; - char *result, *name, *pointer, *arguments; + char *name, *pointer, *arguments; + const char *result; int i; API_INIT_FUNC(1, "infolist_get", API_RETURN_EMPTY); @@ -4712,7 +4702,7 @@ API_FUNC(infolist_get) API_STR2PTR(pointer), arguments)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_next) @@ -4812,7 +4802,8 @@ API_FUNC(infolist_string) API_FUNC(infolist_pointer) { Tcl_Obj *objp; - char *infolist, *variable, *result; + char *infolist, *variable; + const char *result; int i; API_INIT_FUNC(1, "infolist_pointer", API_RETURN_EMPTY); @@ -4824,32 +4815,26 @@ API_FUNC(infolist_pointer) result = API_PTR2STR(weechat_infolist_pointer (API_STR2PTR(infolist), variable)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(infolist_time) { Tcl_Obj *objp; time_t time; - struct tm *date_tmp; - char timebuffer[64], *result, *infolist, *variable; + char *infolist, *variable; int i; - API_INIT_FUNC(1, "infolist_time", API_RETURN_EMPTY); + API_INIT_FUNC(1, "infolist_time", API_RETURN_LONG(0)); if (objc < 3) - API_WRONG_ARGS(API_RETURN_EMPTY); + API_WRONG_ARGS(API_RETURN_LONG(0)); infolist = Tcl_GetStringFromObj (objv[1], &i); variable = Tcl_GetStringFromObj (objv[2], &i); - timebuffer[0] = '\0'; time = weechat_infolist_time (API_STR2PTR(infolist), variable); - date_tmp = localtime (&time); - if (date_tmp) - strftime (timebuffer, sizeof (timebuffer), "%F %T", date_tmp); - result = strdup (timebuffer); - API_RETURN_STRING_FREE(result); + API_RETURN_LONG(time); } API_FUNC(infolist_free) @@ -4869,7 +4854,8 @@ API_FUNC(infolist_free) API_FUNC(hdata_get) { Tcl_Obj *objp; - char *result, *name; + char *name; + const char *result; int i; API_INIT_FUNC(1, "hdata_get", API_RETURN_EMPTY); @@ -4880,7 +4866,7 @@ API_FUNC(hdata_get) result = API_PTR2STR(weechat_hdata_get (name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_get_var_offset) @@ -4985,7 +4971,8 @@ API_FUNC(hdata_get_var_hdata) API_FUNC(hdata_get_list) { Tcl_Obj *objp; - char *hdata, *name, *result; + char *hdata, *name; + const char *result; int i; API_INIT_FUNC(1, "hdata_get_list", API_RETURN_EMPTY); @@ -4998,7 +4985,7 @@ API_FUNC(hdata_get_list) result = API_PTR2STR(weechat_hdata_get_list (API_STR2PTR(hdata), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_check_pointer) @@ -5025,7 +5012,8 @@ API_FUNC(hdata_check_pointer) API_FUNC(hdata_move) { Tcl_Obj *objp; - char *hdata, *pointer, *result; + char *hdata, *pointer; + const char *result; int i, count; API_INIT_FUNC(1, "hdata_move", API_RETURN_EMPTY); @@ -5042,13 +5030,14 @@ API_FUNC(hdata_move) API_STR2PTR(pointer), count)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_search) { Tcl_Obj *objp; - char *hdata, *pointer, *search, *result; + char *hdata, *pointer, *search; + const char *result; int i, move; API_INIT_FUNC(1, "hdata_search", API_RETURN_EMPTY); @@ -5067,7 +5056,7 @@ API_FUNC(hdata_search) search, move)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_char) @@ -5158,7 +5147,8 @@ API_FUNC(hdata_string) API_FUNC(hdata_pointer) { Tcl_Obj *objp; - char *hdata, *pointer, *name, *result; + char *hdata, *pointer, *name; + const char *result; int i; API_INIT_FUNC(1, "hdata_pointer", API_RETURN_EMPTY); @@ -5173,7 +5163,7 @@ API_FUNC(hdata_pointer) API_STR2PTR(pointer), name)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(hdata_time) @@ -5315,9 +5305,9 @@ weechat_tcl_api_upgrade_read_cb (const void *pointer, void *data, snprintf (str_object_id, sizeof (str_object_id), "%d", object_id); func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = API_PTR2STR(upgrade_file); + func_argv[1] = (char *)API_PTR2STR(upgrade_file); func_argv[2] = str_object_id; - func_argv[3] = API_PTR2STR(infolist); + func_argv[3] = (char *)API_PTR2STR(infolist); rc = (int *) weechat_tcl_exec (script, WEECHAT_SCRIPT_EXEC_INT, @@ -5331,10 +5321,6 @@ weechat_tcl_api_upgrade_read_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - free (func_argv[1]); - if (func_argv[3]) - free (func_argv[3]); return ret; } @@ -5345,7 +5331,8 @@ weechat_tcl_api_upgrade_read_cb (const void *pointer, void *data, API_FUNC(upgrade_new) { Tcl_Obj *objp; - char *result, *filename, *function, *data; + char *filename, *function, *data; + const char *result; int i; API_INIT_FUNC(1, "upgrade_new", API_RETURN_EMPTY); @@ -5365,7 +5352,7 @@ API_FUNC(upgrade_new) function, data)); - API_RETURN_STRING_FREE(result); + API_RETURN_STRING(result); } API_FUNC(upgrade_write_object) @@ -5546,6 +5533,7 @@ void weechat_tcl_api_init (Tcl_Interp *interp) API_DEF_FUNC(string_has_highlight); API_DEF_FUNC(string_has_highlight_regex); API_DEF_FUNC(string_mask_to_regex); + API_DEF_FUNC(string_format_size); API_DEF_FUNC(string_remove_color); API_DEF_FUNC(string_is_command_char); API_DEF_FUNC(string_input_for_buffer); diff --git a/src/plugins/tcl/weechat-tcl-api.h b/src/plugins/tcl/weechat-tcl-api.h index 61d4e15f0..600a25fab 100644 --- a/src/plugins/tcl/weechat-tcl-api.h +++ b/src/plugins/tcl/weechat-tcl-api.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2008-2010 Dmitry Kobylin <fnfal@academ.tsc.ru> - * Copyright (C) 2008-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2008-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_TCL_API_H -#define WEECHAT_TCL_API_H 1 +#ifndef WEECHAT_PLUGIN_TCL_API_H +#define WEECHAT_PLUGIN_TCL_API_H extern int weechat_tcl_api_buffer_input_data_cb (const void *pointer, void *data, @@ -30,4 +30,4 @@ extern int weechat_tcl_api_buffer_close_cb (const void *pointer, struct t_gui_buffer *buffer); extern void weechat_tcl_api_init (Tcl_Interp *interp); -#endif /* WEECHAT_TCL_API_H */ +#endif /* WEECHAT_PLUGIN_TCL_API_H */ diff --git a/src/plugins/tcl/weechat-tcl.c b/src/plugins/tcl/weechat-tcl.c index 1523fde0a..f0e138569 100644 --- a/src/plugins/tcl/weechat-tcl.c +++ b/src/plugins/tcl/weechat-tcl.c @@ -2,7 +2,7 @@ * weechat-tcl.c - tcl plugin for WeeChat * * Copyright (C) 2008-2010 Dmitry Kobylin <fnfal@academ.tsc.ru> - * Copyright (C) 2008-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2008-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -40,11 +40,25 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Support of tcl scripts")); WEECHAT_PLUGIN_AUTHOR("Dmitry Kobylin <fnfal@academ.tsc.ru>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(3000); +WEECHAT_PLUGIN_PRIORITY(4000); struct t_weechat_plugin *weechat_tcl_plugin = NULL; +struct t_plugin_script_data tcl_data; + +struct t_config_file *tcl_config_file = NULL; +struct t_config_option *tcl_config_look_check_license = NULL; +struct t_config_option *tcl_config_look_eval_keep_context = NULL; + int tcl_quiet = 0; + +struct t_plugin_script *tcl_script_eval = NULL; +int tcl_eval_mode = 0; +int tcl_eval_send_input = 0; +int tcl_eval_exec_commands = 0; +struct t_gui_buffer *tcl_eval_buffer = NULL; +char *tcl_eval_output = NULL; + struct t_plugin_script *tcl_scripts = NULL; struct t_plugin_script *last_tcl_script = NULL; struct t_plugin_script *tcl_current_script = NULL; @@ -151,7 +165,7 @@ weechat_tcl_dict_to_hashtable (Tcl_Interp *interp, Tcl_Obj *dict, if (Tcl_DictObjFirst (interp, dict, &search, &key, &value, &done) == TCL_OK) { - for (; !done ; Tcl_DictObjNext(&search, &key, &value, &done)) + for (; !done ; Tcl_DictObjNext (&search, &key, &value, &done)) { if (strcmp (type_values, WEECHAT_HASHTABLE_STRING) == 0) { @@ -237,8 +251,9 @@ weechat_tcl_exec (struct t_plugin_script *script, if (Tcl_EvalObjEx (interp, cmdlist, TCL_EVAL_DIRECT) == TCL_OK) { - Tcl_ListObjReplace (interp, cmdlist, 0, llength, 0, NULL); /* remove elements, decrement their ref count */ - Tcl_DecrRefCount (cmdlist); /* -1 */ + /* remove elements, decrement their ref count */ + Tcl_ListObjReplace (interp, cmdlist, 0, llength, 0, NULL); + Tcl_DecrRefCount (cmdlist); /* -1 */ ret_val = NULL; if (ret_type == WEECHAT_SCRIPT_EXEC_STRING) { @@ -248,6 +263,18 @@ weechat_tcl_exec (struct t_plugin_script *script, else ret_val = NULL; } + else if (ret_type == WEECHAT_SCRIPT_EXEC_POINTER) + { + ret_cv = Tcl_GetStringFromObj (Tcl_GetObjResult (interp), &i); + if (ret_cv) + { + ret_val = plugin_script_str2ptr (weechat_tcl_plugin, + script->name, function, + ret_cv); + } + else + ret_val = NULL; + } else if ( ret_type == WEECHAT_SCRIPT_EXEC_INT && Tcl_GetIntFromObj (interp, Tcl_GetObjResult (interp), &i) == TCL_OK) { @@ -269,15 +296,21 @@ weechat_tcl_exec (struct t_plugin_script *script, if (ret_val) return ret_val; - weechat_printf (NULL, - weechat_gettext ("%s%s: function \"%s\" must return a " - "valid value"), - weechat_prefix ("error"), TCL_PLUGIN_NAME, function); + if (ret_type != WEECHAT_SCRIPT_EXEC_IGNORE) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: function \"%s\" must " + "return a valid value"), + weechat_prefix ("error"), TCL_PLUGIN_NAME, + function); + } + return NULL; } - Tcl_ListObjReplace (interp, cmdlist, 0, llength, 0, NULL); /* remove elements, decrement their ref count */ - Tcl_DecrRefCount (cmdlist); /* -1 */ + /* remove elements, decrement their ref count */ + Tcl_ListObjReplace (interp, cmdlist, 0, llength, 0, NULL); + Tcl_DecrRefCount (cmdlist); /* -1 */ weechat_printf (NULL, weechat_gettext ("%s%s: unable to run function \"%s\": %s"), weechat_prefix ("error"), TCL_PLUGIN_NAME, function, @@ -290,24 +323,29 @@ weechat_tcl_exec (struct t_plugin_script *script, /* * Loads a tcl script. * - * Returns: - * 1: OK - * 0: error + * If code is NULL, the content of filename is read and executed. + * If code is not NULL, it is executed (the file is not read). + * + * Returns pointer to new registered script, NULL if error. */ -int -weechat_tcl_load (const char *filename) +struct t_plugin_script * +weechat_tcl_load (const char *filename, const char *code) { int i; Tcl_Interp *interp; struct stat buf; + /* make C compiler happy */ + /* TODO: implement load of code in TCL */ + (void) code; + if (stat (filename, &buf) != 0) { weechat_printf (NULL, weechat_gettext ("%s%s: script \"%s\" not found"), weechat_prefix ("error"), TCL_PLUGIN_NAME, filename); - return 0; + return NULL; } if ((weechat_tcl_plugin->debug >= 2) || !tcl_quiet) @@ -325,7 +363,7 @@ weechat_tcl_load (const char *filename) weechat_gettext ("%s%s: unable to create new " "interpreter"), weechat_prefix ("error"), TCL_PLUGIN_NAME); - return 0; + return NULL; } tcl_current_script_filename = filename; @@ -348,7 +386,7 @@ weechat_tcl_load (const char *filename) tcl_current_script = NULL; } - return 0; + return NULL; } if (!tcl_registered_script) @@ -358,7 +396,7 @@ weechat_tcl_load (const char *filename) "found (or failed) in file \"%s\""), weechat_prefix ("error"), TCL_PLUGIN_NAME, filename); Tcl_DeleteInterp (interp); - return 0; + return NULL; } tcl_current_script = tcl_registered_script; @@ -376,7 +414,7 @@ weechat_tcl_load (const char *filename) WEECHAT_HOOK_SIGNAL_STRING, tcl_current_script->filename); - return 1; + return tcl_current_script; } /* @@ -389,7 +427,7 @@ weechat_tcl_load_cb (void *data, const char *filename) /* make C compiler happy */ (void) data; - weechat_tcl_load (filename); + weechat_tcl_load (filename, NULL); } /* @@ -429,7 +467,7 @@ weechat_tcl_unload (struct t_plugin_script *script) plugin_script_remove (weechat_tcl_plugin, &tcl_scripts, &last_tcl_script, script); - Tcl_DeleteInterp(interp); + Tcl_DeleteInterp (interp); (void) weechat_hook_signal_send ("tcl_script_unloaded", WEECHAT_HOOK_SIGNAL_STRING, filename); @@ -501,7 +539,7 @@ weechat_tcl_reload_name (const char *name) weechat_gettext ("%s: script \"%s\" unloaded"), TCL_PLUGIN_NAME, name); } - weechat_tcl_load (filename); + weechat_tcl_load (filename, NULL); free (filename); } } @@ -514,6 +552,27 @@ weechat_tcl_reload_name (const char *name) } /* + * Evaluates TCL source code. + * + * Returns: + * 1: OK + * 0: error + */ + +int +weechat_tcl_eval (struct t_gui_buffer *buffer, int send_to_buffer_as_input, + int exec_commands, const char *code) +{ + /* TODO: implement tcl eval */ + (void) buffer; + (void) send_to_buffer_as_input; + (void) exec_commands; + (void) code; + + return 1; +} + +/* * Callback for command "/tcl". */ @@ -522,12 +581,12 @@ weechat_tcl_command_cb (const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { - char *ptr_name, *path_script; + char *ptr_name, *ptr_code, *path_script; + int i, send_to_buffer_as_input, exec_commands; /* make C compiler happy */ (void) pointer; (void) data; - (void) buffer; if (argc == 1) { @@ -559,6 +618,10 @@ weechat_tcl_command_cb (const void *pointer, void *data, { weechat_tcl_unload_all (); } + else if (weechat_strcasecmp (argv[1], "version") == 0) + { + plugin_script_display_interpreter (weechat_tcl_plugin, 0); + } else WEECHAT_COMMAND_ERROR; } @@ -593,7 +656,8 @@ weechat_tcl_command_cb (const void *pointer, void *data, /* load tcl script */ path_script = plugin_script_search_path (weechat_tcl_plugin, ptr_name); - weechat_tcl_load ((path_script) ? path_script : ptr_name); + weechat_tcl_load ((path_script) ? path_script : ptr_name, + NULL); if (path_script) free (path_script); } @@ -609,6 +673,44 @@ weechat_tcl_command_cb (const void *pointer, void *data, } tcl_quiet = 0; } + else if (weechat_strcasecmp (argv[1], "eval") == 0) + { + send_to_buffer_as_input = 0; + exec_commands = 0; + ptr_code = argv_eol[2]; + for (i = 2; i < argc; i++) + { + if (argv[i][0] == '-') + { + if (strcmp (argv[i], "-o") == 0) + { + if (i + 1 >= argc) + WEECHAT_COMMAND_ERROR; + send_to_buffer_as_input = 1; + exec_commands = 0; + ptr_code = argv_eol[i + 1]; + } + else if (strcmp (argv[i], "-oc") == 0) + { + if (i + 1 >= argc) + WEECHAT_COMMAND_ERROR; + send_to_buffer_as_input = 1; + exec_commands = 1; + ptr_code = argv_eol[i + 1]; + } + } + else + break; + } + if (!weechat_tcl_eval (buffer, send_to_buffer_as_input, + exec_commands, ptr_code)) + WEECHAT_COMMAND_ERROR; + /* TODO: implement /tcl eval */ + weechat_printf (NULL, + _("%sCommand \"/%s eval\" is not yet implemented"), + weechat_prefix ("error"), + weechat_tcl_plugin->name); + } else WEECHAT_COMMAND_ERROR; } @@ -655,6 +757,26 @@ weechat_tcl_hdata_cb (const void *pointer, void *data, } /* + * Returns tcl info "tcl_eval". + */ + +const char * +weechat_tcl_info_eval_cb (const void *pointer, void *data, + const char *info_name, + const char *arguments) +{ + static const char *not_implemented = "not yet implemented"; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) info_name; + (void) arguments; + + return not_implemented; +} + +/* * Returns infolist with tcl scripts. */ @@ -705,31 +827,6 @@ weechat_tcl_signal_debug_dump_cb (const void *pointer, void *data, } /* - * Display infos about external libraries used. - */ - -int -weechat_tcl_signal_debug_libs_cb (const void *pointer, void *data, - const char *signal, - const char *type_data, void *signal_data) -{ - /* make C compiler happy */ - (void) pointer; - (void) data; - (void) signal; - (void) type_data; - (void) signal_data; - -#ifdef TCL_VERSION - weechat_printf (NULL, " %s: %s", TCL_PLUGIN_NAME, TCL_VERSION); -#else - weechat_printf (NULL, " %s: (?)", TCL_PLUGIN_NAME); -#endif /* TCL_VERSION */ - - return WEECHAT_RC_OK; -} - -/* * Timer for executing actions. */ @@ -823,21 +920,36 @@ weechat_tcl_signal_script_action_cb (const void *pointer, void *data, int weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) { - struct t_plugin_script_init init; - weechat_tcl_plugin = plugin; - init.callback_command = &weechat_tcl_command_cb; - init.callback_completion = &weechat_tcl_completion_cb; - init.callback_hdata = &weechat_tcl_hdata_cb; - init.callback_infolist = &weechat_tcl_infolist_cb; - init.callback_signal_debug_dump = &weechat_tcl_signal_debug_dump_cb; - init.callback_signal_debug_libs = &weechat_tcl_signal_debug_libs_cb; - init.callback_signal_script_action = &weechat_tcl_signal_script_action_cb; - init.callback_load_file = &weechat_tcl_load_cb; + /* set interpreter name and version */ + weechat_hashtable_set (plugin->variables, "interpreter_name", + plugin->name); +#ifdef TCL_VERSION + weechat_hashtable_set (plugin->variables, "interpreter_version", + TCL_VERSION); +#else + weechat_hashtable_set (plugin->variables, "interpreter_version", + ""); +#endif /* TCL_VERSION */ + + tcl_data.config_file = &tcl_config_file; + tcl_data.config_look_check_license = &tcl_config_look_check_license; + tcl_data.config_look_eval_keep_context = &tcl_config_look_eval_keep_context; + tcl_data.scripts = &tcl_scripts; + tcl_data.last_script = &last_tcl_script; + tcl_data.callback_command = &weechat_tcl_command_cb; + tcl_data.callback_completion = &weechat_tcl_completion_cb; + tcl_data.callback_hdata = &weechat_tcl_hdata_cb; + tcl_data.callback_info_eval = &weechat_tcl_info_eval_cb; + tcl_data.callback_infolist = &weechat_tcl_infolist_cb; + tcl_data.callback_signal_debug_dump = &weechat_tcl_signal_debug_dump_cb; + tcl_data.callback_signal_script_action = &weechat_tcl_signal_script_action_cb; + tcl_data.callback_load_file = &weechat_tcl_load_cb; + tcl_data.unload_all = &weechat_tcl_unload_all; tcl_quiet = 1; - plugin_script_init (weechat_tcl_plugin, argc, argv, &init); + plugin_script_init (weechat_tcl_plugin, argc, argv, &tcl_data); tcl_quiet = 0; plugin_script_display_short_list (weechat_tcl_plugin, @@ -856,7 +968,12 @@ weechat_plugin_end (struct t_weechat_plugin *plugin) { /* unload all scripts */ tcl_quiet = 1; - plugin_script_end (plugin, &tcl_scripts, &weechat_tcl_unload_all); + if (tcl_script_eval) + { + weechat_tcl_unload (tcl_script_eval); + tcl_script_eval = NULL; + } + plugin_script_end (plugin, &tcl_data); tcl_quiet = 0; /* free some data */ @@ -866,6 +983,9 @@ weechat_plugin_end (struct t_weechat_plugin *plugin) free (tcl_action_remove_list); if (tcl_action_autoload_list) free (tcl_action_autoload_list); + /* weechat_string_dyn_free (tcl_buffer_output, 1); */ + if (tcl_eval_output) + free (tcl_eval_output); return WEECHAT_RC_OK; } diff --git a/src/plugins/tcl/weechat-tcl.h b/src/plugins/tcl/weechat-tcl.h index dbf2576c2..c5fa8c359 100644 --- a/src/plugins/tcl/weechat-tcl.h +++ b/src/plugins/tcl/weechat-tcl.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2008-2010 Dmitry Kobylin <fnfal@academ.tsc.ru> - * Copyright (C) 2008-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2008-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_TCL_H -#define WEECHAT_TCL_H 1 +#ifndef WEECHAT_PLUGIN_TCL_H +#define WEECHAT_PLUGIN_TCL_H #define weechat_plugin weechat_tcl_plugin #define TCL_PLUGIN_NAME "tcl" @@ -28,6 +28,8 @@ extern struct t_weechat_plugin *weechat_tcl_plugin; +extern struct t_plugin_script_data tcl_data; + extern int tcl_quiet; extern struct t_plugin_script *tcl_scripts; extern struct t_plugin_script *last_tcl_script; @@ -46,4 +48,4 @@ extern void *weechat_tcl_exec (struct t_plugin_script *script, int ret_type, const char *function, const char *format, void **argv); -#endif /* WEECHAT_TCL_H */ +#endif /* WEECHAT_PLUGIN_TCL_H */ diff --git a/src/plugins/trigger/CMakeLists.txt b/src/plugins/trigger/CMakeLists.txt index b9d766c9e..b67f95881 100644 --- a/src/plugins/trigger/CMakeLists.txt +++ b/src/plugins/trigger/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/trigger/Makefile.am b/src/plugins/trigger/Makefile.am index cff2640ef..cf629b1f2 100644 --- a/src/plugins/trigger/Makefile.am +++ b/src/plugins/trigger/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/trigger/trigger-buffer.c b/src/plugins/trigger/trigger-buffer.c index d901cea00..43867ff64 100644 --- a/src/plugins/trigger/trigger-buffer.c +++ b/src/plugins/trigger/trigger-buffer.c @@ -1,7 +1,7 @@ /* * trigger-buffer.c - debug buffer for triggers * - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/trigger/trigger-buffer.h b/src/plugins/trigger/trigger-buffer.h index 0b96797d7..9ab5fc871 100644 --- a/src/plugins/trigger/trigger-buffer.h +++ b/src/plugins/trigger/trigger-buffer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_TRIGGER_BUFFER_H -#define WEECHAT_TRIGGER_BUFFER_H 1 +#ifndef WEECHAT_PLUGIN_TRIGGER_BUFFER_H +#define WEECHAT_PLUGIN_TRIGGER_BUFFER_H #define TRIGGER_BUFFER_NAME "monitor" @@ -32,4 +32,4 @@ extern int trigger_buffer_display_trigger (struct t_trigger *trigger, struct t_hashtable *extra_vars); extern void trigger_buffer_end (); -#endif /* WEECHAT_TRIGGER_BUFFER_H */ +#endif /* WEECHAT_PLUGIN_TRIGGER_BUFFER_H */ diff --git a/src/plugins/trigger/trigger-callback.c b/src/plugins/trigger/trigger-callback.c index 79b2955a9..2ed0909b4 100644 --- a/src/plugins/trigger/trigger-callback.c +++ b/src/plugins/trigger/trigger-callback.c @@ -1,7 +1,7 @@ /* * trigger-callback.c - callbacks for triggers * - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -798,7 +798,9 @@ trigger_callback_print_cb (const void *pointer, void *data, date_tmp = localtime (&date); if (date_tmp) { - strftime (str_temp, sizeof (str_temp), "%Y-%m-%d %H:%M:%S", date_tmp); + if (strftime (str_temp, sizeof (str_temp), + "%Y-%m-%d %H:%M:%S", date_tmp) == 0) + str_temp[0] = '\0'; weechat_hashtable_set (extra_vars, "tg_date", str_temp); } snprintf (str_temp, sizeof (str_temp), "%d", displayed); @@ -940,7 +942,9 @@ trigger_callback_timer_cb (const void *pointer, void *data, date_tmp = localtime (&date); if (date_tmp) { - strftime (str_temp, sizeof (str_temp), "%Y-%m-%d %H:%M:%S", date_tmp); + if (strftime (str_temp, sizeof (str_temp), + "%Y-%m-%d %H:%M:%S", date_tmp) == 0) + str_temp[0] = '\0'; weechat_hashtable_set (extra_vars, "tg_date", str_temp); } diff --git a/src/plugins/trigger/trigger-callback.h b/src/plugins/trigger/trigger-callback.h index 0af3c5ab6..8eeec3171 100644 --- a/src/plugins/trigger/trigger-callback.h +++ b/src/plugins/trigger/trigger-callback.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_TRIGGER_CALLBACK_H -#define WEECHAT_TRIGGER_CALLBACK_H 1 +#ifndef WEECHAT_PLUGIN_TRIGGER_CALLBACK_H +#define WEECHAT_PLUGIN_TRIGGER_CALLBACK_H #include <time.h> @@ -118,4 +118,4 @@ extern struct t_hashtable *trigger_callback_focus_cb (const void *pointer, extern void trigger_callback_init (); extern void trigger_callback_end (); -#endif /* WEECHAT_TRIGGER_CALLBACK_H */ +#endif /* WEECHAT_PLUGIN_TRIGGER_CALLBACK_H */ diff --git a/src/plugins/trigger/trigger-command.c b/src/plugins/trigger/trigger-command.c index 2e49a5478..5de047bc1 100644 --- a/src/plugins/trigger/trigger-command.c +++ b/src/plugins/trigger/trigger-command.c @@ -1,7 +1,7 @@ /* * trigger-command.c - trigger command * - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -1171,7 +1171,7 @@ trigger_command_init () " regex: one or more regular expressions to replace strings " "in variables\n" " command: command to execute (many commands can be separated by " - "\";\"\n" + "\";\")\n" "return_code: return code in callback (ok (default), ok_eat, error)\n" "post_action: action to take after execution (none (default), " "disable, delete)\n" diff --git a/src/plugins/trigger/trigger-command.h b/src/plugins/trigger/trigger-command.h index 4336c9730..43eeec6d9 100644 --- a/src/plugins/trigger/trigger-command.h +++ b/src/plugins/trigger/trigger-command.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_TRIGGER_COMMAND_H -#define WEECHAT_TRIGGER_COMMAND_H 1 +#ifndef WEECHAT_PLUGIN_TRIGGER_COMMAND_H +#define WEECHAT_PLUGIN_TRIGGER_COMMAND_H extern void trigger_command_init (); -#endif /* WEECHAT_TRIGGER_COMMAND_H */ +#endif /* WEECHAT_PLUGIN_TRIGGER_COMMAND_H */ diff --git a/src/plugins/trigger/trigger-completion.c b/src/plugins/trigger/trigger-completion.c index 52977bc4b..90c950597 100644 --- a/src/plugins/trigger/trigger-completion.c +++ b/src/plugins/trigger/trigger-completion.c @@ -1,7 +1,7 @@ /* * trigger-completion.c - completion for trigger commands * - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/trigger/trigger-completion.h b/src/plugins/trigger/trigger-completion.h index 5bf596e4e..694f1a7e4 100644 --- a/src/plugins/trigger/trigger-completion.h +++ b/src/plugins/trigger/trigger-completion.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_TRIGGER_COMPLETION_H -#define WEECHAT_TRIGGER_COMPLETION_H 1 +#ifndef WEECHAT_PLUGIN_TRIGGER_COMPLETION_H +#define WEECHAT_PLUGIN_TRIGGER_COMPLETION_H extern void trigger_completion_init (); -#endif /* WEECHAT_TRIGGER_COMPLETION_H */ +#endif /* WEECHAT_PLUGIN_TRIGGER_COMPLETION_H */ diff --git a/src/plugins/trigger/trigger-config.c b/src/plugins/trigger/trigger-config.c index c85548ab7..8edd61b79 100644 --- a/src/plugins/trigger/trigger-config.c +++ b/src/plugins/trigger/trigger-config.c @@ -1,7 +1,7 @@ /* * trigger-config.c - trigger configuration options (file trigger.conf) * - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -661,6 +661,7 @@ trigger_config_init () if (!ptr_section) { weechat_config_free (trigger_config_file); + trigger_config_file = NULL; return 0; } @@ -690,6 +691,7 @@ trigger_config_init () if (!ptr_section) { weechat_config_free (trigger_config_file); + trigger_config_file = NULL; return 0; } @@ -761,6 +763,7 @@ trigger_config_init () if (!ptr_section) { weechat_config_free (trigger_config_file); + trigger_config_file = NULL; return 0; } diff --git a/src/plugins/trigger/trigger-config.h b/src/plugins/trigger/trigger-config.h index 651cc93f9..05b9515b1 100644 --- a/src/plugins/trigger/trigger-config.h +++ b/src/plugins/trigger/trigger-config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_TRIGGER_CONFIG_H -#define WEECHAT_TRIGGER_CONFIG_H 1 +#ifndef WEECHAT_PLUGIN_TRIGGER_CONFIG_H +#define WEECHAT_PLUGIN_TRIGGER_CONFIG_H #define TRIGGER_CONFIG_NAME "trigger" #define TRIGGER_CONFIG_SECTION_TRIGGER "trigger" @@ -49,4 +49,4 @@ extern int trigger_config_read (); extern int trigger_config_write (); extern void trigger_config_free (); -#endif /* WEECHAT_TRIGGER_CONFIG_H */ +#endif /* WEECHAT_PLUGIN_TRIGGER_CONFIG_H */ diff --git a/src/plugins/trigger/trigger.c b/src/plugins/trigger/trigger.c index 4cd2e7272..b088b1f0e 100644 --- a/src/plugins/trigger/trigger.c +++ b/src/plugins/trigger/trigger.c @@ -1,7 +1,7 @@ /* * trigger.c - trigger plugin for WeeChat * - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -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(11000); +WEECHAT_PLUGIN_PRIORITY(12000); struct t_weechat_plugin *weechat_trigger_plugin = NULL; diff --git a/src/plugins/trigger/trigger.h b/src/plugins/trigger/trigger.h index 0237962a9..78984277b 100644 --- a/src/plugins/trigger/trigger.h +++ b/src/plugins/trigger/trigger.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2014-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_TRIGGER_H -#define WEECHAT_TRIGGER_H 1 +#ifndef WEECHAT_PLUGIN_TRIGGER_H +#define WEECHAT_PLUGIN_TRIGGER_H #include <regex.h> @@ -170,4 +170,4 @@ extern struct t_trigger *trigger_copy (struct t_trigger *trigger, extern void trigger_free (struct t_trigger *trigger); extern void trigger_free_all (); -#endif /* WEECHAT_TRIGGER_H */ +#endif /* WEECHAT_PLUGIN_TRIGGER_H */ diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h index 4ac49d11e..f9a836065 100644 --- a/src/plugins/weechat-plugin.h +++ b/src/plugins/weechat-plugin.h @@ -1,7 +1,7 @@ /* * weechat-plugin.h - header to compile WeeChat plugins * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -20,12 +20,13 @@ */ #ifndef WEECHAT_WEECHAT_PLUGIN_H -#define WEECHAT_WEECHAT_PLUGIN_H 1 +#define WEECHAT_WEECHAT_PLUGIN_H #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ +#include <stddef.h> #include <time.h> #include <sys/types.h> #include <sys/socket.h> @@ -66,7 +67,7 @@ struct timeval; * please change the date with current one; for a second change at same * date, increment the 01, otherwise please keep 01. */ -#define WEECHAT_PLUGIN_API_VERSION "20170617-01" +#define WEECHAT_PLUGIN_API_VERSION "20180520-01" /* macros for defining plugin infos */ #define WEECHAT_PLUGIN_NAME(__name) \ @@ -254,6 +255,7 @@ struct t_weechat_plugin int priority; /* plugin priority (default is 1000) */ int initialized; /* plugin initialized? (init called) */ int debug; /* debug level for plugin (0=off) */ + struct t_hashtable *variables; /* plugin custom variables */ struct t_weechat_plugin *prev_plugin; /* link to previous plugin */ struct t_weechat_plugin *next_plugin; /* link to next plugin */ @@ -361,7 +363,8 @@ struct t_weechat_plugin int (*mkdir_home) (const char *directory, int mode); int (*mkdir) (const char *directory, int mode); int (*mkdir_parents) (const char *directory, int mode); - void (*exec_on_files) (const char *directory, int hidden_files, + void (*exec_on_files) (const char *directory, int recurse_subdirs, + int hidden_files, void (*callback)(void *data, const char *filename), void *callback_data); char *(*file_get_content) (const char *filename); @@ -1281,9 +1284,11 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin); (weechat_plugin->mkdir)(__directory, __mode) #define weechat_mkdir_parents(__directory, __mode) \ (weechat_plugin->mkdir_parents)(__directory, __mode) -#define weechat_exec_on_files(__directory, __hidden_files, __callback, \ +#define weechat_exec_on_files(__directory, __recurse_subdirs, \ + __hidden_files, __callback, \ __callback_data) \ - (weechat_plugin->exec_on_files)(__directory, __hidden_files, \ + (weechat_plugin->exec_on_files)(__directory, __recurse_subdirs, \ + __hidden_files, \ __callback, __callback_data) #define weechat_file_get_content(__filename) \ (weechat_plugin->file_get_content)(__filename) diff --git a/src/plugins/xfer/CMakeLists.txt b/src/plugins/xfer/CMakeLists.txt index e42af2957..2988ee55a 100644 --- a/src/plugins/xfer/CMakeLists.txt +++ b/src/plugins/xfer/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/xfer/Makefile.am b/src/plugins/xfer/Makefile.am index d3901134b..70a08e2ff 100644 --- a/src/plugins/xfer/Makefile.am +++ b/src/plugins/xfer/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # diff --git a/src/plugins/xfer/xfer-buffer.c b/src/plugins/xfer/xfer-buffer.c index 4cb89270f..608ccd25f 100644 --- a/src/plugins/xfer/xfer-buffer.c +++ b/src/plugins/xfer/xfer-buffer.c @@ -1,7 +1,7 @@ /* * xfer-buffer.c - display xfer list on xfer buffer * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -57,9 +57,9 @@ xfer_buffer_refresh (const char *hotlist) xfer_selected = xfer_search_by_number (xfer_buffer_selected_line); weechat_printf_y (xfer_buffer, 0, "%s%s%s%s%s%s%s%s", - weechat_color("green"), + weechat_color ("green"), _("Actions (letter+enter):"), - weechat_color("lightgreen"), + weechat_color ("lightgreen"), /* accept */ (xfer_selected && XFER_IS_RECV(xfer_selected->type) && (xfer_selected->status == XFER_STATUS_WAITING)) ? @@ -116,7 +116,7 @@ xfer_buffer_refresh (const char *hotlist) /* display first line with remote nick, filename and plugin name/id */ weechat_printf_y (xfer_buffer, (line * 2) + 2, "%s%s%-24s %s%s%s%s (%s.%s)%s%s", - weechat_color(str_color), + weechat_color (str_color), (line == xfer_buffer_selected_line) ? "*** " : " ", ptr_xfer->remote_nick, @@ -148,17 +148,18 @@ xfer_buffer_refresh (const char *hotlist) date_tmp = localtime (&(ptr_xfer->start_time)); if (date_tmp) { - strftime (date, sizeof (date), - "%a, %d %b %Y %H:%M:%S", date_tmp); + if (strftime (date, sizeof (date), + "%a, %d %b %Y %H:%M:%S", date_tmp) == 0) + date[0] = '\0'; } weechat_printf_y (xfer_buffer, (line * 2) + 3, "%s%s%s %s%s%s%s%s", - weechat_color(str_color), + weechat_color (str_color), (line == xfer_buffer_selected_line) ? "*** " : " ", (XFER_IS_SEND(ptr_xfer->type)) ? "<<--" : "-->>", - weechat_color(weechat_config_string (xfer_config_color_status[ptr_xfer->status])), + weechat_color (weechat_config_string (xfer_config_color_status[ptr_xfer->status])), status, weechat_color ("reset"), weechat_color (str_color), @@ -227,10 +228,10 @@ xfer_buffer_refresh (const char *hotlist) /* display second line for file with status, progress bar and estimated time */ weechat_printf_y (xfer_buffer, (line * 2) + 3, "%s%s%s %s%s%s%s%3llu%% %s / %s (%s%s/s)", - weechat_color(str_color), + weechat_color (str_color), (line == xfer_buffer_selected_line) ? "*** " : " ", (XFER_IS_SEND(ptr_xfer->type)) ? "<<--" : "-->>", - weechat_color(weechat_config_string (xfer_config_color_status[ptr_xfer->status])), + weechat_color (weechat_config_string (xfer_config_color_status[ptr_xfer->status])), status, weechat_color (str_color), (progress_bar) ? progress_bar : "", diff --git a/src/plugins/xfer/xfer-buffer.h b/src/plugins/xfer/xfer-buffer.h index 9d3c8c2cd..847239545 100644 --- a/src/plugins/xfer/xfer-buffer.h +++ b/src/plugins/xfer/xfer-buffer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_XFER_BUFFER_H -#define WEECHAT_XFER_BUFFER_H 1 +#ifndef WEECHAT_PLUGIN_XFER_BUFFER_H +#define WEECHAT_PLUGIN_XFER_BUFFER_H #define XFER_BUFFER_NAME "xfer.list" @@ -33,4 +33,4 @@ extern int xfer_buffer_close_cb (const void *pointer, void *data, struct t_gui_buffer *buffer); extern void xfer_buffer_open (); -#endif /* WEECHAT_XFER_BUFFER_H */ +#endif /* WEECHAT_PLUGIN_XFER_BUFFER_H */ diff --git a/src/plugins/xfer/xfer-chat.c b/src/plugins/xfer/xfer-chat.c index a08859b9e..42df51249 100644 --- a/src/plugins/xfer/xfer-chat.c +++ b/src/plugins/xfer/xfer-chat.c @@ -1,7 +1,7 @@ /* * xfer-chat.c - chat with direct connection to remote host * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/xfer/xfer-chat.h b/src/plugins/xfer/xfer-chat.h index a44292624..d1163231c 100644 --- a/src/plugins/xfer/xfer-chat.h +++ b/src/plugins/xfer/xfer-chat.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,11 +17,11 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_XFER_CHAT_H -#define WEECHAT_XFER_CHAT_H 1 +#ifndef WEECHAT_PLUGIN_XFER_CHAT_H +#define WEECHAT_PLUGIN_XFER_CHAT_H extern void xfer_chat_sendf (struct t_xfer *xfer, const char *format, ...); extern int xfer_chat_recv_cb (const void *pointer, void *data, int fd); extern void xfer_chat_open_buffer (struct t_xfer *xfer); -#endif /* WEECHAT_XFER_CHAT_H */ +#endif /* WEECHAT_PLUGIN_XFER_CHAT_H */ diff --git a/src/plugins/xfer/xfer-command.c b/src/plugins/xfer/xfer-command.c index 56a2de0fd..fd2d1d86c 100644 --- a/src/plugins/xfer/xfer-command.c +++ b/src/plugins/xfer/xfer-command.c @@ -1,7 +1,7 @@ /* * xfer-command.c - xfer command * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -134,8 +134,9 @@ xfer_command_xfer_list (int full) date_tmp = localtime (&(ptr_xfer->start_time)); if (date_tmp) { - strftime (date, sizeof (date), - "%a, %d %b %Y %H:%M:%S", date_tmp); + if (strftime (date, sizeof (date), + "%a, %d %b %Y %H:%M:%S", date_tmp) == 0) + date[0] = '\0'; } weechat_printf (NULL, /* TRANSLATORS: "%s" after "started on" is a date */ @@ -146,8 +147,8 @@ xfer_command_xfer_list (int full) ptr_xfer->remote_nick, ptr_xfer->local_nick, date, - weechat_color( - weechat_config_string( + weechat_color ( + weechat_config_string ( xfer_config_color_status[ptr_xfer->status])), _(xfer_status_string[ptr_xfer->status])); } @@ -171,8 +172,9 @@ xfer_command_xfer_list (int full) date_tmp = localtime (&(ptr_xfer->start_transfer)); if (date_tmp) { - strftime (date, sizeof (date), - "%a, %d %b %Y %H:%M:%S", date_tmp); + if (strftime (date, sizeof (date), + "%a, %d %b %Y %H:%M:%S", date_tmp) == 0) + date[0] = '\0'; } weechat_printf (NULL, /* TRANSLATORS: "%s" after "started on" is a date */ diff --git a/src/plugins/xfer/xfer-command.h b/src/plugins/xfer/xfer-command.h index 41a14a215..73b9838c7 100644 --- a/src/plugins/xfer/xfer-command.h +++ b/src/plugins/xfer/xfer-command.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_XFER_COMMAND_H -#define WEECHAT_XFER_COMMAND_H 1 +#ifndef WEECHAT_PLUGIN_XFER_COMMAND_H +#define WEECHAT_PLUGIN_XFER_COMMAND_H extern void xfer_command_init (); -#endif /* WEECHAT_XFER_COMMAND_H */ +#endif /* WEECHAT_PLUGIN_XFER_COMMAND_H */ diff --git a/src/plugins/xfer/xfer-completion.c b/src/plugins/xfer/xfer-completion.c index 33f4ffdbf..dc0ef879b 100644 --- a/src/plugins/xfer/xfer-completion.c +++ b/src/plugins/xfer/xfer-completion.c @@ -1,7 +1,7 @@ /* * xfer-completion.c - nick completion for xfer chats * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/xfer/xfer-completion.h b/src/plugins/xfer/xfer-completion.h index 86f8ddbbe..b0d68ba76 100644 --- a/src/plugins/xfer/xfer-completion.h +++ b/src/plugins/xfer/xfer-completion.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_XFER_COMPLETION_H -#define WEECHAT_XFER_COMPLETION_H 1 +#ifndef WEECHAT_PLUGIN_XFER_COMPLETION_H +#define WEECHAT_PLUGIN_XFER_COMPLETION_H extern void xfer_completion_init (); -#endif /* WEECHAT_XFER_COMPLETION_H */ +#endif /* WEECHAT_PLUGIN_XFER_COMPLETION_H */ diff --git a/src/plugins/xfer/xfer-config.c b/src/plugins/xfer/xfer-config.c index b6d0ffd07..e4f8e00d9 100644 --- a/src/plugins/xfer/xfer-config.c +++ b/src/plugins/xfer/xfer-config.c @@ -1,7 +1,7 @@ /* * xfer-config.c - xfer configuration options (file xfer.conf) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -49,6 +49,7 @@ struct t_config_option *xfer_config_network_blocksize; struct t_config_option *xfer_config_network_fast_send; struct t_config_option *xfer_config_network_own_ip; struct t_config_option *xfer_config_network_port_range; +struct t_config_option *xfer_config_network_send_ack; struct t_config_option *xfer_config_network_speed_limit; struct t_config_option *xfer_config_network_timeout; @@ -126,6 +127,7 @@ xfer_config_init () if (!ptr_section) { weechat_config_free (xfer_config_file); + xfer_config_file = NULL; return 0; } @@ -162,6 +164,7 @@ xfer_config_init () if (!ptr_section) { weechat_config_free (xfer_config_file); + xfer_config_file = NULL; return 0; } @@ -248,6 +251,7 @@ xfer_config_init () if (!ptr_section) { weechat_config_free (xfer_config_file); + xfer_config_file = NULL; return 0; } @@ -280,6 +284,16 @@ xfer_config_init () "below 1024)"), NULL, 0, 0, "", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + xfer_config_network_send_ack = weechat_config_new_option ( + xfer_config_file, ptr_section, + "send_ack", "boolean", + N_("send acks when receiving files; if disabled, the transfer may " + "freeze if the sender is waiting for acks (for example a WeeChat " + "sending a file with option xfer.network.fast_send set to off); " + "on the other hand, disabling send of acks may prevent a freeze if " + "the acks are not sent immediately to the sender"), + NULL, 0, 0, "on", NULL, 0, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); xfer_config_network_speed_limit = weechat_config_new_option ( xfer_config_file, ptr_section, "speed_limit", "integer", @@ -304,6 +318,7 @@ xfer_config_init () if (!ptr_section) { weechat_config_free (xfer_config_file); + xfer_config_file = NULL; return 0; } diff --git a/src/plugins/xfer/xfer-config.h b/src/plugins/xfer/xfer-config.h index e6b2c70d2..8012a35ac 100644 --- a/src/plugins/xfer/xfer-config.h +++ b/src/plugins/xfer/xfer-config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_XFER_CONFIG_H -#define WEECHAT_XFER_CONFIG_H 1 +#ifndef WEECHAT_PLUGIN_XFER_CONFIG_H +#define WEECHAT_PLUGIN_XFER_CONFIG_H #define XFER_CONFIG_NAME "xfer" @@ -39,6 +39,7 @@ extern struct t_config_option *xfer_config_network_blocksize; extern struct t_config_option *xfer_config_network_fast_send; extern struct t_config_option *xfer_config_network_own_ip; extern struct t_config_option *xfer_config_network_port_range; +extern struct t_config_option *xfer_config_network_send_ack; extern struct t_config_option *xfer_config_network_speed_limit; extern struct t_config_option *xfer_config_network_timeout; @@ -57,4 +58,4 @@ extern int xfer_config_init (); extern int xfer_config_read (); extern int xfer_config_write (); -#endif /* WEECHAT_XFER_CONFIG_H */ +#endif /* WEECHAT_PLUGIN_XFER_CONFIG_H */ diff --git a/src/plugins/xfer/xfer-dcc.c b/src/plugins/xfer/xfer-dcc.c index fcaa00554..b2c5d8c67 100644 --- a/src/plugins/xfer/xfer-dcc.c +++ b/src/plugins/xfer/xfer-dcc.c @@ -1,7 +1,7 @@ /* * xfer-dcc.c - file transfer via DCC protocol * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -28,6 +28,7 @@ #include <sys/socket.h> #include <poll.h> #include <netinet/in.h> +#include <netinet/tcp.h> #include <fcntl.h> #include <time.h> #include <netdb.h> @@ -308,7 +309,7 @@ xfer_dcc_resume_hash (struct t_xfer *xfer) void xfer_dcc_recv_file_child (struct t_xfer *xfer) { - int flags, num_read, ack_enabled, ready; + int flags, num_read, ready; static char buffer[XFER_BLOCKSIZE_MAX]; time_t last_sent, new_time; unsigned long long pos_last_ack; @@ -345,6 +346,10 @@ xfer_dcc_recv_file_child (struct t_xfer *xfer) return; } + /* set TCP_NODELAY to be more aggressive with acks */ + flags = 1; + setsockopt (xfer->sock, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof (flags)); + /* connection is OK, change DCC status (inform parent process) */ xfer_network_write_pipe (xfer, XFER_STATUS_ACTIVE, XFER_NO_ERROR); @@ -356,7 +361,6 @@ xfer_dcc_recv_file_child (struct t_xfer *xfer) fcntl (xfer->sock, F_SETFL, flags | O_NONBLOCK); last_sent = time (NULL); - ack_enabled = 1; pos_last_ack = 0; while (1) @@ -492,7 +496,7 @@ xfer_dcc_recv_file_child (struct t_xfer *xfer) } /* send ACK to sender (if needed) */ - if (ack_enabled && (xfer->pos > pos_last_ack)) + if (xfer->send_ack && (xfer->pos > pos_last_ack)) { switch (xfer_dcc_recv_file_send_ack (xfer)) { @@ -503,7 +507,7 @@ xfer_dcc_recv_file_child (struct t_xfer *xfer) return; case 1: /* send error, not fatal (buffer full?): disable ACKs */ - ack_enabled = 0; + xfer->send_ack = 0; break; case 2: /* send OK: save position in file as last ACK sent */ diff --git a/src/plugins/xfer/xfer-dcc.h b/src/plugins/xfer/xfer-dcc.h index 553d3029a..06b3b4b89 100644 --- a/src/plugins/xfer/xfer-dcc.h +++ b/src/plugins/xfer/xfer-dcc.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,10 +17,10 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_XFER_DCC_H -#define WEECHAT_XFER_DCC_H 1 +#ifndef WEECHAT_PLUGIN_XFER_DCC_H +#define WEECHAT_PLUGIN_XFER_DCC_H extern void xfer_dcc_send_file_child (struct t_xfer *xfer); extern void xfer_dcc_recv_file_child (struct t_xfer *xfer); -#endif /* WEECHAT_XFER_DCC_H */ +#endif /* WEECHAT_PLUGIN_XFER_DCC_H */ diff --git a/src/plugins/xfer/xfer-file.c b/src/plugins/xfer/xfer-file.c index 9a645a5a4..82853dd0a 100644 --- a/src/plugins/xfer/xfer-file.c +++ b/src/plugins/xfer/xfer-file.c @@ -1,7 +1,7 @@ /* * xfer-file.c - file functions for xfer plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -103,7 +103,7 @@ xfer_file_find_filename (struct t_xfer *xfer) } strcpy (xfer->local_filename, path); - dir_separator = weechat_info_get("dir_separator", ""); + dir_separator = weechat_info_get ("dir_separator", ""); if (dir_separator && (xfer->local_filename[strlen (xfer->local_filename) - 1] != dir_separator[0])) strcat (xfer->local_filename, dir_separator); diff --git a/src/plugins/xfer/xfer-file.h b/src/plugins/xfer/xfer-file.h index 5e6f49fb3..1217e77f4 100644 --- a/src/plugins/xfer/xfer-file.h +++ b/src/plugins/xfer/xfer-file.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,10 +17,10 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_XFER_FILE_H -#define WEECHAT_XFER_FILE_H 1 +#ifndef WEECHAT_PLUGIN_XFER_FILE_H +#define WEECHAT_PLUGIN_XFER_FILE_H extern void xfer_file_find_filename (struct t_xfer *xfer); extern void xfer_file_calculate_speed (struct t_xfer *xfer, int ended); -#endif /* WEECHAT_XFER_FILE_H */ +#endif /* WEECHAT_PLUGIN_XFER_FILE_H */ diff --git a/src/plugins/xfer/xfer-info.c b/src/plugins/xfer/xfer-info.c index 715f97910..c41109b15 100644 --- a/src/plugins/xfer/xfer-info.c +++ b/src/plugins/xfer/xfer-info.c @@ -1,7 +1,7 @@ /* * xfer-info.c - info and infolist hooks for xfer plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/xfer/xfer-info.h b/src/plugins/xfer/xfer-info.h index a90f47ae2..cb6c4d2d1 100644 --- a/src/plugins/xfer/xfer-info.h +++ b/src/plugins/xfer/xfer-info.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_XFER_INFO_H -#define WEECHAT_XFER_INFO_H 1 +#ifndef WEECHAT_PLUGIN_XFER_INFO_H +#define WEECHAT_PLUGIN_XFER_INFO_H extern void xfer_info_init (); -#endif /* WEECHAT_XFER_INFO_H */ +#endif /* WEECHAT_PLUGIN_XFER_INFO_H */ diff --git a/src/plugins/xfer/xfer-network.c b/src/plugins/xfer/xfer-network.c index 7f83d7cd7..79db837b6 100644 --- a/src/plugins/xfer/xfer-network.c +++ b/src/plugins/xfer/xfer-network.c @@ -1,7 +1,7 @@ /* * xfer-network.c - network functions for xfer plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/xfer/xfer-network.h b/src/plugins/xfer/xfer-network.h index d3275b6aa..aebb25854 100644 --- a/src/plugins/xfer/xfer-network.h +++ b/src/plugins/xfer/xfer-network.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_XFER_NETWORK_H -#define WEECHAT_XFER_NETWORK_H 1 +#ifndef WEECHAT_PLUGIN_XFER_NETWORK_H +#define WEECHAT_PLUGIN_XFER_NETWORK_H extern void xfer_network_write_pipe (struct t_xfer *xfer, int status, int error); @@ -27,4 +27,4 @@ extern void xfer_network_child_kill (struct t_xfer *xfer); extern int xfer_network_connect (struct t_xfer *xfer); extern void xfer_network_accept (struct t_xfer *xfer); -#endif /* WEECHAT_XFER_NETWORK_H */ +#endif /* WEECHAT_PLUGIN_XFER_NETWORK_H */ diff --git a/src/plugins/xfer/xfer-upgrade.c b/src/plugins/xfer/xfer-upgrade.c index 290e4a93b..80394e074 100644 --- a/src/plugins/xfer/xfer-upgrade.c +++ b/src/plugins/xfer/xfer-upgrade.c @@ -1,7 +1,7 @@ /* * xfer-upgrade.c - save/restore xfer plugin data when upgrading WeeChat * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/xfer/xfer-upgrade.h b/src/plugins/xfer/xfer-upgrade.h index 6d37203a9..54909e628 100644 --- a/src/plugins/xfer/xfer-upgrade.h +++ b/src/plugins/xfer/xfer-upgrade.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_XFER_UPGRADE_H -#define WEECHAT_XFER_UPGRADE_H 1 +#ifndef WEECHAT_PLUGIN_XFER_UPGRADE_H +#define WEECHAT_PLUGIN_XFER_UPGRADE_H #define XFER_UPGRADE_FILENAME "xfer" @@ -32,4 +32,4 @@ enum t_xfer_upgrade_type extern int xfer_upgrade_save (); extern int xfer_upgrade_load (); -#endif /* WEECHAT_XFER_UPGRADE_H */ +#endif /* WEECHAT_PLUGIN_XFER_UPGRADE_H */ diff --git a/src/plugins/xfer/xfer.c b/src/plugins/xfer/xfer.c index b9c72a1de..9bf7f5442 100644 --- a/src/plugins/xfer/xfer.c +++ b/src/plugins/xfer/xfer.c @@ -1,7 +1,7 @@ /* * xfer.c - file transfer and direct chat plugin for WeeChat * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -52,7 +52,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("DCC file transfer and direct chat")); WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(6000); +WEECHAT_PLUGIN_PRIORITY(7000); struct t_weechat_plugin *weechat_xfer_plugin = NULL; @@ -501,6 +501,7 @@ xfer_alloc () new_xfer->filename_suffix = -1; new_xfer->pos = 0; new_xfer->ack = 0; + new_xfer->send_ack = weechat_config_boolean (xfer_config_network_send_ack); new_xfer->start_resume = 0; new_xfer->last_check_time = time_now; new_xfer->last_check_pos = time_now; @@ -688,11 +689,11 @@ xfer_new (const char *plugin_name, const char *plugin_id, if (XFER_IS_RECV(type)) { new_xfer->local_address_str = strdup (""); - xfer_set_remote_address(new_xfer, address, address_length, str_address); + xfer_set_remote_address (new_xfer, address, address_length, str_address); } else { - xfer_set_local_address(new_xfer, address, address_length, str_address); + xfer_set_local_address (new_xfer, address, address_length, str_address); new_xfer->remote_address_str = strdup (""); } @@ -1184,7 +1185,7 @@ xfer_add_cb (const void *pointer, void *data, } else { - memset(&bind_addr, 0, sizeof(bind_addr)); + memset (&bind_addr, 0, sizeof (bind_addr)); /* determine bind_addr family from either own_ip or default */ if (weechat_config_string (xfer_config_network_own_ip) @@ -1726,8 +1727,8 @@ xfer_print_log () weechat_log_printf (" remote_nick_color . . . : '%s'", ptr_xfer->remote_nick_color); weechat_log_printf (" fast_send . . . . . . . : %d", ptr_xfer->fast_send); weechat_log_printf (" blocksize . . . . . . . : %d", ptr_xfer->blocksize); - weechat_log_printf (" start_time. . . . . . . : %ld", ptr_xfer->start_time); - weechat_log_printf (" start_transfer. . . . . : %ld", ptr_xfer->start_transfer); + weechat_log_printf (" start_time. . . . . . . : %lld", (long long)ptr_xfer->start_time); + weechat_log_printf (" start_transfer. . . . . : %lld", (long long)ptr_xfer->start_transfer); weechat_log_printf (" sock. . . . . . . . . . : %d", ptr_xfer->sock); weechat_log_printf (" child_pid . . . . . . . : %d", ptr_xfer->child_pid); weechat_log_printf (" child_read. . . . . . . : %d", ptr_xfer->child_read); @@ -1742,9 +1743,9 @@ xfer_print_log () weechat_log_printf (" pos . . . . . . . . . . : %llu", ptr_xfer->pos); weechat_log_printf (" ack . . . . . . . . . . : %llu", ptr_xfer->ack); weechat_log_printf (" start_resume. . . . . . : %llu", ptr_xfer->start_resume); - weechat_log_printf (" last_check_time . . . . : %ld", ptr_xfer->last_check_time); + weechat_log_printf (" last_check_time . . . . : %lld", (long long)ptr_xfer->last_check_time); weechat_log_printf (" last_check_pos. . . . . : %llu", ptr_xfer->last_check_pos); - weechat_log_printf (" last_activity . . . . . : %ld", ptr_xfer->last_activity); + weechat_log_printf (" last_activity . . . . . : %lld", (long long)ptr_xfer->last_activity); weechat_log_printf (" bytes_per_sec . . . . . : %llu", ptr_xfer->bytes_per_sec); weechat_log_printf (" eta . . . . . . . . . . : %llu", ptr_xfer->eta); weechat_log_printf (" hash_target . . . . . . : '%s'", ptr_xfer->hash_target); diff --git a/src/plugins/xfer/xfer.h b/src/plugins/xfer/xfer.h index cf5c3147b..f300663e6 100644 --- a/src/plugins/xfer/xfer.h +++ b/src/plugins/xfer/xfer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_XFER_H -#define WEECHAT_XFER_H 1 +#ifndef WEECHAT_PLUGIN_XFER_H +#define WEECHAT_PLUGIN_XFER_H #include <unistd.h> #include <time.h> @@ -156,6 +156,7 @@ struct t_xfer char *remote_nick_color; /* color name for remote nick */ /* (returned by IRC plugin) */ int fast_send; /* fast send file: does not wait ACK */ + int send_ack; /* send acks on file receive */ int blocksize; /* block size for sending file */ time_t start_time; /* time when xfer started */ time_t start_transfer; /* time when xfer transfer started */ @@ -208,4 +209,4 @@ extern void xfer_free (struct t_xfer *xfer); extern int xfer_add_to_infolist (struct t_infolist *infolist, struct t_xfer *xfer); -#endif /* WEECHAT_XFER_H */ +#endif /* WEECHAT_PLUGIN_XFER_H */ |