]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktreeview.c
modify and free tmp instead of path ... (patch from #97927).
[~andy/gtk] / gtk / gtktreeview.c
index b22a434bc2e0cec5d9b76a225776475464fe7988..8ebf772f1988d876841cdc40fc629831415a3fde 100644 (file)
  */
 
 
+#include <string.h>
+#include <gdk/gdkkeysyms.h>
+
 #include "gtktreeview.h"
 #include "gtkrbtree.h"
 #include "gtktreednd.h"
 #include "gtktreeprivate.h"
 #include "gtkcellrenderer.h"
-#include "gtksignal.h"
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
 #include "gtkbutton.h"
@@ -37,9 +39,6 @@
 #include "gtkentry.h"
 #include "gtktreemodelsort.h"
 
-#include <string.h>
-#include <gdk/gdkkeysyms.h>
-
 #define GTK_TREE_VIEW_SEARCH_DIALOG_KEY "gtk-tree-view-search-dialog"
 #define GTK_TREE_VIEW_PRIORITY_VALIDATE (GDK_PRIORITY_REDRAW + 5)
 #define GTK_TREE_VIEW_PRIORITY_SCROLL_SYNC (GTK_TREE_VIEW_PRIORITY_VALIDATE + 2)
@@ -263,7 +262,7 @@ static gboolean validate_row             (GtkTreeView *tree_view,
                                          GtkTreePath *path);
 static void     validate_visible_area    (GtkTreeView *tree_view);
 static gboolean validate_rows_handler    (GtkTreeView *tree_view);
-static gboolean do_validate_rows        (GtkTreeView *tree_view);
+static gboolean validate_rows            (GtkTreeView *tree_view);
 static gboolean presize_handler_callback (gpointer     data);
 static void     install_presize_handler  (GtkTreeView *tree_view);
 static void     install_scroll_sync_handler (GtkTreeView *tree_view);
@@ -347,8 +346,7 @@ static void     gtk_tree_view_real_set_cursor                (GtkTreeView
                                                              GtkTreePath       *path,
                                                              gboolean           clear_and_select,
                                                              gboolean           clamp_node);
-static void     gtk_tree_view_column_autosize                (GtkTreeView       *tree_view,
-                                                             GtkTreeViewColumn *tree_column);
+static gboolean gtk_tree_view_has_special_cell               (GtkTreeView       *tree_view);
 
 /* interactive search */
 static void     gtk_tree_view_search_dialog_destroy     (GtkWidget        *search_dialog,
@@ -417,10 +415,10 @@ static guint tree_view_signals [LAST_SIGNAL] = { 0 };
 /* GType Methods
  */
 
-GtkType
+GType
 gtk_tree_view_get_type (void)
 {
-  static GtkType tree_view_type = 0;
+  static GType tree_view_type = 0;
 
   if (!tree_view_type)
     {
@@ -437,7 +435,9 @@ gtk_tree_view_get_type (void)
         (GInstanceInitFunc) gtk_tree_view_init
       };
 
-      tree_view_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkTreeView", &tree_view_info, 0);
+      tree_view_type =
+       g_type_register_static (GTK_TYPE_CONTAINER, "GtkTreeView",
+                               &tree_view_info, 0);
     }
 
   return tree_view_type;
@@ -601,7 +601,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_int ("expander_size",
                                                             _("Expander Size"),
-                                                            _("Size of the expander arrow."),
+                                                            _("Size of the expander arrow"),
                                                             0,
                                                             G_MAXINT,
                                                             _TREE_VIEW_EXPANDER_SIZE,
@@ -610,7 +610,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_int ("vertical_separator",
                                                             _("Vertical Separator Width"),
-                                                            _("Vertical space between cells.  Must be an even number."),
+                                                            _("Vertical space between cells.  Must be an even number"),
                                                             0,
                                                             G_MAXINT,
                                                             _TREE_VIEW_VERTICAL_SEPARATOR,
@@ -619,7 +619,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_int ("horizontal_separator",
                                                             _("Horizontal Separator Width"),
-                                                            _("Horizontal space between cells.  Must be an even number."),
+                                                            _("Horizontal space between cells.  Must be an even number"),
                                                             0,
                                                             G_MAXINT,
                                                             _TREE_VIEW_HORIZONTAL_SEPARATOR,
@@ -628,170 +628,193 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_boolean ("allow_rules",
                                                                 _("Allow Rules"),
-                                                                _("Allow drawing of alternating color rows."),
+                                                                _("Allow drawing of alternating color rows"),
                                                                 TRUE,
                                                                 G_PARAM_READABLE));
 
   gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_boolean ("indent_expanders",
                                                                 _("Indent Expanders"),
-                                                                _("Make the expanders indented."),
+                                                                _("Make the expanders indented"),
                                                                 TRUE,
                                                                 G_PARAM_READABLE));
+
+  gtk_widget_class_install_style_property (widget_class,
+                                           g_param_spec_boxed ("even_row_color",
+                                                               _("Even Row Color"),
+                                                               _("Color to use for even rows"),
+                                                              GDK_TYPE_COLOR,
+G_PARAM_READABLE));
+
+  gtk_widget_class_install_style_property (widget_class,
+                                           g_param_spec_boxed ("odd_row_color",
+                                                               _("Odd Row Color"),
+                                                               _("Color to use for odd rows"),
+                                                              GDK_TYPE_COLOR,
+G_PARAM_READABLE));
+
   /* Signals */
   widget_class->set_scroll_adjustments_signal =
-    gtk_signal_new ("set_scroll_adjustments",
-                   GTK_RUN_LAST,
-                   GTK_CLASS_TYPE (object_class),
-                   GTK_SIGNAL_OFFSET (GtkTreeViewClass, set_scroll_adjustments),
-                   _gtk_marshal_VOID__OBJECT_OBJECT,
-                   GTK_TYPE_NONE, 2,
-                   GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
+    g_signal_new ("set_scroll_adjustments",
+                 G_TYPE_FROM_CLASS (o_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, set_scroll_adjustments),
+                 NULL, NULL,
+                 _gtk_marshal_VOID__OBJECT_OBJECT,
+                 G_TYPE_NONE, 2,
+                 GTK_TYPE_ADJUSTMENT,
+                 GTK_TYPE_ADJUSTMENT);
 
   tree_view_signals[ROW_ACTIVATED] =
-    gtk_signal_new ("row_activated",
-                   GTK_RUN_LAST | GTK_RUN_ACTION,
-                   GTK_CLASS_TYPE (object_class),
-                   GTK_SIGNAL_OFFSET (GtkTreeViewClass, row_activated),
-                   _gtk_marshal_VOID__BOXED_OBJECT,
-                   GTK_TYPE_NONE, 2,
-                   GTK_TYPE_TREE_PATH,
-                   GTK_TYPE_TREE_VIEW_COLUMN);
+    g_signal_new ("row_activated",
+                 G_TYPE_FROM_CLASS (o_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, row_activated),
+                 NULL, NULL,
+                 _gtk_marshal_VOID__BOXED_OBJECT,
+                 G_TYPE_NONE, 2,
+                 GTK_TYPE_TREE_PATH,
+                 GTK_TYPE_TREE_VIEW_COLUMN);
 
   tree_view_signals[TEST_EXPAND_ROW] =
     g_signal_new ("test_expand_row",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, test_expand_row),
-                  _gtk_boolean_handled_accumulator, NULL,
-                  _gtk_marshal_BOOLEAN__BOXED_BOXED,
-                  G_TYPE_BOOLEAN, 2,
-                  GTK_TYPE_TREE_ITER,
-                  GTK_TYPE_TREE_PATH);
+                 G_TYPE_FROM_CLASS (o_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, test_expand_row),
+                 _gtk_boolean_handled_accumulator, NULL,
+                 _gtk_marshal_BOOLEAN__BOXED_BOXED,
+                 G_TYPE_BOOLEAN, 2,
+                 GTK_TYPE_TREE_ITER,
+                 GTK_TYPE_TREE_PATH);
 
   tree_view_signals[TEST_COLLAPSE_ROW] =
     g_signal_new ("test_collapse_row",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, test_collapse_row),
-                  _gtk_boolean_handled_accumulator, NULL,
-                  _gtk_marshal_BOOLEAN__BOXED_BOXED,
-                  G_TYPE_BOOLEAN, 2,
-                  GTK_TYPE_TREE_ITER,
-                  GTK_TYPE_TREE_PATH);
+                 G_TYPE_FROM_CLASS (o_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, test_collapse_row),
+                 _gtk_boolean_handled_accumulator, NULL,
+                 _gtk_marshal_BOOLEAN__BOXED_BOXED,
+                 G_TYPE_BOOLEAN, 2,
+                 GTK_TYPE_TREE_ITER,
+                 GTK_TYPE_TREE_PATH);
 
   tree_view_signals[ROW_EXPANDED] =
     g_signal_new ("row_expanded",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, row_expanded),
-                  NULL, NULL,
-                  _gtk_marshal_VOID__BOXED_BOXED,
-                  GTK_TYPE_NONE, 2,
-                  GTK_TYPE_TREE_ITER,
-                  GTK_TYPE_TREE_PATH);
+                 G_TYPE_FROM_CLASS (o_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, row_expanded),
+                 NULL, NULL,
+                 _gtk_marshal_VOID__BOXED_BOXED,
+                 G_TYPE_NONE, 2,
+                 GTK_TYPE_TREE_ITER,
+                 GTK_TYPE_TREE_PATH);
 
   tree_view_signals[ROW_COLLAPSED] =
     g_signal_new ("row_collapsed",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, row_collapsed),
-                  NULL, NULL,
-                  _gtk_marshal_VOID__BOXED_BOXED,
-                  GTK_TYPE_NONE, 2,
-                  GTK_TYPE_TREE_ITER,
-                  GTK_TYPE_TREE_PATH);
+                 G_TYPE_FROM_CLASS (o_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, row_collapsed),
+                 NULL, NULL,
+                 _gtk_marshal_VOID__BOXED_BOXED,
+                 G_TYPE_NONE, 2,
+                 GTK_TYPE_TREE_ITER,
+                 GTK_TYPE_TREE_PATH);
 
   tree_view_signals[COLUMNS_CHANGED] =
     g_signal_new ("columns_changed",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, columns_changed),
