changeset 15642:58ec6ce6908d

merge of '2155bccb10577fa20eb47ac96a4912c91545a540' and 'ef4dfbce2370b5d09f48c571a9acb17da53c46c5'
author Sean Egan <seanegan@gmail.com>
date Thu, 15 Feb 2007 23:05:44 +0000
parents 35fa1d1c4ef2 (diff) e023cc99eb39 (current diff)
children ad6f0fb3f8f9
files
diffstat 19 files changed, 908 insertions(+), 80 deletions(-) [+]
line wrap: on
line diff
--- a/console/Makefile.am	Thu Feb 15 19:08:18 2007 +0000
+++ b/console/Makefile.am	Thu Feb 15 23:05:44 2007 +0000
@@ -10,6 +10,7 @@
 	gntconn.c \
 	gntconv.c \
 	gntdebug.c \
+	gntft.c \
 	gntgaim.c \
 	gntnotify.c \
 	gntplugin.c \
@@ -25,6 +26,7 @@
 	gntconn.h \
 	gntconv.h \
 	gntdebug.h \
+	gntft.h \
 	gntgaim.h \
 	gntnotify.h \
 	gntplugin.h \
--- a/console/gntblist.c	Thu Feb 15 19:08:18 2007 +0000
+++ b/console/gntblist.c	Thu Feb 15 23:05:44 2007 +0000
@@ -37,15 +37,16 @@
 #include "gntbox.h"
 #include "gntcombobox.h"
 #include "gntentry.h"
+#include "gntft.h"
 #include "gntlabel.h"
 #include "gntline.h"
 #include "gntmenu.h"
 #include "gntmenuitem.h"
 #include "gntmenuitemcheck.h"
+#include "gntpounce.h"
 #include "gnttree.h"
 #include "gntutils.h"
 #include "gntwindow.h"
-#include "gntpounce.h"
 
 #include "gntblist.h"
 #include "gntconv.h"
@@ -797,6 +798,24 @@
 }
 
 static void
+gg_blist_menu_send_file_cb(GaimBuddy *buddy, GaimBlistNode *selected)
+{
+	serv_send_file(buddy->account->gc, buddy->name, NULL);
+}
+
+static void
+gg_blist_pounce_node_cb(GaimBlistNode *node, GaimBlistNode *selected)
+{
+	GaimBuddy *b;
+	if (GAIM_BLIST_NODE_IS_CONTACT(node))
+		b = gaim_contact_get_priority_buddy((GaimContact *)node);
+	else
+		b = (GaimBuddy *)node;
+	gg_pounce_editor_show(b->account, b->name, NULL);
+}
+
+
+static void
 create_buddy_menu(GntMenu *menu, GaimBuddy *buddy)
 {
 	GaimPluginProtocolInfo *prpl_info;
@@ -808,18 +827,17 @@
 				GAIM_CALLBACK(gg_blist_get_buddy_info_cb), buddy);
 	}
 
-#if 0
-	add_custom_action(tree, _("Add Buddy Pounce"),
-			GAIM_CALLBACK(gg_blist_add_buddy_pounce_cb)), buddy);
+	add_custom_action(menu, _("Add Buddy Pounce"),
+			GAIM_CALLBACK(gg_blist_pounce_node_cb), buddy);
 
 	if (prpl_info && prpl_info->send_file)
 	{
 		if (!prpl_info->can_receive_file ||
 			prpl_info->can_receive_file(buddy->account->gc, buddy->name))
-			add_custom_action(tree, _("Send File"),
-					GAIM_CALLBACK(gg_blist_show_file_cb)), buddy);
+			add_custom_action(menu, _("Send File"),
+					GAIM_CALLBACK(gg_blist_menu_send_file_cb), buddy);
 	}
-
+#if 0
 	add_custom_action(tree, _("View Log"),
 			GAIM_CALLBACK(gg_blist_view_log_cb)), buddy);
 #endif
@@ -884,17 +902,6 @@
 }
 
 static void
-gg_blist_pounce_node_cb(GaimBlistNode *node, GaimBlistNode *selected)
-{
-	GaimBuddy *b;
-	if (GAIM_BLIST_NODE_IS_CONTACT(node))
-		b = gaim_contact_get_priority_buddy((GaimContact *)node);
-	else
-		b = (GaimBuddy *)node;
-	gg_pounce_editor_show(b->account, b->name, NULL);
-}
-
-static void
 gg_blist_rename_node_cb(GaimBlistNode *node, GaimBlistNode *selected)
 {
 	const char *name = NULL;
@@ -1137,8 +1144,6 @@
 		}
 
 		if (GAIM_BLIST_NODE_IS_BUDDY(node) || GAIM_BLIST_NODE_IS_CONTACT(node)) {
-			add_custom_action(GNT_MENU(context), _("Add Buddy Pounce"),
-					GAIM_CALLBACK(gg_blist_pounce_node_cb), node);
 			add_custom_action(GNT_MENU(context), _("Toggle Tag"),
 					GAIM_CALLBACK(gg_blist_toggle_tag_buddy), node);
 		}
--- a/console/gntdebug.c	Thu Feb 15 19:08:18 2007 +0000
+++ b/console/gntdebug.c	Thu Feb 15 23:05:44 2007 +0000
@@ -135,6 +135,10 @@
 }
 
 static void
