/* * Copyright (c) 2003-2007 by FlashCode * See README for License detail, AUTHORS for developers list. * * This program 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. * * This program 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 this program. If not, see . */ /* wee-command.c: WeeChat commands */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "weechat.h" #include "wee-command.h" #include "wee-alias.h" #include "wee-config.h" #include "wee-hook.h" #include "wee-input.h" #include "wee-log.h" #include "wee-upgrade.h" #include "wee-string.h" #include "wee-utf8.h" #include "wee-list.h" #include "../gui/gui-chat.h" #include "../gui/gui-history.h" #include "../gui/gui-keyboard.h" #include "../gui/gui-window.h" #include "../plugins/plugin.h" #include "../plugins/plugin-config.h" /* WeeChat internal commands */ struct command weechat_commands[] = { { "alias", N_("create an alias for a command"), N_("[alias_name [command [arguments]]]"), N_("alias_name: name of alias\n" " command: command name (WeeChat or IRC command, many commands " "can be separated by semicolons)\n" " arguments: arguments for command\n\n" "Note: in command, special variables $1, $2,..,$9 are replaced by " "arguments given by user, and $* is replaced by all arguments.\n" "Variables $nick, $channel and $server are replaced by current " "nick/channel/server."), "%- %A", 0, MAX_ARGS, 1, command_alias }, { "buffer", N_("manage buffers"), N_("[action [args] | number | [[server] [channel]]]"), N_(" action: action to do:\n" " move: move buffer in the list (may be relative, for example -1)\n" " close: close buffer\n" " list: list open buffers (no parameter implies this list)\n" " notify: set notify level for buffer (0=never, 1=highlight, 2=1+msg, " "3=2+join/part)\n" " (when executed on server buffer, this sets default notify " "level for whole server)\n" " scroll: scroll in history (may be relative, and may end by a letter: " "s=sec, m=min, h=hour, d=day, M=month, y=year); if there is " "only letter, then scroll to beginning of this item\n\n" " number: jump to buffer by number\n" "server,\n" "channel: jump to buffer by server and/or channel name\n\n" "Examples:\n" " move buffer: /buffer move 5\n" " close buffer: /buffer close this is part msg\n" " set notify: /buffer notify 2\n" " scroll 1 day up: /buffer scroll 1d == /buffer scroll -1d == " "/buffer scroll -24h\n" "scroll to beginning\n" " of this day: /buffer scroll d\n" " scroll 15 min down: /buffer scroll +15m\n" " scroll 20 msgs up: /buffer scroll -20\n" " jump to #weechat: /buffer #weechat"), "move|close|list|notify|scroll|%S|%C %S|%C", 0, MAX_ARGS, 0, command_buffer }, { "builtin", N_("launch WeeChat/IRC builtin command (do not look at plugins handlers " "or aliases)"), N_("command"), N_("command: command to execute (a '/' is automatically added if not " "found at beginning of command)\n"), "%w|%i", 0, MAX_ARGS, 1, command_builtin }, { "clear", N_("clear window(s)"), N_("[-all | number [number ...]]"), N_(" -all: clear all buffers\n" "number: clear buffer by number"), "-all", 0, MAX_ARGS, 0, command_clear }, { "debug", N_("print debug messages"), N_("dump | buffer | windows"), N_(" dump: save memory dump in WeeChat log file (same dump is written " "when WeeChat crashes)\n" " buffer: dump buffer content with hexadecimal values in log file\n" "windows: display windows tree"), "dump|buffer|windows", 1, 1, 0, command_debug }, { "help", N_("display help about commands"), N_("[command]"), N_("command: name of a WeeChat or IRC command"), "%w|%i|%h", 0, 1, 0, command_help }, { "history", N_("show buffer command history"), N_("[clear | value]"), N_("clear: clear history\n" "value: number of history entries to show"), "clear", 0, 1, 0, command_history }, { "key", N_("bind/unbind keys"), N_("[key [function/command]] [unbind key] [functions] [call function " "[\"args\"]] [reset -yes]"), N_(" key: display or bind this key to an internal function or a " "command (beginning by \"/\")\n" " unbind: unbind a key\n" "functions: list internal functions for key bindings\n" " call: call a function by name (with optional arguments)\n" " reset: restore bindings to the default values and delete ALL " "personal bindings (use carefully!)"), "unbind|functions|call|reset %k", 0, MAX_ARGS, 0, command_key }, { "plugin", N_("list/load/unload plugins"), N_("[list [name]] | [listfull [name]] | [load filename] | [autoload] | " "[reload [name]] | [unload [name]]"), N_(" list: list loaded plugins\n" "listfull: list loaded plugins with detailed info for each plugin\n" " load: load a plugin\n" "autoload: autoload plugins in system or user directory\n" " reload: reload one plugin (if no name given, unload all plugins, " "then autoload plugins)\n" " unload: unload one or all plugins\n\n" "Without argument, /plugin command lists loaded plugins."), "list|listfull|load|autoload|reload|unload %P", 0, 2, 0, command_plugin }, { "quit", "", "", "", NULL, 0, 0, 0, command_quit }, { "save", N_("save configuration files to disk"), "", "", NULL, 0, 1, 0, command_save }, { "set", N_("set config options"), N_("[option [ = value]]"), N_("option: name of an option (if name is full " "and no value is given, then help is displayed on option)\n" " value: value for option\n\n" "Option may be: servername.server_xxx where \"servername\" is an " "internal server name and \"xxx\" an option for this server."), "%o = %v", 0, MAX_ARGS, 0, command_set }, { "setp", N_("set plugin config options"), N_("[option [ = value]]"), N_("option: name of a plugin option\n" " value: value for option\n\n" "Option is format: plugin.option, example: perl.myscript.item1"), "%O = %V", 0, MAX_ARGS, 0, command_setp }, { "unalias", N_("remove an alias"), N_("alias_name"), N_("alias_name: name of alias to remove"), "%a", 1, 1, 0, command_unalias }, { "upgrade", N_("upgrade WeeChat without disconnecting from servers"), N_("[path_to_binary]"), N_("path_to_binary: path to WeeChat binary (default is current binary)\n\n" "This command run again a WeeChat binary, so it should have been " "compiled or installed with a package manager before running this " "command."), "%f", 0, 1, 0, command_upgrade }, { "uptime", N_("show WeeChat uptime"), N_("[-o]"), N_("-o: send uptime on current channel as an IRC message"), "-o", 0, 1, 0, command_uptime }, { "window", N_("manage windows"), N_("[list | -1 | +1 | b# | up | down | left | right | splith [pct] " "| splitv [pct] | resize pct | merge [all]]"), N_(" list: list open windows (no parameter implies this list)\n" " -1: jump to previous window\n" " +1: jump to next window\n" " b#: jump to next window displaying buffer number #\n" " up: switch to window above current one\n" " down: switch to window below current one\n" " left: switch to window on the left\n" " right: switch to window on the right\n" "splith: split current window horizontally\n" "splitv: split current window vertically\n" "resize: resize window size, new size is pourcentage of parent " "window\n" " merge: merge window with another (all = keep only one window)\n\n" "For splith and splitv, pct is a pourcentage which represents " "size of new window, computed with current window as size reference. " "For example 25 means create a new window with size = current_size / 4"), "list|-1|+1|up|down|left|right|splith|splitv|resize|merge all", 0, 2, 0, command_window }, { NULL, NULL, NULL, NULL, NULL, 0, 0, 0, NULL } }; struct t_weelist *weechat_index_commands; struct t_weelist *weechat_last_index_command; /* * command_is_used: return 1 if command is used by weechat * (WeeChat/alias command) */ int command_is_used (char *command) { struct alias *ptr_alias; int i; /* look for alias */ for (ptr_alias = weechat_alias; ptr_alias; ptr_alias = ptr_alias->next_alias) { if (string_strcasecmp (ptr_alias->name, command) == 0) return 1; } /* look for WeeChat command */ for (i = 0; weechat_commands[i].name; i++) { if (string_strcasecmp (weechat_commands[i].name, command) == 0) return 1; } /* no command/alias found */ return 0; } /* * command_index_build: build an index of commands (internal, irc and alias) * This list will be sorted, and used for completion */ void command_index_build () { int i; weechat_index_commands = NULL; weechat_last_index_command = NULL; i = 0; while (weechat_commands[i].name) { (void) weelist_add (&weechat_index_commands, &weechat_last_index_command, weechat_commands[i].name, WEELIST_POS_SORT); i++; } } /* * command_index_free: remove all commands in index */ void command_index_free () { while (weechat_index_commands) { weelist_remove (&weechat_index_commands, &weechat_last_index_command, weechat_index_commands); } } /* * command_index_add: add command to commands index */ void command_index_add (char *command) { if (!weelist_search (weechat_index_commands, command)) weelist_add (&weechat_index_commands, &weechat_last_index_command, command, WEELIST_POS_SORT); } /* * command_index_remove: remove command from commands index */ void command_index_remove (char *command) { if (!command_is_used (command)) weelist_remove (&weechat_index_commands, &weechat_last_index_command, weelist_search (weechat_index_commands, command)); } /* * command_is_command: return 1 if line is a command, 0 otherwise */ int command_is_command (char *line) { char *pos_slash, *pos_space; if (strncmp (line, "/*", 2) == 0) return 0; pos_slash = strchr (line + 1, '/'); pos_space = strchr (line + 1, ' '); return (line[0] == '/') && (!pos_slash || (pos_space && pos_slash > pos_space)); } /* * command_print_stdout: print list of commands on standard output */ void command_print_stdout (struct command *commands) { int i; for (i = 0; commands[i].name; i++) { string_iconv_fprintf (stdout, "* %s", commands[i].name); if (commands[i].arguments && commands[i].arguments[0]) string_iconv_fprintf (stdout, " %s\n\n", _(commands[i].arguments)); else string_iconv_fprintf (stdout, "\n\n"); string_iconv_fprintf (stdout, "%s\n\n", _(commands[i].description)); if (commands[i].arguments_description && commands[i].arguments_description[0]) string_iconv_fprintf (stdout, "%s\n\n", _(commands[i].arguments_description)); } } /* * command_alias: display or create alias */ int command_alias (struct t_gui_buffer *buffer, char *arguments, int argc, char **argv) { char *pos; struct alias *ptr_alias; /* make C compiler happy */ (void) buffer; (void) argc; (void) argv; if (arguments && arguments[0]) { while (arguments[0] == '/') { arguments++; } /* Define new alias */ pos = strchr (arguments, ' '); if (pos) { pos[0] = '\0'; pos++; while (pos[0] == ' ') pos++; if (!pos[0]) { gui_chat_printf (NULL, _("%sError: missing arguments for \"%s\" " "command"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], "alias"); return -1; } if (!alias_new (arguments, pos)) return -1; if (weelist_add (&weechat_index_commands, &weechat_last_index_command, arguments, WEELIST_POS_SORT)) { gui_chat_printf (NULL, _("%sAlias \"%s\" => \"%s\" created"), gui_chat_prefix[GUI_CHAT_PREFIX_INFO], arguments, pos); } else { gui_chat_printf (NULL, _("%sError: not enough memory for creating " "alias \"%s\" => \"%s\""), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], arguments, pos); return -1; } } else { ptr_alias = alias_search (arguments); if (ptr_alias) { gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("Alias:")); gui_chat_printf (NULL, " %s %s=>%s %s", ptr_alias->name, GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), GUI_COLOR(GUI_COLOR_CHAT), ptr_alias->command); } else gui_chat_printf (NULL, _("%sNo alias found."), gui_chat_prefix[GUI_CHAT_PREFIX_INFO]); } } else { /* List all aliases */ if (weechat_alias) { gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("List of aliases:")); for (ptr_alias = weechat_alias; ptr_alias; ptr_alias = ptr_alias->next_alias) { gui_chat_printf (NULL, " %s %s=>%s %s", ptr_alias->name, GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), GUI_COLOR(GUI_COLOR_CHAT), ptr_alias->command); } } else gui_chat_printf (NULL, _("%sNo alias defined."), gui_chat_prefix[GUI_CHAT_PREFIX_INFO]); } return 0; } /* * command_buffer_display_info: display info about a buffer */ void command_buffer_display_info (struct t_gui_buffer *buffer) { /* TODO: write again this function */ (void) buffer; /* switch (buffer->type) { case GUI_BUFFER_TYPE_STANDARD: if (GUI_BUFFER_IS_SERVER(buffer)) { if (GUI_SERVER(buffer)) gui_chat_printf (NULL, _("%sServer: %s%s"), GUI_COLOR(GUI_COLOR_CHAT), GUI_COLOR(GUI_COLOR_WIN_CHAT_SERVER), GUI_SERVER(buffer)->name); else gui_chat_printf (NULL, _("%snot connected"), GUI_COLOR(GUI_COLOR_CHAT)); } else if (GUI_BUFFER_IS_CHANNEL (buffer)) gui_chat_printf (NULL, _("%sChannel: %s%s %s(server: %s%s%s)"), GUI_COLOR(GUI_COLOR_CHAT), GUI_COLOR(GUI_COLOR_CHAT_BUFFER), GUI_CHANNEL(buffer)->name, GUI_COLOR(GUI_COLOR_CHAT), GUI_COLOR(GUI_COLOR_WIN_CHAT_SERVER), GUI_SERVER(buffer)->name, GUI_COLOR(GUI_COLOR_CHAT)); else if (GUI_BUFFER_IS_PRIVATE (buffer)) gui_chat_printf (NULL, _("%sPrivate with: %s%s %s(server: %s%s%s)"), GUI_COLOR(GUI_COLOR_CHAT), GUI_COLOR(GUI_COLOR_CHAT_NICK), GUI_CHANNEL(buffer)->name, GUI_COLOR(GUI_COLOR_CHAT), GUI_COLOR(GUI_COLOR_WIN_CHAT_SERVER), GUI_SERVER(buffer)->name, GUI_COLOR(GUI_COLOR_CHAT)); else gui_chat_printf (NULL, _("%sunknown"), GUI_COLOR(GUI_COLOR_CHAT)); break; case GUI_BUFFER_TYPE_DCC: gui_chat_printf (NULL, "%sDCC", GUI_COLOR(GUI_COLOR_CHAT_BUFFER)); break; case GUI_BUFFER_TYPE_RAW_DATA: gui_chat_printf (NULL, _("%sraw IRC data"), GUI_COLOR(GUI_COLOR_CHAT_BUFFER)); break; default: gui_chat_printf (NULL, _("%sunknown"), GUI_COLOR(GUI_COLOR_CHAT)); break; }*/ } /* * command_buffer: manage buffers */ int command_buffer (struct t_gui_buffer *buffer, char *arguments, int argc, char **argv) { struct t_gui_buffer *ptr_buffer; long number; char *error; int target_buffer; /* make C compiler happy */ (void) arguments; if ((argc == 0) || ((argc == 1) && (string_strcasecmp (argv[0], "list") == 0))) { /* list open buffers */ gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("Open buffers:")); for (ptr_buffer = gui_buffers; ptr_buffer; ptr_buffer = ptr_buffer->next_buffer) { gui_chat_printf (NULL, "%s[%s%d%s] ", GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), GUI_COLOR(GUI_COLOR_CHAT), ptr_buffer->number, GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS)); command_buffer_display_info (ptr_buffer); } } else { if (string_strcasecmp (argv[0], "move") == 0) { /* move buffer to another number in the list */ if (argc < 2) { gui_chat_printf (NULL, _("%sError: missing arguments for \"%s\" " "command"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], "buffer"); return -1; } error = NULL; number = strtol (((argv[1][0] == '+') || (argv[1][0] == '-')) ? argv[1] + 1 : argv[1], &error, 10); if (error && (error[0] == '\0')) { if (argv[1][0] == '+') gui_buffer_move_to_number (buffer, buffer->number + ((int) number)); else if (argv[1][0] == '-') gui_buffer_move_to_number (buffer, buffer->number - ((int) number)); else gui_buffer_move_to_number (buffer, (int) number); } else { /* invalid number */ gui_chat_printf (NULL, _("%sError: incorrect buffer number"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]); return -1; } } else if (string_strcasecmp (argv[0], "notify") == 0) { if (argc < 2) { /* display notify level for all buffers */ gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("Notify levels:")); for (ptr_buffer = gui_buffers; ptr_buffer; ptr_buffer = ptr_buffer->next_buffer) { gui_chat_printf (NULL, " %d.%s: %d", ptr_buffer->number, ptr_buffer->name, ptr_buffer->notify_level); } gui_chat_printf (NULL, ""); } else { /* set notify level for buffer */ error = NULL; number = strtol (argv[1], &error, 10); if (error && (error[0] == '\0')) { if ((number < GUI_BUFFER_NOTIFY_LEVEL_MIN) || (number > GUI_BUFFER_NOTIFY_LEVEL_MAX)) { /* invalid highlight level */ gui_chat_printf (NULL, _("%sError: incorrect notify level " "(must be between %d and %d)"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], GUI_BUFFER_NOTIFY_LEVEL_MIN, GUI_BUFFER_NOTIFY_LEVEL_MAX); return -1; } gui_chat_printf (NULL, _("%sNew notify level for %s%s%s: " "%d %s"), gui_chat_prefix[GUI_CHAT_PREFIX_INFO], GUI_COLOR(GUI_COLOR_CHAT_BUFFER), buffer->name, GUI_COLOR(GUI_COLOR_CHAT), number, GUI_COLOR(GUI_COLOR_CHAT)); switch (number) { case 0: gui_chat_printf (NULL, _("(hotlist: never)")); break; case 1: gui_chat_printf (NULL, _("(hotlist: highlights)")); break; case 2: gui_chat_printf (NULL, _("(hotlist: highlights + " "messages)")); break; case 3: gui_chat_printf (NULL, _("(hotlist: highlights + " "messages + join/part " "(all))")); break; default: gui_chat_printf (NULL, ""); break; } } else { /* invalid number */ gui_chat_printf (NULL, _("%sError: incorrect notify level (must " "be between %d and %d)"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], GUI_BUFFER_NOTIFY_LEVEL_MIN, GUI_BUFFER_NOTIFY_LEVEL_MAX); return -1; } } } else { /* jump to buffer by number or server/channel name */ if (argv[0][0] == '-') { /* relative jump '-' */ error = NULL; number = strtol (argv[0] + 1, &error, 10); if (error && (error[0] == '\0')) { target_buffer = buffer->number - (int) number; if (target_buffer < 1) target_buffer = (last_gui_buffer) ? last_gui_buffer->number + target_buffer : 1; gui_buffer_switch_by_number (gui_current_window, target_buffer); } } else if (argv[0][0] == '+') { /* relative jump '+' */ error = NULL; number = strtol (argv[0] + 1, &error, 10); if (error && (error[0] == '\0')) { target_buffer = buffer->number + (int) number; if (last_gui_buffer && target_buffer > last_gui_buffer->number) target_buffer -= last_gui_buffer->number; gui_buffer_switch_by_number (gui_current_window, target_buffer); } } else { /* absolute jump by number, or by category/name */ error = NULL; number = strtol (argv[0], &error, 10); if (error && (error[0] == '\0')) gui_buffer_switch_by_number (gui_current_window, (int) number); else { ptr_buffer = NULL; if (argc > 1) ptr_buffer = gui_buffer_search_by_category_name (argv[0], argv[1]); else { ptr_buffer = gui_buffer_search_by_category_name (argv[0], NULL); if (!ptr_buffer) ptr_buffer = gui_buffer_search_by_category_name (NULL, argv[0]); } if (ptr_buffer) { gui_window_switch_to_buffer (gui_current_window, ptr_buffer); gui_window_redraw_buffer (ptr_buffer); } } } } } return 0; } /* * command_builtin: launch WeeChat/IRC builtin command */ int command_builtin (struct t_gui_buffer *buffer, char *arguments, int argc, char **argv) { char *command; int length; /* make C compiler happy */ (void) argc; (void) argv; if (arguments && arguments[0]) { if (arguments[0] == '/') input_data (buffer, arguments, 1); else { length = strlen (arguments) + 2; command = (char *)malloc (length); if (command) { snprintf (command, length, "/%s", arguments); input_data (buffer, command, 1); free (command); } } } return 0; } /* * command_clear: display or create alias */ int command_clear (struct t_gui_buffer *buffer, char *arguments, int argc, char **argv) { struct t_gui_buffer *ptr_buffer; char *error; long number; int i; /* make C compiler happy */ (void) arguments; if (argc > 0) { if (string_strcasecmp (argv[0], "-all") == 0) gui_buffer_clear_all (); else { for (i = 0; i < argc; i++) { error = NULL; number = strtol (argv[i], &error, 10); if (error && (error[0] == '\0')) { ptr_buffer = gui_buffer_search_by_number (number); if (!ptr_buffer) { gui_chat_printf (NULL, _("%sError: buffer number \"%s\" not " "found for \"%s\" command"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], argv[i], "clear"); return -1; } gui_buffer_clear (ptr_buffer); } else { gui_chat_printf (NULL, _("%sError: unknown option for \"%s\" " "command"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], "clear"); return -1; } } } } else gui_buffer_clear (buffer); return 0; } /* * command_debug_display_windows: display tree of windows */ void command_debug_display_windows (struct t_gui_window_tree *tree, int indent) { if (tree) { if (tree->window) { /* leaf */ gui_chat_printf (NULL, "leaf: %X (parent:%X), win=%X, child1=%X, " "child2=%X, %d,%d %dx%d, %d%%x%d%%", tree, tree->parent_node, tree->window, tree->child1, tree->child2, tree->window->win_x, tree->window->win_y, tree->window->win_width, tree->window->win_height, tree->window->win_width_pct, tree->window->win_height_pct); } else { /* node */ gui_chat_printf (NULL, "node: %X (parent:%X), win=%X, child1=%X, " "child2=%X)", tree, tree->parent_node, tree->window, tree->child1, tree->child2); } if (tree->child1) command_debug_display_windows (tree->child1, indent + 1); if (tree->child2) command_debug_display_windows (tree->child2, indent + 1); } } /* * command_debug: print debug messages */ int command_debug (struct t_gui_buffer *buffer, char *arguments, int argc, char **argv) { /* make C compiler happy */ (void) buffer; (void) arguments; if (argc != 1) { gui_chat_printf (NULL, _("%sError: wrong argument count for \"%s\" " "command"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], "debug"); return -1; } if (string_strcasecmp (argv[0], "dump") == 0) { weechat_dump (0); } else if (string_strcasecmp (argv[0], "buffer") == 0) { gui_buffer_dump_hexa (buffer); } else if (string_strcasecmp (argv[0], "windows") == 0) { gui_chat_printf (NULL, ""); gui_chat_printf (NULL, "DEBUG: windows tree:"); command_debug_display_windows (gui_windows_tree, 1); } else { gui_chat_printf (NULL, _("%sError: unknown option for \"%s\" command"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], "debug"); return -1; } return 0; } /* * command_help: display help about commands */ int command_help (struct t_gui_buffer *buffer, char *arguments, int argc, char **argv) { int i; struct t_hook *ptr_hook; /* make C compiler happy */ (void) buffer; (void) arguments; switch (argc) { case 0: gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("%s internal commands:"), PACKAGE_NAME); for (i = 0; weechat_commands[i].name; i++) { if (weechat_commands[i].description && weechat_commands[i].description[0]) gui_chat_printf (NULL, " %s%s %s- %s", GUI_COLOR(GUI_COLOR_CHAT_BUFFER), weechat_commands[i].name, GUI_COLOR(GUI_COLOR_CHAT), _(weechat_commands[i].description)); else gui_chat_printf (NULL, " %s%s", GUI_COLOR(GUI_COLOR_CHAT_BUFFER), weechat_commands[i].name); } gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("Other commands:")); for (ptr_hook = weechat_hooks; ptr_hook; ptr_hook = ptr_hook->next_hook) { if ((ptr_hook->type == HOOK_TYPE_COMMAND) && HOOK_COMMAND(ptr_hook, command) && HOOK_COMMAND(ptr_hook, command)[0]) { if (HOOK_COMMAND(ptr_hook, description) && HOOK_COMMAND(ptr_hook, description)[0]) gui_chat_printf (NULL, " %s%s %s- %s", GUI_COLOR(GUI_COLOR_CHAT_BUFFER), HOOK_COMMAND(ptr_hook, command), GUI_COLOR(GUI_COLOR_CHAT), HOOK_COMMAND(ptr_hook, description)); else gui_chat_printf (NULL, " %s%s", GUI_COLOR(GUI_COLOR_CHAT_BUFFER), HOOK_COMMAND(ptr_hook, command)); } } break; case 1: for (ptr_hook = weechat_hooks; ptr_hook; ptr_hook = ptr_hook->next_hook) { if ((ptr_hook->type == HOOK_TYPE_COMMAND) && HOOK_COMMAND(ptr_hook, command) && HOOK_COMMAND(ptr_hook, command)[0] && (string_strcasecmp (HOOK_COMMAND(ptr_hook, command), argv[0]) == 0)) { gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("[%s%s] %s/%s %s%s"), (ptr_hook->plugin) ? _("plugin:") : "weechat", (ptr_hook->plugin) ? ptr_hook->plugin->name : "", GUI_COLOR(GUI_COLOR_CHAT_BUFFER), HOOK_COMMAND(ptr_hook, command), GUI_COLOR(GUI_COLOR_CHAT), (HOOK_COMMAND(ptr_hook, args) && HOOK_COMMAND(ptr_hook, args)[0]) ? HOOK_COMMAND(ptr_hook, args) : ""); if (HOOK_COMMAND(ptr_hook, description) && HOOK_COMMAND(ptr_hook, description)[0]) { gui_chat_printf (NULL, ""); gui_chat_printf (NULL, "%s", HOOK_COMMAND(ptr_hook, description)); } if (HOOK_COMMAND(ptr_hook, args_description) && HOOK_COMMAND(ptr_hook, args_description)[0]) { gui_chat_printf (NULL, ""); gui_chat_printf (NULL, "%s", HOOK_COMMAND(ptr_hook, args_description)); } return 0; } } for (i = 0; weechat_commands[i].name; i++) { if (string_strcasecmp (weechat_commands[i].name, argv[0]) == 0) { gui_chat_printf (NULL, ""); gui_chat_printf (NULL, "[weechat] %s/%s %s%s", GUI_COLOR(GUI_COLOR_CHAT_BUFFER), weechat_commands[i].name, GUI_COLOR(GUI_COLOR_CHAT), (weechat_commands[i].arguments && weechat_commands[i].arguments[0]) ? _(weechat_commands[i].arguments) : ""); if (weechat_commands[i].description && weechat_commands[i].description[0]) { gui_chat_printf (NULL, ""); gui_chat_printf (NULL, "%s", _(weechat_commands[i].description)); } if (weechat_commands[i].arguments_description && weechat_commands[i].arguments_description[0]) { gui_chat_printf (NULL, ""); gui_chat_printf (NULL, "%s", _(weechat_commands[i].arguments_description)); } return 0; } } gui_chat_printf (NULL, _("%sNo help available, \"%s\" is an " "unknown command"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], argv[0]); break; } return 0; } /* * command_history: display current buffer history */ int command_history (struct t_gui_buffer *buffer, char *arguments, int argc, char **argv) { struct t_gui_history *ptr_history; int n; int n_total; int n_user; /* make C compiler happy */ (void) arguments; n_user = cfg_history_display_default; if (argc == 1) { if (string_strcasecmp (argv[0], "clear") == 0) { gui_history_buffer_free (buffer); return 0; } else n_user = atoi (argv[0]); } if (buffer->history) { n_total = 1; for (ptr_history = buffer->history; ptr_history->next_history; ptr_history = ptr_history->next_history) { n_total++; } for (n = 0; ptr_history; ptr_history = ptr_history->prev_history, n++) { if ((n_user > 0) && ((n_total - n_user) > n)) continue; gui_chat_printf (buffer, "%s%s", gui_chat_prefix[GUI_CHAT_PREFIX_INFO], ptr_history->text); } } return 0; } /* * command_key_display: display a key binding */ void command_key_display (t_gui_key *key, int new_key) { char *expanded_name; expanded_name = gui_keyboard_get_expanded_name (key->key); if (new_key) { gui_chat_printf (NULL, _("New key binding: %s"), gui_chat_prefix[GUI_CHAT_PREFIX_INFO], (expanded_name) ? expanded_name : key->key); } else gui_chat_printf (NULL, " %20s", (expanded_name) ? expanded_name : key->key); gui_chat_printf (NULL, "%s => %s%s%s%s%s", GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), GUI_COLOR(GUI_COLOR_CHAT), (key->function) ? gui_keyboard_function_search_by_ptr (key->function) : key->command, (key->args) ? " \"" : "", (key->args) ? key->args : "", (key->args) ? "\"" : ""); if (expanded_name) free (expanded_name); } /* * command_key: bind/unbind keys */ int command_key (struct t_gui_buffer *buffer, char *arguments, int argc, char **argv) { char *pos, *pos_args, *args_tmp, *internal_code; int i, length; t_gui_key *ptr_key; t_gui_key_func *ptr_function; /* make C compiler happy */ (void) buffer; (void) argc; (void) argv; if (arguments) { while (arguments[0] == ' ') arguments++; } if (!arguments || (arguments[0] == '\0')) { gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("Key bindings:")); for (ptr_key = gui_keys; ptr_key; ptr_key = ptr_key->next_key) { command_key_display (ptr_key, 0); } } else if (string_strncasecmp (arguments, "unbind ", 7) == 0) { arguments += 7; while (arguments[0] == ' ') arguments++; if (gui_keyboard_unbind (arguments)) { gui_chat_printf (NULL, _("%sKey \"%s\" unbound"), gui_chat_prefix[GUI_CHAT_PREFIX_INFO], arguments); } else { gui_chat_printf (NULL, _("%sError: unable to unbind key \"%s\""), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], arguments); return -1; } } else if (string_strcasecmp (arguments, "functions") == 0) { gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("Internal key functions:")); i = 0; while (gui_key_functions[i].function_name) { gui_chat_printf (NULL, "%25s %s", gui_key_functions[i].function_name, _(gui_key_functions[i].description)); i++; } } else if (string_strncasecmp (arguments, "call ", 5) == 0) { arguments += 5; while (arguments[0] == ' ') arguments++; pos = strchr (arguments, ' '); if (pos) pos[0] = '\0'; ptr_function = gui_keyboard_function_search_by_name (arguments); if (pos) pos[0] = ' '; if (ptr_function) { pos_args = pos; args_tmp = NULL; if (pos_args) { pos_args++; while (pos_args[0] == ' ') pos_args++; if (pos_args[0] == '"') { length = strlen (pos_args); if ((length > 1) && (pos_args[length - 1] == '"')) args_tmp = strndup (pos_args + 1, length - 2); else args_tmp = strdup (pos_args); } else args_tmp = strdup (pos_args); } (void)(*ptr_function)(args_tmp); if (args_tmp) free (args_tmp); } else { gui_chat_printf (NULL, _("%sError: unknown key function \"%s\""), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], arguments); return -1; } } else if (string_strncasecmp (arguments, "reset", 5) == 0) { arguments += 5; while (arguments[0] == ' ') arguments++; if (string_strcasecmp (arguments, "-yes") == 0) { gui_keyboard_free_all (); gui_keyboard_init (); gui_chat_printf (NULL, _("%sDefault key bindings restored"), gui_chat_prefix[GUI_CHAT_PREFIX_INFO]); } else { gui_chat_printf (NULL, _("%sError: \"-yes\" argument is required for " "keys reset (security reason)"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]); return -1; } } else { while (arguments[0] == ' ') arguments++; pos = strchr (arguments, ' '); if (!pos) { ptr_key = NULL; internal_code = gui_keyboard_get_internal_code (arguments); if (internal_code) ptr_key = gui_keyboard_search (internal_code); if (ptr_key) { gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("Key:")); command_key_display (ptr_key, 0); } else { gui_chat_printf (NULL, _("%sNo key found."), gui_chat_prefix[GUI_CHAT_PREFIX_INFO]); } if (internal_code) free (internal_code); return 0; } pos[0] = '\0'; pos++; while (pos[0] == ' ') pos++; ptr_key = gui_keyboard_bind (arguments, pos); if (ptr_key) command_key_display (ptr_key, 1); else { gui_chat_printf (NULL, _("%sError: unable to bind key \"%s\""), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], arguments); return -1; } } return 0; } /* * command_plugin_list: list loaded plugins */ void command_plugin_list (char *name, int full) { struct t_weechat_plugin *ptr_plugin; struct t_hook *ptr_hook; int plugins_found, hook_found, interval; gui_chat_printf (NULL, ""); if (!name) { gui_chat_printf (NULL, _("Plugins loaded:")); } plugins_found = 0; for (ptr_plugin = weechat_plugins; ptr_plugin; ptr_plugin = ptr_plugin->next_plugin) { if (!name || (string_strcasestr (ptr_plugin->name, name))) { plugins_found++; /* plugin info */ gui_chat_printf (NULL, " %s%s%s v%s - %s (%s)", GUI_COLOR(GUI_COLOR_CHAT_BUFFER), ptr_plugin->name, GUI_COLOR(GUI_COLOR_CHAT), ptr_plugin->version, ptr_plugin->description, ptr_plugin->filename); if (full) { /* commands hooked */ hook_found = 0; for (ptr_hook = weechat_hooks; ptr_hook; ptr_hook = ptr_hook->next_hook) { if ((ptr_hook->plugin == ptr_plugin) && (ptr_hook->type == HOOK_TYPE_COMMAND)) { if (!hook_found) gui_chat_printf (NULL, _(" commands hooked:")); hook_found = 1; gui_chat_printf (NULL, " /%s %s%s%s", ((struct t_hook_command *)ptr_hook->hook_data)->command, (((struct t_hook_command *)ptr_hook->hook_data)->description) ? "(" : "", (((struct t_hook_command *)ptr_hook->hook_data)->description) ? ((struct t_hook_command *)ptr_hook->hook_data)->description : "", (((struct t_hook_command *)ptr_hook->hook_data)->description) ? ")" : ""); } } /* messages hooked */ hook_found = 0; for (ptr_hook = weechat_hooks; ptr_hook; ptr_hook = ptr_hook->next_hook) { if ((ptr_hook->plugin == ptr_plugin) && (ptr_hook->type == HOOK_TYPE_MESSAGE)) { if (!hook_found) gui_chat_printf (NULL, _(" messages hooked:")); hook_found = 1; gui_chat_printf (NULL, " %s", ((struct t_hook_message *)ptr_hook->hook_data)->message); } } /* config options hooked */ hook_found = 0; for (ptr_hook = weechat_hooks; ptr_hook; ptr_hook = ptr_hook->next_hook) { if ((ptr_hook->plugin == ptr_plugin) && (ptr_hook->type == HOOK_TYPE_MESSAGE)) { if (!hook_found) gui_chat_printf (NULL, _(" configuration otions " "hooked:")); hook_found = 1; gui_chat_printf (NULL, " (%s) %s", ((struct t_hook_config *)ptr_hook->hook_data)->type ? ((struct t_hook_config *)ptr_hook->hook_data)->type : "*", ((struct t_hook_config *)ptr_hook->hook_data)->option ? ((struct t_hook_config *)ptr_hook->hook_data)->option : "*"); } } /* timers hooked */ hook_found = 0; for (ptr_hook = weechat_hooks; ptr_hook; ptr_hook = ptr_hook->next_hook) { if ((ptr_hook->plugin == ptr_plugin) && (ptr_hook->type == HOOK_TYPE_TIMER)) { if (!hook_found) gui_chat_printf (NULL, _(" timers hooked:")); hook_found = 1; interval = (((struct t_hook_timer *)ptr_hook->hook_data)->interval % 1000 == 0) ? ((struct t_hook_timer *)ptr_hook->hook_data)->interval / 1000 : ((struct t_hook_timer *)ptr_hook->hook_data)->interval; if (((struct t_hook_timer *)ptr_hook->hook_data)->remaining_calls > 0) gui_chat_printf (NULL, _(" %d %s " "(%d calls remaining)"), interval, (((struct t_hook_timer *)ptr_hook->hook_data)->interval % 1000 == 0) ? ((interval > 1) ? _("seconds") : _("second")) : ((interval > 1) ? _("milliseconds") : _("millisecond")), ((struct t_hook_timer *)ptr_hook->hook_data)->remaining_calls); else gui_chat_printf (NULL, _(" %d %s " "(no call limit)"), interval, (((struct t_hook_timer *)ptr_hook->hook_data)->interval % 1000 == 0) ? ((interval > 1) ? _("seconds") : _("second")) : ((interval > 1) ? _("milliseconds") : _("millisecond"))); } } /* fd hooked */ hook_found = 0; for (ptr_hook = weechat_hooks; ptr_hook; ptr_hook = ptr_hook->next_hook) { if ((ptr_hook->plugin == ptr_plugin) && (ptr_hook->type == HOOK_TYPE_MESSAGE)) { if (!hook_found) gui_chat_printf (NULL, _(" fd hooked:")); hook_found = 1; gui_chat_printf (NULL, _(" %d (flags: %d)"), ((struct t_hook_fd *)ptr_hook->hook_data)->fd, ((struct t_hook_fd *)ptr_hook->hook_data)->flags); } } /* keyboards hooked */ hook_found = 0; for (ptr_hook = weechat_hooks; ptr_hook; ptr_hook = ptr_hook->next_hook) { if ((ptr_hook->plugin == ptr_plugin) && (ptr_hook->type == HOOK_TYPE_KEYBOARD)) hook_found++; } if (hook_found) gui_chat_printf (NULL, _(" %d keyboards hooked"), hook_found); } } } if (plugins_found == 0) { if (name) gui_chat_printf (NULL, _("No plugin found.")); else gui_chat_printf (NULL, _(" (no plugin)")); } } /* * command_plugin: list/load/unload WeeChat plugins */ int command_plugin (struct t_gui_buffer *buffer, char *arguments, int argc, char **argv) { /* make C compiler happy */ (void) buffer; (void) arguments; switch (argc) { case 0: command_plugin_list (NULL, 0); break; case 1: if (string_strcasecmp (argv[0], "list") == 0) command_plugin_list (NULL, 0); else if (string_strcasecmp (argv[0], "listfull") == 0) command_plugin_list (NULL, 1); else if (string_strcasecmp (argv[0], "autoload") == 0) plugin_auto_load (); else if (string_strcasecmp (argv[0], "reload") == 0) { plugin_unload_all (); plugin_auto_load (); } else if (string_strcasecmp (argv[0], "unload") == 0) plugin_unload_all (); break; case 2: if (string_strcasecmp (argv[0], "list") == 0) command_plugin_list (argv[1], 0); else if (string_strcasecmp (argv[0], "listfull") == 0) command_plugin_list (argv[1], 1); else if (string_strcasecmp (argv[0], "load") == 0) plugin_load (argv[1]); else if (string_strcasecmp (argv[0], "reload") == 0) plugin_reload_name (argv[1]); else if (string_strcasecmp (argv[0], "unload") == 0) plugin_unload_name (argv[1]); else { gui_chat_printf (NULL, _("%sError: unknown option for \"%s\" " "command"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], "plugin"); } break; default: gui_chat_printf (NULL, _("%sError: wrong argument count for \"%s\" " "command"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], "plugin"); } return 0; } /* * command_quit: quit WeeChat */ int command_quit (struct t_gui_buffer *buffer, char *arguments, int argc, char **argv) { (void) buffer; (void) arguments; (void) argc; (void) argv; quit_weechat = 1; return 0; } /* * command_save: save WeeChat and plugins options to disk */ int command_save (struct t_gui_buffer *buffer, char *arguments, int argc, char **argv) { /* make C compiler happy */ (void) buffer; (void) arguments; (void) argc; (void) argv; /* save WeeChat configuration */ if (weechat_config_write () == 0) gui_chat_printf (NULL, _("%sWeeChat configuration file saved"), gui_chat_prefix[GUI_CHAT_PREFIX_INFO]); else gui_chat_printf (NULL, _("%sError: failed to save configuration file"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]); /* save plugins configuration */ if (plugin_config_write () == 0) gui_chat_printf (NULL, _("%sPlugins options saved"), gui_chat_prefix[GUI_CHAT_PREFIX_INFO]); else gui_chat_printf (NULL, _("%sError: failed to save plugins options"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]); return 0; } /* * command_set_display_option: display config option */ void command_set_display_option (struct t_config_option *option, char *message) { char *color_name; switch (option->type) { case OPTION_TYPE_BOOLEAN: gui_chat_printf (NULL, "%s%s%s = %s%s", (message) ? message : " ", option->name, GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), GUI_COLOR(GUI_COLOR_CHAT_HOST), (*((int *)(option->ptr_int))) ? "ON" : "OFF"); break; case OPTION_TYPE_INT: gui_chat_printf (NULL, "%s%s%s = %s%d", (message) ? message : " ", option->name, GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), GUI_COLOR(GUI_COLOR_CHAT_HOST), *((int *)(option->ptr_int))); break; case OPTION_TYPE_INT_WITH_STRING: gui_chat_printf (NULL, "%s%s%s = %s%s", (message) ? message : " ", option->name, GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), GUI_COLOR(GUI_COLOR_CHAT_HOST), option->array_values[*((int *)(option->ptr_int))]); break; case OPTION_TYPE_COLOR: color_name = gui_color_get_name (*((int *)(option->ptr_int))); gui_chat_printf (NULL, "%s%s%s = %s%s", (message) ? message : " ", option->name, GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), GUI_COLOR(GUI_COLOR_CHAT_HOST), (color_name) ? color_name : _("(unknown)")); break; case OPTION_TYPE_STRING: if (*((char **)(option->ptr_string))) { gui_chat_printf (NULL, "%s%s%s = \"%s%s%s\"", (message) ? message : " ", option->name, GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), GUI_COLOR(GUI_COLOR_CHAT_HOST), *(option->ptr_string), GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS)); } else gui_chat_printf (NULL, "%s%s%s = \"\"", (message) ? message : " ", option->name, GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS)); break; } } /* * command_set_display_option_list: display list of options * Return: number of options displayed */ int command_set_display_option_list (char **config_sections, struct t_config_option **config_options, char *message, char *search) { int i, j, number_found, section_displayed; if (!config_sections || !config_options) return 0; number_found = 0; for (i = 0; config_sections[i]; i++) { if (config_options[i]) { section_displayed = 0; for (j = 0; config_options[i][j].name; j++) { if ((!search) || ((search) && (search[0]) && (string_strcasestr (config_options[i][j].name, search)))) { if (!section_displayed) { gui_chat_printf (NULL, ""); gui_chat_printf (NULL, "%s[%s%s%s]", GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), GUI_COLOR(GUI_COLOR_CHAT_BUFFER), config_sections[i], GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS)); section_displayed = 1; } command_set_display_option (&config_options[i][j], message); number_found++; } } } } return number_found; } /* * command_set: set config options */ int command_set (struct t_gui_buffer *buffer, char *arguments, int argc, char **argv) { char *option, *value, *pos; struct t_config_option *ptr_option; int number_found; /* make C compiler happy */ (void) buffer; (void) argc; (void) argv; option = NULL; value = NULL; if (arguments && arguments[0]) { option = arguments; value = strchr (option, '='); if (value) { value[0] = '\0'; /* remove spaces before '=' */ pos = value - 1; while ((pos > option) && (pos[0] == ' ')) { pos[0] = '\0'; pos--; } /* skip spaces after '=' */ value++; while (value[0] && (value[0] == ' ')) { value++; } /* remove simple or double quotes and spaces at the end */ if (strlen(value) > 1) { pos = value + strlen (value) - 1; while ((pos > value) && (pos[0] == ' ')) { pos[0] = '\0'; pos--; } pos = value + strlen (value) - 1; if (((value[0] == '\'') && (pos[0] == '\'')) || ((value[0] == '"') && (pos[0] == '"'))) { pos[0] = '\0'; value++; } } } } if (value) { pos = strrchr (option, '.'); /*if (pos) { pos[0] = '\0'; ptr_protocol = protocol_search (option); if (!ptr_protocol) { gui_chat_printf (NULL, _("%sError: protocol \"%s\" not found"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], option); } else { ptr_option = config_option_section_option_search (ptr_protocol->config_sections, ptr_protocol->config_options, pos + 1); if (ptr_option) { switch (config_option_set (ptr_option, value)) { case 0: gui_chat_printf (NULL, ""); command_set_display_option (ptr_option, ptr_protocol->name); break; default: gui_chat_printf (NULL, _("%sError: incorrect value for " "option \"%s\""), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], pos + 1); break; } } else gui_chat_printf (NULL, _("%sError: config option \"%s\" not found"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], pos + 1); } pos[0] = '.'; } else*/ { ptr_option = config_option_section_option_search (weechat_config_sections, weechat_config_options, option); if (ptr_option) { if (ptr_option->handler_change == NULL) { gui_chat_printf (NULL, _("%sError: option \"%s\" can not be " "changed while WeeChat is " "running"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], option); } else { if (config_option_set (ptr_option, value) == 0) { command_set_display_option (ptr_option, _("Option changed: ")); (void) (ptr_option->handler_change()); } else { gui_chat_printf (NULL, _("%sError: incorrect value for " "option \"%s\""), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], option); } } } else { gui_chat_printf (NULL, _("%sError: configuration option \"%s\" not " "found"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], option); } } } else { number_found = 0; number_found += command_set_display_option_list (weechat_config_sections, weechat_config_options, NULL, option); if (number_found == 0) { if (option) gui_chat_printf (NULL, _("No configuration option found with " "\"%s\""), option); else gui_chat_printf (NULL, _("No configuration option found")); } else { gui_chat_printf (NULL, ""); if (option) gui_chat_printf (NULL, _("%s%d%s configuration option(s) found with " "\"%s\""), GUI_COLOR(GUI_COLOR_CHAT_BUFFER), number_found, GUI_COLOR(GUI_COLOR_CHAT), option); else gui_chat_printf (NULL, _("%s%d%s configuration option(s) found"), GUI_COLOR(GUI_COLOR_CHAT_BUFFER), number_found, GUI_COLOR(GUI_COLOR_CHAT)); } } return 0; } /* * command_setp: set plugin options */ int command_setp (struct t_gui_buffer *buffer, char *arguments, int argc, char **argv) { char *option, *value, *pos, *ptr_name; struct t_plugin_option *ptr_option; int number_found; /* make C compiler happy */ (void) buffer; (void) argc; (void) argv; option = NULL; value = NULL; if (arguments && arguments[0]) { option = arguments; value = strchr (option, '='); if (value) { value[0] = '\0'; /* remove spaces before '=' */ pos = value - 1; while ((pos > option) && (pos[0] == ' ')) { pos[0] = '\0'; pos--; } /* skip spaces after '=' */ value++; while (value[0] && (value[0] == ' ')) { value++; } /* remove simple or double quotes and spaces at the end */ if (strlen(value) > 1) { pos = value + strlen (value) - 1; while ((pos > value) && (pos[0] == ' ')) { pos[0] = '\0'; pos--; } pos = value + strlen (value) - 1; if (((value[0] == '\'') && (pos[0] == '\'')) || ((value[0] == '"') && (pos[0] == '"'))) { pos[0] = '\0'; value++; } } } } if (value) { ptr_name = NULL; ptr_option = plugin_config_search_internal (option); if (ptr_option) ptr_name = ptr_option->name; else { pos = strchr (option, '.'); if (pos) pos[0] = '\0'; if (!pos || !pos[1] || (!plugin_search (option))) { gui_chat_printf (NULL, _("%sError: plugin \"%s\" not found"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], option); } else ptr_name = option; if (pos) pos[0] = '.'; } if (ptr_name) { if (plugin_config_set_internal (ptr_name, value)) { gui_chat_printf (NULL, _("Plugin option changed: %s%s = \"%s%s%s\""), ptr_name, GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), GUI_COLOR(GUI_COLOR_CHAT_HOST), value, GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS)); } else { gui_chat_printf (NULL, _("%sError: incorrect value for plugin " "option \"%s\""), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], ptr_name); } } } else { number_found = 0; for (ptr_option = plugin_options; ptr_option; ptr_option = ptr_option->next_option) { if ((!option) || ((option) && (option[0]) && (strstr (ptr_option->name, option) != NULL))) { if (number_found == 0) gui_chat_printf (NULL, ""); gui_chat_printf (NULL, " %s%s = \"%s%s%s\"", ptr_option->name, GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), GUI_COLOR(GUI_COLOR_CHAT_HOST), ptr_option->value, GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS)); number_found++; } } if (number_found == 0) { if (option) gui_chat_printf (NULL, _("No plugin option found with \"%s\""), option); else gui_chat_printf (NULL, _("No plugin option found")); } else { gui_chat_printf (NULL, ""); gui_chat_printf (NULL, "%s%d %s", GUI_COLOR(GUI_COLOR_CHAT_BUFFER), number_found, GUI_COLOR(GUI_COLOR_CHAT)); if (option) gui_chat_printf (NULL, _("plugin option(s) found with \"%s\""), option); else gui_chat_printf (NULL, _("plugin option(s) found")); } } return 0; } /* * command_unalias: remove an alias */ int command_unalias (struct t_gui_buffer *buffer, char *arguments, int argc, char **argv) { struct t_weelist *ptr_weelist; struct alias *ptr_alias; /* make C compiler happy */ (void) buffer; (void) argc; (void) argv; if (arguments[0] == '/') arguments++; ptr_weelist = weelist_search (weechat_index_commands, arguments); if (!ptr_weelist) { gui_chat_printf (NULL, _("%sError: alias or command \"%s\" not found"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], arguments); return -1; } weelist_remove (&weechat_index_commands, &weechat_last_index_command, ptr_weelist); ptr_alias = alias_search (arguments); if (ptr_alias) alias_free (ptr_alias); gui_chat_printf (NULL, _("%sAlias \"%s\" removed"), gui_chat_prefix[GUI_CHAT_PREFIX_INFO], arguments); return 0; } /* * command_upgrade: upgrade WeeChat */ int command_upgrade (struct t_gui_buffer *buffer, char *arguments, int argc, char **argv) { /*int filename_length; char *filename, *ptr_binary; char *exec_args[7] = { NULL, "-a", "--dir", NULL, "--session", NULL, NULL };*/ /* make C compiler happy */ (void) buffer; (void) arguments; (void) argc; (void) argv; /*ptr_binary = (argc > 0) ? argv[0] : weechat_argv0; for (ptr_server = irc_servers; ptr_server; ptr_server = ptr_server->next_server) { if (ptr_server->child_pid != 0) { gui_chat_printf_error (NULL, _("Error: can't upgrade: connection to at least " "one server is pending")); return -1; }*/ /* TODO: remove this test, and fix gnutls save/load in session */ /*if (ptr_server->is_connected && ptr_server->ssl_connected) { gui_chat_printf_error_nolog (NULL, _("Error: can't upgrade: connection to at least " "one SSL server is active " "(should be fixed in a future version)")); return -1; } if (ptr_server->outqueue) { gui_chat_printf_error_nolog (NULL, _("Error: can't upgrade: anti-flood is active on " "at least one server (sending many lines)")); return -1; } } filename_length = strlen (weechat_home) + strlen (WEECHAT_SESSION_NAME) + 2; filename = (char *) malloc (filename_length * sizeof (char)); if (!filename) return -2; snprintf (filename, filename_length, "%s%s" WEECHAT_SESSION_NAME, weechat_home, DIR_SEPARATOR); gui_chat_printf_info_nolog (NULL, _("Upgrading WeeChat...")); if (!session_save (filename)) { free (filename); gui_chat_printf_error_nolog (NULL, _("Error: unable to save session in file")); return -1; } exec_args[0] = strdup (ptr_binary); exec_args[3] = strdup (weechat_home); exec_args[5] = strdup (filename);*/ /* unload plugins, save config, then upgrade */ plugin_end (); /*if (cfg_look_save_on_exit) (void) config_write (NULL); gui_main_end (); fifo_remove (); weechat_log_close (); execvp (exec_args[0], exec_args);*/ /* this code should not be reached if execvp is ok */ plugin_init (1); /*string_iconv_fprintf (stderr, _("Error: exec failed (program: \"%s\"), exiting WeeChat"), exec_args[0]); free (exec_args[0]); free (exec_args[3]); free (filename); exit (EXIT_FAILURE);*/ /* never executed */ return -1; } /* * command_uptime: display WeeChat uptime */ int command_uptime (struct t_gui_buffer *buffer, char *arguments, int argc, char **argv) { time_t running_time; int day, hour, min, sec; char string[256]; /* make C compiler happy */ (void) arguments; running_time = time (NULL) - weechat_start_time; day = running_time / (60 * 60 * 24); hour = (running_time % (60 * 60 * 24)) / (60 * 60); min = ((running_time % (60 * 60 * 24)) % (60 * 60)) / 60; sec = ((running_time % (60 * 60 * 24)) % (60 * 60)) % 60; if ((argc == 1) && (strcmp (argv[0], "-o") == 0)) { snprintf (string, sizeof (string), _("WeeChat uptime: %d %s %02d:%02d:%02d, started on %s"), day, NG_("day", "days", day), hour, min, sec, ctime (&weechat_start_time)); string[strlen (string) - 1] = '\0'; input_data (buffer, string, 0); } else { gui_chat_printf (NULL, _("%sWeeChat uptime: %s%d %s%s " "%s%02d%s:%s%02d%s:%s%02d%s, " "started on %s%s"), gui_chat_prefix[GUI_CHAT_PREFIX_INFO], GUI_COLOR(GUI_COLOR_CHAT_BUFFER), day, GUI_COLOR(GUI_COLOR_CHAT), NG_("day", "days", day), GUI_COLOR(GUI_COLOR_CHAT_BUFFER), hour, GUI_COLOR(GUI_COLOR_CHAT), GUI_COLOR(GUI_COLOR_CHAT_BUFFER), min, GUI_COLOR(GUI_COLOR_CHAT), GUI_COLOR(GUI_COLOR_CHAT_BUFFER), sec, GUI_COLOR(GUI_COLOR_CHAT), GUI_COLOR(GUI_COLOR_CHAT_BUFFER), ctime (&weechat_start_time)); } return 0; } /* * command_window: manage windows */ int command_window (struct t_gui_buffer *buffer, char *arguments, int argc, char **argv) { struct t_gui_window *ptr_win; int i; char *error; long number; /* make C compiler happy */ (void) buffer; (void) arguments; if ((argc == 0) || ((argc == 1) && (string_strcasecmp (argv[0], "list") == 0))) { /* list open windows */ gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("Open windows:")); i = 1; for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window) { gui_chat_printf (NULL, "%s[%s%d%s] (%s%d:%d%s;%s%dx%d%s) ", GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), GUI_COLOR(GUI_COLOR_CHAT), i, GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), GUI_COLOR(GUI_COLOR_CHAT), ptr_win->win_x, ptr_win->win_y, GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), GUI_COLOR(GUI_COLOR_CHAT), ptr_win->win_width, ptr_win->win_height, GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS)); command_buffer_display_info (ptr_win->buffer); i++; } } else { if (string_strcasecmp (argv[0], "splith") == 0) { /* split window horizontally */ if (argc > 1) { error = NULL; number = strtol (argv[1], &error, 10); if (error && (error[0] == '\0') && (number > 0) && (number < 100)) gui_window_split_horiz (gui_current_window, number); } else gui_window_split_horiz (gui_current_window, 50); } else if (string_strcasecmp (argv[0], "splitv") == 0) { /* split window vertically */ if (argc > 1) { error = NULL; number = strtol (argv[1], &error, 10); if (error && (error[0] == '\0') && (number > 0) && (number < 100)) gui_window_split_vertic (gui_current_window, number); } else gui_window_split_vertic (gui_current_window, 50); } else if (string_strcasecmp (argv[0], "resize") == 0) { /* resize window */ if (argc > 1) { error = NULL; number = strtol (argv[1], &error, 10); if (error && (error[0] == '\0') && (number > 0) && (number < 100)) gui_window_resize (gui_current_window, number); } } else if (string_strcasecmp (argv[0], "merge") == 0) { if (argc >= 2) { if (string_strcasecmp (argv[1], "all") == 0) gui_window_merge_all (gui_current_window); else { gui_chat_printf (NULL, _("%sError: unknown option for \"%s\" " "command"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], "window merge"); return -1; } } else { if (!gui_window_merge (gui_current_window)) { gui_chat_printf (NULL, _("%sError: can not merge windows, " "there's no other window with same " "size near current one."), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]); return -1; } } } else if (string_strncasecmp (argv[0], "b", 1) == 0) { /* jump to window by buffer number */ error = NULL; number = strtol (argv[0] + 1, &error, 10); if (error && (error[0] == '\0')) gui_window_switch_by_buffer (gui_current_window, number); } else if (string_strcasecmp (argv[0], "-1") == 0) gui_window_switch_previous (gui_current_window); else if (string_strcasecmp (argv[0], "+1") == 0) gui_window_switch_next (gui_current_window); else if (string_strcasecmp (argv[0], "up") == 0) gui_window_switch_up (gui_current_window); else if (string_strcasecmp (argv[0], "down") == 0) gui_window_switch_down (gui_current_window); else if (string_strcasecmp (argv[0], "left") == 0) gui_window_switch_left (gui_current_window); else if (string_strcasecmp (argv[0], "right") == 0) gui_window_switch_right (gui_current_window); else if (string_strcasecmp (argv[0], "scroll") == 0) { if (argc >= 2) gui_window_scroll (gui_current_window, argv[1]); } else { gui_chat_printf (NULL, _("%sError: unknown option for \"%s\" command"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], "window"); return -1; } } return 0; }