changeset 18358:b246ffeb4756

propagate from branch 'im.pidgin.pidgin' (head 85bfdd599b8244d85271918b48154ff6285139c4) to branch 'im.pidgin.soc.2007.remotelogging' (head e6821cf07a8379217524672c800445ffe3580c58)
author Michael Shkutkov <mshkutkov@soc.pidgin.im>
date Fri, 29 Jun 2007 18:03:53 +0000
parents 2177a11e169d (diff) 54251fa6389d (current diff)
children d1e7c8015308
files COPYRIGHT
diffstat 99 files changed, 1305 insertions(+), 407 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Tue Jun 26 19:53:55 2007 +0000
+++ b/COPYRIGHT	Fri Jun 29 18:03:53 2007 +0000
@@ -357,6 +357,7 @@
 Cestonaro Thilo
 Will Thompson
 Douglas Thrift (douglaswth)
+Mark Tiefenbruck
 Andrew Tinney
 Jeffery To
 Warren Togami
--- a/Doxyfile.in	Tue Jun 26 19:53:55 2007 +0000
+++ b/Doxyfile.in	Fri Jun 29 18:03:53 2007 +0000
@@ -432,8 +432,9 @@
 # with spaces.
 
 INPUT                  = libpurple \
-						 finch \
-						 pidgin \
+	                     finch \
+	                     finch/libgnt \
+	                     pidgin \
                          doc
 
 # If the value of the INPUT tag contains directories, you can use the 
--- a/doc/notify-signals.dox	Tue Jun 26 19:53:55 2007 +0000
+++ b/doc/notify-signals.dox	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,4 @@
-/** @page conversation-signals Notification Signals
+/** @page notify-signals Notification Signals
 
  @signals
   @signal displaying-userinfo
--- a/finch/finch.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/finch.c	Fri Jun 29 18:03:53 2007 +0000
@@ -381,10 +381,12 @@
 {
 	signal(SIGPIPE, SIG_IGN);
 
+	g_set_application_name(_("Finch"));
+
 	/* Initialize the libpurple stuff */
 	if (!init_libpurple(argc, argv))
 		return 0;
-
+ 
 	purple_blist_show();
 	gnt_main();
 
--- a/finch/gntaccount.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/gntaccount.c	Fri Jun 29 18:03:53 2007 +0000
@@ -645,8 +645,10 @@
 	GList *iter;
 	GntWidget *box, *button;
 
-	if (accounts.window)
+	if (accounts.window) {
+		gnt_window_present(accounts.window);
 		return;
+	}
 
 	accounts.window = gnt_vbox_new(FALSE);
 	gnt_box_set_toplevel(GNT_BOX(accounts.window), TRUE);
--- a/finch/gntblist.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/gntblist.c	Fri Jun 29 18:03:53 2007 +0000
@@ -1260,7 +1260,7 @@
 }
 
 static void