+suppress_error_messages(const char *message)
+{}
+
+static void
 toggle_pause(GntWidget *w, gpointer n)
 {
 	debug.paused = !debug.paused;
@@ -283,6 +287,7 @@
 	REGISTER_G_LOG_HANDLER("GThread");
 
 	g_set_print_handler(print_stderr);   /* Redirect the debug messages to stderr */
+	g_set_printerr_handler(suppress_error_messages);
 
 	gaim_prefs_add_none(PREF_ROOT);
 	gaim_prefs_add_none(PREF_ROOT "/size");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/gntft.c	Thu Feb 15 23:05:44 2007 +0000
@@ -0,0 +1,532 @@
+/**
+ * @file gntft.c GNT File Transfer UI
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim 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 program 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 <gnt.h>
+#include <gntbox.h>
+#include <gntbutton.h>
+#include <gntcheckbox.h>
+#include <gntlabel.h>
+#include <gnttree.h>
+#include "internal.h"
+
+#include "debug.h"
+#include "notify.h"
+#include "ft.h"
+#include "prpl.h"
+#include "util.h"
+
+#include "gntft.h"
+#include "prefs.h"
+
+#define GAIM_GNTXFER(xfer) \
+	(GaimGntXferUiData *)(xfer)->ui_data
+
+typedef struct
+{
+	gboolean keep_open;
+	gboolean auto_clear;
+	gint num_transfers;
+
+	GntWidget *window;
+	GntWidget *tree;
+
+	GntWidget *remove_button;
+	GntWidget *stop_button;
+	GntWidget *close_button;
+} GaimGntXferDialog;
+
+static GaimGntXferDialog *xfer_dialog = NULL;
+
+typedef struct
+{
+	time_t last_updated_time;
+	gboolean in_list;
+
+	char *name;
+
+} GaimGntXferUiData;
+
+enum
+{
+	COLUMN_PROGRESS = 0,
+	COLUMN_FILENAME,
+	COLUMN_SIZE,
+	COLUMN_SPEED,
+	COLUMN_REMAINING,
+	COLUMN_STATUS,
+	NUM_COLUMNS
+};
+
+
+/**************************************************************************
+ * Utility Functions
+ **************************************************************************/
+
+static void
+update_title_progress()
+{
+	const GList *list;
+	int num_active_xfers = 0;
+	guint64 total_bytes_xferred = 0;
+	guint64 total_file_size = 0;
+
+	if (xfer_dialog == NULL || xfer_dialog->window == NULL)
+		return;
+
+	/* Find all active transfers */
+	for (list = gnt_tree_get_rows(GNT_TREE(xfer_dialog->tree)); list; list = list->next) {
+		GaimXfer *xfer = (GaimXfer *)list->data;
+
+		if (gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_STARTED) {
+			num_active_xfers++;
+			total_bytes_xferred += gaim_xfer_get_bytes_sent(xfer);
+			total_file_size += gaim_xfer_get_size(xfer);
+		}
+	}
+
+	/* Update the title */
+	if (num_active_xfers > 0) {
+		gchar *title;
+		int total_pct = 0;
+
+		if (total_file_size > 0) {
+			total_pct = 100 * total_bytes_xferred / total_file_size;
+		}
+
+		title = g_strdup_printf(_("File Transfers - %d%% of %d files"),
+				total_pct, num_active_xfers);
+		gnt_screen_rename_widget((xfer_dialog->window), title);
+		g_free(title);
+	} else {
+		gnt_screen_rename_widget((xfer_dialog->window), _("File Transfers"));
+	}
+}
+
+
+/**************************************************************************
+ * Callbacks
+ **************************************************************************/
+static void
+toggle_keep_open_cb(GntWidget *w)
+{
+	xfer_dialog->keep_open = !xfer_dialog->keep_open;
+	gaim_prefs_set_bool("/gaim/gnt/filetransfer/keep_open",
+						xfer_dialog->keep_open);
+}
+
+static void
+toggle_clear_finished_cb(GntWidget *w)
+{
+	xfer_dialog->auto_clear = !xfer_dialog->auto_clear;
+	gaim_prefs_set_bool("/gaim/gnt/filetransfer/clear_finished",
+						xfer_dialog->auto_clear);
+}
+
+static void
+remove_button_cb(GntButton *button)
+{
+	GaimXfer *selected_xfer = gnt_tree_get_selection_data(GNT_TREE(xfer_dialog->tree));
+	if (selected_xfer && (selected_xfer->status == GAIM_XFER_STATUS_CANCEL_LOCAL ||
+			selected_xfer->status == GAIM_XFER_STATUS_CANCEL_REMOTE ||
+			selected_xfer->status == GAIM_XFER_STATUS_DONE)) {
+		gg_xfer_dialog_remove_xfer(selected_xfer);
+	}
+}
+
+static void
+stop_button_cb(GntButton *button)
+{
+	GaimXfer *selected_xfer = gnt_tree_get_selection_data(GNT_TREE(xfer_dialog->tree));
+	if (selected_xfer && selected_xfer->status == GAIM_XFER_STATUS_STARTED)
+		gaim_xfer_cancel_local(selected_xfer);
+}
+
+#if 0
+static void
+tree_selection_changed_cb(GntTree *tree, GntTreeRow *old, GntTreeRow *current, gpointer n)
+{
+	xfer_dialog->selected_xfer = (GaimXfer *)gnt_tree_get_selection_data(tree);
+}
+#endif
+
+/**************************************************************************
+ * Dialog Building Functions
+ **************************************************************************/
+
+
+void
+gg_xfer_dialog_new(void)
+{
+	const GList *iter;
+	GntWidget *window;
+	GntWidget *bbox;
+	GntWidget *button;
+	GntWidget *checkbox;
+	GntWidget *tree;
+
+	if (!xfer_dialog)
+		xfer_dialog = g_new0(GaimGntXferDialog, 1);
+
+	xfer_dialog->keep_open =
+		gaim_prefs_get_bool("/gaim/gnt/filetransfer/keep_open");
+	xfer_dialog->auto_clear =
+		gaim_prefs_get_bool("/gaim/gnt/filetransfer/clear_finished");
+
+	/* Create the window. */
+	xfer_dialog->window = window = gnt_vbox_new(FALSE);
+	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gg_xfer_dialog_destroy), NULL);
+	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
+	gnt_box_set_title(GNT_BOX(window), _("File Transfers"));
+
+	xfer_dialog->tree = tree = gnt_tree_new_with_columns(NUM_COLUMNS);
+	gnt_tree_set_column_titles(GNT_TREE(tree), _("Progress"), _("Filename"), _("Size"), _("Speed"), _("Remaining"), _("Status"));
+	gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_PROGRESS, 8);
+	gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_FILENAME, 8);
+	gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_SIZE, 10);
+	gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_SPEED, 10);
+	gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_REMAINING, 10);
+	gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_STATUS, 10);
+	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
+	gnt_box_add_widget(GNT_BOX(window), tree);
+	/*g_signal_connect(G_OBJECT(tree), "selection-changed",*/
+					/*G_CALLBACK(tree_selection_changed_cb), NULL);*/
+	checkbox = gnt_check_box_new( _("Close this window when all transfers finish"));
+	gnt_check_box_set_checked(GNT_CHECK_BOX(checkbox),
+								 !xfer_dialog->keep_open);
+	g_signal_connect(G_OBJECT(checkbox), "toggled",
+					 G_CALLBACK(toggle_keep_open_cb), NULL);
+	gnt_box_add_widget(GNT_BOX(window), checkbox);
+
+	checkbox = gnt_check_box_new(_("Clear finished transfers"));
+	gnt_check_box_set_checked(GNT_CHECK_BOX(checkbox),
+								 xfer_dialog->auto_clear);
+	g_signal_connect(G_OBJECT(checkbox), "toggled",
+					 G_CALLBACK(toggle_clear_finished_cb), NULL);
+	gnt_box_add_widget(GNT_BOX(window), checkbox);
+
+	bbox = gnt_hbox_new(TRUE);
+
+	xfer_dialog->remove_button = button = gnt_button_new(_("Remove"));
+	g_signal_connect(G_OBJECT(button), "activate",
+					 G_CALLBACK(remove_button_cb), NULL);
+	gnt_box_add_widget(GNT_BOX(bbox), button);
+
+	xfer_dialog->stop_button = button = gnt_button_new(_("Stop"));
+	g_signal_connect(G_OBJECT(button), "activate",
+					 G_CALLBACK(stop_button_cb), NULL);
+	gnt_box_add_widget(GNT_BOX(bbox), button);
+
+	xfer_dialog->close_button = button = gnt_button_new(_("Close"));
+	g_signal_connect(G_OBJECT(button), "activate",
+					 G_CALLBACK(gg_xfer_dialog_destroy), NULL);
+	gnt_box_add_widget(GNT_BOX(bbox), button);
+
+	gnt_box_add_widget(GNT_BOX(window), bbox);
+
+	for (iter = gaim_xfers_get_all(); iter; iter = iter->next) {
+		GaimXfer *xfer = (GaimXfer *)iter->data;
+		GaimGntXferUiData *data = GAIM_GNTXFER(xfer);
+		if (data->in_list) {
+			gg_xfer_dialog_add_xfer(xfer);
+			gg_xfer_dialog_update_xfer(xfer);
+			gnt_tree_set_selected(GNT_TREE(tree), xfer);
+		}
+	}
+	gnt_widget_show(xfer_dialog->window);
+}
+
+void
+gg_xfer_dialog_destroy()
+{
+	gnt_widget_destroy(xfer_dialog->window);
+	g_free(xfer_dialog);
+	xfer_dialog = NULL;
+}
+
+void
+gg_xfer_dialog_show()
+{
+	if (xfer_dialog == NULL)
+		gg_xfer_dialog_new();
+}
+
+void
+gg_xfer_dialog_add_xfer(GaimXfer *xfer)
+{
+	GaimGntXferUiData *data;
+	GaimXferType type;
+	char *size_str, *remaining_str;
+	char *lfilename, *utf8;
+
+	g_return_if_fail(xfer_dialog != NULL);
+	g_return_if_fail(xfer != NULL);
+
+	gaim_xfer_ref(xfer);
+
+	data = GAIM_GNTXFER(xfer);
+	data->in_list = TRUE;
+
+	gg_xfer_dialog_show();
+
+	data->last_updated_time = 0;
+
+	type = gaim_xfer_get_type(xfer);
+
+	size_str      = gaim_str_size_to_units(gaim_xfer_get_size(xfer));
+	remaining_str = gaim_str_size_to_units(gaim_xfer_get_bytes_remaining(xfer));
+
+	lfilename = g_path_get_basename(gaim_xfer_get_local_filename(xfer));
+	utf8 = g_filename_to_utf8(lfilename, -1, NULL, NULL, NULL);
+	g_free(lfilename);
+	lfilename = utf8;
+	gnt_tree_add_row_last(GNT_TREE(xfer_dialog->tree), xfer,
+		gnt_tree_create_row(GNT_TREE(xfer_dialog->tree),
+			"0.0", (type == GAIM_XFER_RECEIVE) ? gaim_xfer_get_filename(xfer) : lfilename,
+			size_str, "0.0", "",_("Waiting for transfer to begin")), NULL);
+	g_free(lfilename);
+
+	g_free(size_str);
+	g_free(remaining_str);
+
+	xfer_dialog->num_transfers++;
+
+	update_title_progress();
+}
+
+void
+gg_xfer_dialog_remove_xfer(GaimXfer *xfer)
+{
+	GaimGntXferUiData *data;
+
+	g_return_if_fail(xfer_dialog != NULL);
+	g_return_if_fail(xfer != NULL);
+
+	data = GAIM_GNTXFER(xfer);
+
+	if (data == NULL)
+		return;
+
+	if (!data->in_list)
+		return;
+
+	data->in_list = FALSE;
+
+	gnt_tree_remove(GNT_TREE(xfer_dialog->tree), xfer);
+
+	xfer_dialog->num_transfers--;
+
+	if (xfer_dialog->num_transfers == 0 && !xfer_dialog->keep_open)
+		gg_xfer_dialog_destroy();
+	else 
+		update_title_progress();
+	gaim_xfer_unref(xfer);
+}
+
+void
+gg_xfer_dialog_cancel_xfer(GaimXfer *xfer)
+{
+	GaimGntXferUiData *data;
+	const gchar *status;
+
+	g_return_if_fail(xfer_dialog != NULL);
+	g_return_if_fail(xfer != NULL);
+
+	data = GAIM_GNTXFER(xfer);
+
+	if (data == NULL)
+		return;
+
+	if (!data->in_list)
+		return;
+
+	if ((gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_CANCEL_LOCAL) && (xfer_dialog->auto_clear)) {
+		gg_xfer_dialog_remove_xfer(xfer);
+		return;
+	}
+
+	data = GAIM_GNTXFER(xfer);
+
+	update_title_progress();
+
+	if (gaim_xfer_is_canceled(xfer))
+		status = _("Canceled");
+	else
+		status = _("Failed");
+
+	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, status);
+}
+
+void
+gg_xfer_dialog_update_xfer(GaimXfer *xfer)
+{
+	GaimGntXferUiData *data;
+	char *size_str, *remaining_str;
+	time_t current_time;
+	char prog_str[5];
+	double kb_sent, kb_rem;
+	double kbps = 0.0;
+	time_t elapsed, now;
+	char *kbsec;
+
+	if (xfer->end_time != 0)
+		now = xfer->end_time;
+	else
+		now = time(NULL);
+
+	kb_sent = gaim_xfer_get_bytes_sent(xfer) / 1024.0;
+	kb_rem  = gaim_xfer_get_bytes_remaining(xfer) / 1024.0;
+	elapsed = (xfer->start_time > 0 ? now - xfer->start_time : 0);
+	kbps    = (elapsed > 0 ? (kb_sent / elapsed) : 0);
+
+	kbsec = g_strdup_printf(_("%.2f KB/s"), kbps);
+
+	g_return_if_fail(xfer_dialog != NULL);
+	g_return_if_fail(xfer != NULL);
+
+	if ((data = GAIM_GNTXFER(xfer)) == NULL)
+		return;
+
+	if (data->in_list == FALSE)
+		return;
+
+	current_time = time(NULL);
+	if (((current_time - data->last_updated_time) == 0) &&
+		(!gaim_xfer_is_completed(xfer))) {
+		/* Don't update the window more than once per second */
+		return;
+	}
+	data->last_updated_time = current_time;
+
+	size_str      = gaim_str_size_to_units(gaim_xfer_get_size(xfer));
+	remaining_str = gaim_str_size_to_units(gaim_xfer_get_bytes_remaining(xfer));
+
+	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_PROGRESS,
+			g_ascii_dtostr(prog_str, sizeof(prog_str), gaim_xfer_get_progress(xfer) * 100.));
+	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_SIZE, size_str);
+	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_REMAINING, remaining_str);
+	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_SPEED, kbsec);
+	g_free(size_str);
+	g_free(remaining_str);
+	if (gaim_xfer_is_completed(xfer)) {
+		gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, _("Finished"));
+	} else {
+		gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, _("Transferring"));
+	}
+
+	update_title_progress();
+
+	if (gaim_xfer_is_completed(xfer) && xfer_dialog->auto_clear)
+		gg_xfer_dialog_remove_xfer(xfer);
+}
+
+/**************************************************************************
+ * File Transfer UI Ops
+ **************************************************************************/
+static void
+gg_xfer_new_xfer(GaimXfer *xfer)
+{
+	GaimGntXferUiData *data;
+
+	/* This is where we're setting xfer->ui_data for the first time. */
+	data = g_new0(GaimGntXferUiData, 1);
+	xfer->ui_data = data;
+}
+
+static void
+gg_xfer_destroy(GaimXfer *xfer)
+{
+	GaimGntXferUiData *data;
+
+	data = GAIM_GNTXFER(xfer);
+	if (data) {
+		g_free(data->name);
+		g_free(data);
+		xfer->ui_data = NULL;
+	}
+}
+
+static void
+gg_xfer_add_xfer(GaimXfer *xfer)
+{
+	if (!xfer_dialog)
+		gg_xfer_dialog_new();
+
+	gg_xfer_dialog_add_xfer(xfer);
+	gnt_tree_set_selected(GNT_TREE(xfer_dialog->tree), xfer);
+}
+
+static void
+gg_xfer_update_progress(GaimXfer *xfer, double percent)
+{
+	if (xfer_dialog)
+		gg_xfer_dialog_update_xfer(xfer);
+}
+
+static void
+gg_xfer_cancel_local(GaimXfer *xfer)
+{
+	if (xfer_dialog)
+		gg_xfer_dialog_cancel_xfer(xfer);
+}
+
+static void
+gg_xfer_cancel_remote(GaimXfer *xfer)
+{
+	if (xfer_dialog)
+		gg_xfer_dialog_cancel_xfer(xfer);
+}
+
+static GaimXferUiOps ops =
+{
+	gg_xfer_new_xfer,
+	gg_xfer_destroy,
+	gg_xfer_add_xfer,
+	gg_xfer_update_progress,
+	gg_xfer_cancel_local,
+	gg_xfer_cancel_remote
+};
+
+/**************************************************************************
+ * GNT File Transfer API
+ **************************************************************************/
+void
+gg_xfers_init(void)
+{
+	gaim_prefs_add_none("/gaim/gnt/filetransfer");
+	gaim_prefs_add_bool("/gaim/gnt/filetransfer/clear_finished", TRUE);
+	gaim_prefs_add_bool("/gaim/gnt/filetransfer/keep_open", FALSE);
+}
+
+void
+gg_xfers_uninit(void)
+{
+	if (xfer_dialog != NULL)
+		gg_xfer_dialog_destroy();
+}
+
+GaimXferUiOps *
+gg_xfers_get_ui_ops(void)
+{
+	return &ops;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/console/gntft.h	Thu Feb 15 23:05:44 2007 +0000
@@ -0,0 +1,123 @@
+/**
+ * @file gntft.h GNT File Transfer UI
+ * @ingroup gntui
+ *
+ * gaim
+ *
+ * Gaim 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 program 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 _GAIM_GNTFT_H_
+#define _GAIM_GNTFT_H_
+
+#include "ft.h"
+
+
+/**************************************************************************/
+/** @name GNT File Transfer Dialog API                                    */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Creates a new file transfer dialog.
+ *
+ * @return The new dialog.
+ */
+void gg_xfer_dialog_new(void);
+
+/**
+ * Destroys a file transfer dialog.
+ *
+ * @param dialog The file transfer dialog.
+ */
+void gg_xfer_dialog_destroy(void);
+
+/**
+ * Displays the file transfer dialog given.
+ * If dialog is @c NULL, displays the default dialog, creating one if necessary
+ *
+ * @param dialog The file transfer dialog to show.
+ */
+void gg_xfer_dialog_show(void);
+
+/**
+ * Hides the file transfer dialog.
+ *
+ * @param dialog The file transfer dialog to hide.
+ */
+void gg_xfer_dialog_hide();
+
+/**
+ * Adds a file transfer to the dialog.
+ *
+ * @param dialog The file transfer dialog.
+ * @param xfer   The file transfer.
+ */
+void gg_xfer_dialog_add_xfer(GaimXfer *xfer);
+
+/**
+ * Removes a file transfer from the dialog.
+ *
+ * @param dialog The file transfer dialog.
+ * @param xfer   The file transfer.
+ */
+void gg_xfer_dialog_remove_xfer(GaimXfer *xfer);
+
+/**
+ * Indicate in a file transfer dialog that a transfer was canceled.
+ *
+ * @param dialog The file transfer dialog.
+ * @param xfer   The file transfer that was canceled.
+ */
+void gg_xfer_dialog_cancel_xfer(GaimXfer *xfer);
+
+/**
+ * Updates the information for a transfer in the dialog.
+ *
+ * @param dialog The file transfer dialog.
+ * @param xfer   The file transfer.
+ */
+void gg_xfer_dialog_update_xfer(GaimXfer *xfer);
+
+/*@}*/
+
+/**************************************************************************/
+/** @name GNT  File Transfer API                                          */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Initializes the GNT file transfer system.
+ */
+void gg_xfers_init(void);
+
+/**
+ * Uninitializes the GNT file transfer system.
+ */
+void gg_xfers_uninit(void);
+
+/**
+ * Returns the UI operations structure for the GNT file transfer UI.
+ *
+ * @return The GNT file transfer UI operations structure.
+ */
+GaimXferUiOps *gg_xfers_get_ui_ops(void);
+
+/*@}*/
+
+#endif /* _GAIM_GNTFT_H_ */
--- a/console/gntgaim.c	Thu Feb 15 19:08:18 2007 +0000
+++ b/console/gntgaim.c	Thu Feb 15 23:05:44 2007 +0000
@@ -396,9 +396,6 @@
 
 int main(int argc, char **argv)
 {
-	/* XXX: Don't puke */
-	freopen(".error", "w", stderr);
-
 	signal(SIGPIPE, SIG_IGN);
 
 	/* Initialize the libgaim stuff */
--- a/console/gntui.c	Thu Feb 15 19:08:18 2007 +0000
+++ b/console/gntui.c	Thu Feb 15 23:05:44 2007 +0000
@@ -26,13 +26,13 @@
 #include "gntconn.h"
 #include "gntconv.h"
 #include "gntdebug.h"
+#include "gntft.h"
 #include "gntnotify.h"
 #include "gntplugin.h"
 #include "gntpounce.h"
 #include "gntprefs.h"
 #include "gntrequest.h"
 #include "gntstatus.h"
-
 #include "internal.h"
 
 #include <prefs.h>
@@ -70,10 +70,14 @@
 
 	gg_pounces_init();
 
+	gg_xfers_init();
+	gaim_xfers_set_ui_ops(gg_xfers_get_ui_ops());
+
 	gnt_register_action(_("Accounts"), gg_accounts_show_all);
 	gnt_register_action(_("Buddy List"), gg_blist_show);
 	gnt_register_action(_("Buddy Pounces"), gg_pounces_manager_show);
 	gnt_register_action(_("Debug Window"), gg_debug_window_show);
+	gnt_register_action(_("File Transfers"), gg_xfer_dialog_show);
 	gnt_register_action(_("Plugins"), gg_plugins_show_all);
 	gnt_register_action(_("Preferences"), gg_prefs_show_all);
 	gnt_register_action(_("Statuses"), gg_savedstatus_show_all);
@@ -105,6 +109,9 @@
 
 	gg_pounces_uninit();
 
+	gg_xfers_uninit();
+	gaim_xfers_set_ui_ops(NULL);
+
 	gnt_quit();
 #endif
 }
--- a/console/libgnt/gntbindable.h	Thu Feb 15 19:08:18 2007 +0000
+++ b/console/libgnt/gntbindable.h	Thu Feb 15 23:05:44 2007 +0000
@@ -13,7 +13,7 @@
 #define GNT_IS_BINDABLE_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_BINDABLE))
 #define GNT_BINDABLE_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_BINDABLE, GntBindableClass))
 
-#define	GNTDEBUG	fprintf(stderr, "%s\n", __FUNCTION__)
+#define	GNTDEBUG	g_printerr("%s\n", __FUNCTION__)
 
 typedef struct _GnBindable			GntBindable;
 typedef struct _GnBindableClass		GntBindableClass;
--- a/console/libgnt/gnttree.c	Thu Feb 15 19:08:18 2007 +0000
+++ b/console/libgnt/gnttree.c	Thu Feb 15 23:05:44 2007 +0000
@@ -512,7 +512,8 @@
 static void
 tree_selection_changed(GntTree *tree, GntTreeRow *old, GntTreeRow *current)
 {
-	g_signal_emit(tree, signals[SIG_SELECTION_CHANGED], 0, old->key, current->key);
+	g_signal_emit(tree, signals[SIG_SELECTION_CHANGED], 0, old ? old->key : NULL,
+				current ? current->key : NULL);
 }
 
 static gboolean
@@ -678,7 +679,8 @@
 	int i;
 
 	end_search(tree);
-	g_hash_table_destroy(tree->hash);
+	if (tree->hash)
+		g_hash_table_destroy(tree->hash);
 	g_list_free(tree->list);
 
 	for (i = 0; i < tree->ncol; i++)
--- a/libpurple/ft.c	Thu Feb 15 19:08:18 2007 +0000
+++ b/libpurple/ft.c	Thu Feb 15 23:05:44 2007 +0000
@@ -35,9 +35,16 @@
 #define FT_MAX_BUFFER_SIZE     65535
 
 static GaimXferUiOps *xfer_ui_ops = NULL;
+static GList *xfers;
 
 static int gaim_xfer_choose_file(GaimXfer *xfer);
 
+GList *
+gaim_xfers_get_all()
+{
+	return xfers;
+}
+
 GaimXfer *
 gaim_xfer_new(GaimAccount *account, GaimXferType type, const char *who)
 {
@@ -63,6 +70,7 @@
 	if (ui_ops != NULL && ui_ops->new_xfer != NULL)
 		ui_ops->new_xfer(xfer);
 
+	xfers = g_list_prepend(xfers, xfer);
 	return xfer;
 }
 
@@ -90,6 +98,7 @@
 	g_free(xfer->local_filename);
 
 	g_free(xfer);
+	xfers = g_list_remove(xfers, xfer);
 }
 
 void
