#include "signals.h"
#include "commands.h"
#include "misc.h"
+#include "levels.h"
+#include "lib-config/iconfig.h"
#include "settings.h"
#include "chatnets.h"
#include "nicklist.h"
#include "completion.h"
+#include "chat-completion.h"
#include "window-items.h"
static int keep_privates_count, keep_publics_count;
}
}
+static void last_msg_destroy(GSList **list, LAST_MSG_REC *rec)
+{
+ *list = g_slist_remove(*list, rec);
+
+ g_free(rec->nick);
+ g_free(rec);
+}
+
static void last_msg_add(GSList **list, const char *nick, int own, int max)
{
LAST_MSG_REC *rec;
+ if (max <= 0)
+ return;
+
rec = last_msg_find(*list, nick);
if (rec != NULL) {
/* msg already exists, update it */
rec = g_new(LAST_MSG_REC, 1);
rec->nick = g_strdup(nick);
- if ((int)g_slist_length(*list) == max) {
- *list = g_slist_remove(*list,
- g_slist_last(*list)->data);
+ while ((int)g_slist_length(*list) >= max) {
+ last_msg_destroy(list, g_slist_last(*list)->data);
}
rec->own = own ? max : 0;
*list = g_slist_prepend(*list, rec);
}
-static void last_msg_destroy(GSList **list, LAST_MSG_REC *rec)
-{
- *list = g_slist_remove(*list, rec);
-
- g_free(rec->nick);
- g_free(rec);
-}
-
void completion_last_message_add(const char *nick)
{
g_return_if_fail(nick != NULL);
const char *target, const char *origtarget)
{
g_return_if_fail(server != NULL);
- g_return_if_fail(target != NULL);
if (target != NULL && query_find(server, target) == NULL)
SERVER_LAST_MSG_ADD(server, target);
}
/* Complete /MSG - if `find_server' is NULL, complete nicks from all servers */
-static GList *completion_msg(SERVER_REC *win_server,
+GList *completion_msg(SERVER_REC *win_server,
SERVER_REC *find_server,
const char *nick, const char *prefix)
{
for (tmp = servers; tmp != NULL; tmp = tmp->next) {
SERVER_REC *rec = tmp->data;
- if (rec == win_server)
+ if (servers->next == NULL && rec == win_server)
newprefix = g_strdup(prefix);
else {
newprefix = prefix == NULL ?
return list1;
}
+GList *completion_get_servertags(const char *word)
+{
+ GList *list;
+ GSList *tmp;
+ int len;
+
+ g_return_val_if_fail(word != NULL, NULL);
+
+ len = strlen(word);
+ list = NULL;
+
+ for (tmp = servers; tmp != NULL; tmp = tmp->next) {
+ SERVER_REC *rec = tmp->data;
+
+ if (g_strncasecmp(rec->tag, word, len) == 0) {
+ if (rec == active_win->active_server)
+ list = g_list_prepend(list, g_strdup(rec->tag));
+ else
+ list = g_list_append(list, g_strdup(rec->tag));
+ }
+
+ }
+
+ return list;
+}
+
GList *completion_get_channels(SERVER_REC *server, const char *word)
{
GList *list;
int len;
g_return_val_if_fail(word != NULL, NULL);
- g_return_val_if_fail(*word != '\0', NULL);
len = strlen(word);
list = NULL;
for (; tmp != NULL; tmp = tmp->next) {
CHANNEL_REC *rec = tmp->data;
- if (g_strncasecmp(rec->name, word, len) == 0)
+ if (g_strncasecmp(rec->visible_name, word, len) == 0)
+ list = g_list_append(list, g_strdup(rec->visible_name));
+ else if (g_strncasecmp(rec->name, word, len) == 0)
list = g_list_append(list, g_strdup(rec->name));
}
return list;
}
+GList *completion_get_aliases(const char *word)
+{
+ CONFIG_NODE *node;
+ GList *list;
+ GSList *tmp;
+ int len;
+
+ g_return_val_if_fail(word != NULL, NULL);
+
+ len = strlen(word);
+ list = NULL;
+
+ /* get the list of all aliases */
+ node = iconfig_node_traverse("aliases", FALSE);
+ tmp = node == NULL ? NULL : config_node_first(node->value);
+ for (; tmp != NULL; tmp = config_node_next(tmp)) {
+ node = tmp->data;
+
+ if (node->type != NODE_TYPE_KEY)
+ continue;
+
+ if (len != 0 && g_strncasecmp(node->key, word, len) != 0)
+ continue;
+
+ list = g_list_append(list, g_strdup(node->key));
+ }
+
+ return list;
+}
+
static void complete_window_nicks(GList **list, WINDOW_REC *window,
const char *word, const char *linestart)
{
/* nick completion .. we could also be completing a nick
after /MSG from nicks in channel */
complete_window_nicks(list, window, word, linestart);
+ } else if (window->level & MSGLEVEL_MSGS) {
+ /* msgs window, complete /MSG nicks */
+ *list = g_list_concat(completion_msg(server, NULL, word, NULL), *list);
}
if (*list != NULL) signal_stop();
return list;
}
+GList *completion_get_targets(const char *word)
+{
+ CONFIG_NODE *node;
+ GList *list;
+ GSList *tmp;
+ int len;
+
+ g_return_val_if_fail(word != NULL, NULL);
+
+ len = strlen(word);
+ list = NULL;
+
+ /* get the list of all conversion targets */
+ node = iconfig_node_traverse("conversions", FALSE);
+ tmp = node == NULL ? NULL : config_node_first(node->value);
+ for (; tmp != NULL; tmp = config_node_next(tmp)) {
+ node = tmp->data;
+
+ if (node->type != NODE_TYPE_KEY)
+ continue;
+
+ if (len != 0 && g_strncasecmp(node->key, word, len) != 0)
+ continue;
+
+ list = g_list_append(list, g_strdup(node->key));
+ }
+
+ return list;
+}
+
static void sig_complete_connect(GList **list, WINDOW_REC *window,
const char *word, const char *line,
int *want_space)
if (*list != NULL) signal_stop();
}
+static void sig_complete_tag(GList **list, WINDOW_REC *window,
+ const char *word, const char *line,
+ int *want_space)
+{
+ g_return_if_fail(list != NULL);
+ g_return_if_fail(word != NULL);
+
+ *list = completion_get_servertags(word);
+ if (*list != NULL) signal_stop();
+}
+
static void sig_complete_topic(GList **list, WINDOW_REC *window,
const char *word, const char *line,
int *want_space)
}
}
+static void sig_complete_away(GList **list, WINDOW_REC *window,
+ const char *word, const char *line,
+ int *want_space)
+{
+ const char *reason;
+
+ g_return_if_fail(list != NULL);
+ g_return_if_fail(word != NULL);
+
+ *want_space = FALSE;
+
+ if (*word == '\0' && window->active_server != NULL) {
+ reason = SERVER(window->active_server)->away_reason;
+ if (reason != NULL) {
+ *list = g_list_append(NULL, g_strdup(reason));
+ signal_stop();
+ }
+ }
+}
+
+static void sig_complete_unalias(GList **list, WINDOW_REC *window,
+ const char *word, const char *line,
+ int *want_space)
+{
+ g_return_if_fail(list != NULL);
+ g_return_if_fail(word != NULL);
+
+ *list = completion_get_aliases(word);
+ if (*list != NULL) signal_stop();
+}
+
+static void sig_complete_alias(GList **list, WINDOW_REC *window,
+ const char *word, const char *line,
+ int *want_space)
+{
+ const char *definition;
+
+ g_return_if_fail(list != NULL);
+ g_return_if_fail(word != NULL);
+ g_return_if_fail(line != NULL);
+
+ if (*line != '\0') {
+ if ((definition = alias_find(line)) != NULL) {
+ *list = g_list_append(NULL, g_strdup(definition));
+ signal_stop();
+ }
+ } else {
+ *list = completion_get_aliases(word);
+ if (*list != NULL) signal_stop();
+ }
+}
+
+static void sig_complete_channel(GList **list, WINDOW_REC *window,
+ const char *word, const char *line,
+ int *want_space)
+{
+ g_return_if_fail(list != NULL);
+ g_return_if_fail(word != NULL);
+
+ *list = completion_get_channels(NULL, word);
+ if (*list != NULL) signal_stop();
+}
+
+static void sig_complete_server(GList **list, WINDOW_REC *window,
+ const char *word, const char *line,
+ int *want_space)
+{
+ g_return_if_fail(list != NULL);
+ g_return_if_fail(word != NULL);
+
+ *list = completion_get_servers(word);
+ if (*list != NULL) signal_stop();
+}
+
+static void sig_complete_target(GList **list, WINDOW_REC *window,
+ const char *word, const char *line,
+ int *want_space)
+{
+ const char *definition;
+
+ g_return_if_fail(list != NULL);
+ g_return_if_fail(word != NULL);
+ g_return_if_fail(line != NULL);
+
+ if (*line != '\0') {
+ if ((definition = iconfig_get_str("conversions", line ,NULL)) != NULL) {
+ *list = g_list_append(NULL, g_strdup(definition));
+ signal_stop();
+ }
+ } else {
+ *list = completion_get_targets(word);
+ if (*list != NULL) signal_stop();
+ }
+}
+
/* expand \n, \t and \\ */
static char *expand_escapes(const char *line, SERVER_REC *server,
WI_ITEM_REC *item)
static void event_text(const char *data, SERVER_REC *server, WI_ITEM_REC *item)
{
- char *line, *str;
+ char *line, *str, *target;
g_return_if_fail(data != NULL);
- if (item == NULL) return;
+
+ if (item == NULL)
+ return;
+
+ if (*data == '\0') {
+ /* empty line, forget it. */
+ signal_stop();
+ return;
+ }
line = settings_get_bool("expand_escapes") ?
expand_escapes(data, server, item) : g_strdup(data);
}
}
- str = g_strdup_printf(IS_CHANNEL(item) ? "-channel %s %s" :
- IS_QUERY(item) ? "-nick %s %s" : "%s %s",
- item->name, line);
+ /* the nick is quoted in case it contains '-' character. also
+ spaces should work too now :) The nick is also escaped in case
+ it contains '\' characters */
+ target = escape_string(window_item_get_target(item));
+ str = g_strdup_printf(IS_CHANNEL(item) ? "-channel \"%s\" %s" :
+ IS_QUERY(item) ? "-nick \"%s\" %s" : "%s %s",
+ target, line);
+ g_free(target);
signal_emit("command msg", 3, str, server, item);
settings_add_bool("completion", "completion_auto", FALSE);
settings_add_int("completion", "completion_keep_publics", 50);
settings_add_int("completion", "completion_keep_privates", 10);
- settings_add_bool("completion", "expand_escapes", FALSE);
settings_add_bool("completion", "completion_nicks_lowercase", FALSE);
settings_add_bool("completion", "completion_strict", FALSE);
+ settings_add_bool("lookandfeel", "expand_escapes", FALSE);
+
read_settings();
signal_add("complete word", (SIGNAL_FUNC) sig_complete_word);
signal_add("complete command msg", (SIGNAL_FUNC) sig_complete_msg);
signal_add("complete command query", (SIGNAL_FUNC) sig_complete_msg);
+ signal_add("complete command action", (SIGNAL_FUNC) sig_complete_msg);
signal_add("complete erase command msg", (SIGNAL_FUNC) sig_erase_complete_msg);
signal_add("complete erase command query", (SIGNAL_FUNC) sig_erase_complete_msg);
+ signal_add("complete erase command action", (SIGNAL_FUNC) sig_erase_complete_msg);
signal_add("complete command connect", (SIGNAL_FUNC) sig_complete_connect);
signal_add("complete command server", (SIGNAL_FUNC) sig_complete_connect);
+ signal_add("complete command disconnect", (SIGNAL_FUNC) sig_complete_tag);
+ signal_add("complete command reconnect", (SIGNAL_FUNC) sig_complete_tag);
signal_add("complete command topic", (SIGNAL_FUNC) sig_complete_topic);
+ signal_add("complete command away", (SIGNAL_FUNC) sig_complete_away);
+ signal_add("complete command unalias", (SIGNAL_FUNC) sig_complete_unalias);
+ signal_add("complete command alias", (SIGNAL_FUNC) sig_complete_alias);
+ signal_add("complete command window item move", (SIGNAL_FUNC) sig_complete_channel);
+ signal_add("complete command server add", (SIGNAL_FUNC) sig_complete_server);
+ signal_add("complete command server remove", (SIGNAL_FUNC) sig_complete_server);
+ signal_add("complete command recode remove", (SIGNAL_FUNC) sig_complete_target);
signal_add("message public", (SIGNAL_FUNC) sig_message_public);
signal_add("message join", (SIGNAL_FUNC) sig_message_join);
signal_add("message private", (SIGNAL_FUNC) sig_message_private);
signal_remove("complete word", (SIGNAL_FUNC) sig_complete_word);
signal_remove("complete command msg", (SIGNAL_FUNC) sig_complete_msg);
signal_remove("complete command query", (SIGNAL_FUNC) sig_complete_msg);
+ signal_remove("complete command action", (SIGNAL_FUNC) sig_complete_msg);
signal_remove("complete erase command msg", (SIGNAL_FUNC) sig_erase_complete_msg);
signal_remove("complete erase command query", (SIGNAL_FUNC) sig_erase_complete_msg);
+ signal_remove("complete erase command action", (SIGNAL_FUNC) sig_erase_complete_msg);
signal_remove("complete command connect", (SIGNAL_FUNC) sig_complete_connect);
signal_remove("complete command server", (SIGNAL_FUNC) sig_complete_connect);
+ signal_remove("complete command disconnect", (SIGNAL_FUNC) sig_complete_tag);
+ signal_remove("complete command reconnect", (SIGNAL_FUNC) sig_complete_tag);
signal_remove("complete command topic", (SIGNAL_FUNC) sig_complete_topic);
+ signal_remove("complete command away", (SIGNAL_FUNC) sig_complete_away);
+ signal_remove("complete command unalias", (SIGNAL_FUNC) sig_complete_unalias);
+ signal_remove("complete command alias", (SIGNAL_FUNC) sig_complete_alias);
+ signal_remove("complete command window item move", (SIGNAL_FUNC) sig_complete_channel);
+ signal_remove("complete command server add", (SIGNAL_FUNC) sig_complete_server);
+ signal_remove("complete command server remove", (SIGNAL_FUNC) sig_complete_server);
+ signal_remove("complete command recode remove", (SIGNAL_FUNC) sig_complete_target);
signal_remove("message public", (SIGNAL_FUNC) sig_message_public);
signal_remove("message join", (SIGNAL_FUNC) sig_message_join);
signal_remove("message private", (SIGNAL_FUNC) sig_message_private);