-                  NULL, NULL,
-                  _gtk_marshal_NONE__NONE,
-                  G_TYPE_NONE, 0);
+                 G_TYPE_FROM_CLASS (o_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, columns_changed),
+                 NULL, NULL,
+                 _gtk_marshal_NONE__NONE,
+                 G_TYPE_NONE, 0);
 
   tree_view_signals[CURSOR_CHANGED] =
     g_signal_new ("cursor_changed",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, cursor_changed),
-                  NULL, NULL,
-                  _gtk_marshal_NONE__NONE,
-                  G_TYPE_NONE, 0);
+                 G_TYPE_FROM_CLASS (o_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, cursor_changed),
+                 NULL, NULL,
+                 _gtk_marshal_NONE__NONE,
+                 G_TYPE_NONE, 0);
 
   tree_view_signals[MOVE_CURSOR] =
     g_signal_new ("move_cursor",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, move_cursor),
-                  NULL, NULL,
-                  _gtk_marshal_BOOLEAN__ENUM_INT,
-                  GTK_TYPE_BOOL, 2, GTK_TYPE_MOVEMENT_STEP, GTK_TYPE_INT);
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, move_cursor),
+                 NULL, NULL,
+                 _gtk_marshal_BOOLEAN__ENUM_INT,
+                 G_TYPE_BOOLEAN, 2,
+                 GTK_TYPE_MOVEMENT_STEP,
+                 G_TYPE_INT);
 
   tree_view_signals[SELECT_ALL] =
     g_signal_new ("select_all",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, select_all),
-                  NULL, NULL,
-                  _gtk_marshal_NONE__NONE,
-                  GTK_TYPE_NONE, 0);
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, select_all),
+                 NULL, NULL,
+                 _gtk_marshal_NONE__NONE,
+                 G_TYPE_NONE, 0);
 
   tree_view_signals[UNSELECT_ALL] =
     g_signal_new ("unselect_all",
                  G_TYPE_FROM_CLASS (object_class),
-                 G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, unselect_all),
                  NULL, NULL,
                  _gtk_marshal_NONE__NONE,
-                 GTK_TYPE_NONE, 0);
+                 G_TYPE_NONE, 0);
 
   tree_view_signals[SELECT_CURSOR_ROW] =
     g_signal_new ("select_cursor_row",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_row),
-                  NULL, NULL,
-                  _gtk_marshal_VOID__BOOLEAN,
-                  GTK_TYPE_NONE, 1,
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_row),
+                 NULL, NULL,
+                 _gtk_marshal_VOID__BOOLEAN,
+                 G_TYPE_NONE, 1,
                  G_TYPE_BOOLEAN);
 
   tree_view_signals[TOGGLE_CURSOR_ROW] =
     g_signal_new ("toggle_cursor_row",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, toggle_cursor_row),
-                  NULL, NULL,
-                  _gtk_marshal_NONE__NONE,
-                  GTK_TYPE_NONE, 0);
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, toggle_cursor_row),
+                 NULL, NULL,
+                 _gtk_marshal_NONE__NONE,
+                 G_TYPE_NONE, 0);
 
   tree_view_signals[EXPAND_COLLAPSE_CURSOR_ROW] =
     g_signal_new ("expand_collapse_cursor_row",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, expand_collapse_cursor_row),
-                  NULL, NULL,
-                  _gtk_marshal_VOID__BOOLEAN_BOOLEAN_BOOLEAN,
-                  GTK_TYPE_NONE, 3, GTK_TYPE_BOOL, GTK_TYPE_BOOL, GTK_TYPE_BOOL);
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, expand_collapse_cursor_row),
+                 NULL, NULL,
+                 _gtk_marshal_VOID__BOOLEAN_BOOLEAN_BOOLEAN,
+                 G_TYPE_NONE, 3,
+                 G_TYPE_BOOLEAN,
+                 G_TYPE_BOOLEAN,
+                 G_TYPE_BOOLEAN);
 
   tree_view_signals[SELECT_CURSOR_PARENT] =
     g_signal_new ("select_cursor_parent",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_parent),
-                  NULL, NULL,
-                  _gtk_marshal_NONE__NONE,
-                  GTK_TYPE_NONE, 0);
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_parent),
+                 NULL, NULL,
+                 _gtk_marshal_NONE__NONE,
+                 G_TYPE_NONE, 0);
 
   tree_view_signals[START_INTERACTIVE_SEARCH] =
     g_signal_new ("start_interactive_search",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, start_interactive_search),
-                  NULL, NULL,
-                  _gtk_marshal_NONE__NONE,
-                  GTK_TYPE_NONE, 0);
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, start_interactive_search),
+                 NULL, NULL,
+                 _gtk_marshal_NONE__NONE,
+                 G_TYPE_NONE, 0);
 
   /* Key bindings */
   gtk_tree_view_add_move_binding (binding_set, GDK_Up, 0,
@@ -819,28 +842,28 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                                  GTK_MOVEMENT_PAGES, 1);
 
   gtk_binding_entry_add_signal (binding_set, GDK_Right, 0, "move_cursor", 2,
-                               GTK_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
-                               GTK_TYPE_INT, 1);
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, 1);
 
   gtk_binding_entry_add_signal (binding_set, GDK_Left, 0, "move_cursor", 2,
-                               GTK_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
-                               GTK_TYPE_INT, -1);
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, -1);
 
   gtk_binding_entry_add_signal (binding_set, GDK_Right, GDK_CONTROL_MASK, "move_cursor", 2,
-                               GTK_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
-                               GTK_TYPE_INT, 1);
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, 1);
 
   gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_CONTROL_MASK, "move_cursor", 2,
-                               GTK_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
-                               GTK_TYPE_INT, -1);
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, -1);
 
   gtk_binding_entry_add_signal (binding_set, GDK_Right, GDK_CONTROL_MASK|GDK_SHIFT_MASK, "move_cursor", 2,
-                               GTK_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
-                               GTK_TYPE_INT, 1);
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, 1);
 
   gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_CONTROL_MASK|GDK_SHIFT_MASK, "move_cursor", 2,
-                               GTK_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
-                               GTK_TYPE_INT, -1);
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, -1);
 
   gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK, "toggle_cursor_row", 0);
 
@@ -851,58 +874,58 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   gtk_binding_entry_add_signal (binding_set, GDK_backslash, GDK_CONTROL_MASK, "unselect_all", 0);
 
   gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_SHIFT_MASK, "select_cursor_row", 1,
-                               GTK_TYPE_BOOL, TRUE);
+                               G_TYPE_BOOLEAN, TRUE);
 
   gtk_binding_entry_add_signal (binding_set, GDK_space, 0, "select_cursor_row", 1,
-                               GTK_TYPE_BOOL, TRUE);
+                               G_TYPE_BOOLEAN, TRUE);
 
   /* expand and collapse rows */
   gtk_binding_entry_add_signal (binding_set, GDK_plus, 0, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, TRUE,
-                               GTK_TYPE_BOOL, FALSE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, FALSE);
   /* Not doable on US keyboards */
   gtk_binding_entry_add_signal (binding_set, GDK_plus, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, TRUE,
-                               GTK_TYPE_BOOL, TRUE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE);
   gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, 0, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, TRUE,
-                               GTK_TYPE_BOOL, FALSE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, FALSE);
   gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, TRUE,
-                               GTK_TYPE_BOOL, TRUE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE);
   gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, TRUE,
-                               GTK_TYPE_BOOL, TRUE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE);
   gtk_binding_entry_add_signal (binding_set, GDK_Right, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, TRUE,
-                               GTK_TYPE_BOOL, TRUE,
-                               GTK_TYPE_BOOL, TRUE);
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE);
 
   gtk_binding_entry_add_signal (binding_set, GDK_minus, 0, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, FALSE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE);
   gtk_binding_entry_add_signal (binding_set, GDK_minus, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, TRUE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE);
   gtk_binding_entry_add_signal (binding_set, GDK_KP_Subtract, 0, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, FALSE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE);
   gtk_binding_entry_add_signal (binding_set, GDK_KP_Subtract, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, TRUE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE);
   gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, TRUE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE);
 
   gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0, "select_cursor_parent", 0);
 
@@ -917,6 +940,8 @@ gtk_tree_view_init (GtkTreeView *tree_view)
   tree_view->priv = g_new0 (GtkTreeViewPrivate, 1);
   GTK_WIDGET_SET_FLAGS (tree_view, GTK_CAN_FOCUS);
 
+  gtk_widget_set_redraw_on_allocate (GTK_WIDGET (tree_view), FALSE);
+
   tree_view->priv->flags = GTK_TREE_VIEW_IS_LIST | GTK_TREE_VIEW_SHOW_EXPANDERS | GTK_TREE_VIEW_DRAW_KEYFOCUS | GTK_TREE_VIEW_HEADERS_VISIBLE;
 
   /* We need some padding */
@@ -1141,8 +1166,8 @@ gtk_tree_view_destroy (GtkObject *object)
   tree_view->priv->anchor = NULL;
 
   /* destroy interactive search dialog */
