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 |
141 MSGLEVEL_NEVER, "%s", str);
144 line_split_free(buffer);
150 static void cmd_beep(void)
152 signal_emit("beep", 0);
155 static void cmd_nick(const char *data, SERVER_REC *server)
157 g_return_if_fail(data != NULL);
159 if (*data != '\0') return;
160 if (server == NULL || !server->connected)
161 cmd_return_error(CMDERR_NOT_CONNECTED);
163 /* display current nick */
164 printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_YOUR_NICK, server->nick);
168 static void cmd_join(const char *data, SERVER_REC *server)
174 g_return_if_fail(data != NULL);
176 if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
177 PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST,
178 "join", &optlist, &channels))
181 server = cmd_options_get_server("join", optlist, server);
182 if (g_hash_table_lookup(optlist, "invite") &&
183 server != NULL && server->last_invite == NULL) {
184 /* ..all this trouble just to print this error message */
185 printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_NOT_INVITED);
189 cmd_params_free(free_arg);
192 static void sig_stop(void)
197 static void event_command(const char *data)
202 /* empty line, forget it. */
207 /* save current command line */
208 current_cmdline = data;
210 /* for detecting if we're pasting text */
211 time_command_last = time_command_now;
212 last_command_cmd = command_cmd;
214 g_get_current_time(&time_command_now);
215 command_cmd = strchr(settings_get_str("cmdchars"), *data) != NULL;
217 /* /^command hides the output of the command */
218 cmdchar = strchr(settings_get_str("cmdchars"), *data);
219 if (cmdchar != NULL && (data[1] == '^' ||
220 (data[1] == *cmdchar && data[2] == '^'))) {
222 signal_add_first("print starting", (SIGNAL_FUNC) sig_stop);
223 signal_add_first("print format", (SIGNAL_FUNC) sig_stop);
224 signal_add_first("print text", (SIGNAL_FUNC) sig_stop);
228 static void event_command_last(const char *data)
232 signal_remove("print starting", (SIGNAL_FUNC) sig_stop);
233 signal_remove("print format", (SIGNAL_FUNC) sig_stop);
234 signal_remove("print text", (SIGNAL_FUNC) sig_stop);
238 static void event_default_command(const char *data, void *server,
241 const char *cmdchars, *ptr;
245 cmdchars = settings_get_str("cmdchars");
248 while (*ptr != '\0' && *ptr != ' ') {
249 if (strchr(cmdchars, *ptr)) {
250 /* command character inside command .. we probably
251 want to send this text to channel. for example
252 when pasting a path /usr/bin/xxx. */
253 signal_emit("send text", 3, current_cmdline, server, item);
259 /* maybe we're copy+pasting text? check how long it was since the
261 diff = get_timeval_diff(&time_command_now, &time_command_last);
262 if (item != NULL && !last_command_cmd && diff < PASTE_CHECK_SPEED) {
263 signal_emit("send text", 3, current_cmdline, active_win->active_server, active_win->active);
268 /* get the command part of the line, send "error command" signal */
269 cmd = g_strdup(data);
270 p = strchr(cmd, ' ');
271 if (p != NULL) *p = '\0';
273 signal_emit("error command", 2, GINT_TO_POINTER(CMDERR_UNKNOWN), cmd);
278 static void event_cmderror(void *errorp, const char *arg)
282 error = GPOINTER_TO_INT(errorp);
283 if (error == CMDERR_ERRNO) {
284 /* errno is special */
285 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "%s", g_strerror(errno));
288 printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, ret_texts[error + -CMDERR_OPTION_UNKNOWN], arg);
292 static void event_list_subcommands(const char *command)
298 str = g_string_new(NULL);
300 len = strlen(command);
301 for (tmp = commands; tmp != NULL; tmp = tmp->next) {
302 COMMAND_REC *rec = tmp->data;
304 if (g_strncasecmp(rec->cmd, command, len) == 0 &&
305 rec->cmd[len] == ' ' &&
306 strchr(rec->cmd+len+1, ' ') == NULL) {
307 g_string_sprintfa(str, "%s ", rec->cmd+len+1);
312 g_string_truncate(str, str->len-1);
313 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "%s", str->str);
316 g_string_free(str, TRUE);
319 void fe_core_commands_init(void)
324 memset(&time_command_now, 0, sizeof(GTimeVal));
326 command_bind("echo", NULL, (SIGNAL_FUNC) cmd_echo);
327 command_bind("version", NULL, (SIGNAL_FUNC) cmd_version);
328 command_bind("cat", NULL, (SIGNAL_FUNC) cmd_cat);
329 command_bind("beep", NULL, (SIGNAL_FUNC) cmd_beep);
330 command_bind_first("nick", NULL, (SIGNAL_FUNC) cmd_nick);
331 command_bind_first("join", NULL, (SIGNAL_FUNC) cmd_join);
333 signal_add("send command", (SIGNAL_FUNC) event_command);
334 signal_add_last("send command", (SIGNAL_FUNC) event_command_last);
335 signal_add("default command", (SIGNAL_FUNC) event_default_command);
336 signal_add("error command", (SIGNAL_FUNC) event_cmderror);
337 signal_add("list subcommands", (SIGNAL_FUNC) event_list_subcommands);
339 command_set_options("echo", "current +level +window");
342 void fe_core_commands_deinit(void)
344 command_unbind("echo", (SIGNAL_FUNC) cmd_echo);
345 command_unbind("version", (SIGNAL_FUNC) cmd_version);
346 command_unbind("cat", (SIGNAL_FUNC) cmd_cat);
347 command_unbind("beep", (SIGNAL_FUNC) cmd_beep);
348 command_unbind("nick", (SIGNAL_FUNC) cmd_nick);
349 command_unbind("join", (SIGNAL_FUNC) cmd_join);
351 signal_remove("send command", (SIGNAL_FUNC) event_command);
352 signal_remove("send command", (SIGNAL_FUNC) event_command_last);
353 signal_remove("default command", (SIGNAL_FUNC) event_default_command);
354 signal_remove("error command", (SIGNAL_FUNC) event_cmderror);
355 signal_remove("list subcommands", (SIGNAL_FUNC) event_list_subcommands);