2 fe-core-commands.c : irssi
4 Copyright (C) 1999-2001 Timo Sirainen
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "module-formats.h"
27 #include "line-split.h"
29 #include "irssi-version.h"
32 #include "fe-windows.h"
33 #include "printtext.h"
35 #define PASTE_CHECK_SPEED 200 /* 0.2 sec */
37 static int ret_texts[] = {
40 TXT_OPTION_MISSING_ARG,
42 TXT_COMMAND_AMBIGUOUS,
44 TXT_NOT_ENOUGH_PARAMS,
53 /* keep the whole command line here temporarily. we need it in
54 "default command" event handler, but there we don't know if the start of
55 the line had one or two command chars, and which one.. */
56 static const char *current_cmdline;
57 static int hide_output;
59 static GTimeVal time_command_last, time_command_now;
60 static int last_command_cmd, command_cmd;
62 /* SYNTAX: ECHO [-current] [-window <name>] [-level <level>] <text> */
63 static void cmd_echo(const char *data, void *server, WI_ITEM_REC *item)
67 char *msg, *levelstr, *winname;
71 g_return_if_fail(data != NULL);
73 if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
74 PARAM_FLAG_GETREST, "echo", &optlist, &msg))
77 levelstr = g_hash_table_lookup(optlist, "level");
78 level = levelstr == NULL ? 0 :
79 level2bits(g_hash_table_lookup(optlist, "level"));
80 if (level == 0) level = MSGLEVEL_CRAP;
82 winname = g_hash_table_lookup(optlist, "window");
83 window = winname == NULL ? NULL :
84 is_numeric(winname, '\0') ?
85 window_find_refnum(atoi(winname)) :
86 window_find_item(NULL, winname);
87 if (window == NULL) window = active_win;
89 printtext_window(window, level, "%s", msg);
90 cmd_params_free(free_arg);
94 static void cmd_version(char *data)
98 g_return_if_fail(data != NULL);
101 g_snprintf(time, sizeof(time), "%04d", IRSSI_VERSION_TIME);
102 printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
103 "Client: "PACKAGE" " IRSSI_VERSION" (%d %s)",
104 IRSSI_VERSION_DATE, time);
108 /* SYNTAX: CAT <file> */
109 static void cmd_cat(const char *data)
111 LINEBUF_REC *buffer = NULL;
112 char *fname, *fposstr;
113 char tmpbuf[1024], *str;
115 int f, ret, recvlen, fpos;
117 if (!cmd_get_params(data, &free_arg, 2, &fname, &fposstr))
120 fname = convert_home(fname);
121 fpos = atoi(fposstr);
122 cmd_params_free(free_arg);
124 f = open(fname, O_RDONLY);
129 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
130 "%s", g_strerror(errno));
134 lseek(f, fpos, SEEK_SET);
136 recvlen = read(f, tmpbuf, sizeof(tmpbuf));
138 ret = line_split(tmpbuf, recvlen, &str, &buffer);
140 printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "%s", str);
142 line_split_free(buffer);
148 static void cmd_beep(void)
150 signal_emit("beep", 0);
153 static void cmd_nick(const char *data, SERVER_REC *server)
155 g_return_if_fail(data != NULL);
157 if (*data != '\0') return;
158 if (server == NULL || !server->connected)
159 cmd_return_error(CMDERR_NOT_CONNECTED);
161 /* display current nick */
162 printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_YOUR_NICK, server->nick);
166 static void cmd_join(const char *data, SERVER_REC *server)
172 g_return_if_fail(data != NULL);
174 if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
175 PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST,
176 "join", &optlist, &channels))
179 server = cmd_options_get_server("join", optlist, server);
180 if (g_hash_table_lookup(optlist, "invite") &&
181 server != NULL && server->last_invite == NULL) {
182 /* ..all this trouble just to print this error message */
183 printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_NOT_INVITED);
187 cmd_params_free(free_arg);
190 static void sig_stop(void)
195 static void event_command(const char *data)
200 /* empty line, forget it. */
205 /* save current command line */
206 current_cmdline = data;
208 /* for detecting if we're pasting text */
209 time_command_last = time_command_now;
210 last_command_cmd = command_cmd;
212 g_get_current_time(&time_command_now);
213 command_cmd = strchr(settings_get_str("cmdchars"), *data) != NULL;
215 /* /^command hides the output of the command */
216 cmdchar = strchr(settings_get_str("cmdchars"), *data);
217 if (cmdchar != NULL && (data[1] == '^' ||
218 (data[1] == *cmdchar && data[2] == '^'))) {
220 signal_add_first("print starting", (SIGNAL_FUNC) sig_stop);
221 signal_add_first("print format", (SIGNAL_FUNC) sig_stop);
222 signal_add_first("print text", (SIGNAL_FUNC) sig_stop);
226 static void event_command_last(const char *data)
230 signal_remove("print starting", (SIGNAL_FUNC) sig_stop);
231 signal_remove("print format", (SIGNAL_FUNC) sig_stop);
232 signal_remove("print text", (SIGNAL_FUNC) sig_stop);
236 static void event_default_command(const char *data, void *server,
239 const char *cmdchars, *ptr;
243 cmdchars = settings_get_str("cmdchars");
246 while (*ptr != '\0' && *ptr != ' ') {
247 if (strchr(cmdchars, *ptr)) {
248 /* command character inside command .. we probably
249 want to send this text to channel. for example
250 when pasting a path /usr/bin/xxx. */
251 signal_emit("send text", 3, current_cmdline, server, item);
257 /* maybe we're copy+pasting text? check how long it was since the
259 diff = get_timeval_diff(&time_command_now, &time_command_last);
260 if (item != NULL && !last_command_cmd && diff < PASTE_CHECK_SPEED) {
261 signal_emit("send text", 3, current_cmdline, active_win->active_server, active_win->active);
266 /* get the command part of the line, send "error command" signal */
267 cmd = g_strdup(data);
268 p = strchr(cmd, ' ');
269 if (p != NULL) *p = '\0';
271 signal_emit("error command", 2, GINT_TO_POINTER(CMDERR_UNKNOWN), cmd);
276 static void event_cmderror(void *errorp, const char *arg)
280 error = GPOINTER_TO_INT(errorp);
281 if (error == CMDERR_ERRNO) {
282 /* errno is special */
283 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "%s", g_strerror(errno));
286 printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, ret_texts[error + -CMDERR_OPTION_UNKNOWN], arg);
290 static void event_list_subcommands(const char *command)
296 str = g_string_new(NULL);
298 len = strlen(command);
299 for (tmp = commands; tmp != NULL; tmp = tmp->next) {
300 COMMAND_REC *rec = tmp->data;
302 if (g_strncasecmp(rec->cmd, command, len) == 0 &&
303 rec->cmd[len] == ' ' &&
304 strchr(rec->cmd+len+1, ' ') == NULL) {
305 g_string_sprintfa(str, "%s ", rec->cmd+len+1);
310 g_string_truncate(str, str->len-1);
311 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "%s", str->str);
314 g_string_free(str, TRUE);
317 void fe_core_commands_init(void)
322 memset(&time_command_now, 0, sizeof(GTimeVal));
324 command_bind("echo", NULL, (SIGNAL_FUNC) cmd_echo);
325 command_bind("version", NULL, (SIGNAL_FUNC) cmd_version);
326 command_bind("cat", NULL, (SIGNAL_FUNC) cmd_cat);
327 command_bind("beep", NULL, (SIGNAL_FUNC) cmd_beep);
328 command_bind_first("nick", NULL, (SIGNAL_FUNC) cmd_nick);
329 command_bind_first("join", NULL, (SIGNAL_FUNC) cmd_join);
331 signal_add("send command", (SIGNAL_FUNC) event_command);
332 signal_add_last("send command", (SIGNAL_FUNC) event_command_last);
333 signal_add("default command", (SIGNAL_FUNC) event_default_command);
334 signal_add("error command", (SIGNAL_FUNC) event_cmderror);
335 signal_add("list subcommands", (SIGNAL_FUNC) event_list_subcommands);
337 command_set_options("echo", "current +level +window");
340 void fe_core_commands_deinit(void)
342 command_unbind("echo", (SIGNAL_FUNC) cmd_echo);
343 command_unbind("version", (SIGNAL_FUNC) cmd_version);
344 command_unbind("cat", (SIGNAL_FUNC) cmd_cat);
345 command_unbind("beep", (SIGNAL_FUNC) cmd_beep);
346 command_unbind("nick", (SIGNAL_FUNC) cmd_nick);
347 command_unbind("join", (SIGNAL_FUNC) cmd_join);
349 signal_remove("send command", (SIGNAL_FUNC) event_command);
350 signal_remove("send command", (SIGNAL_FUNC) event_command_last);
351 signal_remove("default command", (SIGNAL_FUNC) event_default_command);
352 signal_remove("error command", (SIGNAL_FUNC) event_cmderror);
353 signal_remove("list subcommands", (SIGNAL_FUNC) event_list_subcommands);