--- a/libpurple/ft.h	Thu Feb 15 19:08:18 2007 +0000
+++ b/libpurple/ft.h	Thu Feb 15 23:05:44 2007 +0000
@@ -163,6 +163,13 @@
 								GaimXferType type, const char *who);
 
 /**
+ * Returns all xfers
+ *
+ * @return all current xfers with refs
+ */
+GList *gaim_xfers_get_all(void);
+
+/**
  * Increases the reference count on a GaimXfer.
  * Please call gaim_xfer_unref later.
  *
--- a/libpurple/gaim-compat.h	Thu Feb 15 19:08:18 2007 +0000
+++ b/libpurple/gaim-compat.h	Thu Feb 15 23:05:44 2007 +0000
@@ -1844,4 +1844,144 @@
 
 #define gaim_sounds_get_handle  purple_sounds_get_handle
 
+/* from sslconn.h */
+
+#define GAIM_SSL_DEFAULT_PORT  PURPLE_SSL_DEFAULT_PORT
+
+#define GAIM_SSL_HANDSHAKE_FAILED  PURPLE_SSL_HANDSHAKE_FAILED
+#define GAIM_SSL_CONNECT_FAILED    PURPLE_SSL_CONNECT_FAILED
+#define GaimSslErrorType  PurpleSslErrorType
+
+#define GaimSslConnection  PurpleSslConnection
+
+#define GaimSslInputFunction  PurpleSslInputFunction
+#define GaimSslErrorFunction  PurpleSslErrorFunction
+
+#define GaimSslOps  PurpleSslOps
+
+#define gaim_ssl_is_supported  purple_ssl_is_supported
+#define gaim_ssl_connect       purple_ssl_connect
+#define gaim_ssl_connect_fd    purple_ssl_connect_fd
+#define gaim_ssl_input_add     purple_ssl_input_add
+#define gaim_ssl_close         purple_ssl_close
+#define gaim_ssl_read          purple_ssl_read
+#define gaim_ssl_write         purple_ssl_write
+
+#define gaim_ssl_set_ops  purple_ssl_set_ops
+#define gaim_ssl_get_ops  purple_ssl_get_ops
+#define gaim_ssl_init     purple_ssl_init
+#define gaim_ssl_uninit   purple_ssl_uninit
+
+/* from status.h */
+
+#define GaimStatusType  PurpleStatusType
+#define GaimStatusAttr  PurpleStatusAttr
+#define GaimPresence    PurplePresence
+#define GaimStatus      PurpleStatus
+
+#define GAIM_PRESENCE_CONTEXT_UNSET    PURPLE_PRESENCE_CONTEXT_UNSET
+#define GAIM_PRESENCE_CONTEXT_ACCOUNT  PURPLE_PRESENCE_CONTEXT_ACCOUNT
+#define GAIM_PRESENCE_CONTEXT_CONV     PURPLE_PRESENCE_CONTEXT_CONV
+#define GAIM_PRESENCE_CONTEXT_BUDDY    PURPLE_PRESENCE_CONTEXT_BUDDY
+#define GaimPresenceContext  PurplePresenceContext
+
+#define GAIM_STATUS_UNSET           PURPLE_STATUS_UNSET
+#define GAIM_STATUS_OFFLINE         PURPLE_STATUS_OFFLINE
+#define GAIM_STATUS_AVAILABLE       PURPLE_STATUS_AVAILABLE
+#define GAIM_STATUS_UNAVAILABLE     PURPLE_STATUS_UNAVAILABLE
+#define GAIM_STATUS_INVISIBLE       PURPLE_STATUS_INVISIBLE
+#define GAIM_STATUS_AWAY            PURPLE_STATUS_AWAY
+#define GAIM_STATUS_EXTENDED_AWAY   PURPLE_STATUS_EXTENDED_AWAY
+#define GAIM_STATUS_MOBILE          PURPLE_STATUS_MOBILE
+#define GAIM_STATUS_NUM_PRIMITIVES  PURPLE_STATUS_NUM_PRIMITIVES
+#define GaimStatusPrimitive  PurpleStatusPrimitive
+
+#define gaim_primitive_get_id_from_type    purple_primitive_get_id_from_type
+#define gaim_primitive_get_name_from_type  purple_primitive_get_name_from_type
+#define gaim_primitive_get_type_from_id    purple_primitive_get_type_from_id
+
+#define gaim_status_type_new_full          purple_status_type_new_full
+#define gaim_status_type_new               purple_status_type_new
+#define gaim_status_type_new_with_attrs    purple_status_type_new_with_attrs
+#define gaim_status_type_destroy           purple_status_type_destroy
+#define gaim_status_type_set_primary_attr  purple_status_type_set_primary_attr
+#define gaim_status_type_add_attr          purple_status_type_add_attr
+#define gaim_status_type_add_attrs         purple_status_type_add_attrs
+#define gaim_status_type_add_attrs_vargs   purple_status_type_add_attrs_vargs
+#define gaim_status_type_get_primitive     purple_status_type_get_primitive
+#define gaim_status_type_get_id            purple_status_type_get_id
+#define gaim_status_type_get_name          purple_status_type_get_name
+#define gaim_status_type_is_saveable       purple_status_type_is_saveable
+#define gaim_status_type_is_user_settable  purple_status_type_is_user_settable
+#define gaim_status_type_is_independent    purple_status_type_is_independent
+#define gaim_status_type_is_exclusive      purple_status_type_is_exclusive
+#define gaim_status_type_is_available      purple_status_type_is_available
+#define gaim_status_type_get_primary_attr  purple_status_type_get_primary_attr
+#define gaim_status_type_get_attr          purple_status_type_get_attr
+#define gaim_status_type_get_attrs         purple_status_type_get_attrs
+#define gaim_status_type_find_with_id      purple_status_type_find_with_id
+
+#define gaim_status_attr_new        purple_status_attr_new
+#define gaim_status_attr_destroy    purple_status_attr_destroy
+#define gaim_status_attr_get_id     purple_status_attr_get_id
+#define gaim_status_attr_get_name   purple_status_attr_get_name
+#define gaim_status_attr_get_value  purple_status_attr_get_value
+
+#define gaim_status_new                         purple_status_new
+#define gaim_status_destroy                     purple_status_destroy
+#define gaim_status_set_active                  purple_status_set_active
+#define gaim_status_set_active_with_attrs       purple_status_set_active_with_attrs
+#define gaim_status_set_active_with_attrs_list  purple_status_set_active_with_attrs_list
+#define gaim_status_set_attr_boolean            purple_status_set_attr_boolean
+#define gaim_status_set_attr_int                purple_status_set_attr_int
+#define gaim_status_set_attr_string             purple_status_set_attr_string
+#define gaim_status_get_type                    purple_status_get_type
+#define gaim_status_get_presence                purple_status_get_presence
+#define gaim_status_get_id                      purple_status_get_id
+#define gaim_status_get_name                    purple_status_get_name
+#define gaim_status_is_independent              purple_status_is_independent
+#define gaim_status_is_exclusive                purple_status_is_exclusive
+#define gaim_status_is_available                purple_status_is_available
+#define gaim_status_is_active                   purple_status_is_active
+#define gaim_status_is_online                   purple_status_is_online
+#define gaim_status_get_attr_value              purple_status_get_attr_value
+#define gaim_status_get_attr_boolean            purple_status_get_attr_boolean
+#define gaim_status_get_attr_int                purple_status_get_attr_int
+#define gaim_status_get_attr_string             purple_status_get_attr_string
+#define gaim_status_compare                     purple_status_compare
+
+#define gaim_presence_new                purple_presence_new
+#define gaim_presence_new_for_account    purple_presence_new_for_account
+#define gaim_presence_new_for_conv       purple_presence_new_for_conv
+#define gaim_presence_new_for_buddy      purple_presence_new_for_buddy
+#define gaim_presence_destroy            purple_presence_destroy
+#define gaim_presence_remove_buddy       purple_presence_remove_buddy
+#define gaim_presence_add_status         purple_presence_add_status
+#define gaim_presence_add_list           purple_presence_add_list
+#define gaim_presence_set_status_active  purple_presence_set_status_active
+#define gaim_presence_switch_status      purple_presence_switch_status
+#define gaim_presence_set_idle           purple_presence_set_idle
+#define gaim_presence_set_login_time     purple_presence_set_login_time
+#define gaim_presence_get_context        purple_presence_get_context
+#define gaim_presence_get_account        purple_presence_get_account
+#define gaim_presence_get_conversation   purple_presence_get_conversation
+#define gaim_presence_get_chat_user      purple_presence_get_chat_user
+#define gaim_presence_get_buddies        purple_presence_get_buddies
+#define gaim_presence_get_statuses       purple_presence_get_statuses
+#define gaim_presence_get_status         purple_presence_get_status
+#define gaim_presence_get_active_status  purple_presence_get_active_status
+#define gaim_presence_is_available       purple_presence_is_available
+#define gaim_presence_is_online          purple_presence_is_online
+#define gaim_presence_is_status_active   purple_presence_is_status_active
+#define gaim_presence_is_status_primitive_active \
+	purple_presence_is_status_primitive_active
+#define gaim_presence_is_idle            purple_presence_is_idle
+#define gaim_presence_get_idle_time      purple_presence_get_idle_time
+#define gaim_presence_get_login_time     purple_presence_get_login_time
+#define gaim_presence_compare            purple_presence_compare
+
+#define gaim_status_get_handle  purple_status_get_handle
+#define gaim_status_init        purple_status_init
+#define gaim_status_uninit      purple_status_uninit
+
 #endif /* _GAIM_COMPAT_H_ */
