# HG changeset patch # User Sean Egan # Date 1187971126 0 # Node ID 41417f94afe9b878606c99aa43fdf0fc4a2b3ba8 # Parent 215c02a8ff884e618e081380da033fa09a9508f0# Parent fbdabdd3839aa2b4a42adf439e37f868c5b5f1c7 merge of '8d675a1883a0f1c7f3c08d9b12242cd3fc7bcaf9' and 'b1a0340ea0f3e2adf428695c63bf6f5c526b375f' diff -r 215c02a8ff88 -r 41417f94afe9 AUTHORS --- a/AUTHORS Tue Aug 21 15:10:03 2007 +0000 +++ b/AUTHORS Fri Aug 24 15:58:46 2007 +0000 @@ -22,7 +22,7 @@ Ka-Hing Cheung - Developer Sadrul Habib Chowdhury - Developer Mark 'KingAnt' Doliner - Developer -Christian 'ChipX86' Hammond - Developer & Webmaster +Casey Harkins - Developer Gary 'grim' Kramlich - Developer Richard 'rlaager' Laager - Developer Richard 'wabz' Nelson - Developer @@ -31,21 +31,16 @@ Etan 'deryni' Reisner - Developer Tim 'marv' Ringenbach - Developer Luke 'LSchiere' Schierer - Support -Megan 'Cae' Schneider (support/QA) +Megan 'Cae' Schneider - support/QA Evan Schoenberg - Developer +Kevin 'SimGuy' Stange - Developer & Webmaster Stu 'nosnilmot' Tomlinson - Developer Nathan 'faceprint' Walp - Developer Crazy Patch Writers: ------------------- John 'rekkanoryo' Bailey -Felipe 'shx' Contreras -Decklin Foster -Casey Harkins Peter 'Bleeter' Lawler -Robert 'Robot101' McQueen -Benjamin Miller -Kevin 'SimGuy' Stange Retired Developers: ------------------ @@ -53,11 +48,19 @@ Jim Duchek - maintainer Rob Flynn - maintainer Adam Fritzler - libfaim maintainer +Christian 'ChipX86' Hammond - Developer & Webmaster Syd Logan - hacker and designated driver [lazy bum] Jim Seymour - XMPP developer Mark Spencer - original author Eric Warmenhoven - lead developer +Retired Crazy Patch Writers: +--------------------------- +Felipe 'shx' Contreras +Decklin Foster +Robert 'Robot101' McQueen +Benjamin Miller + Artists: ------- Hylke Bons - Icons diff -r 215c02a8ff88 -r 41417f94afe9 COPYRIGHT --- a/COPYRIGHT Tue Aug 21 15:10:03 2007 +0000 +++ b/COPYRIGHT Fri Aug 24 15:58:46 2007 +0000 @@ -214,6 +214,7 @@ Nicolas Lichtmaier Wesley Lin Artem Litvinovich +Josh Littlefield Syd Logan Lokheed Norberto Lopes diff -r 215c02a8ff88 -r 41417f94afe9 ChangeLog.API --- a/ChangeLog.API Tue Aug 21 15:10:03 2007 +0000 +++ b/ChangeLog.API Fri Aug 24 15:58:46 2007 +0000 @@ -1,5 +1,11 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +Version 2.2.0 (??/??/????): + Pidgin: + Added: + * pidgin_set_accessible_relations, sets up label-for and labelled-by + ATK relations (broken out from pidgin_set_accessible_label) + Version 2.1.1 (08/20/2007): libpurple: Changed: diff -r 215c02a8ff88 -r 41417f94afe9 configure.ac --- a/configure.ac Tue Aug 21 15:10:03 2007 +0000 +++ b/configure.ac Fri Aug 24 15:58:46 2007 +0000 @@ -43,18 +43,18 @@ # # Make sure to update finch/libgnt/configure.ac with libgnt version changes. # -m4_define([purple_lt_current], [1]) +m4_define([purple_lt_current], [2]) m4_define([purple_major_version], [2]) -m4_define([purple_minor_version], [1]) -m4_define([purple_micro_version], [2]) +m4_define([purple_minor_version], [2]) +m4_define([purple_micro_version], [0]) m4_define([purple_version_suffix], [devel]) m4_define([purple_version], [purple_major_version.purple_minor_version.purple_micro_version]) m4_define([purple_display_version], purple_version[]m4_ifdef([purple_version_suffix],[purple_version_suffix])) -m4_define([gnt_lt_current], [1]) +m4_define([gnt_lt_current], [2]) m4_define([gnt_major_version], [2]) -m4_define([gnt_minor_version], [1]) +m4_define([gnt_minor_version], [2]) m4_define([gnt_micro_version], [0]) m4_define([gnt_version_suffix], [devel]) m4_define([gnt_version], @@ -2210,6 +2210,7 @@ finch/Makefile finch/libgnt/Makefile finch/libgnt/gnt.pc + finch/libgnt/pygnt/Makefile finch/libgnt/wms/Makefile finch/plugins/Makefile po/Makefile.in diff -r 215c02a8ff88 -r 41417f94afe9 finch/gntaccount.c --- a/finch/gntaccount.c Tue Aug 21 15:10:03 2007 +0000 +++ b/finch/gntaccount.c Fri Aug 24 15:58:46 2007 +0000 @@ -222,6 +222,11 @@ /* XXX: Proxy options */ + if (accounts.window && accounts.tree) { + gnt_tree_set_selected(GNT_TREE(accounts.tree), account); + gnt_box_give_focus_to_child(GNT_BOX(accounts.window), accounts.tree); + } + gnt_widget_destroy(dialog->window); } diff -r 215c02a8ff88 -r 41417f94afe9 finch/gntblist.c --- a/finch/gntblist.c Tue Aug 21 15:10:03 2007 +0000 +++ b/finch/gntblist.c Fri Aug 24 15:58:46 2007 +0000 @@ -2139,20 +2139,29 @@ } } -static void -account_signed_on_cb(PurpleConnection *pc, gpointer null) +static gboolean +auto_join_chats(gpointer data) { PurpleBlistNode *node; + PurpleConnection *pc = data; + PurpleAccount *account = purple_connection_get_account(pc); for (node = purple_blist_get_root(); node; node = purple_blist_node_next(node, FALSE)) { if (PURPLE_BLIST_NODE_IS_CHAT(node)) { PurpleChat *chat = (PurpleChat*)node; - if (chat->account == purple_connection_get_account(pc) && + if (chat->account == account && purple_blist_node_get_bool(node, "gnt-autojoin")) serv_join_chat(purple_account_get_connection(chat->account), chat->components); } } + return FALSE; +} + +static void +account_signed_on_cb(PurpleConnection *gc, gpointer null) +{ + g_idle_add(auto_join_chats, gc); } static void toggle_pref_cb(GntMenuItem *item, gpointer n) diff -r 215c02a8ff88 -r 41417f94afe9 finch/gntconv.c --- a/finch/gntconv.c Tue Aug 21 15:10:03 2007 +0000 +++ b/finch/gntconv.c Fri Aug 24 15:58:46 2007 +0000 @@ -142,6 +142,11 @@ } g_free(error); } + else if (!purple_account_is_connected(ggconv->active_conv->account)) + { + purple_conversation_write(ggconv->active_conv, "", _("Message was not sent, because you are not signed on."), + PURPLE_MESSAGE_ERROR | PURPLE_MESSAGE_NO_LOG, time(NULL)); + } else { char *escape = g_markup_escape_text(text, -1); diff -r 215c02a8ff88 -r 41417f94afe9 finch/gntft.c --- a/finch/gntft.c Tue Aug 21 15:10:03 2007 +0000 +++ b/finch/gntft.c Fri Aug 24 15:58:46 2007 +0000 @@ -193,6 +193,8 @@ g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(finch_xfer_dialog_destroy), NULL); gnt_box_set_toplevel(GNT_BOX(window), TRUE); gnt_box_set_title(GNT_BOX(window), _("File Transfers")); + gnt_box_set_fill(GNT_BOX(window), TRUE); + gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID); xfer_dialog->tree = tree = gnt_tree_new_with_columns(NUM_COLUMNS); gnt_tree_set_column_titles(GNT_TREE(tree), _("Progress"), _("Filename"), _("Size"), _("Speed"), _("Remaining"), _("Status")); @@ -219,7 +221,7 @@ G_CALLBACK(toggle_clear_finished_cb), NULL); gnt_box_add_widget(GNT_BOX(window), checkbox); - bbox = gnt_hbox_new(TRUE); + bbox = gnt_hbox_new(FALSE); xfer_dialog->remove_button = button = gnt_button_new(_("Remove")); g_signal_connect(G_OBJECT(button), "activate", @@ -425,8 +427,11 @@ g_free(remaining_str); g_free(kbsec); if (purple_xfer_is_completed(xfer)) { + char *msg = g_strdup_printf(_("The file was saved as %s."), purple_xfer_get_local_filename(xfer)); gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, _("Finished")); gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_REMAINING, _("Finished")); + purple_xfer_conversation_write(xfer, msg, FALSE); + g_free(msg); } else { gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, _("Transferring")); } diff -r 215c02a8ff88 -r 41417f94afe9 finch/gntpounce.c --- a/finch/gntpounce.c Tue Aug 21 15:10:03 2007 +0000 +++ b/finch/gntpounce.c Fri Aug 24 15:58:46 2007 +0000 @@ -452,7 +452,7 @@ gnt_box_add_widget(GNT_BOX(window), gnt_line_new(FALSE)); /* Now the button box! */ - bbox = gnt_hbox_new(TRUE); + bbox = gnt_hbox_new(FALSE); /* Cancel button */ button = gnt_button_new(_("Cancel")); @@ -613,6 +613,12 @@ static void pounces_manager_add_cb(GntButton *button, gpointer user_data) { + if (purple_accounts_get_all() == NULL) { + purple_notify_error(NULL, _("Cannot create pounce"), + _("You do not have any accounts."), + _("You must create an account first before you can create a pounce.")); + return; + } finch_pounce_editor_show(NULL, NULL, NULL); } @@ -622,7 +628,8 @@ { PouncesManager *dialog = user_data; PurplePounce *pounce = gnt_tree_get_selection_data(GNT_TREE(dialog->tree)); - finch_pounce_editor_show(NULL, NULL, pounce); + if (pounce) + finch_pounce_editor_show(NULL, NULL, pounce); } static void @@ -645,6 +652,9 @@ char *buf; pounce = (PurplePounce *)gnt_tree_get_selection_data(GNT_TREE(dialog->tree)); + if (pounce == NULL) + return; + account = purple_pounce_get_pouncer(pounce); pouncer = purple_account_get_username(account); pouncee = purple_pounce_get_pouncee(pounce); @@ -696,7 +706,7 @@ gnt_box_add_widget(GNT_BOX(win), tree); /* Button box. */ - bbox = gnt_hbox_new(TRUE); + bbox = gnt_hbox_new(FALSE); /* Add button */ button = gnt_button_new(_("Add")); diff -r 215c02a8ff88 -r 41417f94afe9 finch/gntsound.c --- a/finch/gntsound.c Tue Aug 21 15:10:03 2007 +0000 +++ b/finch/gntsound.c Fri Aug 24 15:58:46 2007 +0000 @@ -409,14 +409,14 @@ GError *err = NULL; switch (GST_MESSAGE_TYPE (msg)) { - case GST_MESSAGE_EOS: - gst_element_set_state(play, GST_STATE_NULL); - gst_object_unref(GST_OBJECT(play)); - break; case GST_MESSAGE_ERROR: gst_message_parse_error(msg, &err, NULL); purple_debug_error("gstreamer", "%s\n", err->message); g_error_free(err); + /* fall-through and clean up */ + case GST_MESSAGE_EOS: + gst_element_set_state(play, GST_STATE_NULL); + gst_object_unref(GST_OBJECT(play)); break; case GST_MESSAGE_WARNING: gst_message_parse_warning(msg, &err, NULL); @@ -670,28 +670,34 @@ { PurpleSoundEventID id = GPOINTER_TO_INT(gnt_tree_get_selection_data(GNT_TREE(pref_dialog->events))); FinchSoundEvent * event = &sounds[id]; - char *enabled, *file, *tmpfile; + char *enabled, *file, *tmpfile, *volpref; gboolean temp_value; + int volume; enabled = g_strdup_printf(FINCH_PREFS_ROOT "/sound/profiles/%s/enabled/%s", finch_sound_get_active_profile(), event->pref); file = g_strdup_printf(FINCH_PREFS_ROOT "/sound/profiles/%s/file/%s", finch_sound_get_active_profile(), event->pref); + volpref = g_strdup(make_pref("/volume")); temp_value = purple_prefs_get_bool(enabled); tmpfile = g_strdup(purple_prefs_get_string(file)); + volume = purple_prefs_get_int(volpref); purple_prefs_set_string(file, event->file); if (!temp_value) purple_prefs_set_bool(enabled, TRUE); + purple_prefs_set_int(volpref, gnt_slider_get_value(GNT_SLIDER(pref_dialog->volume))); purple_sound_play_event(id, NULL); if (!temp_value) purple_prefs_set_bool(enabled, FALSE); purple_prefs_set_string(file, tmpfile); + purple_prefs_set_int(volpref, volume); g_free(enabled); g_free(file); g_free(tmpfile); + g_free(volpref); } static void diff -r 215c02a8ff88 -r 41417f94afe9 finch/gntstatus.c --- a/finch/gntstatus.c Tue Aug 21 15:10:03 2007 +0000 +++ b/finch/gntstatus.c Fri Aug 24 15:58:46 2007 +0000 @@ -299,6 +299,7 @@ { purple_notify_error(edit, _("Error"), _("Invalid title"), _("Please enter a non-empty title for the status.")); + gnt_box_give_focus_to_child(GNT_BOX(edit->window), edit->title); return; } @@ -307,6 +308,7 @@ { purple_notify_error(edit, _("Error"), _("Duplicate title"), _("Please enter a different title for the status.")); + gnt_box_give_focus_to_child(GNT_BOX(edit->window), edit->title); return; } @@ -447,6 +449,7 @@ sub->window = window = gnt_vbox_new(FALSE); gnt_box_set_toplevel(GNT_BOX(window), TRUE); gnt_box_set_title(GNT_BOX(window), _("Substatus")); /* XXX: a better title */ + gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID); box = gnt_hbox_new(FALSE); gnt_box_add_widget(GNT_BOX(box), gnt_label_new(_("Account:"))); @@ -523,7 +526,7 @@ gnt_box_set_toplevel(GNT_BOX(window), TRUE); gnt_box_set_title(GNT_BOX(window), _("Edit Status")); gnt_box_set_fill(GNT_BOX(window), TRUE); - gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_LEFT); + gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID); gnt_box_set_pad(GNT_BOX(window), 0); edits = g_list_append(edits, edit); diff -r 215c02a8ff88 -r 41417f94afe9 finch/libgnt/configure.ac --- a/finch/libgnt/configure.ac Tue Aug 21 15:10:03 2007 +0000 +++ b/finch/libgnt/configure.ac Fri Aug 24 15:58:46 2007 +0000 @@ -24,9 +24,9 @@ # Make sure to update ../../configure.ac with libgnt version changes. # -m4_define([gnt_lt_current], [1]) +m4_define([gnt_lt_current], [2]) m4_define([gnt_major_version], [2]) -m4_define([gnt_minor_version], [1]) +m4_define([gnt_minor_version], [2]) m4_define([gnt_micro_version], [0]) m4_define([gnt_version_suffix], [devel]) m4_define([gnt_version], diff -r 215c02a8ff88 -r 41417f94afe9 finch/libgnt/gnt.h --- a/finch/libgnt/gnt.h Tue Aug 21 15:10:03 2007 +0000 +++ b/finch/libgnt/gnt.h Fri Aug 24 15:58:46 2007 +0000 @@ -37,6 +37,15 @@ #include "gntkeys.h" /** + * Get things to compile in Glib < 2.8 + */ +#if !GLIB_CHECK_VERSION(2,8,0) + #define G_PARAM_STATIC_NAME G_PARAM_PRIVATE + #define G_PARAM_STATIC_NICK G_PARAM_PRIVATE + #define G_PARAM_STATIC_BLURB G_PARAM_PRIVATE +#endif + +/** * */ void gnt_init(void); diff -r 215c02a8ff88 -r 41417f94afe9 finch/libgnt/gntcolors.c --- a/finch/libgnt/gntcolors.c Tue Aug 21 15:10:03 2007 +0000 +++ b/finch/libgnt/gntcolors.c Fri Aug 24 15:58:46 2007 +0000 @@ -133,6 +133,7 @@ restore_colors(); } +#if GLIB_CHECK_VERSION(2,6,0) static int get_color(char *key) { @@ -164,7 +165,6 @@ return color; } -#if GLIB_CHECK_VERSION(2,6,0) void gnt_colors_parse(GKeyFile *kfile) { GError *error = NULL; diff -r 215c02a8ff88 -r 41417f94afe9 finch/libgnt/gntfilesel.c --- a/finch/libgnt/gntfilesel.c Tue Aug 21 15:10:03 2007 +0000 +++ b/finch/libgnt/gntfilesel.c Fri Aug 24 15:58:46 2007 +0000 @@ -200,7 +200,7 @@ const char *tmp; tmp = sel->suggest ? sel->suggest : (const char*)gnt_tree_get_selection_data(sel->dirsonly ? GNT_TREE(sel->dirs) : GNT_TREE(sel->files)); - old = g_strdup_printf("%s%s%s", sel->current, sel->current[1] ? G_DIR_SEPARATOR_S : "", tmp ? tmp : ""); + old = g_strdup_printf("%s%s%s", SAFE(sel->current), SAFE(sel->current)[1] ? G_DIR_SEPARATOR_S : "", tmp ? tmp : ""); gnt_entry_set_text(GNT_ENTRY(sel->location), old); g_free(old); } diff -r 215c02a8ff88 -r 41417f94afe9 finch/libgnt/gntstyle.c --- a/finch/libgnt/gntstyle.c Tue Aug 21 15:10:03 2007 +0000 +++ b/finch/libgnt/gntstyle.c Fri Aug 24 15:58:46 2007 +0000 @@ -55,6 +55,8 @@ if (!group) group = "general"; return g_key_file_get_value(gkfile, group, key, NULL); +#else + return NULL; #endif } @@ -93,6 +95,7 @@ return def; } +#if GLIB_CHECK_VERSION(2,6,0) static void refine(char *text) { @@ -133,6 +136,7 @@ { return (char *)gnt_key_translate(key); } +#endif void gnt_style_read_workspaces(GntWM *wm) { diff -r 215c02a8ff88 -r 41417f94afe9 finch/libgnt/gnttextview.c --- a/finch/libgnt/gnttextview.c Tue Aug 21 15:10:03 2007 +0000 +++ b/finch/libgnt/gnttextview.c Fri Aug 24 15:58:46 2007 +0000 @@ -549,7 +549,8 @@ if ((end = strchr(start, '\r')) != NULL || (end = strchr(start, '\n')) != NULL) { len = gnt_util_onscreen_width(start, end - has_scroll); - if (len >= widget->priv.width - line->length - has_scroll) { + if (widget->priv.width > 0 && + len >= widget->priv.width - line->length - has_scroll) { end = NULL; } } diff -r 215c02a8ff88 -r 41417f94afe9 finch/libgnt/gnttree.c --- a/finch/libgnt/gnttree.c Tue Aug 21 15:10:03 2007 +0000 +++ b/finch/libgnt/gnttree.c Fri Aug 24 15:58:46 2007 +0000 @@ -985,11 +985,7 @@ g_param_spec_int("columns", "Columns", "Number of columns in the tree.", 1, G_MAXINT, 1, -#if GLIB_CHECK_VERSION(2,8,0) G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB -#else - G_PARAM_READWRITE|G_PARAM_PRIVATE -#endif ) ); diff -r 215c02a8ff88 -r 41417f94afe9 finch/libgnt/gntutils.c --- a/finch/libgnt/gntutils.c Tue Aug 21 15:10:03 2007 +0000 +++ b/finch/libgnt/gntutils.c Fri Aug 24 15:58:46 2007 +0000 @@ -376,6 +376,101 @@ #endif } +#ifndef NO_LIBXML +static void +util_parse_html_to_tv(xmlNode *node, GntTextView *tv, GntTextFormatFlags flag) +{ + const char *name; + char *content; + xmlNode *ch; + gboolean processed = FALSE; + char *url = NULL; + gboolean insert_nl_s = FALSE, insert_nl_e = FALSE; + + if (node == NULL || node->name == NULL || node->type != XML_ELEMENT_NODE) + return; + + name = (char*)node->name; + if (g_ascii_strcasecmp(name, "b") == 0 || + g_ascii_strcasecmp(name, "strong") == 0 || + g_ascii_strcasecmp(name, "i") == 0 || + g_ascii_strcasecmp(name, "blockquote") == 0) { + flag |= GNT_TEXT_FLAG_BOLD; + } else if (g_ascii_strcasecmp(name, "u") == 0) { + flag |= GNT_TEXT_FLAG_UNDERLINE; + } else if (g_ascii_strcasecmp(name, "br") == 0) { + insert_nl_e = TRUE; + } else if (g_ascii_strcasecmp(name, "a") == 0) { + flag |= GNT_TEXT_FLAG_UNDERLINE; + url = (char *)xmlGetProp(node, (xmlChar*)"href"); + } else if (g_ascii_strcasecmp(name, "h1") == 0 || + g_ascii_strcasecmp(name, "h2") == 0 || + g_ascii_strcasecmp(name, "h3") == 0 || + g_ascii_strcasecmp(name, "h4") == 0 || + g_ascii_strcasecmp(name, "h5") == 0 || + g_ascii_strcasecmp(name, "h6") == 0) { + insert_nl_s = TRUE; + insert_nl_e = TRUE; + } else if (g_ascii_strcasecmp(name, "title") == 0) { + insert_nl_s = TRUE; + insert_nl_e = TRUE; + flag |= GNT_TEXT_FLAG_BOLD | GNT_TEXT_FLAG_UNDERLINE; + } else { + /* XXX: Process other possible tags */ + } + + if (insert_nl_s) + gnt_text_view_append_text_with_flags(tv, "\n", flag); + + for (ch = node->children; ch; ch = ch->next) { + if (ch->type == XML_ELEMENT_NODE) { + processed = TRUE; + util_parse_html_to_tv(ch, tv, flag); + } + } + + if (!processed) { + content = (char*)xmlNodeGetContent(node); + gnt_text_view_append_text_with_flags(tv, content, flag); + xmlFree(content); + } + + if (url) { + char *href = g_strdup_printf(" (%s)", url); + gnt_text_view_append_text_with_flags(tv, href, flag); + g_free(href); + xmlFree(url); + } + + if (insert_nl_e) + gnt_text_view_append_text_with_flags(tv, "\n", flag); +} +#endif + +gboolean gnt_util_parse_xhtml_to_textview(const char *string, GntTextView *tv) +{ +#ifdef NO_LIBXML + return FALSE; +#else + xmlParserCtxtPtr ctxt; + xmlDocPtr doc; + xmlNodePtr node; + GntTextFormatFlags flag = GNT_TEXT_FLAG_NORMAL; + gboolean ret = FALSE; + + ctxt = xmlNewParserCtxt(); + doc = xmlCtxtReadDoc(ctxt, (xmlChar*)string, NULL, NULL, XML_PARSE_NOBLANKS | XML_PARSE_RECOVER); + if (doc) { + node = xmlDocGetRootElement(doc); + util_parse_html_to_tv(node, tv, flag); + xmlFreeDoc(doc); + ret = TRUE; + } + xmlCleanupParser(); + return ret; +#endif +} + /* Setup trigger widget */ typedef struct { char *text; @@ -408,4 +503,3 @@ g_signal_connect(G_OBJECT(wid), "key_pressed", G_CALLBACK(key_pressed), tb); g_signal_connect_swapped(G_OBJECT(button), "destroy", G_CALLBACK(free_trigger_button), tb); } - diff -r 215c02a8ff88 -r 41417f94afe9 finch/libgnt/gntutils.h --- a/finch/libgnt/gntutils.h Tue Aug 21 15:10:03 2007 +0000 +++ b/finch/libgnt/gntutils.h Fri Aug 24 15:58:46 2007 +0000 @@ -27,6 +27,7 @@ #include #include "gnt.h" +#include "gnttextview.h" #include "gntwidget.h" typedef gpointer (*GDupFunc)(gconstpointer data); @@ -132,6 +133,16 @@ void gnt_util_parse_widgets(const char *string, int num, ...); /** + * Parse an XHTML string and add it in a GntTextView with + * appropriate text flags. + * + * @param string The XHTML string + * @param tv The GntTextView + * @return @c TRUE if the string was added to the textview properly, @c FALSE otherwise. + */ +gboolean gnt_util_parse_xhtml_to_textview(const char *string, GntTextView *tv); + +/** * Make some keypress activate a button when some key is pressed with 'wid' in focus. * * @param widget The widget diff -r 215c02a8ff88 -r 41417f94afe9 finch/libgnt/gntwm.c --- a/finch/libgnt/gntwm.c Tue Aug 21 15:10:03 2007 +0000 +++ b/finch/libgnt/gntwm.c Fri Aug 24 15:58:46 2007 +0000 @@ -738,7 +738,7 @@ print = ch; #ifndef NO_WIDECHAR if (wch.chars[0] > 255) { - snprintf(unicode, sizeof(unicode), "&#x%x;", wch.chars[0]); + snprintf(unicode, sizeof(unicode), "&#x%x;", (unsigned int)wch.chars[0]); print = unicode; } #endif diff -r 215c02a8ff88 -r 41417f94afe9 finch/libgnt/test/tv.c --- a/finch/libgnt/test/tv.c Tue Aug 21 15:10:03 2007 +0000 +++ b/finch/libgnt/test/tv.c Fri Aug 24 15:58:46 2007 +0000 @@ -5,6 +5,7 @@ #include "gntbox.h" #include "gntentry.h" #include "gnttextview.h" +#include "gntutils.h" static gboolean key_pressed(GntWidget *w, const char *key, GntWidget *view) @@ -117,6 +118,8 @@ gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "plugins: ", GNT_TEXT_FLAG_BOLD); gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "this is the 4th line\n", GNT_TEXT_FLAG_NORMAL); + gnt_util_parse_xhtml_to_textview("

