changeset 25543:5e76304ebcc8

propagate from branch 'im.pidgin.pidgin' (head 40c25a37a614d9667d4cf190640316f92edbe3d6) to branch 'im.pidgin.pidgin.yaz' (head 1bfde92fb6a41d9c59719cd3d6a56bdb86c45234)
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Sat, 25 Aug 2007 08:42:33 +0000
parents 92d8c9b08dab (current diff) 4fced00fdc9f (diff)
children 7f8cf35fc99b
files configure.ac libpurple/protocols/oscar/oscar.c libpurple/protocols/yahoo/yahoo.c libpurple/protocols/yahoo/yahoo_packet.c libpurple/util.c libpurple/util.h
diffstat 52 files changed, 542 insertions(+), 191 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Aug 23 06:53:06 2007 +0000
+++ b/ChangeLog	Sat Aug 25 08:42:33 2007 +0000
@@ -1,5 +1,9 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
+version 2.1.2:
+	* New protocol plugin: MySpaceIM (Jeff Connelly, Google Summer of
+	  Code)
+
 version 2.1.1 (08/20/2007):
 	Yahoo:
 	* Added an account action to open your inbox in the yahoo prpl.
--- a/configure.ac	Thu Aug 23 06:53:06 2007 +0000
+++ b/configure.ac	Sat Aug 25 08:42:33 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
--- a/finch/gntaccount.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/gntaccount.c	Sat Aug 25 08:42:33 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);
 }
 
--- a/finch/gntblist.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/gntblist.c	Sat Aug 25 08:42:33 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)
--- a/finch/gntconv.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/gntconv.c	Sat Aug 25 08:42:33 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);
--- a/finch/gntft.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/gntft.c	Sat Aug 25 08:42:33 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"));
 	}
--- a/finch/gntpounce.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/gntpounce.c	Sat Aug 25 08:42:33 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"));
--- a/finch/gntsound.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/gntsound.c	Sat Aug 25 08:42:33 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
@@ -990,6 +996,8 @@
 
 	pref_dialog->volume = slider = gnt_slider_new(FALSE, 100, 0);
 	gnt_slider_set_step(GNT_SLIDER(slider), 5);
+	gnt_slider_set_small_step(GNT_SLIDER(slider), 1);
+	gnt_slider_set_large_step(GNT_SLIDER(slider), 20);
 	label = gnt_label_new("");
 	gnt_slider_reflect_label(GNT_SLIDER(slider), GNT_LABEL(label));
 	gnt_box_set_pad(GNT_BOX(tmpbox), 1);
--- a/finch/gntstatus.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/gntstatus.c	Sat Aug 25 08:42:33 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);
--- a/finch/libgnt/configure.ac	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/libgnt/configure.ac	Sat Aug 25 08:42:33 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],
--- a/finch/libgnt/gnt.h	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/libgnt/gnt.h	Sat Aug 25 08:42:33 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);
--- a/finch/libgnt/gntcolors.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/libgnt/gntcolors.c	Sat Aug 25 08:42:33 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;
--- a/finch/libgnt/gntfilesel.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/libgnt/gntfilesel.c	Sat Aug 25 08:42:33 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);
 }
--- a/finch/libgnt/gntslider.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/libgnt/gntslider.c	Sat Aug 25 08:42:33 2007 +0000
@@ -125,22 +125,66 @@
 step_back(GntBindable *bindable, GList *null)
 {
 	GntSlider *slider = GNT_SLIDER(bindable);
-	if (slider->current <= slider->min)
-		return FALSE;
 	gnt_slider_advance_step(slider, -1);
 	return TRUE;
 }
 
 static gboolean
+small_step_back(GntBindable *bindable, GList *null)
+{
+	GntSlider *slider = GNT_SLIDER(bindable);
+	gnt_slider_set_value(slider, slider->current - slider->smallstep);
+	return TRUE;
+}
+
+static gboolean
+large_step_back(GntBindable *bindable, GList *null)
+{
+	GntSlider *slider = GNT_SLIDER(bindable);
+	gnt_slider_set_value(slider, slider->current - slider->largestep);
+	return TRUE;
+}
+
+static gboolean
 step_forward(GntBindable *bindable, GList *list)
 {
 	GntSlider *slider = GNT_SLIDER(bindable);
-	if (slider->current >= slider->max)
-		return FALSE;
 	gnt_slider_advance_step(slider, 1);
 	return TRUE;
 }
 
