changeset 7712:2823111061ba

[gaim-migrate @ 8357] I did a few things to my drag-and-drop patch. First, I moved the application/x-im-contact parsing code into its own function, so we don't have to duplicate stuff. The reason I did this is because Sean suggested support for dragging x-im-contacts into conversation windows, which is also implemented now, and it rocks. :) committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Wed, 03 Dec 2003 02:03:25 +0000
parents ebd43be54140
children 1adc71ed6d45
files src/gtkblist.c src/gtkconv.c src/gtkutils.c src/gtkutils.h
diffstat 4 files changed, 238 insertions(+), 96 deletions(-) [+]
line wrap: on
line diff
--- a/src/gtkblist.c	Wed Dec 03 01:27:53 2003 +0000
+++ b/src/gtkblist.c	Wed Dec 03 02:03:25 2003 +0000
@@ -1349,11 +1349,10 @@
 		GaimGroup *group = NULL;
 		GtkTreePath *path = NULL;
 		GtkTreeViewDropPosition position;
+		GaimAccount *account;
 		char *protocol = NULL;
 		char *username = NULL;
 		char *alias = NULL;
-		char *contact_str;
-		char *c, *s;
 
 		if (gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget),
 											  x, y, &path, &position))
@@ -1383,96 +1382,9 @@
 			}
 		}
 