-  search_dialog = gtk_object_get_data (GTK_OBJECT (tree_view),
-                                      GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
+  search_dialog = g_object_get_data (G_OBJECT (tree_view),
+                                    GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
   if (search_dialog)
     gtk_tree_view_search_dialog_destroy (search_dialog,
                                         tree_view);
@@ -1496,7 +1521,7 @@ gtk_tree_view_size_request (GtkWidget      *widget,
 
   /* we validate 50 rows initially just to make sure we have some size */
   /* in practice, with a lot of static lists, this should get a good width */
-  do_validate_rows (tree_view);
+  validate_rows (tree_view);
   gtk_tree_view_size_request_columns (tree_view);
   gtk_tree_view_update_size (GTK_TREE_VIEW (widget));
 
@@ -1551,11 +1576,13 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
       if (column == tree_view->priv->drag_column)
        {
          GtkAllocation drag_allocation;
-         gdk_window_get_size (tree_view->priv->drag_window,
-                              &(drag_allocation.width), &(drag_allocation.height));
+         gdk_drawable_get_size (tree_view->priv->drag_window,
+                                &(drag_allocation.width),
+                                &(drag_allocation.height));
          drag_allocation.x = 0;
          drag_allocation.y = 0;
-         gtk_widget_size_allocate (tree_view->priv->drag_column->button, &drag_allocation);
+         gtk_widget_size_allocate (tree_view->priv->drag_column->button,
+                                   &drag_allocation);
          width += drag_allocation.width;
          continue;
        }
@@ -1603,15 +1630,52 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
     }
 }
 
+static void
+invalidate_last_column (GtkTreeView *tree_view)
+{
+  GList *list, *last_column;
+  gint last_column_x;
+  GtkWidget *widget = GTK_WIDGET (tree_view);
+
+  for (last_column = g_list_last (tree_view->priv->columns);
+       last_column && !(GTK_TREE_VIEW_COLUMN (last_column->data)->visible);
+       last_column = last_column->prev)
+    ;
+  
+  last_column_x = 0;
+  for (list = tree_view->priv->columns; list; list = list->next)
+    {
+      GtkTreeViewColumn *column = list->data;
+      if (list == last_column)
+       {
+         GdkRectangle invalid_rect;
+         
+         invalid_rect.x = last_column_x;
+         invalid_rect.y = 0;
+         invalid_rect.width = column->width;
+         invalid_rect.height = widget->allocation.height;
+         
+         gdk_window_invalidate_rect (widget->window, &invalid_rect, TRUE);
+         break;
+       }
+      
+      last_column_x += column->width;
+    }
+}
+
 static void
 gtk_tree_view_size_allocate (GtkWidget     *widget,
                             GtkAllocation *allocation)
 {
   GList *tmp_list;
   GtkTreeView *tree_view;
+  gboolean width_changed = FALSE;
 
   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
 
+  if (allocation->width != widget->allocation.width)
+    width_changed = TRUE;
+  
   widget->allocation = *allocation;
 
   tree_view = GTK_TREE_VIEW (widget);
@@ -1673,6 +1737,9 @@ gtk_tree_view_size_allocate (GtkWidget     *widget,
     }
 
   gtk_tree_view_size_allocate_columns (widget);
+
+  if (GTK_WIDGET_REALIZED (widget) && width_changed)
+    invalidate_last_column (tree_view);
 }
 
 static gboolean
@@ -1711,6 +1778,7 @@ gtk_tree_view_button_press (GtkWidget      *widget,
       gint dval;
       gint pre_val, aft_val;
       GtkTreeViewColumn *column = NULL;
+      GtkCellRenderer *focus_cell = NULL;
       gint column_handled_click = FALSE;
       gboolean emit_row_activated = FALSE;
 
@@ -1786,7 +1854,11 @@ gtk_tree_view_button_press (GtkWidget      *widget,
        }
 
       if (column == NULL)
-       return FALSE;
+       {
+         gtk_tree_path_free (path);
+
+         return FALSE;
+       }
 
       /* decide if we edit */
       if (event->type == GDK_BUTTON_PRESS &&
@@ -1831,7 +1903,7 @@ gtk_tree_view_button_press (GtkWidget      *widget,
                      GdkRectangle area;
 
                      area = cell_area;
-                     _gtk_tree_view_column_get_neighbor_sizes (column, _gtk_tree_view_column_get_editable_cell (column), &left, &right);
+                     _gtk_tree_view_column_get_neighbor_sizes (column, _gtk_tree_view_column_get_edited_cell (column), &left, &right);
 
                      area.x += left;
                      area.width -= right + left;
@@ -1843,6 +1915,7 @@ gtk_tree_view_button_press (GtkWidget      *widget,
                                                        &area,
                                                        (GdkEvent *)event,
                                                        flags);
+                     g_free (path_string);
                      gtk_tree_path_free (path);
                      gtk_tree_path_free (anchor);
                      return TRUE;
@@ -1859,6 +1932,10 @@ gtk_tree_view_button_press (GtkWidget      *widget,
       pre_val = tree_view->priv->vadjustment->value;
 
       tree_view->priv->focus_column = column;
+      focus_cell = _gtk_tree_view_column_get_cell_at_pos (column, event->x - background_area.x);
+      if (focus_cell)
+        gtk_tree_view_column_focus_cell (column, focus_cell);
+
       if (event->state & GDK_CONTROL_MASK)
        {
          gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
@@ -1947,9 +2024,10 @@ gtk_tree_view_button_press (GtkWidget      *widget,
        {
          gpointer drag_data;
 
-         if (event->type == GDK_2BUTTON_PRESS)
+         if (event->type == GDK_2BUTTON_PRESS &&
+             gtk_tree_view_column_get_sizing (column) != GTK_TREE_VIEW_COLUMN_AUTOSIZE)
            {
-             gtk_tree_view_column_autosize (tree_view, column);
+             _gtk_tree_view_column_autosize (tree_view, column);
              break;
            }
 
@@ -1966,9 +2044,12 @@ gtk_tree_view_button_press (GtkWidget      *widget,
          column->use_resized_width = TRUE;
 
          /* block attached dnd signal handler */
-         drag_data = gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data");
+         drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
          if (drag_data)
-           gtk_signal_handler_block_by_data (GTK_OBJECT (widget), drag_data);
+           g_signal_handlers_block_matched (widget,
+                                            G_SIGNAL_MATCH_DATA,
+                                            0, 0, NULL, NULL,
+                                            drag_data);
 
          if (!GTK_WIDGET_HAS_FOCUS (widget))
            gtk_widget_grab_focus (widget);
@@ -1990,8 +2071,8 @@ gtk_tree_view_button_release_drag_column (GtkWidget      *widget,
 
   tree_view = GTK_TREE_VIEW (widget);
 
-  gdk_pointer_ungrab (GDK_CURRENT_TIME);
-  gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+  gdk_display_pointer_ungrab (gtk_widget_get_display (widget), GDK_CURRENT_TIME);
+  gdk_display_keyboard_ungrab (gtk_widget_get_display (widget), GDK_CURRENT_TIME);
 
   /* Move the button back */
   g_object_ref (tree_view->priv->drag_column->button);
@@ -2046,15 +2127,18 @@ gtk_tree_view_button_release_column_resize (GtkWidget      *widget,
   tree_view->priv->drag_pos = -1;
 
       /* unblock attached dnd signal handler */
-  drag_data = gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data");
+  drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
   if (drag_data)
-    gtk_signal_handler_unblock_by_data (GTK_OBJECT (widget), drag_data);
+    g_signal_handlers_unblock_matched (widget,
+                                      G_SIGNAL_MATCH_DATA,
+                                      0, 0, NULL, NULL,
+                                      drag_data);
 
   GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE);
   gtk_widget_get_pointer (widget, &x, NULL);
   gtk_grab_remove (widget);
-  gdk_pointer_ungrab (event->time);
-
+  gdk_display_pointer_ungrab (gdk_drawable_get_display (event->window),
+                             event->time);
   return TRUE;
 }
 
@@ -2275,9 +2359,12 @@ gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
 
       if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ORIGINAL)
        {
-
          if (tree_view->priv->drag_highlight_window)
-           gdk_window_destroy (tree_view->priv->drag_highlight_window);
+           {
+             gdk_window_set_user_data (tree_view->priv->drag_highlight_window,
+                                       NULL);
+             gdk_window_destroy (tree_view->priv->drag_highlight_window);
+           }
 
          attributes.window_type = GDK_WINDOW_CHILD;
          attributes.wclass = GDK_INPUT_OUTPUT;
@@ -2301,11 +2388,11 @@ gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
          col.pixel = 0;
          gdk_gc_set_foreground(gc, &col);
          gdk_draw_rectangle (mask, gc, TRUE, 2, 2, width - 4, height - 4);
-         gdk_gc_destroy (gc);
+         g_object_unref (gc);
 
          gdk_window_shape_combine_mask (tree_view->priv->drag_highlight_window,
                                         mask, 0, 0);
-         if (mask) gdk_pixmap_unref (mask);
+         if (mask) g_object_unref (mask);
          tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_ORIGINAL;
        }
     }
@@ -2336,7 +2423,11 @@ gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
       if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW)
        {
          if (tree_view->priv->drag_highlight_window)
-           gdk_window_destroy (tree_view->priv->drag_highlight_window);
+           {
+             gdk_window_set_user_data (tree_view->priv->drag_highlight_window,
+                                       NULL);
+             gdk_window_destroy (tree_view->priv->drag_highlight_window);
+           }
 
          attributes.window_type = GDK_WINDOW_TEMP;
          attributes.wclass = GDK_INPUT_OUTPUT;
@@ -2346,7 +2437,8 @@ gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
          attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
          attributes.width = width;
          attributes.height = height;
-         tree_view->priv->drag_highlight_window = gdk_window_new (NULL, &attributes, attributes_mask);
+         tree_view->priv->drag_highlight_window = gdk_window_new (gtk_widget_get_root_window (widget),
+                                                                  &attributes, attributes_mask);
          gdk_window_set_user_data (tree_view->priv->drag_highlight_window, GTK_WIDGET (tree_view));
 
          mask = gdk_pixmap_new (tree_view->priv->drag_highlight_window, width, height, 1);
@@ -2368,10 +2460,10 @@ gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
              else
                j--;
            }
-         gdk_gc_destroy (gc);
+         g_object_unref (gc);
          gdk_window_shape_combine_mask (tree_view->priv->drag_highlight_window,
                                         mask, 0, 0);
-         if (mask) gdk_pixmap_unref (mask);
+         if (mask) g_object_unref (mask);
        }
 
       tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_ARROW;
@@ -2405,7 +2497,11 @@ gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
          tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
        {
          if (tree_view->priv->drag_highlight_window)
-           gdk_window_destroy (tree_view->priv->drag_highlight_window);
+           {
+             gdk_window_set_user_data (tree_view->priv->drag_highlight_window,
+                                       NULL);
+             gdk_window_destroy (tree_view->priv->drag_highlight_window);
+           }
 
          attributes.window_type = GDK_WINDOW_TEMP;
          attributes.wclass = GDK_INPUT_OUTPUT;
@@ -2440,10 +2536,10 @@ gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
              gdk_draw_line (mask, gc, k, height, k, height - tree_view->priv->expander_size + j);
              j--;
            }
-         gdk_gc_destroy (gc);
+         g_object_unref (gc);
          gdk_window_shape_combine_mask (tree_view->priv->drag_highlight_window,
                                         mask, 0, 0);
-         if (mask) gdk_pixmap_unref (mask);
+         if (mask) g_object_unref (mask);
        }
 
       tree_view->priv->drag_column_window_state = arrow_type;
@@ -2727,7 +2823,9 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
   GList *last_column;
   gint vertical_separator;
   gint horizontal_separator;
+  gint focus_line_width;
   gboolean allow_rules;
+  gboolean has_special_cell;
 
   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
 
@@ -2737,6 +2835,7 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                        "horizontal_separator", &horizontal_separator,
                        "vertical_separator", &vertical_separator,
                        "allow_rules", &allow_rules,
+                       "focus-line-width", &focus_line_width,
                        NULL);
 
   if (tree_view->priv->tree == NULL)
@@ -2822,6 +2921,8 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
 
       parity = _gtk_rbtree_node_find_parity (tree, node);
 
+      has_special_cell = gtk_tree_view_has_special_cell (tree_view);
+
       for (list = tree_view->priv->columns; list; list = list->next)
        {
          GtkTreeViewColumn *column = list->data;
@@ -2843,13 +2944,6 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
           else
             flags &= ~GTK_CELL_RENDERER_SORTED;
 
-         gtk_tree_view_column_cell_set_cell_data (column,
-                                                  tree_view->priv->model,
-                                                  &iter,
-                                                  GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
-                                                  node->children?TRUE:FALSE);
-
-
          background_area.x = cell_offset;
          background_area.width = column->width;
 
@@ -2859,6 +2953,18 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
           cell_area.height -= vertical_separator;
          cell_area.width -= horizontal_separator;
 
+         if (gdk_region_rect_in (event->region, &background_area) == GDK_OVERLAP_RECTANGLE_OUT)
+           {
+             cell_offset += column->width;
+             continue;
+           }
+
+         gtk_tree_view_column_cell_set_cell_data (column,
+                                                  tree_view->priv->model,
+                                                  &iter,
+                                                  GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
+                                                  node->children?TRUE:FALSE);
+
           /* Select the detail for drawing the cell.  relevant
            * factors are parity, sortedness, and whether to
            * display rules.
@@ -2954,7 +3060,7 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                                                 &event->area,
                                                 flags);
            }
-         if (node == cursor &&
+         if (node == cursor && has_special_cell &&
              ((column == tree_view->priv->focus_column &&
                GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS) &&
                GTK_WIDGET_HAS_FOCUS (widget)) ||
@@ -2970,7 +3076,6 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
          cell_offset += column->width;
        }
 
-
       if (node == drag_highlight)
         {
           /* Draw indicator for the drop
@@ -3027,6 +3132,35 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
             }
         }
 
+      /* draw the big row-spanning focus rectangle, if needed */
+      if (!has_special_cell && node == cursor &&
+         GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS) &&
+         GTK_WIDGET_HAS_FOCUS (widget))
+        {
+         gint width;
+         GtkStateType focus_rect_state;
+
+         focus_rect_state =
+           flags & GTK_CELL_RENDERER_SELECTED ? GTK_STATE_SELECTED :
+           (flags & GTK_CELL_RENDERER_PRELIT ? GTK_STATE_PRELIGHT :
+            (flags & GTK_CELL_RENDERER_INSENSITIVE ? GTK_STATE_INSENSITIVE :
+             GTK_STATE_NORMAL));
+
+         gdk_drawable_get_size (tree_view->priv->bin_window,
+                                &width, NULL);
+         gtk_paint_focus (widget->style,
+                          tree_view->priv->bin_window,
+                          focus_rect_state,
+                          NULL,
+                          widget,
+                          "treeview",
+                          0,
+                          BACKGROUND_FIRST_PIXEL (tree_view, tree, node),
+                          width,
+                          MAX (BACKGROUND_HEIGHT (node),
+                               tree_view->priv->expander_size));
+       }
+
       y_offset += max_height;
       if (node->children)
        {
@@ -3582,7 +3716,7 @@ gtk_tree_view_leave_notify (GtkWidget        *widget,
 
   ensure_unprelighted (tree_view);
 
-return TRUE;
+  return TRUE;
 }
 
 
@@ -3595,8 +3729,8 @@ gtk_tree_view_focus_out (GtkWidget     *widget,
   gtk_widget_queue_draw (widget);
 
   /* destroy interactive search dialog */
-  search_dialog = gtk_object_get_data (GTK_OBJECT (widget),
-                                      GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
+  search_dialog = g_object_get_data (G_OBJECT (widget),
+                                    GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
   if (search_dialog)
     gtk_tree_view_search_dialog_destroy (search_dialog, GTK_TREE_VIEW (widget));
 
@@ -3651,6 +3785,7 @@ validate_row (GtkTreeView *tree_view,
       gtk_tree_view_column_cell_get_size (column,
                                          NULL, NULL, NULL,
                                          &tmp_width, &tmp_height);
+
       height = MAX (height, tmp_height);
       height = MAX (height, tree_view->priv->expander_size);
 
@@ -3689,7 +3824,7 @@ validate_visible_area (GtkTreeView *tree_view)
   GtkRBNode *node = NULL;
   gboolean need_redraw = FALSE;
   gboolean size_changed = FALSE;
-  gboolean modify_dy = FALSE;
+  gboolean update_dy = FALSE;
   gint total_height;
   gint area_above = 0;
   gint area_below = 0;
@@ -3699,10 +3834,13 @@ validate_visible_area (GtkTreeView *tree_view)
 
   if (! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID) &&
       tree_view->priv->scroll_to_path == NULL)
-      return;
+    return;
 
   total_height = GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
 
+  if (total_height == 0)
+    return;
+
   /* First, we check to see if we need to scroll anywhere
    */
   if (tree_view->priv->scroll_to_path)
@@ -3729,10 +3867,11 @@ validate_visible_area (GtkTreeView *tree_view)
            }
          else
            {
-             /* FIXME: */
-             g_warning ("non use_align not implemented yet");
-             gtk_tree_path_free (path);
-             path = NULL;
+             /* FIXME: temporary solution, just validate a complete height
+              * and all will be fine...
+              */
+             area_above = total_height;
+             area_below = total_height;
            }
        }
       else
@@ -3887,11 +4026,35 @@ validate_visible_area (GtkTreeView *tree_view)
            size_changed = TRUE;
        }
       area_above -= MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
-      modify_dy = TRUE;
+      update_dy = TRUE;
+    }
+
+  if (size_changed)
+    {
+      GtkRequisition requisition;
+      /* We temporarily guess a size, under the assumption that it will be the
+       * same when we get our next size_allocate.  If we don't do this, we'll be
+       * in an inconsistent state if we call top_row_to_dy. */
+      tree_view->priv->hadjustment->upper = MAX (tree_view->priv->hadjustment->upper, (gfloat)requisition.width);
+      tree_view->priv->vadjustment->upper = MAX (tree_view->priv->vadjustment->upper, (gfloat)requisition.height);
+      gtk_adjustment_changed (tree_view->priv->hadjustment);
+      gtk_adjustment_changed (tree_view->priv->vadjustment);
+      gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+    }
+
+  /* if we scroll at all, always update dy and kill the top_row */
+  if (tree_view->priv->scroll_to_path)
+    {
+      update_dy = TRUE;
+      if (tree_view->priv->top_row)
+        {
+         gtk_tree_row_reference_free (tree_view->priv->top_row);
+         tree_view->priv->top_row = NULL;
+       }
     }
 
   /* if we walk backwards at all, then we need to reset our dy. */
-  if (modify_dy)
+  if (update_dy)
     {
       gint dy;
       if (node != NULL)
@@ -3919,8 +4082,6 @@ validate_visible_area (GtkTreeView *tree_view)
     {
       tree_view->priv->scroll_to_column = NULL;
     }
-  if (size_changed)
-    gtk_widget_queue_resize (GTK_WIDGET (tree_view));
   if (need_redraw)
     gtk_widget_queue_draw (GTK_WIDGET (tree_view));
 }
@@ -3949,10 +4110,8 @@ do_validate_rows (GtkTreeView *tree_view)
   g_assert (tree_view);
 
   if (tree_view->priv->tree == NULL)
-    {
-      tree_view->priv->validate_rows_timer = 0;
       return FALSE;
-    }
+
   do
     {
       if (! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
@@ -4039,20 +4198,46 @@ do_validate_rows (GtkTreeView *tree_view)
    }
   
  done:
+  if (validated_area)
+    {
+      GtkRequisition requisition;
+      /* We temporarily guess a size, under the assumption that it will be the
+       * same when we get our next size_allocate.  If we don't do this, we'll be
+       * in an inconsistent state when we call top_row_to_dy. */
+      gtk_widget_size_request (GTK_WIDGET (tree_view), &requisition);
+      tree_view->priv->hadjustment->upper = MAX (tree_view->priv->hadjustment->upper, (gfloat)requisition.width);
+      tree_view->priv->vadjustment->upper = MAX (tree_view->priv->vadjustment->upper, (gfloat)requisition.height);
+      gtk_adjustment_changed (tree_view->priv->hadjustment);
+      gtk_adjustment_changed (tree_view->priv->vadjustment);
+      gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+    }
+
   if (gtk_tree_row_reference_valid (tree_view->priv->top_row))
     gtk_tree_view_top_row_to_dy (tree_view);
   else
     gtk_tree_view_dy_to_top_row (tree_view);
 
   if (path) gtk_tree_path_free (path);
-  if (validated_area)
-    gtk_widget_queue_resize (GTK_WIDGET (tree_view));
-  if (! retval)
-    tree_view->priv->validate_rows_timer = 0;
 
   return retval;
 }
 
+static gboolean
+validate_rows (GtkTreeView *tree_view)
+{
+  gboolean retval;
+  
+  retval = do_validate_rows (tree_view);
+  
+  if (! retval && tree_view->priv->validate_rows_timer)
+    {
+      g_source_remove (tree_view->priv->validate_rows_timer);
+      tree_view->priv->validate_rows_timer = 0;
+    }
+  
+  return retval;
+}
+
 static gboolean
 validate_rows_handler (GtkTreeView *tree_view)
 {
@@ -4061,7 +4246,9 @@ validate_rows_handler (GtkTreeView *tree_view)
   GDK_THREADS_ENTER ();
 
   retval = do_validate_rows (tree_view);
-  
+  if (! retval)
+    tree_view->priv->validate_rows_timer = 0;
+
   GDK_THREADS_LEAVE ();
 
   return retval;
@@ -4214,9 +4401,10 @@ gtk_tree_view_top_row_to_dy (GtkTreeView *tree_view)
   tree_view->priv->dy = _gtk_rbtree_node_find_offset (tree, node);
   tree_view->priv->dy += tree_view->priv->top_row_dy;
   gtk_adjustment_set_value (tree_view->priv->vadjustment,
-                           tree_view->priv->dy);
+                           (gdouble)tree_view->priv->dy);
 }
 
+
 void
 _gtk_tree_view_install_mark_rows_col_dirty (GtkTreeView *tree_view)
 {
@@ -4225,6 +4413,28 @@ _gtk_tree_view_install_mark_rows_col_dirty (GtkTreeView *tree_view)
   install_presize_handler (tree_view);
 }
 
+/*
+ * This function works synchronously (due to the while (validate_rows...)
+ * loop).
+ *
+ * There was a check for column_type != GTK_TREE_VIEW_COLUMN_AUTOSIZE
+ * here. You now need to check that yourself.
+ */
+void
+_gtk_tree_view_column_autosize (GtkTreeView *tree_view,
+                               GtkTreeViewColumn *column)
+{
+  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+  g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (column));
+
+  _gtk_tree_view_column_cell_set_dirty (column, FALSE);
+
+  do_presize_handler (tree_view);
+  while (validate_rows (tree_view));
+
+  gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+}
+
 /* Drag-and-drop */
 
 static void
@@ -4424,7 +4634,7 @@ check_model_dnd (GtkTreeModel *model,
                  "on GtkTreeView when using models that don't support "
                  "the %s interface and enabling drag-and-drop. The simplest way to do this "
                  "is to connect to '%s' and call "
-                 "gtk_signal_emit_stop_by_name() in your signal handler to prevent "
+                 "g_signal_stop_emission_by_name() in your signal handler to prevent "
                  "the default handler from running. Look at the source code "
                  "for the default handler in gtktreeview.c to get an idea what "
                  "your handler should do. (gtktreeview.c is in the GTK source "
@@ -4739,7 +4949,7 @@ gtk_tree_view_maybe_begin_dragging_row (GtkTreeView      *tree_view,
                               tree_view->priv->press_start_x + 1,
                               cell_y + 1);
 
-    gdk_pixmap_unref (row_pix);
+    g_object_unref (row_pix);
   }
 
   set_source_row (context, model, path);
@@ -5170,6 +5380,25 @@ gtk_tree_view_forall (GtkContainer *container,
     }
 }
 