+static gboolean
+small_step_forward(GntBindable *bindable, GList *null)
+{
+	GntSlider *slider = GNT_SLIDER(bindable);
+	gnt_slider_set_value(slider, slider->current + slider->smallstep);
+	return TRUE;
+}
+
+static gboolean
+large_step_forward(GntBindable *bindable, GList *null)
+{
+	GntSlider *slider = GNT_SLIDER(bindable);
+	gnt_slider_set_value(slider, slider->current + slider->largestep);
+	return TRUE;
+}
+
+static gboolean
+move_min_value(GntBindable *bindable, GList *null)
+{
+	GntSlider *slider = GNT_SLIDER(bindable);
+	gnt_slider_set_value(slider, slider->min);
+	return TRUE;
+}
+
+static gboolean
+move_max_value(GntBindable *bindable, GList *null)
+{
+	GntSlider *slider = GNT_SLIDER(bindable);
+	gnt_slider_set_value(slider, slider->max);
+	return TRUE;
+}
+
 static void
 gnt_slider_class_init(GntSliderClass *klass)
 {
@@ -165,8 +209,14 @@
 	gnt_bindable_register_binding(bindable, "step-backward", GNT_KEY_DOWN, NULL);
 	gnt_bindable_class_register_action(bindable, "step-forward", step_forward, GNT_KEY_RIGHT, NULL);
 	gnt_bindable_register_binding(bindable, "step-forward", GNT_KEY_UP, NULL);
-
-	/* XXX: how would home/end work? */
+	gnt_bindable_class_register_action(bindable, "small-step-backward", small_step_back, GNT_KEY_CTRL_LEFT, NULL);
+	gnt_bindable_register_binding(bindable, "small-step-backward", GNT_KEY_CTRL_DOWN, NULL);
+	gnt_bindable_class_register_action(bindable, "small-step-forward", small_step_forward, GNT_KEY_CTRL_RIGHT, NULL);
+	gnt_bindable_register_binding(bindable, "small-step-forward", GNT_KEY_CTRL_UP, NULL);
+	gnt_bindable_class_register_action(bindable, "large-step-backward", large_step_back, GNT_KEY_PGDOWN, NULL);
+	gnt_bindable_class_register_action(bindable, "large-step-forward", large_step_forward, GNT_KEY_PGUP, NULL);
+	gnt_bindable_class_register_action(bindable, "min-value", move_min_value, GNT_KEY_HOME, NULL);
+	gnt_bindable_class_register_action(bindable, "max-value", move_max_value, GNT_KEY_END, NULL);
 
 	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
 }
@@ -233,10 +283,14 @@
 
 void gnt_slider_set_value(GntSlider *slider, int value)
 {
+	int old;
 	if (slider->current == value)
 		return;
+	old = slider->current;
 	slider->current = value;
 	sanitize_value(slider);
+	if (old == slider->current)
+		return;
 	redraw_slider(slider);
 	slider_value_changed(slider);
 }
@@ -248,10 +302,7 @@
 
 int gnt_slider_advance_step(GntSlider *slider, int steps)
 {
-	slider->current += steps * slider->step;
-	sanitize_value(slider);
-	redraw_slider(slider);
-	slider_value_changed(slider);
+	gnt_slider_set_value(slider, slider->current + steps * slider->step);
 	return slider->current;
 }
 
@@ -260,6 +311,16 @@
 	slider->step = step;
 }
 
+void gnt_slider_set_small_step(GntSlider *slider, int step)
+{
+	slider->smallstep = step;
+}
+
+void gnt_slider_set_large_step(GntSlider *slider, int step)
+{
+	slider->largestep = step;
+}
+
 void gnt_slider_set_range(GntSlider *slider, int max, int min)
 {
 	slider->max = MAX(max, min);
--- a/finch/libgnt/gntslider.h	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/libgnt/gntslider.h	Sat Aug 25 08:42:33 2007 +0000
@@ -56,6 +56,8 @@
 	int min;        /* minimum value */
 	int step;       /* amount to change at each step */
 	int current;    /* current value */
+	int smallstep;
+	int largestep;
 };
 
 struct _GntSliderClass
@@ -103,11 +105,27 @@
  * Sets the amount of change at each step.
  * 
  * @param slider  The slider
