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"
31 #include "fe-windows.h"
32 #include "printtext.h"
34 #define PASTE_CHECK_SPEED 200 /* 0.2 sec */
36 static int ret_texts[] = {
39 TXT_OPTION_MISSING_ARG,
41 TXT_COMMAND_AMBIGUOUS,
43 TXT_NOT_ENOUGH_PARAMS,
51 /* keep the whole command line here temporarily. we need it in
52 "default command" event handler, but there we don't know if the start of
53 the line had one or two command chars, and which one.. */
54 static const char *current_cmdline;
55 static int hide_output;
57 static GTimeVal time_command_last, time_command_now;
58 static int last_command_cmd, command_cmd;
60 /* SYNTAX: ECHO [-current] [-window <name>] [-level <level>] <text> */
61 static void cmd_echo(const char *data, void *server, WI_ITEM_REC *item)
65 char *msg, *levelstr, *winname;
69 g_return_if_fail(data != NULL);
71 if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
72 PARAM_FLAG_GETREST, "echo", &optlist, &msg))
75 levelstr = g_hash_table_lookup(optlist, "level");
76 level = levelstr == NULL ? 0 :
77 level2bits(g_hash_table_lookup(optlist, "level"));
78 if (level == 0) level = MSGLEVEL_CRAP;
80 winname = g_hash_table_lookup(optlist, "window");
81 window = winname == NULL ? NULL :
82 is_numeric(winname, '\0') ?
83 window_find_refnum(atoi(winname)) :
84 window_find_item(NULL, winname);
85 if (window == NULL) window = active_win;
87 printtext_window(window, level, "%s", msg);
88 cmd_params_free(free_arg);
92 static void cmd_version(char *data)
94 g_return_if_fail(data != NULL);
97 printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
98 "Client: "PACKAGE" " IRSSI_VERSION);
102 /* SYNTAX: CAT <file> */
103 static void cmd_cat(const char *data)
105 LINEBUF_REC *buffer = NULL;
106 char *fname, *fposstr;
107 char tmpbuf[1024], *str;
109 int f, ret, recvlen, fpos;
111 if (!cmd_get_params(data, &free_arg, 2, &fname, &fposstr))
114 fname = convert_home(fname);
115 fpos = atoi(fposstr);
116 cmd_params_free(free_arg);
118 f = open(fname, O_RDONLY);
123 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
124 "%s", g_strerror(errno));
128 lseek(f, fpos, SEEK_SET);
130 recvlen = read(f, tmpbuf, sizeof(tmpbuf));
132 ret = line_split(tmpbuf, recvlen, &str, &buffer);
134 printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "%s", str);
136 line_split_free(buffer);
142 static void cmd_beep(void)
144 signal_emit("beep", 0);
147 static void sig_stop(void)
152 static void event_command(const char *data)
156 /* save current command line */
157 current_cmdline = data;
159 /* for detecting if we're pasting text */
160 time_command_last = time_command_now;
161 last_command_cmd = command_cmd;
163 g_get_current_time(&time_command_now);
164 command_cmd = strchr(settings_get_str("cmdchars"), *data) != NULL;
166 /* /^command hides the output of the command */
167 cmdchar = strchr(settings_get_str("cmdchars"), *data);
168 if (cmdchar != NULL && (data[1] == '^' ||
169 (data[1] == *cmdchar && data[2] == '^'))) {
171 signal_add_first("print starting", (SIGNAL_FUNC) sig_stop);
172 signal_add_first("print format", (SIGNAL_FUNC) sig_stop);
173 signal_add_first("print text stripped", (SIGNAL_FUNC) sig_stop);
174 signal_add_first("print text", (SIGNAL_FUNC) sig_stop);
178 static void event_command_last(const char *data)
182 signal_remove("print starting", (SIGNAL_FUNC) sig_stop);
183 signal_remove("print format", (SIGNAL_FUNC) sig_stop);
184 signal_remove("print text stripped", (SIGNAL_FUNC) sig_stop);
185 signal_remove("print text", (SIGNAL_FUNC) sig_stop);
189 static void event_default_command(const char *data, void *server,
192 const char *cmdchars, *ptr;
196 cmdchars = settings_get_str("cmdchars");
199 while (*ptr != '\0' && *ptr != ' ') {
200 if (strchr(cmdchars, *ptr)) {
201 /* command character inside command .. we probably
202 want to send this text to channel. for example
203 when pasting a path /usr/bin/xxx. */
204 signal_emit("send text", 3, current_cmdline, server, item);
210 /* maybe we're copy+pasting text? check how long it was since the
212 diff = get_timeval_diff(&time_command_now, &time_command_last);
213 if (item != NULL && !last_command_cmd && diff < PASTE_CHECK_SPEED) {
214 signal_emit("send text", 3, current_cmdline, active_win->active_server, active_win->active);
219 /* get the command part of the line, send "error command" signal */
220 cmd = g_strdup(data);
221 p = strchr(cmd, ' ');
222 if (p != NULL) *p = '\0';
224 signal_emit("error command", 2, GINT_TO_POINTER(CMDERR_UNKNOWN), cmd);
229 static void event_cmderror(void *errorp, const char *arg)
233 error = GPOINTER_TO_INT(errorp);
234 if (error == CMDERR_ERRNO) {
235 /* errno is special */
236 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "%s", g_strerror(errno));
239 printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, ret_texts[error + -CMDERR_OPTION_UNKNOWN], arg);
243 static void event_list_subcommands(const char *command)
249 str = g_string_new(NULL);
251 len = strlen(command);
252 for (tmp = commands; tmp != NULL; tmp = tmp->next) {
253 COMMAND_REC *rec = tmp->data;
255 if (g_strncasecmp(rec->cmd, command, len) == 0 &&
256 rec->cmd[len] == ' ' &&
257 strchr(rec->cmd+len+1, ' ') == NULL) {
258 g_string_sprintfa(str, "%s ", rec->cmd+len+1);
263 g_string_truncate(str, str->len-1);
264 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "%s", str->str);
267 g_string_free(str, TRUE);
270 void fe_core_commands_init(void)
275 memset(&time_command_now, 0, sizeof(GTimeVal));
277 command_bind("echo", NULL, (SIGNAL_FUNC) cmd_echo);
278 command_bind("version", NULL, (SIGNAL_FUNC) cmd_version);
279 command_bind("cat", NULL, (SIGNAL_FUNC) cmd_cat);
280 command_bind("beep", NULL, (SIGNAL_FUNC) cmd_beep);
282 signal_add("send command", (SIGNAL_FUNC) event_command);
283 signal_add_last("send command", (SIGNAL_FUNC) event_command_last);
284 signal_add("default command", (SIGNAL_FUNC) event_default_command);
285 signal_add("error command", (SIGNAL_FUNC) event_cmderror);
286 signal_add("list subcommands", (SIGNAL_FUNC) event_list_subcommands);
288 command_set_options("echo", "current +level +window");
291 void fe_core_commands_deinit(void)
293 command_unbind("echo", (SIGNAL_FUNC) cmd_echo);
294 command_unbind("version", (SIGNAL_FUNC) cmd_version);
295 command_unbind("cat", (SIGNAL_FUNC) cmd_cat);
296 command_unbind("beep", (SIGNAL_FUNC) cmd_beep);
298 signal_remove("send command", (SIGNAL_FUNC) event_command);
299 signal_remove("send command", (SIGNAL_FUNC) event_command_last);
300 signal_remove("default command", (SIGNAL_FUNC) event_default_command);
301 signal_remove("error command", (SIGNAL_FUNC) event_cmderror);
302 signal_remove("list subcommands", (SIGNAL_FUNC) event_list_subcommands);