+/* Returns TRUE if the treeview contains no "special" (editable or activatable)
+ * cells. If so we draw one big row-spanning focus rectangle.
+ */
+static gboolean
+gtk_tree_view_has_special_cell (GtkTreeView *tree_view)
+{
+  GList *list;
+
+  for (list = tree_view->priv->columns; list; list = list->next)
+    {
+      if (!((GtkTreeViewColumn *)list->data)->visible)
+       continue;
+      if (_gtk_tree_view_column_count_special_cells (list->data))
+       return TRUE;
+    }
+
+  return FALSE;
+}
+
 /* Returns TRUE if the focus is within the headers, after the focus operation is
  * done
  */
@@ -5484,37 +5713,41 @@ gtk_tree_view_set_adjustments (GtkTreeView   *tree_view,
 
   if (tree_view->priv->hadjustment && (tree_view->priv->hadjustment != hadj))
     {
-      gtk_signal_disconnect_by_data (GTK_OBJECT (tree_view->priv->hadjustment), tree_view);
-      gtk_object_unref (GTK_OBJECT (tree_view->priv->hadjustment));
+      g_signal_handlers_disconnect_by_func (tree_view->priv->hadjustment,
+                                           gtk_tree_view_adjustment_changed,
+                                           tree_view);
+      g_object_unref (tree_view->priv->hadjustment);
     }
 
   if (tree_view->priv->vadjustment && (tree_view->priv->vadjustment != vadj))
     {
-      gtk_signal_disconnect_by_data (GTK_OBJECT (tree_view->priv->vadjustment), tree_view);
-      gtk_object_unref (GTK_OBJECT (tree_view->priv->vadjustment));
+      g_signal_handlers_disconnect_by_func (tree_view->priv->vadjustment,
+                                           gtk_tree_view_adjustment_changed,
+                                           tree_view);
+      g_object_unref (tree_view->priv->vadjustment);
     }
 
   if (tree_view->priv->hadjustment != hadj)
     {
       tree_view->priv->hadjustment = hadj;
-      gtk_object_ref (GTK_OBJECT (tree_view->priv->hadjustment));
+      g_object_ref (tree_view->priv->hadjustment);
       gtk_object_sink (GTK_OBJECT (tree_view->priv->hadjustment));
 
-      gtk_signal_connect (GTK_OBJECT (tree_view->priv->hadjustment), "value_changed",
-                         (GtkSignalFunc) gtk_tree_view_adjustment_changed,
-                         tree_view);
+      g_signal_connect (tree_view->priv->hadjustment, "value_changed",
+                       G_CALLBACK (gtk_tree_view_adjustment_changed),
+                       tree_view);
       need_adjust = TRUE;
     }
 
   if (tree_view->priv->vadjustment != vadj)
     {
       tree_view->priv->vadjustment = vadj;
-      gtk_object_ref (GTK_OBJECT (tree_view->priv->vadjustment));
+      g_object_ref (tree_view->priv->vadjustment);
       gtk_object_sink (GTK_OBJECT (tree_view->priv->vadjustment));
 
-      gtk_signal_connect (GTK_OBJECT (tree_view->priv->vadjustment), "value_changed",
-                         (GtkSignalFunc) gtk_tree_view_adjustment_changed,
-                         tree_view);
+      g_signal_connect (tree_view->priv->vadjustment, "value_changed",
+                       G_CALLBACK (gtk_tree_view_adjustment_changed),
+                       tree_view);
       need_adjust = TRUE;
     }
 
@@ -5655,6 +5888,9 @@ gtk_tree_view_row_changed (GtkTreeModel *model,
      */
     return;
 
+  if (tree_view->priv->edited_column)
+    gtk_tree_view_stop_editing (tree_view, TRUE);
+
   gtk_widget_style_get (GTK_WIDGET (data), "vertical_separator", &vertical_separator, NULL);
 
   if (path == NULL)
@@ -5944,7 +6180,7 @@ gtk_tree_view_row_deleted (GtkTreeModel *model,
   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
 
   if (selection_changed)
-    g_signal_emit_by_name (G_OBJECT (tree_view->priv->selection), "changed");
+    g_signal_emit_by_name (tree_view->priv->selection, "changed");
 }
 
 
@@ -6260,28 +6496,20 @@ gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view,
                                  GtkRBTree   *tree,
                                  GtkRBNode   *node)
 {
-  GdkRectangle cell_rect;
-  GdkRectangle vis_rect;
-  gint dest_y;
+  GtkTreePath *path = NULL;
 
   /* We process updates because we want to clear old selected items when we scroll.
    * if this is removed, we get a "selection streak" at the bottom. */
   if (!GTK_WIDGET_REALIZED (tree_view))
     return;
 
-  gdk_window_process_updates (tree_view->priv->bin_window, TRUE);
-  cell_rect.y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, BACKGROUND_FIRST_PIXEL (tree_view, tree, node));
-  cell_rect.height = BACKGROUND_HEIGHT (node);
-  gtk_tree_view_get_visible_rect (tree_view, &vis_rect);
-
-  dest_y = vis_rect.y;
-
-  if (cell_rect.y + cell_rect.height > vis_rect.y + vis_rect.height)
-    dest_y = cell_rect.y + cell_rect.height - vis_rect.height;
-  if (cell_rect.y < vis_rect.y)
-    dest_y = cell_rect.y;
+  path = _gtk_tree_view_find_path (tree_view, tree, node);
 
-  gtk_tree_view_scroll_to_point (tree_view, -1, dest_y);
+  if (path)
+    {
+      gtk_tree_view_scroll_to_cell (tree_view, path, NULL, FALSE, 0.0, 0.0);
+      gtk_tree_path_free (path);
+    }
 }
 
 static void
