diff --git a/ChangeLog b/ChangeLog
index 43eb8bceb..7234c6626 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2005-03-12  Mike Kestner  <mkestner@novell.com>
+
+	* glib/Makefile.am : add new file.
+	* glib/Object.cs : add protected PersistentData hash to hold data
+	across GC cycles.
+	* glib/WeakObject.cs : new object to hold managed refs weakly against
+	the native object.
+	* gtk/ListStore.custom : hold refs for DefaultSortFuncs.
+	* gtk/TreeModelSort.custom : hold refs for DefaultSortFuncs.
+	* gtk/TreeStore.custom : hold refs for DefaultSortFuncs.
+
 2005-03-12  Mike Kestner  <mkestner@novell.com>
 
 	* generator/CallbackGen.cs : don't derive Wrappers from DelegateWrapper
diff --git a/glib/Makefile.am b/glib/Makefile.am
index 85b62d6a6..53de58fbd 100644
--- a/glib/Makefile.am
+++ b/glib/Makefile.am
@@ -49,7 +49,8 @@ sources =		 			\
 	TypeFundamentals.cs			\
 	UnwrappedObject.cs			\
 	ValueArray.cs				\
-	Value.cs
+	Value.cs				\
+	WeakObject.cs
 
 build_sources = $(addprefix $(srcdir)/, $(sources)) ../AssemblyInfo.cs
 dist_sources = $(sources)
diff --git a/glib/Object.cs b/glib/Object.cs
index 3b281d525..725f836ef 100644
--- a/glib/Object.cs
+++ b/glib/Object.cs
@@ -357,6 +357,12 @@ namespace GLib {
 			}
 		}
 
+		protected Hashtable PersistentData {
+			get {
+				return WeakObject.Lookup (Handle).Data;
+			}
+		}
+
 		[DllImport("libgobject-2.0-0.dll")]
 		static extern void g_object_get_property (IntPtr obj, IntPtr name, ref GLib.Value val);
 
diff --git a/glib/WeakObject.cs b/glib/WeakObject.cs
new file mode 100644
index 000000000..24d5ea266
--- /dev/null
+++ b/glib/WeakObject.cs
@@ -0,0 +1,89 @@
+// WeakObject.cs - Object to hold managed references via native weakref.
+//
+// Authors: Mike Kestner <mkestner@novell.com>
+//
+// Copyright (c) 2005 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the Lesser 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
+// Lesser 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.
+
+
+namespace GLib {
+
+	using System;
+	using System.Collections;
+	using System.Runtime.InteropServices;
+
+	internal class WeakObject {
+
+		GCHandle gc_handle;
+
+		static DestroyNotify notify = new DestroyNotify (OnNativeDestroy);
+		delegate void DestroyNotify (IntPtr data);
+		static void OnNativeDestroy (IntPtr data)
+		{
+			GCHandle gch = (GCHandle) data;
+			WeakObject obj = gch.Target as WeakObject;
+			obj.Dispose ();
+			gch.Free ();
+		}
+
+		void Dispose ()
+		{
+			signals = null;
+			data = null;
+		}
+
+		WeakObject (IntPtr obj)
+		{
+			gc_handle = GCHandle.Alloc (this);
+			g_object_set_data_full (obj, "gtk_sharp_weak_object", (IntPtr) gc_handle, notify);
+		}
+
+		Hashtable data;
+		public Hashtable Data {
+			get {
+				if (data == null)
+					data = new Hashtable ();
+				return data;
+			}
+		}
+
+		Hashtable signals;
+		public Hashtable Signals {
+			get {
+				if (signals == null)
+					signals = new Hashtable ();
+				return signals;
+			}
+		}
+
+		public static WeakObject Lookup (IntPtr obj)
+		{
+			IntPtr data = g_object_get_data (obj, "gtk_sharp_weak_object");
+			if (data == IntPtr.Zero)
+				return new WeakObject (obj);
+
+			GCHandle gch = (GCHandle) data;
+			return gch.Target as WeakObject;
+		}
+
+		[DllImport("libgobject-2.0-0.dll")]
+		static extern IntPtr g_object_get_data (IntPtr instance, string key);
+
+		[DllImport("libgobject-2.0-0.dll")]
+		static extern void g_object_set_data_full (IntPtr instance, string key, IntPtr data, DestroyNotify notify);
+	}
+}
+
diff --git a/gtk/Gtk.metadata b/gtk/Gtk.metadata
index 4bffbd3ee..1a5f951d2 100644
--- a/gtk/Gtk.metadata
+++ b/gtk/Gtk.metadata
@@ -93,6 +93,7 @@
   <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='RowHasChildToggled']" name="name">EmitRowHasChildToggled</attr>
   <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='RowInserted']" name="name">EmitRowInserted</attr>
   <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='RowsReordered']" name="name">EmitRowsReordered</attr>
+  <attr path="/api/namespace/interface[@cname='GtkTreeSortable']/method[@name='SetDefaultSortFunc']" name="hidden">1</attr>
   <attr path="/api/namespace/interface[@cname='GtkTreeSortable']/method[@name='SortColumnChanged']" name="name">ChangeSortColumn</attr>
   <attr path="/api/namespace/object[@cname='GtkAccelLabel']/constructor[@cname='gtk_accel_label_new']/*/*[@name='string']" name="property_name">label</attr>
   <attr path="/api/namespace/object[@cname='GtkAction']/signal[@name='Activate']" name="name">Activated</attr>
