# HG changeset patch # User Yoshiki Yazawa # Date 1181272753 0 # Node ID be1c61b5f30da4ec1f8e9497cf6c22319b6bcdbf # Parent 5eebb9b24e30340335eb01d204880c92166b01a0# Parent 24d035ad12cd404fd76f469c1b25571c62ebd358 propagate from branch 'im.pidgin.pidgin' (head 4b50880d8517570eaa67d4cd9d88c5934bb832f1) to branch 'im.pidgin.pidgin.yaz' (head eb10df5cf156fff3f6d9f0ad9f8d81e5b8f833b4) diff -r 24d035ad12cd -r be1c61b5f30d ChangeLog.API --- a/ChangeLog.API Thu Jun 07 07:32:06 2007 +0000 +++ b/ChangeLog.API Fri Jun 08 03:19:13 2007 +0000 @@ -1,5 +1,11 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +version 2.0.2 (6/14/2007): + Pidgin: + Deprecated: + * pidgin_dialogs_alias_contact: This will be removed in 3.0.0 + unless there is sufficient demand to keep it. + version 2.0.0 (5/3/2007): Please note all functions, defines, and data structures have been re-namespaced to match the new names of Pidgin, Finch, and libpurple. diff -r 24d035ad12cd -r be1c61b5f30d libpurple/protocols/bonjour/bonjour.c --- a/libpurple/protocols/bonjour/bonjour.c Thu Jun 07 07:32:06 2007 +0000 +++ b/libpurple/protocols/bonjour/bonjour.c Fri Jun 08 03:19:13 2007 +0000 @@ -94,14 +94,13 @@ bonjour_login(PurpleAccount *account) { PurpleConnection *gc = purple_account_get_connection(account); - PurpleGroup *bonjour_group = NULL; - BonjourData *bd = NULL; + PurpleGroup *bonjour_group; + BonjourData *bd; PurpleStatus *status; PurplePresence *presence; gc->flags |= PURPLE_CONNECTION_HTML; - gc->proto_data = g_new0(BonjourData, 1); - bd = gc->proto_data; + gc->proto_data = bd = g_new0(BonjourData, 1); /* Start waiting for jabber connections (iChat style) */ bd->jabber_data = g_new(BonjourJabber, 1); @@ -111,10 +110,6 @@ if (bonjour_jabber_start(bd->jabber_data) == -1) { /* Send a message about the connection error */ purple_connection_error(gc, _("Unable to listen for incoming IM connections\n")); - - /* Free the data */ - g_free(bd->jabber_data); - bd->jabber_data = NULL; return; } @@ -155,7 +150,7 @@ bonjour_close(PurpleConnection *connection) { PurpleGroup *bonjour_group; - BonjourData *bd = (BonjourData*)connection->proto_data; + BonjourData *bd = connection->proto_data; /* Stop looking for buddies in the LAN */ if (bd->dns_sd_data != NULL) diff -r 24d035ad12cd -r be1c61b5f30d libpurple/protocols/bonjour/buddy.c --- a/libpurple/protocols/bonjour/buddy.c Thu Jun 07 07:32:06 2007 +0000 +++ b/libpurple/protocols/bonjour/buddy.c Fri Jun 08 03:19:13 2007 +0000 @@ -162,6 +162,8 @@ bonjour_buddy_delete(BonjourBuddy *buddy) { g_free(buddy->name); + g_free(buddy->ip); + g_free(buddy->first); g_free(buddy->phsh); g_free(buddy->status); @@ -170,8 +172,11 @@ g_free(buddy->jid); g_free(buddy->AIM); g_free(buddy->vc); - g_free(buddy->ip); g_free(buddy->msg); + g_free(buddy->ext); + g_free(buddy->nick); + g_free(buddy->node); + g_free(buddy->ver); if (buddy->conversation != NULL) { diff -r 24d035ad12cd -r be1c61b5f30d libpurple/protocols/bonjour/jabber.c --- a/libpurple/protocols/bonjour/jabber.c Thu Jun 07 07:32:06 2007 +0000 +++ b/libpurple/protocols/bonjour/jabber.c Fri Jun 08 03:19:13 2007 +0000 @@ -123,46 +123,41 @@ return "1"; } + static void _jabber_parse_and_write_message_to_ui(char *message, PurpleConnection *connection, PurpleBuddy *gb) { - xmlnode *body_node = NULL; - char *body = NULL; - xmlnode *html_node = NULL; - gboolean isHTML = FALSE; - xmlnode *html_body_node = NULL; + xmlnode *message_node, *body_node, *html_node, *events_node; + char *body, *html_body = NULL; const char *ichat_balloon_color = NULL; const char *ichat_text_color = NULL; - xmlnode *html_body_font_node = NULL; const char *font_face = NULL; const char *font_size = NULL; const char *font_color = NULL; - char *html_body = NULL; - xmlnode *events_node = NULL; gboolean composing_event = FALSE; - gint garbage = -1; - xmlnode *message_node = NULL; /* Parsing of the message */ message_node = xmlnode_from_str(message, strlen(message)); - if (message_node == NULL) { + if (message_node == NULL) return; - } body_node = xmlnode_get_child(message_node, "body"); - if (body_node != NULL) { - body = xmlnode_get_data(body_node); - } else { + if (body_node == NULL) { + xmlnode_free(message_node); return; } + body = xmlnode_get_data(body_node); html_node = xmlnode_get_child(message_node, "html"); if (html_node != NULL) { - isHTML = TRUE; + xmlnode *html_body_node; + html_body_node = xmlnode_get_child(html_node, "body"); if (html_body_node != NULL) { + xmlnode *html_body_font_node; + ichat_balloon_color = xmlnode_get_attrib(html_body_node, "ichatballooncolor"); ichat_text_color = xmlnode_get_attrib(html_body_node, "ichattextcolor"); html_body_font_node = xmlnode_get_child(html_body_node, "font"); @@ -172,23 +167,17 @@ /* The absolute iChat font sizes should be converted to 1..7 range */ font_size = xmlnode_get_attrib(html_body_font_node, "ABSZ"); if (font_size != NULL) - { font_size = _font_size_ichat_to_purple(atoi(font_size)); - } font_color = xmlnode_get_attrib(html_body_font_node, "color"); html_body = xmlnode_get_data(html_body_font_node); if (html_body == NULL) { + gint garbage = -1; /* This is the kind of formated messages that Purple creates */ html_body = xmlnode_to_str(html_body_font_node, &garbage); } - } else { - isHTML = FALSE; } - } else { - isHTML = FALSE; } - } events_node = xmlnode_get_child_with_namespace(message_node, "x", "jabber:x:event"); @@ -201,6 +190,7 @@ if (xmlnode_get_child(events_node, "id") != NULL) { /* The user is just typing */ + /* TODO: Deal with typing notification */ xmlnode_free(message_node); g_free(body); g_free(html_body); @@ -209,8 +199,10 @@ } /* Compose the message */ - if (isHTML) + if (html_body != NULL) { + g_free(body); + if (font_face == NULL) font_face = "Helvetica"; if (font_size == NULL) font_size = "3"; if (ichat_text_color == NULL) ichat_text_color = "#000000"; @@ -219,6 +211,8 @@ "' back='", ichat_balloon_color, "'>", html_body, "", NULL); } + /* TODO: Should we do something with "composing_event" here? */ + /* Send the message to the UI */ serv_got_im(connection, gb->name, body, 0, time(NULL)); @@ -229,7 +223,7 @@ } struct _check_buddy_by_address_t { - char *address; + const char *address; PurpleBuddy **gb; BonjourJabber *bj; }; @@ -237,12 +231,9 @@ static void _check_buddy_by_address(gpointer key, gpointer value, gpointer data) { - PurpleBuddy *gb = (PurpleBuddy*)value; + PurpleBuddy *gb = value; BonjourBuddy *bb; - struct _check_buddy_by_address_t *cbba; - - gb = value; - cbba = data; + struct _check_buddy_by_address_t *cbba = data; /* * If the current PurpleBuddy's data is not null and the PurpleBuddy's account @@ -274,14 +265,14 @@ if (partial_message_length == -1) { - purple_debug_warning("bonjour", "receive error: %s\n", strerror(errno)); + if (errno != EAGAIN) + purple_debug_warning("bonjour", "receive error: %s\n", strerror(errno)); if (total_message_length == 0) { return -1; } } - *message = data->str; - g_string_free(data, FALSE); + *message = g_string_free(data, FALSE); if (total_message_length != 0) purple_debug_info("bonjour", "Receive: -%s- %d bytes\n", *message, total_message_length); @@ -313,17 +304,17 @@ { char *message = NULL; gint message_length; - PurpleBuddy *gb = (PurpleBuddy*)data; + PurpleBuddy *gb = data; PurpleAccount *account = gb->account; PurpleConversation *conversation; - char *closed_conv_message; - BonjourBuddy *bb = (BonjourBuddy*)gb->proto_data; + BonjourBuddy *bb = gb->proto_data; gboolean closed_conversation = FALSE; - xmlnode *message_node = NULL; + xmlnode *message_node; /* Read the data from the socket */ if ((message_length = _read_data(socket, &message)) == -1) { /* There have been an error reading from the socket */ + /* TODO: Shouldn't we handle the error if it isn't EAGAIN? */ return; } else if (message_length == 0) { /* The other end has closed the socket */ closed_conversation = TRUE; @@ -345,8 +336,8 @@ { /* Check if this is the start of the stream */ if ((message_node != NULL) && - g_ascii_strcasecmp(xmlnode_get_attrib(message_node, "xmlns"), "jabber:client") && - (xmlnode_get_attrib(message_node,"xmlns:stream") != NULL)) + g_ascii_strcasecmp(xmlnode_get_attrib(message_node, "xmlns"), "jabber:client") && + (xmlnode_get_attrib(message_node,"xmlns:stream") != NULL)) { bb->conversation->stream_started = TRUE; } @@ -354,13 +345,9 @@ { /* TODO: This needs to be nonblocking! */ if (send(bb->conversation->socket, DOCTYPE, strlen(DOCTYPE), 0) == -1) - { purple_debug_error("bonjour", "Unable to start a conversation with %s\n", bb->name); - } else - { bb->conversation->stream_started = TRUE; - } } } @@ -370,6 +357,8 @@ * parsing an end tag */ if (purple_str_has_prefix(message, STREAM_END) || (closed_conversation == TRUE)) { + char *closed_conv_message; + /* Close the socket, clear the watcher and free memory */ if (bb->conversation != NULL) { close(bb->conversation->socket); @@ -400,21 +389,18 @@ struct sockaddr_in their_addr; /* connector's address information */ socklen_t sin_size = sizeof(struct sockaddr); int client_socket; - BonjourBuddy *bb = NULL; - BonjourJabber *bj = data; + BonjourBuddy *bb; char *address_text = NULL; PurpleBuddyList *bl = purple_get_blist(); struct _check_buddy_by_address_t *cbba; /* Check that it is a read condition */ - if (condition != PURPLE_INPUT_READ) { + if (condition != PURPLE_INPUT_READ) return; - } if ((client_socket = accept(server_socket, (struct sockaddr *)&their_addr, &sin_size)) == -1) - { return; - } + fcntl(client_socket, F_SETFL, O_NONBLOCK); /* Look for the buddy that has opened the conversation and fill information */ @@ -422,7 +408,7 @@ cbba = g_new0(struct _check_buddy_by_address_t, 1); cbba->address = address_text; cbba->gb = &gb; - cbba->bj = bj; + cbba->bj = data; g_hash_table_foreach(bl->buddies, _check_buddy_by_address, cbba); g_free(cbba); if (gb == NULL) @@ -431,7 +417,7 @@ close(client_socket); return; } - bb = (BonjourBuddy*)gb->proto_data; + bb = gb->proto_data; /* Check if the conversation has been previously started */ if (bb->conversation == NULL) @@ -608,28 +594,28 @@ /* Start the stream */ if (send(bb->conversation->socket, DOCTYPE, strlen(DOCTYPE), 0) == -1) { - purple_debug_error("bonjour", "Unable to start a conversation\n"); - purple_debug_warning("bonjour", "send error: %s\n", strerror(errno)); - conversation = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, data->account); - purple_conversation_write(conversation, NULL, - _("Unable to send the message, the conversation couldn't be started."), - PURPLE_MESSAGE_SYSTEM, time(NULL)); - close(bb->conversation->socket); - purple_input_remove(bb->conversation->watcher_id); + purple_debug_error("bonjour", "Unable to start a conversation\n"); + purple_debug_warning("bonjour", "send error: %s\n", strerror(errno)); + conversation = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, data->account); + purple_conversation_write(conversation, NULL, + _("Unable to send the message, the conversation couldn't be started."), + PURPLE_MESSAGE_SYSTEM, time(NULL)); + close(bb->conversation->socket); + purple_input_remove(bb->conversation->watcher_id); - /* Free all the data related to the conversation */ - g_free(bb->conversation->buddy_name); - g_free(bb->conversation); - bb->conversation = NULL; - g_free(message); - return 0; + /* Free all the data related to the conversation */ + g_free(bb->conversation->buddy_name); + g_free(bb->conversation); + bb->conversation = NULL; + g_free(message); + return 0; } bb->conversation->stream_started = TRUE; } /* Send the message */ - ret = _send_data(bb->conversation->socket, message) == -1; + ret = (_send_data(bb->conversation->socket, message) == -1); g_free(message); if (ret == -1) @@ -662,30 +648,21 @@ void bonjour_jabber_stop(BonjourJabber *data) { - PurpleBuddy *gb = NULL; - BonjourBuddy *bb = NULL; - GSList *buddies; - GSList *l; + /* Close the server socket and remove the watcher */ + if (data->socket >= 0) + close(data->socket); + if (data->watcher_id > 0) + purple_input_remove(data->watcher_id); - /* Close the server socket and remove all the watcher */ - close(data->socket); - purple_input_remove(data->watcher_id); - - /* Close all the sockets and remove all the watchers after sending end streams */ + /* Close all the conversation sockets and remove all the watchers after sending end streams */ if (data->account->gc != NULL) { + GSList *buddies; + GSList *l; + buddies = purple_find_buddies(data->account, data->account->username); for (l = buddies; l; l = l->next) - { - gb = (PurpleBuddy*)l->data; - bb = (BonjourBuddy*)gb->proto_data; - if (bb->conversation != NULL) - { - send(bb->conversation->socket, STREAM_END, strlen(STREAM_END), 0); - close(bb->conversation->socket); - purple_input_remove(bb->conversation->watcher_id); - } - } + bonjour_jabber_close_conversation(data, l->data); g_slist_free(buddies); } } diff -r 24d035ad12cd -r be1c61b5f30d pidgin/gtkconv.c --- a/pidgin/gtkconv.c Thu Jun 07 07:32:06 2007 +0000 +++ b/pidgin/gtkconv.c Fri Jun 08 03:19:13 2007 +0000 @@ -1251,6 +1251,37 @@ } static void +menu_insert_link_cb(gpointer data, guint action, GtkWidget *widget) +{ + PidginWindow *win = data; + PidginConversation *gtkconv; + GtkIMHtmlToolbar *toolbar; + + gtkconv = pidgin_conv_window_get_active_gtkconv(win); + toolbar = GTK_IMHTMLTOOLBAR(gtkconv->toolbar); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toolbar->link), + !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->link))); +} + +static void +menu_insert_image_cb(gpointer data, guint action, GtkWidget *widget) +{ + PidginWindow *win = data; + PurpleConversation *conv; + PidginConversation *gtkconv; + GtkIMHtmlToolbar *toolbar; + + gtkconv = pidgin_conv_window_get_active_gtkconv(win); + conv = gtkconv->active_conv; + toolbar = GTK_IMHTMLTOOLBAR(gtkconv->toolbar); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toolbar->image), + !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->image))); +} + + +static void menu_alias_cb(gpointer data, guint action, GtkWidget *widget) { PidginWindow *win = data; @@ -2835,6 +2866,14 @@ { "/Conversation/sep3", NULL, NULL, 0, "", NULL }, + { N_("/Conversation/Insert Lin_k..."), NULL, menu_insert_link_cb, 0, + "", PIDGIN_STOCK_TOOLBAR_INSERT_LINK }, + { N_("/Conversation/Insert Imag_e..."), NULL, menu_insert_image_cb, 0, + "", PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE }, + + { "/Conversation/sep4", NULL, NULL, 0, "", NULL }, + + { N_("/Conversation/_Close"), NULL, menu_close_conv_cb, 0, "", GTK_STOCK_CLOSE }, @@ -3059,6 +3098,18 @@ gtk_item_factory_get_widget(win->menu.item_factory, N_("/Conversation/Remove...")); + /* --- */ + + win->menu.insert_link = + gtk_item_factory_get_widget(win->menu.item_factory, + N_("/Conversation/Insert Link...")); + + win->menu.insert_image = + gtk_item_factory_get_widget(win->menu.item_factory, + N_("/Conversation/Insert Image...")); + + /* --- */ + win->menu.logging = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Options/Enable Logging")); @@ -5936,6 +5987,8 @@ gtk_widget_hide(win->menu.add); } + gtk_widget_show(win->menu.insert_link); + gtk_widget_show(win->menu.insert_image); gtk_widget_show(win->menu.show_icon); } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { /* Show stuff that applies to Chats, hide stuff that applies to IMs */ @@ -5961,6 +6014,8 @@ gtk_widget_show(win->menu.remove); } + gtk_widget_show(win->menu.insert_link); + gtk_widget_show(win->menu.insert_image); } /* @@ -6002,6 +6057,8 @@ gtk_widget_set_sensitive(win->menu.add_pounce, TRUE); gtk_widget_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL)); gtk_widget_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL)); + gtk_widget_set_sensitive(win->menu.insert_link, (conv->features & PURPLE_CONNECTION_HTML)); + gtk_widget_set_sensitive(win->menu.insert_image, (prpl_info->options & OPT_PROTO_IM_IMAGE) && !(conv->features & PURPLE_CONNECTION_NO_IMAGES)); if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { @@ -6036,6 +6093,8 @@ gtk_widget_set_sensitive(win->menu.alias, FALSE); gtk_widget_set_sensitive(win->menu.add, FALSE); gtk_widget_set_sensitive(win->menu.remove, FALSE); + gtk_widget_set_sensitive(win->menu.insert_link, TRUE); + gtk_widget_set_sensitive(win->menu.insert_image, FALSE); } /* diff -r 24d035ad12cd -r be1c61b5f30d pidgin/gtkdialogs.h --- a/pidgin/gtkdialogs.h Thu Jun 07 07:32:06 2007 +0000 +++ b/pidgin/gtkdialogs.h Fri Jun 08 03:19:13 2007 +0000 @@ -36,10 +36,15 @@ void pidgin_dialogs_im_with_user(PurpleAccount *, const char *); void pidgin_dialogs_info(void); void pidgin_dialogs_log(void); + +/** + * @deprecated This function is no longer used and will be removed in + * Pidgin 3.0.0 unless there is sufficient demand to keep it. + */ void pidgin_dialogs_alias_contact(PurpleContact *); + void pidgin_dialogs_alias_buddy(PurpleBuddy *); void pidgin_dialogs_alias_chat(PurpleChat *); - void pidgin_dialogs_remove_buddy(PurpleBuddy *); void pidgin_dialogs_remove_group(PurpleGroup *); void pidgin_dialogs_remove_chat(PurpleChat *); diff -r 24d035ad12cd -r be1c61b5f30d pidgin/gtkrequest.c --- a/pidgin/gtkrequest.c Thu Jun 07 07:32:06 2007 +0000 +++ b/pidgin/gtkrequest.c Fri Jun 08 03:19:13 2007 +0000 @@ -323,7 +323,8 @@ /* Setup the dialog */ gtk_container_set_border_width(GTK_CONTAINER(dialog), PIDGIN_HIG_BORDER/2); gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER/2); - gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); + if (!multiline) + gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); gtk_dialog_set_default_response(GTK_DIALOG(dialog), 0); gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER); @@ -341,7 +342,7 @@ /* Vertical box */ vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER); - gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0); /* Descriptive label */ primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL; @@ -359,7 +360,7 @@ gtk_label_set_markup(GTK_LABEL(label), label_text); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); gtk_misc_set_alignment(GTK_MISC(label), 0, 0); - gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); g_free(label_text); diff -r 24d035ad12cd -r be1c61b5f30d pidgin/gtksavedstatuses.c --- a/pidgin/gtksavedstatuses.c Thu Jun 07 07:32:06 2007 +0000 +++ b/pidgin/gtksavedstatuses.c Fri Jun 08 03:19:13 2007 +0000 @@ -1088,7 +1088,6 @@ dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_role(GTK_WINDOW(win), "status"); gtk_window_set_title(GTK_WINDOW(win), _("Status")); - gtk_window_set_resizable(GTK_WINDOW(win), FALSE); gtk_container_set_border_width(GTK_CONTAINER(win), PIDGIN_HIG_BORDER); g_signal_connect(G_OBJECT(win), "delete_event", @@ -1137,7 +1136,7 @@ /* Status message */ hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); label = gtk_label_new_with_mnemonic(_("_Message:")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);