- * @param step    The amount for each ste
+ * @param step    The amount for each step
  */
 void gnt_slider_set_step(GntSlider *slider, int step);
 
 /**
+ * Sets the amount of change a small step.
+ * 
+ * @param slider  The slider
+ * @param step    The amount for a small step (for the slider)
+ */
+void gnt_slider_set_small_step(GntSlider *slider, int step);
+
+/**
+ * Sets the amount of change a large step.
+ * 
+ * @param slider  The slider
+ * @param step    The amount for a large step (for the slider)
+ */
+void gnt_slider_set_large_step(GntSlider *slider, int step);
+
+/**
  * Advance the slider forward or backward.
  *
  * @param slider   The slider
--- a/finch/libgnt/gntstyle.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/libgnt/gntstyle.c	Sat Aug 25 08:42:33 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)
 {
--- a/finch/libgnt/gnttextview.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/libgnt/gnttextview.c	Sat Aug 25 08:42:33 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;
 			}
 		}
--- a/finch/libgnt/gnttree.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/libgnt/gnttree.c	Sat Aug 25 08:42:33 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
 			)
 		);
 
--- a/finch/libgnt/gntutils.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/libgnt/gntutils.c	Sat Aug 25 08:42:33 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);
 }
-
--- a/finch/libgnt/gntutils.h	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/libgnt/gntutils.h	Sat Aug 25 08:42:33 2007 +0000
@@ -27,6 +27,7 @@
 #include <glib.h>
 
 #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
--- a/finch/libgnt/gntwm.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/libgnt/gntwm.c	Sat Aug 25 08:42:33 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
--- a/finch/libgnt/test/tv.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/finch/libgnt/test/tv.c	Sat Aug 25 08:42:33 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("<p><b>Ohoy hoy!!</b><br/><p>I think this is going to</p> <u> WORK!!! </u><a href='www.google.com'>check this out!!</a></p>", GNT_TEXT_VIEW(view));
+
 #ifdef STANDALONE
 	gnt_main();
 
--- a/libpurple/Makefile.am	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/Makefile.am	Sat Aug 25 08:42:33 2007 +0000
@@ -22,9 +22,9 @@
 		win32/giowin32.c \
 		win32/win32dep.h
 
-if USE_GCONFTOOL
-GCONF_DIR=gconf
-endif
+# if USE_GCONFTOOL
+# GCONF_DIR=gconf
+# endif
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = purple.pc
--- a/libpurple/blist.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/blist.c	Sat Aug 25 08:42:33 2007 +0000
@@ -1190,6 +1190,12 @@
 			group = purple_group_new(_("Chats"));
 			purple_blist_add_group(group,
 					purple_blist_get_last_sibling(purplebuddylist->root));
+		} else {
+			/* Add group to blist if isn't already on it. Fixes #2752. */
+			if (!purple_find_group(group->name)) {
+				purple_blist_add_group(group,
+						purple_blist_get_last_sibling(purplebuddylist->root));
+			}
 		}
 	} else {
 		group = (PurpleGroup*)node->parent;
@@ -1284,6 +1290,12 @@
 		g = (PurpleGroup *)((PurpleBlistNode *)c)->parent;
 	} else {
 		if (group) {
+			/* Add chat to blist if isn't already on it. Fixes #2752. */
+			if (!purple_find_group(group->name)) {
+				purple_blist_add_group(group,
+						purple_blist_get_last_sibling(purplebuddylist->root));
+			}
+
 			g = group;
 		} else {
 			g = purple_group_new(_("Buddies"));
--- a/libpurple/idle.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/idle.c	Sat Aug 25 08:42:33 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;
--- a/libpurple/network.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/network.c	Sat Aug 25 08:42:33 2007 +0000
@@ -436,7 +436,7 @@
 static gint
 wpurple_get_connected_network_count(void)
 {
-	guint net_cnt = 0;
+	gint net_cnt = 0;
 
 	WSAQUERYSET qs;
 	HANDLE h;
@@ -521,7 +521,7 @@
 		HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer,
 		DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
 		LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion) = NULL;
- 
+
 	if (!(MyWSANSPIoctl = (void*) wpurple_find_and_loadproc("ws2_32.dll", "WSANSPIoctl"))) {
 		g_thread_exit(NULL);
 		return NULL;
@@ -636,7 +636,7 @@
 purple_network_get_handle(void)
 {
 	static int handle;
-	
+
 	return &handle;
 }
 
@@ -675,7 +675,7 @@
 
 	purple_signal_register(purple_network_get_handle(), "network-configuration-changed",
 						   purple_marshal_VOID, NULL, 0);
-	
+
 	purple_pmp_init();
 	purple_upnp_init();
 }
--- a/libpurple/protocols/bonjour/jabber.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/protocols/bonjour/jabber.c	Sat Aug 25 08:42:33 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 "</stream:stream>" 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);
--- a/libpurple/protocols/bonjour/mdns_win32.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_win32.c	Sat Aug 25 08:42:33 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;
 		}