-tooltip_for_buddy(PurpleBuddy *buddy, GString *str)
+tooltip_for_buddy(PurpleBuddy *buddy, GString *str, gboolean full)
 {
 	PurplePlugin *prpl;
 	PurplePluginProtocolInfo *prpl_info;
@@ -1273,7 +1273,7 @@
 
 	account = purple_buddy_get_account(buddy);
 
-	if (g_utf8_collate(purple_buddy_get_name(buddy), alias))
+	if (!full || g_utf8_collate(purple_buddy_get_name(buddy), alias))
 		purple_notify_user_info_add_pair(user_info, _("Nickname"), alias);
 
 	tmp = g_strdup_printf("%s (%s)",
@@ -1285,7 +1285,7 @@
 	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
 	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 	if (prpl_info && prpl_info->tooltip_text) {
-		prpl_info->tooltip_text(buddy, user_info, TRUE);
+		prpl_info->tooltip_text(buddy, user_info, full);
 	}
 
 	if (purple_prefs_get_bool("/finch/blist/idletime")) {
@@ -1357,7 +1357,7 @@
 		const char *name = purple_buddy_get_name(pr);
 
 		title = g_strdup(name);
-		tooltip_for_buddy(pr, str);
+		tooltip_for_buddy(pr, str, TRUE);
 		for (node = node->child; node; node = node->next) {
 			PurpleBuddy *buddy = (PurpleBuddy*)node;
 			if (offline) {
@@ -1372,11 +1372,11 @@
 			if (!showoffline && !PURPLE_BUDDY_IS_ONLINE(buddy))
 				continue;
 			str = g_string_append(str, "\n----------\n");
-			tooltip_for_buddy(buddy, str);
+			tooltip_for_buddy(buddy, str, FALSE);
 		}
 	} else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
 		PurpleBuddy *buddy = (PurpleBuddy *)node;
-		tooltip_for_buddy(buddy, str);
+		tooltip_for_buddy(buddy, str, TRUE);
 		title = g_strdup(purple_buddy_get_name(buddy));
 		if (!PURPLE_BUDDY_IS_ONLINE((PurpleBuddy*)node))
 			lastseen = purple_blist_node_get_int(node, "last_seen");
@@ -1422,9 +1422,10 @@
 
 	str = make_sure_text_fits(str);
 	gnt_util_get_text_bound(str->str, &w, &h);
-	h = MAX(2, h);
+	h = MAX(1, h);
 	tv = gnt_text_view_new();
 	gnt_widget_set_size(tv, w + 1, h);
+	gnt_text_view_set_flag(GNT_TEXT_VIEW(tv), GNT_TEXT_VIEW_NO_SCROLL);
 	gnt_box_add_widget(GNT_BOX(box), tv);
 
 	gnt_widget_set_position(box, x, y);
@@ -2249,8 +2250,10 @@
 {
 	if (ggblist == NULL)
 		new_list(list);
-	else if (ggblist->window)
+	else if (ggblist->window) {
+		gnt_window_present(ggblist->window);
 		return;
+	}
 
 	ggblist->window = gnt_vwindow_new(FALSE);
 	gnt_widget_set_name(ggblist->window, "buddylist");
--- a/finch/gntdebug.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/gntdebug.c	Fri Jun 29 18:03:53 2007 +0000
@@ -221,56 +221,59 @@
 
 void finch_debug_window_show()
 {
+	GntWidget *wid, *box;
+
 	debug.paused = FALSE;
-	if (debug.window == NULL)
-	{
-		GntWidget *wid, *box;
-		debug.window = gnt_vbox_new(FALSE);
-		gnt_box_set_toplevel(GNT_BOX(debug.window), TRUE);
-		gnt_box_set_title(GNT_BOX(debug.window), _("Debug Window"));
-		gnt_box_set_pad(GNT_BOX(debug.window), 0);
-		gnt_box_set_alignment(GNT_BOX(debug.window), GNT_ALIGN_MID);
+	if (debug.window) {
+		gnt_window_present(debug.window);
+		return;
+	}
 
-		debug.tview = gnt_text_view_new();
-		gnt_box_add_widget(GNT_BOX(debug.window), debug.tview);
-		gnt_widget_set_size(debug.tview,
-				purple_prefs_get_int(PREF_ROOT "/size/width"),
-				purple_prefs_get_int(PREF_ROOT "/size/height"));
-		g_signal_connect(G_OBJECT(debug.tview), "size_changed", G_CALLBACK(size_changed_cb), NULL);
+	debug.window = gnt_vbox_new(FALSE);
+	gnt_box_set_toplevel(GNT_BOX(debug.window), TRUE);
+	gnt_box_set_title(GNT_BOX(debug.window), _("Debug Window"));
+	gnt_box_set_pad(GNT_BOX(debug.window), 0);
+	gnt_box_set_alignment(GNT_BOX(debug.window), GNT_ALIGN_MID);
 
-		gnt_box_add_widget(GNT_BOX(debug.window), gnt_line_new(FALSE));
+	debug.tview = gnt_text_view_new();
+	gnt_box_add_widget(GNT_BOX(debug.window), debug.tview);
+	gnt_widget_set_size(debug.tview,
+			purple_prefs_get_int(PREF_ROOT "/size/width"),
+			purple_prefs_get_int(PREF_ROOT "/size/height"));
+	g_signal_connect(G_OBJECT(debug.tview), "size_changed", G_CALLBACK(size_changed_cb), NULL);
 
-		box = gnt_hbox_new(FALSE);
-		gnt_box_set_alignment(GNT_BOX(box), GNT_ALIGN_MID);
-		gnt_box_set_fill(GNT_BOX(box), FALSE);
+	gnt_box_add_widget(GNT_BOX(debug.window), gnt_line_new(FALSE));
+
+	box = gnt_hbox_new(FALSE);
+	gnt_box_set_alignment(GNT_BOX(box), GNT_ALIGN_MID);
+	gnt_box_set_fill(GNT_BOX(box), FALSE);
 
-		/* XXX: Setting the GROW_Y for the following widgets don't make sense. But right now
-		 * it's necessary to make the width of the debug window resizable ... like I said,
-		 * it doesn't make sense. The bug is likely in the packing in gntbox.c.
-		 */
-		wid = gnt_button_new(_("Clear"));
-		g_signal_connect(G_OBJECT(wid), "activate", G_CALLBACK(clear_debug_win), debug.tview);
-		GNT_WIDGET_SET_FLAGS(wid, GNT_WIDGET_GROW_Y);
-		gnt_box_add_widget(GNT_BOX(box), wid);
-
-		debug.search = gnt_entry_new(purple_prefs_get_string(PREF_ROOT "/filter"));
-		gnt_box_add_widget(GNT_BOX(box), gnt_label_new(_("Filter: ")));
-		gnt_box_add_widget(GNT_BOX(box), debug.search);
-		g_signal_connect(G_OBJECT(debug.search), "text_changed", G_CALLBACK(update_filter_string), NULL);
+	/* XXX: Setting the GROW_Y for the following widgets don't make sense. But right now
+	 * it's necessary to make the width of the debug window resizable ... like I said,
+	 * it doesn't make sense. The bug is likely in the packing in gntbox.c.
+	 */
+	wid = gnt_button_new(_("Clear"));
+	g_signal_connect(G_OBJECT(wid), "activate", G_CALLBACK(clear_debug_win), debug.tview);
+	GNT_WIDGET_SET_FLAGS(wid, GNT_WIDGET_GROW_Y);
+	gnt_box_add_widget(GNT_BOX(box), wid);
 
-		wid = gnt_check_box_new(_("Pause"));
-		g_signal_connect(G_OBJECT(wid), "toggled", G_CALLBACK(toggle_pause), NULL);
-		GNT_WIDGET_SET_FLAGS(wid, GNT_WIDGET_GROW_Y);
-		gnt_box_add_widget(GNT_BOX(box), wid);
+	debug.search = gnt_entry_new(purple_prefs_get_string(PREF_ROOT "/filter"));
+	gnt_box_add_widget(GNT_BOX(box), gnt_label_new(_("Filter: ")));
+	gnt_box_add_widget(GNT_BOX(box), debug.search);
+	g_signal_connect(G_OBJECT(debug.search), "text_changed", G_CALLBACK(update_filter_string), NULL);
 
-		gnt_box_add_widget(GNT_BOX(debug.window), box);
-		GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_GROW_Y);
+	wid = gnt_check_box_new(_("Pause"));
+	g_signal_connect(G_OBJECT(wid), "toggled", G_CALLBACK(toggle_pause), NULL);
+	GNT_WIDGET_SET_FLAGS(wid, GNT_WIDGET_GROW_Y);
+	gnt_box_add_widget(GNT_BOX(box), wid);
 
-		gnt_widget_set_name(debug.window, "debug-window");
+	gnt_box_add_widget(GNT_BOX(debug.window), box);
+	GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_GROW_Y);
 
-		g_signal_connect(G_OBJECT(debug.window), "destroy", G_CALLBACK(reset_debug_win), NULL);
-		gnt_text_view_attach_scroll_widget(GNT_TEXT_VIEW(debug.tview), debug.window);
-	}
+	gnt_widget_set_name(debug.window, "debug-window");
+
+	g_signal_connect(G_OBJECT(debug.window), "destroy", G_CALLBACK(reset_debug_win), NULL);
+	gnt_text_view_attach_scroll_widget(GNT_TEXT_VIEW(debug.tview), debug.window);
 
 	gnt_widget_show(debug.window);
 }
--- a/finch/gntft.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/gntft.c	Fri Jun 29 18:03:53 2007 +0000
@@ -262,6 +262,8 @@
 {
 	if (xfer_dialog == NULL)
 		finch_xfer_dialog_new();
+	else
+		gnt_window_present(xfer_dialog->window);
 }
 
 void
--- a/finch/gntnotify.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/gntnotify.c	Fri Jun 29 18:03:53 2007 +0000
@@ -304,7 +304,7 @@
 	PurpleAccount *account = g_object_get_data(G_OBJECT(widget), "notify-account");
 	gpointer data = g_object_get_data(G_OBJECT(widget), "notify-data");
 
-	list = gnt_tree_get_selection_text_list(GNT_TREE(widget));
+	list = gnt_tree_get_selection_text_list(GNT_TREE(g_object_get_data(G_OBJECT(widget), "notify-tree")));
 
 	b->callback(purple_account_get_connection(account), list, data);
 	g_list_foreach(list, (GFunc)g_free, NULL);
@@ -335,23 +335,31 @@
 {
 	GntWidget *window, *tree, *box, *button;
 	GList *iter;
+	int columns, i;
 
 	window = gnt_vbox_new(FALSE);
 	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
 	gnt_box_set_title(GNT_BOX(window), title);
-	gnt_box_set_fill(GNT_BOX(window), FALSE);
+	gnt_box_set_fill(GNT_BOX(window), TRUE);
 	gnt_box_set_pad(GNT_BOX(window), 0);
 	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
 
-	gnt_box_add_widget(GNT_BOX(window),
+	if (primary)
+		gnt_box_add_widget(GNT_BOX(window),
 			gnt_label_new_with_format(primary, GNT_TEXT_FLAG_BOLD));
-	gnt_box_add_widget(GNT_BOX(window),
+	if (secondary)
+		gnt_box_add_widget(GNT_BOX(window),
 			gnt_label_new_with_format(secondary, GNT_TEXT_FLAG_NORMAL));
 
-	tree = gnt_tree_new_with_columns(g_list_length(results->columns));
+	columns = purple_notify_searchresults_get_columns_count(results);
+	tree = gnt_tree_new_with_columns(columns);
 	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
 	gnt_box_add_widget(GNT_BOX(window), tree);
 
+	for (i = 0; i < columns; i++)
+		gnt_tree_set_column_title(GNT_TREE(tree), i, 
+				purple_notify_searchresults_column_get_title(results, i));
+
 	box = gnt_hbox_new(TRUE);
 
 	for (iter = results->buttons; iter; iter = iter->next)
@@ -389,7 +397,8 @@
 		button = gnt_button_new(text);
 		g_object_set_data(G_OBJECT(button), "notify-account", purple_connection_get_account(gc));
 		g_object_set_data(G_OBJECT(button), "notify-data", data);
-		g_signal_connect_swapped(G_OBJECT(button), "activate",
+		g_object_set_data(G_OBJECT(button), "notify-tree", tree);
+		g_signal_connect(G_OBJECT(button), "activate",
 				G_CALLBACK(notify_button_activated), b);
 
 		gnt_box_add_widget(GNT_BOX(box), button);
--- a/finch/gntplugin.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/gntplugin.c	Fri Jun 29 18:03:53 2007 +0000
@@ -242,8 +242,10 @@
 	GList *iter;
 	GList *seen;
 
-	if (plugins.window)
+	if (plugins.window) {
+		gnt_window_present(plugins.window);
 		return;
+	}
 
 	purple_plugins_probe(G_MODULE_SUFFIX);
 
@@ -277,6 +279,14 @@
 	{
 		PurplePlugin *plug = iter->data;
 
+		if (plug->info->type == PURPLE_PLUGIN_LOADER) {
+			GList *cur;
+			for (cur = PURPLE_PLUGIN_LOADER_INFO(plug)->exts; cur != NULL;
+					 cur = cur->next)
+				purple_plugins_probe(cur->data);
+			continue;
+		}
+
 		if (plug->info->type != PURPLE_PLUGIN_STANDARD ||
 			(plug->info->flags & PURPLE_PLUGIN_FLAG_INVISIBLE) ||
 			plug->error)
--- a/finch/gntpounce.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/gntpounce.c	Fri Jun 29 18:03:53 2007 +0000
@@ -672,6 +672,7 @@
 	GntWidget *win;
 
 	if (pounces_manager != NULL) {
+		gnt_window_present(pounces_manager->window);
 		return;
 	}
 
--- a/finch/gntprefs.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/gntprefs.c	Fri Jun 29 18:03:53 2007 +0000
@@ -30,9 +30,16 @@
 #include "gntprefs.h"
 #include "gntrequest.h"
 
+#include "gnt.h"
+#include "gntwidget.h"
+
 #include <string.h>
 
-static GList *freestrings;  /* strings to be freed when the pref-window is closed */
+static struct {
+	GList *freestrings;  /* strings to be freed when the pref-window is closed */
+	gboolean showing;
+	GntWidget *window;
+} pref_request;
 
 void finch_prefs_init()
 {
@@ -98,7 +105,7 @@
 		str = g_strdup_printf("%ld", purple_savedstatus_get_creation_time(iter->data));
 		list = g_list_append(list, (char*)purple_savedstatus_get_title(iter->data));
 		list = g_list_append(list, str);
-		freestrings = g_list_prepend(freestrings, str);
+		pref_request.freestrings = g_list_prepend(pref_request.freestrings, str);
 	}
 	return list;
 }
@@ -190,22 +197,22 @@
 	{PURPLE_PREF_NONE, NULL, NULL, NULL},
 };
 
-/* XXX: Translate after the freeze */
 static Prefs idle[] =
 {
-	{PURPLE_PREF_STRING, "/purple/away/idle_reporting", "Report Idle time", get_idle_options},
-	{PURPLE_PREF_BOOLEAN, "/purple/away/away_when_idle", "Change status when idle", NULL},
-	{PURPLE_PREF_INT, "/purple/away/mins_before_away", "Minutes before changing status", NULL},
-	{PURPLE_PREF_INT, "/purple/savedstatus/idleaway", "Change status to", get_status_titles},
+	{PURPLE_PREF_STRING, "/purple/away/idle_reporting", N_("Report Idle time"), get_idle_options},
+	{PURPLE_PREF_BOOLEAN, "/purple/away/away_when_idle", N_("Change status when idle"), NULL},
+	{PURPLE_PREF_INT, "/purple/away/mins_before_away", N_("Minutes before changing status"), NULL},
+	{PURPLE_PREF_INT, "/purple/savedstatus/idleaway", N_("Change status to"), get_status_titles},
 	{PURPLE_PREF_NONE, NULL, NULL, NULL},
 };
 
 static void
 free_strings()
 {
-	g_list_foreach(freestrings, (GFunc)g_free, NULL);
-	g_list_free(freestrings);
-	freestrings = NULL;
+	g_list_foreach(pref_request.freestrings, (GFunc)g_free, NULL);
+	g_list_free(pref_request.freestrings);
+	pref_request.freestrings = NULL;
+	pref_request.showing = FALSE;
 }
 
 static void
@@ -236,6 +243,11 @@
 {
 	PurpleRequestFields *fields;
 
+	if (pref_request.showing) {
+		gnt_window_present(pref_request.window);
+		return;
+	}
+
 	fields = purple_request_fields_new();
 
 	add_pref_group(fields, _("Buddy List"), blist);
@@ -243,7 +255,8 @@
 	add_pref_group(fields, _("Logging"), logging);
 	add_pref_group(fields, _("Idle"), idle);
 
-	purple_request_fields(NULL, _("Preferences"), NULL, NULL, fields,
+	pref_request.showing = TRUE;
+	pref_request.window = purple_request_fields(NULL, _("Preferences"), NULL, NULL, fields,
 			_("Save"), G_CALLBACK(save_cb), _("Cancel"), free_strings,
 			NULL, NULL, NULL,
 			NULL);
--- a/finch/gntrequest.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/gntrequest.c	Fri Jun 29 18:03:53 2007 +0000
@@ -67,8 +67,35 @@
 	return window;
 }
 
+/**
+ * If the window is closed by the wm (ie, without triggering any of
+ * the buttons, then do some default callback.
+ */
+static void
+setup_default_callback(GntWidget *window, gpointer default_cb, gpointer data)
+{
+	g_object_set_data(G_OBJECT(window), "default-callback", default_cb);
+	g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(default_cb), data);
+}
+
+static void
+action_performed(GntWidget *button, gpointer data)
+{
+	g_signal_handlers_disconnect_matched(data, G_SIGNAL_MATCH_FUNC,
+			0, 0, NULL,
+			g_object_get_data(data, "default-callback"),
+			 NULL);
+}
+
+/**
+ * window: this is the window
+ * userdata: the userdata to pass to the primary callbacks
+ * cb: the callback
+ * data: data for the callback
+ * (text, primary-callback) pairs, ended by a NULL
+ */
 static GntWidget *
-setup_button_box(gpointer userdata, gpointer cb, gpointer data, ...)
+setup_button_box(GntWidget *win, gpointer userdata, gpointer cb, gpointer data, ...)
 {
 	GntWidget *box, *button;
 	va_list list;
@@ -86,6 +113,7 @@
 		gnt_box_add_widget(GNT_BOX(box), button);
 		g_object_set_data(G_OBJECT(button), "activate-callback", callback);
 		g_object_set_data(G_OBJECT(button), "activate-userdata", userdata);
+		g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(action_performed), win);
 		g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(cb), data);
 	}
 
@@ -127,10 +155,11 @@
 		gnt_entry_set_masked(GNT_ENTRY(entry), TRUE);
 	gnt_box_add_widget(GNT_BOX(window), entry);
 
-	box = setup_button_box(user_data, notify_input_cb, entry,
+	box = setup_button_box(window, user_data, notify_input_cb, entry,
 			ok_text, ok_cb, cancel_text, cancel_cb, NULL);
 	gnt_box_add_widget(GNT_BOX(window), box);
 
+	setup_default_callback(window, cancel_cb, user_data);
 	gnt_widget_show(window);
 
 	return window;
@@ -189,10 +218,11 @@
 	}
 	gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), GINT_TO_POINTER(default_value + 1));
 
-	box = setup_button_box(user_data, request_choice_cb, combo,
+	box = setup_button_box(window, user_data, request_choice_cb, combo,
 			ok_text, ok_cb, cancel_text, cancel_cb, NULL);
 	gnt_box_add_widget(GNT_BOX(window), box);
 
+	setup_default_callback(window, cancel_cb, user_data);
 	gnt_widget_show(window);
 	
 	return window;
@@ -538,10 +568,11 @@
 	}
 	gnt_box_add_widget(GNT_BOX(window), box);
 
-	box = setup_button_box(userdata, request_fields_cb, allfields,
+	box = setup_button_box(window, userdata, request_fields_cb, allfields,
 			ok, ok_cb, cancel, cancel_cb, NULL);
 	gnt_box_add_widget(GNT_BOX(window), box);
 
+	setup_default_callback(window, cancel_cb, userdata);
 	gnt_widget_show(window);
 
 	g_object_set_data(G_OBJECT(window), "fields", allfields);
--- a/finch/gntstatus.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/gntstatus.c	Fri Jun 29 18:03:53 2007 +0000
@@ -163,8 +163,10 @@
 void finch_savedstatus_show_all()
 {
 	GntWidget *window, *tree, *box, *button;
-	if (statuses.window)
+	if (statuses.window) {
+		gnt_window_present(statuses.window);
 		return;
+	}
 
 	statuses.window = window = gnt_vbox_new(FALSE);
 	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
--- a/finch/libgnt/Makefile.am	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/Makefile.am	Fri Jun 29 18:03:53 2007 +0000
@@ -26,6 +26,7 @@
 	gntmenu.c \
 	gntmenuitem.c \
 	gntmenuitemcheck.c \
+	gntslider.c \
 	gntstyle.c \
 	gnttextview.c \
 	gnttree.c \
@@ -53,6 +54,7 @@
 	gntmenu.h \
 	gntmenuitem.h \
 	gntmenuitemcheck.h \
+	gntslider.h \
 	gntstyle.h \
 	gnttextview.h \
 	gnttree.h \
--- a/finch/libgnt/gnt-skel.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gnt-skel.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gnt-skel.h -skel API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- a/finch/libgnt/gnt.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gnt.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,14 @@
 /**
+ * @defgroup gnt GNT (GLib Ncurses Toolkit)
+ *
+ * GNT is an ncurses toolkit for creating text-mode graphical user interfaces
+ * in a fast and easy way.
+ */
+/**
+ * @file gnt.h GNT API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- a/finch/libgnt/gntbindable.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntbindable.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntbindable.h Bindable API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- a/finch/libgnt/gntbox.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntbox.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntbox.h Box API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
@@ -84,9 +88,8 @@
 G_BEGIN_DECLS
 
 /**
- * 
- *
- * @return
+ * The GType for GntBox.
+ * @return The GType.
  */
 GType gnt_box_get_gtype(void);
 
@@ -94,98 +97,110 @@
 #define gnt_hbox_new(homo) gnt_box_new(homo, FALSE)
 
 /**
- * 
- * @param homo
- * @param vert
+ * Create a new GntBox.
  *
- * @return
+ * @param homo  If @c TRUE, all the widgets in it will have the same width (or height)
+ * @param vert  Whether the widgets in it should be stacked vertically (if @c TRUE)
+ *              or horizontally (if @c FALSE).
+ *
+ * @return The new GntBox.
  */
 GntWidget * gnt_box_new(gboolean homo, gboolean vert);
 
 /**
- * 
- * @param box
- * @param widget
+ * Add a widget in the box.
+ *
+ * @param box     The box
+ * @param widget  The widget to add
  */
 void gnt_box_add_widget(GntBox *box, GntWidget *widget);
 
 /**
- * 
- * @param box
- * @param title
+ * Set a title for the box.
+ *
+ * @param box    The box
+ * @param title	 The title to set
  */
 void gnt_box_set_title(GntBox *box, const char *title);
 
 /**
- * 
- * @param box
- * @param pad
+ * Set the padding to use between the widgets in the box.
+ *
+ * @param box The box
+ * @param pad The padding to use
  */
 void gnt_box_set_pad(GntBox *box, int pad);
 
 /**
- * 
- * @param box
- * @param set
+ * Set whether it's a toplevel box (ie, a window) or not. If a box is toplevel,
+ * then it will show borders, the title (if set) and shadow (if enabled in
+ * @e .gntrc)
+ *
+ * @param box The box
+ * @param set @c TRUE if it's a toplevel box, @c FALSE otherwise.
  */
 void gnt_box_set_toplevel(GntBox *box, gboolean set);
 
 /**
- * 
- * @param box
+ * Reposition and refresh the widgets in the box.
+ *
+ * @param box The box
  */
 void gnt_box_sync_children(GntBox *box);
 
 /**
- * 
- * @param box
- * @param alignment
+ * Set the alignment for the widgets in the box.
+ *
+ * @param box       The box
+ * @param alignment The alignment to use
  */
 void gnt_box_set_alignment(GntBox *box, GntAlignment alignment);
 
 /**
- * 
- * @param box
- * @param widget
+ * Remove a widget from the box. Calling this does NOT destroy the removed widget.
+ *
+ * @param box       The box
+ * @param widget    The widget to remove
  */
 void gnt_box_remove(GntBox *box, GntWidget *widget);
 
- /* XXX: does NOT destroy widget */
-
 /**
- * 
- * @param box
+ * Remove all widgets from the box. This DOES destroy all widgets in the box.
+ *
+ * @param box The box
  */
 void gnt_box_remove_all(GntBox *box);
 
-      /* Removes AND destroys all the widgets in it */
-
 /**
- * 
- * @param box
+ * Readjust the size of each child widget, reposition the child widgets and
+ * recalculate the size of the box.
+ *
+ * @param box  The box
  */
 void gnt_box_readjust(GntBox *box);
 
 /**
- * 
- * @param box
- * @param fill
+ * Set whether the widgets in the box should fill the empty spaces.
+ *
+ * @param box   The box
+ * @param fill  Whether the child widgets should fill the empty space
  */
 void gnt_box_set_fill(GntBox *box, gboolean fill);
 
 /**
- * 
- * @param box
- * @param dir
+ * Move the focus from one widget to the other.
+ *
+ * @param box The box
+ * @param dir The direction. If it's 1, then the focus is moved forwards, if it's
+ *            -1, the focus is moved backwards.
  */
 void gnt_box_move_focus(GntBox *box, int dir);
 
-  /* +1 to move forward, -1 for backward */
-
 /**
- * 
- * @param box
- * @param widget
+ * Give focus to a specific child widget.
+ *
+ * @param box       The box
+ * @param widget    The child widget to give focus
  */
 void gnt_box_give_focus_to_child(GntBox *box, GntWidget *widget);
 
--- a/finch/libgnt/gntbutton.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntbutton.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntbutton.h Button API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- a/finch/libgnt/gntcheckbox.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntcheckbox.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntcheckbox.h Checkbox API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- a/finch/libgnt/gntclipboard.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntclipboard.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntclipboard.h Clipboard API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- a/finch/libgnt/gntcolors.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntcolors.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntcolors.h Colors API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- a/finch/libgnt/gntcombobox.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntcombobox.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntcombobox.h Combobox API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- a/finch/libgnt/gntentry.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntentry.c	Fri Jun 29 18:03:53 2007 +0000
@@ -179,7 +179,7 @@
 
 	stop = gnt_util_onscreen_width(entry->scroll, entry->end);
 	if (stop < widget->priv.width)
-		whline(widget->window, ENTRY_CHAR, widget->priv.width - stop);
+		mvwhline(widget->window, 0, stop, ENTRY_CHAR, widget->priv.width - stop);
 
 	if (focus)
 		mvwchgat(widget->window, 0, gnt_util_onscreen_width(entry->scroll, entry->cursor),
--- a/finch/libgnt/gntentry.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntentry.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntentry.h Entry API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- a/finch/libgnt/gntfilesel.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntfilesel.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntfilesel.h File selector API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- a/finch/libgnt/gntkeys.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntkeys.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntkeys.h Keys API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- a/finch/libgnt/gntlabel.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntlabel.c	Fri Jun 29 18:03:53 2007 +0000
@@ -138,8 +138,7 @@
 
 	if (GNT_WIDGET(label)->window)
 	{
-		gnt_widget_hide(GNT_WIDGET(label));
-		gnt_label_size_request(GNT_WIDGET(label));
+		werase(GNT_WIDGET(label)->window);
 		gnt_widget_draw(GNT_WIDGET(label));
 	}
 }
--- a/finch/libgnt/gntlabel.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntlabel.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntlabel.h Label API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- a/finch/libgnt/gntline.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntline.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntline.h Line API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- a/finch/libgnt/gntmain.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntmain.c	Fri Jun 29 18:03:53 2007 +0000
@@ -488,8 +488,12 @@
  * Stuff for 'window management' *
  *********************************/
 
-void gnt_window_present(GntWidget *window) {
-	gnt_wm_raise_window(wm, window);
+void gnt_window_present(GntWidget *window)
+{
+	if (wm->event_stack)
+		gnt_wm_raise_window(wm, window);
+	else
+		gnt_widget_set_urgent(window);
 }
 
 void gnt_screen_occupy(GntWidget *widget)
--- a/finch/libgnt/gntmenu.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntmenu.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntmenu.h Menu API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- a/finch/libgnt/gntmenuitem.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntmenuitem.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntmenuitem.h Menuitem API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- a/finch/libgnt/gntmenuitemcheck.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntmenuitemcheck.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntmenuitemcheck.h Check Menuitem API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntslider.c	Fri Jun 29 18:03:53 2007 +0000
@@ -0,0 +1,277 @@
+/**
+ * GNT - The GLib Ncurses Toolkit
+ *
+ * GNT is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "gntcolors.h"
+#include "gntkeys.h"
+#include "gntslider.h"
+#include "gntstyle.h"
+
+enum
+{
+	SIG_VALUE_CHANGED,
+	SIGS,
+};
+
+static guint signals[SIGS] = { 0 };
+
+static GntWidgetClass *parent_class = NULL;
+
+/* returns TRUE if the value was changed */
+static gboolean
+sanitize_value(GntSlider *slider)
+{
+	if (slider->current < slider->min)
+		slider->current = slider->min;
+	else if (slider->current > slider->max)
+		slider->current = slider->max;
+	else
+		return FALSE;
+	return TRUE;
+}
+
+static void
+redraw_slider(GntSlider *slider)
+{
+	GntWidget *widget = GNT_WIDGET(slider);
+	if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED))
+		gnt_widget_draw(widget);
+}
+
+static void
+slider_value_changed(GntSlider *slider)
+{
+	g_signal_emit(slider, signals[SIG_VALUE_CHANGED], 0, slider->current);
+}
+
+static void
+gnt_slider_draw(GntWidget *widget)
+{
+	GntSlider *slider = GNT_SLIDER(widget);
+	int attr = 0;
+	int position, size = 0;
+
+	if (slider->vertical)
+		size = widget->priv.height;
+	else
+		size = widget->priv.width;
+
+	if (gnt_widget_has_focus(widget))
+		attr |= GNT_COLOR_HIGHLIGHT;
+	else
+		attr |= GNT_COLOR_HIGHLIGHT_D;
+
+	if (slider->max != slider->min)
+		position = ((size - 1) * (slider->current - slider->min)) / (slider->max - slider->min);
+	else
+		position = 0;
+	if (slider->vertical) {
+		mvwvline(widget->window, size-position, 0, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL) | A_BOLD,
+				position);
+		mvwvline(widget->window, 0, 0, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL),
+				size-position);
+	} else {
+		mvwhline(widget->window, 0, 0, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL) | A_BOLD,
+				position);
+		mvwhline(widget->window, 0, position, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL),
+				size - position);
+	}
+
+	mvwaddch(widget->window,
+			slider->vertical ? (size - position - 1) : 0,
+			slider->vertical ? 0 : position,
+			ACS_CKBOARD | COLOR_PAIR(attr));
+}
+
+static void
+gnt_slider_size_request(GntWidget *widget)
+{
+	if (GNT_SLIDER(widget)->vertical) {
+		widget->priv.width = 1;
+		widget->priv.height = 5;
+	} else {
+		widget->priv.width = 5;
+		widget->priv.height = 1;
+	}
+}
+
+static void
+gnt_slider_map(GntWidget *widget)
+{
+	if (widget->priv.width == 0 || widget->priv.height == 0)
+		gnt_widget_size_request(widget);
+	GNTDEBUG;
+}
+
+static gboolean
+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
+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 void
+gnt_slider_class_init(GntSliderClass *klass)
+{
+	GntBindableClass *bindable = GNT_BINDABLE_CLASS(klass);
+	parent_class = GNT_WIDGET_CLASS(klass);
+	parent_class->draw = gnt_slider_draw;
+	parent_class->map = gnt_slider_map;
+	parent_class->size_request = gnt_slider_size_request;
+
+	klass->changed = NULL;
+
+	signals[SIG_VALUE_CHANGED] =
+		g_signal_new("changed",
+		             G_TYPE_FROM_CLASS(klass),
+		             G_SIGNAL_RUN_LAST,
+		             G_STRUCT_OFFSET(GntSliderClass, changed),
+		             NULL, NULL,
+		             g_cclosure_marshal_VOID__INT,
+		             G_TYPE_NONE, 1, G_TYPE_INT);
+
+	gnt_bindable_class_register_action(bindable, "step-backward", step_back, GNT_KEY_LEFT, NULL);
+	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_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
+}
+
+static void
+gnt_slider_init(GTypeInstance *instance, gpointer class)
+{
+	GntWidget *widget = GNT_WIDGET(instance);
+	GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_SHADOW | GNT_WIDGET_NO_BORDER | GNT_WIDGET_CAN_TAKE_FOCUS);
+	widget->priv.minw = 1;
+	widget->priv.minh = 1;
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * GntSlider API
+ *****************************************************************************/
+GType
+gnt_slider_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0)
+	{
+		static const GTypeInfo info = {
+			sizeof(GntSliderClass),
+			NULL,                   /* base_init        */
+			NULL,                   /* base_finalize    */
+			(GClassInitFunc)gnt_slider_class_init,
+			NULL,                   /* class_finalize   */
+			NULL,                   /* class_data       */
+			sizeof(GntSlider),
+			0,                      /* n_preallocs      */
+			gnt_slider_init,        /* instance_init    */
+			NULL                    /* value_table      */
+		};
+
+		type = g_type_register_static(GNT_TYPE_WIDGET,
+		                              "GntSlider",
+		                              &info, 0);
+	}
+
+	return type;
+}
+
+GntWidget *gnt_slider_new(gboolean vertical, int max, int min)
+{
+	GntWidget *widget = g_object_new(GNT_TYPE_SLIDER, NULL);
+	GntSlider *slider = GNT_SLIDER(widget);
+
+	slider->vertical = vertical;
+
+	if (vertical) {
+		GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_Y);
+	} else {
+		GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X);
+	}
+
+	gnt_slider_set_range(slider, max, min);
+	slider->step = 1;
+
+	return widget;
+}
+
+void gnt_slider_set_value(GntSlider *slider, int value)
+{
+	if (slider->current == value)
+		return;
+	slider->current = value;
+	sanitize_value(slider);
+	redraw_slider(slider);
+	slider_value_changed(slider);
+}
+
+int gnt_slider_advance_step(GntSlider *slider, int steps)
+{
+	slider->current += steps * slider->step;
+	sanitize_value(slider);
+	redraw_slider(slider);
+	slider_value_changed(slider);
+	return slider->current;
+}
+
+void gnt_slider_set_step(GntSlider *slider, int step)
+{
+	slider->step = step;
+}
+
+void gnt_slider_set_range(GntSlider *slider, int max, int min)
+{
+	slider->max = MAX(max, min);
+	slider->min = MIN(max, min);
+	sanitize_value(slider);
+}
+
+static void
+update_label(GntSlider *slider, int current_value, GntLabel *label)
+{
+	char value[256];
+	g_snprintf(value, sizeof(value), "%d/%d", current_value, slider->max);
+	gnt_label_set_text(label, value);
+}
+
+void gnt_slider_reflect_label(GntSlider *slider, GntLabel *label)
+{
+	g_signal_connect(G_OBJECT(slider), "changed", G_CALLBACK(update_label), label);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntslider.h	Fri Jun 29 18:03:53 2007 +0000
@@ -0,0 +1,139 @@
+/**
+ * @file gntslider.h Slider API
+ * @ingroup gnt
+ */
+/*
+ * GNT - The GLib Ncurses Toolkit
+ *
+ * GNT is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef GNT_SLIDER_H
+#define GNT_SLIDER_H
+
+#include "gntwidget.h"
+#include "gnt.h"
+#include "gntlabel.h"
+
+#define GNT_TYPE_SLIDER             (gnt_slider_get_gtype())
+#define GNT_SLIDER(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_SLIDER, GntSlider))
+#define GNT_SLIDER_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_SLIDER, GntSliderClass))
+#define GNT_IS_SLIDER(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_SLIDER))
+#define GNT_IS_SLIDER_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_SLIDER))
+#define GNT_SLIDER_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_SLIDER, GntSliderClass))
+
+#define GNT_SLIDER_FLAGS(obj)                (GNT_SLIDER(obj)->priv.flags)
+#define GNT_SLIDER_SET_FLAGS(obj, flags)     (GNT_SLIDER_FLAGS(obj) |= flags)
+#define GNT_SLIDER_UNSET_FLAGS(obj, flags)   (GNT_SLIDER_FLAGS(obj) &= ~(flags))
+
+typedef struct _GntSlider			GntSlider;
+typedef struct _GntSliderPriv		GntSliderPriv;
+typedef struct _GntSliderClass		GntSliderClass;
+
+struct _GntSlider
+{
+	GntWidget parent;
+
+	gboolean vertical;
+
+	int max;        /* maximum value */
+	int min;        /* minimum value */
+	int step;       /* amount to change at each step */
+	int current;    /* current value */
+};
+
+struct _GntSliderClass
+{
+	GntWidgetClass parent;
+
+	void (*changed)(GntSlider *slider, int);
+	void (*gnt_reserved1)(void);
+	void (*gnt_reserved2)(void);
+	void (*gnt_reserved3)(void);
+	void (*gnt_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+/**
+ * @return The GType for GntSlider
+ */
+GType gnt_slider_get_gtype(void);
+
+#define gnt_hslider_new(max, min) gnt_slider_new(FALSE, max, min)
+#define gnt_vslider_new(max, min) gnt_slider_new(TRUE, max, min)
+
+/**
+ * Create a new slider.
+ *
+ * @param orient A vertical slider is created if @c TRUE, otherwise the slider is horizontal.
+ * @param max    The maximum value for the slider
+ * @param min    The minimum value for the slider
+ *
+ * @return  The newly created slider
+ */
+GntWidget * gnt_slider_new(gboolean orient, int max, int min);
+
+/**
+ * Set the range of the slider.
+ *
+ * @param slider  The slider
+ * @param max     The maximum value
+ * @param min     The minimum value
+ */
+void gnt_slider_set_range(GntSlider *slider, int max, int min);
+
+/**
+ * Sets the amount of change at each step.
+ * 
+ * @param slider  The slider
+ * @param step    The amount for each ste
+ */
+void gnt_slider_set_step(GntSlider *slider, int step);
+
+/**
+ * Advance the slider forward or backward.
+ *
+ * @param slider   The slider
+ * @param steps    The number of amounts to change, positive to change
+ *                 forward, negative to change backward
+ *
+ * @return   The value of the slider after the change
+ */
+int gnt_slider_advance_step(GntSlider *slider, int steps);
+
+/**
+ * Set the current value for the slider.
+ *
+ * @param slider  The slider
+ * @param value   The current value
+ */
+void gnt_slider_set_value(GntSlider *slider, int value);
+
+/**
+ * Update a label with the value of the slider whenever the value changes.
+ *
+ * @param slider   The slider
+ * @param label    The label to update
+ */
+void gnt_slider_reflect_label(GntSlider *slider, GntLabel *label);
+
+G_END_DECLS
+
+#endif /* GNT_SLIDER_H */
--- a/finch/libgnt/gntstyle.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntstyle.c	Fri Jun 29 18:03:53 2007 +0000
@@ -36,7 +36,6 @@
 static GKeyFile *gkfile;
 #endif
 
-static GHashTable *unknowns;
 static char * str_styles[GNT_STYLES];
 static int int_styles[GNT_STYLES];
 static int bool_styles[GNT_STYLES];
@@ -46,9 +45,11 @@
 	return str_styles[style];
 }
 
-const char *gnt_style_get_from_name(const char *name)
+char *gnt_style_get_from_name(const char *group, const char *key)
 {
-	return g_hash_table_lookup(unknowns, name);
+#if GLIB_CHECK_VERSION(2,6,0)
+	return g_key_file_get_value(gkfile, group, key, NULL);
+#endif
 }
 
 gboolean gnt_style_get_bool(GntStyle style, gboolean def)
@@ -293,10 +294,6 @@
 			str_styles[styles[i].en] =
 					g_key_file_get_string(kfile, "general", styles[i].style, NULL);
 		}
