diff src/conversation.c @ 9554:8b2451878e26

[gaim-migrate @ 10387] " This patch adds chat user status icons (voice / halfop / op / founder) to chats There's a screenshot here, showing ops, voices and ignored ops and voices http://nosnilmot.com/gaim/chatusers.png This required some changes in how the core stores the list of users in chats to be able to store the status too, which are detailed below. I also fixed up some memory leaks as I came across them (string values returned by gtk_tree_model_get() not being g_free()'d) and a minor bug in signals-test.c Conversation API: Changed: gaim_conv_chat_add_user() (added flags parameter) gaim_conv_chat_add_users() now (added GList of flags parameter) gaim_conv_chat_get_users() now returns a GList of GaimChatBuddy's gaim_conv_chat_set_users() now expects a GList of GaimChatBuddy's Added: gaim_conv_chat_set_user_flags() gaim_conv_chat_get_user_flags() gaim_conv_chat_find_user() gaim_conv_chat_cb_new() gaim_conv_chat_cb_find() gaim_conv_chat_cb_destroy() gaim_conv_chat_cb_get_name() Conversation UI ops: added: chat_update_user() Signals: Changed: chat-buddy-joining & chat-buddy-joined now include the user's flags Added: chat-buddy-flags for when user's flags change Added: gaim_marshal_VOID__POINTER_POINTER_POINTER_UINT_UINT (required for the new chat-buddy-flags signal) Protocol Plugins: All updated to work with above changes (obviously) User flags support added to IRC, Jabber and SILC New Files: pixmaps/status/default/ voice.svg halfop.svg op.svg founder.svg " --Stu Tomlinson committer: Tailor Script <tailor@pidgin.im>
author Luke Schierer <lschiere@pidgin.im>
date Sat, 17 Jul 2004 18:11:12 +0000
parents 7ca073ddf9b0
children 5e1c76f3d232
line wrap: on
line diff
--- a/src/conversation.c	Sat Jul 17 17:08:24 2004 +0000
+++ b/src/conversation.c	Sat Jul 17 18:11:12 2004 +0000
@@ -30,10 +30,6 @@
 #include "signals.h"
 #include "util.h"
 
-/* XXX CORE/UI, waiting for away splittage */
-#include "gtkinternal.h"
-#include "ui.h"
-
 typedef struct
 {
 	char *id;
@@ -56,34 +52,6 @@
 static void ensure_default_funcs(void);
 static void conv_placement_last_created_win(GaimConversation *conv);
 
-static gint
-insertname_compare(gconstpointer one, gconstpointer two)
-{
-	const char *a = (const char *)one;
-	const char *b = (const char *)two;
-
-	if (*a == '@') {
-		if (*b != '@') return -1;
-
-		return g_ascii_strcasecmp(a + 1, b + 1);
-
-	} else if (*a == '%') {
-		if (*b != '%') return -1;
-
-		return g_ascii_strcasecmp(a + 1, b + 1);
-
-	} else if (*a == '+') {
-		if (*b == '@') return  1;
-		if (*b != '+') return -1;
-
-		return g_ascii_strcasecmp(a + 1, b + 1);
-
-	} else if (*b == '@' || *b == '%' || *b == '+')
-		return 1;
-
-	return g_ascii_strcasecmp(a, b);
-}
-
 static gboolean
 find_nick(const char *nick, const char *message)
 {
@@ -1927,10 +1895,12 @@
 }
 
 void
-gaim_conv_chat_add_user(GaimConvChat *chat, const char *user, const char *extra_msg)
+gaim_conv_chat_add_user(GaimConvChat *chat, const char *user, const char *extra_msg,
+						GaimConvChatBuddyFlags flags)
 {
 	GaimConversation *conv;
 	GaimConversationUiOps *ops;
+	GaimConvChatBuddy *cb;
 	char tmp[BUF_LONG];
 
 	g_return_if_fail(chat != NULL);
@@ -1942,9 +1912,10 @@
 	gaim_signal_emit(gaim_conversations_get_handle(),
 					 "chat-buddy-joining", conv, user);
 
+	cb = gaim_conv_chat_cb_new(user, flags);
+
 	gaim_conv_chat_set_users(chat,
-		g_list_insert_sorted(gaim_conv_chat_get_users(chat), g_strdup(user),
-							 insertname_compare));
+		g_list_append(gaim_conv_chat_get_users(chat), cb));
 
 	if (ops != NULL && ops->chat_add_user != NULL)
 		ops->chat_add_user(conv, user);
@@ -1963,11 +1934,12 @@
 }
 
 void