--- a/libpurple/protocols/msn/servconn.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/protocols/msn/servconn.c	Sat Aug 25 08:42:33 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);
--- a/libpurple/protocols/myspace/CHANGES	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/protocols/myspace/CHANGES	Sat Aug 25 08:42:33 2007 +0000
@@ -1,3 +1,28 @@
+2007-08-23 Jeff Connelly <pidgin@xyzzy.cjb.net> - 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 <pidgin@xyzzy.cjb.net> - 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 <jeff2@soc.pidgin.im> - 0.14
 * Full emoticon support (except no difference between nerd and geek emoticons),
   thanks to a number of new icons from Hylke Bons.
--- a/libpurple/protocols/myspace/README	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/protocols/myspace/README	Sat Aug 25 08:42:33 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
 
--- a/libpurple/protocols/myspace/myspace.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/protocols/myspace/myspace.c	Sat Aug 25 08:42:33 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);
 }
 
--- a/libpurple/protocols/myspace/myspace.h	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/protocols/myspace/myspace.h	Sat Aug 25 08:42:33 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;
 
 
--- a/libpurple/protocols/myspace/release.sh	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/protocols/myspace/release.sh	Sat Aug 25 08:42:33 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.
--- a/libpurple/protocols/oscar/oscar.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Sat Aug 25 08:42:33 2007 +0000
@@ -3555,6 +3555,7 @@
 	PurpleConnection *gc;
 	PurpleAccount *account;
 	PurpleStatus *status;
+	PurplePresence *presence;
 	const char *message, *itmsurl;
 	char *tmp;
 	va_list ap;
@@ -3598,7 +3599,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);
--- a/libpurple/protocols/sametime/sametime.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/protocols/sametime/sametime.c	Sat Aug 25 08:42:33 2007 +0000
@@ -3183,13 +3183,12 @@
   PurpleConnection *gc;
   struct mwPurplePluginData *pd;
   struct mwAwareIdBlock t = { mwAware_USER, b->name, NULL };
-  const char *ret;
-
-  gc = b->account->gc;
-  pd = gc->proto_data;
-
-  ret = mwServiceAware_getText(pd->srvc_aware, &t);
-  
+  const char *ret = NULL;
+
+  if ((gc = purple_account_get_connection(b->account))
+      && (pd = gc->proto_data))
+    ret = mwServiceAware_getText(pd->srvc_aware, &t);
+
   return (ret && g_utf8_validate(ret, -1, NULL)) ? g_markup_escape_text(ret, -1): NULL;
 }
 
@@ -3242,17 +3241,17 @@
 
 static void mw_prpl_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) {
   PurpleConnection *gc;
-  struct mwPurplePluginData *pd;
+  struct mwPurplePluginData *pd = NULL;
   struct mwAwareIdBlock idb = { mwAware_USER, b->name, NULL };
 
-  const char *message;
+  const char *message = NULL;
   const char *status;
   char *tmp;
 
-  gc = b->account->gc;
-  pd = gc->proto_data;
-
-  message = mwServiceAware_getText(pd->srvc_aware, &idb);
+  if ((gc = purple_account_get_connection(b->account))
+      && (pd = gc->proto_data))
+     message = mwServiceAware_getText(pd->srvc_aware, &idb);
+
   status = status_text(b);
 
   if(message != NULL && g_utf8_validate(message, -1, NULL) && purple_utf8_strcasecmp(status, message)) {
@@ -3264,7 +3263,7 @@
 	purple_notify_user_info_add_pair(user_info, _("Status"), status);
   }
 
-  if(full) {
+  if(full && pd != NULL) {
     tmp = user_supports_text(pd->srvc_aware, b->name);
     if(tmp) {
 	  purple_notify_user_info_add_pair(user_info, _("Supports"), tmp);
--- a/libpurple/protocols/yahoo/yahoo.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/protocols/yahoo/yahoo.c	Sat Aug 25 08:42:33 2007 +0000
@@ -2920,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);
--- a/libpurple/protocols/yahoo/yahoo_packet.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/protocols/yahoo/yahoo_packet.c	Sat Aug 25 08:42:33 2007 +0000
@@ -298,7 +298,7 @@
 
 	if (writelen == 0) {
 		purple_input_remove(yd->txhandler);
-		yd->txhandler = -1;
+		yd->txhandler = 0;
 		return;
 	}
 
@@ -359,7 +359,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;
@@ -375,7 +375,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);
--- a/libpurple/protocols/yahoo/yahoochat.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/protocols/yahoo/yahoochat.c	Sat Aug 25 08:42:33 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);
 }
