# HG changeset patch # User Christian Hammond # Date 1070417005 0 # Node ID 2823111061ba64057330cae7e2c105debb057a3f # Parent ebd43be54140e3ceb1eeb34a2ddc4da4c1001db0 [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 diff -r ebd43be54140 -r 2823111061ba src/gtkblist.c --- 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); diff -r ebd43be54140 -r 2823111061ba src/gtkconv.c --- 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 diff -r ebd43be54140 -r 2823111061ba src/gtkutils.c --- 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; +} diff -r ebd43be54140 -r 2823111061ba src/gtkutils.h --- 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_ */