@@ -6425,26 +6653,26 @@ gtk_tree_view_add_move_binding (GtkBindingSet  *binding_set,
   
   gtk_binding_entry_add_signal (binding_set, keyval, modmask,
                                 "move_cursor", 2,
-                                GTK_TYPE_ENUM, step,
-                                GTK_TYPE_INT, count);
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count);
 
   gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
                                 "move_cursor", 2,
-                                GTK_TYPE_ENUM, step,
-                                GTK_TYPE_INT, count);
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count);
 
   if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
    return;
 
   gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
                                 "move_cursor", 2,
-                                GTK_TYPE_ENUM, step,
-                                GTK_TYPE_INT, count);
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count);
 
   gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK,
                                 "move_cursor", 2,
-                                GTK_TYPE_ENUM, step,
-                                GTK_TYPE_INT, count);
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count);
 }
 
 static gint
@@ -6470,7 +6698,9 @@ gtk_tree_view_unref_tree_helper (GtkTreeModel *model,
          while (new_node && new_node->left != new_tree->nil)
            new_node = new_node->left;
 
-         g_return_val_if_fail (gtk_tree_model_iter_children (model, &child, iter), FALSE);
+         if (!gtk_tree_model_iter_children (model, &child, iter))
+           return FALSE;
+
          retval = retval || gtk_tree_view_unref_tree_helper (model, &child, new_tree, new_node);
        }
 