-
-		for (i = 0; i < nkeys; i++)
-			g_hash_table_replace(unknowns, g_strdup(keys[i]),
-					g_strdup(g_key_file_get_string(kfile, "general", keys[i], NULL)));
 	}
 	g_strfreev(keys);
 }
@@ -307,9 +304,9 @@
 #if GLIB_CHECK_VERSION(2,6,0)
 	GError *error = NULL;
 	gkfile = g_key_file_new();
-	unknowns = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
 
-	if (!g_key_file_load_from_file(gkfile, filename, G_KEY_FILE_NONE, &error))
+	if (!g_key_file_load_from_file(gkfile, filename,
+                G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error))
 	{
 		g_printerr("GntStyle: %s\n", error->message);
 		g_error_free(error);
@@ -337,7 +334,6 @@
 	for (i = 0; i < GNT_STYLES; i++)
 		g_free(str_styles[i]);
 
-	g_hash_table_destroy(unknowns);
 #if GLIB_CHECK_VERSION(2,6,0)
 	g_key_file_free(gkfile);
 #endif
--- a/finch/libgnt/gntstyle.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntstyle.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntstyle.h Style API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
@@ -41,7 +45,7 @@
 
 const char *gnt_style_get(GntStyle style);
 
-const char *gnt_style_get_from_name(const char *key);
+char *gnt_style_get_from_name(const char *group, const char *key);
 
 /**
  * 
--- a/finch/libgnt/gnttextview.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gnttextview.c	Fri Jun 29 18:03:53 2007 +0000
@@ -65,6 +65,7 @@
 	int i = 0;
 	GList *lines;
 	int rows, scrcol;
+	gboolean has_scroll = !(view->flags & GNT_TEXT_VIEW_NO_SCROLL);
 
 	wbkgd(widget->window, COLOR_PAIR(GNT_COLOR_NORMAL));
 	werase(widget->window);
@@ -111,12 +112,12 @@
 			*end = back;
 		}
 		wattroff(widget->window, A_UNDERLINE | A_BLINK | A_REVERSE);
-		whline(widget->window, ' ', widget->priv.width - line->length - 1);
+		whline(widget->window, ' ', widget->priv.width - line->length - has_scroll);
 	}
 
 	scrcol = widget->priv.width - 1;
 	rows = widget->priv.height - 2;
-	if (rows > 0)
+	if (has_scroll && rows > 0)
 	{
 		int total = g_list_length(g_list_first(view->list));
 		int showing, position, up, down;
@@ -143,11 +144,13 @@
 				ACS_CKBOARD | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D), showing);
 	}
 
-	mvwaddch(widget->window, 0, scrcol,
-			(lines ? ACS_UARROW : ' ') | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D));
-	mvwaddch(widget->window, widget->priv.height - 1, scrcol,
-			((view->list && view->list->prev) ? ACS_DARROW : ' ') |
-				COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D));
+	if (has_scroll) {
+		mvwaddch(widget->window, 0, scrcol,
+				(lines ? ACS_UARROW : ' ') | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D));
+		mvwaddch(widget->window, widget->priv.height - 1, scrcol,
+				((view->list && view->list->prev) ? ACS_DARROW : ' ') |
+					COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D));
+	}
 
 	GNTDEBUG;
 }
@@ -483,6 +486,8 @@
 	GList *list = view->list;
 	GntTextLine *line;
 	int len;
+	gboolean has_scroll = !(view->flags & GNT_TEXT_VIEW_NO_SCROLL);
+	gboolean wrap_word = !(view->flags & GNT_TEXT_VIEW_WRAP_CHAR);
 
 	if (text == NULL || *text == '\0')
 		return;
@@ -519,7 +524,7 @@
 		}
 
 		line = view->list->data;
-		if (line->length == widget->priv.width - 1) {
+		if (line->length == widget->priv.width - has_scroll) {
 			/* The last added line was exactly the same width as the widget */
 			line = g_new0(GntTextLine, 1);
 			line->soft = TRUE;
@@ -528,15 +533,15 @@
 
 		if ((end = strchr(start, '\r')) != NULL ||
 			(end = strchr(start, '\n')) != NULL) {
-			len = gnt_util_onscreen_width(start, end - 1);
-			if (len >= widget->priv.width - line->length - 1) {
+			len = gnt_util_onscreen_width(start, end - has_scroll);
+			if (len >= widget->priv.width - line->length - has_scroll) {
 				end = NULL;
 			}
 		}
 
 		if (end == NULL)
 			end = gnt_util_onscreen_width_to_pointer(start,
-					widget->priv.width - line->length - 1, &len);
+					widget->priv.width - line->length - has_scroll, &len);
 
 		/* Try to append to the previous segment if possible */
 		if (line->segments) {
@@ -554,7 +559,7 @@
 		}
 
 		oldl = line;
-		if (*end && *end != '\n' && *end != '\r') {
+		if (wrap_word && *end && *end != '\n' && *end != '\r') {
 			const char *tmp = end;
 			while (end && *end != '\n' && *end != '\r' && !g_ascii_isspace(*end)) {
 				end = g_utf8_find_prev_char(seg->start + view->string->str, end);
@@ -783,3 +788,8 @@
 	g_signal_connect(G_OBJECT(widget), "key_pressed", G_CALLBACK(scroll_tv), view);
 }
 
+void gnt_text_view_set_flag(GntTextView *view, GntTextViewFlag flag)
+{
+	view->flags |= flag;
+}
+
--- a/finch/libgnt/gnttextview.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gnttextview.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gnttextview.h Textview API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
@@ -43,6 +47,11 @@
 typedef struct _GntTextViewPriv		GntTextViewPriv;
 typedef struct _GntTextViewClass		GntTextViewClass;
 
+typedef enum {
+	GNT_TEXT_VIEW_NO_SCROLL     = 1 << 0,
+	GNT_TEXT_VIEW_WRAP_CHAR     = 1 << 1,
+} GntTextViewFlag;
+
 struct _GntTextView
 {
 	GntWidget parent;
@@ -51,6 +60,7 @@
 	GList *list;        /* List of GntTextLine */
 
 	GList *tags;       /* A list of tags */
+	GntTextViewFlag flags;
 };
 
 typedef enum
@@ -173,6 +183,14 @@
  */
 void gnt_text_view_attach_scroll_widget(GntTextView *view, GntWidget *widget);
 
+/**
+ * Set a GntTextViewFlag for the textview widget.
+ *
+ * @param view  The textview widget
+ * @param flag  The flag to set
+ */
+void gnt_text_view_set_flag(GntTextView *view, GntTextViewFlag flag);
+
 G_END_DECLS
 
 #endif /* GNT_TEXT_VIEW_H */
--- a/finch/libgnt/gnttree.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gnttree.c	Fri Jun 29 18:03:53 2007 +0000
@@ -1526,6 +1526,12 @@
 	tree->columns[col].width = width;
 }
 
+void gnt_tree_set_column_title(GntTree *tree, int index, const char *title)
+{
+	g_free(tree->columns[index].title);
+	tree->columns[index].title = g_strdup(title);
+}
+
 void gnt_tree_set_column_titles(GntTree *tree, ...)
 {
 	int i;
--- a/finch/libgnt/gnttree.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gnttree.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gnttree.h Tree API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
@@ -298,6 +302,15 @@
 void gnt_tree_set_col_width(GntTree *tree, int col, int width);
 
 /**
+ * Set the title for a column.
+ *
+ * @param tree   The tree
+ * @param index  The index of the column
+ * @param title  The title for the column
+ */
+void gnt_tree_set_column_title(GntTree *tree, int index, const char *title);
+
+/**
  * 
  * @param tree
  */
--- a/finch/libgnt/gntutils.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntutils.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntutils.h Some utility functions
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
@@ -28,87 +32,101 @@
 typedef gpointer (*GDupFunc)(gconstpointer data);
 
 /**
- * 
- * @param text
- * @param width
- * @param height
+ * Compute the width and height required to view the text on the screen.
+ *
+ * @param text     The text to be displayed.
+ * @param width    The width required is set here, if not @c NULL.
+ * @param height   The height required is set here, if not @c NULL.
  */
 void gnt_util_get_text_bound(const char *text, int *width, int *height);
 
-/* excluding *end */
 /**
- * 
- * @param start
- * @param end
+ * Get the onscreen width of a string, or a substring.
  *
- * @return
+ * @param start  The beginning of the string.
+ * @param end    The end of the string. The width returned is the width
+ *               upto (but not including) end. If end is NULL, then start
+ *               is considered as a @c NULL-terminated string.
+ *
+ * @return       The on-screen width of the string.
  */
 int gnt_util_onscreen_width(const char *start, const char *end);
 
+/**
+ * Computes and returns the string after a specific number of onscreen characters.
+ *
+ * @param str  The string.
+ * @param len  The length to consider. If non-positive, the entire screenlength is used.
+ * @param w    The actual width of the string upto the returned offset, if not @c NULL.
+ *
+ * @return     The string after len offset.
+ */
 const char *gnt_util_onscreen_width_to_pointer(const char *str, int len, int *w);
 
-/* Inserts newlines in 'string' where necessary so that its onscreen width is
+/**
+ * Inserts newlines in 'string' where necessary so that its onscreen width is 
  * no more than 'maxw'.
- * 'maxw' can be <= 0, in which case the maximum screen width is considered.
  *
- * Returns a newly allocated string.
- */
-/**
- * 
- * @param string
- * @param maxw
+ * @param string  The string.
+ * @param maxw    The width that the string should fit into. If maxw is <= 0,
+ *                then the available maximum width is used.
  *
- * @return
+ * @return  A newly allocated string that needs to be freed by the caller.
  */
 char * gnt_util_onscreen_fit_string(const char *string, int maxw);
 
 /**
- * 
- * @param src
- * @param hash
- * @param equal
- * @param key_d
- * @param value_d
- * @param key_dup
- * @param value_dup
+ * Duplicate the contents of a hastable.
  *
- * @return
+ * @param src         The source hashtable.
+ * @param hash        The hash-function to use.
+ * @param equal       The hash-equal function to use.
+ * @param key_d       The key-destroy function to use.
+ * @param value_d     The value-destroy function to use.
+ * @param key_dup     The function to use to duplicate the key.
+ * @param value_dup   The function to use to duplicate the value.
+ *
+ * @return    The new hashtable.
  */
 GHashTable * g_hash_table_duplicate(GHashTable *src, GHashFunc hash, GEqualFunc equal, GDestroyNotify key_d, GDestroyNotify value_d, GDupFunc key_dup, GDupFunc value_dup);
 
 /**
  * To be used with g_signal_new. Look in the key_pressed signal-definition in
  * gntwidget.c for usage.
- */
-/**
- * 
- * @param ihint
- * @param return_accu
- * @param handler_return
- * @param dummy
  *
- * @return
+ * @param ihint           NA
+ * @param return_accu     NA
+ * @param handler_return  NA
+ * @param dummy           NA
+ *
+ * @return  NA
  */
 gboolean gnt_boolean_handled_accumulator(GSignalInvocationHint *ihint, GValue *return_accu, const GValue *handler_return, gpointer dummy);
 
 /**
- * Returns a GntTree populated with "key" -> "binding" for the widget.
- */
-/**
+ * Get a helpful display about the bindings of a widget.
  * 
- * @param widget
+ * @param widget The widget to get bindings for.
  *
- * @return
+ * @return Returns a GntTree populated with "key" -> "binding" for the widget.
  */
 GntWidget * gnt_widget_bindings_view(GntWidget *widget);
 
 /**
- * Parse widgets from 'string'.
- */
-/**
+ * Parse widgets from an XML description. For example,
+ *
+ * @code
+ * GntWidget *win, *button;
+ * gnt_util_parse_widgets("\
+ *      <vwindow id='0' fill='0' align='2'>     \
+ *          <label>This is a test</label>       \
+ *          <button id='1'>OK</button>          \
+ *      </vwindow>",
+ *   2, &win, &button);
+ * @endcode
  * 
- * @param string
- * @param num
+ * @param string  The XML string.
+ * @param num     The number of widgets to return, followed by 'num' GntWidget **
  */
 void gnt_util_parse_widgets(const char *string, int num, ...);
 
--- a/finch/libgnt/gntwidget.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntwidget.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntwidget.h Widget API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- a/finch/libgnt/gntwindow.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntwindow.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntwindow.h Window API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- a/finch/libgnt/gntwm.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntwm.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,4 +1,8 @@
 /**
+ * @file gntwm.h Window-manager API
+ * @ingroup gnt
+ */
+/*
  * GNT - The GLib Ncurses Toolkit
  *
  * GNT is the legal property of its developers, whose names are too numerous
--- a/finch/libgnt/gntws.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/gntws.h	Fri Jun 29 18:03:53 2007 +0000
@@ -1,3 +1,29 @@
+/**
+ * @file gntws.h Workspace API
+ * @ingroup gnt
+ */
+/*
+ * GNT - The GLib Ncurses Toolkit
+ *
+ * GNT is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
 #ifndef GNTWS_H
 #define GNTWS_H
 
--- a/finch/libgnt/wms/irssi.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/finch/libgnt/wms/irssi.c	Fri Jun 29 18:03:53 2007 +0000
@@ -274,17 +274,19 @@
 
 void gntwm_init(GntWM **wm)
 {
-	const char *style = NULL;
+	char *style = NULL;
 	Irssi *irssi;
 
 	irssi = g_object_new(TYPE_IRSSI, NULL);
 	*wm = GNT_WM(irssi);
 
-	style = gnt_style_get_from_name("irssi-split-v");
+	style = gnt_style_get_from_name("irssi", "split-v");
 	irssi->vert = style ? atoi(style) : 1;
+	g_free(style);
 
-	style = gnt_style_get_from_name("irssi-split-h");
+	style = gnt_style_get_from_name("irssi", "split-h");
 	irssi->horiz = style ? atoi(style) : 1;
+	g_free(style);
 
 	irssi->vert = MAX(irssi->vert, 1);
 	irssi->horiz = MAX(irssi->horiz, 1);
--- a/libpurple/Makefile.am	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/Makefile.am	Fri Jun 29 18:03:53 2007 +0000
@@ -157,10 +157,10 @@
 purple_build_coreheaders = $(addprefix $(srcdir)/, $(purple_coreheaders))
 dbus_build_exported = $(addprefix $(srcdir)/, $(dbus_exported))
 
-dbus-types.c: dbus-analyze-types.py $(purple_coreheaders)
+dbus-types.c: dbus-analyze-types.py $(purple_build_coreheaders)
 	cat $(purple_build_coreheaders) | $(PYTHON) $(srcdir)/dbus-analyze-types.py --pattern=PURPLE_DBUS_DEFINE_TYPE\(%s\) > $@
 
-dbus-types.h: dbus-analyze-types.py $(dbus_coreheaders)
+dbus-types.h: dbus-analyze-types.py $(purple_build_coreheaders)
 	cat $(purple_build_coreheaders) | $(PYTHON) $(srcdir)/dbus-analyze-types.py --pattern=PURPLE_DBUS_DECLARE_TYPE\(%s\) > $@
 
 dbus-bindings.c: dbus-analyze-functions.py $(dbus_exported)
--- a/libpurple/blist.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/blist.h	Fri Jun 29 18:03:53 2007 +0000
@@ -21,6 +21,8 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @see @ref blist-signals
  */
 #ifndef _PURPLE_BLIST_H_
 #define _PURPLE_BLIST_H_
--- a/libpurple/cipher.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/cipher.h	Fri Jun 29 18:03:53 2007 +0000
@@ -21,6 +21,8 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @see @ref cipher-signals
  */
 #ifndef PURPLE_CIPHER_H
 #define PURPLE_CIPHER_H
--- a/libpurple/conversation.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/conversation.c	Fri Jun 29 18:03:53 2007 +0000
@@ -1563,6 +1563,7 @@
 				purple_conv_chat_is_user_ignored(chat, user);
 
 		cbuddy = purple_conv_chat_cb_new(user, alias, flag);
+		cbuddy->buddy = purple_find_buddy(conv->account, user) != NULL;
 		/* This seems dumb. Why should we set users thousands of times? */
 		purple_conv_chat_set_users(chat,
 				g_list_prepend(chat->in_room, cbuddy));
@@ -1631,11 +1632,6 @@
 	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
 	g_return_if_fail(prpl_info != NULL);
 
-	flags = purple_conv_chat_user_get_flags(chat, old_user);
-	cb = purple_conv_chat_cb_new(new_user, NULL, flags);
-	purple_conv_chat_set_users(chat,
-		g_list_prepend(chat->in_room, cb));
-
 	if (!strcmp(chat->nick, purple_normalize(conv->account, old_user))) {
 		const char *alias;
 
@@ -1659,6 +1655,12 @@
 			new_alias = purple_buddy_get_contact_alias(buddy);
 	}
 
+	flags = purple_conv_chat_user_get_flags(chat, old_user);
+	cb = purple_conv_chat_cb_new(new_user, new_alias, flags);
+	cb->buddy = purple_find_buddy(conv->account, new_user) != NULL;
+	purple_conv_chat_set_users(chat,
+		g_list_prepend(chat->in_room, cb));
+
 	if (ops != NULL && ops->chat_rename_user != NULL)
 		ops->chat_rename_user(conv, old_user, new_user, new_alias);
 
@@ -1949,6 +1951,7 @@
 
 	return chat->left;
 }
+
 PurpleConvChatBuddy *
 purple_conv_chat_cb_new(const char *name, const char *alias, PurpleConvChatBuddyFlags flags)
 {
--- a/libpurple/core.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/core.h	Fri Jun 29 18:03:53 2007 +0000
@@ -20,6 +20,8 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @see @ref core-signals
  */
 #ifndef _PURPLE_CORE_H_
 #define _PURPLE_CORE_H_
--- a/libpurple/dbus-server.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/dbus-server.h	Fri Jun 29 18:03:53 2007 +0000
@@ -22,6 +22,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
+ * @see @ref dbus-server-signals
  */
 
 #ifndef _PURPLE_DBUS_SERVER_H_
--- a/libpurple/imgstore.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/imgstore.c	Fri Jun 29 18:03:53 2007 +0000
@@ -55,8 +55,8 @@
 {
 	PurpleStoredImage *img;
 
-	g_return_val_if_fail(data != NULL, 0);
-	g_return_val_if_fail(size > 0, 0);
+	g_return_val_if_fail(data != NULL, NULL);
+	g_return_val_if_fail(size > 0, NULL);
 
 	img = g_new(PurpleStoredImage, 1);
 	PURPLE_DBUS_REGISTER_POINTER(img, PurpleStoredImage);
@@ -73,11 +73,13 @@
 purple_imgstore_add_with_id(gpointer data, size_t size, const char *filename)
 {
 	PurpleStoredImage *img = purple_imgstore_add(data, size, filename);
-	img->id = ++nextid;
+	if (img) {
+		img->id = ++nextid;
 
-	g_hash_table_insert(imgstore, &(img->id), img);
+		g_hash_table_insert(imgstore, &(img->id), img);
+	}
 
-	return img->id;
+	return (img ? img->id : 0);
 }
 
 PurpleStoredImage *purple_imgstore_find_by_id(int id) {
--- a/libpurple/imgstore.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/imgstore.h	Fri Jun 29 18:03:53 2007 +0000
@@ -22,6 +22,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
+ * @see @ref imgstore-signals
  */
 #ifndef _PURPLE_IMGSTORE_H_
 #define _PURPLE_IMGSTORE_H_
--- a/libpurple/log.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/log.h	Fri Jun 29 18:03:53 2007 +0000
@@ -21,6 +21,8 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @see @ref log-signals
  */
 #ifndef _PURPLE_LOG_H_
 #define _PURPLE_LOG_H_
--- a/libpurple/notify.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/notify.h	Fri Jun 29 18:03:53 2007 +0000
@@ -21,6 +21,8 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @see @ref notify-signals
  */
 #ifndef _PURPLE_NOTIFY_H_
 #define _PURPLE_NOTIFY_H_
--- a/libpurple/plugin.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/plugin.h	Fri Jun 29 18:03:53 2007 +0000
@@ -21,6 +21,10 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @see @ref plugin-signals
+ * @see @ref plugin-ids
+ * @see @ref plugin-i18n
  */
 #ifndef _PURPLE_PLUGIN_H_
 #define _PURPLE_PLUGIN_H_
--- a/libpurple/plugins/perl/scripts/signals-test.pl	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/plugins/perl/scripts/signals-test.pl	Fri Jun 29 18:03:53 2007 +0000
@@ -7,7 +7,7 @@
 	name => "Perl: $MODULE_NAME",
 	version => "0.1",
 	summary => "Signals Test plugin for the Perl interpreter.",
-	description => "Demonstrate the user of purple signals from " .
+	description => "Demonstrate the use of purple signals from " .
 		       "a perl plugin.",
 	author => "Sadrul Habib Chowdhury <sadrul\@pidgin.im>",
 	url => "http://developer.pidgin.im/wiki/sadrul/",
--- a/libpurple/protocols/bonjour/buddy.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/protocols/bonjour/buddy.c	Fri Jun 29 18:03:53 2007 +0000
@@ -17,6 +17,7 @@
 #include <glib.h>
 #include <stdlib.h>
 
+#include "internal.h"
 #include "buddy.h"
 #include "account.h"
 #include "blist.h"
--- a/libpurple/protocols/bonjour/jabber.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/protocols/bonjour/jabber.c	Fri Jun 29 18:03:53 2007 +0000
@@ -31,6 +31,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 
+#include "internal.h"
 #include "network.h"
 #include "eventloop.h"
 #include "connection.h"
--- a/libpurple/protocols/bonjour/mdns_common.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_common.c	Fri Jun 29 18:03:53 2007 +0000
@@ -16,6 +16,7 @@
 
 #include <string.h>
 
+#include "internal.h"
 #include "config.h"
 #include "mdns_common.h"
 #include "bonjour.h"
--- a/libpurple/protocols/bonjour/mdns_win32.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_win32.c	Fri Jun 29 18:03:53 2007 +0000
@@ -14,6 +14,7 @@
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+#include "internal.h"
 #include "mdns_win32.h"
 
 #include "debug.h"
--- a/libpurple/protocols/jabber/.todo	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/protocols/jabber/.todo	Fri Jun 29 18:03:53 2007 +0000
@@ -1,13 +1,4 @@
 <todo version="0.1.19">
-    <note priority="verylow" time="1036043981" done="1089237837">
-        *sigh* file transfer (do we really need/want this?)
-        <comment>
-            faceprint did this
-        </comment>
-    </note>
-    <note priority="high" time="1036043427">
-        problem seeing buddies with long blist?
-    </note>
     <note priority="medium" time="1036044198">
         Browsing
     </note>
@@ -17,12 +8,6 @@
     <note priority="medium" time="1036044448">
         Add option for user info to be published or not in JUD.
     </note>
-    <note priority="medium" time="1036044571">
-        Show self on buddylist
-        <comment>
-            is this done?
-        </comment>
-    </note>
     <note priority="medium" time="1036044583">
         Delete server account.
     </note>
@@ -37,9 +22,6 @@
         <note priority="medium" time="1037893000">
             formatted. enhancement-request so that the birthday field in the setinfo form would split up into relevant fields allowing for a strict syntax (like year--month--day or so, perhaps even dropdown menus)
         </note>
-        <note priority="low" time="1037890968">
-            have set info pre-fill values from the server when no local vcard exists. this will help people migrating to libpurple-based clients
-        </note>
     </note>
     <note priority="verylow" time="1036044192">
         Jabber Transports (having them show up on the buddy list should be fairly easy; having an appropriate right-click menu for them should also be somewhat easy. Providing a UI for adding transports should be rather difficult.)
--- a/libpurple/protocols/jabber/buddy.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/protocols/jabber/buddy.c	Fri Jun 29 18:03:53 2007 +0000
@@ -419,6 +419,10 @@
 
 			avatar_data = purple_imgstore_get_data(img);
 			avatar_len = purple_imgstore_get_size(img);
+			/* have to get rid of the old PHOTO if it exists */
+			if((photo = xmlnode_get_child(vc_node, "PHOTO"))) {
+				xmlnode_free(photo);
+			}
 			photo = xmlnode_new_child(vc_node, "PHOTO");
 			binval = xmlnode_new_child(photo, "BINVAL");
 			enc = purple_base64_encode(avatar_data, avatar_len);
--- a/libpurple/protocols/jabber/disco.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/protocols/jabber/disco.c	Fri Jun 29 18:03:53 2007 +0000
@@ -83,6 +83,7 @@
 			SUPPORT_FEATURE("jabber:iq:last")
 			SUPPORT_FEATURE("jabber:iq:oob")
 			SUPPORT_FEATURE("jabber:iq:time")
+			SUPPORT_FEATURE("xmpp:urn:time")
 			SUPPORT_FEATURE("jabber:iq:version")
 			SUPPORT_FEATURE("jabber:x:conference")
 			SUPPORT_FEATURE("http://jabber.org/protocol/bytestreams")
--- a/libpurple/protocols/jabber/iq.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/protocols/jabber/iq.c	Fri Jun 29 18:03:53 2007 +0000
@@ -169,7 +169,7 @@
 
 static void jabber_iq_time_parse(JabberStream *js, xmlnode *packet)
 {
-	const char *type, *from, *id;
+	const char *type, *from, *id, *xmlns;
 	JabberIq *iq;
 	xmlnode *query;
 	time_t now_t;
@@ -182,27 +182,40 @@
 	from = xmlnode_get_attrib(packet, "from");
 	id = xmlnode_get_attrib(packet, "id");
 
+	/* we're gonna throw this away in a moment, but we need it
+	 * to get the xmlns, so we can figure out if this is
+	 * jabber:iq:time or urn:xmpp:time */
+	query = xmlnode_get_child(packet, "query");
+	xmlns = xmlnode_get_namespace(query);
+
 	if(type && !strcmp(type, "get")) {
+		xmlnode *utc;
 		const char *date;
 
-		iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:time");
+		iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, xmlns);
 		jabber_iq_set_id(iq, id);
 		xmlnode_set_attrib(iq->node, "to", from);
 
 		query = xmlnode_get_child(iq->node, "query");
 
 		date = purple_utf8_strftime("%Y%m%dT%T", now);
-		xmlnode_insert_data(xmlnode_new_child(query, "utc"), date, -1);
+		utc = xmlnode_new_child(query, "utc");
+		xmlnode_insert_data(utc, date, -1);
+
+		if(!strcmp("urn:xmpp:time", xmlns)) {
+			xmlnode_insert_data(utc, "Z", 1); /* of COURSE the thing that is the same is different */
 
-		date = purple_utf8_strftime("%Z", now);
-		xmlnode_insert_data(xmlnode_new_child(query, "tz"), date, -1);
+			date = purple_get_tzoff_str(now, TRUE);
+			xmlnode_insert_data(xmlnode_new_child(query, "tzo"), date, -1);
+		} else { /* jabber:iq:time */
+			date = purple_utf8_strftime("%Z", now);
+			xmlnode_insert_data(xmlnode_new_child(query, "tz"), date, -1);
 
-		date = purple_utf8_strftime("%d %b %Y %T", now);
-		xmlnode_insert_data(xmlnode_new_child(query, "display"), date, -1);
+			date = purple_utf8_strftime("%d %b %Y %T", now);
+			xmlnode_insert_data(xmlnode_new_child(query, "display"), date, -1);
+		}
 
 		jabber_iq_send(iq);
-	} else {
-		/* XXX: error */
 	}
 }
 
@@ -347,6 +360,7 @@
 	jabber_iq_register_handler("http://jabber.org/protocol/bytestreams", jabber_bytestreams_parse);
 	jabber_iq_register_handler("jabber:iq:last", jabber_iq_last_parse);
 	jabber_iq_register_handler("jabber:iq:time", jabber_iq_time_parse);
+	jabber_iq_register_handler("urn:xmpp:time", jabber_iq_time_parse);
 	jabber_iq_register_handler("jabber:iq:version", jabber_iq_version_parse);
 	jabber_iq_register_handler("http://jabber.org/protocol/disco#info", jabber_disco_info_parse);
 	jabber_iq_register_handler("http://jabber.org/protocol/disco#items", jabber_disco_items_parse);
--- a/libpurple/protocols/jabber/jabber.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Fri Jun 29 18:03:53 2007 +0000
@@ -1369,11 +1369,13 @@
 	field = purple_request_field_string_new("password1", _("Password"),
 			"", FALSE);
 	purple_request_field_string_set_masked(field, TRUE);
+	purple_request_field_set_required(field, TRUE);
 	purple_request_field_group_add_field(group, field);
 
 	field = purple_request_field_string_new("password2", _("Password (again)"),
 			"", FALSE);
 	purple_request_field_string_set_masked(field, TRUE);
+	purple_request_field_set_required(field, TRUE);
 	purple_request_field_group_add_field(group, field);
 
 	purple_request_fields(js->gc, _("Change XMPP Password"),
--- a/libpurple/protocols/jabber/presence.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/protocols/jabber/presence.c	Fri Jun 29 18:03:53 2007 +0000
@@ -565,9 +565,7 @@
 		}
 
 		if((found_jbr = jabber_buddy_find_resource(jb, NULL))) {
-			if(!jbr || jbr == found_jbr) {
-				purple_prpl_got_user_status(js->gc->account, buddy_name, jabber_buddy_state_get_status_id(state), "priority", found_jbr->priority, found_jbr->status ? "message" : NULL, found_jbr->status, NULL);
-			}
+			purple_prpl_got_user_status(js->gc->account, buddy_name, jabber_buddy_state_get_status_id(found_jbr->state), "priority", found_jbr->priority, found_jbr->status ? "message" : NULL, found_jbr->status, NULL);
 		} else {
 			purple_prpl_got_user_status(js->gc->account, buddy_name, "offline", status ? "message" : NULL, status, NULL);
 		}
--- a/libpurple/protocols/oscar/family_auth.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/protocols/oscar/family_auth.c	Fri Jun 29 18:03:53 2007 +0000
@@ -211,7 +211,7 @@
 
 #ifdef USE_XOR_FOR_ICQ
 	/* If we're signing on an ICQ account then use the older, XOR login method */
-	if (isdigit(sn[0]))
+	if (aim_sn_is_icq(sn))
 		return goddamnicq2(od, conn, sn, password, ci);
 #endif
 
@@ -224,7 +224,7 @@
 
 	/* Truncate ICQ and AOL passwords, if necessary */
 	password_len = strlen(password);
-	if (isdigit(sn[0]) && (password_len > MAXICQPASSLEN))
+	if (aim_sn_is_icq(sn) && (password_len > MAXICQPASSLEN))
 		password_len = MAXICQPASSLEN;
 	else if (truncate_pass && password_len > 8)
 		password_len = 8;
@@ -477,7 +477,7 @@
 		return -EINVAL;
 
 #ifdef USE_XOR_FOR_ICQ
-	if (isdigit(sn[0]))
+	if (aim_sn_is_icq(sn))
 		return goddamnicq(od, conn, sn);
 #endif
 
--- a/libpurple/protocols/oscar/libicq.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/protocols/oscar/libicq.c	Fri Jun 29 18:03:53 2007 +0000
@@ -32,7 +32,7 @@
 	OPT_PROTO_MAIL_CHECK | OPT_PROTO_IM_IMAGE,
 	NULL,					/* user_splits */
 	NULL,					/* protocol_options */
-	{"gif,jpeg,bmp,ico", 48, 48, 50, 50, 7168,
+	{"gif,jpeg,bmp,ico", 48, 48, 52, 64, 7168,
 		PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY},	/* icon_spec */
 	oscar_list_icon_icq,		/* list_icon */
 	oscar_list_emblem,		/* list_emblems */
--- a/libpurple/protocols/oscar/oscar.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Fri Jun 29 18:03:53 2007 +0000
@@ -425,7 +425,7 @@
 		charsetstr1 = "UCS-2BE";
 		charsetstr2 = "UTF-8";
 	} else if (charset == AIM_CHARSET_CUSTOM) {
-		if ((sourcesn != NULL) && isdigit(sourcesn[0]))
+		if ((sourcesn != NULL) && aim_sn_is_icq(sourcesn))
 			charsetstr1 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING);
 		else
 			charsetstr1 = "ISO-8859-1";
@@ -1258,7 +1258,7 @@
 
 	if (!aim_snvalid(purple_account_get_username(account))) {
 		gchar *buf;
-		buf = g_strdup_printf(_("Unable to login: Could not sign on as %s because the screen name is invalid.  Screen names must either start with a letter and contain only letters, numbers and spaces, or contain only numbers."), purple_account_get_username(account));
+		buf = g_strdup_printf(_("Unable to login: Could not sign on as %s because the screen name is invalid.  Screen names must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), purple_account_get_username(account));
 		gc->wants_to_die = TRUE;
 		purple_connection_error(gc, buf);
 		g_free(buf);
@@ -4623,7 +4623,7 @@
 
 	if (!aim_snvalid(buddy->name)) {
 		gchar *buf;
-		buf = g_strdup_printf(_("Could not add the buddy %s because the screen name is invalid.  Screen names must either start with a letter and contain only letters, numbers and spaces, or contain only numbers."), buddy->name);
+		buf = g_strdup_printf(_("Could not add the buddy %s because the screen name is invalid.  Screen names must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), buddy->name);
 		if (!purple_conv_present_error(buddy->name, purple_connection_get_account(gc), buf))
 			purple_notify_error(gc, NULL, _("Unable To Add"), buf);
 		g_free(buf);
@@ -5060,7 +5060,8 @@
 			default: { /* La la la */
 				gchar *buf;
 				purple_debug_error("oscar", "ssi: Action 0x%04hx was unsuccessful with error 0x%04hx\n", retval->action, retval->ack);
-				buf = g_strdup_printf(_("Could not add the buddy %s for an unknown reason.  The most common reason for this is that you have the maximum number of allowed buddies in your buddy list."), (retval->name ? retval->name : _("(no name)")));
+				buf = g_strdup_printf(_("Could not add the buddy %s for an unknown reason."),
+						(retval->name ? retval->name : _("(no name)")));
 				if ((retval->name != NULL) && !purple_conv_present_error(retval->name, purple_connection_get_account(gc), buf))
 					purple_notify_error(gc, NULL, _("Unable To Add"), buf);
 				g_free(buf);
--- a/libpurple/protocols/oscar/peer.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/protocols/oscar/peer.c	Fri Jun 29 18:03:53 2007 +0000
@@ -1019,7 +1019,7 @@
 						PURPLE_DEFAULT_ACTION_NONE,
 						account, sn, NULL,
 						conn, 2,
-						_("_Connect"), G_CALLBACK(peer_connection_got_proposition_yes_cb),
+						_("C_onnect"), G_CALLBACK(peer_connection_got_proposition_yes_cb),
 						_("Cancel"), G_CALLBACK(peer_connection_got_proposition_no_cb));
 	}
 	else if (args->type == OSCAR_CAPABILITY_SENDFILE)
--- a/libpurple/protocols/oscar/util.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/protocols/oscar/util.c	Fri Jun 29 18:03:53 2007 +0000
@@ -37,6 +37,7 @@
  *   -- DMP.
  *
  */
+/* TODO: Get rid of this and use glib functions */
 int
 aimutil_tokslen(char *toSearch, int theindex, char dl)
 {
@@ -138,6 +139,7 @@
  * Check if the given screen name is a valid AIM screen name.
  * Example: BobDole
  * Example: Henry_Ford@mac.com
+ * Example: 1KrazyKat@example.com
  *
  * @return TRUE if the screen name is valid, FALSE if not.
  */
@@ -146,9 +148,16 @@
 {
 	int i;
 
+	if (purple_email_is_valid(sn))
+		return TRUE;
+
+	/* Normal AIM screen names can't start with a number */
+	if (isdigit(sn[0]))
+		return FALSE;
+
 	for (i = 0; sn[i] != '\0'; i++) {
 		if (!isalnum(sn[i]) && (sn[i] != ' ') &&
-			(sn[i] != '@') && (sn[i] != '.') &&
+			(sn[i] != '.') &&
 			(sn[i] != '_') && (sn[i] != '-'))
 			return FALSE;
 	}
@@ -169,10 +178,10 @@
 
 	for (i = 0; sn[i] != '\0'; i++) {
 		if (!isdigit(sn[i]))
-			return 0;
+			return FALSE;
 	}
 
-	return 1;
+	return TRUE;
 }
 
 /**
@@ -187,14 +196,14 @@
 	int i;
 
 	if (sn[0] != '+')
-		return 0;
+		return FALSE;
 
 	for (i = 1; sn[i] != '\0'; i++) {
 		if (!isdigit(sn[i]))
-			return 0;
+			return FALSE;
 	}
 
-	return 1;
+	return TRUE;
 }
 
 /**
@@ -206,70 +215,37 @@
 aim_snvalid(const char *sn)
 {
 	if ((sn == NULL) || (*sn == '\0'))
-		return 0;
+		return FALSE;
 
-	if (isalpha(sn[0]))
-		return aim_snvalid_aim(sn);
-	else if (isdigit(sn[0]))
-		return aim_snvalid_icq(sn);
-	else if (sn[0] == '+')
-		return aim_snvalid_sms(sn);
-
-	return 0;
+	return aim_snvalid_icq(sn) || aim_snvalid_sms(sn) || aim_snvalid_aim(sn);
 }
 
 /**
  * Determine if a given screen name is an ICQ screen name
- * (i.e. it begins with a number).
+ * (i.e. it is composed of only numbers).
  *
- * @sn A valid AIM or ICQ screen name.
+ * @param sn A valid AIM or ICQ screen name.
  * @return TRUE if the screen name is an ICQ screen name.  Otherwise
  *         FALSE is returned.
  */
 gboolean
 aim_sn_is_icq(const char *sn)
 {
-	if (isalpha(sn[0]))
-		return FALSE;
-	return TRUE;
+	return aim_snvalid_icq(sn);
 }
 
 /**
  * Determine if a given screen name is an SMS number
  * (i.e. it begins with a +).
  *
- * @sn A valid AIM or ICQ screen name.
+ * @param sn A valid AIM or ICQ screen name.
  * @return TRUE if the screen name is an SMS number.  Otherwise
  *         FALSE is returned.
  */
 gboolean
 aim_sn_is_sms(const char *sn)
 {
-	if (sn[0] != '+')
-		return FALSE;
-	return TRUE;
-}
-
-/**
- * This takes a screen name and returns its length without
- * spaces.  If there are no spaces in the SN, then the
- * return is equal to that of strlen().
- */
-int
-aim_snlen(const char *sn)
-{
-	int i = 0;
-
-	if (!sn)
-		return 0;
-
-	while (*sn != '\0') {
-		if (*sn != ' ')
-			i++;
-		sn++;
-	}
-
-	return i;
+	return (sn[0] == '+');
 }
 
 /**
@@ -279,9 +255,9 @@
  * ignored, with the exception that screen names can not start with
  * a space).
  *
- * Return: 0 if equal
- *     non-0 if different
+ * @return 0 if equal, non-0 if different
  */
+/* TODO: Do something different for email addresses. */
 int
 aim_sncmp(const char *sn1, const char *sn2)
 {
--- a/libpurple/protocols/qq/Makefile.mingw	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/protocols/qq/Makefile.mingw	Fri Jun 29 18:03:53 2007 +0000
@@ -54,7 +54,6 @@
 	group_im.c \
 	group_info.c \
 	group_join.c \
-	group_misc.c \
 	group_network.c \
 	group_opt.c \
 	group_search.c \
--- a/libpurple/request.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/request.c	Fri Jun 29 18:03:53 2007 +0000
@@ -150,7 +150,8 @@
 		switch (purple_request_field_get_type(field))
 		{
 			case PURPLE_REQUEST_FIELD_STRING:
-				if (purple_request_field_string_get_value(field) == NULL)
+				if (purple_request_field_string_get_value(field) == NULL ||
+				    *(purple_request_field_string_get_value(field)) == '\0')
 					return FALSE;
 
 				break;
--- a/libpurple/savedstatuses.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/savedstatuses.h	Fri Jun 29 18:03:53 2007 +0000
@@ -21,6 +21,8 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @see @ref savedstatus-signals
  */
 #ifndef _PURPLE_SAVEDSTATUSES_H_
 #define _PURPLE_SAVEDSTATUSES_H_
--- a/libpurple/sound.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/sound.h	Fri Jun 29 18:03:53 2007 +0000
@@ -21,6 +21,8 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @see @ref sound-signals
  */
 #ifndef _PURPLE_SOUND_H_
 #define _PURPLE_SOUND_H_
--- a/libpurple/util.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/util.c	Fri Jun 29 18:03:53 2007 +0000
@@ -531,10 +531,9 @@
 }
 #endif
 
-#ifndef HAVE_STRFTIME_Z_FORMAT
-static const char *get_tmoff(const struct tm *tm)
+const char *purple_get_tzoff_str(const struct tm *tm, gboolean iso)
 {
-	static char buf[6];
+	static char buf[7];
 	long off;
 	gint8 min;
 	gint8 hrs;
@@ -554,7 +553,7 @@
 # else
 #  ifdef HAVE_TIMEZONE
 	tzset();
-	off = -timezone;
+	off = -1 * timezone;
 #  endif /* HAVE_TIMEZONE */
 # endif /* !HAVE_TM_GMTOFF */
 #endif /* _WIN32 */
@@ -562,12 +561,22 @@
 	min = (off / 60) % 60;
 	hrs = ((off / 60) - min) / 60;
 
-	if (g_snprintf(buf, sizeof(buf), "%+03d%02d", hrs, ABS(min)) > 5)
-		g_return_val_if_reached("");
+	if(iso) {
+		if (0 == off) {
+			strcpy(buf, "Z");
+		} else {
+			/* please leave the colons...they're optional for iso, but jabber
+			 * wants them */
+			if(g_snprintf(buf, sizeof(buf), "%+03d:%02d", hrs, ABS(min)) > 6)
+				g_return_val_if_reached("");
+		}
+	} else {
+		if (g_snprintf(buf, sizeof(buf), "%+03d%02d", hrs, ABS(min)) > 5)
+			g_return_val_if_reached("");
+	}
 
 	return buf;
 }
-#endif
 
 /* Windows doesn't HAVE_STRFTIME_Z_FORMAT, but this seems clearer. -- rlaager */
 #if !defined(HAVE_STRFTIME_Z_FORMAT) || defined(_WIN32)
@@ -600,7 +609,7 @@
 			                            fmt ? fmt : "",
 			                            c - start - 1,
 			                            start,
-			                            get_tmoff(tm));
+			                            purple_get_tzoff_str(tm, FALSE));
 			g_free(fmt);
 			fmt = tmp;
 			start = c + 1;
--- a/libpurple/util.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/util.h	Fri Jun 29 18:03:53 2007 +0000
@@ -257,6 +257,16 @@
 const char *purple_utf8_strftime(const char *format, const struct tm *tm);
 
 /**
+ * Gets a string representation of the local timezone offset
+ *
+ * @param tm   The time to get the timezone for
+ * @param iso  TRUE to format the offset according to ISO-8601, FALSE to
+ *             not substitute 'Z' for 0 offset, and to not separate
+ *             hours and minutes with a colon.
+ */
+const char *purple_get_tzoff_str(const struct tm *tm, gboolean iso);
+
+/**
  * Formats a time into the user's preferred short date format.
  *
  * The returned string is stored in a static buffer, so the result
--- a/libpurple/win32/win32dep.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/win32/win32dep.c	Fri Jun 29 18:03:53 2007 +0000
@@ -32,6 +32,7 @@
 #include <glib.h>
 #include <glib/gstdio.h>
 
+#include "internal.h"
 #include "debug.h"
 #include "notify.h"
 
--- a/libpurple/xmlnode.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/libpurple/xmlnode.c	Fri Jun 29 18:03:53 2007 +0000
@@ -268,6 +268,22 @@
 
 	g_return_if_fail(node != NULL);
 
+	/* if we're part of a tree, remove ourselves from the tree first */
+	if(NULL != node->parent) {
+		if(node->parent->child == node) {
+			node->parent->child = node->next;
+		} else {
+			xmlnode *prev = node->parent->child;
+			while(prev && prev->next != node) {
+				prev = prev->next;
+			}
+			if(prev) {
+				prev->next = node->next;
+			}
+		}
+	}
+
+	/* now free our children */
 	x = node->child;
 	while(x) {
 		y = x->next;
@@ -275,6 +291,7 @@
 		x = y;
 	}
 
+	/* now dispose of ourselves */
 	g_free(node->name);
 	g_free(node->data);
 	g_free(node->xmlns);
--- a/pidgin/eggtrayicon.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/pidgin/eggtrayicon.c	Fri Jun 29 18:03:53 2007 +0000
@@ -152,6 +152,26 @@
     }
 }
 
+static Display *
+egg_tray_icon_get_x_display(EggTrayIcon *icon)
+{
+  Display *xdisplay = NULL;
+
+#if GTK_CHECK_VERSION(2,1,0)
+  {
+    GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (icon));
+    if (!GDK_IS_DISPLAY (display))
+      display = gdk_display_get_default ();
+
+    xdisplay = GDK_DISPLAY_XDISPLAY (display);
+  }
+#else
+  xdisplay = gdk_display;
+#endif
+
+  return xdisplay;
+}
+
 static void
 egg_tray_icon_get_orientation_property (EggTrayIcon *icon)
 {
@@ -168,11 +188,10 @@
 
   g_return_if_fail(icon->manager_window != None);
 
-#if GTK_CHECK_VERSION(2,1,0)
-  xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
-#else
-  xdisplay = gdk_display;
-#endif
+  xdisplay = egg_tray_icon_get_x_display(icon);
+
+  if (xdisplay == NULL)
+    return;
 
   gdk_error_trap_push ();
   type = None;
@@ -321,11 +340,10 @@
   if (icon->manager_window != None)
     return;
 
-#if GTK_CHECK_VERSION(2,1,0)
-  xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
-#else
-  xdisplay = gdk_display;
-#endif
+  xdisplay = egg_tray_icon_get_x_display(icon);
+
+  if (xdisplay == NULL)
+    return;
 
   XGrabServer (xdisplay);
   
@@ -424,12 +442,15 @@
 
   make_transparent (widget, NULL);
 
+  xdisplay = egg_tray_icon_get_x_display(icon);
+
+  if (xdisplay == NULL)
+    return;
+
 #if GTK_CHECK_VERSION(2,1,0)
   screen = gdk_screen_get_number (gtk_widget_get_screen (widget));
-  xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (widget));
 #else
   screen = XScreenNumberOfScreen (DefaultScreenOfDisplay (gdk_display));
-  xdisplay = gdk_display;
 #endif
 
   /* Now see if there's a manager window around */
@@ -519,11 +540,10 @@
       XClientMessageEvent ev;
       Display *xdisplay;
 
-#if GTK_CHECK_VERSION(2,1,0)
-      xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
-#else
-      xdisplay = gdk_display;
-#endif
+      xdisplay = egg_tray_icon_get_x_display(icon);
+
+      if (xdisplay == NULL)
+        return;
 
       ev.type = ClientMessage;
       ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon));
--- a/pidgin/gtkblist.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/pidgin/gtkblist.c	Fri Jun 29 18:03:53 2007 +0000
@@ -174,6 +174,7 @@
 
 static gboolean gtk_blist_window_state_cb(GtkWidget *w, GdkEventWindowState *event, gpointer data)
 {
+#if GTK_CHECK_VERSION(2,2,0)
 	if(event->changed_mask & GDK_WINDOW_STATE_WITHDRAWN) {
 		if(event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN)
 			purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_visible", FALSE);
@@ -195,6 +196,28 @@
 		if (!(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED))
 			pidgin_blist_refresh_timer(purple_get_blist());
 	}
+#else
+	/* At least gtk+ 2.0.6 does not properly set the change_mask when unsetting a
+	 * GdkWindowState flag. To work around, the window state will be explicitly
+	 * queried on these older versions of gtk+. See pidgin ticket #739.
+	 */
+	GdkWindowState new_window_state = gdk_window_get_state(G_OBJECT(gtkblist->window->window));
+
+	if(new_window_state & GDK_WINDOW_STATE_WITHDRAWN) {
+		purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_visible", FALSE);
+	} else {
+		purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_visible", TRUE);
+		pidgin_blist_refresh_timer(purple_get_blist());
+	}
+
+	if(new_window_state & GDK_WINDOW_STATE_MAXIMIZED)
+		purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_maximized", TRUE);
+	else
+		purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/list_maximized", FALSE);
+
+	if (!(new_window_state & GDK_WINDOW_STATE_ICONIFIED))
+		pidgin_blist_refresh_timer(purple_get_blist());
+#endif
 
 	return FALSE;
 }
@@ -2976,10 +2999,11 @@
 		signon = purple_presence_get_login_time(presence);
 		if (full && PURPLE_BUDDY_IS_ONLINE(b) && signon > 0)
 		{
-			if (time(NULL) - signon > 63072000 /* 2 years */) {
+			if (signon > time(NULL)) {
 				/*
-				 * Our local clock must be wrong, show the actual
-				 * date instead of "4 days", etc.
+				 * They signed on in the future?!  Our local clock
+				 * must be wrong, show the actual date instead of
+				 * "4 days", etc.
 				 */
 				tmp = g_strdup(purple_date_format_long(localtime(&signon)));
 			} else
@@ -3092,6 +3116,15 @@
 	} else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) {
 		buddy = (PurpleBuddy*)node;
 		gtkbuddynode = node->ui_data;
+		p = purple_buddy_get_presence(buddy);
+		if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_MOBILE)) {
+			path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", 
+						"16", "mobile.png", NULL);
+			ret = gdk_pixbuf_new_from_file(path, NULL);
+			g_free(path);
+			return ret;
+		}
+
 		if (((struct _pidgin_blist_node*)(node->parent->ui_data))->contact_expanded)
 			return pidgin_create_prpl_icon(((PurpleBuddy*)node)->account, PIDGIN_PRPL_ICON_SMALL);
 	} else if(PURPLE_BLIST_NODE_IS_CHAT(node)) {
@@ -4887,10 +4920,17 @@
 	gboolean selected;
 	char group_count[12] = "";
 	char *mark, *esc;
+	PurpleBlistNode *selected_node = NULL;
+	GtkTreeIter iter;
 
 	group = (PurpleGroup*)gnode;
 	textcolor = gtkblist->treeview->style->fg[GTK_STATE_ACTIVE];
-	selected = gtkblist ? (gtkblist->selected_node == gnode) : FALSE;
+        
+	if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkblist->treeview)), NULL, &iter)) {
+		gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter,
+				NODE_COLUMN, &selected_node, -1);
+	}
+	selected = (gnode == selected_node);
 
 	if (!expanded) {
 		g_snprintf(group_count, sizeof(group_count), " (%d/%d)",
--- a/pidgin/gtkconv.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/pidgin/gtkconv.c	Fri Jun 29 18:03:53 2007 +0000
@@ -256,19 +256,11 @@
 	 * negate it anyway.  --luke */
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
 	{
-		if (w == gtkconv->imhtml) {
-			purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/default_width", allocation->width);
-			purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/default_height", allocation->height);
-		}
 		if (w == gtkconv->lower_hbox)
 			purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height", allocation->height);
 	}
 	else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT)
 	{
-		if (w == gtkconv->imhtml) {
-			purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_width", allocation->width);
-			purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_height", allocation->height);
-		}
 		if (w == gtkconv->lower_hbox)
 			purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height", allocation->height);
 	}
@@ -347,15 +339,28 @@
 	}
 }
 
