[pan2] Bug 596648: remove deprecated glib/gdk/gtk calls to prepare for GNOME 3



commit 75134b8d83e9c47aa7098dbd6ff98eedd6ebd664
Author: Charles Kerr <charles rebelbase com>
Date:   Mon Sep 28 13:57:29 2009 -0500

    Bug 596648: remove deprecated glib/gdk/gtk calls to prepare for GNOME 3

 pan/gui/Makefile.am           |   12 +-
 pan/gui/actions.cc            |    2 +-
 pan/gui/body-pane.cc          |    8 +-
 pan/gui/dl-headers-ui.cc      |    4 +-
 pan/gui/e-action-combo-box.c  |  583 +++++++++++++++++++++++++
 pan/gui/e-action-combo-box.h  |   85 ++++
 pan/gui/e-charset-combo-box.c |  463 ++++++++++++++++++++
 pan/gui/e-charset-combo-box.h |   69 +++
 pan/gui/e-charset-dialog.c    |   95 ++++
 pan/gui/e-charset-dialog.h    |   11 +
 pan/gui/e-charset-picker.c    |  439 -------------------
 pan/gui/e-charset-picker.h    |   41 --
 pan/gui/e-charset.c           |  257 +++++++++++
 pan/gui/e-charset.h           |   36 ++
 pan/gui/group-pane.cc         |   14 +-
 pan/gui/group-prefs-dialog.cc |   10 +-
 pan/gui/gui.cc                |   69 ++--
 pan/gui/gui.h                 |    1 -
 pan/gui/header-pane.cc        |   28 +-
 pan/gui/log-ui.cc             |    2 +-
 pan/gui/pad.h                 |    4 +
 pan/gui/pan-tree.cc           |    4 +-
 pan/gui/pan-tree.h            |    8 +-
 pan/gui/post-ui.cc            |   22 +-
 pan/gui/post-ui.h             |    1 -
 pan/gui/prefs-ui.cc           |   46 +-
 pan/gui/profiles-dialog.cc    |   19 +-
 pan/gui/progress-view.cc      |    2 -
 pan/gui/save-ui.cc            |    2 +-
 pan/gui/score-view-ui.cc      |   10 +-
 pan/gui/server-ui.cc          |   27 +-
 pan/gui/sexy-icon-entry.c     |  968 -----------------------------------------
 pan/gui/sexy-icon-entry.h     |  101 -----
 pan/gui/task-pane.cc          |   11 +-
 pan/gui/xface.c               |   12 +-
 pan/tasks/socket-impl-gio.cc  |    2 +-
 36 files changed, 1754 insertions(+), 1714 deletions(-)
---
diff --git a/pan/gui/Makefile.am b/pan/gui/Makefile.am
index b3605f2..3de23ae 100644
--- a/pan/gui/Makefile.am
+++ b/pan/gui/Makefile.am
@@ -6,7 +6,10 @@ libpangui_a_SOURCES = \
  actions.cc \
  body-pane.cc \
  dl-headers-ui.cc \
- e-charset-picker.c \
+ e-action-combo-box.c \
+ e-charset.c \
+ e-charset-combo-box.c \
+ e-charset-dialog.c \
  group-pane.cc \
  group-prefs.cc \
  group-prefs-dialog.cc \
@@ -27,7 +30,6 @@ libpangui_a_SOURCES = \
  score-add-ui.cc \
  score-view-ui.cc \
  server-ui.cc \
- sexy-icon-entry.c \
  task-pane.cc \
  xface.c \
  url.cc
@@ -38,7 +40,10 @@ noinst_HEADERS = \
  body-pane.h \
  defgroup.h \
  dl-headers-ui.h \
- e-charset-picker.h \
+ e-action-combo-box.h \
+ e-charset.h \
+ e-charset-combo-box.h \
+ e-charset-dialog.h \
  group-pane.h \
  group-prefs.h \
  group-prefs-dialog.h \
@@ -64,7 +69,6 @@ noinst_HEADERS = \
  score-add-ui.h \
  score-view-ui.h \
  server-ui.h \
- sexy-icon-entry.h \
  tango-colors.h \
  task-pane.h \
  url.h \
diff --git a/pan/gui/actions.cc b/pan/gui/actions.cc
index 1f69a74..7fb68b3 100644
--- a/pan/gui/actions.cc
+++ b/pan/gui/actions.cc
@@ -89,7 +89,7 @@ namespace
 
       //std::cerr << "registered icon " << my_builtin_icons[i].name << std::endl;
 
-      gdk_pixbuf_unref (pixbuf);
+      g_object_unref (pixbuf);
       gtk_icon_set_unref (icon_set);
     }
 
diff --git a/pan/gui/body-pane.cc b/pan/gui/body-pane.cc
index d0a9ebd..7501eb0 100644
--- a/pan/gui/body-pane.cc
+++ b/pan/gui/body-pane.cc
@@ -158,7 +158,7 @@ namespace
   void free_cursors (void)
   {
     for (int i=0; i<CURSOR_QTY; ++i)
-      gdk_cursor_destroy (cursors[i]);
+      gdk_cursor_unref (cursors[i]);
   }
 
   void ensure_cursors_created (GtkWidget * w)
@@ -1359,8 +1359,7 @@ BodyPane :: BodyPane (Data& data, ArticleCache& cache, Prefs& prefs):
   gtk_box_pack_start (GTK_BOX(vbox), w, false, false, 0);
 
   _terse = gtk_label_new ("Expander");
-  g_object_ref (_terse);
-  gtk_object_sink (GTK_OBJECT(_terse));
+  g_object_ref_sink_pan (G_OBJECT(_terse));
   gtk_misc_set_alignment (GTK_MISC(_terse), 0.0f, 0.5f);
   gtk_label_set_use_markup (GTK_LABEL(_terse), true);
   gtk_label_set_selectable (GTK_LABEL(_terse), true);
@@ -1370,8 +1369,7 @@ BodyPane :: BodyPane (Data& data, ArticleCache& cache, Prefs& prefs):
   gtk_widget_show (_terse);
 
   GtkWidget * hbox = _verbose = gtk_hbox_new (false, 0);
-  g_object_ref (_verbose);
-  gtk_object_sink (GTK_OBJECT(_verbose));
+  g_object_ref_sink_pan (G_OBJECT(_verbose));
   w = _headers = gtk_label_new ("Headers");
   gtk_label_set_selectable (GTK_LABEL(_headers), TRUE);
   gtk_misc_set_alignment (GTK_MISC(w), 0.0f, 0.5f);
diff --git a/pan/gui/dl-headers-ui.cc b/pan/gui/dl-headers-ui.cc
index 7446e12..69c3906 100644
--- a/pan/gui/dl-headers-ui.cc
+++ b/pan/gui/dl-headers-ui.cc
@@ -137,7 +137,7 @@ pan :: headers_dialog (Data& data, Prefs& prefs, Queue& queue,
     gtk_table_attach_defaults (GTK_TABLE(t), w, 0, 1, row, row+1);
     adj = GTK_ADJUSTMENT(gtk_adjustment_new (n_days, 1, INT_MAX, 1, 1, 0));
     state->n_days_spinbutton = x = gtk_spin_button_new (adj, 1, 0);
-    g_signal_connect (x, "focus_in_event", GTK_SIGNAL_FUNC(spin_tickled_cb), state->n_days_rb);
+    g_signal_connect (x, "focus_in_event", G_CALLBACK(spin_tickled_cb), state->n_days_rb);
     gtk_table_attach_defaults (GTK_TABLE(t), x, 1, 2, row, row+1);
     ++row;
     state->new_headers_rb = w = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON(w), _("Get _new headers"));
