Added SILC Thread Queue API
[runtime.git] / apps / irssi / src / core / channels.c
index f3d3a7a45ef0bd313a09268014e2b0a0a3f2c2e4..79d8f0e7c826fc81da9960fc993ec15beecfb39e 100644 (file)
@@ -35,23 +35,37 @@ static char *get_join_data(CHANNEL_REC *channel)
        return g_strdup(channel->name);
 }
 
-void channel_init(CHANNEL_REC *channel, int automatic)
+static const char *channel_get_target(WI_ITEM_REC *item)
+{
+       return ((CHANNEL_REC *) item)->name;
+}
+
+void channel_init(CHANNEL_REC *channel, SERVER_REC *server, const char *name,
+                 const char *visible_name, int automatic)
 {
        g_return_if_fail(channel != NULL);
-       g_return_if_fail(channel->name != NULL);
+       g_return_if_fail(name != NULL);
+       g_return_if_fail(server != NULL);
 
-       channels = g_slist_append(channels, channel);
-       if (channel->server != NULL) {
-               channel->server->channels =
-                       g_slist_append(channel->server->channels, channel);
-       }
+       if (visible_name == NULL)
+               visible_name = name;
 
         MODULE_DATA_INIT(channel);
        channel->type = module_get_uniq_id_str("WINDOW ITEM TYPE", "CHANNEL");
-        channel->mode = g_strdup("");
-       channel->createtime = time(NULL);
+        channel->destroy = (void (*) (WI_ITEM_REC *)) channel_destroy;
+       channel->get_target = channel_get_target;
         channel->get_join_data = get_join_data;
 
+       channel->chat_type = server->chat_type;
+       channel->server = server;
+       channel->name = g_strdup(name);
+       channel->visible_name = g_strdup(visible_name);
+       channel->mode = g_strdup("");
+       channel->createtime = time(NULL);
+
+       channels = g_slist_append(channels, channel);
+       server->channels = g_slist_append(server->channels, channel);
+
        signal_emit("channel created", 2, channel, GINT_TO_POINTER(automatic));
 }
 
@@ -63,8 +77,9 @@ void channel_destroy(CHANNEL_REC *channel)
        channel->destroying = TRUE;
 
        channels = g_slist_remove(channels, channel);
-       if (channel->server != NULL)
-               channel->server->channels = g_slist_remove(channel->server->channels, channel);
+       channel->server->channels =
+               g_slist_remove(channel->server->channels, channel);
+
        signal_emit("channel destroyed", 1, channel);
 
         MODULE_DATA_DEINIT(channel);
@@ -74,6 +89,9 @@ void channel_destroy(CHANNEL_REC *channel)
        g_free_not_null(channel->key);
        g_free(channel->mode);
        g_free(channel->name);
+       g_free(channel->visible_name);
+
+        channel->type = 0;
        g_free(channel);
 }
 
@@ -113,17 +131,68 @@ CHANNEL_REC *channel_find(SERVER_REC *server, const char *name)
                                   (void *) name);
 }
 
+void channel_change_name(CHANNEL_REC *channel, const char *name)
+{
+       g_return_if_fail(IS_CHANNEL(channel));
+
+       g_free(channel->name);
+       channel->name = g_strdup(name);
+
+       signal_emit("channel name changed", 1, channel);
+}
+
+void channel_change_visible_name(CHANNEL_REC *channel, const char *name)
+{
+       g_return_if_fail(IS_CHANNEL(channel));
+
+       g_free(channel->visible_name);
+       channel->visible_name = g_strdup(name);
+
+       signal_emit("window item name changed", 1, channel);
+}
+
+static CHANNEL_REC *channel_find_servers(GSList *servers, const char *name)
+{
+       return gslist_foreach_find(servers,
+                                  (FOREACH_FIND_FUNC) channel_find_server,
+                                  (void *) name);
+}
+
+static GSList *servers_find_chatnet_except(SERVER_REC *server)
+{
+       GSList *tmp, *list;
+
+        list = NULL;
+       for (tmp = servers; tmp != NULL; tmp = tmp->next) {
+               SERVER_REC *rec = tmp->data;
+
+               if (server != rec && rec->connrec->chatnet != NULL &&
+                   strcmp(server->connrec->chatnet,
+                          rec->connrec->chatnet) == 0) {
+                       /* chatnets match */
+                       list = g_slist_append(list, rec);
+               }
+       }
+
+        return list;
+}
+
 /* connected to server, autojoin to channels. */
 static void event_connected(SERVER_REC *server)
 {
        GString *chans;
-       GSList *tmp;
+       GSList *tmp, *chatnet_servers;
 
        g_return_if_fail(SERVER(server));
 
-       if (server->connrec->reconnection)
+       if (server->connrec->reconnection ||
+           server->connrec->no_autojoin_channels)
                return;
 
+       /* get list of servers in same chat network */
+       chatnet_servers = server->connrec->chatnet == NULL ? NULL:
+               servers_find_chatnet_except(server);
+
        /* join to the channels marked with autojoin in setup */
        chans = g_string_new(NULL);
        for (tmp = setupchannels; tmp != NULL; tmp = tmp->next) {
@@ -134,8 +203,12 @@ static void event_connected(SERVER_REC *server)
                                           server->connrec->chatnet))
                        continue;
 
-               g_string_sprintfa(chans, "%s,", rec->name);
+               /* check that we haven't already joined this channel in
+                  same chat network connection.. */
+                if (channel_find_servers(chatnet_servers, rec->name) == NULL)
+                       g_string_sprintfa(chans, "%s,", rec->name);
        }
+        g_slist_free(chatnet_servers);
 
        if (chans->len > 0) {
                g_string_truncate(chans, chans->len-1);
@@ -147,7 +220,7 @@ static void event_connected(SERVER_REC *server)
 
 static int match_nick_flags(SERVER_REC *server, NICK_REC *nick, char flag)
 {
-       const char *flags = server->get_nick_flags();
+       const char *flags = server->get_nick_flags(server);
 
        return strchr(flags, flag) == NULL ||
                (flag == flags[0] && nick->op) ||
@@ -165,6 +238,9 @@ void channel_send_autocommands(CHANNEL_REC *channel)
 
        g_return_if_fail(IS_CHANNEL(channel));
 
+       if (channel->session_rejoin)
+                return;
+
        rec = channel_setup_find(channel->name, channel->server->connrec->chatnet);
        if (rec == NULL || rec->autosendcmd == NULL || !*rec->autosendcmd)
                return;
@@ -180,8 +256,11 @@ void channel_send_autocommands(CHANNEL_REC *channel)
        for (bot = bots; *bot != NULL; bot++) {
                const char *botnick = *bot;
 
+               if (*botnick == '\0')
+                        continue;
+
                nick = nicklist_find_mask(channel,
-                                         channel->server->isnickflag(*botnick) ?
+                                         channel->server->isnickflag(channel->server, *botnick) ?
                                          botnick+1 : botnick);
                if (nick != NULL &&
                    match_nick_flags(channel->server, nick, *botnick)) {
@@ -205,5 +284,4 @@ void channels_deinit(void)
        channels_setup_deinit();
 
        signal_remove("event connected", (SIGNAL_FUNC) event_connected);
-       module_uniq_destroy("CHANNEL");
 }