-static PurpleCmdRet
-clear_command_cb(PurpleConversation *conv,
-                 const char *cmd, char **args, char **error, void *data)
+static void clear_conversation_scrollback(PurpleConversation *conv)
 {
 	PidginConversation *gtkconv = NULL;
 
 	gtkconv = PIDGIN_CONVERSATION(conv);
 
 	gtk_imhtml_clear(GTK_IMHTML(gtkconv->imhtml));
+}
+
+static PurpleCmdRet
+clear_command_cb(PurpleConversation *conv,
+                 const char *cmd, char **args, char **error, void *data)
+{
+	clear_conversation_scrollback(conv);
+	return PURPLE_CMD_STATUS_OK;
+}
+
+static PurpleCmdRet
+clearall_command_cb(PurpleConversation *conv,
+                 const char *cmd, char **args, char **error, void *data)
+{
+	purple_conversation_foreach(clear_conversation_scrollback);
 	return PURPLE_CMD_STATUS_OK;
 }
 
@@ -528,13 +533,6 @@
 
 	account = purple_conversation_get_account(conv);
 
-	if (!purple_account_is_connected(account))
-		return;
-
-	if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) &&
-		purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)))
-		return;
-
 	if (check_for_and_do_command(conv)) {
 		if (gtkconv->entry_growing) {
 			reset_default_size(gtkconv);
@@ -544,6 +542,13 @@
 		return;
 	}
 
+	if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) &&
+		purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)))
+		return;
+
+	if (!purple_account_is_connected(account))
+		return;
+
 	buf = gtk_imhtml_get_markup(GTK_IMHTML(gtkconv->entry));
 	clean = gtk_imhtml_get_text(GTK_IMHTML(gtkconv->entry), NULL, NULL);
 