-		contact_str = g_strndup(sd->data, sd->length);
-
-		s = contact_str;
-
-		while (*s != '\r' && *s != '\n' && *s != '\0')
+		if (gaim_gtk_parse_x_im_contact(sd->data, FALSE, &account,
+										&protocol, &username, &alias))
 		{
-			char *key, *value;
-
-			key = s;
-
-			/* Grab the key */
-			while (*s != '\r' && *s != '\n' && *s != '\0' && *s != ' ')
-				s++;
-
-			if (*s == '\r') s++;
-
-			if (*s == '\n')
-			{
-				s++;
-				continue;
-			}
-
-			if (*s != '\0') *s++ = '\0';
-
-			/* Clear past any whitespace */
-			while (*s != '\0' && *s == ' ')
-				s++;
-
-			/* Now let's grab until the end of the line. */
-			value = s;
-
-			while (*s != '\r' && *s != '\n' && *s != '\0')
-				s++;
-
-			if (*s == '\r') *s++ = '\0';
-			if (*s == '\n') *s++ = '\0';
-
-			if ((c = strchr(key, ':')) != NULL)
-			{
-				if (!g_ascii_strcasecmp(key, "X-IM-Username:"))
-					username = g_strdup(value);
-				else if (!g_ascii_strcasecmp(key, "X-IM-Protocol:"))
-					protocol = g_strdup(value);
-				else if (!g_ascii_strcasecmp(key, "X-IM-Alias:"))
-					alias = g_strdup(value);
-			}
-		}
-
-		if (username != NULL && protocol != NULL)
-		{
-			GaimAccount *account = NULL;
-			GList *l;
-			const char *protoname;
-
-			for (l = gaim_connections_get_all(); l != NULL; l = l->next)
-			{
-				GaimConnection *gc = (GaimConnection *)l->data;
-				account = gaim_connection_get_account(gc);
-
-				protoname =
-					GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->list_icon(account,
-																   NULL);
-
-				if (!strcmp(protoname, protocol))
-					break;
-
-				account = NULL;
-			}
-
-			/* Special case for AIM and ICQ */
-			if (account == NULL && (!strcmp(protocol, "aim") ||
-									!strcmp(protocol, "icq")))
-			{
-
-				for (l = gaim_connections_get_all(); l != NULL; l = l->next)
-				{
-					GaimConnection *gc = (GaimConnection *)l->data;
-					account = gaim_connection_get_account(gc);
-
-					protoname =
-						GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->list_icon(account,
-																	   NULL);
-
-					if (!strcmp(protoname, "aim") || !strcmp(protoname, "icq"))
-						break;
-
-					account = NULL;
-				}				
-			}
-
 			if (account == NULL)
 			{
 				gaim_notify_error(NULL, NULL,
@@ -1491,8 +1403,6 @@
 		if (protocol != NULL) g_free(protocol);
 		if (alias    != NULL) g_free(alias);
 
-		g_free(contact_str);
-
 		if (path != NULL)
 			gtk_tree_path_free(path);
 
--- a/src/gtkconv.c	Wed Dec 03 01:27:53 2003 +0000
+++ b/src/gtkconv.c	Wed Dec 03 02:03:25 2003 +0000
@@ -3778,7 +3778,8 @@
 	GaimConvWindow *win = conv->window;
 	GaimConversation *c;
 
-	if (sd->target == gdk_atom_intern("GAIM_BLIST_NODE", FALSE)) {
+	if (sd->target == gdk_atom_intern("GAIM_BLIST_NODE", FALSE))
+	{
 		GaimBlistNode *n = NULL;
 		GaimBuddy *b;
 		memcpy(&n, sd->data, sizeof(n));
@@ -3794,6 +3795,32 @@
 
 		gaim_conv_window_add_conversation(win, c);
 	}
+	else if (sd->target == gdk_atom_intern("application/x-im-contact", FALSE))
+	{
+		char *protocol = NULL;
+		char *username = NULL;
+		GaimAccount *account;
+
+		if (gaim_gtk_parse_x_im_contact(sd->data, FALSE, &account,
+										&protocol, &username, NULL))
+		{
+			if (account == NULL)
+			{
+				gaim_notify_error(NULL, NULL,
+					_("You are not currently signed on with an account that "
+					  "can add that buddy."), NULL);
+			}
+			else
+			{
+				gaim_conversation_new(GAIM_CONV_IM, account, username);
+			}
+		}
+
+		if (username != NULL) g_free(username);
+		if (protocol != NULL) g_free(protocol);
+
+		gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t);
+	}
 }
 
 /**************************************************************************
@@ -3944,8 +3971,9 @@
 {
 	{"text/plain", 0, 0},
 	{"text/uri-list", 0, 1},
-	{"GAIM_BLIST_NODE", 0, 2},
-	{"STRING", 0, 3}
+	{"GAIM_BLIST_NODE", GTK_TARGET_SAME_APP, 2},
+	{"STRING", 0, 3},
+	{"application/x-im-contact", 0, 4}
 };
 
 static void
--- a/src/gtkutils.c	Wed Dec 03 01:27:53 2003 +0000
+++ b/src/gtkutils.c	Wed Dec 03 02:03:25 2003 +0000
@@ -1140,3 +1140,186 @@
 	gtk_accel_map_load(filename);
 	g_free(filename);
 }
+
+gboolean
+gaim_gtk_parse_x_im_contact(const char *msg, gboolean all_accounts,
+							GaimAccount **ret_account, char **ret_protocol,
+							char **ret_username, char **ret_alias)
+{
+	char *protocol = NULL;
+	char *username = NULL;
+	char *alias    = NULL;
+	char *str;
+	char *c, *s;
+	gboolean valid;
+
+	g_return_val_if_fail(msg          != NULL, FALSE);
+	g_return_val_if_fail(ret_protocol != NULL, FALSE);
+	g_return_val_if_fail(ret_username != NULL, FALSE);
+
+	s = str = g_strdup(msg);
+
+	while (*s != '\r' && *s != '\n' && *s != '\0')
+	{
+		char *key, *value;
+
+		key = s;
+
+		/* Grab the key */
+		while (*s != '\r' && *s != '\n' && *s != '\0' && *s != ' ')
+			s++;
+
+		if (*s == '\r') s++;
+
+		if (*s == '\n')
+		{
+			s++;
+			continue;
+		}
+
+		if (*s != '\0') *s++ = '\0';
+
+		/* Clear past any whitespace */
+		while (*s != '\0' && *s == ' ')
+			s++;
+
+		/* Now let's grab until the end of the line. */
+		value = s;
+
+		while (*s != '\r' && *s != '\n' && *s != '\0')
+			s++;
+
+		if (*s == '\r') *s++ = '\0';
+		if (*s == '\n') *s++ = '\0';
+
+		if ((c = strchr(key, ':')) != NULL)
+		{
+			if (!g_ascii_strcasecmp(key, "X-IM-Username:"))
+				username = g_strdup(value);
+			else if (!g_ascii_strcasecmp(key, "X-IM-Protocol:"))
+				protocol = g_strdup(value);
+			else if (!g_ascii_strcasecmp(key, "X-IM-Alias:"))
+				alias = g_strdup(value);
+		}
+	}
+
+	if (username != NULL && protocol != NULL)
+	{
+		valid = TRUE;
+
+		*ret_username = username;
+		*ret_protocol = protocol;
+
+		if (ret_alias != NULL)
+			*ret_alias = alias;
+
+		/* Check for a compatible account. */
+		if (ret_account != NULL)
+		{
+			GList *list;
+			GaimAccount *account = NULL;
+			GList *l;
+			const char *protoname;
+
+			if (all_accounts)
+				list = gaim_accounts_get_all();
+			else
+				list = gaim_connections_get_all();
+
+			for (l = list; l != NULL; l = l->next)
+			{
+				GaimConnection *gc;
+				GaimPluginProtocolInfo *prpl_info = NULL;
+				GaimPlugin *plugin;
+
+				if (all_accounts)
+				{
+					account = (GaimAccount *)l->data;
+
+					plugin = gaim_plugins_find_with_id(
+						gaim_account_get_protocol_id(account));
+
+					if (plugin == NULL)
+					{
+						account = NULL;
+
+						continue;
+					}
+
+					prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(plugin);
+				}
+				else
+				{
+					gc = (GaimConnection *)l->data;
+					account = gaim_connection_get_account(gc);
+
+					prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl);
+				}
+
+				protoname = prpl_info->list_icon(account, NULL);
+
+				if (!strcmp(protoname, protocol))
+					break;
+
+				account = NULL;
+			}
+
+			/* Special case for AIM and ICQ */
+			if (account == NULL && (!strcmp(protocol, "aim") ||
+									!strcmp(protocol, "icq")))
+			{
+				for (l = list; l != NULL; l = l->next)
+				{
+					GaimConnection *gc;
+					GaimPluginProtocolInfo *prpl_info = NULL;
+					GaimPlugin *plugin;
+
+					if (all_accounts)
+					{
+						account = (GaimAccount *)l->data;
+
+						plugin = gaim_plugins_find_with_id(
+							gaim_account_get_protocol_id(account));
+
+						if (plugin == NULL)
+						{
+							account = NULL;
+
+							continue;
+						}
+
+						prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(plugin);
+					}
+					else
+					{
+						gc = (GaimConnection *)l->data;
+						account = gaim_connection_get_account(gc);
+
+						prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl);
+					}
+
+					protoname = prpl_info->list_icon(account, NULL);
+
+					if (!strcmp(protoname, "aim") || !strcmp(protoname, "icq"))
+						break;
+
+					account = NULL;
+				}
+			}
+
+			*ret_account = account;
+		}
+	}
+	else
+	{
+		valid = FALSE;
+
+		if (username != NULL) g_free(username);
+		if (protocol != NULL) g_free(protocol);
+		if (alias    != NULL) g_free(alias);
+	}
+
+	g_free(str);
+
+	return valid;
+}
--- a/src/gtkutils.h	Wed Dec 03 01:27:53 2003 +0000
+++ b/src/gtkutils.h	Wed Dec 03 02:03:25 2003 +0000
@@ -313,4 +313,25 @@
  */
 void gaim_gtk_load_accels();
 
+/**
+ * Parses an application/x-im-contact MIME message and returns the
+ * data inside.
+ *
+ * @param msg          The MIME message.
+ * @param all_accounts If TRUE, check all compatible accounts, online or
+ *                     offline. If FALSE, check only online accounts.
+ * @param ret_account  The best guess at a compatible protocol,
+ *                     based on ret_protocol. If NULL, no account was found.
+ * @param ret_protocol The returned protocol type.
+ * @param ret_username The returned username.
+ * @param ret_alias    The returned alias.
+ *
+ * @return TRUE if the message was parsed for the minimum necessary data.
+ *         FALSE otherwise.
+ */
+gboolean gaim_gtk_parse_x_im_contact(const char *msg, gboolean all_accounts,
+									 GaimAccount **ret_account,
+									 char **ret_protocol, char **ret_username,
+									 char **ret_alias);
+
 #endif /* _GAIM_GTK_UTILS_H_ */