Ohoy hoy!!

I think this is going to

WORK!!! check this out!!

", GNT_TEXT_VIEW(view)); + #ifdef STANDALONE gnt_main(); diff -r 215c02a8ff88 -r 41417f94afe9 libpurple/blist.c --- a/libpurple/blist.c Tue Aug 21 15:10:03 2007 +0000 +++ b/libpurple/blist.c Fri Aug 24 15:58:46 2007 +0000 @@ -1190,6 +1190,9 @@ group = purple_group_new(_("Chats")); purple_blist_add_group(group, purple_blist_get_last_sibling(purplebuddylist->root)); + } else { + /* Fail if tried to add buddy to a group that isn't on the blist. #2752. */ + g_return_if_fail(purple_find_group(group->name)); } } else { group = (PurpleGroup*)node->parent; @@ -1284,6 +1287,10 @@ g = (PurpleGroup *)((PurpleBlistNode *)c)->parent; } else { if (group) { + /* Fail if trying to add buddy to a group that is not on the buddy list. + * Fix for #2752. */ + g_return_if_fail(purple_find_group(group->name)); + g = group; } else { g = purple_group_new(_("Buddies")); diff -r 215c02a8ff88 -r 41417f94afe9 libpurple/idle.c --- a/libpurple/idle.c Tue Aug 21 15:10:03 2007 +0000 +++ b/libpurple/idle.c Fri Aug 24 15:58:46 2007 +0000 @@ -163,8 +163,8 @@ { if (!no_away) { + no_away = TRUE; purple_savedstatus_set_idleaway(FALSE); - no_away = TRUE; } time_until_next_idle_event = 0; return; diff -r 215c02a8ff88 -r 41417f94afe9 libpurple/protocols/bonjour/jabber.c --- a/libpurple/protocols/bonjour/jabber.c Tue Aug 21 15:10:03 2007 +0000 +++ b/libpurple/protocols/bonjour/jabber.c Fri Aug 24 15:58:46 2007 +0000 @@ -82,8 +82,8 @@ BonjourJabberConversation *bconv = g_new0(BonjourJabberConversation, 1); bconv->socket = -1; bconv->tx_buf = purple_circ_buffer_new(512); - bconv->tx_handler = -1; - bconv->rx_handler = -1; + bconv->tx_handler = 0; + bconv->rx_handler = 0; return bconv; } @@ -234,7 +234,7 @@ if (writelen == 0) { purple_input_remove(bconv->tx_handler); - bconv->tx_handler = -1; + bconv->tx_handler = 0; return; } @@ -272,7 +272,7 @@ BonjourJabberConversation *bconv = bb->conversation; /* If we're not ready to actually send, append it to the buffer */ - if (bconv->tx_handler != -1 + if (bconv->tx_handler != 0 || bconv->connect_data != NULL || !bconv->sent_stream_start || !bconv->recv_stream_start @@ -304,7 +304,7 @@ } if (ret < len) { - if (bconv->tx_handler == -1) + if (bconv->tx_handler == 0) bconv->tx_handler = purple_input_add(bconv->socket, PURPLE_INPUT_WRITE, _send_data_write_cb, pb); purple_circ_buffer_append(bconv->tx_buf, message + ret, len - ret); @@ -455,7 +455,7 @@ /* Stream started; process the send buffer if there is one */ purple_input_remove(bconv->tx_handler); - bconv->tx_handler= -1; + bconv->tx_handler= 0; bconv->sent_stream_start = TRUE; bonjour_jabber_stream_started(pb); @@ -779,7 +779,7 @@ /* TODO: We're really supposed to wait for "" before closing the socket */ close(bconv->socket); } - if (bconv->rx_handler != -1) + if (bconv->rx_handler != 0) purple_input_remove(bconv->rx_handler); if (bconv->tx_handler > 0) purple_input_remove(bconv->tx_handler); diff -r 215c02a8ff88 -r 41417f94afe9 libpurple/protocols/bonjour/mdns_win32.c --- a/libpurple/protocols/bonjour/mdns_win32.c Tue Aug 21 15:10:03 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_win32.c Fri Aug 24 15:58:46 2007 +0000 @@ -99,7 +99,7 @@ /* We've got what we need; stop listening */ purple_input_remove(idata->null_query_handler); - idata->null_query_handler = -1; + idata->null_query_handler = 0; DNSServiceRefDeallocate(idata->null_query); idata->null_query = NULL; } diff -r 215c02a8ff88 -r 41417f94afe9 libpurple/protocols/msn/servconn.c --- a/libpurple/protocols/msn/servconn.c Tue Aug 21 15:10:03 2007 +0000 +++ b/libpurple/protocols/msn/servconn.c Fri Aug 24 15:58:46 2007 +0000 @@ -51,7 +51,7 @@ servconn->num = session->servconns_count++; servconn->tx_buf = purple_circ_buffer_new(MSN_BUF_LEN); - servconn->tx_handler = -1; + servconn->tx_handler = 0; return servconn; } @@ -303,7 +303,7 @@ if (writelen == 0) { purple_input_remove(servconn->tx_handler); - servconn->tx_handler = -1; + servconn->tx_handler = 0; return; } @@ -328,7 +328,7 @@ if (!servconn->session->http_method) { - if (servconn->tx_handler == -1) { + if (servconn->tx_handler == 0) { switch (servconn->type) { case MSN_SERVCONN_NS: @@ -353,7 +353,7 @@ if (ret < 0 && errno == EAGAIN) ret = 0; if (ret >= 0 && ret < len) { - if (servconn->tx_handler == -1) + if (servconn->tx_handler == 0) servconn->tx_handler = purple_input_add( servconn->fd, PURPLE_INPUT_WRITE, servconn_write_cb, servconn); diff -r 215c02a8ff88 -r 41417f94afe9 libpurple/protocols/myspace/CHANGES --- a/libpurple/protocols/myspace/CHANGES Tue Aug 21 15:10:03 2007 +0000 +++ b/libpurple/protocols/myspace/CHANGES Fri Aug 24 15:58:46 2007 +0000 @@ -1,3 +1,28 @@ +2007-08-23 Jeff Connelly - 0.16 +* Add option to add all friends from myspace.com to your buddy list (#2660) +* If a user doesn't have a picture, don't display an icon (instead of + displaying MySpace's "no photo" icon) +* Fix #2725, a common crash related to buddy icon data +* Fix #2752, which led to duplicate groups +* Fix #2720, crash/disconnect when adding a buddy that doesn't exist + (You'll now receive an error when looking up invalid usernames). + +2007-08-22 Jeff Connelly - 0.15 +* Incomplete implementation of adding friends from myspace.com. +* Change msim_msg_get() to start at the given node instead of the beginning. +* Add msim_msg_get_*_from_element() to access data in MsimMessagElement *'s. +* Use MsimMessage dictionaries everywhere in incoming messages, instead of + the old GHashTable method. Dictionary type is now fully implemented. +* Add functions to loop over MsimMessages. +* Link to myspace.com profile in Get Info. +* Conditionally use my proposed attention API if defined. +* Propagate to im.pidgin.pidgin branch for 2.1.2. +* GSoC ended on 2007-08-20. The code in this release hasn't changed since + then. I did, however, bump the version number to 0.15 to distinguish this + release from the previous one. But there were no code changes. I updated + the text files, too. +* Note: msimprpl will continue to be developed as time permits. + 2007-08-12 Jeff Connelly - 0.14 * Full emoticon support (except no difference between nerd and geek emoticons), thanks to a number of new icons from Hylke Bons. diff -r 215c02a8ff88 -r 41417f94afe9 libpurple/protocols/myspace/README --- a/libpurple/protocols/myspace/README Tue Aug 21 15:10:03 2007 +0000 +++ b/libpurple/protocols/myspace/README Fri Aug 24 15:58:46 2007 +0000 @@ -1,4 +1,4 @@ -MySpaceIM Protocol Plugin by Jeff Connelly 20070807 +MySpaceIM Protocol Plugin for Libpurple by Jeff Connelly 20070807 Greetings. This package contains a plugin for libpurple (as used in @@ -6,7 +6,7 @@ network and send/receive messages. Functionality is only basic as of yet, and this code should be considered alpha quality. -This code is being developed under Google Summer of Code 2007. +This code was initially developed under Google Summer of Code 2007. For features and TODO, see http://developer.pidgin.im/wiki/MySpaceIM @@ -28,7 +28,5 @@ Enjoy, -Jeff Connelly -California Polytechnic State University at San Luis Obispo -myspaceim@xyzzy.cjb.net -jeff2@soc.pidgin.im +msimprpl@xyzzy.cjb.net diff -r 215c02a8ff88 -r 41417f94afe9 libpurple/protocols/myspace/myspace.c --- a/libpurple/protocols/myspace/myspace.c Tue Aug 21 15:10:03 2007 +0000 +++ b/libpurple/protocols/myspace/myspace.c Fri Aug 24 15:58:46 2007 +0000 @@ -1669,8 +1669,8 @@ * by Alexandr Shutko, who maintains OSCAR protocol documentation). */ purple_debug_info("msim", "Unrecognized data on account for %s\n", - session->account->username ? session->account->username - : "(NULL)"); + (session && session->account && session->account->username) ? + session->account->username : "(NULL)"); if (note) { purple_debug_info("msim", "(Note: %s)\n", note); } @@ -1784,7 +1784,7 @@ return rc; } -/* Process an incoming media (buddy icon) message. */ +/* Process an incoming media (message background?) message. */ static gboolean msim_incoming_media(MsimSession *session, MsimMessage *msg) { @@ -2656,11 +2656,18 @@ purple_debug_info("msim_downloaded_buddy_icon", "Downloaded %d bytes\n", len); + if (!url_text) { + purple_debug_info("msim_downloaded_buddy_icon", + "failed to download icon for %s", + user->buddy->name); + return; + } + purple_buddy_icons_set_for_user(user->buddy->account, user->buddy->name, - (gchar *)url_text, len, - /* Use URL itself as buddy icon "checksum" */ - user->image_url); + g_memdup((gchar *)url_text, len), len, + /* Use URL itself as buddy icon "checksum" (TODO: ETag) */ + user->image_url); /* checksum */ } /** Store a field of information about a buddy. */ @@ -2696,6 +2703,15 @@ const gchar *previous_url; user->image_url = g_strdup(value_str); + + /* Instead of showing 'no photo' picture, show nothing. */ + if (!strcmp(user->image_url, "http://x.myspace.com/images/no_pic.gif")) + { + purple_buddy_icons_set_for_user(user->buddy->account, + user->buddy->name, + NULL, 0, NULL); + return; + } previous_url = purple_buddy_icons_get_checksum_for_user(user->buddy); @@ -2703,6 +2719,9 @@ if (!previous_url || strcmp(previous_url, user->image_url)) { purple_util_fetch_url(user->image_url, TRUE, NULL, TRUE, msim_downloaded_buddy_icon, (gpointer)user); } + } else if (!strcmp(key_str, "LastImageUpdated")) { + /* TODO: use somewhere */ + user->last_image_updated = atol(value_str); } else if (!strcmp(key_str, "Headline")) { user->headline = g_strdup(value_str); } else { @@ -3207,7 +3226,7 @@ msim_postprocess_outgoing_cb(MsimSession *session, MsimMessage *userinfo, gpointer data) { - gchar *uid_field_name, *uid_before; + gchar *uid_field_name, *uid_before, *username; guint uid; MsimMessage *msg, *body; @@ -3222,6 +3241,19 @@ uid = msim_msg_get_integer(body, "UserID"); msim_msg_free(body); + username = msim_msg_get_string(msg, "_username"); + + if (!uid) { + gchar *msg; + + msg = g_strdup_printf(_("No such user: %s"), username); + purple_notify_error(NULL, NULL, _("User lookup"), msg); + g_free(msg); + g_free(username); + //msim_msg_free(msg); + return; + } + uid_field_name = msim_msg_get_string(msg, "_uid_field_name"); uid_before = msim_msg_get_string(msg, "_uid_before"); @@ -3238,6 +3270,7 @@ */ g_free(uid_field_name); g_free(uid_before); + g_free(username); //msim_msg_free(msg); } @@ -3908,6 +3941,8 @@ group_name = msim_msg_get_string(contact_info, "GroupName"); if (group_name) { group = purple_group_new(group_name); + purple_debug_info("msim_add_contact_from_server_cb", + "adding to GroupName: %s\n", group_name); g_free(group_name); } else { group = purple_group_new(_("IM Friends")); @@ -3916,13 +3951,17 @@ /* 2. Get or create buddy */ buddy = purple_find_buddy(session->account, username); if (!buddy) { + purple_debug_info("msim_add_contact_from_server_cb", + "creating new buddy: %s\n", username); buddy = purple_buddy_new(session->account, username, NULL); } + /* Add group to beginning. See #2752. */ + purple_blist_add_group(group, NULL); + /* TODO: use 'Position' in contact_info to take into account where buddy is */ purple_blist_add_buddy(buddy, NULL, group, NULL /* insertion point */); - /* 3. Update buddy information */ user = msim_get_user_from_buddy(buddy); @@ -3943,14 +3982,14 @@ * * @return TRUE if added. * */ -static void +static gboolean msim_add_contact_from_server(MsimSession *session, MsimMessage *contact_info) { guint uid; const gchar *username; uid = msim_msg_get_integer(contact_info, "ContactID"); - g_return_if_fail(uid != 0); + g_return_val_if_fail(uid != 0, FALSE); /* Lookup the username, since NickName and IMName is unreliable */ username = msim_uid2username_from_blist(session, uid); @@ -3965,6 +4004,10 @@ } else { msim_add_contact_from_server_cb(session, NULL, (gpointer)msim_msg_clone(contact_info)); } + + /* Say that the contact was added, even if we're still looking up + * their username. */ + return TRUE; } /** Called when contact list is received from server. */ @@ -3972,12 +4015,16 @@ msim_got_contact_list(MsimSession *session, MsimMessage *reply, gpointer user_data) { MsimMessage *body, *body_node; + gchar *msg; + guint buddy_count; msim_msg_dump("msim_got_contact_list: reply=%s", reply); body = msim_msg_get_dictionary(reply, "body"); g_return_if_fail(body != NULL); + buddy_count = 0; + for (body_node = body; body_node != NULL; body_node = msim_msg_get_next_element_node(body_node)) @@ -3989,10 +4036,18 @@ if (!strcmp(elem->name, "ContactID")) { /* Will look for first contact in body_node */ - msim_add_contact_from_server(session, body_node); + if (msim_add_contact_from_server(session, body_node)) { + ++buddy_count; + } } } + msg = g_strdup_printf(_("%d buddies were added or updated"), buddy_count); + + purple_notify_info(session->account, _("Add contacts from server"), msg, NULL); + + g_free(msg); + msim_msg_free(body); } diff -r 215c02a8ff88 -r 41417f94afe9 libpurple/protocols/myspace/myspace.h --- a/libpurple/protocols/myspace/myspace.h Tue Aug 21 15:10:03 2007 +0000 +++ b/libpurple/protocols/myspace/myspace.h Fri Aug 24 15:58:46 2007 +0000 @@ -90,7 +90,7 @@ #define MSIM_LANGUAGE_NAME_ENGLISH "ENGLISH" /* msimprpl version string of this plugin */ -#define MSIM_PRPL_VERSION_STRING "0.14" +#define MSIM_PRPL_VERSION_STRING "0.16" /* Default server */ #define MSIM_SERVER "im.myspace.akadns.net" @@ -226,6 +226,7 @@ gchar *username; gchar *band_name, *song_name; gchar *image_url; + guint last_image_updated; } MsimUser; diff -r 215c02a8ff88 -r 41417f94afe9 libpurple/protocols/myspace/release.sh --- a/libpurple/protocols/myspace/release.sh Tue Aug 21 15:10:03 2007 +0000 +++ b/libpurple/protocols/myspace/release.sh Fri Aug 24 15:58:46 2007 +0000 @@ -4,7 +4,7 @@ # Package a new msimprpl for release. Must be run with bash. -VERSION=0.14 +VERSION=0.16 make # Include 'myspace' directory in archive, so it can easily be unextracted # into ~/pidgin/libpurple/protocols at the correct location. diff -r 215c02a8ff88 -r 41417f94afe9 libpurple/protocols/oscar/oscar.c --- a/libpurple/protocols/oscar/oscar.c Tue Aug 21 15:10:03 2007 +0000 +++ b/libpurple/protocols/oscar/oscar.c Fri Aug 24 15:58:46 2007 +0000 @@ -3529,6 +3529,7 @@ PurpleConnection *gc; PurpleAccount *account; PurpleStatus *status; + PurplePresence *presence; const char *message, *itmsurl; char *tmp; va_list ap; @@ -3572,7 +3573,8 @@ aim_srv_setextrainfo(od, FALSE, 0, TRUE, tmp, itmsurl); g_free(tmp); - aim_srv_setidle(od, 0); + presence = purple_status_get_presence(status); + aim_srv_setidle(od, purple_presence_is_idle(presence) ? 0 : time(NULL) - purple_presence_get_idle_time(presence)); if (od->icq) { aim_icq_reqofflinemsgs(od); diff -r 215c02a8ff88 -r 41417f94afe9 libpurple/protocols/qq/sys_msg.c --- a/libpurple/protocols/qq/sys_msg.c Tue Aug 21 15:10:03 2007 +0000 +++ b/libpurple/protocols/qq/sys_msg.c Fri Aug 24 15:58:46 2007 +0000 @@ -166,7 +166,7 @@ message = g_strdup_printf(_("You have been added by %s"), from); _qq_sys_msg_log_write(gc, message, from); purple_request_action(gc, NULL, message, - _("Would like to add him?"), 2, + _("Would you like to add him?"), 2, purple_connection_get_account(gc), name, NULL, g, 3, _("Cancel"), NULL, diff -r 215c02a8ff88 -r 41417f94afe9 libpurple/protocols/yahoo/yahoo.c --- a/libpurple/protocols/yahoo/yahoo.c Tue Aug 21 15:10:03 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Fri Aug 24 15:58:46 2007 +0000 @@ -568,6 +568,11 @@ purple_debug_info("yahoo", "Setting protocol to %d\n", f->protocol); } break; + case 317: /* Stealth Setting */ + if (f && (strtol(pair->value, NULL, 10) == 2)) { + f->presence = YAHOO_PRESENCE_PERM_OFFLINE; + } + break; /* case 242: */ /* this seems related to 241 */ /* break; */ } @@ -768,7 +773,13 @@ if (bud) yahoo_update_status(gc, from, f); } + } else if (!g_ascii_strncasecmp(msg, "WEBCAMINVITE", strlen("WEBCAMINVITE"))) { + PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, gc->account); + char *buf = g_strdup_printf(_("%s has sent you a webcam invite, which is not yet supported."), from); + purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NOTIFY, time(NULL)); + g_free(buf); } + } @@ -964,7 +975,7 @@ yahoo_packet_hash(pkt, "ssiii", 1, add_req->id, 5, add_req->who, 241, add_req->protocol, 13, 1, 334, 0); yahoo_packet_send_and_free(pkt, yd); - + g_free(add_req->id); g_free(add_req->who); g_free(add_req->msg); @@ -976,19 +987,20 @@ struct yahoo_packet *pkt; char *encoded_msg = NULL; struct yahoo_data *yd = add_req->gc->proto_data; - - if (msg) + PurpleAccount *account = purple_connection_get_account(add_req->gc); + + if (msg && *msg) encoded_msg = yahoo_string_encode(add_req->gc, msg, NULL); - pkt = yahoo_packet_new(YAHOO_SERVICE_REJECTCONTACT, + pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15, YAHOO_STATUS_AVAILABLE, 0); - yahoo_packet_hash(pkt, "sss", - 1, purple_normalize(add_req->gc->account, - purple_account_get_username( - purple_connection_get_account( - add_req->gc))), - 7, add_req->who, + yahoo_packet_hash(pkt, "ssiiis", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, add_req->who, + 13, 2, + 334, 0, + 97, 1, 14, encoded_msg ? encoded_msg : ""); yahoo_packet_send_and_free(pkt, yd); @@ -1018,51 +1030,129 @@ add_req); } +static void yahoo_buddy_denied_our_add(PurpleConnection *gc, const char *who, const char *reason) +{ + char *notify_msg; + struct yahoo_data *yd = gc->proto_data; + + if (who == NULL) + return; + + if (reason != NULL) { + char *msg2 = yahoo_string_decode(gc, reason, FALSE); + notify_msg = g_strdup_printf(_("%s has (retroactively) denied your request to add them to your list for the following reason: %s."), who, msg2); + g_free(msg2); + } else + notify_msg = g_strdup_printf(_("%s has (retroactively) denied your request to add them to your list."), who); + + purple_notify_info(gc, NULL, _("Add buddy rejected"), notify_msg); + g_free(notify_msg); + + g_hash_table_remove(yd->friends, who); + purple_prpl_got_user_status(purple_connection_get_account(gc), who, "offline", NULL); /* FIXME: make this set not on list status instead */ + /* TODO: Shouldn't we remove the buddy from our local list? */ +} + static void yahoo_buddy_auth_req_15(PurpleConnection *gc, struct yahoo_packet *pkt) { - struct yahoo_add_request *add_req; - char *msg = NULL; GSList *l = pkt->hash; - - add_req = g_new0(struct yahoo_add_request, 1); - add_req->gc = gc; - - while (l) { - struct yahoo_pair *pair = l->data; - - switch (pair->key) { - case 5: - add_req->id = g_strdup(pair->value); - break; - case 4: - add_req->who = g_strdup(pair->value); - break; - case 241: - add_req->protocol = strtol(pair->value, NULL, 10); - break; - case 14: - msg = pair->value; - break; + const char *msg = NULL; + + /* Buddy authorized/declined our addition */ + if (pkt->status == 1) { + const char *who = NULL; + int response = 0; + + while (l) { + struct yahoo_pair *pair = l->data; + + switch (pair->key) { + case 4: + who = pair->value; + break; + case 13: + response = strtol(pair->value, NULL, 10); + break; + case 14: + msg = pair->value; + break; + } + l = l->next; } - l = l->next; + + if (response == 1) /* Authorized */ + purple_debug_info("yahoo", "Received authorization from buddy '%s'.\n", who ? who : "(Unknown Buddy)"); + else if (response == 2) { /* Declined */ + purple_debug_info("yahoo", "Received authorization decline from buddy '%s'.\n", who ? who : "(Unknown Buddy)"); + yahoo_buddy_denied_our_add(gc, who, msg); + } else + purple_debug_error("yahoo", "Received unknown authorization response of %d from buddy '%s'.\n", response, who ? who : "(Unknown Buddy)"); + } - - if (add_req->id) { - if (msg) - add_req->msg = yahoo_string_decode(gc, msg, FALSE); - - /* DONE! this is almost exactly the same as what MSN does, - * this should probably be moved to the core. - */ - purple_account_request_authorization(purple_connection_get_account(gc), add_req->who, add_req->id, - NULL, add_req->msg, purple_find_buddy(purple_connection_get_account(gc),add_req->who) != NULL, + /* Buddy requested authorization to add us. */ + else if (pkt->status == 3) { + struct yahoo_add_request *add_req; + const char *firstname = NULL, *lastname = NULL; + + add_req = g_new0(struct yahoo_add_request, 1); + add_req->gc = gc; + + while (l) { + struct yahoo_pair *pair = l->data; + + switch (pair->key) { + case 4: + add_req->who = g_strdup(pair->value); + break; + case 5: + add_req->id = g_strdup(pair->value); + break; + case 14: + msg = pair->value; + break; + case 216: + firstname = pair->value; + break; + case 241: + add_req->protocol = strtol(pair->value, NULL, 10); + break; + case 254: + lastname = pair->value; + break; + + } + l = l->next; + } + + if (add_req->id) { + char *alias = NULL; + if (msg) + add_req->msg = yahoo_string_decode(gc, msg, FALSE); + + if (firstname && lastname) + alias = g_strdup_printf("%s %s", firstname, lastname); + else if (firstname) + alias = g_strdup(firstname); + else if (lastname) + alias = g_strdup(lastname); + + + /* DONE! this is almost exactly the same as what MSN does, + * this should probably be moved to the core. + */ + purple_account_request_authorization(purple_connection_get_account(gc), add_req->who, add_req->id, + alias, add_req->msg, purple_find_buddy(purple_connection_get_account(gc),add_req->who) != NULL, yahoo_buddy_add_authorize_cb, yahoo_buddy_add_deny_reason_cb, - add_req); + add_req); + g_free(alias); + } else { + g_free(add_req->id); + g_free(add_req->who); + /*g_free(add_req->msg);*/ + g_free(add_req); + } } else { - g_free(add_req->id); - g_free(add_req->who); - /*g_free(add_req->msg);*/ - g_free(add_req); + purple_debug_error("yahoo", "Received authorization of unknown status (%d).\n", pkt->status); } } @@ -1113,13 +1203,12 @@ } } -static void yahoo_buddy_denied_our_add(PurpleConnection *gc, struct yahoo_packet *pkt) +/* I have no idea if this every gets called in version 15 */ +static void yahoo_buddy_denied_our_add_old(PurpleConnection *gc, struct yahoo_packet *pkt) { char *who = NULL; char *msg = NULL; GSList *l = pkt->hash; - GString *buf = NULL; - struct yahoo_data *yd = gc->proto_data; while (l) { struct yahoo_pair *pair = l->data; @@ -1135,22 +1224,7 @@ l = l->next; } - if (who) { - char *msg2; - buf = g_string_sized_new(0); - if (!msg) { - g_string_printf(buf, _("%s has (retroactively) denied your request to add them to your list."), who); - } else { - msg2 = yahoo_string_decode(gc, msg, FALSE); - g_string_printf(buf, _("%s has (retroactively) denied your request to add them to your list for the following reason: %s."), who, msg2); - g_free(msg2); - } - purple_notify_info(gc, NULL, _("Add buddy rejected"), buf->str); - g_string_free(buf, TRUE); - g_hash_table_remove(yd->friends, who); - purple_prpl_got_user_status(purple_connection_get_account(gc), who, "offline", NULL); /* FIXME: make this set not on list status instead */ - /* TODO: Shouldn't we remove the buddy from our local list? */ - } + yahoo_buddy_denied_our_add(gc, who, msg); } static void yahoo_process_contact(PurpleConnection *gc, struct yahoo_packet *pkt) @@ -1163,7 +1237,7 @@ yahoo_buddy_added_us(gc, pkt); break; case 7: - yahoo_buddy_denied_our_add(gc, pkt); + yahoo_buddy_denied_our_add_old(gc, pkt); break; default: break; @@ -2265,7 +2339,7 @@ break; case YAHOO_SERVICE_AUTH_REQ_15: yahoo_buddy_auth_req_15(gc, pkt); - break; + break; case YAHOO_SERVICE_ADDBUDDY: yahoo_process_addbuddy(gc, pkt); break; @@ -2846,7 +2920,7 @@ purple_connection_set_display_name(gc, purple_account_get_username(account)); yd->fd = -1; - yd->txhandler = -1; + yd->txhandler = 0; /* TODO: Is there a good grow size for the buffer? */ yd->txbuf = purple_circ_buffer_new(0); yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free); @@ -3734,7 +3808,7 @@ return; f = yahoo_friend_find(gc, purple_buddy_get_name(buddy)); - + if (foo) group = foo->name; if (!group) { diff -r 215c02a8ff88 -r 41417f94afe9 libpurple/protocols/yahoo/yahoo_packet.c --- a/libpurple/protocols/yahoo/yahoo_packet.c Tue Aug 21 15:10:03 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo_packet.c Fri Aug 24 15:58:46 2007 +0000 @@ -294,7 +294,7 @@ if (writelen == 0) { purple_input_remove(yd->txhandler); - yd->txhandler = -1; + yd->txhandler = 0; return; } @@ -355,7 +355,7 @@ len = yahoo_packet_build(pkt, 0, yd->wm, yd->jp, &data); yahoo_packet_dump(data, len); - if (yd->txhandler == -1) + if (yd->txhandler == 0) ret = write(yd->fd, data, len); else { ret = -1; @@ -371,7 +371,7 @@ } if (ret < len) { - if (yd->txhandler == -1) + if (yd->txhandler == 0) yd->txhandler = purple_input_add(yd->fd, PURPLE_INPUT_WRITE, yahoo_packet_send_can_write, yd); purple_circ_buffer_append(yd->txbuf, data + ret, len - ret); diff -r 215c02a8ff88 -r 41417f94afe9 libpurple/protocols/yahoo/yahoochat.c --- a/libpurple/protocols/yahoo/yahoochat.c Tue Aug 21 15:10:03 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoochat.c Fri Aug 24 15:58:46 2007 +0000 @@ -62,8 +62,9 @@ } pkt = yahoo_packet_new(YAHOO_SERVICE_CHATONLINE, YAHOO_STATUS_AVAILABLE,0); - yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), - 109, purple_connection_get_display_name(gc), 6, "abcde"); + yahoo_packet_hash(pkt, "ssss", 1, purple_connection_get_display_name(gc), + 109, purple_connection_get_display_name(gc), 6, "abcde", + 135, "ym8.1.0.415"); yahoo_packet_send_and_free(pkt, yd); } @@ -155,7 +156,7 @@ if (members) { g_hash_table_replace(components, g_strdup("members"), g_strdup(members->str)); } - if (!yahoo_privacy_check(gc, who) || + if (!yahoo_privacy_check(gc, who) || (purple_account_get_bool(purple_connection_get_account(gc), "ignore_invites", FALSE))) { purple_debug_info("yahoo", "Invite to conference %s from %s has been dropped.\n", room, who); @@ -640,7 +641,7 @@ GList *w; purple_debug_misc("yahoo", "leaving conference %s\n", room); - + pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGOFF, YAHOO_STATUS_AVAILABLE, 0); yahoo_packet_hash_str(pkt, 1, dn); @@ -732,7 +733,7 @@ continue; yahoo_packet_hash(pkt, "ss", 52, name, 53, name); } - + yahoo_packet_send_and_free(pkt, yd); g_free(msg2); } diff -r 215c02a8ff88 -r 41417f94afe9 libpurple/win32/global.mak --- a/libpurple/win32/global.mak Tue Aug 21 15:10:03 2007 +0000 +++ b/libpurple/win32/global.mak Fri Aug 24 15:58:46 2007 +0000 @@ -11,7 +11,7 @@ # Locations of our various dependencies WIN32_DEV_TOP ?= $(PIDGIN_TREE_TOP)/../win32-dev ASPELL_TOP ?= $(WIN32_DEV_TOP)/aspell-dev-0-50-3-3 -GTKSPELL_TOP ?= $(WIN32_DEV_TOP)/gtkspell-2.0.6 +GTKSPELL_TOP ?= $(WIN32_DEV_TOP)/gtkspell-2.0.11 GTK_TOP ?= $(WIN32_DEV_TOP)/gtk_2_0 GTK_BIN ?= $(GTK_TOP)/bin BONJOUR_TOP ?= $(WIN32_DEV_TOP)/Bonjour_SDK diff -r 215c02a8ff88 -r 41417f94afe9 libpurple/xmlnode.c --- a/libpurple/xmlnode.c Tue Aug 21 15:10:03 2007 +0000 +++ b/libpurple/xmlnode.c Fri Aug 24 15:58:46 2007 +0000 @@ -272,6 +272,8 @@ if(NULL != node->parent) { if(node->parent->child == node) { node->parent->child = node->next; + if (node->parent->lastchild == node) + node->parent->lastchild = node->next; } else { xmlnode *prev = node->parent->child; while(prev && prev->next != node) { @@ -279,6 +281,8 @@ } if(prev) { prev->next = node->next; + if (node->parent->lastchild == node) + node->parent->lastchild = prev; } } } diff -r 215c02a8ff88 -r 41417f94afe9 pidgin/gtkaccount.c --- a/pidgin/gtkaccount.c Tue Aug 21 15:10:03 2007 +0000 +++ b/pidgin/gtkaccount.c Fri Aug 24 15:58:46 2007 +0000 @@ -272,7 +272,8 @@ add_user_options(dialog, dialog->top_vbox); add_protocol_options(dialog, dialog->bottom_vbox); - if (!dialog->prpl_info || !dialog->prpl_info->register_user) { + if (!dialog->prpl_info || !dialog->prpl_info->register_user || + g_object_get_data(G_OBJECT(item), "fake")) { gtk_widget_hide(dialog->register_button); } else { if (dialog->prpl_info != NULL && @@ -1394,7 +1395,9 @@ purple_signal_emit(pidgin_account_get_handle(), "account-modified", account); /* If this is a new account, then sign on! */ - if (new && !dialog->registering) { + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->register_button))) { + purple_account_register(account); + } else if (new) { const PurpleSavedStatus *saved_status; saved_status = purple_savedstatus_get_current(); @@ -1410,19 +1413,6 @@ return account; } -static void -register_account_prefs_cb(GtkWidget *w, AccountPrefsDialog *dialog) -{ - PurpleAccount *account; - - dialog->registering = TRUE; - - account = ok_account_prefs_cb(NULL, dialog); - - purple_account_register(account); -} - - static const GtkTargetEntry dnd_targets[] = { {"text/plain", 0, 0}, {"text/uri-list", 0, 1}, @@ -1501,6 +1491,18 @@ add_login_options(dialog, vbox); add_user_options(dialog, vbox); + button = gtk_check_button_new_with_label(_("Create this new account on the server")); + gtk_box_pack_start(GTK_BOX(main_vbox), button, FALSE, FALSE, 0); + gtk_widget_show(button); + dialog->register_button = button; + if (dialog->account == NULL) + gtk_widget_set_sensitive(button, FALSE); + + if (!dialog->prpl_info || !dialog->prpl_info->register_user) + gtk_widget_hide(button); + + + /* Setup the page with 'Advanced'. */ dialog->bottom_vbox = dbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER); gtk_container_set_border_width(GTK_CONTAINER(dbox), PIDGIN_HIG_BORDER); @@ -1519,22 +1521,6 @@ gtk_box_pack_end(GTK_BOX(main_vbox), bbox, FALSE, TRUE, 0); gtk_widget_show(bbox); - /* Register button */ - button = gtk_button_new_with_label(_("Register")); - gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); - gtk_widget_show(button); - - g_signal_connect(G_OBJECT(button), "clicked", - G_CALLBACK(register_account_prefs_cb), dialog); - - dialog->register_button = button; - - if (dialog->account == NULL) - gtk_widget_set_sensitive(button, FALSE); - - if (!dialog->prpl_info || !dialog->prpl_info->register_user) - gtk_widget_hide(button); - /* Cancel button */ button = gtk_button_new_from_stock(GTK_STOCK_CANCEL); gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); diff -r 215c02a8ff88 -r 41417f94afe9 pidgin/gtkblist.c --- a/pidgin/gtkblist.c Tue Aug 21 15:10:03 2007 +0000 +++ b/pidgin/gtkblist.c Fri Aug 24 15:58:46 2007 +0000 @@ -2528,7 +2528,8 @@ GValue val; struct _pidgin_blist_node *gtknode; - if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->tip_rect.x, gtkblist->tip_rect.y, &path, NULL, NULL, NULL)) + if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->tip_rect.x, gtkblist->tip_rect.y + (gtkblist->tip_rect.height/2), + &path, NULL, NULL, NULL)) return FALSE; gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); val.g_type = 0; @@ -2585,7 +2586,8 @@ PurpleBlistNode *node; GValue val; - if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->tip_rect.x, gtkblist->tip_rect.y, &path, NULL, NULL, NULL)) + if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->tip_rect.x, gtkblist->tip_rect.y + (gtkblist->tip_rect.height/2), + &path, NULL, NULL, NULL)) return FALSE; gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); val.g_type = 0; diff -r 215c02a8ff88 -r 41417f94afe9 pidgin/gtkconv.c --- a/pidgin/gtkconv.c Tue Aug 21 15:10:03 2007 +0000 +++ b/pidgin/gtkconv.c Fri Aug 24 15:58:46 2007 +0000 @@ -100,36 +100,6 @@ #define LUMINANCE(c) (float)((0.3*(c.red))+(0.59*(c.green))+(0.11*(c.blue))) -#if 0 -/* These colors come from the default GNOME palette */ -static GdkColor nick_colors[] = { - {0, 47616, 46336, 43776}, /* Basic 3D Medium */ - {0, 32768, 32000, 29696}, /* Basic 3D Dark */ - {0, 22016, 20992, 18432}, /* 3D Shadow */ - {0, 33536, 42496, 32512}, /* Green Medium */ - {0, 23808, 29952, 21760}, /* Green Dark */ - {0, 17408, 22016, 12800}, /* Green Shadow */ - {0, 57344, 46592, 44800}, /* Red Hilight */ - {0, 49408, 26112, 23040}, /* Red Medium */ - {0, 34816, 17920, 12544}, /* Red Dark */ - {0, 49408, 14336, 8704}, /* Red Shadow */ - {0, 34816, 32512, 41728}, /* Purple Medium */ - {0, 25088, 23296, 33024}, /* Purple Dark */ - {0, 18688, 16384, 26112}, /* Purple Shadow */ - {0, 40192, 47104, 53760}, /* Blue Hilight */ - {0, 29952, 36864, 44544}, /* Blue Medium */ - {0, 57344, 49920, 40448}, /* Face Skin Medium */ - {0, 45824, 37120, 26880}, /* Face skin Dark */ - {0, 33280, 26112, 18176}, /* Face Skin Shadow */ - {0, 57088, 16896, 7680}, /* Accent Red */ - {0, 39168, 0, 0}, /* Accent Red Dark */ - {0, 17920, 40960, 17920}, /* Accent Green */ - {0, 9728, 50944, 9728} /* Accent Green Dark */ -}; - -#define NUM_NICK_COLORS (sizeof(nick_colors) / sizeof(*nick_colors)) -#endif - /* From http://www.w3.org/TR/AERT#color-contrast */ #define MIN_BRIGHTNESS_CONTRAST 75 #define MIN_COLOR_CONTRAST 200 @@ -8736,7 +8706,7 @@ angle = 270; #if GTK_CHECK_VERSION(2,6,0) - if (!angle && pidgin_conv_window_get_gtkconv_count(win) > 1) { + if (!angle) { g_object_set(G_OBJECT(gtkconv->tab_label), "ellipsize", PANGO_ELLIPSIZE_END, NULL); gtk_label_set_width_chars(GTK_LABEL(gtkconv->tab_label), 4); } else { @@ -8801,14 +8771,15 @@ } gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, - !tabs_side && !angle && pidgin_conv_window_get_gtkconv_count(win) > 1, + !tabs_side && !angle, TRUE, GTK_PACK_START); if (pidgin_conv_window_get_gtkconv_count(win) == 1) gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), - !purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons") || + purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/tabs") && + (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons") || purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == GTK_POS_LEFT || - purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == GTK_POS_RIGHT); + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == GTK_POS_RIGHT)); /* show the widgets */ /* gtk_widget_show(gtkconv->icon); */ diff -r 215c02a8ff88 -r 41417f94afe9 pidgin/gtkdialogs.c --- a/pidgin/gtkdialogs.c Tue Aug 21 15:10:03 2007 +0000 +++ b/pidgin/gtkdialogs.c Fri Aug 24 15:58:46 2007 +0000 @@ -86,6 +86,7 @@ {"Luke 'LSchiere' Schierer", N_("support"), "lschiere@users.sf.net"}, {"Megan 'Cae' Schneider", N_("support/QA"), NULL}, {"Evan Schoenberg", N_("developer"), NULL}, + {"Kevin 'SimGuy' Stange", N_("developer & webmaster"), NULL}, {"Stu 'nosnilmot' Tomlinson", N_("developer"), NULL}, {"Nathan 'faceprint' Walp", N_("developer"), NULL}, {NULL, NULL, NULL} @@ -95,7 +96,6 @@ static struct developer patch_writers[] = { {"John 'rekkanoryo' Bailey", NULL, NULL}, {"Peter 'Bleeter' Lawler", NULL, NULL}, - {"Kevin 'SimGuy' Stange", NULL, NULL}, {NULL, NULL, NULL} }; diff -r 215c02a8ff88 -r 41417f94afe9 pidgin/gtknotify.c --- a/pidgin/gtknotify.c Tue Aug 21 15:10:03 2007 +0000 +++ b/pidgin/gtknotify.c Fri Aug 24 15:58:46 2007 +0000 @@ -589,16 +589,16 @@ char label_text[2048]; char *linked_text, *primary_esc, *secondary_esc; - window = pidgin_create_window(title, PIDGIN_HIG_BORDER, NULL, TRUE); - gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); + window = gtk_dialog_new(); + gtk_window_set_title(GTK_WINDOW(window), title); + gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER); + gtk_window_set_resizable(GTK_WINDOW(window), TRUE); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(formatted_close_cb), NULL); /* Setup the main vbox */ - vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(window), vbox); - gtk_widget_show(vbox); + vbox = GTK_DIALOG(window)->vbox; /* Setup the descriptive label */ primary_esc = g_markup_escape_text(primary, -1); @@ -630,9 +630,7 @@ gtk_widget_show(frame); /* Add the Close button. */ - button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); - gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0); - gtk_widget_show(button); + button = gtk_dialog_add_button(GTK_DIALOG(window), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE); gtk_widget_grab_focus(button); g_signal_connect_swapped(G_OBJECT(button), "clicked", @@ -708,7 +706,6 @@ guint i; GtkWidget *vbox; - GtkWidget *button_area; GtkWidget *label; GtkWidget *sw; PidginNotifySearchResultsData *data; @@ -723,16 +720,16 @@ data->results = results; /* Create the window */ - window = pidgin_create_window(title ? title :_("Search Results"), PIDGIN_HIG_BORDER, NULL, TRUE); - gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); + window = gtk_dialog_new(); + gtk_window_set_title(GTK_WINDOW(window), title ? title :_("Search Results")); + gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER); + gtk_window_set_resizable(GTK_WINDOW(window), TRUE); g_signal_connect_swapped(G_OBJECT(window), "delete_event", G_CALLBACK(searchresults_close_cb), data); /* Setup the main vbox */ - vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(window), vbox); - gtk_widget_show(vbox); + vbox = GTK_DIALOG(window)->vbox; /* Setup the descriptive label */ primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL; @@ -796,13 +793,6 @@ renderer, "text", i, NULL); } - /* Setup the button area */ - button_area = gtk_hbutton_box_new(); - gtk_box_pack_start(GTK_BOX(vbox), button_area, FALSE, FALSE, 0); - gtk_button_box_set_layout(GTK_BUTTON_BOX(button_area), GTK_BUTTONBOX_END); - gtk_box_set_spacing(GTK_BOX(button_area), PIDGIN_HIG_BORDER); - gtk_widget_show(button_area); - for (i = 0; i < g_list_length(results->buttons); i++) { PurpleNotifySearchButton *b = g_list_nth_data(results->buttons, i); GtkWidget *button = NULL; @@ -815,22 +805,22 @@ } break; case PURPLE_NOTIFY_BUTTON_CONTINUE: - button = gtk_button_new_from_stock(GTK_STOCK_GO_FORWARD); + button = gtk_dialog_add_button(GTK_DIALOG(window), GTK_STOCK_GO_FORWARD, GTK_RESPONSE_NONE); break; case PURPLE_NOTIFY_BUTTON_ADD: - button = gtk_button_new_from_stock(GTK_STOCK_ADD); + button = gtk_dialog_add_button(GTK_DIALOG(window), GTK_STOCK_ADD, GTK_RESPONSE_NONE); break; case PURPLE_NOTIFY_BUTTON_INFO: - button = gtk_button_new_from_stock(PIDGIN_STOCK_TOOLBAR_USER_INFO); + button = gtk_dialog_add_button(GTK_DIALOG(window), PIDGIN_STOCK_TOOLBAR_USER_INFO, GTK_RESPONSE_NONE); break; case PURPLE_NOTIFY_BUTTON_IM: - button = gtk_button_new_from_stock(PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW); + button = gtk_dialog_add_button(GTK_DIALOG(window), PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, GTK_RESPONSE_NONE); break; case PURPLE_NOTIFY_BUTTON_JOIN: - button = gtk_button_new_from_stock(PIDGIN_STOCK_CHAT); + button = gtk_dialog_add_button(GTK_DIALOG(window), PIDGIN_STOCK_CHAT, GTK_RESPONSE_NONE); break; case PURPLE_NOTIFY_BUTTON_INVITE: - button = gtk_button_new_from_stock(PIDGIN_STOCK_INVITE); + button = gtk_dialog_add_button(GTK_DIALOG(window), PIDGIN_STOCK_INVITE, GTK_RESPONSE_NONE); break; default: purple_debug_warning("gtknotify", "Incorrect button type: %d\n", b->type); @@ -838,9 +828,6 @@ if (button != NULL) { PidginNotifySearchResultsButtonData *bd; - gtk_box_pack_start(GTK_BOX(button_area), button, FALSE, FALSE, 0); - gtk_widget_show(button); - bd = g_new0(PidginNotifySearchResultsButtonData, 1); bd->button = b; bd->data = data; @@ -852,9 +839,7 @@ } /* Add the Close button */ - close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); - gtk_box_pack_start(GTK_BOX(button_area), close_button, FALSE, FALSE, 0); - gtk_widget_show(close_button); + close_button = gtk_dialog_add_button(GTK_DIALOG(window), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE); g_signal_connect_swapped(G_OBJECT(close_button), "clicked", G_CALLBACK(searchresults_close_cb), data); diff -r 215c02a8ff88 -r 41417f94afe9 pidgin/gtkpounce.c --- a/pidgin/gtkpounce.c Tue Aug 21 15:10:03 2007 +0000 +++ b/pidgin/gtkpounce.c Fri Aug 24 15:58:46 2007 +0000 @@ -467,7 +467,6 @@ PidginPounceDialog *dialog; GtkWidget *window; GtkWidget *label; - GtkWidget *bbox; GtkWidget *vbox1, *vbox2; GtkWidget *hbox; GtkWidget *button; @@ -513,17 +512,16 @@ sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); /* Create the window. */ - dialog->window = window = pidgin_create_window((cur_pounce == NULL ? _("New Buddy Pounce") : _("Edit Buddy Pounce")), - PIDGIN_HIG_BORDER, "buddy_pounce", FALSE) ; - gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); + dialog->window = window = gtk_dialog_new(); + gtk_window_set_title(GTK_WINDOW(window), (cur_pounce == NULL ? _("New Buddy Pounce") : _("Edit Buddy Pounce"))); + gtk_window_set_role(GTK_WINDOW(window), "buddy_pounce"); + gtk_container_set_border_width(GTK_CONTAINER(dialog->window), PIDGIN_HIG_BORDER); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_win_cb), dialog); /* Create the parent vbox for everything. */ - vbox1 = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(window), vbox1); - gtk_widget_show(vbox1); + vbox1 = GTK_DIALOG(window)->vbox; /* Create the vbox that will contain all the prefs stuff. */ vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); @@ -808,26 +806,13 @@ gtk_widget_show(dialog->on_away); gtk_widget_show(dialog->save_pounce); - /* Now the button box! */ - bbox = gtk_hbutton_box_new(); - gtk_box_set_spacing(GTK_BOX(bbox), PIDGIN_HIG_BOX_SPACE); - gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); - gtk_box_pack_end(GTK_BOX(vbox1), bbox, FALSE, FALSE, 0); - gtk_widget_show(bbox); - /* Cancel button */ - button = gtk_button_new_from_stock(GTK_STOCK_CANCEL); - gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); - gtk_widget_show(button); - + button = gtk_dialog_add_button(GTK_DIALOG(window), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(cancel_cb), dialog); /* Save button */ - dialog->save_button = button = gtk_button_new_from_stock(GTK_STOCK_SAVE); - gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); - gtk_widget_show(button); - + dialog->save_button = button = gtk_dialog_add_button(GTK_DIALOG(window), GTK_STOCK_SAVE, GTK_RESPONSE_OK); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(save_pounce_cb), dialog); diff -r 215c02a8ff88 -r 41417f94afe9 pidgin/gtkprefs.c --- a/pidgin/gtkprefs.c Tue Aug 21 15:10:03 2007 +0000 +++ b/pidgin/gtkprefs.c Fri Aug 24 15:58:46 2007 +0000 @@ -240,7 +240,7 @@ if (label != NULL) { gtk_label_set_mnemonic_widget(GTK_LABEL(label), dropdown); - pidgin_set_accessible_label (dropdown, label); + pidgin_set_accessible_relations (dropdown, label); } if (type == PURPLE_PREF_INT) diff -r 215c02a8ff88 -r 41417f94afe9 pidgin/gtksavedstatuses.c --- a/pidgin/gtksavedstatuses.c Tue Aug 21 15:10:03 2007 +0000 +++ b/pidgin/gtksavedstatuses.c Fri Aug 24 15:58:46 2007 +0000 @@ -1450,7 +1450,9 @@ GtkWidget *win; GtkTreeIter iter; GtkCellRenderer *rend; - const char *status_id = NULL; + char *status_id = NULL; + char *message = NULL; + gboolean parent_dialog_has_substatus = FALSE; GList *list; gboolean select = FALSE; @@ -1553,25 +1555,29 @@ G_CALLBACK(substatus_editor_ok_cb), dialog); /* Seed the input widgets with the current values */ - /* TODO: Get the current values from our parent's list store, not the saved_status! */ - if (status_editor->original_title != NULL) - { + + /* Only look at the saved status if we can't find it in the parent status dialog's substatuses model */ + gtk_tree_model_get(GTK_TREE_MODEL(status_editor->model), &iter, + STATUS_EDITOR_COLUMN_ENABLE_SUBSTATUS, &parent_dialog_has_substatus, -1); + if (parent_dialog_has_substatus) { + gtk_tree_model_get(GTK_TREE_MODEL(status_editor->model), &iter, + STATUS_EDITOR_COLUMN_STATUS_ID, &status_id, + STATUS_EDITOR_COLUMN_STATUS_MESSAGE, &message, -1); + } else if (status_editor->original_title != NULL) { PurpleSavedStatus *saved_status = NULL; PurpleSavedStatusSub *substatus = NULL; - saved_status = purple_savedstatus_find(status_editor->original_title); - if (saved_status != NULL) - substatus = purple_savedstatus_get_substatus(saved_status, account); + if ((saved_status = purple_savedstatus_find(status_editor->original_title)) != NULL) { + if ((substatus = purple_savedstatus_get_substatus(saved_status, account)) != NULL) { + message = (char *)purple_savedstatus_substatus_get_message(substatus); + status_id = (char *)purple_status_type_get_id(purple_savedstatus_substatus_get_type(substatus)); + } + } + } + /* TODO: Else get the generic status type from our parent */ - if (substatus != NULL) - { - gtk_imhtml_append_text(dialog->message, - purple_savedstatus_substatus_get_message(substatus), - 0); - status_id = purple_status_type_get_id(purple_savedstatus_substatus_get_type(substatus)); - } - /* TODO: Else get the generic status type from our parent */ - } + if (message) + gtk_imhtml_append_text(dialog->message, message, 0); for (list = purple_account_get_status_types(account); list; list = list->next) { @@ -1607,6 +1613,12 @@ if (!select) gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); + if (parent_dialog_has_substatus) { + /* These two were gotten from the parent tree model, so they need to be freed */ + g_free(status_id); + g_free(message); + } + gtk_widget_show_all(win); } diff -r 215c02a8ff88 -r 41417f94afe9 pidgin/gtksound.c --- a/pidgin/gtksound.c Tue Aug 21 15:10:03 2007 +0000 +++ b/pidgin/gtksound.c Fri Aug 24 15:58:46 2007 +0000 @@ -364,14 +364,14 @@ GError *err = NULL; switch (GST_MESSAGE_TYPE (msg)) { - case GST_MESSAGE_EOS: - gst_element_set_state(play, GST_STATE_NULL); - gst_object_unref(GST_OBJECT(play)); - break; case GST_MESSAGE_ERROR: gst_message_parse_error(msg, &err, NULL); purple_debug_error("gstreamer", "%s\n", err->message); g_error_free(err); + /* fall-through and clean up */ + case GST_MESSAGE_EOS: + gst_element_set_state(play, GST_STATE_NULL); + gst_object_unref(GST_OBJECT(play)); break; case GST_MESSAGE_WARNING: gst_message_parse_warning(msg, &err, NULL); diff -r 215c02a8ff88 -r 41417f94afe9 pidgin/gtkstatusbox.c --- a/pidgin/gtkstatusbox.c Tue Aug 21 15:10:03 2007 +0000 +++ b/pidgin/gtkstatusbox.c Fri Aug 24 15:58:46 2007 +0000 @@ -1415,15 +1415,15 @@ } -static void -toggled_cb(GtkWidget *widget, PidginStatusBox *box) +static +gboolean +toggled_cb(GtkWidget *widget, GdkEventButton *event, PidginStatusBox *box) { - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) { if (!box->popup_in_progress) pidgin_status_box_popup (box); - } else { - pidgin_status_box_popdown(box); - } + else + pidgin_status_box_popdown(box); +return TRUE; } static void @@ -1773,7 +1773,7 @@ g_signal_connect(G_OBJECT(status_box->toggle_button), "button-release-event", G_CALLBACK(button_released_cb), status_box); #endif - g_signal_connect(G_OBJECT(status_box->toggle_button), "toggled", + g_signal_connect(G_OBJECT(status_box->toggle_button), "button-press-event", G_CALLBACK(toggled_cb), status_box); g_signal_connect(G_OBJECT(buffer), "changed", G_CALLBACK(imhtml_changed_cb), status_box); g_signal_connect(G_OBJECT(status_box->imhtml), "format_function_toggle", diff -r 215c02a8ff88 -r 41417f94afe9 pidgin/gtkutils.c --- a/pidgin/gtkutils.c Tue Aug 21 15:10:03 2007 +0000 +++ b/pidgin/gtkutils.c Fri Aug 24 15:58:46 2007 +0000 @@ -1147,12 +1147,30 @@ void pidgin_set_accessible_label (GtkWidget *w, GtkWidget *l) { + AtkObject *acc; + const gchar *label_text; + const gchar *existing_name; + + acc = gtk_widget_get_accessible (w); + + /* If this object has no name, set it's name with the label text */ + existing_name = atk_object_get_name (acc); + if (!existing_name) { + label_text = gtk_label_get_text (GTK_LABEL(l)); + if (label_text) + atk_object_set_name (acc, label_text); + } + + pidgin_set_accessible_relations(w, l); +} + +void +pidgin_set_accessible_relations (GtkWidget *w, GtkWidget *l) +{ AtkObject *acc, *label; AtkObject *rel_obj[1]; AtkRelationSet *set; AtkRelation *relation; - const gchar *label_text; - const gchar *existing_name; acc = gtk_widget_get_accessible (w); label = gtk_widget_get_accessible (l); @@ -1160,14 +1178,6 @@ /* Make sure mnemonics work */ gtk_label_set_mnemonic_widget(GTK_LABEL(l), w); - /* If this object has no name, set it's name with the label text */ - existing_name = atk_object_get_name (acc); - if (!existing_name) { - label_text = gtk_label_get_text (GTK_LABEL(l)); - if (label_text) - atk_object_set_name (acc, label_text); - } - /* Create the labeled-by relation */ set = atk_object_ref_relation_set (acc); rel_obj[0] = label; diff -r 215c02a8ff88 -r 41417f94afe9 pidgin/gtkutils.h --- a/pidgin/gtkutils.h Tue Aug 21 15:10:03 2007 +0000 +++ b/pidgin/gtkutils.h Fri Aug 24 15:58:46 2007 +0000 @@ -418,6 +418,14 @@ void pidgin_set_accessible_label(GtkWidget *w, GtkWidget *l); /** + * Sets the labelled-by and label-for ATK relationships. + * + * @param w The widget that we want to label. + * @param l A GtkLabel that we want to use as the label for the widget. + */ +void pidgin_set_accessible_relations(GtkWidget *w, GtkWidget *l); + +/** * A helper function for GtkMenuPositionFuncs. This ensures the menu will * be kept on screen if possible. * diff -r 215c02a8ff88 -r 41417f94afe9 pidgin/plugins/musicmessaging/musicmessaging.c --- a/pidgin/plugins/musicmessaging/musicmessaging.c Tue Aug 21 15:10:03 2007 +0000 +++ b/pidgin/plugins/musicmessaging/musicmessaging.c Fri Aug 24 15:58:46 2007 +0000 @@ -71,10 +71,10 @@ /* Globals */ /* List of sessions */ -GList *conversations; +static GList *conversations; /* Pointer to this plugin */ -PurplePlugin *plugin_pointer; +static PurplePlugin *plugin_pointer; /* Define types needed for DBus */ DBusGConnection *connection; @@ -350,7 +350,16 @@ static gboolean intercept_received(PurpleAccount *account, char **sender, char **message, PurpleConversation *conv, int *flags) { - MMConversation *mmconv = mmconv_from_conv(conv); + MMConversation *mmconv; + + if (conv == NULL) { + /* XXX: This is just to avoid a crash (#2726). + * We may want to create the conversation instead of returning from here + */ + return FALSE; + } + + mmconv = mmconv_from_conv(conv); purple_debug_misc("purple-musicmessaging", "Intercepted: %s\n", *message); if (strstr(*message, MUSICMESSAGING_PREFIX))