@@ -1736,6 +1741,9 @@
 
 	gtk_tree_selection_select_path(GTK_TREE_SELECTION(
 			gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkchat->list))), path);
+	gtk_tree_view_set_cursor(GTK_TREE_VIEW(gtkchat->list),
+							 path, NULL, FALSE); 
+	gtk_widget_grab_focus(GTK_WIDGET(gtkchat->list));
 
 	gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path);
 	gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1);
@@ -3671,7 +3679,7 @@
 	if (!strcmp(chat->nick, purple_normalize(conv->account, old_name != NULL ? old_name : name)))
 		is_me = TRUE;
 
-	is_buddy = (purple_find_buddy(conv->account, name) != NULL);
+	is_buddy = cb->buddy;
 
 	tmp = g_utf8_casefold(alias, -1);
 	alias_key = g_utf8_collate_key(tmp, -1);
@@ -3879,7 +3887,7 @@
 						   CHAT_USERS_ALIAS_COLUMN, &alias,
 						   -1);
 
-				if (strcmp(name, alias))
+				if (name && alias && strcmp(name, alias))
 					tab_complete_process_item(&most_matched, entered, &partial, nick_partial,
 										  &matches, FALSE, alias);
 				g_free(name);
@@ -4464,15 +4472,6 @@
 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
 	                               imhtml_sw_hscroll, GTK_POLICY_ALWAYS);
 