@@ -6602,7 +6832,7 @@ gtk_tree_view_set_column_drag_info (GtkTreeView       *tree_view,
        {
          gint width;
 
-         gdk_window_get_size (tree_view->priv->header_window, &width, NULL);
+         gdk_drawable_get_size (tree_view->priv->header_window, &width, NULL);
          reorder->right_align = width + TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER (tree_view);
        }
     }
@@ -6612,9 +6842,11 @@ void
 _gtk_tree_view_column_start_drag (GtkTreeView       *tree_view,
                                  GtkTreeViewColumn *column)
 {
-  GdkEvent send_event;
+  GdkEvent *send_event;
   GtkAllocation allocation;
   gint x, y, width, height;
+  GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (tree_view));
+  GdkDisplay *display = gdk_screen_get_display (screen);
 
   g_return_if_fail (tree_view->priv->column_drag_info == NULL);
 
@@ -6641,34 +6873,36 @@ _gtk_tree_view_column_start_drag (GtkTreeView       *tree_view,
       gdk_window_set_user_data (tree_view->priv->drag_window, GTK_WIDGET (tree_view));
     }
 
-  gdk_pointer_ungrab (GDK_CURRENT_TIME);
-  gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+  gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
+  gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
 
   gtk_grab_remove (column->button);
 
-  send_event.crossing.type = GDK_LEAVE_NOTIFY;
-  send_event.crossing.send_event = TRUE;
-  send_event.crossing.window = column->button->window;
-  send_event.crossing.subwindow = NULL;
-  send_event.crossing.detail = GDK_NOTIFY_ANCESTOR;
-  send_event.crossing.time = GDK_CURRENT_TIME;
-
-  gtk_propagate_event (column->button, &send_event);
-
-  send_event.button.type = GDK_BUTTON_RELEASE;
-  send_event.button.window = GDK_ROOT_PARENT ();
-  send_event.button.send_event = TRUE;
-  send_event.button.time = GDK_CURRENT_TIME;
-  send_event.button.x = -1;
-  send_event.button.y = -1;
-  send_event.button.axes = NULL;
-  send_event.button.state = 0;
-  send_event.button.button = 1;
-  send_event.button.device = gdk_device_get_core_pointer ();
-  send_event.button.x_root = 0;
-  send_event.button.y_root = 0;
-
-  gtk_propagate_event (column->button, &send_event);
+  send_event = gdk_event_new (GDK_LEAVE_NOTIFY);
+  send_event->crossing.send_event = TRUE;
+  send_event->crossing.window = g_object_ref (column->button->window);
+  send_event->crossing.subwindow = NULL;
+  send_event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+  send_event->crossing.time = GDK_CURRENT_TIME;
+
+  gtk_propagate_event (column->button, send_event);
+  gdk_event_free (send_event);
+
+  send_event = gdk_event_new (GDK_BUTTON_RELEASE);
+  send_event->button.window = g_object_ref (gdk_screen_get_root_window (screen));
+  send_event->button.send_event = TRUE;
+  send_event->button.time = GDK_CURRENT_TIME;
+  send_event->button.x = -1;
+  send_event->button.y = -1;
+  send_event->button.axes = NULL;
+  send_event->button.state = 0;
+  send_event->button.button = 1;
+  send_event->button.device = gdk_display_get_core_pointer (display);
+  send_event->button.x_root = 0;
+  send_event->button.y_root = 0;
+
+  gtk_propagate_event (column->button, send_event);
+  gdk_event_free (send_event);
 
   gdk_window_move_resize (tree_view->priv->drag_window,
                          column->button->allocation.x,
@@ -6693,7 +6927,7 @@ _gtk_tree_view_column_start_drag (GtkTreeView       *tree_view,
   gdk_window_show (tree_view->priv->drag_window);
 
   gdk_window_get_origin (tree_view->priv->header_window, &x, &y);
-  gdk_window_get_size (tree_view->priv->header_window, &width, &height);
+  gdk_drawable_get_size (tree_view->priv->header_window, &width, &height);
 
   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
   while (gtk_events_pending ())
@@ -7050,7 +7284,9 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
                                               &iter,
                                               GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT),
                                               cursor_node->children?TRUE:FALSE);
-      if (_gtk_tree_view_column_cell_focus (column, count))
+      if (_gtk_tree_view_column_cell_focus (column, count,
+                                           list->prev?TRUE:FALSE,
+                                           list->next?TRUE:FALSE))
        {
          tree_view->priv->focus_column = column;
          found_column = TRUE;
@@ -7065,11 +7301,12 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
 
   if (found_column)
     {
-      _gtk_tree_view_queue_draw_node (tree_view,
-                                    cursor_tree,
-                                    cursor_node,
-                                    NULL);
-      g_signal_emit (G_OBJECT (tree_view), tree_view_signals[CURSOR_CHANGED], 0);
+      if (!gtk_tree_view_has_special_cell (tree_view))
+       _gtk_tree_view_queue_draw_node (tree_view,
+                                       cursor_tree,
+                                       cursor_node,
+                                       NULL);
+      g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
     }
   gtk_tree_view_clamp_column_visible (tree_view, tree_view->priv->focus_column);
 }
@@ -7320,13 +7557,38 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
   gtk_tree_path_free (cursor_path);
 }
 
+/* Cut and paste from gtkwindow.c */
+static void
+send_focus_change (GtkWidget *widget,
+                  gboolean   in)
+{
+  GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
+
+  g_object_ref (widget);
+   
+ if (in)
+    GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
+  else
+    GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
+
+  fevent->focus_change.type = GDK_FOCUS_CHANGE;
+  fevent->focus_change.window = g_object_ref (widget->window);
+  fevent->focus_change.in = in;
+  
+  gtk_widget_event (widget, fevent);
+  
+  g_object_notify (G_OBJECT (widget), "has_focus");
+
+  g_object_unref (widget);
+  gdk_event_free (fevent);
+}
+
 static void
 gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view)
 {
   GtkWidget *window;
   GtkWidget *entry;
   GtkWidget *search_dialog;
-  GdkEventFocus focus_event;
 
   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
     return;
@@ -7345,22 +7607,23 @@ gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view)
   gtk_window_set_title (GTK_WINDOW (window), "search dialog");
   gtk_container_set_border_width (GTK_CONTAINER (window), 3);
   gtk_window_set_modal (GTK_WINDOW (window), TRUE);
