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
23 #include "module-formats.h"
28 #include "line-split.h"
30 #include "irssi-version.h"
33 #include "fe-windows.h"
34 #include "printtext.h"
36 #define PASTE_CHECK_SPEED 200 /* 0.2 sec */
38 static int ret_texts[] = {
41 TXT_OPTION_MISSING_ARG,
43 TXT_COMMAND_AMBIGUOUS,
45 TXT_NOT_ENOUGH_PARAMS,
58 int command_hide_output;
60 /* keep the whole command line here temporarily. we need it in
61 "default command" event handler, but there we don't know if the start of
62 the line had one or two command chars, and which one.. */
63 static const char *current_cmdline;
65 static GTimeVal time_command_last, time_command_now;
66 static int last_command_cmd, command_cmd;
68 /* SYNTAX: ECHO [-current] [-window <name>] [-level <level>] <text> */
69 static void cmd_echo(const char *data, void *server, WI_ITEM_REC *item)
73 char *msg, *levelstr, *winname;
77 g_return_if_fail(data != NULL);
79 if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
80 PARAM_FLAG_GETREST, "echo", &optlist, &msg))
83 levelstr = g_hash_table_lookup(optlist, "level");
84 level = levelstr == NULL ? 0 :
85 level2bits(g_hash_table_lookup(optlist, "level"));
86 if (level == 0) level = MSGLEVEL_CRAP;
88 winname = g_hash_table_lookup(optlist, "window");
89 window = winname == NULL ? NULL :
90 is_numeric(winname, '\0') ?
91 window_find_refnum(atoi(winname)) :
92 window_find_item(NULL, winname);
93 if (window == NULL) window = active_win;
95 printtext_window(window, level, "%s", msg);
96 cmd_params_free(free_arg);
100 static void cmd_version(char *data)
104 g_return_if_fail(data != NULL);
107 g_snprintf(time, sizeof(time), "%04d", IRSSI_VERSION_TIME);
108 printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
109 "Client: "PACKAGE" " IRSSI_VERSION" (%d %s)",
110 IRSSI_VERSION_DATE, time);
114 /* SYNTAX: CAT <file> */
115 static void cmd_cat(const char *data)
117 LINEBUF_REC *buffer = NULL;
118 char *fname, *fposstr;
119 char tmpbuf[1024], *str;
121 int f, ret, recvlen, fpos;
123 if (!cmd_get_params(data, &free_arg, 2, &fname, &fposstr))
126 fname = convert_home(fname);
127 fpos = atoi(fposstr);
128 cmd_params_free(free_arg);
130 f = open(fname, O_RDONLY);
135 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
136 "%s", g_strerror(errno));
140 lseek(f, fpos, SEEK_SET);
142 recvlen = read(f, tmpbuf, sizeof(tmpbuf));
144 ret = line_split(tmpbuf, recvlen, &str, &buffer);
146 printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP |
147 MSGLEVEL_NEVER, "%s", str);
150 line_split_free(buffer);
156 static void cmd_beep(void)
158 signal_emit("beep", 0);
161 static void cmd_nick(const char *data, SERVER_REC *server)
163 g_return_if_fail(data != NULL);
165 if (*data != '\0') return;
166 if (server == NULL || !server->connected)
167 cmd_return_error(CMDERR_NOT_CONNECTED);
169 /* display current nick */
170 printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_YOUR_NICK, server->nick);
174 static void cmd_join(const char *data, SERVER_REC *server)
180 g_return_if_fail(data != NULL);
182 if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
183 PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST,
184 "join", &optlist, &channels))
187 server = cmd_options_get_server("join", optlist, server);
188 if (g_hash_table_lookup(optlist, "invite") &&
189 server != NULL && server->last_invite == NULL) {
190 /* ..all this trouble just to print this error message */
191 printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_NOT_INVITED);
195 cmd_params_free(free_arg);
199 static void cmd_uptime(char *data)
203 g_return_if_fail(data != NULL);
206 uptime = time(NULL) - client_start_time;
207 printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
208 "Uptime: %ldd %ldh %ldm %lds",
209 uptime/3600/24, uptime/3600%24,
210 uptime/60%60, uptime%60);
214 static void sig_stop(void)
219 static void event_command(const char *data)
223 /* save current command line */
224 current_cmdline = data;
226 /* for detecting if we're pasting text */
227 time_command_last = time_command_now;
228 last_command_cmd = command_cmd;
230 g_get_current_time(&time_command_now);
231 command_cmd = *data != '\0' &&
232 strchr(settings_get_str("cmdchars"), *data) != NULL;
234 /* /^command hides the output of the command */
235 cmdchar = *data == '\0' ? NULL :
236 strchr(settings_get_str("cmdchars"), *data);
237 if (cmdchar != NULL && (data[1] == '^' ||
238 (data[1] == *cmdchar && data[2] == '^'))
239 && !command_hide_output++) {
240 signal_add_first("print starting", (SIGNAL_FUNC) sig_stop);
241 signal_add_first("print format", (SIGNAL_FUNC) sig_stop);
242 signal_add_first("print text", (SIGNAL_FUNC) sig_stop);
246 static void event_command_last(const char *data)
248 if (command_hide_output && !--command_hide_output) {
249 signal_remove("print starting", (SIGNAL_FUNC) sig_stop);
250 signal_remove("print format", (SIGNAL_FUNC) sig_stop);
251 signal_remove("print text", (SIGNAL_FUNC) sig_stop);
255 static void event_default_command(const char *data, void *server,
258 const char *cmdchars, *ptr;
262 cmdchars = settings_get_str("cmdchars");
265 while (*ptr != '\0' && *ptr != ' ') {
266 if (strchr(cmdchars, *ptr)) {
267 /* command character inside command .. we probably
268 want to send this text to channel. for example
269 when pasting a path /usr/bin/xxx. */
270 signal_emit("send text", 3, current_cmdline, server, item);
276 /* maybe we're copy+pasting text? check how long it was since the
278 diff = get_timeval_diff(&time_command_now, &time_command_last);
279 if (item != NULL && !last_command_cmd && diff < PASTE_CHECK_SPEED) {
280 signal_emit("send text", 3, current_cmdline, active_win->active_server, active_win->active);
285 /* get the command part of the line, send "error command" signal */
286 cmd = g_strdup(data);
287 p = strchr(cmd, ' ');
288 if (p != NULL) *p = '\0';
290 signal_emit("error command", 2, GINT_TO_POINTER(CMDERR_UNKNOWN), cmd);
295 static void event_cmderror(void *errorp, const char *arg)
299 error = GPOINTER_TO_INT(errorp);
300 if (error == CMDERR_ERRNO) {
301 /* errno is special */
302 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "%s", g_strerror(errno));
305 printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, ret_texts[error + -CMDERR_OPTION_UNKNOWN], arg);
309 static void event_list_subcommands(const char *command)
315 str = g_string_new(NULL);
317 len = strlen(command);
318 for (tmp = commands; tmp != NULL; tmp = tmp->next) {
319 COMMAND_REC *rec = tmp->data;
321 if (g_strncasecmp(rec->cmd, command, len) == 0 &&
322 rec->cmd[len] == ' ' &&
323 strchr(rec->cmd+len+1, ' ') == NULL) {
324 g_string_sprintfa(str, "%s ", rec->cmd+len+1);
329 g_string_truncate(str, str->len-1);
330 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "%s", str->str);
333 g_string_free(str, TRUE);
336 void fe_core_commands_init(void)
338 command_hide_output = 0;
341 memset(&time_command_now, 0, sizeof(GTimeVal));
343 command_bind("echo", NULL, (SIGNAL_FUNC) cmd_echo);
344 command_bind("version", NULL, (SIGNAL_FUNC) cmd_version);
345 command_bind("cat", NULL, (SIGNAL_FUNC) cmd_cat);
346 command_bind("beep", NULL, (SIGNAL_FUNC) cmd_beep);
347 command_bind("uptime", NULL, (SIGNAL_FUNC) cmd_uptime);
348 command_bind_first("nick", NULL, (SIGNAL_FUNC) cmd_nick);
349 command_bind_first("join", NULL, (SIGNAL_FUNC) cmd_join);
351 signal_add("send command", (SIGNAL_FUNC) event_command);
352 signal_add_last("send command", (SIGNAL_FUNC) event_command_last);
353 signal_add("default command", (SIGNAL_FUNC) event_default_command);
354 signal_add("error command", (SIGNAL_FUNC) event_cmderror);
355 signal_add("list subcommands", (SIGNAL_FUNC) event_list_subcommands);
357 command_set_options("echo", "current +level +window");
360 void fe_core_commands_deinit(void)
362 command_unbind("echo", (SIGNAL_FUNC) cmd_echo);
363 command_unbind("version", (SIGNAL_FUNC) cmd_version);
364 command_unbind("cat", (SIGNAL_FUNC) cmd_cat);
365 command_unbind("beep", (SIGNAL_FUNC) cmd_beep);
366 command_unbind("uptime", (SIGNAL_FUNC) cmd_uptime);
367 command_unbind("nick", (SIGNAL_FUNC) cmd_nick);
368 command_unbind("join", (SIGNAL_FUNC) cmd_join);
370 signal_remove("send command", (SIGNAL_FUNC) event_command);
371 signal_remove("send command", (SIGNAL_FUNC) event_command_last);
372 signal_remove("default command", (SIGNAL_FUNC) event_default_command);
373 signal_remove("error command", (SIGNAL_FUNC) event_cmderror);
374 signal_remove("list subcommands", (SIGNAL_FUNC) event_list_subcommands);