-	gtk_widget_set_size_request(gtkconv->imhtml,
-			chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_width") :
-			purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_width"),
-			chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_height") :
-			purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_height"));
-
-	g_signal_connect(G_OBJECT(gtkconv->imhtml), "size-allocate",
-	                 G_CALLBACK(size_allocate_cb), gtkconv);
-
 	g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event",
 	                       G_CALLBACK(entry_stop_rclick_cb), NULL);
 	g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event",
@@ -5563,7 +5562,7 @@
 
 	g_return_if_fail(new_alias != NULL);
 
-	cbuddy = purple_conv_chat_cb_new(new_name, new_alias, flags);
+	cbuddy = purple_conv_chat_cb_find(chat, new_name);
 
 	add_chat_buddy_common(conv, cbuddy, old_name);
 }
@@ -6192,10 +6191,12 @@
 				markup = title;
 		} else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
 			PurpleConvChat *chat = PURPLE_CONV_CHAT(conv);
-			markup = g_strdup_printf("%s\n<span color='%s' size='smaller'>%s</span>",
+			const char *topic = purple_conv_chat_get_topic(chat);
+			markup = g_strdup_printf("%s%s<span color='%s' size='smaller'>%s</span>",
 						purple_conversation_get_title(conv),
+						topic ? "\n" : "",
 						pidgin_get_dim_grey_string(gtkconv->infopane),
-						purple_conv_chat_get_topic(chat));
+						topic ? topic : "");
 		}
 		gtk_list_store_set(gtkconv->infopane_model, &(gtkconv->infopane_iter),
 				TEXT_COLUMN, markup, -1);
