libpurple/conversations.c

branch
soc.2013.gobjectification
changeset 34648
a6587d8cf907
parent 34600
3180ebbd06be
child 34649
4a0ec0fff2e1
--- a/libpurple/conversations.c	Wed Jun 26 14:45:08 2013 +0530
+++ b/libpurple/conversations.c	Wed Jun 26 14:45:36 2013 +0530
@@ -26,6 +26,112 @@
 static GList *chats = NULL;
 static PurpleConversationUiOps *default_ops = NULL;
 
+/**
+ * A hash table used for efficient lookups of conversations by name.
+ * struct _purple_hconv => PurpleConversation*
+ */
+static GHashTable *conversation_cache = NULL;
+
+struct _purple_hconv {
+	gboolean im;
+	char *name;
+	const PurpleAccount *account;
+};
+
+static guint
+_purple_conversations_hconv_hash(struct _purple_hconv *hc)
+{
+	return g_str_hash(hc->name) ^ hc->im ^ g_direct_hash(hc->account);
+}
+
+static guint
+_purple_conversations_hconv_equal(struct _purple_hconv *hc1, struct _purple_hconv *hc2)
+{
+	return (hc1->im == hc2->im &&
+	        hc1->account == hc2->account &&
+	        g_str_equal(hc1->name, hc2->name));
+}
+
+static void
+_purple_conversations_hconv_free_key(struct _purple_hconv *hc)
+{
+	g_free(hc->name);
+	g_free(hc);
+}
+
+static guint
+_purple_conversation_user_hash(gconstpointer data)
+{
+	const gchar *name = data;
+	gchar *collated;
+	guint hash;
+
+	collated = g_utf8_collate_key(name, -1);
+	hash     = g_str_hash(collated);
+	g_free(collated);
+	return hash;
+}
+
+static gboolean
+_purple_conversation_user_equal(gconstpointer a, gconstpointer b)
+{
+	return !g_utf8_collate(a, b);
+}
+
+void
+purple_conversations_add(PurpleConversation *conv)
+{
+	PurpleAccount *account;
+	struct _purple_hconv *hc;
+
+	g_return_if_fail(conv != NULL);
+
+	if (g_list_find(conversations, conv) != NULL)
+		return;
+
+	conversations = g_list_prepend(conversations, conv);
+
+	if (PURPLE_IS_IM_CONVERSATION(conv))
+		g_list_prepend(ims, conv);
+	else
+		g_list_prepend(chats, conv);
+
+	account = purple_conversation_get_account(conv);
+
+	hc = g_new(struct _purple_hconv, 1);
+	hc->name = g_strdup(purple_normalize(account,
+				purple_conversation_get_name(conv)));
+	hc->account = account;
+	hc->im = PURPLE_IS_IM_CONVERSATION(conv);
+
+	g_hash_table_insert(conversation_cache, hc, conv);
+}
+
+void
+purple_conversations_remove(PurpleConversation *conv)
+{
+	PurpleAccount *account;
+	struct _purple_hconv hc;
+
+	g_return_if_fail(conv != NULL);
+
+	conversations = g_list_remove(conversations, conv);
+
+	if (PURPLE_IS_IM_CONVERSATION(conv))
+		g_list_remove(ims, conv);
+	else
+		g_list_remove(chats, conv);
+
+	account = purple_conversation_get_account(conv);
+
+	hc.name = (gchar *)purple_normalize(account,
+				purple_conversation_get_name(conv));
+	hc.account = account;
+	hc.im = PURPLE_IS_IM_CONVERSATION(conv);
+
+	g_hash_table_remove(conversation_cache, &hc);
+}
+
 GList *
 purple_conversations_get(void)
 {
@@ -45,9 +151,8 @@
 }
 
 PurpleConversation *
-purple_conversations_find_with_account(PurpleConversationType type,
-									const char *name,
-									const PurpleAccount *account)
+purple_conversations_find_with_account(const char *name,
+		const PurpleAccount *account)
 {
 	PurpleConversation *c = NULL;
 	struct _purple_hconv hc;
@@ -58,26 +163,52 @@
 	hc.account = account;
 	hc.type = type;
 
-	switch (type) {
-		case PURPLE_CONVERSATION_TYPE_IM:
-		case PURPLE_CONVERSATION_TYPE_CHAT:
-			c = g_hash_table_lookup(conversation_cache, &hc);
-			break;
-		case PURPLE_CONVERSATION_TYPE_ANY:
-			hc.type = PURPLE_CONVERSATION_TYPE_IM;
-			c = g_hash_table_lookup(conversation_cache, &hc);
-			if (!c) {
-				hc.type = PURPLE_CONVERSATION_TYPE_CHAT;
-				c = g_hash_table_lookup(conversation_cache, &hc);
-			}
-			break;
-		default:
-			g_return_val_if_reached(NULL);
+	hc.im = TRUE;
+	c = g_hash_table_lookup(conversation_cache, &hc);
+	if (!c) {
+		hc.im = FALSE;
+		c = g_hash_table_lookup(conversation_cache, &hc);
 	}
 
 	return c;
 }
 
+PurpleIMConversation *
+purple_conversations_find_im_with_account(const char *name,
+		const PurpleAccount *account)
+{
+	PurpleIMConversation *im = NULL;
+	struct _purple_hconv hc;
+
+	g_return_val_if_fail(name != NULL, NULL);
+
+	hc.name = (gchar *)purple_normalize(account, name);
+	hc.account = account;
+	hc.im = TRUE;
+
+	im = g_hash_table_lookup(conversation_cache, &hc);
+
+	return im;
+}
+
+PurpleChatConversation *
+purple_conversations_find_chat_with_account(const char *name,
+		const PurpleAccount *account)
+{
+	PurpleChatConversation *c = NULL;
+	struct _purple_hconv hc;
+
+	g_return_val_if_fail(name != NULL, NULL);
+
+	hc.name = (gchar *)purple_normalize(account, name);
+	hc.account = account;
+	hc.im = FALSE;
+
+	c = g_hash_table_lookup(conversation_cache, &hc);
+
+	return c;
+}
+
 PurpleChatConversation *
 purple_conversations_find_chat(const PurpleConnection *gc, int id)
 {
@@ -101,6 +232,12 @@
 	default_ops = ops;
 }
 
+PurpleConversationUiOps *
+purple_conversations_get_ui_ops(void)
+{
+	return default_ops;
+}
+
 void *
 purple_conversations_get_handle(void)
 {

mercurial