-gaim_conv_chat_add_users(GaimConvChat *chat, GList *users)
+gaim_conv_chat_add_users(GaimConvChat *chat, GList *users, GList *flags)
 {
 	GaimConversation *conv;
 	GaimConversationUiOps *ops;
-	GList *l;
+	GaimConvChatBuddy *cb;
+	GList *ul, *fl;
 
 	g_return_if_fail(chat  != NULL);
 	g_return_if_fail(users != NULL);
@@ -1975,19 +1947,23 @@
 	conv = gaim_conv_chat_get_conversation(chat);
 	ops  = gaim_conversation_get_ui_ops(conv);
 
-	for (l = users; l != NULL; l = l->next) {
-		const char *user = (const char *)l->data;
+	ul = users;
+	fl = flags;
+	while ((ul != NULL) && (fl != NULL)) {
+		const char *user = (const char *)ul->data;
+		GaimConvChatBuddyFlags f = GPOINTER_TO_INT(fl->data);
 
 		gaim_signal_emit(gaim_conversations_get_handle(),
-						 "chat-buddy-joining", conv, user);
-
+						 "chat-buddy-joining", conv, user, f);
+
+		cb = gaim_conv_chat_cb_new(user, f);
 		gaim_conv_chat_set_users(chat,
-				g_list_insert_sorted(gaim_conv_chat_get_users(chat),
-									 g_strdup((char *)l->data),
-									 insertname_compare));
+				g_list_append(gaim_conv_chat_get_users(chat), cb));
 
 		gaim_signal_emit(gaim_conversations_get_handle(),
-						 "chat-buddy-joined", conv, user);
+						 "chat-buddy-joined", conv, user, f);
+		ul = ul->next;
+		fl = fl->next;
 	}
 
 	if (ops != NULL && ops->chat_add_users != NULL)
@@ -2000,8 +1976,9 @@
 {
 	GaimConversation *conv;
 	GaimConversationUiOps *ops;
+	GaimConvChatBuddy *cb;
+	GaimConvChatBuddyFlags flags;
 	char tmp[BUF_LONG];
-	GList *names;
 	gboolean its_me = FALSE;
 
 	g_return_if_fail(chat != NULL);
@@ -2011,22 +1988,20 @@
 	conv = gaim_conv_chat_get_conversation(chat);
 	ops  = gaim_conversation_get_ui_ops(conv);
 
+	flags = gaim_conv_chat_user_get_flags(chat, old_user);
+	cb = gaim_conv_chat_cb_new(new_user, flags);
 	gaim_conv_chat_set_users(chat,
-		g_list_insert_sorted(gaim_conv_chat_get_users(chat), g_strdup(new_user),
-							 insertname_compare));
+		g_list_append(gaim_conv_chat_get_users(chat), cb));
 
 	if (ops != NULL && ops->chat_rename_user != NULL)
 		ops->chat_rename_user(conv, old_user, new_user);
 