--- a/pidgin/gtkeventloop.c	Thu Feb 15 19:08:18 2007 +0000
+++ b/pidgin/gtkeventloop.c	Thu Feb 15 23:05:44 2007 +0000
@@ -63,7 +63,7 @@
 
 #ifdef _WIN32
 	if(! gaim_cond) {
-#if DEBUG
+#ifdef DEBUG
 		gaim_debug(GAIM_DEBUG_MISC, "gtk_eventloop",
 			   "CLOSURE received GIOCondition of 0x%x, which does not"
 			   " match 0x%x (READ) or 0x%x (WRITE)\n",
--- a/pidgin/gtkmain.c	Thu Feb 15 19:08:18 2007 +0000
+++ b/pidgin/gtkmain.c	Thu Feb 15 23:05:44 2007 +0000
@@ -455,6 +455,8 @@
 
 /* FUCKING GET ME A TOWEL! */
 #ifdef _WIN32
+/* suppress gcc "no previous prototype" warning */
+int pidgin_main(HINSTANCE hint, int argc, char *argv[]);
 int pidgin_main(HINSTANCE hint, int argc, char *argv[])
 #else
 int main(int argc, char *argv[])
@@ -726,7 +728,7 @@
 	/* TODO: Move pounces loading into gaim_pounces_init() */
 	gaim_pounces_load();
 
-	
+
 	/* HACK BY SEANEGAN:
 	 * We've renamed prpl-oscar to prpl-aim and prpl-icq, accordingly.
 	 * Let's do that change right here... after everything's loaded, but
@@ -741,7 +743,7 @@
 				gaim_account_set_protocol_id(account, "prpl-aim");
 		}
 	}
-	
+
 	ui_main();
 
 #ifdef USE_SM
--- a/pidgin/plugins/win32/winprefs/gtkappbar.c	Thu Feb 15 19:08:18 2007 +0000
+++ b/pidgin/plugins/win32/winprefs/gtkappbar.c	Thu Feb 15 23:05:44 2007 +0000
@@ -4,7 +4,7 @@
  * File: gtkappbar.c
  * Date: August 2, 2003
  * Description: Appbar functionality for Windows GTK+ applications
- * 
+ *
  * Copyright (C) 2003, Herman Bloggs <hermanator12002@yahoo.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -128,21 +128,17 @@
 }
 
 /* Retrieve the rectangle of the active work area at a point */
-static RECT get_rect_at_point(POINT pt) {
-	RECT rc;
-	if (!get_rect_at_point_multimonitor(pt, &rc)) {
-		get_default_workarea(&rc);
+static void get_rect_at_point(POINT pt, RECT *rc) {
+	if (!get_rect_at_point_multimonitor(pt, rc)) {
+		get_default_workarea(rc);
 	}
-	return rc;
 }
 
 /* Retrieve the rectangle of the active work area of a window*/
-static RECT get_rect_of_window(HWND window) {
-	RECT rc;
-	if (!get_rect_of_window_multimonitor(window, &rc)) {
-		get_default_workarea(&rc);
+static void get_rect_of_window(HWND window, RECT *rc) {
+	if (!get_rect_of_window_multimonitor(window, rc)) {
+		get_default_workarea(rc);
 	}
-	return rc;
 }
 
 static void get_window_normal_rc(HWND hwnd, RECT *rc) {
@@ -173,7 +169,7 @@
 	
 /*	This really should be the following, but SWP_FRAMECHANGED strangely causes initermittent problems "Show Desktop" done more than once.
  *	Not having SWP_FRAMECHANGED *should* cause the Style not to be applied, but i haven't noticed any problems
- *			SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); 
+ *			SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
  */
 }
 /** Register the window as an appbar */
@@ -212,15 +208,15 @@
 	APPBARDATA abd;
 	guint iWidth = 0;
 
-        if(!ab->registered)
-                gtk_appbar_register(ab, hwnd);
+	if(!ab->registered)
+		gtk_appbar_register(ab, hwnd);
 
 	abd.hWnd = hwnd;
 	abd.cbSize = sizeof(APPBARDATA);
 	abd.uEdge = ab->side;
 
 	iWidth = ab->docked_rect.right - ab->docked_rect.left;
-        
+
 	abd.rc.top = rcWorkspace.top;
 	abd.rc.bottom = rcWorkspace.bottom;
 	switch (abd.uEdge)
@@ -288,7 +284,7 @@
         gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "wnd_moving\n");
 
         GetCursorPos(&cp);
-	monRect = get_rect_at_point(cp);
+	get_rect_at_point(cp, &monRect);
 
 	dockAreaWidth = (monRect.right - monRect.left) / 10;
         /* Which part of the screen are we in ? */
@@ -318,7 +314,7 @@
                 rc->bottom = rc->top + ab->undocked_height;
         }
 
-        /* Switch to toolbar/regular caption*/ 
+        /* Switch to toolbar/regular caption*/
         if(ab->docking)
                 set_toolbar(msg->hwnd, TRUE);
         else if(!ab->docked)
@@ -453,7 +449,7 @@
 
 static GdkFilterReturn wnd_nchittest(GtkAppBar *ab, GdkXEvent *xevent) {
         MSG *msg = (MSG*)xevent;
-        
+
         if(ab->docked) {
                 UINT ret = DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
 
@@ -463,7 +459,7 @@
                 case HTBOTTOMRIGHT:
                 case HTTOP:
                 case HTTOPLEFT:
-                case HTTOPRIGHT: 
+                case HTTOPRIGHT:
                         return GDK_FILTER_REMOVE;
                 case HTLEFT:
                         if(ab->side == ABE_LEFT)
@@ -499,7 +495,7 @@
 
 static GdkFilterReturn gtk_appbar_callback(GtkAppBar *ab, GdkXEvent *xevent) {
         MSG *msg = (MSG*)xevent;
-	RECT orig;
+	RECT orig, windowRect;
 
         switch (msg->wParam) {
         case ABN_STATECHANGE:
@@ -519,18 +515,18 @@
 		}
 
                 break;
-        
-    	case ABN_POSCHANGED:
-                gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: ABN_POSCHANGED\n");
-        	CopyRect(&orig, &(ab->docked_rect));
-		gtk_appbar_querypos(ab, msg->hwnd, get_rect_of_window(msg->hwnd));
+	case ABN_POSCHANGED:
+		gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: ABN_POSCHANGED\n");
+		CopyRect(&orig, &(ab->docked_rect));
+		get_rect_of_window(msg->hwnd, &windowRect);
+		gtk_appbar_querypos(ab, msg->hwnd, windowRect);
 		if (EqualRect(&orig, &(ab->docked_rect)) == 0) {
-			MoveWindow(msg->hwnd, ab->docked_rect.left, ab->docked_rect.top, 
+			MoveWindow(msg->hwnd, ab->docked_rect.left, ab->docked_rect.top,
 				ab->docked_rect.right - ab->docked_rect.left,
 				ab->docked_rect.bottom - ab->docked_rect.top, TRUE);
 		}
                 gtk_appbar_setpos(ab, msg->hwnd);
-        	break;
+		break;
 #if 0
 	default:
 		gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: %d\n", msg->wParam);
@@ -577,7 +573,7 @@
 }
 
 void gtk_appbar_dock(GtkAppBar *ab, UINT side) {
-        RECT orig;
+	RECT orig, windowRect;
 
         gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_dock\n");
 
@@ -587,12 +583,12 @@
         ab->side = side;
         get_window_normal_rc(GDK_WINDOW_HWND(ab->win->window), &(ab->docked_rect));
         CopyRect(&orig, &(ab->docked_rect));
-	gtk_appbar_querypos(ab, GDK_WINDOW_HWND(ab->win->window),
-			get_rect_of_window(GDK_WINDOW_HWND(ab->win->window)));
+	get_rect_of_window(GDK_WINDOW_HWND(ab->win->window), &windowRect);
+	gtk_appbar_querypos(ab, GDK_WINDOW_HWND(ab->win->window), windowRect);
         if(EqualRect(&orig, &(ab->docked_rect)) == 0)
                 MoveWindow(GDK_WINDOW_HWND(ab->win->window),
                            ab->docked_rect.left,
-                           ab->docked_rect.top, 
+                           ab->docked_rect.top,
                            ab->docked_rect.right - ab->docked_rect.left,
                            ab->docked_rect.bottom - ab->docked_rect.top, TRUE);
         gtk_appbar_setpos(ab, GDK_WINDOW_HWND(ab->win->window));
--- a/pidgin/win32/IdleTracker/idletrack.c	Thu Feb 15 19:08:18 2007 +0000
+++ b/pidgin/win32/IdleTracker/idletrack.c	Thu Feb 15 23:05:44 2007 +0000
@@ -172,7 +172,9 @@
 		CloseHandle(hMapObject);
 }
 
-int WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) {
+/* suppress gcc "no previous prototype" warning */
+BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved);
+BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) {
 	switch(dwReason) {
 		case DLL_PROCESS_ATTACH:
 			g_hInstance = hInstance;
--- a/pidgin/win32/gtkwin32dep.c	Thu Feb 15 19:08:18 2007 +0000
+++ b/pidgin/win32/gtkwin32dep.c	Thu Feb 15 23:05:44 2007 +0000
@@ -329,7 +329,7 @@
 	if(!winpidgin_set_idlehooks())
 		gaim_debug_error("winpidgin", "Failed to initialize idle tracker\n");
 
-	wpidginspell_init();
+	winpidgin_spell_init();
 	gaim_debug_info("winpidgin", "GTK+ :%u.%u.%u\n",
 		gtk_major_version, gtk_minor_version, gtk_micro_version);
 
@@ -365,6 +365,8 @@
 }
 
 /* DLL initializer */
+/* suppress gcc "no previous prototype" warning */
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
 	dll_hInstance = hinstDLL;
 	return TRUE;
--- a/pidgin/win32/wspell.c	Thu Feb 15 19:08:18 2007 +0000
+++ b/pidgin/win32/wspell.c	Thu Feb 15 23:05:44 2007 +0000
@@ -30,17 +30,14 @@
 #include <gtkspell/gtkspell.h>
 #include "debug.h"
 #include "win32dep.h"
+#include "wspell.h"
 
 /* GTKSPELL DUMMY FUNCS */
-GtkSpell* wgtkspell_new_attach(GtkTextView *view,
-			       const gchar *lang,
-			       GError **error) {return NULL;}
-GtkSpell* wgtkspell_get_from_text_view(GtkTextView *view) {return NULL;}
-void      wgtkspell_detach(GtkSpell *spell) {}
-gboolean  wgtkspell_set_language(GtkSpell *spell,
-				const gchar *lang,
-				GError **error) {return 0;}
-void      wgtkspell_recheck_all(GtkSpell *spell) {}
+static GtkSpell* wgtkspell_new_attach(GtkTextView *view, const gchar *lang, GError **error) {return NULL;}
+static GtkSpell* wgtkspell_get_from_text_view(GtkTextView *view) {return NULL;}
+static void wgtkspell_detach(GtkSpell *spell) {}
+static gboolean wgtkspell_set_language(GtkSpell *spell, const gchar *lang, GError **error) {return FALSE;}
+static void wgtkspell_recheck_all(GtkSpell *spell) {}
 
 /* GTKSPELL PROTOS */
 GtkSpell*         (*wpidginspell_new_attach)              (GtkTextView *,
@@ -58,11 +55,11 @@
 void              (*wpidginspell_recheck_all)             (GtkSpell*) = wgtkspell_recheck_all;
 
 static void load_gtkspell() {
-	wpidginspell_new_attach = (void*)wgaim_find_and_loadproc("libgtkspell.dll", "gtkspell_new_attach" );
-	wpidginspell_get_from_text_view = (void*)wgaim_find_and_loadproc("libgtkspell.dll", "gtkspell_get_from_text_view");
-	wpidginspell_detach = (void*)wgaim_find_and_loadproc("libgtkspell.dll", "gtkspell_detach");
-	wpidginspell_set_language = (void*)wgaim_find_and_loadproc("libgtkspell.dll", "gtkspell_set_language");
-	wpidginspell_recheck_all = (void*)wgaim_find_and_loadproc("libgtkspell.dll", "gtkspell_recheck_all");
+	wpidginspell_new_attach = (void*) wgaim_find_and_loadproc("libgtkspell.dll", "gtkspell_new_attach" );
+	wpidginspell_get_from_text_view = (void*) wgaim_find_and_loadproc("libgtkspell.dll", "gtkspell_get_from_text_view");
+	wpidginspell_detach = (void*) wgaim_find_and_loadproc("libgtkspell.dll", "gtkspell_detach");
+	wpidginspell_set_language = (void*) wgaim_find_and_loadproc("libgtkspell.dll", "gtkspell_set_language");
+	wpidginspell_recheck_all = (void*) wgaim_find_and_loadproc("libgtkspell.dll", "gtkspell_recheck_all");
 }
 
 static char* lookup_aspell_path() {
@@ -74,7 +71,7 @@
 	return wgaim_read_reg_string(HKEY_LOCAL_MACHINE, "Software\\Aspell", "Path");
 }
 
-void wpidginspell_init() {
+void winpidgin_spell_init() {
 	char *aspell_path = lookup_aspell_path();
 
 	if (aspell_path != NULL) {
--- a/pidgin/win32/wspell.h	Thu Feb 15 19:08:18 2007 +0000
+++ b/pidgin/win32/wspell.h	Thu Feb 15 23:05:44 2007 +0000
@@ -24,7 +24,7 @@
 #define _WSPELL_H_
 #include <gtkspell/gtkspell.h>
 
-void wpidginspell_init(void);
+void winpidgin_spell_init(void);
 
 extern GtkSpell* (*wpidginspell_new_attach)(GtkTextView*, const gchar*, GError**);
 #define gtkspell_new_attach( view, lang, error ) \
@@ -38,7 +38,7 @@
 #define gtkspell_detach( spell ) \
 wpidginspell_detach( spell )
 
-extern gboolean (*wpidginspell_set_language)(GtkSpell*,	const gchar*, GError**);
+extern gboolean (*wpidginspell_set_language)(GtkSpell*, const gchar*, GError**);
 #define gtkspell_set_language( spell, lang, error ) \
 wpidginspell_set_language( spell, lang, error )