+
+/* Removes a client entry from all channel it has joined. This really is
+ a performance killer (client_entry should have pointers to channel
+ entry list). */
+
+void silc_client_remove_from_channels(SilcClient client,
+ SilcClientConnection conn,
+ SilcClientEntry client_entry)
+{
+ SilcIDCacheEntry id_cache;
+ SilcIDCacheList list;
+ SilcChannelEntry channel;
+ int i;
+
+ if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
+ SILC_ID_CHANNEL, &list))
+ return;
+
+ silc_idcache_list_first(list, &id_cache);
+ channel = (SilcChannelEntry)id_cache->context;
+
+ while (channel) {
+
+ /* Remove client from channel */
+ for (i = 0; i < channel->clients_count; i++) {
+ if (channel->clients[i].client == client_entry) {
+ channel->clients[i].client = NULL;
+ channel->clients_count--;
+ break;
+ }
+ }
+
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+
+ channel = (SilcChannelEntry)id_cache->context;
+ }
+
+ silc_idcache_list_free(list);
+}
+
+/* Replaces `old' client entries from all channels to `new' client entry.
+ This can be called for example when nickname changes and old ID entry
+ is replaced from ID cache with the new one. If the old ID entry is only
+ updated, then this fucntion needs not to be called. */
+
+void silc_client_replace_from_channels(SilcClient client,
+ SilcClientConnection conn,
+ SilcClientEntry old,
+ SilcClientEntry new)
+{
+ SilcIDCacheEntry id_cache;
+ SilcIDCacheList list;
+ SilcChannelEntry channel;
+ int i;
+
+ if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
+ SILC_ID_CHANNEL, &list))
+ return;
+
+ silc_idcache_list_first(list, &id_cache);
+ channel = (SilcChannelEntry)id_cache->context;
+
+ while (channel) {
+
+ /* Remove client from channel */
+ for (i = 0; i < channel->clients_count; i++) {
+ if (channel->clients[i].client == old) {
+ channel->clients[i].client = new;
+ break;
+ }
+ }
+
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+
+ channel = (SilcChannelEntry)id_cache->context;
+ }
+
+ silc_idcache_list_free(list);
+}