@@ -7057,6 +7058,8 @@
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/tabs", TRUE);
 	purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/tab_side", GTK_POS_TOP);
 	purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/scrollback_lines", 4000);
+	purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/x", 0);
+	purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/y", 0);
 
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/use_theme_font", TRUE);
 	purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/custom_font", "");
@@ -7202,6 +7205,9 @@
 	purple_cmd_register("clear", "", PURPLE_CMD_P_DEFAULT,
 	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM, NULL,
 	                  clear_command_cb, _("clear: Clears the conversation scrollback."), NULL);
+	purple_cmd_register("clearall", "", PURPLE_CMD_P_DEFAULT,
+	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM, NULL,
+	                  clearall_command_cb, _("clear: Clears all conversation scrollbacks."), NULL);
 	purple_cmd_register("help", "w", PURPLE_CMD_P_DEFAULT,
 	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, NULL,
 	                  help_command_cb, _("help &lt;command&gt;:  Help on a specific command."), NULL);
@@ -8203,6 +8209,44 @@
 	regenerate_plugins_items(data);
 }
 
+static gboolean gtk_conv_configure_cb(GtkWidget *w, GdkEventConfigure *event, gpointer data) {
+	int x, y;
+	
+	if (GTK_WIDGET_VISIBLE(w))
+		gtk_window_get_position(GTK_WINDOW(w), &x, &y);
+	else
+		return FALSE; /* carry on normally */
+
+	/* Workaround for GTK+ bug # 169811 - "configure_event" is fired
+	* when the window is being maximized */
+	if (gdk_window_get_state(w->window) & GDK_WINDOW_STATE_MAXIMIZED)
+		return FALSE;
+	
+	/* don't save if nothing changed */
+	if (x == purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/x") &&
+	    y == purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/y") &&
+	    event->width  == purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_width") &&
+	    event->height == purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_height"))
+		return FALSE; /* carry on normally */
+		
+	/* don't save off-screen positioning */
+	if (x + event->width < 0 ||
+	    y + event->height < 0 ||
+	    x > gdk_screen_width() ||
+	    y > gdk_screen_height())
+		return FALSE; /* carry on normally */
+
+        /* store the position */
+        purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/x",      x);
+	purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/y",      y);
+	purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/width",  event->width);
+	purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/height", event->height);
+
+	/* continue to handle event normally */
+	return FALSE;
+						
+}
+
 PidginWindow *
 pidgin_conv_window_new()
 {
@@ -8217,7 +8261,8 @@
 
 	/* Create the window. */
 	win->window = pidgin_create_window(NULL, 0, "conversation", TRUE);
-	GTK_WINDOW(win->window)->allow_shrink = TRUE;
+	gtk_window_set_default_size(GTK_WINDOW(win->window), purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/width"),
+							     purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/height"));
 
 	if (available_list == NULL) {
 		create_icon_lists(win->window);
@@ -8225,7 +8270,8 @@
 
 	g_signal_connect(G_OBJECT(win->window), "delete_event",
 	                 G_CALLBACK(close_win_cb), win);
-
+	g_signal_connect(G_OBJECT(win->window), "configure_event", 
+			 G_CALLBACK(gtk_conv_configure_cb), NULL);
 	g_signal_connect(G_OBJECT(win->window), "focus_in_event",
 	                 G_CALLBACK(focus_win_cb), win);
 
@@ -8560,7 +8606,7 @@
 	win->gtkconvs = g_list_remove(win->gtkconvs, gtkconv);
 
 	if (!win->gtkconvs || !win->gtkconvs->next)
-		gtk_notebook_set_show_tabs(win->notebook, FALSE);
+		gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), FALSE);
 
 	if (!win->gtkconvs && win != hidden_convwin)
 		pidgin_conv_window_destroy(win);
--- a/pidgin/gtkdialogs.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/pidgin/gtkdialogs.c	Fri Jun 29 18:03:53 2007 +0000
@@ -165,7 +165,7 @@
 	{N_("Japanese"),            "ja", "Takashi Aihana", "aihana@gnome.gr.jp"},
 	{N_("Georgian"),            "ka", N_("Ubuntu Georgian Translators"), "alexander.didebulidze@stusta.mhn.de"},
 	{N_("Kannada"),             "kn", N_("Kannada Translation team"), "translation@sampada.info"},
-	{N_("Korean"),              "ko", "Kyung-uk Son", "vvs740@chol.com"},
+	{N_("Korean"),              "ko", "Sushizang", "sushizang@empal.com"},
 	{N_("Kurdish"),             "ku", "Erdal Ronahi", "erdal.ronahi@gmail.com"},
 	{N_("Kurdish"),             "ku", "Amed Ç. Jiyan", "amedcj@hotmail.com"},
 	{N_("Kurdish"),             "ku", "Rizoyê Xerzî", "rizoxerzi@hotmail.com"},
@@ -230,6 +230,7 @@
 	{N_("Japanese"),            "ja", "Junichi Uekawa", NULL},
 	{N_("Georgian"),            "ka", "Temuri Doghonadze", NULL},
 	{N_("Korean"),              "ko", "Sang-hyun S, A Ho-seok Lee", NULL},
+	{N_("Korean"),              "ko", "Kyeong-uk Son", "hey@gnome.or.kr"},
 	{N_("Lithuanian"),          "lt", "Andrius Štikonas", NULL},
 	{N_("Lithuanian"),          "lt", "Gediminas Čičinskas", NULL},
 	{N_("Macedonian"),          "mk", "Tomislav Markovski", "herrera@users.sf.net"},
--- a/pidgin/gtkimhtml.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/pidgin/gtkimhtml.c	Fri Jun 29 18:03:53 2007 +0000
@@ -1002,11 +1002,12 @@
 		gtk_imhtml_close_tags(imhtml, &iter);
 
 	gtk_imhtml_insert_html_at_iter(imhtml, text, flags, &iter);
-	if (!imhtml->wbfo && !plaintext)
-		gtk_imhtml_close_tags(imhtml, &iter);
 	gtk_text_buffer_move_mark_by_name(imhtml->text_buffer, "insert", &iter);
 	gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(imhtml), gtk_text_buffer_get_insert(imhtml->text_buffer),
 	                             0, FALSE, 0.0, 0.0);
+	if (!imhtml->wbfo && !plaintext)
+		gtk_imhtml_close_tags(imhtml, &iter);
+
 }
 
 static void paste_plaintext_received_cb (GtkClipboard *clipboard, const gchar *text, gpointer data)
@@ -4938,9 +4939,6 @@
 
 	if (imhtml->edit.link)
 		gtk_imhtml_toggle_link(imhtml, NULL);
-
-	gtk_text_buffer_remove_all_tags(imhtml->text_buffer, iter, iter);
-
 }
 
 char *gtk_imhtml_get_markup(GtkIMHtml *imhtml)