diff --git a/gtk/ListStore.custom b/gtk/ListStore.custom
index 91c2a62cd..1df78d56e 100644
--- a/gtk/ListStore.custom
+++ b/gtk/ListStore.custom
@@ -150,3 +150,24 @@
 			return ret;
 		}
 
+		[DllImport("libgtk-win32-2.0-0.dll")]
+		static extern void gtk_tree_sortable_set_default_sort_func(IntPtr raw, IntPtr sort_func, IntPtr user_data, IntPtr destroy);
+
+		[DllImport("libgtk-win32-2.0-0.dll")]
+		static extern void gtk_tree_sortable_set_default_sort_func(IntPtr raw, GtkSharp.TreeIterCompareFuncNative sort_func, IntPtr user_data, GtkSharp.DestroyNotifyNative destroy);
+
+		public void SetDefaultSortFunc (TreeIterCompareFunc sort_func, IntPtr user_data, Gtk.DestroyNotify destroy) 
+		{
+			if (sort_func == null) {
+				PersistentData ["default_sort_func"] = null;
+				gtk_tree_sortable_set_default_sort_func (Handle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
+				return;
+			}
+
+			GtkSharp.TreeIterCompareFuncWrapper sort_func_wrapper = new GtkSharp.TreeIterCompareFuncWrapper (sort_func);
+			PersistentData ["default_sort_func"] = sort_func_wrapper;
+			GtkSharp.DestroyNotifyWrapper destroy_wrapper = null;
+			destroy_wrapper = new GtkSharp.DestroyNotifyWrapper (destroy);
+			gtk_tree_sortable_set_default_sort_func(Handle, sort_func_wrapper.NativeDelegate, user_data, destroy_wrapper.NativeDelegate);
+		}
+
diff --git a/gtk/TreeModelSort.custom b/gtk/TreeModelSort.custom
index 3fc366bb6..ba9c182e5 100644
--- a/gtk/TreeModelSort.custom
+++ b/gtk/TreeModelSort.custom
@@ -84,3 +84,25 @@
 			val.Dispose ();
 			return ret;
 		}
+
+		[DllImport("libgtk-win32-2.0-0.dll")]
+		static extern void gtk_tree_sortable_set_default_sort_func(IntPtr raw, IntPtr sort_func, IntPtr user_data, IntPtr destroy);
+
+		[DllImport("libgtk-win32-2.0-0.dll")]
+		static extern void gtk_tree_sortable_set_default_sort_func(IntPtr raw, GtkSharp.TreeIterCompareFuncNative sort_func, IntPtr user_data, GtkSharp.DestroyNotifyNative destroy);
+
+		public void SetDefaultSortFunc (TreeIterCompareFunc sort_func, IntPtr user_data, Gtk.DestroyNotify destroy) 
+		{
+			if (sort_func == null) {
+				PersistentData ["default_sort_func"] = null;
+				gtk_tree_sortable_set_default_sort_func (Handle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
+				return;
+			}
+
+			GtkSharp.TreeIterCompareFuncWrapper sort_func_wrapper = new GtkSharp.TreeIterCompareFuncWrapper (sort_func);
+			PersistentData ["default_sort_func"] = sort_func_wrapper;
+			GtkSharp.DestroyNotifyWrapper destroy_wrapper = null;
+			destroy_wrapper = new GtkSharp.DestroyNotifyWrapper (destroy);
+			gtk_tree_sortable_set_default_sort_func(Handle, sort_func_wrapper.NativeDelegate, user_data, destroy_wrapper.NativeDelegate);
+		}
+
diff --git a/gtk/TreeStore.custom b/gtk/TreeStore.custom
index 95eaa8f2c..3671d2ec7 100644
--- a/gtk/TreeStore.custom
+++ b/gtk/TreeStore.custom
@@ -193,4 +193,25 @@
 			return ret;
 		}
 
+		[DllImport("libgtk-win32-2.0-0.dll")]
+		static extern void gtk_tree_sortable_set_default_sort_func(IntPtr raw, IntPtr sort_func, IntPtr user_data, IntPtr destroy);
+
+		[DllImport("libgtk-win32-2.0-0.dll")]
+		static extern void gtk_tree_sortable_set_default_sort_func(IntPtr raw, GtkSharp.TreeIterCompareFuncNative sort_func, IntPtr user_data, GtkSharp.DestroyNotifyNative destroy);
+
+		public void SetDefaultSortFunc (TreeIterCompareFunc sort_func, IntPtr user_data, Gtk.DestroyNotify destroy) 
+		{
+			if (sort_func == null) {
+				PersistentData ["default_sort_func"] = null;
+				gtk_tree_sortable_set_default_sort_func (Handle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
+				return;
+			}
+
+			GtkSharp.TreeIterCompareFuncWrapper sort_func_wrapper = new GtkSharp.TreeIterCompareFuncWrapper (sort_func);
+			PersistentData ["default_sort_func"] = sort_func_wrapper;
+			GtkSharp.DestroyNotifyWrapper destroy_wrapper = null;
+			destroy_wrapper = new GtkSharp.DestroyNotifyWrapper (destroy);
+			gtk_tree_sortable_set_default_sort_func(Handle, sort_func_wrapper.NativeDelegate, user_data, destroy_wrapper.NativeDelegate);
+		}
+