diff --git a/src/core/chat-commands.c b/src/core/chat-commands.c index 7b76511f..07a9ae88 100644 --- a/src/core/chat-commands.c +++ b/src/core/chat-commands.c @@ -308,13 +308,13 @@ static void cmd_join(const char *data, SERVER_REC *server) cmd_params_free(free_arg); } -/* SYNTAX: MSG [-] */ +/* SYNTAX: MSG [-] [-channel | -nick] */ static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item) { GHashTable *optlist; char *target, *origtarget, *msg; void *free_arg; - int free_ret; + int free_ret, target_type; g_return_if_fail(data != NULL); @@ -342,10 +342,23 @@ static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item) target = item->name; } - if (target != NULL) - server->send_message(server, target, msg); + if (g_hash_table_lookup(optlist, "channel") != NULL) + target_type = SEND_TARGET_CHANNEL; + else if (g_hash_table_lookup(optlist, "nick") != NULL) + target_type = SEND_TARGET_NICK; + else { + /* Need to rely on server_ischannel(). If the protocol + doesn't really know if it's channel or nick based on the + name, it should just assume it's nick, because when typing + text to channels it's always sent with /MSG -channel. */ + target_type = server_ischannel(server, target) ? + SEND_TARGET_CHANNEL : SEND_TARGET_NICK; + } - signal_emit(target != NULL && server_ischannel(server, target) ? + if (target != NULL) + server->send_message(server, target, msg, target_type); + + signal_emit(target != NULL && target_type == SEND_TARGET_CHANNEL ? "message own_public" : "message own_private", 4, server, msg, target, origtarget); @@ -419,6 +432,7 @@ void chat_commands_init(void) command_set_options("connect", "4 6 !! +host noproxy -rawlog"); command_set_options("join", "invite"); + command_set_options("msg", "channel nick"); } void chat_commands_deinit(void) diff --git a/src/core/ignore.c b/src/core/ignore.c index c98646c1..23bdf83c 100644 --- a/src/core/ignore.c +++ b/src/core/ignore.c @@ -161,9 +161,8 @@ int ignore_check(SERVER_REC *server, const char *nick, const char *host, g_return_val_if_fail(server != NULL, 0); if (nick == NULL) nick = ""; - chanrec = (channel != NULL && server != NULL && - server_ischannel(server, channel)) ? - channel_find(server, channel) : NULL; + chanrec = server == NULL || channel == NULL ? NULL : + channel_find(server, channel); if (chanrec != NULL && nick != NULL && (nickrec = nicklist_find(chanrec, nick)) != NULL) { /* nick found - check only ignores in nickmatch cache */ diff --git a/src/core/server-rec.h b/src/core/server-rec.h index 9f5070f7..0003f698 100644 --- a/src/core/server-rec.h +++ b/src/core/server-rec.h @@ -60,7 +60,8 @@ int (*ischannel)(SERVER_REC *server, const char *data); of them aren't supported '\0' can be used. */ const char *(*get_nick_flags)(void); /* send public or private message to server */ -void (*send_message)(SERVER_REC *server, const char *target, const char *msg); +void (*send_message)(SERVER_REC *server, const char *target, + const char *msg, int target_type); /* -- Default implementations are used if NULL -- */ CHANNEL_REC *(*channel_find_func)(SERVER_REC *server, const char *name); diff --git a/src/core/servers.h b/src/core/servers.h index 05ebc55e..dddde263 100644 --- a/src/core/servers.h +++ b/src/core/servers.h @@ -31,6 +31,9 @@ struct _SERVER_REC { #include "server-rec.h" }; +#define SEND_TARGET_CHANNEL 0 +#define SEND_TARGET_NICK 1 + extern GSList *servers, *lookup_servers; void servers_init(void); diff --git a/src/fe-common/core/chat-completion.c b/src/fe-common/core/chat-completion.c index 6b988a1c..7be923fc 100644 --- a/src/fe-common/core/chat-completion.c +++ b/src/fe-common/core/chat-completion.c @@ -762,48 +762,62 @@ static char *expand_escapes(const char *line, SERVER_REC *server, return ret; } +static char *auto_complete(CHANNEL_REC *channel, const char *line) +{ + GList *comp; + const char *p; + char *nick, *ret; + + p = strstr(line, completion_char); + if (p == NULL) + return NULL; + + nick = g_strndup(line, (int) (p-line)); + + ret = NULL; + if (nicklist_find(channel, nick) == NULL) { + /* not an exact match, use the first possible completion */ + comp = completion_channel_nicks(channel, nick, NULL); + if (comp != NULL) { + ret = g_strconcat(comp->data, p, NULL); + g_list_foreach(comp, (GFunc) g_free, NULL); + g_list_free(comp); + } + } + + g_free(nick); + + return ret; +} + static void event_text(const char *data, SERVER_REC *server, WI_ITEM_REC *item) { - CHANNEL_REC *channel; - GList *comp; - char *line, *str, *ptr, comp_char; + char *line, *str; g_return_if_fail(data != NULL); if (item == NULL) return; line = settings_get_bool("expand_escapes") ? expand_escapes(data, server, item) : g_strdup(data); - comp_char = *completion_char; /* check for automatic nick completion */ - ptr = NULL; - comp = NULL; - channel = CHANNEL(item); - - if (completion_auto && channel != NULL && comp_char != '\0') { - ptr = strchr(line, comp_char); - if (ptr != NULL) { - *ptr++ = '\0'; - if (nicklist_find(channel, line) == NULL) { - comp = completion_channel_nicks(channel, - line, NULL); - } + if (completion_auto && IS_CHANNEL(item)) { + str = auto_complete(CHANNEL(item), line); + if (str != NULL) { + g_free(line); + line = str; } } - str = g_strdup_printf(ptr == NULL ? "%s %s" : "%s %s%c%s", item->name, - comp != NULL ? (char *) comp->data : line, - comp_char, ptr); + str = g_strdup_printf(IS_CHANNEL(item) ? "-channel %s %s" : + IS_QUERY(item) ? "-nick %s %s" : "%s %s", + item->name, line); + signal_emit("command msg", 3, str, server, item); g_free(str); g_free(line); - if (comp != NULL) { - g_list_foreach(comp, (GFunc) g_free, NULL); - g_list_free(comp); - } - signal_stop(); } @@ -840,6 +854,11 @@ static void read_settings(void) cmdchars = settings_get_str("cmdchars"); completion_auto = settings_get_bool("completion_auto"); completion_strict = settings_get_bool("completion_strict"); + + if (*completion_char == '\0') { + /* this would break.. */ + completion_auto = FALSE; + } } void chat_completion_init(void) diff --git a/src/fe-common/core/fe-queries.c b/src/fe-common/core/fe-queries.c index 9847c886..39191e5a 100644 --- a/src/fe-common/core/fe-queries.c +++ b/src/fe-common/core/fe-queries.c @@ -226,7 +226,8 @@ static void cmd_query(const char *data, SERVER_REC *server, WI_ITEM_REC *item) query = query_find(server, nick); if (query == NULL) - CHAT_PROTOCOL(server)->query_create(server->tag, nick, FALSE); + query = CHAT_PROTOCOL(server)-> + query_create(server->tag, nick, FALSE); else { /* query already exists */ WINDOW_REC *window = window_item_window(query); @@ -252,13 +253,9 @@ static void cmd_query(const char *data, SERVER_REC *server, WI_ITEM_REC *item) } if (*msg != '\0') { - /* FIXME: we'll need some function that does both - of these. and separate the , and . target handling - from own_private messagge.. */ - server->send_message(server, nick, msg); - - signal_emit("message own_private", 4, - server, msg, nick, nick); + msg = g_strdup_printf("-nick %s %s", nick, msg); + signal_emit("command msg", 3, msg, server, query); + g_free(msg); } cmd_params_free(free_arg); diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index 91935fb5..0faa299f 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -72,7 +72,7 @@ static int ischannel_func(SERVER_REC *server, const char *data) } static void send_message(SERVER_REC *server, const char *target, - const char *msg) + const char *msg, int target_type) { IRC_SERVER_REC *ircserver; char *str;