@@ -153,7 +153,7 @@ pan :: headers_dialog (Data& data, Prefs& prefs, Queue& queue,
     gtk_table_attach_defaults (GTK_TABLE(t), w, 0, 1, row, row+1);
     adj = GTK_ADJUSTMENT(gtk_adjustment_new (n_headers, 0, INT_MAX, 50, 50, 0));
     state->n_headers_spinbutton = x = gtk_spin_button_new (adj, 1, 0);
-    g_signal_connect (x, "focus_in_event", GTK_SIGNAL_FUNC(spin_tickled_cb), state->n_headers_rb);
+    g_signal_connect (x, "focus_in_event", G_CALLBACK(spin_tickled_cb), state->n_headers_rb);
     gtk_table_attach_defaults (GTK_TABLE(t), x, 1, 2, row, row+1);
 
     gtk_container_add (GTK_CONTAINER(GTK_DIALOG(state->dialog)->vbox), t);
diff --git a/pan/gui/e-action-combo-box.c b/pan/gui/e-action-combo-box.c
new file mode 100644
index 0000000..3d5f3b0
--- /dev/null
+++ b/pan/gui/e-action-combo-box.c
@@ -0,0 +1,583 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-action-combo-box.c
+ *
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 Lesser 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 "e-action-combo-box.h"
+
+#include <glib/gi18n.h>
+
+#define E_ACTION_COMBO_BOX_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_ACTION_COMBO_BOX, EActionComboBoxPrivate))
+
+enum {
+	COLUMN_ACTION,
+	COLUMN_SORT
+};
+
+enum {
+	PROP_0,
+	PROP_ACTION
+};
+
+struct _EActionComboBoxPrivate {
+	GtkRadioAction *action;
+	GtkActionGroup *action_group;
+	GHashTable *index;
+	guint changed_handler_id;		/* action::changed */
+	guint group_sensitive_handler_id;	/* action-group::sensitive */
+	guint group_visible_handler_id;		/* action-group::visible */
+	gboolean group_has_icons : 1;
+};
+
+static gpointer parent_class;
+
+static void
+action_combo_box_action_changed_cb (GtkRadioAction *action G_GNUC_UNUSED,
+                                    GtkRadioAction *current,
+                                    EActionComboBox *combo_box)
+{
+	GtkTreeRowReference *reference;
+	GtkTreeModel *model;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	gboolean valid;
+
+	reference = g_hash_table_lookup (
+		combo_box->priv->index, GINT_TO_POINTER (
+		gtk_radio_action_get_current_value (current)));
+	g_return_if_fail (reference != NULL);
+
+	model = gtk_tree_row_reference_get_model (reference);
+	path = gtk_tree_row_reference_get_path (reference);
+	valid = gtk_tree_model_get_iter (model, &iter, path);
+	gtk_tree_path_free (path);
+	g_return_if_fail (valid);
+
+	gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo_box), &iter);
+}
+
+static void
+action_combo_box_action_group_notify_cb (GtkActionGroup *action_group,
+                                         GParamSpec *pspec G_GNUC_UNUSED,
+                                         EActionComboBox *combo_box)
+{
+	g_object_set (
+		combo_box, "sensitive",
+		gtk_action_group_get_sensitive (action_group), "visible",
+		gtk_action_group_get_visible (action_group), NULL);
+}
+
+static void
+action_combo_box_render_pixbuf (GtkCellLayout *layout G_GNUC_UNUSED,
+                                GtkCellRenderer *renderer,
+                                GtkTreeModel *model,
+                                GtkTreeIter *iter,
+                                EActionComboBox *combo_box)
+{
+	GtkRadioAction *action;
+	gchar *icon_name;
+	gchar *stock_id;
+	gboolean sensitive;
+	gboolean visible;
+	gint width;
+
+	gtk_tree_model_get (model, iter, COLUMN_ACTION, &action, -1);
+
+	/* Do any of the actions have an icon? */
+	if (!combo_box->priv->group_has_icons)
+		return;
+
+	/* A NULL action means the row is a separator. */
+	if (action == NULL)
+		return;
+
+	g_object_get (
+		G_OBJECT (action),
+		"icon-name", &icon_name,
+		"sensitive", &sensitive,
+		"stock-id", &stock_id,
+		"visible", &visible,
+		NULL);
+
+	/* Keep the pixbuf renderer a fixed size for proper alignment. */
+	gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, NULL);
+
+	/* We can't set both "icon-name" and "stock-id" because setting
+	 * one unsets the other.  So pick the one that has a non-NULL
+	 * value.  If both are non-NULL, "stock-id" wins. */
+
+	if (stock_id != NULL)
+		g_object_set (
+			G_OBJECT (renderer),
+			"sensitive", sensitive,
+			"stock-id", stock_id,
+			"stock-size", GTK_ICON_SIZE_MENU,
+			"visible", visible,
+			"width", width,
+			NULL);
+	else
+		g_object_set (
+			G_OBJECT (renderer),
+			"icon-name", icon_name,
+			"sensitive", sensitive,
+			"stock-size", GTK_ICON_SIZE_MENU,
+			"visible", visible,
+			"width", width,
+			NULL);
+
+	g_free (icon_name);
+	g_free (stock_id);
+}
+
+static void
+action_combo_box_render_text (GtkCellLayout *layout G_GNUC_UNUSED,
+                              GtkCellRenderer *renderer,
+                              GtkTreeModel *model,
+                              GtkTreeIter *iter,
+                              EActionComboBox *combo_box)
+{
+	GtkRadioAction *action;
+	gchar **strv;
+	gchar *label;
+	gboolean sensitive;
+	gboolean visible;
+	gint xpad;
+
+	gtk_tree_model_get (model, iter, COLUMN_ACTION, &action, -1);
+
+	/* A NULL action means the row is a separator. */
+	if (action == NULL)
+		return;
+
+	g_object_get (
+		G_OBJECT (action),
+		"label", &label,
+		"sensitive", &sensitive,
+		"visible", &visible,
+		NULL);
+
+	/* Strip out underscores. */
+	strv = g_strsplit (label, "_", -1);
+	g_free (label);
+	label = g_strjoinv (NULL, strv);
+	g_strfreev (strv);
+
+	xpad = combo_box->priv->group_has_icons ? 3 : 0;
+
+	g_object_set (
+		G_OBJECT (renderer),
+		"sensitive", sensitive,
+		"text", label,
+		"visible", visible,
+		"xpad", xpad,
+		NULL);
+
+	g_free (label);
+}
+
+static gboolean
+action_combo_box_is_row_separator (GtkTreeModel *model,
+                                   GtkTreeIter *iter)
+{
+	GtkAction *action;
+	gboolean separator;
+
+	/* NULL actions are rendered as separators. */
+	gtk_tree_model_get (model, iter, COLUMN_ACTION, &action, -1);
+	separator = (action == NULL);
+	if (action != NULL)
+		g_object_unref (action);
+
+	return separator;
+}
+
+static void
+action_combo_box_update_model (EActionComboBox *combo_box)
+{
+	GtkListStore *list_store;
+	GSList *list;
+
+	g_hash_table_remove_all (combo_box->priv->index);
+
+	if (combo_box->priv->action == NULL) {
+		gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box), NULL);
+		return;
+	}
+
+	/* We store values in the sort column as floats so that we can
+	 * insert separators in between consecutive integer values and
+	 * still maintain the proper ordering. */
+	list_store = gtk_list_store_new (
+		2, GTK_TYPE_RADIO_ACTION, G_TYPE_FLOAT);
+
+	list = gtk_radio_action_get_group (combo_box->priv->action);
+	combo_box->priv->group_has_icons = FALSE;
+
+	while (list != NULL) {
+		GtkTreeRowReference *reference;
+		GtkRadioAction *action = list->data;
+		GtkTreePath *path;
+		GtkTreeIter iter;
+		gchar *icon_name;
+		gchar *stock_id;
+		gint value;
+
+		g_object_get (
+			action, "icon-name", &icon_name,
+			"stock-id", &stock_id, NULL);
+		combo_box->priv->group_has_icons |=
+			(icon_name != NULL || stock_id != NULL);
+		g_free (icon_name);
+		g_free (stock_id);
+
+		gtk_list_store_append (list_store, &iter);
+		g_object_get (G_OBJECT (action), "value", &value, NULL);
+		gtk_list_store_set (
+			list_store, &iter, COLUMN_ACTION,
+			list->data, COLUMN_SORT, (gfloat) value, -1);
+
+		path = gtk_tree_model_get_path (
+			GTK_TREE_MODEL (list_store), &iter);
+		reference = gtk_tree_row_reference_new (
+			GTK_TREE_MODEL (list_store), path);
+		g_hash_table_insert (
+			combo_box->priv->index,
+			GINT_TO_POINTER (value), reference);
+		gtk_tree_path_free (path);
+
+		list = g_slist_next (list);
+	}
+
+	gtk_tree_sortable_set_sort_column_id (
+		GTK_TREE_SORTABLE (list_store),
+		COLUMN_SORT, GTK_SORT_ASCENDING);
+	gtk_combo_box_set_model (
+		GTK_COMBO_BOX (combo_box), GTK_TREE_MODEL (list_store));
+
+	action_combo_box_action_changed_cb (
+		combo_box->priv->action,
+		combo_box->priv->action,
+		combo_box);
+}
+
+static void
+action_combo_box_set_property (GObject *object,
+                               guint property_id,
+                               const GValue *value,
+                               GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACTION:
+			e_action_combo_box_set_action (
+				E_ACTION_COMBO_BOX (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+action_combo_box_get_property (GObject *object,
+                               guint property_id,
+                               GValue *value,
+                               GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACTION:
+			g_value_set_object (
+				value, e_action_combo_box_get_action (
+				E_ACTION_COMBO_BOX (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+action_combo_box_dispose (GObject *object)
+{
+	EActionComboBoxPrivate *priv = E_ACTION_COMBO_BOX_GET_PRIVATE (object);
+
+	if (priv->action != NULL) {
+		g_object_unref (priv->action);
+		priv->action = NULL;
+	}
+
+	if (priv->action_group != NULL) {
+		g_object_unref (priv->action_group);
+		priv->action_group = NULL;
+	}
+
+	g_hash_table_remove_all (priv->index);
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+action_combo_box_finalize (GObject *object)
+{
+	EActionComboBoxPrivate *priv = E_ACTION_COMBO_BOX_GET_PRIVATE (object);
+
+	g_hash_table_destroy (priv->index);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+action_combo_box_changed (GtkComboBox *combo_box)
+{
+	GtkRadioAction *action;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	gint value;
+
+	/* This method is virtual, so no need to chain up. */
+
+	if (!gtk_combo_box_get_active_iter (combo_box, &iter))
+		return;
+
+	model = gtk_combo_box_get_model (combo_box);
+	gtk_tree_model_get (model, &iter, COLUMN_ACTION, &action, -1);
+	g_object_get (G_OBJECT (action), "value", &value, NULL);
+	gtk_radio_action_set_current_value (action, value);
+}
+
+static void
+action_combo_box_class_init (EActionComboBoxClass *class)
+{
+	GObjectClass *object_class;
+	GtkComboBoxClass *combo_box_class;
+
+	parent_class = g_type_class_peek_parent (class);
+	g_type_class_add_private (class, sizeof (EActionComboBoxPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = action_combo_box_set_property;
+	object_class->get_property = action_combo_box_get_property;
+	object_class->dispose = action_combo_box_dispose;
+	object_class->finalize = action_combo_box_finalize;
+
+	combo_box_class = GTK_COMBO_BOX_CLASS (class);
+	combo_box_class->changed = action_combo_box_changed;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_ACTION,
+		g_param_spec_object (
+			"action",
+			_("Action"),
+			_("A GtkRadioAction"),
+			GTK_TYPE_RADIO_ACTION,
+			G_PARAM_READWRITE));
+}
+
+static void
+action_combo_box_init (EActionComboBox *combo_box)
+{
+	GtkCellRenderer *renderer;
+
+	combo_box->priv = E_ACTION_COMBO_BOX_GET_PRIVATE (combo_box);
+
+	renderer = gtk_cell_renderer_pixbuf_new ();
+	gtk_cell_layout_pack_start (
+		GTK_CELL_LAYOUT (combo_box), renderer, FALSE);
+	gtk_cell_layout_set_cell_data_func (
+		GTK_CELL_LAYOUT (combo_box), renderer,
+		(GtkCellLayoutDataFunc) action_combo_box_render_pixbuf,
+		combo_box, NULL);
+
+	renderer = gtk_cell_renderer_text_new ();
+	gtk_cell_layout_pack_start (
+		GTK_CELL_LAYOUT (combo_box), renderer, TRUE);
+	gtk_cell_layout_set_cell_data_func (
+		GTK_CELL_LAYOUT (combo_box), renderer,
+		(GtkCellLayoutDataFunc) action_combo_box_render_text,
+		combo_box, NULL);
+
+	gtk_combo_box_set_row_separator_func (
+		GTK_COMBO_BOX (combo_box), (GtkTreeViewRowSeparatorFunc)
+		action_combo_box_is_row_separator, NULL, NULL);
+
+	combo_box->priv->index = g_hash_table_new_full (
+		g_direct_hash, g_direct_equal,
+		(GDestroyNotify) NULL,
+		(GDestroyNotify) gtk_tree_row_reference_free);
+}
+
+GType
+e_action_combo_box_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static const GTypeInfo type_info = {
+			sizeof (EActionComboBoxClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) action_combo_box_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL,  /* class_data */
+			sizeof (EActionComboBox),
+			0,     /* n_preallocs */
+			(GInstanceInitFunc) action_combo_box_init,
+			NULL   /* value_table */
+		};
+
+		type = g_type_register_static (
+			GTK_TYPE_COMBO_BOX, "EActionComboBox",
+			&type_info, 0);
+	}
+
+	return type;
+}
+
+GtkWidget *
+e_action_combo_box_new (void)
+{
+	return e_action_combo_box_new_with_action (NULL);
+}
+
+GtkWidget *
+e_action_combo_box_new_with_action (GtkRadioAction *action)
+{
+	return g_object_new (E_TYPE_ACTION_COMBO_BOX, "action", action, NULL);
+}
+
+GtkRadioAction *
+e_action_combo_box_get_action (EActionComboBox *combo_box)
+{
+	g_return_val_if_fail (E_ACTION_IS_COMBO_BOX (combo_box), NULL);
+
+	return combo_box->priv->action;
+}
+
+void
+e_action_combo_box_set_action (EActionComboBox *combo_box,
+                               GtkRadioAction *action)
+{
+	g_return_if_fail (E_ACTION_IS_COMBO_BOX (combo_box));
+
+	if (action != NULL)
+		g_return_if_fail (GTK_IS_RADIO_ACTION (action));
+
+	if (combo_box->priv->action != NULL) {
+		g_signal_handler_disconnect (
+			combo_box->priv->action,
+			combo_box->priv->changed_handler_id);
+		g_object_unref (combo_box->priv->action);
+	}
+
+	if (combo_box->priv->action_group != NULL) {
+		g_signal_handler_disconnect (
+			combo_box->priv->action_group,
+			combo_box->priv->group_sensitive_handler_id);
+		g_signal_handler_disconnect (
+			combo_box->priv->action_group,
+			combo_box->priv->group_visible_handler_id);
+		g_object_unref (combo_box->priv->action_group);
+		combo_box->priv->action_group = NULL;
+	}
+
+	if (action != NULL)
+		g_object_get (
+			g_object_ref (action), "action-group",
+			&combo_box->priv->action_group, NULL);
+	combo_box->priv->action = action;
+	action_combo_box_update_model (combo_box);
+
+	if (combo_box->priv->action != NULL)
+		combo_box->priv->changed_handler_id = g_signal_connect (
+			combo_box->priv->action, "changed",
+			G_CALLBACK (action_combo_box_action_changed_cb),
+			combo_box);
+
+	if (combo_box->priv->action_group != NULL) {
+		g_object_ref (combo_box->priv->action_group);
+		combo_box->priv->group_sensitive_handler_id =
+			g_signal_connect (
+				combo_box->priv->action_group,
+				"notify::sensitive", G_CALLBACK (
+				action_combo_box_action_group_notify_cb),
+				combo_box);
+		combo_box->priv->group_visible_handler_id =
+			g_signal_connect (
+				combo_box->priv->action_group,
+				"notify::visible", G_CALLBACK (
+				action_combo_box_action_group_notify_cb),
+				combo_box);
+	}
+}
+
+gint
+e_action_combo_box_get_current_value (EActionComboBox *combo_box)
+{
+	g_return_val_if_fail (E_ACTION_IS_COMBO_BOX (combo_box), 0);
+	g_return_val_if_fail (combo_box->priv->action != NULL, 0);
+
+	return gtk_radio_action_get_current_value (combo_box->priv->action);
+}
+
+void
+e_action_combo_box_set_current_value (EActionComboBox *combo_box,
+                                      gint current_value)
+{
+	g_return_if_fail (E_ACTION_IS_COMBO_BOX (combo_box));
+	g_return_if_fail (combo_box->priv->action != NULL);
+
+	gtk_radio_action_set_current_value (
+		combo_box->priv->action, current_value);
+}
+
+void
+e_action_combo_box_add_separator_before (EActionComboBox *combo_box,
+                                         gint action_value)
+{
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+
+	g_return_if_fail (E_ACTION_IS_COMBO_BOX (combo_box));
+
+	/* NULL actions are rendered as separators. */
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
+	gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+	gtk_list_store_set (
+		GTK_LIST_STORE (model), &iter, COLUMN_ACTION,
+		NULL, COLUMN_SORT, (gfloat) action_value - 0.5, -1);
+}
+
+void
+e_action_combo_box_add_separator_after (EActionComboBox *combo_box,
+                                        gint action_value)
+{
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+
+	g_return_if_fail (E_ACTION_IS_COMBO_BOX (combo_box));
+
+	/* NULL actions are rendered as separators. */
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
+	gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+	gtk_list_store_set (
+		GTK_LIST_STORE (model), &iter, COLUMN_ACTION,
+		NULL, COLUMN_SORT, (gfloat) action_value + 0.5, -1);
+}
diff --git a/pan/gui/e-action-combo-box.h b/pan/gui/e-action-combo-box.h
new file mode 100644
index 0000000..3003386
--- /dev/null
+++ b/pan/gui/e-action-combo-box.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-action-combo-box.h
+ *
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 Lesser 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 E_ACTION_COMBO_BOX_H
+#define E_ACTION_COMBO_BOX_H
+
+/* This is a GtkComboBox that is driven by a group of GtkRadioActions.
+ * Just plug in a GtkRadioAction and the widget will handle the rest.
+ * (Based on GtkhtmlComboBox.) */
+
+#include <gtk/gtk.h>
+
+/* Standard GObject macros */
+#define E_TYPE_ACTION_COMBO_BOX \
+	(e_action_combo_box_get_type ())
+#define E_ACTION_COMBO_BOX(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_ACTION_COMBO_BOX, EActionComboBox))
+#define E_ACTION_COMBO_BOX_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_ACTION_COMBO_BOX, EActionComboBoxClass))
+#define E_ACTION_IS_COMBO_BOX(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_ACTION_COMBO_BOX))
+#define E_ACTION_IS_COMBO_BOX_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_ACTION_COMBO_BOX))
+#define E_ACTION_COMBO_BOX_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_ACTION_COMBO_BOX, EActionComboBoxClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EActionComboBox EActionComboBox;
+typedef struct _EActionComboBoxClass EActionComboBoxClass;
+typedef struct _EActionComboBoxPrivate EActionComboBoxPrivate;
+
+struct _EActionComboBox {
+	GtkComboBox parent;
+	EActionComboBoxPrivate *priv;
+};
+
+struct _EActionComboBoxClass {
+	GtkComboBoxClass parent_class;
+};
+
+GType		e_action_combo_box_get_type	(void);
+GtkWidget *	e_action_combo_box_new		(void);
+GtkWidget *	e_action_combo_box_new_with_action
+						(GtkRadioAction *action);
+GtkRadioAction *e_action_combo_box_get_action	(EActionComboBox *combo_box);
+void		e_action_combo_box_set_action	(EActionComboBox *combo_box,
+						 GtkRadioAction *action);
+gint		e_action_combo_box_get_current_value
+						(EActionComboBox *combo_box);
+void		e_action_combo_box_set_current_value
+						(EActionComboBox *combo_box,
+						 gint current_value);
+void		e_action_combo_box_add_separator_before
+						(EActionComboBox *combo_box,
+						 gint action_value);
+void		e_action_combo_box_add_separator_after
+						(EActionComboBox *combo_box,
+						 gint action_value);
+
+G_END_DECLS
+
+#endif /* E_ACTION_COMBO_BOX_H */
diff --git a/pan/gui/e-charset-combo-box.c b/pan/gui/e-charset-combo-box.c
new file mode 100644
index 0000000..cbdb6e6
--- /dev/null
+++ b/pan/gui/e-charset-combo-box.c
@@ -0,0 +1,463 @@
+/*
+ * e-charset-combo-box.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-charset-combo-box.h"
+
+#include <glib/gi18n.h>
+
+#include "e-charset.h"
+
+#define E_CHARSET_COMBO_BOX_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_CHARSET_COMBO_BOX, ECharsetComboBoxPrivate))
+
+#define DEFAULT_CHARSET "UTF-8"
+#define OTHER_VALUE G_MAXINT
+
+struct _ECharsetComboBoxPrivate {
+	GtkActionGroup *action_group;
+	GtkRadioAction *other_action;
+	GHashTable *charset_index;
+
+	/* Used when the user clicks Cancel in the character set
+	 * dialog. Reverts to the previous combo box setting. */
+	gint previous_index;
+
+	/* When setting the character set programmatically, this
+	 * prevents the custom character set dialog from running. */
+	guint block_dialog : 1;
+};
+
+enum {
+	PROP_0,
+	PROP_CHARSET
+};
+
+static gpointer parent_class;
+
+static void
+charset_combo_box_entry_changed_cb (GtkEntry *entry,
+                                    GtkDialog *dialog)
+{
+	const gchar *text;
+	gboolean sensitive;
+
+	text = gtk_entry_get_text (entry);
+	sensitive = (text != NULL && *text != '\0');
+	gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_OK, sensitive);
+}
+
+static void
+charset_combo_box_run_dialog (ECharsetComboBox *combo_box)
+{
+	GtkDialog *dialog;
+	GtkEntry *entry;
+	GtkWidget *container;
+	GtkWidget *widget;
+	GObject *object;
+	gpointer parent;
+	const gchar *charset;
+
+	/* FIXME Using a dialog for this is lame.  Selecting "Other..."
+	 *       should unlock an entry directly in the Preferences tab.
+	 *       Unfortunately space in Preferences is at a premium right
+	 *       now, but we should revisit this when the space issue is
+	 *       finally resolved. */
+
+	parent = gtk_widget_get_toplevel (GTK_WIDGET (combo_box));
+	parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
+
+	object = G_OBJECT (combo_box->priv->other_action);
+	charset = g_object_get_data (object, "charset");
+
+	widget = gtk_dialog_new_with_buttons (
+		_("Character Encoding"), parent,
+		GTK_DIALOG_DESTROY_WITH_PARENT,
+		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+		GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
+
+	/* Load the broken border width defaults so we can override them. */
+	gtk_widget_ensure_style (widget);
+
+	dialog = GTK_DIALOG (widget);
+
+	gtk_dialog_set_has_separator (dialog, FALSE);
+	gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK);
+
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
+
+	widget = gtk_dialog_get_action_area (dialog);
+	gtk_container_set_border_width (GTK_CONTAINER (widget), 0);
+
+	widget = gtk_dialog_get_content_area (dialog);
+	gtk_box_set_spacing (GTK_BOX (widget), 12);
+	gtk_container_set_border_width (GTK_CONTAINER (widget), 0);
+
+	container = widget;
+
+	widget = gtk_label_new (_("Enter the character set to use"));
+	gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	widget = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
+	gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 0, 12, 0);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	widget = gtk_entry_new ();
+	entry = GTK_ENTRY (widget);
+	gtk_entry_set_activates_default (entry, TRUE);
+	gtk_container_add (GTK_CONTAINER (container), widget);
+	gtk_widget_show (widget);
+
+	g_signal_connect (
+		entry, "changed",
+		G_CALLBACK (charset_combo_box_entry_changed_cb), dialog);
+
+	/* Set the default text -after- connecting the signal handler.
+	 * This will initialize the "OK" button to the proper state. */
+	gtk_entry_set_text (entry, charset);
+
+	if (gtk_dialog_run (dialog) != GTK_RESPONSE_OK) {
+		gint active;
+
+		/* Revert to the previously selected character set. */
+		combo_box->priv->block_dialog = TRUE;
+		active = combo_box->priv->previous_index;
+		gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), active);
+		combo_box->priv->block_dialog = FALSE;
+
+		goto exit;
+	}
+
+	charset = gtk_entry_get_text (entry);
+	g_return_if_fail (charset != NULL && charset != '\0');
+
+	g_object_set_data_full (
+		object, "charset", g_strdup (charset),
+		(GDestroyNotify) g_free);
+
+exit:
+	gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void
+charset_combo_box_notify_charset_cb (ECharsetComboBox *combo_box)
+{
+	GtkToggleAction *action;
+
+	action = GTK_TOGGLE_ACTION (combo_box->priv->other_action);
+	if (!gtk_toggle_action_get_active (action))
+		return;
+
+	if (combo_box->priv->block_dialog)
+		return;
+
+	/* "Other" action was selected by user. */
+	charset_combo_box_run_dialog (combo_box);
+}
+
+static void
+charset_combo_box_set_property (GObject *object,
+                                guint property_id,
+                                const GValue *value,
+                                GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_CHARSET:
+			e_charset_combo_box_set_charset (
+				E_CHARSET_COMBO_BOX (object),
+				g_value_get_string (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+charset_combo_box_get_property (GObject *object,
+                                guint property_id,
+                                GValue *value,
+                                GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_CHARSET:
+			g_value_set_string (
+				value, e_charset_combo_box_get_charset (
+				E_CHARSET_COMBO_BOX (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+charset_combo_box_dispose (GObject *object)
+{
+	ECharsetComboBoxPrivate *priv;
+
+	priv = E_CHARSET_COMBO_BOX_GET_PRIVATE (object);
+
+	if (priv->action_group != NULL) {
+		g_object_unref (priv->action_group);
+		priv->action_group = NULL;
+	}
+
+	if (priv->other_action != NULL) {
+		g_object_unref (priv->other_action);
+		priv->other_action = NULL;
+	}
+
+	g_hash_table_remove_all (priv->charset_index);
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+charset_combo_box_finalize (GObject *object)
+{
+	ECharsetComboBoxPrivate *priv;
+
+	priv = E_CHARSET_COMBO_BOX_GET_PRIVATE (object);
+
+	g_hash_table_destroy (priv->charset_index);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+charset_combo_box_changed (GtkComboBox *combo_box)
+{
+	ECharsetComboBoxPrivate *priv;
+
+	priv = E_CHARSET_COMBO_BOX_GET_PRIVATE (combo_box);
+
+	/* Chain up to parent's changed() method. */
+	GTK_COMBO_BOX_CLASS (parent_class)->changed (combo_box);
+
+	/* Notify -before- updating previous index. */
+	g_object_notify (G_OBJECT (combo_box), "charset");
+	priv->previous_index = gtk_combo_box_get_active (combo_box);
+}
+
+static void
+charset_combo_box_class_init (ECharsetComboBoxClass *class)
+{
+	GObjectClass *object_class;
+	GtkComboBoxClass *combo_box_class;
+
+	parent_class = g_type_class_peek_parent (class);
+	g_type_class_add_private (class, sizeof (ECharsetComboBoxPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = charset_combo_box_set_property;
+	object_class->get_property = charset_combo_box_get_property;
+	object_class->dispose = charset_combo_box_dispose;
+	object_class->finalize = charset_combo_box_finalize;
+
+	combo_box_class = GTK_COMBO_BOX_CLASS (class);
+	combo_box_class->changed = charset_combo_box_changed;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_CHARSET,
+		g_param_spec_string (
+			"charset",
+			"Charset",
+			"The selected character set",
+			"UTF-8",
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT));
+}
+
+static void
+charset_combo_box_init (ECharsetComboBox *combo_box)
+{
+	GtkActionGroup *action_group;
+	GtkRadioAction *radio_action;
+	GHashTable *charset_index;
+	GSList *group, *iter;
+
+	action_group = gtk_action_group_new ("charset-combo-box-internal");
+
+	charset_index = g_hash_table_new_full (
+		g_str_hash, g_str_equal,
+		(GDestroyNotify) g_free,
+		(GDestroyNotify) g_object_unref);
+
+	combo_box->priv = E_CHARSET_COMBO_BOX_GET_PRIVATE (combo_box);
+	combo_box->priv->action_group = action_group;
+	combo_box->priv->charset_index = charset_index;
+
+	group = e_charset_add_radio_actions (
+		action_group, "charset-", NULL, NULL, NULL);
+
+	/* Populate the character set index. */
+	for (iter = group; iter != NULL; iter = iter->next) {
+		GObject *object = iter->data;
+		const gchar *charset;
+
+		charset = g_object_get_data (object, "charset");
+		g_return_if_fail (charset != NULL);
+
+		g_hash_table_insert (
+			charset_index, g_strdup (charset),
+			g_object_ref (object));
+	}
+
+	/* Note the "other" action is not included in the index. */
+
+	radio_action = gtk_radio_action_new (
+		"charset-other", _("Other..."), NULL, NULL, OTHER_VALUE);
+
+	g_object_set_data (G_OBJECT (radio_action), "charset", (gpointer) "");
+
+	gtk_radio_action_set_group (radio_action, group);
+	group = gtk_radio_action_get_group (radio_action);
+
+	e_action_combo_box_set_action (
+		E_ACTION_COMBO_BOX (combo_box), radio_action);
+
+	e_action_combo_box_add_separator_after (
+		E_ACTION_COMBO_BOX (combo_box), g_slist_length (group));
+
+	g_signal_connect (
+		combo_box, "notify::charset",
+		G_CALLBACK (charset_combo_box_notify_charset_cb), NULL);
+
+	combo_box->priv->other_action = radio_action;
+}
+
+GType
+e_charset_combo_box_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static const GTypeInfo type_info = {
+			sizeof (ECharsetComboBoxClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) charset_combo_box_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL,  /* class_data */
+			sizeof (ECharsetComboBox),
+			0,     /* n_preallocs */
+			(GInstanceInitFunc) charset_combo_box_init,
+			NULL   /* value_table */
+		};
+
+		type = g_type_register_static (
+			E_TYPE_ACTION_COMBO_BOX, "ECharsetComboBox",
+			&type_info, 0);
+	}
+
+	return type;
+}
+
+GtkWidget *
+e_charset_combo_box_new (void)
+{
+	return g_object_new (E_TYPE_CHARSET_COMBO_BOX, NULL);
+}
+
+/**
+ * e_radio_action_get_current_action:
+ * @radio_action: a #GtkRadioAction
+ *
+ * Returns the currently active member of the group to which @radio_action
+ * belongs.
+ *
+ * Returns: the currently active group member
+ **/
+static GtkRadioAction *
+e_radio_action_get_current_action (GtkRadioAction *radio_action)
+{
+	GSList *group;
+	gint current_value;
+
+	g_return_val_if_fail (GTK_IS_RADIO_ACTION (radio_action), NULL);
+
+	group = gtk_radio_action_get_group (radio_action);
+	current_value = gtk_radio_action_get_current_value (radio_action);
+
+	while (group != NULL) {
+		gint value;
+
+		radio_action = GTK_RADIO_ACTION (group->data);
+		g_object_get (radio_action, "value", &value, NULL);
+
+		if (value == current_value)
+			return radio_action;
+
+		group = g_slist_next (group);
+	}
+
+	return NULL;
+}
+
+
+const gchar *
+e_charset_combo_box_get_charset (ECharsetComboBox *combo_box)
+{
+	GtkRadioAction *radio_action;
+
+	g_return_val_if_fail (E_IS_CHARSET_COMBO_BOX (combo_box), NULL);
+
+	radio_action = combo_box->priv->other_action;
+	radio_action = e_radio_action_get_current_action (radio_action);
+
+	return g_object_get_data (G_OBJECT (radio_action), "charset");
+}
+
+void
+e_charset_combo_box_set_charset (ECharsetComboBox *combo_box,
+                                 const gchar *charset)
+{
+	GHashTable *charset_index;
+	GtkRadioAction *radio_action;
+
+	g_return_if_fail (E_IS_CHARSET_COMBO_BOX (combo_box));
+
+	if (charset == NULL || *charset == '\0')
+		charset = "UTF-8";
+
+	charset_index = combo_box->priv->charset_index;
+	radio_action = g_hash_table_lookup (charset_index, charset);
+
+	if (radio_action == NULL) {
+		radio_action = combo_box->priv->other_action;
+		g_object_set_data_full (
+			G_OBJECT (radio_action),
+			"charset", g_strdup (charset),
+			(GDestroyNotify) g_free);
+	}
+
+	combo_box->priv->block_dialog = TRUE;
+	gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (radio_action), TRUE);
+	combo_box->priv->block_dialog = FALSE;
+}
diff --git a/pan/gui/e-charset-combo-box.h b/pan/gui/e-charset-combo-box.h
new file mode 100644
index 0000000..328f3c7
--- /dev/null
+++ b/pan/gui/e-charset-combo-box.h
@@ -0,0 +1,69 @@
+/*
+ * e-charset-combo-box.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_CHARSET_COMBO_BOX_H
+#define E_CHARSET_COMBO_BOX_H
+
+#include "e-action-combo-box.h"
+
+/* Standard GObject macros */
+#define E_TYPE_CHARSET_COMBO_BOX \
+	(e_charset_combo_box_get_type ())
+#define E_CHARSET_COMBO_BOX(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_CHARSET_COMBO_BOX, ECharsetComboBox))
+#define E_CHARSET_COMBO_BOX_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_CHARSET_COMBO_BOX, ECharsetComboBoxClass))
+#define E_IS_CHARSET_COMBO_BOX(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_CHARSET_COMBO_BOX))
+#define E_IS_CHARSET_COMBO_BOX_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_CHARSET_COMBO_BOX))
+#define E_CHARSET_COMBO_BOX_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_CHARSET_COMBO_BOX, ECharsetComboBoxClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ECharsetComboBox ECharsetComboBox;
+typedef struct _ECharsetComboBoxClass ECharsetComboBoxClass;
+typedef struct _ECharsetComboBoxPrivate ECharsetComboBoxPrivate;
+
+struct _ECharsetComboBox {
+	EActionComboBox parent;
+	ECharsetComboBoxPrivate *priv;
+};
+
+struct _ECharsetComboBoxClass {
+	EActionComboBoxClass parent_class;
+};
+
+GType		e_charset_combo_box_get_type	(void);
+GtkWidget *	e_charset_combo_box_new		(void);
+const gchar *	e_charset_combo_box_get_charset	(ECharsetComboBox *combo_box);
+void		e_charset_combo_box_set_charset	(ECharsetComboBox *combo_box,
+						 const gchar *charset);
+
+G_END_DECLS
+
+#endif /* E_CHARSET_COMBO_BOX_H */
diff --git a/pan/gui/e-charset-dialog.c b/pan/gui/e-charset-dialog.c
new file mode 100644
index 0000000..3e09b94
--- /dev/null
+++ b/pan/gui/e-charset-dialog.c
@@ -0,0 +1,95 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 "e-charset-combo-box.h"
+#include "e-charset-dialog.h"
+
+/**
+ * e_charset_dialog:
+ * @title: title for the dialog box
+ * @prompt: prompt string for the dialog box
+ * @default_charset: as for e_charset_picker_new()
+ * @parent: a parent window for the dialog box, or %NULL
+ *
+ * This creates a new dialog box with the given @title and @prompt and
+ * a character set picker menu. It then runs the dialog and returns
+ * the selected character set, or %NULL if the user clicked "Cancel".
+ *
+ * Return value: the selected character set (which must be freed with
+ * g_free()), or %NULL.
+ **/
+char *
+e_charset_dialog (const char *title, const char *prompt,
+			 const char *default_charset, GtkWindow *parent)
+{
+	GtkDialog *dialog;
+	GtkWidget *label, *picker, *vbox, *hbox;
+	char *charset = NULL;
+
+	dialog = GTK_DIALOG (gtk_dialog_new_with_buttons (title,
+							  parent,
+							  GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+							  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+							  GTK_STOCK_OK, GTK_RESPONSE_OK,
+							  NULL));
+
+	gtk_dialog_set_has_separator (dialog, FALSE);
+	gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK);
+
+	vbox = gtk_vbox_new (FALSE, 6);
+	gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
+	gtk_box_pack_start (GTK_BOX (dialog->vbox), vbox, FALSE, FALSE, 0);
+	gtk_widget_show (vbox);
+
+	label = gtk_label_new (prompt);
+	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+	gtk_widget_show (label);
+
+	hbox = gtk_hbox_new (FALSE, 12);
+	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+	gtk_widget_show (hbox);
+
+	label = gtk_label_new ("");
+	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+	gtk_widget_show (label);
+
+
+	picker = e_charset_combo_box_new ();
+        e_charset_combo_box_set_charset (E_CHARSET_COMBO_BOX(picker), default_charset);
+	gtk_box_pack_start (GTK_BOX (hbox), picker, TRUE, TRUE, 0);
+	gtk_widget_show (picker);
+
+	gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), 0);
+	gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 12);
+
+	gtk_widget_show_all (GTK_WIDGET (dialog));
+
+	g_object_ref (dialog);
+
+	if (gtk_dialog_run (dialog) == GTK_RESPONSE_OK)
+		charset = g_strdup (e_charset_combo_box_get_charset (E_CHARSET_COMBO_BOX(picker)));
+
+	gtk_widget_destroy (GTK_WIDGET (dialog));
+	g_object_unref (dialog);
+
+	return charset;
+}
diff --git a/pan/gui/e-charset-dialog.h b/pan/gui/e-charset-dialog.h
new file mode 100644
index 0000000..f22369d
--- /dev/null
+++ b/pan/gui/e-charset-dialog.h
@@ -0,0 +1,11 @@
+#ifndef E_CHARSET_DIALOG_H
+#define E_CHARSET_DIALOG_H
+
+G_BEGIN_DECLS
+
+char* e_charset_dialog (const char *title, const char *prompt,
+                        const char *default_charset, GtkWindow *parent);
+
+G_END_DECLS
+
+#endif
diff --git a/pan/gui/e-charset.c b/pan/gui/e-charset.c
new file mode 100644
index 0000000..ab90e47
--- /dev/null
+++ b/pan/gui/e-charset.c
@@ -0,0 +1,257 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-charset.h"
+
+#include <string.h>
+#include <iconv.h>
+
+#include <glib/gi18n-lib.h>
+
+typedef enum {
+	E_CHARSET_UNKNOWN,
+	E_CHARSET_ARABIC,
+	E_CHARSET_BALTIC,
+	E_CHARSET_CENTRAL_EUROPEAN,
+	E_CHARSET_CHINESE,
+	E_CHARSET_CYRILLIC,
+	E_CHARSET_GREEK,
+	E_CHARSET_HEBREW,
+	E_CHARSET_JAPANESE,
+	E_CHARSET_KOREAN,
+	E_CHARSET_THAI,
+	E_CHARSET_TURKISH,
+	E_CHARSET_UNICODE,
+	E_CHARSET_WESTERN_EUROPEAN,
+	E_CHARSET_WESTERN_EUROPEAN_NEW
+} ECharsetClass;
+
+static const gchar *classnames[] = {
+	N_("Unknown"),
+	N_("Arabic"),
+	N_("Baltic"),
+	N_("Central European"),
+	N_("Chinese"),
+	N_("Cyrillic"),
+	N_("Greek"),
+	N_("Hebrew"),
+	N_("Japanese"),
+	N_("Korean"),
+	N_("Thai"),
+	N_("Turkish"),
+	N_("Unicode"),
+	N_("Western European"),
+	N_("Western European, New"),
+};
+
+typedef struct {
+	const gchar *name;
+	ECharsetClass class;
+	const gchar *subclass;
+} ECharset;
+
+/* This list is based on what other mailers/browsers support. There's
+ * not a lot of point in using, say, ISO-8859-3, if anything that can
+ * read that can read UTF8 too.
+ */
+/* To Translators: Character set "Logical Hebrew" */
+static ECharset charsets[] = {
+	{ "ISO-8859-6", E_CHARSET_ARABIC, NULL },
+	{ "ISO-8859-13", E_CHARSET_BALTIC, NULL },
+	{ "ISO-8859-4", E_CHARSET_BALTIC, NULL },
+	{ "ISO-8859-2", E_CHARSET_CENTRAL_EUROPEAN, NULL },
+	{ "Big5", E_CHARSET_CHINESE, N_("Traditional") },
+	{ "BIG5HKSCS", E_CHARSET_CHINESE, N_("Traditional") },
+	{ "EUC-TW", E_CHARSET_CHINESE, N_("Traditional") },
+	{ "GB18030", E_CHARSET_CHINESE, N_("Simplified") },
+	{ "GB2312", E_CHARSET_CHINESE, N_("Simplified") },
+	{ "HZ", E_CHARSET_CHINESE, N_("Simplified") },
+	{ "ISO-2022-CN", E_CHARSET_CHINESE, N_("Simplified") },
+	{ "KOI8-R", E_CHARSET_CYRILLIC, NULL },
+	{ "Windows-1251", E_CHARSET_CYRILLIC, NULL },
+	{ "KOI8-U", E_CHARSET_CYRILLIC, N_("Ukrainian") },
+	{ "ISO-8859-5", E_CHARSET_CYRILLIC, NULL },
+	{ "ISO-8859-7", E_CHARSET_GREEK, NULL },
+	{ "ISO-8859-8", E_CHARSET_HEBREW, N_("Visual") },
+	{ "ISO-2022-JP", E_CHARSET_JAPANESE, NULL },
+	{ "EUC-JP", E_CHARSET_JAPANESE, NULL },
+	{ "Shift_JIS", E_CHARSET_JAPANESE, NULL },
+	{ "EUC-KR", E_CHARSET_KOREAN, NULL },
+	{ "TIS-620", E_CHARSET_THAI, NULL },
+	{ "ISO-8859-9", E_CHARSET_TURKISH, NULL },
+	{ "UTF-8", E_CHARSET_UNICODE, NULL },
+	{ "UTF-7", E_CHARSET_UNICODE, NULL },
+	{ "ISO-8859-1", E_CHARSET_WESTERN_EUROPEAN, NULL },
+	{ "ISO-8859-15", E_CHARSET_WESTERN_EUROPEAN_NEW, NULL },
+};
+
+/**
+ * e_charset_add_radio_actions:
+ * @action_group: a #GtkActionGroup
+ * @action_prefix: a prefix for action names, or %NULL
+ * @default_charset: the default character set, or %NULL to use the
+ *                   locale character set
+ * @callback: a callback function for actions in the group, or %NULL
+ * @user_data: user data to be passed to @callback, or %NULL
+ *
+ * Adds a set of #GtkRadioActions for available character sets to
+ * @action_group.  The @default_charset (or locale character set if
+ * @default_charset is %NULL) will be added first, and selected by
+ * default (except that ISO-8859-1 will always be used instead of
+ * US-ASCII).  Any other character sets of the same language class as
+ * the default will be added next, followed by the remaining character
+ * sets.
+ *
+ * Returns: the radio action group
+ **/
+GSList *
+e_charset_add_radio_actions (GtkActionGroup *action_group,
+                             const gchar *action_prefix,
+                             const gchar *default_charset,
+                             GCallback callback,
+                             gpointer user_data)
+{
+	GtkRadioAction *action = NULL;
+	GSList *group = NULL;
+	const gchar *locale_charset;
+	gint def, ii;
+
+	g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
+
+	if (action_prefix == NULL)
+		action_prefix = "";
+
+	g_get_charset (&locale_charset);
+	if (!g_ascii_strcasecmp (locale_charset, "US-ASCII"))
+		locale_charset = "ISO-8859-1";
+
+	if (default_charset == NULL)
+		default_charset = locale_charset;
+	for (def = 0; def < (gint)G_N_ELEMENTS (charsets); def++)
+		if (!g_ascii_strcasecmp (charsets[def].name, default_charset))
+			break;
+
+	for (ii = 0; ii < (gint)G_N_ELEMENTS (charsets); ii++) {
+		const gchar *charset_name;
+		gchar *action_name;
+		gchar *escaped_name;
+		gchar *charset_label;
+		gchar **str_array;
+
+		charset_name = charsets[ii].name;
+		action_name = g_strconcat (action_prefix, charset_name, NULL);
+
+		/* Escape underlines in the character set name so
+		 * they're not treated as GtkLabel mnemonics. */
+		str_array = g_strsplit (charset_name, "_", -1);
+		escaped_name = g_strjoinv ("__", str_array);
+		g_strfreev (str_array);
+
+		if (charsets[ii].subclass != NULL)
+			charset_label = g_strdup_printf (
+				"%s, %s (%s)",
+				gettext (classnames[charsets[ii].class]),
+				gettext (charsets[ii].subclass),
+				escaped_name);
+		else if (charsets[ii].class != E_CHARSET_UNKNOWN)
+			charset_label = g_strdup_printf (
+				"%s (%s)",
+				gettext (classnames[charsets[ii].class]),
+				escaped_name);
+		else
+			charset_label = g_strdup (escaped_name);
+
+		/* XXX Add a tooltip! */
+		action = gtk_radio_action_new (
+			action_name, charset_label, NULL, NULL, ii);
+
+		/* Character set name is static so no need to free it. */
+		g_object_set_data (
+			G_OBJECT (action), "charset",
+			(gpointer) charset_name);
+
+		gtk_radio_action_set_group (action, group);
+		group = gtk_radio_action_get_group (action);
+
+		if (callback != NULL)
+			g_signal_connect (
+				action, "changed", callback, user_data);
+
+		gtk_action_group_add_action (
+			action_group, GTK_ACTION (action));
+
+		g_object_unref (action);
+
+		g_free (action_name);
+		g_free (escaped_name);
+		g_free (charset_label);
+	}
+
+	if (def == G_N_ELEMENTS (charsets)) {
+		const gchar *charset_name;
+		gchar *action_name;
+		gchar *charset_label;
+		gchar **str_array;
+
+		charset_name = default_charset;
+		action_name = g_strconcat (action_prefix, charset_name, NULL);
+
+		/* Escape underlines in the character set name so
+		 * they're not treated as GtkLabel mnemonics. */
+		str_array = g_strsplit (charset_name, "_", -1);
+		charset_label = g_strjoinv ("__", str_array);
+		g_strfreev (str_array);
+
+		/* XXX Add a tooltip! */
+		action = gtk_radio_action_new (
+			action_name, charset_label, NULL, NULL, def);
+
+		/* Character set name is static so no need to free it. */
+		g_object_set_data (
+			G_OBJECT (action), "charset",
+			(gpointer) charset_name);
+
+		gtk_radio_action_set_group (action, group);
+		group = gtk_radio_action_get_group (action);
+
+		if (callback != NULL)
+			g_signal_connect (
+				action, "changed", callback, user_data);
+
+		gtk_action_group_add_action (
+			action_group, GTK_ACTION (action));
+
+		g_object_unref (action);
+
+		g_free (action_name);
+		g_free (charset_label);
+	}
+
+	/* Any of the actions in the action group will do. */
+	if (action != NULL)
+		gtk_radio_action_set_current_value (action, def);
+
+	return group;
+}
diff --git a/pan/gui/e-charset.h b/pan/gui/e-charset.h
new file mode 100644
index 0000000..57b6976
--- /dev/null
+++ b/pan/gui/e-charset.h
@@ -0,0 +1,36 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_CHARSET_H
+#define E_CHARSET_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+GSList *	e_charset_add_radio_actions	(GtkActionGroup *action_group,
+						 const gchar *action_prefix,
+						 const gchar *default_charset,
+						 GCallback callback,
+						 gpointer user_data);
+
+G_END_DECLS
+
+#endif /* E_CHARSET_H */
diff --git a/pan/gui/group-pane.cc b/pan/gui/group-pane.cc
index 77a4237..82c0582 100644
--- a/pan/gui/group-pane.cc
+++ b/pan/gui/group-pane.cc
@@ -33,7 +33,6 @@ extern "C" {
 #include <pan/data/data.h>
 #include "group-pane.h"
 #include "pad.h"
-#include "sexy-icon-entry.h"
 
 using namespace pan;
 
@@ -597,7 +596,7 @@ namespace
     remove_activate_soon_tag ();
   }
 
-  void clear_button_clicked_cb (SexyIconEntry *e, SexyIconEntryPosition, int, gpointer pane_gpointer)
+  void clear_button_clicked_cb (GtkEntry * e, GtkEntryIconPosition, GdkEventButton *, gpointer pane_gpointer)
   {
     set_search_entry (GTK_WIDGET(e), "");
     refresh_search_entry (GTK_WIDGET(e));
@@ -796,18 +795,17 @@ namespace
 GtkWidget*
 GroupPane :: create_filter_entry ()
 {
-  GtkWidget * entry = sexy_icon_entry_new ();
-
-  GtkWidget * icon = gtk_image_new_from_stock(GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU);
-  sexy_icon_entry_set_icon (SEXY_ICON_ENTRY(entry), SEXY_ICON_ENTRY_SECONDARY, GTK_IMAGE(icon));
-  sexy_icon_entry_set_icon_highlight(SEXY_ICON_ENTRY(entry), SEXY_ICON_ENTRY_SECONDARY, true);
+  GtkWidget * entry = gtk_entry_new ();
+  gtk_entry_set_icon_from_stock( GTK_ENTRY( entry ),
+                                 GTK_ENTRY_ICON_SECONDARY,
+                                 GTK_STOCK_CLEAR );
   gtk_widget_set_size_request (entry, 133, -1);
 
   _action_manager.disable_accelerators_when_focused (entry);
   g_signal_connect (entry, "focus-in-event", G_CALLBACK(search_entry_focus_in_cb), NULL);
   g_signal_connect (entry, "focus-out-event", G_CALLBACK(search_entry_focus_out_cb), NULL);
   g_signal_connect (entry, "activate", G_CALLBACK(search_entry_activated), this);
-  g_signal_connect (entry, "icon_released", G_CALLBACK(clear_button_clicked_cb), this);
+  g_signal_connect (entry, "icon-release", G_CALLBACK(clear_button_clicked_cb), this);
   entry_changed_tag = g_signal_connect (entry, "changed", G_CALLBACK(search_entry_changed_by_user), this);
   refresh_search_entry (entry);
   return entry;
diff --git a/pan/gui/group-prefs-dialog.cc b/pan/gui/group-prefs-dialog.cc
index 578b6c6..731f1cd 100644
--- a/pan/gui/group-prefs-dialog.cc
+++ b/pan/gui/group-prefs-dialog.cc
@@ -25,7 +25,7 @@ extern "C" {
 #include <pan/general/debug.h>
 #include <pan/general/macros.h>
 #include <pan/data/data.h>
-#include "e-charset-picker.h"
+#include "e-charset-combo-box.h"
 #include "group-prefs-dialog.h"
 #include "hig.h"
 #include "pad.h"
@@ -58,9 +58,8 @@ void
 GroupPrefsDialog :: save_from_gui ()
 {
   // charset...
-  char * tmp = e_charset_picker_get_charset (_charset);
+  const char * tmp = e_charset_combo_box_get_charset (E_CHARSET_COMBO_BOX(_charset));
   _group_prefs.set_string (_group, "character-encoding", tmp);
-  g_free (tmp);
 
   // posting profile...
   std::string profile;
@@ -144,9 +143,8 @@ GroupPrefsDialog :: GroupPrefsDialog (Data         & data,
   g_snprintf (buf, sizeof(buf), _("Properties for %s"), group.c_str());
   HIG::workarea_add_section_title (t, &row, buf);
     HIG :: workarea_add_section_spacer (t, row, 3);
-    _charset = e_charset_picker_new (_group_prefs.get_string (group, "character-encoding", "UTF-8").c_str());
-    w = gtk_option_menu_new ();
-    gtk_option_menu_set_menu (GTK_OPTION_MENU (w), _charset);
+    _charset = w = e_charset_combo_box_new( );
+    e_charset_combo_box_set_charset( E_CHARSET_COMBO_BOX(_charset), _group_prefs.get_string (group, "character-encoding", "UTF-8").c_str());
     HIG :: workarea_add_row (t, &row, _("Character _encoding:"), w);
     w = _save_path = file_entry_new (_("Directory for Saving Attachments"));
     char * pch = g_build_filename (g_get_home_dir(), "News", NULL);
diff --git a/pan/gui/gui.cc b/pan/gui/gui.cc
index 8fa6fa1..6ec5114 100644
--- a/pan/gui/gui.cc
+++ b/pan/gui/gui.cc
@@ -38,8 +38,8 @@ extern "C" {
 #include <pan/icons/pan-pixbufs.h>
 #include "actions.h"
 #include "body-pane.h"
-#include "e-charset-picker.h"
 #include "dl-headers-ui.h"
+#include "e-charset-dialog.h"
 #include "group-pane.h"
 #include "group-prefs-dialog.h"
 #include "header-pane.h"
@@ -73,6 +73,25 @@ namespace pan
     gtk_object_sink (GTK_OBJECT(o));
 #endif
   }
+
+  void
+  pan_widget_set_tooltip_text( GtkWidget * w, const char * tip )
+  {
+#if GTK_CHECK_VERSION( 2,12,0 )
+    gtk_widget_set_tooltip_text( w, tip );
+#else
+    static GtkTooltips * tips = NULL;
+    if( tips == NULL )
+        tips = gtk_tooltips_new( );
+    gtk_tooltips_set_tip( tips, w, tip, NULL );
+#endif
+  }
+
+  void
+  pan_box_pack_start_defaults (GtkBox * box, GtkWidget * child)
+  {
+    gtk_box_pack_start( box, child, TRUE, TRUE, 0 );
+  }
 }
 
 using namespace pan;
@@ -179,12 +198,8 @@ GUI :: GUI (Data& data, Queue& queue, ArticleCache& cache, Prefs& prefs, GroupPr
   _connection_size_label (0),
   _queue_size_label (0),
   _queue_size_button (0),
-  _taskbar (0),
-  _ttips (gtk_tooltips_new ())
+  _taskbar (0)
 {
-  g_object_ref_sink_pan (G_OBJECT(_ttips));
-  g_object_weak_ref (G_OBJECT(_root), (GWeakNotify)g_object_unref, _ttips);
-
   char * filename = g_build_filename (file::get_pan_home().c_str(), "pan.ui", NULL);
   if (!gtk_ui_manager_add_ui_from_file (_ui_manager, filename, NULL))
     gtk_ui_manager_add_ui_from_string (_ui_manager, fallback_ui_file, -1, NULL);
@@ -256,7 +271,7 @@ GUI :: GUI (Data& data, Queue& queue, ArticleCache& cache, Prefs& prefs, GroupPr
   w = _queue_size_label = gtk_label_new (NULL);
   gtk_misc_set_padding (GTK_MISC(w), PAD, 0);
   w = _queue_size_button = gtk_button_new();
-  gtk_tooltips_set_tip (GTK_TOOLTIPS(_ttips), w, _("Open the Task Manager"), NULL);
+  pan_widget_set_tooltip_text (w, _("Open the Task Manager"));
   gtk_button_set_relief (GTK_BUTTON(w), GTK_RELIEF_NONE);
   g_signal_connect (GTK_OBJECT(w), "clicked", G_CALLBACK(show_task_window_cb), this);
   gtk_container_add (GTK_CONTAINER(w), _queue_size_label);
@@ -278,7 +293,7 @@ GUI :: GUI (Data& data, Queue& queue, ArticleCache& cache, Prefs& prefs, GroupPr
 
   // status 
   w = _event_log_button = gtk_button_new ();
-  gtk_tooltips_set_tip (GTK_TOOLTIPS(_ttips), w, _("Open the Event Log"), NULL);
+  pan_widget_set_tooltip_text (w, _("Open the Event Log"));
   gtk_button_set_relief (GTK_BUTTON(w), GTK_RELIEF_NONE);
   gtk_box_pack_start (GTK_BOX(status_bar), w, false, false, 0);
   gtk_container_add (GTK_CONTAINER(w), _info_image);
@@ -294,14 +309,11 @@ GUI :: GUI (Data& data, Queue& queue, ArticleCache& cache, Prefs& prefs, GroupPr
   _queue.add_listener (this);
   Log::get().add_listener (this);
 
-  gtk_widget_ref (_info_image);
-  gtk_widget_ref (_error_image);
-  gtk_widget_ref (_group_pane->root());
-  gtk_widget_ref (_header_pane->root());
-  gtk_widget_ref (_body_pane->root());
-
-  gtk_object_sink (GTK_OBJECT (_info_image));
-  gtk_object_sink (GTK_OBJECT (_error_image));
+  g_object_ref_sink_pan (G_OBJECT(_info_image));
+  g_object_ref_sink_pan (G_OBJECT(_error_image));
+  g_object_ref (_group_pane->root());
+  g_object_ref (_header_pane->root());
+  g_object_ref (_body_pane->root());
 
   do_work_online (is_action_active ("work-online"));
 
@@ -372,7 +384,7 @@ GUI :: ~GUI ()
     delete _views[i];
 
   foreach (std::set<GtkWidget*>, unref, it)
-    gtk_widget_unref (*it);
+    g_object_unref (*it);
   g_object_unref (G_OBJECT(_ui_manager));
 }
 
@@ -1248,7 +1260,11 @@ void GUI :: do_about_pan ()
   const gchar * authors [] = { "Charles Kerr <charles rebelbase com>", "Calin Culianu <calin ajvar org> - Threaded Decoding", 0 };
   GdkPixbuf * logo = gdk_pixbuf_new_from_inline(-1, icon_pan_about_logo, 0, 0);
   GtkAboutDialog * w (GTK_ABOUT_DIALOG (gtk_about_dialog_new ()));
+#if GTK_CHECK_VERSION(2,12,0)
+  gtk_about_dialog_set_program_name (w, _("Pan"));
+#else
   gtk_about_dialog_set_name (w, _("Pan"));
+#endif
   gtk_about_dialog_set_version (w, PACKAGE_VERSION);
   gtk_about_dialog_set_comments (w, VERSION_TITLE);
   gtk_about_dialog_set_copyright (w, _("Copyright © 2002-2007 Charles Kerr"));
@@ -1376,7 +1392,7 @@ void GUI :: do_tabbed_layout (bool tabbed)
   remove_from_parent (body_w);
 
   // remove workarea's current child
-  GList * children = gtk_container_children (GTK_CONTAINER(_workarea_bin));
+  GList * children = gtk_container_get_children (GTK_CONTAINER(_workarea_bin));
   if (children) {
     gtk_container_remove (GTK_CONTAINER(_workarea_bin), GTK_WIDGET(children->data));
     g_list_free (children);
@@ -1390,7 +1406,6 @@ void GUI :: do_tabbed_layout (bool tabbed)
     gtk_notebook_append_page (n, group_w, gtk_label_new_with_mnemonic (_("_1. Group Pane")));
     gtk_notebook_append_page (n, header_w, gtk_label_new_with_mnemonic (_("_2. Header Pane")));
     gtk_notebook_append_page (n, body_w, gtk_label_new_with_mnemonic (_("_3. Body Pane")));
-    gtk_notebook_set_tab_border (n, PAD_SMALL);
     g_signal_connect (n, "switch-page", G_CALLBACK(notebook_page_switched_cb), this);
   }
   else
@@ -1641,10 +1656,10 @@ void GUI :: do_prompt_for_charset ()
   if (_charset.empty())
       _charset = "UTF-8";
 
-  char * tmp = e_charset_picker_dialog (_("Character Encoding"),
-                                        _("Body Pane Encoding"),
-                                        _charset.c_str(),
-                                        get_window(root()));
+  char * tmp = e_charset_dialog (_("Character Encoding"),
+                                 _("Body Pane Encoding"),
+                                 _charset.c_str(),
+                                 get_window(root()));
   set_charset (tmp);
   free (tmp);
 }
@@ -1711,7 +1726,7 @@ GUI :: refresh_connection_label ()
   }
 
   gtk_label_set_text (GTK_LABEL(_connection_size_label), str);
-  gtk_tooltips_set_tip (GTK_TOOLTIPS(_ttips), _connection_size_eventbox, tip, NULL);
+  pan_widget_set_tooltip_text (_connection_size_eventbox, tip);
 }
 
 namespace
@@ -1744,8 +1759,8 @@ void
 GUI :: set_queue_size_label (unsigned int running,
                              unsigned int size)
 {
-  char str[128];
-  char tip[128];
+  char str[256];
+  char tip[256];
 
   // build the button label
   if (!size)
@@ -1766,7 +1781,7 @@ GUI :: set_queue_size_label (unsigned int running,
 
   // update the gui
   gtk_label_set_text (GTK_LABEL(_queue_size_label), str);
-  gtk_tooltips_set_tip (GTK_TOOLTIPS(_ttips), _queue_size_button, tip, NULL);
+  pan_widget_set_tooltip_text (_queue_size_button, tip);
 }
 
 void
diff --git a/pan/gui/gui.h b/pan/gui/gui.h
index ed4c2f2..b8ec1a6 100644
--- a/pan/gui/gui.h
+++ b/pan/gui/gui.h
@@ -209,7 +209,6 @@ namespace pan
       GtkWidget * _taskbar;
       std::vector<ProgressView*> _views;
       std::list<Task*> _active_tasks;
-      GtkTooltips * _ttips;
 
       std::string _charset;
 
diff --git a/pan/gui/header-pane.cc b/pan/gui/header-pane.cc
index d0e0e63..489cb0f 100644
--- a/pan/gui/header-pane.cc
+++ b/pan/gui/header-pane.cc
@@ -36,7 +36,6 @@ extern "C" {
 #include <pan/icons/pan-pixbufs.h>
 #include "header-pane.h"
 #include "render-bytes.h"
-#include "sexy-icon-entry.h"
 #include "tango-colors.h"
 
 using namespace pan;
@@ -1271,15 +1270,15 @@ namespace
     }
   }
 
-  void entry_icon_released (SexyIconEntry*, SexyIconEntryPosition icon_pos, int, gpointer menu)
+  void entry_icon_release (GtkEntry*, GtkEntryIconPosition icon_pos, GdkEventButton*, gpointer menu)
   {
-    if (icon_pos == SEXY_ICON_ENTRY_PRIMARY)
+    if (icon_pos == GTK_ENTRY_ICON_PRIMARY)
       gtk_menu_popup (GTK_MENU(menu), 0, 0, 0, 0, 0, gtk_get_current_event_time());
   }
 
-  void entry_icon_released_2 (SexyIconEntry *entry, SexyIconEntryPosition icon_pos, int, gpointer pane_gpointer)
+  void entry_icon_release_2 (GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEventButton*, gpointer pane_gpointer)
   {
-    if (icon_pos == SEXY_ICON_ENTRY_SECONDARY) {
+    if (icon_pos == GTK_ENTRY_ICON_SECONDARY) {
       set_search_entry (GTK_WIDGET(entry), "");
       refresh_search_entry (GTK_WIDGET(entry));
       search_text.clear ();
@@ -1489,7 +1488,7 @@ HeaderPane :: ~HeaderPane ()
 GtkWidget*
 HeaderPane :: create_filter_entry ()
 {
-  GtkWidget * entry = sexy_icon_entry_new ();
+  GtkWidget * entry = gtk_entry_new ();
   _action_manager.disable_accelerators_when_focused (entry);
   g_object_set_data (G_OBJECT(entry), "header-pane", this);
   g_signal_connect (entry, "focus-in-event", G_CALLBACK(search_entry_focus_in_cb), NULL);
@@ -1497,13 +1496,12 @@ HeaderPane :: create_filter_entry ()
   g_signal_connect (entry, "activate", G_CALLBACK(search_entry_activated), this);
   entry_changed_tag = g_signal_connect (entry, "changed", G_CALLBACK(search_entry_changed), this);
 
-  GtkWidget * image = gtk_image_new_from_stock(GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU);
-  sexy_icon_entry_set_icon (SEXY_ICON_ENTRY(entry), SEXY_ICON_ENTRY_SECONDARY, GTK_IMAGE(image));
-  sexy_icon_entry_set_icon_highlight(SEXY_ICON_ENTRY(entry), SEXY_ICON_ENTRY_SECONDARY, true);
-
-  image = gtk_image_new_from_stock ("ICON_SEARCH_PULLDOWN", GTK_ICON_SIZE_MENU);
-  sexy_icon_entry_set_icon (SEXY_ICON_ENTRY(entry), SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE(image));
-  sexy_icon_entry_set_icon_highlight (SEXY_ICON_ENTRY(entry), SEXY_ICON_ENTRY_PRIMARY, TRUE);
+      gtk_entry_set_icon_from_stock( GTK_ENTRY( entry ),
+                                   GTK_ENTRY_ICON_PRIMARY,
+                                   GTK_STOCK_FIND);
+   gtk_entry_set_icon_from_stock( GTK_ENTRY( entry ),
+                                  GTK_ENTRY_ICON_SECONDARY,
+                                  GTK_STOCK_CLEAR );
 
   GtkWidget * menu = gtk_menu_new ();
   mode = 0;
@@ -1516,8 +1514,8 @@ HeaderPane :: create_filter_entry ()
     gtk_menu_shell_append (GTK_MENU_SHELL(menu), w);
     gtk_widget_show (w);
   }
-  g_signal_connect (entry, "icon-released", G_CALLBACK(entry_icon_released), menu);
-  g_signal_connect (entry, "icon-released", G_CALLBACK(entry_icon_released_2), this);
+  g_signal_connect (entry, "icon-release", G_CALLBACK(entry_icon_release), menu);
+  g_signal_connect (entry, "icon-release", G_CALLBACK(entry_icon_release_2), this);
 
   refresh_search_entry (entry);
 
diff --git a/pan/gui/log-ui.cc b/pan/gui/log-ui.cc
index fb3586d..5c863f0 100644
--- a/pan/gui/log-ui.cc
+++ b/pan/gui/log-ui.cc
@@ -222,7 +222,7 @@ pan :: log_dialog_new (Prefs& prefs, GtkWindow* window)
 
   gtk_widget_show (view);
   gtk_widget_show (scroll);
-  gtk_box_pack_start_defaults (GTK_BOX(GTK_DIALOG(dialog)->vbox), scroll);
+  pan_box_pack_start_defaults (GTK_BOX(GTK_DIALOG(dialog)->vbox), scroll);
 
   gtk_window_set_role (GTK_WINDOW(dialog), "pan-events-dialog");
   prefs.set_window ("events-window", GTK_WINDOW(dialog), 150, 150, 600, 300);
diff --git a/pan/gui/pad.h b/pan/gui/pad.h
index bcedbab..6d8726d 100644
--- a/pan/gui/pad.h
+++ b/pan/gui/pad.h
@@ -4,6 +4,10 @@
 namespace pan
 {
   extern void g_object_ref_sink_pan (GObject*);
+
+  extern void pan_widget_set_tooltip_text (GtkWidget * w, const char * tip);
+
+  extern void pan_box_pack_start_defaults (GtkBox * box, GtkWidget * child);
 };
 
 #define PAD_SMALL 3
diff --git a/pan/gui/pan-tree.cc b/pan/gui/pan-tree.cc
index 91e6ee3..5915590 100644
--- a/pan/gui/pan-tree.cc
+++ b/pan/gui/pan-tree.cc
@@ -554,7 +554,7 @@ PanTreeStore :: sortable_set_sort_func (GtkTreeSortable        *sortable,
                                         gint                    col,
                                         GtkTreeIterCompareFunc  func,
                                         gpointer                data,
-                                        GtkDestroyNotify        destroy)
+                                        GDestroyNotify          destroy)
 {
   PanTreeStore * tree (PAN_TREE_STORE (sortable));
   g_return_if_fail (tree);
@@ -569,7 +569,7 @@ void
 PanTreeStore :: sortable_set_default_sort_func (GtkTreeSortable        * s,
                                                 GtkTreeIterCompareFunc   f,
                                                 gpointer                 p,
-                                                GtkDestroyNotify         d)
+                                                GDestroyNotify           d)
 {
   sortable_set_sort_func (s, GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, f, p, d);
 }
diff --git a/pan/gui/pan-tree.h b/pan/gui/pan-tree.h
index e3fac89..ed2c0c9 100644
--- a/pan/gui/pan-tree.h
+++ b/pan/gui/pan-tree.h
@@ -309,7 +309,7 @@ struct PanTreeStore
     {
       GtkTreeIterCompareFunc sort_func;
       gpointer user_data;
-      GtkDestroyNotify destroy_notify;
+      GDestroyNotify destroy_notify;
 
       SortInfo(): sort_func(0), user_data(0), destroy_notify(0) {}
       ~SortInfo() { clear(); }
@@ -323,7 +323,7 @@ struct PanTreeStore
 
       void assign (GtkTreeIterCompareFunc sort_func,
                    gpointer user_data,
-                   GtkDestroyNotify destroy_notify) {
+                   GDestroyNotify destroy_notify) {
         clear ();
         this->sort_func = sort_func;
         this->user_data = user_data;
@@ -438,13 +438,13 @@ struct PanTreeStore
                                                     gint,
                                                     GtkTreeIterCompareFunc,
                                                     gpointer,
-                                                    GtkDestroyNotify);
+                                                    GDestroyNotify);
     static gboolean sortable_has_sort_func         (GtkTreeSortable*,
                                                     gint);
     static void     sortable_set_default_sort_func (GtkTreeSortable*,
                                                     GtkTreeIterCompareFunc,
                                                     gpointer,
-                                                    GtkDestroyNotify);
+                                                    GDestroyNotify);
     static gboolean sortable_has_default_sort_func (GtkTreeSortable*);
  
   private:
diff --git a/pan/gui/post-ui.cc b/pan/gui/post-ui.cc
index 4e3cf40..8bfbdc4 100644
--- a/pan/gui/post-ui.cc
+++ b/pan/gui/post-ui.cc
@@ -39,7 +39,7 @@ extern "C" {
 #include <pan/usenet-utils/mime-utils.h>
 #include <pan/data/data.h>
 #include <pan/tasks/task-post.h>
-#include "e-charset-picker.h"
+#include "e-charset-dialog.h"
 #include "pad.h"
 #include "hig.h"
 #include "post-ui.h"
@@ -244,10 +244,10 @@ PostUI :: prompt_for_charset ()
   if (_charset.empty())
       _charset = DEFAULT_CHARSET;
 
-  char * tmp = e_charset_picker_dialog (_("Character Encoding"),
-                                        _("New Article's Encoding:"),
-                                        _charset.c_str(),
-                                        GTK_WINDOW(root()));
+  char * tmp = e_charset_dialog (_("Character Encoding"),
+                                 _("New Article's Encoding:"),
+                                 _charset.c_str(),
+                                 GTK_WINDOW(root()));
   set_charset (tmp);
   free (tmp);
 }
@@ -1731,7 +1731,7 @@ PostUI :: create_main_tab ()
   GtkWidget * v = gtk_vbox_new (false, PAD);
   gtk_container_set_border_width (GTK_CONTAINER(v), PAD);
   gtk_box_pack_start (GTK_BOX(v), t, false, false, 0);
-  gtk_box_pack_start_defaults (GTK_BOX(v), w);
+  pan_box_pack_start_defaults (GTK_BOX(v), w);
   return v;
 }
 
@@ -1770,7 +1770,7 @@ PostUI :: create_extras_tab ()
   w = _followupto_entry = gtk_entry_new ();
   gtk_label_set_mnemonic_widget (GTK_LABEL(l), w);
   /* i18n: "poster" is a key used by many newsreaders.  probably safest to keep this key in english. */
-  gtk_tooltips_set_tip (GTK_TOOLTIPS(_ttips), w, _("The newsgroups where replies to your message should go.  This is only needed if it differs from the \"Newsgroups\" header.\n\nTo direct all replies to your email address, use \"Followup-To: poster\""), 0);
+pan_widget_set_tooltip_text (w, _("The newsgroups where replies to your message should go.  This is only needed if it differs from the \"Newsgroups\" header.\n\nTo direct all replies to your email address, use \"Followup-To: poster\""));
   gtk_table_attach (GTK_TABLE(t), w, 1, 2, row, row+1, fe, fill, 0, 0);
 
   //  Reply-To
@@ -1784,7 +1784,7 @@ PostUI :: create_extras_tab ()
 
   w = _replyto_entry = gtk_entry_new ();
   gtk_label_set_mnemonic_widget (GTK_LABEL(l), w);
-  gtk_tooltips_set_tip (GTK_TOOLTIPS(_ttips), w, _("The email account where mail replies to your posted message should go.  This is only needed if it differs from the \"From\" header."), 0);
+pan_widget_set_tooltip_text (w, _("The email account where mail replies to your posted message should go.  This is only needed if it differs from the \"From\" header."));
   gtk_table_attach (GTK_TABLE(t), w, 1, 2, row, row+1, fe, fill, 0, 0);
 
   //  Extra Headers
@@ -1886,10 +1886,6 @@ PostUI :: PostUI (GtkWindow    * parent,
     gtk_window_set_position (GTK_WINDOW(_root), GTK_WIN_POS_CENTER_ON_PARENT);
   }
 
-  _ttips = gtk_tooltips_new ();
-  g_object_ref_sink_pan (G_OBJECT(_ttips));
-  g_object_weak_ref (G_OBJECT(_root), (GWeakNotify)g_object_unref, _ttips);
-
   // populate the window
   GtkWidget * vbox = gtk_vbox_new (false, PAD_SMALL);
   GtkWidget * menu_vbox = gtk_vbox_new (false, PAD_SMALL);
@@ -1902,7 +1898,7 @@ PostUI :: PostUI (GtkWindow    * parent,
   GtkWidget * notebook = gtk_notebook_new ();
   gtk_notebook_append_page (GTK_NOTEBOOK(notebook), create_main_tab(), gtk_label_new_with_mnemonic(_("_Message")));
   gtk_notebook_append_page (GTK_NOTEBOOK(notebook), create_extras_tab(), gtk_label_new_with_mnemonic(_("More _Headers")));
-  gtk_box_pack_start_defaults (GTK_BOX(vbox), notebook);
+  pan_box_pack_start_defaults (GTK_BOX(vbox), notebook);
 
   // remember this message, but don't put it in the text view yet.
   // we have to wait for it to be realized first so that wrapping
diff --git a/pan/gui/post-ui.h b/pan/gui/post-ui.h
index 584445e..766e438 100644
--- a/pan/gui/post-ui.h
+++ b/pan/gui/post-ui.h
@@ -111,7 +111,6 @@ namespace pan
       str2str_t _profile_headers;
       std::string _unchanged_body;
       int _wrap_pixels;
-      GtkTooltips * _ttips;
 
     private:
       void add_actions (GtkWidget* box);
diff --git a/pan/gui/prefs-ui.cc b/pan/gui/prefs-ui.cc
index c5b42e7..62fac28 100644
--- a/pan/gui/prefs-ui.cc
+++ b/pan/gui/prefs-ui.cc
@@ -546,42 +546,42 @@ PrefsDialog :: PrefsDialog (Prefs& prefs, GtkWindow* parent):
   HIG :: workarea_add_section_title (t, &row, _("Header Pane"));
     HIG :: workarea_add_section_spacer(t, row, 5);
     h = gtk_hbox_new (false, PAD);
-    gtk_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Text:")));
-    gtk_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-watched-fg", "black", prefs));
-    gtk_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Background:")));
-    gtk_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-watched-bg", TANGO_CHAMELEON_LIGHT, prefs));
+    pan_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Text:")));
+    pan_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-watched-fg", "black", prefs));
+    pan_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Background:")));
+    pan_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-watched-bg", TANGO_CHAMELEON_LIGHT, prefs));
     HIG :: workarea_add_row (t, &row, _("Scores of 9999 or more:"), h);
     h = gtk_hbox_new (false, PAD);
-    gtk_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Text:")));
-    gtk_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-high-fg", "black", prefs));
-    gtk_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Background:")));
-    gtk_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-high-bg", TANGO_BUTTER_LIGHT, prefs));
+    pan_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Text:")));
+    pan_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-high-fg", "black", prefs));
+    pan_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Background:")));
+    pan_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-high-bg", TANGO_BUTTER_LIGHT, prefs));
     HIG :: workarea_add_row (t, &row, _("Scores from 5000 to 9998:"), h);
     h = gtk_hbox_new (false, PAD);
-    gtk_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Text:")));
-    gtk_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-medium-fg", "black", prefs));
-    gtk_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Background:")));
-    gtk_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-medium-bg", TANGO_SKY_BLUE_LIGHT, prefs));
+    pan_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Text:")));
+    pan_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-medium-fg", "black", prefs));
+    pan_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Background:")));
+    pan_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-medium-bg", TANGO_SKY_BLUE_LIGHT, prefs));
     HIG :: workarea_add_row (t, &row, _("Scores from 1 to 4999:"), h);
     h = gtk_hbox_new (false, PAD);
-    gtk_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Text:")));
-    gtk_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-low-fg", TANGO_ALUMINUM_2, prefs));
-    gtk_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Background:")));
-    gtk_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-low-bg", "black", prefs));
+    pan_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Text:")));
+    pan_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-low-fg", TANGO_ALUMINUM_2, prefs));
+    pan_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Background:")));
+    pan_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-low-bg", "black", prefs));
     HIG :: workarea_add_row (t, &row, _("Scores from -9998 to -1:"), h);
     h = gtk_hbox_new (false, PAD);
-    gtk_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Text:")));
-    gtk_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-ignored-fg", TANGO_ALUMINUM_4, prefs));
-    gtk_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Background:")));
-    gtk_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-ignored-bg", "black", prefs));
+    pan_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Text:")));
+    pan_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-ignored-fg", TANGO_ALUMINUM_4, prefs));
+    pan_box_pack_start_defaults (GTK_BOX(h), gtk_label_new (_("Background:")));
+    pan_box_pack_start_defaults (GTK_BOX(h), new_color_button ("score-color-ignored-bg", "black", prefs));
     HIG :: workarea_add_row (t, &row, _("Scores of -9999 or less:"), h);
   HIG :: workarea_add_section_divider (t, &row);
   HIG :: workarea_add_section_title (t, &row, _("Body Pane"));
     HIG :: workarea_add_section_spacer (t, row, 3);
     h = gtk_hbox_new (false, PAD_SMALL);
-    gtk_box_pack_start_defaults (GTK_BOX(h), new_color_button ("body-pane-color-quote-1", TANGO_CHAMELEON_DARK, prefs));
-    gtk_box_pack_start_defaults (GTK_BOX(h), new_color_button ("body-pane-color-quote-2", TANGO_ORANGE_DARK, prefs));
-    gtk_box_pack_start_defaults (GTK_BOX(h), new_color_button ("body-pane-color-quote-3", TANGO_PLUM_DARK, prefs));
+    pan_box_pack_start_defaults (GTK_BOX(h), new_color_button ("body-pane-color-quote-1", TANGO_CHAMELEON_DARK, prefs));
+    pan_box_pack_start_defaults (GTK_BOX(h), new_color_button ("body-pane-color-quote-2", TANGO_ORANGE_DARK, prefs));
+    pan_box_pack_start_defaults (GTK_BOX(h), new_color_button ("body-pane-color-quote-3", TANGO_PLUM_DARK, prefs));
     HIG :: workarea_add_row (t, &row, _("Quoted Text:"), h);
     HIG :: workarea_add_row (t, &row, _("URL:"), new_color_button ("body-pane-color-url", TANGO_SKY_BLUE_DARK, prefs));
     HIG :: workarea_add_row (t, &row, _("Signature:"), new_color_button ("body-pane-color-signature", TANGO_SKY_BLUE_LIGHT, prefs));
diff --git a/pan/gui/profiles-dialog.cc b/pan/gui/profiles-dialog.cc
index c614108..8f613b3 100644
--- a/pan/gui/profiles-dialog.cc
+++ b/pan/gui/profiles-dialog.cc
@@ -105,10 +105,6 @@ ProfileDialog :: ProfileDialog (const Data         & data,
   gtk_dialog_set_default_response (GTK_DIALOG(_root), GTK_RESPONSE_OK); 
   gtk_window_set_role (GTK_WINDOW(_root), "pan-edit-profile-dialog");
 
-  GtkTooltips * ttips = gtk_tooltips_new ();
-  g_object_ref_sink_pan (G_OBJECT(ttips));
-  g_object_weak_ref (G_OBJECT(_root), (GWeakNotify)g_object_unref, ttips);
-
   int row (0);
   GtkWidget *t = HIG :: workarea_create ();
   HIG :: workarea_add_section_title (t, &row, _("Profile Information"));
@@ -167,12 +163,12 @@ ProfileDialog :: ProfileDialog (const Data         & data,
 
     w = _msgid_fqdn_entry = gtk_entry_new ();
     set_entry (w, profile.fqdn);
-    gtk_tooltips_set_tip (GTK_TOOLTIPS(ttips), w, _("When posting to Usenet, your article's Message-ID contains a domain name.  You can set a custom domain name here, or leave it blank to let Pan use the domain name from your email address."), "");
+    pan_widget_set_tooltip_text (w, _("When posting to Usenet, your article's Message-ID contains a domain name.  You can set a custom domain name here, or leave it blank to let Pan use the domain name from your email address."));
     HIG :: workarea_add_row (t, &row, _("Message-ID _Domain Name:"), w, NULL);
 
     w = _attribution_entry = gtk_entry_new ();
     set_entry (w, profile.attribution);
-    gtk_tooltips_set_tip (GTK_TOOLTIPS(ttips), w, _("%i for Message-ID\n%a for Author and Address\n%n for Author name\n%d for Date"), "");
+    pan_widget_set_tooltip_text (w, _("%i for Message-ID\n%a for Author and Address\n%n for Author name\n%d for Date"));
     HIG :: workarea_add_row (t, &row, _("_Attribution:"), w, NULL);
 
 
@@ -196,7 +192,7 @@ ProfileDialog :: ProfileDialog (const Data         & data,
       s += it->first + ": " + it->second + "\n";
     gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW(w)), s.c_str(), s.size());
     GtkWidget * eventbox = gtk_event_box_new ();
-    gtk_tooltips_set_tip (GTK_TOOLTIPS(ttips), eventbox, _("Extra headers to be included in your posts, such as\nReply-To: \"Your Name\" <yourname somewhere com>\nOrganization: Your Organization"), "");
+    pan_widget_set_tooltip_text (eventbox, _("Extra headers to be included in your posts, such as\nReply-To: \"Your Name\" <yourname somewhere com>\nOrganization: Your Organization"));
     GtkWidget * scrolled_window = gtk_scrolled_window_new (NULL, NULL);
     gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(scrolled_window),
                                          GTK_SHADOW_IN);
@@ -474,16 +470,13 @@ ProfilesDialog :: ProfilesDialog (const Data& data, Profiles &profiles, GtkWindo
   gtk_widget_set_size_request (w, 300, 300);
 
   // button box
-  GtkTooltips * tips = gtk_tooltips_new ();
-  g_object_ref_sink_pan (G_OBJECT(tips));
-  g_object_weak_ref (G_OBJECT(_root), (GWeakNotify)g_object_unref, tips);
   GtkWidget * bbox = gtk_vbox_new (FALSE, PAD_SMALL);
   gtk_box_pack_start (GTK_BOX (hbox), bbox, false, false, 0);
 
   // add button
   w = gtk_button_new_from_stock (GTK_STOCK_ADD);
   gtk_box_pack_start (GTK_BOX (bbox), w, false, false, 0);
-  gtk_signal_connect (GTK_OBJECT(w), "clicked", GTK_SIGNAL_FUNC(on_add_button), this);
+  g_signal_connect (GTK_OBJECT(w), "clicked", G_CALLBACK(on_add_button), this);
 
   // edit button
 #if GTK_CHECK_VERSION(2,6,0)
@@ -493,12 +486,12 @@ ProfilesDialog :: ProfilesDialog (const Data& data, Profiles &profiles, GtkWindo
 #endif
   _edit_button = w;
   gtk_box_pack_start (GTK_BOX (bbox), w, false, false, 0);
-  gtk_signal_connect (GTK_OBJECT(w), "clicked", GTK_SIGNAL_FUNC(on_edit_button), this);
+  g_signal_connect (GTK_OBJECT(w), "clicked", G_CALLBACK(on_edit_button), this);
 
   // remove button
   _remove_button = w = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
   gtk_box_pack_start (GTK_BOX (bbox), w, false, false, 0);
-  gtk_signal_connect (GTK_OBJECT(w), "clicked", GTK_SIGNAL_FUNC(on_delete_button), this);
+  g_signal_connect (GTK_OBJECT(w), "clicked", G_CALLBACK(on_delete_button), this);
 
   // set sensitive buttons
   refresh_buttons ();
diff --git a/pan/gui/progress-view.cc b/pan/gui/progress-view.cc
index 1799301..6d439eb 100644
--- a/pan/gui/progress-view.cc
+++ b/pan/gui/progress-view.cc
@@ -33,8 +33,6 @@ ProgressView :: ProgressView ():
   _progressbar (gtk_progress_bar_new ()),
   _progress (0)
 {
-  gtk_progress_set_format_string (GTK_PROGRESS(_progressbar), "");
-  gtk_progress_set_show_text (GTK_PROGRESS(_progressbar), TRUE);
 #if GTK_CHECK_VERSION(2,6,0)
   gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR(_progressbar), PANGO_ELLIPSIZE_MIDDLE);
 #endif
diff --git a/pan/gui/save-ui.cc b/pan/gui/save-ui.cc
index cac9954..e13eda5 100644
--- a/pan/gui/save-ui.cc
+++ b/pan/gui/save-ui.cc
@@ -272,7 +272,7 @@ SaveDialog :: SaveDialog (Prefs                       & prefs,
     path = g_get_home_dir ();
   file_entry_set (w, path.c_str());
   g_signal_connect (file_entry_gtk_entry(w), "changed", G_CALLBACK(entry_changed_cb), _save_custom_path_radio);
-  gtk_widget_set_usize (GTK_WIDGET(w), 400, 0);
+  gtk_widget_set_size_request (GTK_WIDGET(w), 400, 0);
   w = gtk_button_new_from_stock (GTK_STOCK_HELP);
   gtk_box_pack_start (GTK_BOX(h), w, false, false, 0);
   g_signal_connect_swapped (w, "clicked", G_CALLBACK (show_group_substitution_help_dialog), dialog);
diff --git a/pan/gui/score-view-ui.cc b/pan/gui/score-view-ui.cc
index a4d33f5..0b48e08 100644
--- a/pan/gui/score-view-ui.cc
+++ b/pan/gui/score-view-ui.cc
@@ -187,14 +187,10 @@ ScoreView :: ScoreView (Data& data, GtkWindow* parent,
 	                                               GTK_DIALOG_DESTROY_WITH_PARENT,
 	                                               GTK_STOCK_CLOSE, GTK_RESPONSE_OK,
 	                                               NULL);
-  GtkTooltips * tips = gtk_tooltips_new ();
-  g_object_ref_sink_pan (G_OBJECT(tips));
-  g_object_weak_ref (G_OBJECT(w), (GWeakNotify)g_object_unref, tips);
-
   GtkWidget * button = create_rescore_button ();
   gtk_widget_show (button); 
   gtk_dialog_add_action_widget (GTK_DIALOG(w), button, GTK_RESPONSE_APPLY);
-  gtk_window_set_policy (GTK_WINDOW(w), true, true, true);
+  gtk_window_set_resizable (GTK_WINDOW(w), true);
   g_signal_connect (GTK_OBJECT(w), "response", G_CALLBACK(response_cb), &data);
   g_object_set_data_full (G_OBJECT(w), "score_view", this, delete_score_view);
 
@@ -245,14 +241,14 @@ ScoreView :: ScoreView (Data& data, GtkWindow* parent,
   // add button
   w = gtk_button_new_from_stock (GTK_STOCK_ADD);
   gtk_box_pack_start (GTK_BOX (bbox), w, FALSE, FALSE, 0);
-  gtk_tooltips_set_tip (tips, w, _("Add a New Scoring Rule"), NULL);
+  pan_widget_set_tooltip_text (w, _("Add a New Scoring Rule"));
   gtk_widget_show (w);
   g_signal_connect (w, "clicked", G_CALLBACK(this->add_clicked_cb), this);
 
   // remove button
   w = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
   gtk_box_pack_start (GTK_BOX (bbox), w, FALSE, FALSE, 0);
-  gtk_tooltips_set_tip (tips, w, _("Remove the Selected Scoring Rule"), NULL);
+  pan_widget_set_tooltip_text (w, _("Remove the Selected Scoring Rule"));
   gtk_widget_show (w);
   g_signal_connect (w, "clicked", G_CALLBACK(this->remove_clicked_cb), this);
 
diff --git a/pan/gui/server-ui.cc b/pan/gui/server-ui.cc
index 8ff1097..6a981c8 100644
--- a/pan/gui/server-ui.cc
+++ b/pan/gui/server-ui.cc
@@ -216,11 +216,6 @@ pan :: server_edit_dialog_new (Data& data, Queue& queue, GtkWindow * window, con
   ***  workarea
   **/
 
-  GtkTooltips * ttips = gtk_tooltips_new ();
-  g_object_ref_sink_pan (G_OBJECT(ttips));
-  g_object_weak_ref (G_OBJECT(dialog), (GWeakNotify)g_object_unref, ttips);
-
-
   int row (0);
   GtkWidget * t (HIG::workarea_create ());
   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(d->dialog)->vbox), t, TRUE, TRUE, 0);
@@ -228,12 +223,12 @@ pan :: server_edit_dialog_new (Data& data, Queue& queue, GtkWindow * window, con
     HIG::workarea_add_section_spacer (t, row, 2);
 
     GtkWidget * w = d->address_entry = gtk_entry_new ();
-    gtk_tooltips_set_tip (GTK_TOOLTIPS(ttips), w, _("The news server's actual address, e.g. \"news.mynewsserver.com\""), NULL);
+    pan_widget_set_tooltip_text( w, _("The news server's actual address, e.g. \"news.mynewsserver.com\""));
     HIG::workarea_add_row (t, &row, _("_Address:"), w, NULL);
 
     GtkAdjustment * a = GTK_ADJUSTMENT (gtk_adjustment_new (1.0, 1.0, ULONG_MAX, 1.0, 1.0, 0.0));
     w = d->port_spin = gtk_spin_button_new (GTK_ADJUSTMENT(a), 1.0, 0u);
-    gtk_tooltips_set_tip (GTK_TOOLTIPS(ttips), w, _("The news server's port number.  Typically 119."), NULL);
+    pan_widget_set_tooltip_text( w, _("The news server's port number.  Typically 119."));
     HIG::workarea_add_row (t, &row, _("Por_t:"), w, NULL);
 
   HIG::workarea_add_section_divider (t, &row);
@@ -242,12 +237,12 @@ pan :: server_edit_dialog_new (Data& data, Queue& queue, GtkWindow * window, con
 
     w = d->auth_username_entry = gtk_entry_new ();
     HIG::workarea_add_row (t, &row, _("_Username:"), w, NULL);
-    gtk_tooltips_set_tip (GTK_TOOLTIPS(ttips), w, _("The username to give the server when asked.  If your server doesn't require authentication, you can leave this blank."), NULL);
+    pan_widget_set_tooltip_text( w, _("The username to give the server when asked.  If your server doesn't require authentication, you can leave this blank."));
 
     w = d->auth_password_entry = gtk_entry_new ();
     gtk_entry_set_visibility (GTK_ENTRY(w), FALSE);
     HIG::workarea_add_row (t, &row, _("_Password:"), w, NULL);
-    gtk_tooltips_set_tip (GTK_TOOLTIPS(ttips), w, _("The password to give the server when asked.  If your server doesn't require authentication, you can leave this blank."), NULL);
+    pan_widget_set_tooltip_text( w, _("The password to give the server when asked.  If your server doesn't require authentication, you can leave this blank."));
 
   HIG::workarea_add_section_divider (t, &row);
   HIG::workarea_add_section_title (t, &row, _("Settings"));
@@ -300,7 +295,7 @@ pan :: server_edit_dialog_new (Data& data, Queue& queue, GtkWindow * window, con
     GtkWidget * e = gtk_event_box_new ();
     gtk_container_add (GTK_CONTAINER(e), l);
     gtk_misc_set_alignment (GTK_MISC(l), 0.0f, 0.5f);
-    gtk_tooltips_set_tip (GTK_TOOLTIPS(ttips), e, _("Fallback servers are used for articles that can't be found on the primaries.  One common approach is to use free servers as primaries and subscription servers as fallbacks."), NULL);
+    pan_widget_set_tooltip_text( e, _("Fallback servers are used for articles that can't be found on the primaries.  One common approach is to use free servers as primaries and subscription servers as fallbacks."));
     HIG::workarea_add_row (t, &row, e, w);
 
   d->server = server;
@@ -501,14 +496,10 @@ pan :: server_list_dialog_new (Data& data, Queue& queue, GtkWindow* parent)
                                                            NULL);
   g_free (title);
   gtk_window_set_role (GTK_WINDOW(w), "pan-servers-dialog");
-  gtk_window_set_policy (GTK_WINDOW(w), TRUE, TRUE, TRUE);
+  gtk_window_set_resizable (GTK_WINDOW(w), TRUE);
   g_signal_connect (GTK_OBJECT(w), "response", G_CALLBACK(server_list_dialog_response_cb), d);
   g_object_set_data_full (G_OBJECT(w), "dialog", d, delete_server_list_dialog);
 
-  GtkTooltips * tips = gtk_tooltips_new ();
-  g_object_ref_sink_pan (G_OBJECT(tips));
-  g_object_weak_ref (G_OBJECT(w), (GWeakNotify)g_object_unref, tips);
-
   // workarea
   GtkWidget * hbox = gtk_hbox_new (FALSE, PAD);
   gtk_container_set_border_width (GTK_CONTAINER(hbox), 12);
@@ -545,7 +536,7 @@ pan :: server_list_dialog_new (Data& data, Queue& queue, GtkWindow* parent)
   // add button
   w = gtk_button_new_from_stock (GTK_STOCK_ADD);
   gtk_box_pack_start (GTK_BOX (bbox), w, FALSE, FALSE, 0);
-  gtk_tooltips_set_tip (tips, w, _("Add a Server"), NULL);
+  pan_widget_set_tooltip_text(w, _("Add a Server"));
   g_signal_connect (w, "clicked", G_CALLBACK(add_button_clicked_cb), d->dialog);
 
   // edit button
@@ -555,14 +546,14 @@ pan :: server_list_dialog_new (Data& data, Queue& queue, GtkWindow* parent)
   w = gtk_button_new_from_stock (GTK_STOCK_OPEN);
 #endif
   gtk_box_pack_start (GTK_BOX (bbox), w, FALSE, FALSE, 0);
-  gtk_tooltips_set_tip (tips, w, _("Edit a Server's Settings"), NULL);
+  pan_widget_set_tooltip_text(w, _("Edit a Server's Settings"));
   g_signal_connect (w, "clicked", G_CALLBACK(edit_button_clicked_cb), d->dialog);
   d->edit_button = w;
 
   // remove button
   w = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
   gtk_box_pack_start (GTK_BOX (bbox), w, FALSE, FALSE, 0);
-  gtk_tooltips_set_tip (tips, w, _("Remove a Server"), NULL);
+  pan_widget_set_tooltip_text(w, _("Remove a Server"));
   g_signal_connect (w, "clicked", G_CALLBACK(remove_button_clicked_cb), d);
   d->remove_button = w;
 
diff --git a/pan/gui/task-pane.cc b/pan/gui/task-pane.cc
index 2475a53..f5ba2ea 100644
--- a/pan/gui/task-pane.cc
+++ b/pan/gui/task-pane.cc
@@ -423,9 +423,6 @@ TaskPane :: TaskPane (Queue& queue, Prefs& prefs): _queue(queue)
   _root = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 
   GtkWidget * w;
-  GtkTooltips * ttips = gtk_tooltips_new ();
-  g_object_ref_sink_pan (G_OBJECT(ttips));
-  g_object_weak_ref (G_OBJECT(_root), (GWeakNotify)g_object_unref, ttips);
 
   GtkWidget * vbox = gtk_vbox_new (false, 0);
 
@@ -451,15 +448,15 @@ TaskPane :: TaskPane (Queue& queue, Prefs& prefs): _queue(queue)
     add_button (buttons, GTK_STOCK_GOTO_BOTTOM, G_CALLBACK(bottom_clicked_cb), this);
     gtk_box_pack_start (GTK_BOX(buttons), gtk_vseparator_new(), 0, 0, 0);
     w = add_button (buttons, GTK_STOCK_REDO, G_CALLBACK(restart_clicked_cb), this);
-    gtk_tooltips_set_tip (ttips, w, _("Restart Tasks"), NULL);
+    pan_widget_set_tooltip_text( w, _("Restart Tasks"));
     w = add_button (buttons, GTK_STOCK_STOP, G_CALLBACK(stop_clicked_cb), this);
-    gtk_tooltips_set_tip (ttips, w, _("Stop Tasks"), NULL);
+    pan_widget_set_tooltip_text( w, _("Stop Tasks"));
     w = add_button (buttons, GTK_STOCK_DELETE, G_CALLBACK(delete_clicked_cb), this);
-    gtk_tooltips_set_tip (ttips, w, _("Delete Tasks"), NULL);
+    pan_widget_set_tooltip_text( w, _("Delete Tasks"));
     gtk_box_pack_start (GTK_BOX(buttons), gtk_vseparator_new(), 0, 0, 0);
     w = add_button (buttons, GTK_STOCK_CLOSE, 0, 0);
     g_signal_connect_swapped (w, "clicked", G_CALLBACK(gtk_widget_destroy), _root);
-    gtk_box_pack_start_defaults (GTK_BOX(buttons), gtk_event_box_new()); // eat h space
+    pan_box_pack_start_defaults (GTK_BOX(buttons), gtk_event_box_new()); // eat h space
 
   gtk_box_pack_start (GTK_BOX(vbox), buttons, false, false, 0);
   gtk_box_pack_start (GTK_BOX(vbox), gtk_hseparator_new(), false, false, 0);
diff --git a/pan/gui/xface.c b/pan/gui/xface.c
index c177e56..3914542 100644
--- a/pan/gui/xface.c
+++ b/pan/gui/xface.c
@@ -1089,12 +1089,18 @@ pan_gdk_pixbuf_create_from_x_face (GdkColormap* cmap, GdkDrawable *drawable, con
 
     if (!cmap)
       cmap = gdk_colormap_get_system ();
-    gdk_color_black (cmap, &black);
-    gdk_color_white (cmap, &white);
+
+    gdk_color_parse ("black", &black);
+    gdk_colormap_alloc_color (cmap, &black, FALSE, TRUE);
+    gdk_color_parse ("white", &white);
+    gdk_colormap_alloc_color (cmap, &white, FALSE, TRUE);
 
     pixmap = gdk_pixmap_create_from_data (drawable, bits, WIDTH, HEIGHT, -1, &white, &black);
     pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, cmap, 0, 0, 0, 0, WIDTH, HEIGHT);
-    gdk_bitmap_unref (pixmap);
+    g_object_unref (pixmap);
+
+    gdk_colormap_free_colors (cmap, &white, 1 );
+    gdk_colormap_free_colors (cmap, &black, 1 );
   }
 
   return pixbuf;
diff --git a/pan/tasks/socket-impl-gio.cc b/pan/tasks/socket-impl-gio.cc
index b2ad315..04ec1bc 100644
--- a/pan/tasks/socket-impl-gio.cc
+++ b/pan/tasks/socket-impl-gio.cc
@@ -321,7 +321,7 @@ GIOChannelSocket :: ~GIOChannelSocket ()
 
   if (_channel)
   {
-    g_io_channel_close (_channel);
+    g_io_channel_shutdown (_channel, TRUE, NULL);
     g_io_channel_unref (_channel);
     _channel = 0;
   }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]