-  g_signal_connect (G_OBJECT (window), "delete_event",
+  g_signal_connect (window, "delete_event",
                    G_CALLBACK (gtk_tree_view_search_delete_event),
                    tree_view);
-  g_signal_connect (G_OBJECT (window), "key_press_event",
+  g_signal_connect (window, "key_press_event",
                    G_CALLBACK (gtk_tree_view_search_key_press_event),
                    tree_view);
-  g_signal_connect (G_OBJECT (window), "button_press_event",
+  g_signal_connect (window, "button_press_event",
                    G_CALLBACK (gtk_tree_view_search_button_press_event),
                    tree_view);
 
   /* add entry */
   entry = gtk_entry_new ();
   gtk_widget_show (entry);
-  g_signal_connect (G_OBJECT (entry), "changed",
-                   G_CALLBACK (gtk_tree_view_search_init), tree_view);
-  g_signal_connect (G_OBJECT (entry), "populate_popup",
+  g_signal_connect (entry, "changed",
+                   G_CALLBACK (gtk_tree_view_search_init),
+                   tree_view);
+  g_signal_connect (entry, "populate_popup",
                    G_CALLBACK (gtk_tree_view_search_disable_popdown),
                    tree_view);
   gtk_container_add (GTK_CONTAINER (window), entry);
@@ -7371,9 +7634,7 @@ gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view)
   gtk_widget_grab_focus (entry);
 
   /* send focus-in event */
-  focus_event.type = GDK_FOCUS_CHANGE;
-  focus_event.in = TRUE;
-  gtk_widget_event (entry, (GdkEvent *) &focus_event);
+  send_focus_change (entry, TRUE);
 
   /* position window */
 
@@ -7462,11 +7723,7 @@ gtk_tree_view_adjustment_changed (GtkAdjustment *adjustment,
 GtkWidget *
 gtk_tree_view_new (void)
 {
-  GtkTreeView *tree_view;
-
-  tree_view = GTK_TREE_VIEW (gtk_type_new (gtk_tree_view_get_type ()));
-
-  return GTK_WIDGET (tree_view);
+  return g_object_new (GTK_TYPE_TREE_VIEW, NULL);
 }
 
 /**
@@ -7480,12 +7737,7 @@ gtk_tree_view_new (void)
 GtkWidget *
 gtk_tree_view_new_with_model (GtkTreeModel *model)
 {
-  GtkTreeView *tree_view;
-
-  tree_view = GTK_TREE_VIEW (gtk_type_new (gtk_tree_view_get_type ()));
-  gtk_tree_view_set_model (tree_view, model);
-
-  return GTK_WIDGET (tree_view);
+  return g_object_new (GTK_TYPE_TREE_VIEW, "model", model, NULL);
 }
 
 /* Public Accessors
@@ -7528,18 +7780,30 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
 
   if (tree_view->priv->model)
     {
+      GList *tmplist = tree_view->priv->columns;
+
       gtk_tree_view_unref_and_check_selection_tree (tree_view, tree_view->priv->tree);
 
-      g_signal_handlers_disconnect_by_func (G_OBJECT (tree_view->priv->model),
-                                           (gpointer) gtk_tree_view_row_changed, tree_view);
-      g_signal_handlers_disconnect_by_func (G_OBJECT (tree_view->priv->model),
-                                           (gpointer) gtk_tree_view_row_inserted, tree_view);
-      g_signal_handlers_disconnect_by_func (G_OBJECT (tree_view->priv->model),
-                                           (gpointer) gtk_tree_view_row_has_child_toggled, tree_view);
-      g_signal_handlers_disconnect_by_func (G_OBJECT (tree_view->priv->model),
-                                           (gpointer) gtk_tree_view_row_deleted, tree_view);
-      g_signal_handlers_disconnect_by_func (G_OBJECT (tree_view->priv->model),
-                                           (gpointer) gtk_tree_view_rows_reordered, tree_view);
+      g_signal_handlers_disconnect_by_func (tree_view->priv->model,
+                                           gtk_tree_view_row_changed,
+                                           tree_view);
+      g_signal_handlers_disconnect_by_func (tree_view->priv->model,
+                                           gtk_tree_view_row_inserted,
+                                           tree_view);
+      g_signal_handlers_disconnect_by_func (tree_view->priv->model,
+                                           gtk_tree_view_row_has_child_toggled,
+                                           tree_view);
+      g_signal_handlers_disconnect_by_func (tree_view->priv->model,
+                                           gtk_tree_view_row_deleted,
+                                           tree_view);
+      g_signal_handlers_disconnect_by_func (tree_view->priv->model,
+                                           gtk_tree_view_rows_reordered,
+                                           tree_view);
+
+      for (; tmplist; tmplist = tmplist->next)
+       _gtk_tree_view_column_unset_model (tmplist->data,
+                                          tree_view->priv->model);
+
       if (tree_view->priv->tree)
        {
          _gtk_rbtree_free (tree_view->priv->tree);
@@ -7793,31 +8057,13 @@ gtk_tree_view_set_headers_visible (GtkTreeView *tree_view,
   tree_view->priv->vadjustment->page_increment = (GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view)) / 2;
   tree_view->priv->vadjustment->lower = 0;
   tree_view->priv->vadjustment->upper = tree_view->priv->height;
-  gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->vadjustment), "changed");
+  gtk_adjustment_changed (tree_view->priv->vadjustment);
 
   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
 
   g_object_notify (G_OBJECT (tree_view), "headers_visible");
 }
 
-static void
-gtk_tree_view_column_autosize (GtkTreeView *tree_view,
-                              GtkTreeViewColumn *column)
-{
-  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
-  g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (column));
-
-  if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
-    return;
-
-  _gtk_tree_view_column_cell_set_dirty (column, FALSE);
-
-  do_presize_handler (tree_view);
-  while (do_validate_rows (tree_view));
-
-  gtk_widget_queue_resize (GTK_WIDGET (tree_view));
-}
-
 /**
  * gtk_tree_view_columns_autosize:
  * @tree_view: A #GtkTreeView.
@@ -7992,8 +8238,8 @@ gtk_tree_view_remove_column (GtkTreeView       *tree_view,
       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
     }
 
-  g_object_unref (G_OBJECT (column));
-  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[COLUMNS_CHANGED], 0);
+  g_object_unref (column);
+  g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
 
   return tree_view->priv->n_columns;
 }
@@ -8018,7 +8264,7 @@ gtk_tree_view_insert_column (GtkTreeView       *tree_view,
   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
   g_return_val_if_fail (column->tree_view == NULL, -1);
 
-  g_object_ref (G_OBJECT (column));
+  g_object_ref (column);
   gtk_object_sink (GTK_OBJECT (column));
 
   if (tree_view->priv->n_columns == 0 &&
@@ -8049,7 +8295,7 @@ gtk_tree_view_insert_column (GtkTreeView       *tree_view,
       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
     }
 
-  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[COLUMNS_CHANGED], 0);
+  g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
 
   return tree_view->priv->n_columns;
 }
@@ -8242,7 +8488,7 @@ gtk_tree_view_move_column_after (GtkTreeView       *tree_view,
       gtk_tree_view_size_allocate_columns (GTK_WIDGET (tree_view));
     }
 
-  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[COLUMNS_CHANGED], 0);
+  g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
 }
 
 /**
@@ -8505,7 +8751,7 @@ gtk_tree_view_row_activated (GtkTreeView       *tree_view,
 {
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
 
-  g_signal_emit (G_OBJECT(tree_view), tree_view_signals[ROW_ACTIVATED], 0, path, column);
+  g_signal_emit (tree_view, tree_view_signals[ROW_ACTIVATED], 0, path, column);
 }
 
 
@@ -8646,7 +8892,7 @@ gtk_tree_view_collapse_all (GtkTreeView *tree_view)
   GtkRBTree *tree;
   GtkRBNode *node;
   GtkTreePath *path;
-  guint *indices;
+  gint *indices;
 
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
 
@@ -8673,6 +8919,40 @@ gtk_tree_view_collapse_all (GtkTreeView *tree_view)
   gtk_tree_path_free (path);
 }
 
+/**
+ * gtk_tree_view_expand_to_path:
+ * @tree_view: A #GtkTreeView.
+ * @path: path to a row.
+ *
+ * Expands the row at @path. This will also expand all parent rows of
+ * @path as necessary.
+ **/
+void
+gtk_tree_view_expand_to_path (GtkTreeView *tree_view,
+                             GtkTreePath *path)
+{
+  gint i, depth;
+  gint *indices;
+  GtkTreePath *tmp;
+
+  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+  g_return_if_fail (path != NULL);
+
+  depth = gtk_tree_path_get_depth (path);
+  indices = gtk_tree_path_get_indices (path);
+
+  tmp = gtk_tree_path_new ();
+  g_return_if_fail (tmp != NULL);
+
+  for (i = 0; i < depth; i++)
+    {
+      gtk_tree_path_append_index (tmp, indices[i]);
+      gtk_tree_view_expand_row (tree_view, tmp, FALSE);
+    }
+
+  gtk_tree_path_free (tmp);
+}
+
 /* FIXME the bool return values for expand_row and collapse_row are
  * not analagous; they should be TRUE if the row had children and
  * was not already in the requested state.
@@ -8691,9 +8971,9 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
   GtkTreeIter temp;
   gboolean expand;
 
-
   if (node->children && !open_all)
-    return TRUE;
+    return FALSE;
+
   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
     return FALSE;
 
@@ -8701,7 +8981,37 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
   if (! gtk_tree_model_iter_has_child (tree_view->priv->model, &iter))
     return FALSE;
 
-  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[TEST_EXPAND_ROW], 0, &iter, path, &expand);
+
+   if (node->children && open_all)
+    {
+      gboolean retval = FALSE;
+      GtkTreePath *tmp_path = gtk_tree_path_copy (path);
+
+      gtk_tree_path_append_index (tmp_path, 0);
+      tree = node->children;
+      node = tree->root;
+      while (node->left != tree->nil)
+       node = node->left;
+      /* try to expand the children */
+      do
+        {
+         gboolean t;
+        t = gtk_tree_view_real_expand_row (tree_view, tmp_path, tree, node,
+                                           TRUE, animate);
+         if (t)
+           retval = TRUE;
+
+         gtk_tree_path_next (tmp_path);
+        node = _gtk_rbtree_next (tree, node);
+       }
+      while (node != NULL);
+
+      gtk_tree_path_free (tmp_path);
+
+      return retval;
+    }
+
+  g_signal_emit (tree_view, tree_view_signals[TEST_EXPAND_ROW], 0, &iter, path, &expand);
 
   if (expand)
     return FALSE;
@@ -8743,7 +9053,7 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
 
   install_presize_handler (tree_view);
 
-  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[ROW_EXPANDED], 0, &iter, path);
+  g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
   return TRUE;
 }
 
@@ -8794,13 +9104,14 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
   gboolean collapse;
   gint x, y;
   GList *list;
+  GdkDisplay *display;
 
   if (node->children == NULL)
     return FALSE;
 
   gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
 
-  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[TEST_COLLAPSE_ROW], 0, &iter, path, &collapse);
+  g_signal_emit (tree_view, tree_view_signals[TEST_COLLAPSE_ROW], 0, &iter, path, &collapse);
 
   if (collapse)
     return FALSE;
@@ -8901,7 +9212,7 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
   if (gtk_tree_view_unref_and_check_selection_tree (tree_view, node->children))
     {
       _gtk_rbtree_remove (node->children);
-      g_signal_emit_by_name (G_OBJECT (tree_view->priv->selection), "changed", 0);
+      g_signal_emit_by_name (tree_view->priv->selection, "changed");
     }
   else
     _gtk_rbtree_remove (node->children);
@@ -8934,12 +9245,13 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
     }
 
-  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[ROW_COLLAPSED], 0, &iter, path);
+  g_signal_emit (tree_view, tree_view_signals[ROW_COLLAPSED], 0, &iter, path);
 
   /* now that we've collapsed all rows, we want to try to set the prelight
    * again. To do this, we fake a motion event and send it to ourselves. */
 