--- a/pidgin/gtkmain.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/pidgin/gtkmain.c	Fri Jun 29 18:03:53 2007 +0000
@@ -677,6 +677,8 @@
 		return 1;
 	}
 
+	g_set_application_name(_("Pidgin"));
+
 #ifdef _WIN32
 	winpidgin_init(hint);
 #endif
@@ -855,7 +857,6 @@
 	winpidgin_post_init();
 #endif
 
-	g_set_application_name(_("Pidgin"));
 	gtk_main();
 
 #ifdef HAVE_SIGNAL_H
--- a/pidgin/gtkprivacy.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/pidgin/gtkprivacy.c	Fri Jun 29 18:03:53 2007 +0000
@@ -366,7 +366,7 @@
 
 	dialog = g_new0(PidginPrivacyDialog, 1);
 
-	dialog->win = pidgin_create_window(_("Privacy"), PIDGIN_HIG_BORDER, "privacy", FALSE);
+	dialog->win = pidgin_create_window(_("Privacy"), PIDGIN_HIG_BORDER, "privacy", TRUE);
 
 	g_signal_connect(G_OBJECT(dialog->win), "delete_event",
 					 G_CALLBACK(destroy_cb), dialog);
--- a/pidgin/gtksavedstatuses.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/pidgin/gtksavedstatuses.c	Fri Jun 29 18:03:53 2007 +0000
@@ -1140,7 +1140,7 @@
 	if (edit)
 		dialog->original_title = g_strdup(purple_savedstatus_get_title(saved_status));
 
-	dialog->window = win = pidgin_create_window (_("Status"), PIDGIN_HIG_BORDER, "status", FALSE) ;
+	dialog->window = win = pidgin_create_window(_("Status"), PIDGIN_HIG_BORDER, "status", TRUE);
 
 	g_signal_connect(G_OBJECT(win), "delete_event",
 					 G_CALLBACK(status_editor_destroy_cb), dialog);
@@ -1475,7 +1475,7 @@
 	dialog->account = account;
 
 	tmp = g_strdup_printf(_("Status for %s"), purple_account_get_username(account));
-	dialog->window = win = pidgin_create_window(tmp, PIDGIN_HIG_BORDER, "substatus", FALSE) ;
+	dialog->window = win = pidgin_create_window(tmp, PIDGIN_HIG_BORDER, "substatus", TRUE);
 	g_free(tmp);
 
 	g_signal_connect(G_OBJECT(win), "delete_event",
@@ -1520,7 +1520,7 @@
 
 	/* Status mesage */
 	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
-	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
 
 	label = gtk_label_new_with_mnemonic(_("_Message:"));
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
--- a/pidgin/gtkstatusbox.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/pidgin/gtkstatusbox.c	Fri Jun 29 18:03:53 2007 +0000
@@ -1016,8 +1016,8 @@
 	}
 }
 
-static void
-pidgin_status_box_regenerate(PidginStatusBox *status_box)
+static gboolean
+pidgin_status_box_regenerate_real(PidginStatusBox *status_box)
 {
 	GdkPixbuf *pixbuf, *pixbuf2, *pixbuf3, *pixbuf4, *pixbuf5;
 	GtkIconSize icon_size;
@@ -1081,11 +1081,21 @@
 	}
 	gtk_tree_view_set_model(GTK_TREE_VIEW(status_box->tree_view), GTK_TREE_MODEL(status_box->dropdown_store));
 	gtk_tree_view_set_search_column(GTK_TREE_VIEW(status_box->tree_view), TEXT_COLUMN);
+
+	return FALSE;
+}
+
+static void
+pidgin_status_box_regenerate(PidginStatusBox *status_box)
+{
+	/* we have to do this in a timeout, so we avoid recursing
+	 * to infinity (and beyond) */
+	purple_timeout_add(0, (GSourceFunc)pidgin_status_box_regenerate_real, status_box);
 }
 
 static gboolean combo_box_scroll_event_cb(GtkWidget *w, GdkEventScroll *event, GtkIMHtml *imhtml)
 {
-  	pidgin_status_box_popup(PIDGIN_STATUS_BOX(w));
+	pidgin_status_box_popup(PIDGIN_STATUS_BOX(w));
 	return TRUE;
 }
 
--- a/pidgin/gtkutils.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/pidgin/gtkutils.c	Fri Jun 29 18:03:53 2007 +0000
@@ -1147,6 +1147,9 @@
 	acc = gtk_widget_get_accessible (w);
 	label = gtk_widget_get_accessible (l);
 
+	/* 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) {
--- a/pidgin/pidginstock.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/pidgin/pidginstock.c	Fri Jun 29 18:03:53 2007 +0000
@@ -169,10 +169,8 @@
 	{ PIDGIN_STOCK_TRAY_XA, "tray", "tray-extended-away.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL  },
 	{ PIDGIN_STOCK_TRAY_OFFLINE, "tray", "tray-offline.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL  },
 	{ PIDGIN_STOCK_TRAY_CONNECT, "tray", "tray-connecting.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL  },
-	{ PIDGIN_STOCK_TRAY_PENDING, "tray", "tray-new-im.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL  }
-/* Uncomment me after 2.0.2!
- *	{ PIDGIN_STOCK_TRAY_EMAIL, "tray", "tray-message.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL  }
- */
+	{ PIDGIN_STOCK_TRAY_PENDING, "tray", "tray-new-im.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL  },
+	{ PIDGIN_STOCK_TRAY_EMAIL, "tray", "tray-message.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL  }
 };
 
 static gchar *
--- a/pidgin/pidginstock.h	Tue Jun 26 19:53:55 2007 +0000
+++ b/pidgin/pidginstock.h	Fri Jun 29 18:03:53 2007 +0000
@@ -137,9 +137,7 @@
 #define PIDGIN_STOCK_TRAY_OFFLINE         "pidgin-tray-offline"
 #define PIDGIN_STOCK_TRAY_CONNECT         "pidgin-tray-connect"
 #define PIDGIN_STOCK_TRAY_PENDING         "pidgin-tray-pending"
-/* Uncomment me after 2.0.2! 
- * #define PIDGIN_STOCK_TRAY_EMAIL		  "pidgin-tray-email"
- */
+#define PIDGIN_STOCK_TRAY_EMAIL		  "pidgin-tray-email"
 
 
 /*@}*/
--- a/pidgin/plugins/gtkbuddynote.c	Tue Jun 26 19:53:55 2007 +0000
+++ b/pidgin/plugins/gtkbuddynote.c	Fri Jun 29 18:03:53 2007 +0000
@@ -30,8 +30,8 @@
 	if (full) {
 		const gchar *note = purple_blist_node_get_string(node, "notes");
 
-		if (note != NULL) {
-			g_string_append_printf(text, _("\nBuddy Note: %s"),
+		if ((note != NULL) && (*note != '\0')) {
+			g_string_append_printf(text, _("\n<b>Buddy Note</b>: %s"),
 			                       note);
 		}
 	}
@@ -94,6 +94,7 @@
 check_for_buddynote(gpointer data)
 {
 	PurplePlugin *buddynote = NULL;
+	PurplePlugin *plugin = (PurplePlugin *)data;
 
 	buddynote = purple_plugins_find_with_id("core-plugin_pack-buddynote");
 
@@ -108,6 +109,18 @@
 
 		info.dependencies = g_list_append(info.dependencies,
 		                                  "core-plugin_pack-buddynote");
+
+		/* If non-gtk buddy note plugin is loaded, but we are not, then load
+		 * ourselves, otherwise people upgrading from pre-gtkbuddynote days
+		 * will not have 'Buddy Notes' showing as loaded in the plugins list.
+		 * We also trigger a save on the list of plugins because it's not been
+		 * loaded through the UI. */
+		if (purple_plugin_is_loaded(buddynote) &&
+		    !purple_plugin_is_loaded(plugin)) {
+			purple_plugin_load(plugin);
+			pidgin_plugins_save();
+		}
+
 	} else {
 		info.flags = PURPLE_PLUGIN_FLAG_INVISIBLE;
 	}
--- a/po/ChangeLog	Tue Jun 26 19:53:55 2007 +0000
+++ b/po/ChangeLog	Fri Jun 29 18:03:53 2007 +0000
@@ -1,5 +1,8 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
+version 2.1.0
+	* Korean translation updated (Sushizang)
+
 version 2.0.2
 	* Chinese (Traditional) translation updated (Ambrose C. Li)
 	* English (British) translation updated (Luke Ross)
--- a/po/ko.po	Tue Jun 26 19:53:55 2007 +0000
+++ b/po/ko.po	Fri Jun 29 18:03:53 2007 +0000
@@ -11,7 +11,7 @@
 "Project-Id-Version: gaim 2.0\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2005-10-27 16:12-0400\n"
-"PO-Revision-Date: 2007-05-07 09:18+0900\n"
+"PO-Revision-Date: 2007-06-28 10:48+0900\n"
 "Last-Translator: sushizang <sushizang@empal.com>\n"
 "Language-Team: GTP Korean <gnome-kr-translation@gnome.or.kr>\n"
 "MIME-Version: 1.0\n"
@@ -1388,18 +1388,34 @@
 msgid "Login Options"
 msgstr "로그인 설정"
 
-#: ../gtk/gtkaccount.c:492
-msgid "Local alias:"
-msgstr "별칭:"
+#: ../pidgin/gtkaccount.c:430
+msgid "Pro_tocol:"
+msgstr "프로토콜(_t):"
+
+#: ../pidgin/gtkaccount.c:441
+msgid "Screen _name:"
+msgstr "아이디(_n):"
+
+#: ../pidgin/gtkaccount.c:531
+msgid "_Local alias:"
+msgstr "별칭(_L):"
+
+#: ../pidgin/gtkaccount.c:535
+msgid "Remember pass_word"
+msgstr "비밀번호 저장"
 
 #. Build the user options frame.
 #: ../gtk/gtkaccount.c:554
 msgid "User Options"
 msgstr "사용자 설정"
 
+#: ../pidgin/gtkaccount.c:606
+msgid "New _mail notifications"
+msgstr "새 메일 알림"
+
 #. Buddy icon
-#: ../gtk/gtkaccount.c:572
-msgid "Use this buddy icon for this account:"
+#: ../pidgin/gtkaccount.c:611
+msgid "Use this buddy _icon for this account:"
 msgstr "다음 아이콘 사용:"
 
 #. Build the protocol options frame.
@@ -3906,6 +3922,22 @@
 msgid "F_lash window when IMs are received"
 msgstr "메시지를 받으면 창을 깜빡거림(_L)"
 
+#: ../pidgin/gtkprefs.c:943
+msgid "Font"
+msgstr "글꼴"
+
+#: ../pidgin/gtkprefs.c:945
+msgid "Use document font from _theme"
+msgstr "테마로부터 문서 글꼴 사용(_t)"
+
+#: ../pidgin/gtkprefs.c:947
+msgid "Use font from _theme"
+msgstr "테마로부터 글꼴 사용(_t)"
+
+#: ../pidgin/gtkprefs.c:949
+msgid "Conversation _font:"
+msgstr "대화창 글꼴(_f):"
+
 #: ../gtk/gtkprefs.c:925
 msgid "Default Formatting"
 msgstr "기본 서식"
@@ -4710,7 +4742,7 @@
 #. Not used yet.
 #: ../gtk/plugins/contact_priority.c:66
 msgid "Buddy is mobile"
-msgstr "이동 중인 친구"
+msgstr "휴대 기기 친구"
 
 #: ../gtk/plugins/contact_priority.c:68
 msgid "Buddy is offline"
@@ -9352,7 +9384,7 @@
 
 #: ../libgaim/protocols/msn/msn.c:291
 msgid "Set your mobile phone number."
-msgstr "이동 전화번호를 설정해 주십시오."
+msgstr "휴대 전화번호를 설정해 주십시오."
 
 #: ../libgaim/protocols/msn/msn.c:304
 msgid "Allow MSN Mobile pages?"
@@ -9360,7 +9392,7 @@
 
 #: ../libgaim/protocols/msn/msn.c:305
 msgid "Do you want to allow or disallow people on your buddy list to send you MSN Mobile pages to your cell phone or other mobile device?"
-msgstr "친구가 휴대 전화 등의 모바일 기기에 MSN 모바일 호출을 전송하는 것을 허가하시겠습니까?"
+msgstr "친구가 휴대 전화 등의 휴대용 기기에 MSN 모바일 호출을 전송하는 것을 허가하시겠습니까?"
 
 #: ../libgaim/protocols/msn/msn.c:309
 msgid "Allow"
@@ -9434,11 +9466,11 @@
 
 #: ../libgaim/protocols/msn/msn.c:638
 msgid "Enable/Disable Mobile Devices..."
-msgstr "모바일 기기 사용/사용 안 함..."
+msgstr "휴대용 기기 사용/사용 안 함..."
 
 #: ../libgaim/protocols/msn/msn.c:643
 msgid "Allow/Disallow Mobile Pages..."
-msgstr "모바일 호출 허가/허가 안 함..."
+msgstr "무선 호출 허가/허가 안 함..."
 
 #: ../libgaim/protocols/msn/msn.c:653
 msgid "Open Hotmail Inbox"
@@ -9446,7 +9478,7 @@
 
 #: ../libgaim/protocols/msn/msn.c:677
 msgid "Send to Mobile"
-msgstr "모바일 기기에 전송"
+msgstr "휴대용 기기에 전송"
 
 #: ../libgaim/protocols/msn/msn.c:687
 #: ../libgaim/protocols/novell/novell.c:3443
@@ -9563,11 +9595,11 @@
 
 #: ../libgaim/protocols/msn/msn.c:1602
 msgid "Home Phone"
-msgstr "자택 전화1"
+msgstr "자택 전화"
 
 #: ../libgaim/protocols/msn/msn.c:1603
 msgid "Home Phone 2"
-msgstr "자택 전화2"
+msgstr "자택 전화 2"
 
 #: ../libgaim/protocols/msn/msn.c:1604
 #: ../libgaim/protocols/oscar/oscar.c:3768
@@ -9576,7 +9608,7 @@
 
 #: ../libgaim/protocols/msn/msn.c:1605
 msgid "Personal Mobile"
-msgstr "휴대 전화"
+msgstr "개인 휴대 기기"
 
 #: ../libgaim/protocols/msn/msn.c:1606
 msgid "Home Fax"
@@ -9620,11 +9652,11 @@
 
 #: ../libgaim/protocols/msn/msn.c:1632
 msgid "Work Phone"
-msgstr "회사 전화1"
+msgstr "회사 전화"
 
 #: ../libgaim/protocols/msn/msn.c:1633
 msgid "Work Phone 2"
-msgstr "회사 전화2"
+msgstr "회사 전화 2"
 
 #: ../libgaim/protocols/msn/msn.c:1634
 #: ../libgaim/protocols/oscar/oscar.c:3781
@@ -9633,7 +9665,7 @@
 
 #: ../libgaim/protocols/msn/msn.c:1635
 msgid "Work Mobile"
-msgstr "회사 휴대 전화"
+msgstr "업무 휴대 기기"
 
 #: ../libgaim/protocols/msn/msn.c:1636
 msgid "Work Pager"
@@ -14816,7 +14848,7 @@
 
 #: ../libgaim/status.c:160
 msgid "Mobile"
-msgstr "이동 중"
+msgstr "휴대 기기"
 
 #: ../libgaim/status.c:611
 #, c-format