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 int command_hide_output;
55 /* keep the whole command line here temporarily. we need it in
56 "default command" event handler, but there we don't know if the start of
57 the line had one or two command chars, and which one.. */
58 static const char *current_cmdline;
60 static GTimeVal time_command_last, time_command_now;
61 static int last_command_cmd, command_cmd;
63 /* SYNTAX: ECHO [-current] [-window <name>] [-level <level>] <text> */
64 static void cmd_echo(const char *data, void *server, WI_ITEM_REC *item)
68 char *msg, *levelstr, *winname;
72 g_return_if_fail(data != NULL);
74 if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
75 PARAM_FLAG_GETREST, "echo", &optlist, &msg))
78 levelstr = g_hash_table_lookup(optlist, "level");
79 level = levelstr == NULL ? 0 :
80 level2bits(g_hash_table_lookup(optlist, "level"));
81 if (level == 0) level = MSGLEVEL_CRAP;
83 winname = g_hash_table_lookup(optlist, "window");
84 window = winname == NULL ? NULL :
85 is_numeric(winname, '\0') ?
86 window_find_refnum(atoi(winname)) :
87 window_find_item(NULL, winname);
88 if (window == NULL) window = active_win;
90 printtext_window(window, level, "%s", msg);
91 cmd_params_free(free_arg);
95 static void cmd_version(char *data)
99 g_return_if_fail(data != NULL);
102 g_snprintf(time, sizeof(time), "%04d", IRSSI_VERSION_TIME);
103 printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
104 "Client: "PACKAGE" " IRSSI_VERSION" (%d %s)",
105 IRSSI_VERSION_DATE, time);
109 /* SYNTAX: CAT <file> */
110 static void cmd_cat(const char *data)
112 LINEBUF_REC *buffer = NULL;
113 char *fname, *fposstr;
114 char tmpbuf[1024], *str;
116 int f, ret, recvlen, fpos;
118 if (!cmd_get_params(data, &free_arg, 2, &fname, &fposstr))
121 fname = convert_home(fname);
122 fpos = atoi(fposstr);
123 cmd_params_free(free_arg);
125 f = open(fname, O_RDONLY);
130 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
131 "%s", g_strerror(errno));
135 lseek(f, fpos, SEEK_SET);
137 recvlen = read(f, tmpbuf, sizeof(tmpbuf));
139 ret = line_split(tmpbuf, recvlen, &str, &buffer);
141 printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP |
142 MSGLEVEL_NEVER, "%s", str);
145 line_split_free(buffer);
151 static void cmd_beep(void)
153 signal_emit("beep", 0);
156 static void cmd_nick(const char *data, SERVER_REC *server)
158 g_return_if_fail(data != NULL);
160 if (*data != '\0') return;
161 if (server == NULL || !server->connected)
162 cmd_return_error(CMDERR_NOT_CONNECTED);
164 /* display current nick */
165 printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_YOUR_NICK, server->nick);
169 static void cmd_join(const char *data, SERVER_REC *server)
175 g_return_if_fail(data != NULL);
177 if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
178 PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST,
179 "join", &optlist, &channels))
182 server = cmd_options_get_server("join", optlist, server);
183 if (g_hash_table_lookup(optlist, "invite") &&
184 server != NULL && server->last_invite == NULL) {
185 /* ..all this trouble just to print this error message */
186 printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_NOT_INVITED);
190 cmd_params_free(free_arg);
193 static void sig_stop(void)
198 static void event_command(const char *data)
202 /* save current command line */
203 current_cmdline = data;
205 /* for detecting if we're pasting text */
206 time_command_last = time_command_now;
207 last_command_cmd = command_cmd;
209 g_get_current_time(&time_command_now);
210 command_cmd = *data != '\0' &&
211 strchr(settings_get_str("cmdchars"), *data) != NULL;
213 /* /^command hides the output of the command */
214 cmdchar = *data == '\0' ? NULL :
215 strchr(settings_get_str("cmdchars"), *data);
216 if (cmdchar != NULL && (data[1] == '^' ||
217 (data[1] == *cmdchar && data[2] == '^'))) {
218 command_hide_output = TRUE;
219 signal_add_first("print starting", (SIGNAL_FUNC) sig_stop);
220 signal_add_first("print format", (SIGNAL_FUNC) sig_stop);
221 signal_add_first("print text", (SIGNAL_FUNC) sig_stop);
225 static void event_command_last(const char *data)
227 if (command_hide_output) {
228 command_hide_output = FALSE;
229 signal_remove("print starting", (SIGNAL_FUNC) sig_stop);
230 signal_remove("print format", (SIGNAL_FUNC) sig_stop);
231 signal_remove("print text", (SIGNAL_FUNC) sig_stop);
235 static void event_default_command(const char *data, void *server,
238 const char *cmdchars, *ptr;
242 cmdchars = settings_get_str("cmdchars");
245 while (*ptr != '\0' && *ptr != ' ') {
246 if (strchr(cmdchars, *ptr)) {
247 /* command character inside command .. we probably
248 want to send this text to channel. for example
249 when pasting a path /usr/bin/xxx. */
250 signal_emit("send text", 3, current_cmdline, server, item);
256 /* maybe we're copy+pasting text? check how long it was since the
258 diff = get_timeval_diff(&time_command_now, &time_command_last);
259 if (item != NULL && !last_command_cmd && diff < PASTE_CHECK_SPEED) {
260 signal_emit("send text", 3, current_cmdline, active_win->active_server, active_win->active);
265 /* get the command part of the line, send "error command" signal */
266 cmd = g_strdup(data);
267 p = strchr(cmd, ' ');
268 if (p != NULL) *p = '\0';
270 signal_emit("error command", 2, GINT_TO_POINTER(CMDERR_UNKNOWN), cmd);
275 static void event_cmderror(void *errorp, const char *arg)
279 error = GPOINTER_TO_INT(errorp);
280 if (error == CMDERR_ERRNO) {
281 /* errno is special */
282 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "%s", g_strerror(errno));
285 printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, ret_texts[error + -CMDERR_OPTION_UNKNOWN], arg);
289 static void event_list_subcommands(const char *command)
295 str = g_string_new(NULL);
297 len = strlen(command);
298 for (tmp = commands; tmp != NULL; tmp = tmp->next) {
299 COMMAND_REC *rec = tmp->data;
301 if (g_strncasecmp(rec->cmd, command, len) == 0 &&
302 rec->cmd[len] == ' ' &&
303 strchr(rec->cmd+len+1, ' ') == NULL) {
304 g_string_sprintfa(str, "%s ", rec->cmd+len+1);
309 g_string_truncate(str, str->len-1);
310 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "%s", str->str);
313 g_string_free(str, TRUE);
316 void fe_core_commands_init(void)
318 command_hide_output = FALSE;
321 memset(&time_command_now, 0, sizeof(GTimeVal));
323 command_bind("echo", NULL, (SIGNAL_FUNC) cmd_echo);
324 command_bind("version", NULL, (SIGNAL_FUNC) cmd_version);
325 command_bind("cat", NULL, (SIGNAL_FUNC) cmd_cat);
326 command_bind("beep", NULL, (SIGNAL_FUNC) cmd_beep);
327 command_bind_first("nick", NULL, (SIGNAL_FUNC) cmd_nick);
328 command_bind_first("join", NULL, (SIGNAL_FUNC) cmd_join);
330 signal_add("send command", (SIGNAL_FUNC) event_command);
331 signal_add_last("send command", (SIGNAL_FUNC) event_command_last);
332 signal_add("default command", (SIGNAL_FUNC) event_default_command);
333 signal_add("error command", (SIGNAL_FUNC) event_cmderror);
334 signal_add("list subcommands", (SIGNAL_FUNC) event_list_subcommands);
336 command_set_options("echo", "current +level +window");
339 void fe_core_commands_deinit(void)
341 command_unbind("echo", (SIGNAL_FUNC) cmd_echo);
342 command_unbind("version", (SIGNAL_FUNC) cmd_version);
343 command_unbind("cat", (SIGNAL_FUNC) cmd_cat);
344 command_unbind("beep", (SIGNAL_FUNC) cmd_beep);
345 command_unbind("nick", (SIGNAL_FUNC) cmd_nick);
346 command_unbind("join", (SIGNAL_FUNC) cmd_join);
348 signal_remove("send command", (SIGNAL_FUNC) event_command);
349 signal_remove("send command", (SIGNAL_FUNC) event_command_last);
350 signal_remove("default command", (SIGNAL_FUNC) event_default_command);
351 signal_remove("error command", (SIGNAL_FUNC) event_cmderror);
352 signal_remove("list subcommands", (SIGNAL_FUNC) event_list_subcommands);