--- a/libpurple/request.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/request.c	Sat Aug 25 08:42:33 2007 +0000
@@ -1172,7 +1172,7 @@
 
 void *
 purple_request_choice(void *handle, const char *title, const char *primary,
-					const char *secondary, unsigned int default_value,
+					const char *secondary, int default_value,
 					const char *ok_text, GCallback ok_cb,
 					const char *cancel_text, GCallback cancel_cb,
 					PurpleAccount *account, const char *who, PurpleConversation *conv,
@@ -1197,7 +1197,7 @@
 void *
 purple_request_choice_varg(void *handle, const char *title,
 			 const char *primary, const char *secondary,
-			 unsigned int default_value,
+			 int default_value,
 			 const char *ok_text, GCallback ok_cb,
 			 const char *cancel_text, GCallback cancel_cb,
 			 PurpleAccount *account, const char *who, PurpleConversation *conv,
@@ -1233,7 +1233,7 @@
 
 void *
 purple_request_action(void *handle, const char *title, const char *primary,
-					const char *secondary, unsigned int default_action,
+					const char *secondary, int default_action,
 					PurpleAccount *account, const char *who, PurpleConversation *conv,
 					void *user_data, size_t action_count, ...)
 {
@@ -1254,7 +1254,7 @@
 void *
 purple_request_action_varg(void *handle, const char *title,
 						 const char *primary, const char *secondary,
-						 unsigned int default_action,
+						 int default_action,
 						 PurpleAccount *account, const char *who, PurpleConversation *conv,
 						  void *user_data, size_t action_count, va_list actions)
 {
--- a/libpurple/request.h	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/request.h	Sat Aug 25 08:42:33 2007 +0000
@@ -190,13 +190,13 @@
 						   PurpleAccount *account, const char *who, PurpleConversation *conv,
 						   void *user_data);
 	void *(*request_choice)(const char *title, const char *primary,
-							const char *secondary, unsigned int default_value,
+							const char *secondary, int default_value,
 							const char *ok_text, GCallback ok_cb,
 							const char *cancel_text, GCallback cancel_cb,
 							PurpleAccount *account, const char *who, PurpleConversation *conv,
 							void *user_data, va_list choices);
 	void *(*request_action)(const char *title, const char *primary,
-							const char *secondary, unsigned int default_action,
+							const char *secondary, int default_action,
 							PurpleAccount *account, const char *who, PurpleConversation *conv,
 							void *user_data, size_t action_count,
 							va_list actions);
@@ -1215,7 +1215,7 @@
  * @param cancel_cb     The callback for the @c Cancel button.
  * @param account		The PurpleAccount associated with this request, or NULL if none is
  * @param who			The username of the buddy assocaited with this request, or NULL if none is
- * @param conv			The PurpleConversation associated with this request, or NULL if none is 
+ * @param conv			The PurpleConversation associated with this request, or NULL if none is
  * @param user_data     The data to pass to the callback.
  * @param ...           The choices.  This argument list should be
  *                      terminated with a NULL parameter.
@@ -1224,7 +1224,7 @@
  */
 void *purple_request_choice(void *handle, const char *title,
 						  const char *primary, const char *secondary,
-						  unsigned int default_value,
+						  int default_value,
 						  const char *ok_text, GCallback ok_cb,
 						  const char *cancel_text, GCallback cancel_cb,
 						  PurpleAccount *account, const char *who, PurpleConversation *conv,
@@ -1246,7 +1246,7 @@
  * @param cancel_cb     The callback for the @c Cancel button.
  * @param account		The PurpleAccount associated with this request, or NULL if none is
  * @param who			The username of the buddy assocaited with this request, or NULL if none is
- * @param conv			The PurpleConversation associated with this request, or NULL if none is 
+ * @param conv			The PurpleConversation associated with this request, or NULL if none is
  * @param user_data     The data to pass to the callback.
  * @param choices       The choices.  This argument list should be
  *                      terminated with a @c NULL parameter.
@@ -1255,7 +1255,7 @@
  */
 void *purple_request_choice_varg(void *handle, const char *title,
 							   const char *primary, const char *secondary,
-							   unsigned int default_value,
+							   int default_value,
 							   const char *ok_text, GCallback ok_cb,
 							   const char *cancel_text, GCallback cancel_cb,
 							   PurpleAccount *account, const char *who, PurpleConversation *conv,
@@ -1275,7 +1275,7 @@
  * @param default_action The default value.
  * @param account		 The PurpleAccount associated with this request, or NULL if none is
  * @param who			 The username of the buddy assocaited with this request, or NULL if none is
- * @param conv			 The PurpleConversation associated with this request, or NULL if none is 
+ * @param conv			 The PurpleConversation associated with this request, or NULL if none is
  * @param user_data      The data to pass to the callback.
  * @param action_count   The number of actions.
  * @param ...            A list of actions.  These are pairs of
@@ -1290,7 +1290,7 @@
  */
 void *purple_request_action(void *handle, const char *title,
 						  const char *primary, const char *secondary,
-						  unsigned int default_action,
+						  int default_action,
 						  PurpleAccount *account, const char *who, PurpleConversation *conv,
 						  void *user_data, size_t action_count, ...);
 
@@ -1308,7 +1308,7 @@
  * @param default_action The default value.
  * @param account		 The PurpleAccount associated with this request, or NULL if none is
  * @param who			 The username of the buddy assocaited with this request, or NULL if none is
- * @param conv			 The PurpleConversation associated with this request, or NULL if none is 
+ * @param conv			 The PurpleConversation associated with this request, or NULL if none is
  * @param user_data      The data to pass to the callback.
  * @param action_count   The number of actions.
  * @param actions        A list of actions and callbacks.
@@ -1317,7 +1317,7 @@
  */
 void *purple_request_action_varg(void *handle, const char *title,
 							   const char *primary, const char *secondary,
-							   unsigned int default_action,
+							   int default_action,
 							   PurpleAccount *account, const char *who, PurpleConversation *conv,
 							   void *user_data, size_t action_count,
 							   va_list actions);
@@ -1338,7 +1338,7 @@
  * @param cancel_cb   The callback for the @c Cancel button.
  * @param account	  The PurpleAccount associated with this request, or NULL if none is
  * @param who		  The username of the buddy associated with this request, or NULL if none is
- * @param conv		  The PurpleConversation associated with this request, or NULL if none is 
+ * @param conv		  The PurpleConversation associated with this request, or NULL if none is
  * @param user_data   The data to pass to the callback.
  *
  * @return A UI-specific handle.
@@ -1411,7 +1411,7 @@
  * @param cancel_cb   The callback for the @c Cancel button.
  * @param account	  The PurpleAccount associated with this request, or NULL if none is
  * @param who		  The username of the buddy assocaited with this request, or NULL if none is
- * @param conv		  The PurpleConversation associated with this request, or NULL if none is 
+ * @param conv		  The PurpleConversation associated with this request, or NULL if none is
  * @param user_data   The data to pass to the callback.
  *
  * @return A UI-specific handle.
@@ -1435,7 +1435,7 @@
  * @param cancel_cb   The callback for the @c Cancel button.
  * @param account	  The PurpleAccount associated with this request, or NULL if none is
  * @param who		  The username of the buddy assocaited with this request, or NULL if none is
- * @param conv		  The PurpleConversation associated with this request, or NULL if none is 
+ * @param conv		  The PurpleConversation associated with this request, or NULL if none is
  * @param user_data   The data to pass to the callback.
  *
  * @return A UI-specific handle.
--- a/libpurple/util.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/util.c	Sat Aug 25 08:42:33 2007 +0000
@@ -1376,7 +1376,7 @@
 								g_string_free(cdata, TRUE);
 								cdata = NULL;
 							}
-							
+
 						}
 						if(tags == tag)
 							break;
@@ -1427,7 +1427,7 @@
 				ALLOW_TAG("strong");
 				ALLOW_TAG("ul");
 
-				
+
 				/* we skip <HR> because it's not legal in XHTML-IM.  However,
 				 * we still want to send something sensible, so we put a
 				 * linebreak in its place. <BR> also needs special handling
@@ -2541,7 +2541,7 @@
  * people's settings if there is a problem writing the new values.
  */
 gboolean
-purple_util_write_data_to_file(const char *filename, const char *data, size_t size)
+purple_util_write_data_to_file(const char *filename, const char *data, gssize size)
 {
 	const char *user_dir = purple_user_dir();
 	gchar *filename_temp, *filename_full;
@@ -4307,7 +4307,7 @@
 	}
 }
 
-gboolean purple_message_meify(char *message, size_t len)
+gboolean purple_message_meify(char *message, gssize len)
 {
 	char *c;
 	gboolean inside_html = FALSE;
--- a/libpurple/util.h	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/util.h	Sat Aug 25 08:42:33 2007 +0000
@@ -586,7 +586,7 @@
  * @return TRUE if the file was written successfully.  FALSE otherwise.
  */
 gboolean purple_util_write_data_to_file(const char *filename, const char *data,
-									  size_t size);
+									  gssize size);
 
 /**
  * Read the contents of a given file and parse the results into an
@@ -1113,7 +1113,7 @@
  * @return TRUE if it starts with "/me ", and it has been removed, otherwise
  *         FALSE
  */
-gboolean purple_message_meify(char *message, size_t len);
+gboolean purple_message_meify(char *message, gssize len);
 
 /**
  * Removes the underscore characters from a string used identify the mnemonic
--- a/libpurple/win32/global.mak	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/win32/global.mak	Sat Aug 25 08:42:33 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
--- a/libpurple/xmlnode.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/libpurple/xmlnode.c	Sat Aug 25 08:42:33 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;
 			}
 		}
 	}
--- a/pidgin/gtkaccount.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/pidgin/gtkaccount.c	Sat Aug 25 08:42:33 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);
--- a/pidgin/gtkrequest.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/pidgin/gtkrequest.c	Sat Aug 25 08:42:33 2007 +0000
@@ -442,7 +442,7 @@
 
 static void *
 pidgin_request_choice(const char *title, const char *primary,
-			const char *secondary, unsigned int default_value,
+			const char *secondary, int default_value,
 			const char *ok_text, GCallback ok_cb,
 			const char *cancel_text, GCallback cancel_cb,
 			PurpleAccount *account, const char *who, PurpleConversation *conv,
@@ -548,7 +548,7 @@
 
 static void *
 pidgin_request_action(const char *title, const char *primary,
-						const char *secondary, unsigned int default_action,
+						const char *secondary, int default_action,
 					    PurpleAccount *account, const char *who, PurpleConversation *conv,
 						void *user_data, size_t action_count, va_list actions)
 {
@@ -1083,7 +1083,7 @@
 	data->cbs[0] = ok_cb;
 	data->cbs[1] = cancel_cb;
 
-	
+
 #ifdef _WIN32
 	data->dialog = win = pidgin_create_window(PIDGIN_ALERT_TITLE, PIDGIN_HIG_BORDER, "multifield", TRUE) ;
 #else /* !_WIN32 */
--- a/pidgin/gtksavedstatuses.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/pidgin/gtksavedstatuses.c	Sat Aug 25 08:42:33 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);
 }
 
--- a/pidgin/gtksound.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/pidgin/gtksound.c	Sat Aug 25 08:42:33 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);
--- a/pidgin/gtkstatusbox.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/pidgin/gtkstatusbox.c	Sat Aug 25 08:42:33 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",
--- a/pidgin/plugins/musicmessaging/musicmessaging.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/pidgin/plugins/musicmessaging/musicmessaging.c	Sat Aug 25 08:42:33 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))
--- a/pidgin/plugins/spellchk.c	Thu Aug 23 06:53:06 2007 +0000
+++ b/pidgin/plugins/spellchk.c	Sat Aug 25 08:42:33 2007 +0000
@@ -667,7 +667,7 @@
 	return;
 }
 
-static int buf_get_line(char *ibuf, char **buf, int *position, int len)
+static int buf_get_line(char *ibuf, char **buf, int *position, gsize len)
 {
 	int pos = *position;
 	int spos = pos;