-  if (gdk_window_at_pointer (&x, &y) == tree_view->priv->bin_window)
+  display = gdk_drawable_get_display (tree_view->priv->bin_window);
+  if (gdk_display_get_window_at_pointer (display, &x, &y) == tree_view->priv->bin_window)
     {
       GdkEventMotion event;
       event.window = tree_view->priv->bin_window;
@@ -9007,10 +9319,10 @@ gtk_tree_view_map_expanded_rows_helper (GtkTreeView            *tree_view,
     {
       if (node->children)
        {
+         (* func) (tree_view, path, user_data);
          gtk_tree_path_down (path);
          gtk_tree_view_map_expanded_rows_helper (tree_view, node->children, path, func, user_data);
          gtk_tree_path_up (path);
-         (* func) (tree_view, path, user_data);
        }
       gtk_tree_path_next (path);
       node = _gtk_rbtree_next (tree, node);
@@ -9181,7 +9493,7 @@ gtk_tree_view_real_set_cursor (GtkTreeView     *tree_view,
        }
     }
 
-  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[CURSOR_CHANGED], 0);
+  g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
 }
 
 /**
@@ -9236,11 +9548,47 @@ gtk_tree_view_set_cursor (GtkTreeView       *tree_view,
                          GtkTreePath       *path,
                          GtkTreeViewColumn *focus_column,
                          gboolean           start_editing)
+{
+  gtk_tree_view_set_cursor_on_cell (tree_view, path, focus_column,
+                                   NULL, start_editing);
+}
+
+/**
+ * gtk_tree_view_set_cursor_on_cell:
+ * @tree_view: A #GtkTreeView
+ * @path: A #GtkTreePath
+ * @focus_column: A #GtkTreeViewColumn, or %NULL
+ * @focus_cell: A #GtkCellRenderer, or %NULL
+ * @start_editing: %TRUE if the specified cell should start being edited.
+ *
+ * Sets the current keyboard focus to be at @path, and selects it.  This is
+ * useful when you want to focus the user's attention on a particular row.  If
+ * @focus_column is not %NULL, then focus is given to the column specified by
+ * it. If @focus_column and @focus_cell are not %NULL, and @focus_column
+ * contains 2 or more editable or activatable cells, then focus is given to
+ * the cell specified by @focus_cell. Additionally, if @focus_column is
+ * specified, and @start_editing is %TRUE, then editing should be started in
+ * the specified cell.  This function is often followed by
+ * @gtk_widget_grab_focus (@tree_view) in order to give keyboard focus to the
+ * widget.  Please note that editing can only happen when the widget is
+ * realized.
+ **/
+void
+gtk_tree_view_set_cursor_on_cell (GtkTreeView       *tree_view,
+                                 GtkTreePath       *path,
+                                 GtkTreeViewColumn *focus_column,
+                                 GtkCellRenderer   *focus_cell,
+                                 gboolean           start_editing)
 {
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
   g_return_if_fail (path != NULL);
   if (focus_column)
     g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (focus_column));
+  if (focus_cell)
+    {
+      g_return_if_fail (focus_column);
+      g_return_if_fail (GTK_IS_CELL_RENDERER (focus_cell));
+    }
 
   gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
 
@@ -9257,12 +9605,13 @@ gtk_tree_view_set_cursor (GtkTreeView       *tree_view,
          }
       g_return_if_fail (column_in_tree);
       tree_view->priv->focus_column = focus_column;
+      if (focus_cell)
+       gtk_tree_view_column_focus_cell (focus_column, focus_cell);
       if (start_editing)
        gtk_tree_view_start_editing (tree_view, path);
     }
 }
 
-
 /**
  * gtk_tree_view_get_bin_window:
  * @tree_view: A #GtkTreeView
@@ -9444,9 +9793,10 @@ gtk_tree_view_get_cell_area (GtkTreeView        *tree_view,
 
   if (path)
     {
+      gboolean ret = _gtk_tree_view_find_node (tree_view, path, &tree, &node);
+
       /* Get vertical coords */
-      if (!_gtk_tree_view_find_node (tree_view, path, &tree, &node) &&
-         tree == NULL)
+      if ((!ret && tree == NULL) || ret)
        return;
 
       rect->y = CELL_FIRST_PIXEL (tree_view, tree, node, vertical_separator);
@@ -9978,7 +10328,6 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
                                           &cell_area,
                                           &expose_area,
                                           0);
-
       cell_offset += column->width;
     }
 
@@ -10084,10 +10433,11 @@ gtk_tree_view_get_search_column (GtkTreeView *tree_view)
 /**
  * gtk_tree_view_set_search_column:
  * @tree_view: A #GtkTreeView
- * @column: the column to search in
+ * @column: the column of the model to search in
  *
- * Sets @column as the column where the interactive search code should search
- * in.  Additionally, turns on interactive searching.
+ * Sets @column as the column where the interactive search code should
+ * search in.  Additionally, turns on interactive searching. Note that
+ * @column refers to a column of the model.
  */
 void
 gtk_tree_view_set_search_column (GtkTreeView *tree_view,
@@ -10160,11 +10510,8 @@ gtk_tree_view_search_dialog_destroy (GtkWidget   *search_dialog,
 
   if (entry)
     {
-      GdkEventFocus focus_event;
-
-      focus_event.type = GDK_FOCUS_CHANGE;
-      focus_event.in = FALSE;
-      gtk_widget_event (GTK_WIDGET (entry), (GdkEvent *) &focus_event);
+      /* send focus-in event */
+      send_focus_change (GTK_WIDGET (entry), FALSE);
     }
 
   /* remove data from tree_view */
@@ -10189,25 +10536,26 @@ gtk_tree_view_search_position_func (GtkTreeView *tree_view,
   gint tree_x, tree_y;
   gint tree_width, tree_height;
   GdkWindow *tree_window = GTK_WIDGET (tree_view)->window;
+  GdkScreen *screen = gdk_drawable_get_screen (tree_window);
   GtkRequisition requisition;
 
   gtk_widget_realize (search_dialog);
 
   gdk_window_get_origin (tree_window, &tree_x, &tree_y);
-  gdk_window_get_size (tree_window,
-                      &tree_width,
-                      &tree_height);
+  gdk_drawable_get_size (tree_window,
+                        &tree_width,
+                        &tree_height);
   gtk_widget_size_request (search_dialog, &requisition);
 
-  if (tree_x + tree_width - requisition.width > gdk_screen_width ())
-    x = gdk_screen_width () - requisition.width;
+  if (tree_x + tree_width - requisition.width > gdk_screen_get_width (screen))
+    x = gdk_screen_get_width (screen) - requisition.width;
   else if (tree_x + tree_width - requisition.width < 0)
     x = 0;
   else
     x = tree_x + tree_width - requisition.width;
 
-  if (tree_y + tree_height > gdk_screen_height ())
-    y = gdk_screen_height () - requisition.height;
+  if (tree_y + tree_height > gdk_screen_get_height (screen))
+    y = gdk_screen_get_height (screen) - requisition.height;
   else if (tree_y + tree_height < 0) /* isn't really possible ... */
     y = 0;
   else
@@ -10224,7 +10572,7 @@ gtk_tree_view_search_disable_popdown (GtkEntry *entry,
   GtkTreeView *tree_view = (GtkTreeView *)data;
 
   tree_view->priv->disable_popdown = 1;
-  g_signal_connect (G_OBJECT (menu), "hide",
+  g_signal_connect (menu, "hide",
                    G_CALLBACK (gtk_tree_view_search_enable_popdown), data);
 }
 
@@ -10408,8 +10756,6 @@ gtk_tree_view_search_iter (GtkTreeModel     *model,
   GtkTreePath *path;
 
   GtkTreeView *tree_view = gtk_tree_selection_get_tree_view (selection);
-  GtkTreeViewColumn *column =
-    gtk_tree_view_get_column (tree_view, tree_view->priv->search_column);
 
   path = gtk_tree_model_get_path (model, iter);
   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
@@ -10421,8 +10767,8 @@ gtk_tree_view_search_iter (GtkTreeModel     *model,
           (*count)++;
           if (*count == n)
             {
-              gtk_tree_view_scroll_to_cell (tree_view, path, column,
-                                           TRUE, 0.5, 0.5);
+              gtk_tree_view_scroll_to_cell (tree_view, path, NULL,
+                                           TRUE, 0.5, 0.0);
               gtk_tree_selection_select_iter (selection, iter);
              gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
 
@@ -10502,9 +10848,6 @@ gtk_tree_view_search_iter (GtkTreeModel     *model,
     }
   while (1);
 
-  if (path)
-    gtk_tree_path_free (path);
-
   return FALSE;
 }
 
@@ -10624,11 +10967,22 @@ gtk_tree_view_start_editing (GtkTreeView *tree_view,
       retval = TRUE;
       if (editable_widget != NULL)
        {
+         gint left, right;
+         GdkRectangle area;
+         GtkCellRenderer *cell;
+
+         area = cell_area;
+         cell = _gtk_tree_view_column_get_edited_cell (tree_view->priv->focus_column);
+         _gtk_tree_view_column_get_neighbor_sizes (tree_view->priv->focus_column, cell, &left, &right);
+
+         area.x += left;
+         area.width -= right + left;
+
          gtk_tree_view_real_start_editing (tree_view,
                                            tree_view->priv->focus_column,
                                            cursor_path,
                                            editable_widget,
-                                           &cell_area,
+                                           &area,
                                            NULL,
                                            flags);
        }
@@ -10663,18 +11017,36 @@ gtk_tree_view_real_start_editing (GtkTreeView       *tree_view,
   gtk_cell_editable_start_editing (GTK_CELL_EDITABLE (cell_editable),
                                   (GdkEvent *)event);
   gtk_widget_grab_focus (GTK_WIDGET (cell_editable));
-  g_signal_connect (cell_editable, "remove_widget", G_CALLBACK (gtk_tree_view_remove_widget), tree_view);
+  g_signal_connect (cell_editable, "remove_widget",
+                   G_CALLBACK (gtk_tree_view_remove_widget), tree_view);
 }
 
 static void
 gtk_tree_view_stop_editing (GtkTreeView *tree_view,
                            gboolean     cancel_editing)
 {
+  GtkTreeViewColumn *column;
+
   if (tree_view->priv->edited_column == NULL)
     return;
 
+  /*
+   * This is very evil. We need to do this, because
+   * gtk_cell_editable_editing_done may trigger gtk_tree_view_row_changed
+   * later on. If gtk_tree_view_row_changed notices
+   * tree_view->priv->edited_column != NULL, it'll call
+   * gtk_tree_view_stop_editing again. Bad things will happen then.
+   *
+   * Please read that again if you intend to modify anything here.
+   */
+
+  column = tree_view->priv->edited_column;
+  tree_view->priv->edited_column = NULL;
+
   if (! cancel_editing)
-    gtk_cell_editable_editing_done (tree_view->priv->edited_column->editable_widget);
+    gtk_cell_editable_editing_done (column->editable_widget);
+
+  tree_view->priv->edited_column = column;
 
-  gtk_cell_editable_remove_widget (tree_view->priv->edited_column->editable_widget);
+  gtk_cell_editable_remove_widget (column->editable_widget);
 }