Merged Irssi SVN (upcoming irssi 0.8.11).
[silc.git] / apps / irssi / src / fe-common / core / chat-completion.c
index 803700de521465f49d22e08de10d20b48b77a15f..dea7360568443d35ead76320055bfa361428f680 100644 (file)
@@ -77,10 +77,21 @@ static void last_msg_dec_owns(GSList *list)
        }
 }
 
+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 */
@@ -93,9 +104,8 @@ static void last_msg_add(GSList **list, const char *nick, int own, int max)
                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;
@@ -107,14 +117,6 @@ static void last_msg_add(GSList **list, const char *nick, int own, int max)
        *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);
@@ -216,7 +218,6 @@ static void sig_message_own_private(SERVER_REC *server, const char *msg,
                                    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);
@@ -786,6 +787,36 @@ GList *completion_get_servers(const char *word)
        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)
@@ -879,7 +910,6 @@ static void sig_complete_alias(GList **list, WINDOW_REC *window,
        }
 }
 
-
 static void sig_complete_channel(GList **list, WINDOW_REC *window,
                                 const char *word, const char *line,
                                 int *want_space)
@@ -902,6 +932,27 @@ static void sig_complete_server(GList **list, WINDOW_REC *window,
        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)
@@ -1088,6 +1139,7 @@ void chat_completion_init(void)
        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);
@@ -1124,6 +1176,7 @@ void chat_completion_deinit(void)
        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);