-	for (names = gaim_conv_chat_get_users(chat);
-		 names != NULL;
-		 names = names->next) {
-
-		if (!gaim_utf8_strcasecmp((char *)names->data, old_user)) {
-			gaim_conv_chat_set_users(chat,
-					g_list_remove(gaim_conv_chat_get_users(chat), names->data));
-			break;
-		}
+	cb = gaim_conv_chat_cb_find(chat, old_user);
+
+	if (cb) {
+		gaim_conv_chat_set_users(chat,
+				g_list_remove(gaim_conv_chat_get_users(chat), cb));
+		gaim_conv_chat_cb_destroy(cb);
 	}
 
 	if (gaim_conv_chat_is_user_ignored(chat, old_user)) {
@@ -2059,8 +2034,8 @@
 {
 	GaimConversation *conv;
 	GaimConversationUiOps *ops;
+	GaimConvChatBuddy *cb;
 	char tmp[BUF_LONG];
-	GList *names;
 
 	g_return_if_fail(chat != NULL);
 	g_return_if_fail(user != NULL);
@@ -2074,15 +2049,12 @@
 	if (ops != NULL && ops->chat_remove_user != NULL)
 		ops->chat_remove_user(conv, user);
 
-	for (names = gaim_conv_chat_get_users(chat);
-		 names != NULL;
-		 names = names->next) {
-
-		if (!gaim_utf8_strcasecmp((char *)names->data, user)) {
-			gaim_conv_chat_set_users(chat,
-					g_list_remove(gaim_conv_chat_get_users(chat), names->data));
-			break;
-		}
+	cb = gaim_conv_chat_cb_find(chat, user);
+
+	if (cb) {
+		gaim_conv_chat_set_users(chat,
+				g_list_remove(gaim_conv_chat_get_users(chat), cb));
+		gaim_conv_chat_cb_destroy(cb);
 	}
 
 	/* NOTE: Don't remove them from ignored in case they re-enter. */
@@ -2104,8 +2076,9 @@
 {
 	GaimConversation *conv;
 	GaimConversationUiOps *ops;
+	GaimConvChatBuddy *cb;
 	char tmp[BUF_LONG];
-	GList *names, *l;
+	GList *l;
 
 	g_return_if_fail(chat  != NULL);
 	g_return_if_fail(users != NULL);
@@ -2126,17 +2099,12 @@
 	for (l = users; l != NULL; l = l->next) {
 		const char *user = (const char *)l->data;
 
-		for (names = gaim_conv_chat_get_users(chat);
-			 names != NULL;
-			 names = names->next) {
-
-			if (!gaim_utf8_strcasecmp((char *)names->data, user))
-			{
-				gaim_conv_chat_set_users(chat,
-					g_list_remove(gaim_conv_chat_get_users(chat), names->data));
-
-				break;
-			}
+		cb = gaim_conv_chat_cb_find(chat, user);
+
+		if (cb) {
+			gaim_conv_chat_set_users(chat,
+					g_list_remove(gaim_conv_chat_get_users(chat), cb));
+			gaim_conv_chat_cb_destroy(cb);
 		}
 
 		gaim_signal_emit(gaim_conversations_get_handle(), "chat-buddy-left",
@@ -2176,8 +2144,8 @@
 {
 	GaimConversation *conv;
 	GaimConversationUiOps *ops;
-	GList *users;
-	GList *l, *l_next;
+	GList *users, *names = NULL;
+	GList *l;
 
 	g_return_if_fail(chat != NULL);
 
@@ -2185,27 +2153,90 @@
 	ops   = gaim_conversation_get_ui_ops(conv);
 	users = gaim_conv_chat_get_users(chat);
 
-	if (ops != NULL && ops->chat_remove_users != NULL)
-		ops->chat_remove_users(conv, users);
-
-	for (l = users; l != NULL; l = l_next)
+	if (ops != NULL && ops->chat_remove_users != NULL) {
+		for (l = users; l; l = l->next) {
+			GaimConvChatBuddy *cb = l->data;
+			names = g_list_append(names, cb->name);
+		}
+		ops->chat_remove_users(conv, names);
+		g_list_free(names);
+	}
+
+	for (l = users; l; l = l->next)
 	{
-		char *user = (char *)l->data;
-
-		l_next = l->next;
+		GaimConvChatBuddy *cb = l->data;
 
 		gaim_signal_emit(gaim_conversations_get_handle(),
-						 "chat-buddy-leaving", conv, user, NULL);
+						 "chat-buddy-leaving", conv, cb->name, NULL);
 		gaim_signal_emit(gaim_conversations_get_handle(),
-						 "chat-buddy-left", conv, user, NULL);
-
-		g_free(user);
+						 "chat-buddy-left", conv, cb->name, NULL);
+
+		gaim_conv_chat_cb_destroy(cb);
 	}
 
 	g_list_free(users);
 	gaim_conv_chat_set_users(chat, NULL);
 }
 
+
+gboolean
+gaim_conv_chat_find_user(GaimConvChat *chat, const char *user)
+{
+	g_return_val_if_fail(chat != NULL, FALSE);
+	g_return_val_if_fail(user != NULL, FALSE);
+
+	return (gaim_conv_chat_cb_find(chat, user) != NULL);
+}
+
+void
+gaim_conv_chat_user_set_flags(GaimConvChat *chat, const char *user,
+							  GaimConvChatBuddyFlags flags)
+{
+	GaimConversation *conv;
+	GaimConversationUiOps *ops;
+	GaimConvChatBuddy *cb;
+	GaimConvChatBuddyFlags oldflags;
+
+	g_return_if_fail(chat != NULL);
+	g_return_if_fail(user != NULL);
+
+	cb = gaim_conv_chat_cb_find(chat, user);
+
+	if (!cb)
+		return;
+
+	if (flags == cb->flags)
+		return;
+
+	oldflags = cb->flags;
+	cb->flags = flags;
+
+	conv = gaim_conv_chat_get_conversation(chat);
+	ops = gaim_conversation_get_ui_ops(conv);
+
+	if (ops != NULL && ops->chat_update_user != NULL)
+			ops->chat_update_user(conv, user);
+
+	gaim_signal_emit(gaim_conversations_get_handle(),
+					 "chat-buddy-flags", conv, user, oldflags, flags);
+}
+
+GaimConvChatBuddyFlags
+gaim_conv_chat_user_get_flags(GaimConvChat *chat, const char *user)
+{
+	GaimConvChatBuddy *cb;
+
+	g_return_val_if_fail(chat != NULL, 0);
+	g_return_val_if_fail(user != NULL, 0);
+
+	cb = gaim_conv_chat_cb_find(chat, user);
+
+	if (!cb)
+		return GAIM_CBFLAGS_NONE;
+
+	return cb->flags;
+}
+
 void gaim_conv_chat_set_nick(GaimConvChat *chat, const char *nick) {
 	g_return_if_fail(chat != NULL);
 
@@ -2254,6 +2285,58 @@
 	return chat->left;
 }
 
+GaimConvChatBuddy *
+gaim_conv_chat_cb_new(const char *name, GaimConvChatBuddyFlags flags)
+{
+	GaimConvChatBuddy *cb;
+
+	g_return_val_if_fail(name != NULL, NULL);
+
+	cb = g_new0(GaimConvChatBuddy, 1);
+	cb->name = g_strdup(name);
+	cb->flags = flags;
+
+	return cb;
+}
+
+GaimConvChatBuddy *
+gaim_conv_chat_cb_find(GaimConvChat *chat, const char *name)
+{
+	GList *l;
+	GaimConvChatBuddy *cb = NULL;
+
+	g_return_val_if_fail(chat != NULL, NULL);
+	g_return_val_if_fail(name != NULL, NULL);
+
+	for (l = gaim_conv_chat_get_users(chat); l; l = l->next) {
+		cb = l->data;
+		if (!gaim_utf8_strcasecmp(cb->name, name))
+			return cb;
+	}
+
+	return NULL;
+}
+
+void
+gaim_conv_chat_cb_destroy(GaimConvChatBuddy *cb)
+{
+	g_return_if_fail(cb != NULL);
+
+	if (cb->name)
+		g_free(cb->name);
+	cb->name = NULL;
+	cb->flags = 0;
+	g_free(cb);
+}
+
+const char *
+gaim_conv_chat_cb_get_name(GaimConvChatBuddy *cb)
+{
+	g_return_val_if_fail(cb != NULL, NULL);
+
+	return cb->name;
+}
+
 /**************************************************************************
  * Conversation placement functions
  **************************************************************************/
@@ -2798,16 +2881,26 @@
 										GAIM_SUBTYPE_CONVERSATION));
 
 	gaim_signal_register(handle, "chat-buddy-joining",
-						 gaim_marshal_VOID__POINTER_POINTER, NULL, 2,
+						 gaim_marshal_VOID__POINTER_POINTER_UINT, NULL, 3,
+						 gaim_value_new(GAIM_TYPE_SUBTYPE,
+										GAIM_SUBTYPE_CONVERSATION),
+						 gaim_value_new(GAIM_TYPE_STRING),
+						 gaim_value_new(GAIM_TYPE_UINT));
+
+	gaim_signal_register(handle, "chat-buddy-joined",
+						 gaim_marshal_VOID__POINTER_POINTER_UINT, NULL, 3,
 						 gaim_value_new(GAIM_TYPE_SUBTYPE,
 										GAIM_SUBTYPE_CONVERSATION),
-						 gaim_value_new(GAIM_TYPE_STRING));
-
-	gaim_signal_register(handle, "chat-buddy-joined",
-						 gaim_marshal_VOID__POINTER_POINTER, NULL, 2,
+						 gaim_value_new(GAIM_TYPE_STRING),
+						 gaim_value_new(GAIM_TYPE_UINT));
+
+	gaim_signal_register(handle, "chat-buddy-flags",
+						 gaim_marshal_VOID__POINTER_POINTER_UINT_UINT, NULL, 4,
 						 gaim_value_new(GAIM_TYPE_SUBTYPE,
 										GAIM_SUBTYPE_CONVERSATION),
-						 gaim_value_new(GAIM_TYPE_STRING));
+						 gaim_value_new(GAIM_TYPE_STRING),
+						 gaim_value_new(GAIM_TYPE_UINT),
+						 gaim_value_new(GAIM_TYPE_UINT));
 
 	gaim_signal_register(handle, "chat-buddy-leaving",
 						 gaim_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3,