]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktreeview.c
get logic right, #66249
[~andy/gtk] / gtk / gtktreeview.c
index 78efc2509e9696511a88d9885739c8bbd744d077..ecf3e6b39351d41d1fd57b16b3404bf4faacdf5f 100644 (file)
@@ -25,6 +25,7 @@
 #include "gtkcellrenderer.h"
 #include "gtksignal.h"
 #include "gtkmain.h"
+#include "gtkmarshalers.h"
 #include "gtkbutton.h"
 #include "gtkalignment.h"
 #include "gtklabel.h"
 #include "gtkbindings.h"
 #include "gtkcontainer.h"
 #include "gtkentry.h"
+#include "gtktreemodelsort.h"
 
 #include <string.h>
 #include <gdk/gdkkeysyms.h>
 
-#if defined (GDK_WINDOWING_X11)
-#include "x11/gdkx.h"
-#elif defined (GDK_WINDOWING_WIN32)
-#include "win32/gdkwin32.h"
-#elif defined(GDK_WINDOWING_FB)
-#include "linux-fb/gdkfb.h"
-#elif defined (GDK_WINDOWING_NANOX)
-#include "nanox/gdkprivate-nanox.h"
-#endif
-
-
+#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_NUM_ROWS_PER_IDLE 50
 #define SCROLL_EDGE_SIZE 15
 #define EXPANDER_EXTRA_PADDING 4
 
  * The "cell" areas are the cell_area passed in to gtk_cell_renderer_render(),
  * i.e. just the cells, no spacing.
  */
-#define BACKGROUND_FIRST_PIXEL(tree_view,tree,node) (_gtk_rbtree_node_find_offset ((tree), (node)) + TREE_VIEW_HEADER_HEIGHT ((tree_view)))
-#define CELL_FIRST_PIXEL(tree_view,tree,node,separator) (BACKGROUND_FIRST_PIXEL (tree_view,tree,node) + separator/2)
 
 #define BACKGROUND_HEIGHT(node) (GTK_RBNODE_GET_HEIGHT (node))
 #define CELL_HEIGHT(node, separator) (BACKGROUND_HEIGHT (node) - separator);
 
-#define TREE_WINDOW_Y_TO_RBTREE_Y(tree_view,y) ((y) - TREE_VIEW_HEADER_HEIGHT (tree_view))
-#define RBTREE_Y_TO_TREE_WINDOW_Y(tree_view,y) ((y) + TREE_VIEW_HEADER_HEIGHT (tree_view))
+#define TREE_WINDOW_Y_TO_RBTREE_Y(tree_view,y) ((y) - TREE_VIEW_HEADER_HEIGHT (tree_view) + tree_view->priv->dy)
+#define RBTREE_Y_TO_TREE_WINDOW_Y(tree_view,y) ((y) + TREE_VIEW_HEADER_HEIGHT (tree_view) - tree_view->priv->dy)
+
+/* This is in Window coordinates */
+#define BACKGROUND_FIRST_PIXEL(tree_view,tree,node) (RBTREE_Y_TO_TREE_WINDOW_Y (tree_view, _gtk_rbtree_node_find_offset ((tree), (node))))
+#define CELL_FIRST_PIXEL(tree_view,tree,node,separator) (BACKGROUND_FIRST_PIXEL (tree_view,tree,node) + separator/2)
 
 
 typedef struct _GtkTreeViewChild GtkTreeViewChild;
@@ -73,6 +69,8 @@ struct _GtkTreeViewChild
   GtkWidget *widget;
   gint x;
   gint y;
+  gint width;
+  gint height;
 };
 
 
@@ -82,10 +80,8 @@ struct _TreeViewDragInfo
   GdkModifierType start_button_mask;
   GtkTargetList *source_target_list;
   GdkDragAction source_actions;
-  GClosure *row_draggable_closure;
 
   GtkTargetList *dest_target_list;
-  GClosure *location_droppable_closure;
 
   guint source_set : 1;
   guint dest_set : 1;
@@ -101,15 +97,14 @@ enum
   ROW_EXPANDED,
   ROW_COLLAPSED,
   COLUMNS_CHANGED,
-  BEGIN_EXTENDED_SELECTION,
-  END_EXTENDED_SELECTION,
-  BEGIN_FREE_MOTION,
-  END_FREE_MOTION,
+  CURSOR_CHANGED,
   MOVE_CURSOR,
+  SELECT_ALL,
   SELECT_CURSOR_ROW,
   TOGGLE_CURSOR_ROW,
   EXPAND_COLLAPSE_CURSOR_ROW,
   SELECT_CURSOR_PARENT,
+  START_INTERACTIVE_SEARCH,
   LAST_SIGNAL
 };
 
@@ -169,7 +164,6 @@ static gboolean gtk_tree_view_button_release       (GtkWidget        *widget,
                                                    GdkEventButton   *event);
 static void     gtk_tree_view_set_focus_child      (GtkContainer     *container,
                                                    GtkWidget        *child);
-static void     gtk_tree_view_draw_focus           (GtkWidget        *widget);
 static gint     gtk_tree_view_focus_in             (GtkWidget        *widget,
                                                    GdkEventFocus    *event);
 static gint     gtk_tree_view_focus_out            (GtkWidget        *widget,
@@ -224,43 +218,49 @@ static void     gtk_tree_view_drag_data_received (GtkWidget        *widget,
 static void gtk_tree_view_set_adjustments                 (GtkTreeView     *tree_view,
                                                           GtkAdjustment   *hadj,
                                                           GtkAdjustment   *vadj);
-static void gtk_tree_view_real_begin_extended_selection   (GtkTreeView     *tree_view);
-static void gtk_tree_view_real_end_extended_selection     (GtkTreeView     *tree_view);
-static void gtk_tree_view_real_begin_free_motion          (GtkTreeView     *tree_view);
-static void gtk_tree_view_real_end_free_motion            (GtkTreeView     *tree_view);
 static void gtk_tree_view_real_move_cursor                (GtkTreeView     *tree_view,
                                                           GtkMovementStep  step,
                                                           gint             count);
-static void gtk_tree_view_real_select_cursor_row          (GtkTreeView     *tree_view);
+static void gtk_tree_view_real_select_all                 (GtkTreeView     *tree_view);
+static void gtk_tree_view_real_select_cursor_row          (GtkTreeView     *tree_view,
+                                                          gboolean         start_editing);
 static void gtk_tree_view_real_toggle_cursor_row          (GtkTreeView     *tree_view);
 static void gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView     *tree_view,
                                                           gboolean         logical,
                                                           gboolean         expand,
                                                           gboolean         open_all);
 static void gtk_tree_view_real_select_cursor_parent       (GtkTreeView     *tree_view);
-static void gtk_tree_view_range_changed                   (GtkTreeModel    *model,
+static void gtk_tree_view_row_changed                     (GtkTreeModel    *model,
                                                           GtkTreePath     *path,
                                                           GtkTreeIter     *iter,
-                                                          GtkTreePath     *end_path,
-                                                          GtkTreeIter     *end_iter,
                                                           gpointer         data);
-static void gtk_tree_view_inserted                        (GtkTreeModel    *model,
+static void gtk_tree_view_row_inserted                    (GtkTreeModel    *model,
                                                           GtkTreePath     *path,
                                                           GtkTreeIter     *iter,
                                                           gpointer         data);
-static void gtk_tree_view_has_child_toggled               (GtkTreeModel    *model,
+static void gtk_tree_view_row_has_child_toggled           (GtkTreeModel    *model,
                                                           GtkTreePath     *path,
                                                           GtkTreeIter     *iter,
                                                           gpointer         data);
-static void gtk_tree_view_deleted                         (GtkTreeModel    *model,
+static void gtk_tree_view_row_deleted                     (GtkTreeModel    *model,
                                                           GtkTreePath     *path,
                                                           gpointer         data);
-static void gtk_tree_view_reordered                       (GtkTreeModel    *model,
+static void gtk_tree_view_rows_reordered                  (GtkTreeModel    *model,
                                                           GtkTreePath     *parent,
                                                           GtkTreeIter     *iter,
                                                           gint            *new_order,
                                                           gpointer         data);
 
+/* Incremental reflow */
+static gboolean validate_row             (GtkTreeView *tree_view,
+                                         GtkRBTree   *tree,
+                                         GtkRBNode   *node,
+                                         GtkTreeIter *iter,
+                                         GtkTreePath *path);
+static void     validate_visible_area    (GtkTreeView *tree_view);
+static gboolean validate_rows_handler    (GtkTreeView *tree_view);
+static gboolean presize_handler_callback (gpointer     data);
+static void     install_presize_handler  (GtkTreeView *tree_view);
 
 
 /* Internal functions */
@@ -290,29 +290,19 @@ static void     gtk_tree_view_draw_arrow                     (GtkTreeView
                                                              gint               x,
                                                              gint               y);
 static void     gtk_tree_view_get_arrow_xrange               (GtkTreeView       *tree_view,
+                                                             GtkRBTree         *tree,
                                                              gint              *x1,
                                                              gint              *x2);
 static gint     gtk_tree_view_new_column_width               (GtkTreeView       *tree_view,
                                                              gint               i,
                                                              gint              *x);
-static void     gtk_tree_view_ensure_scroll_timeout          (GtkTreeView       *tree_view,
-                                                             GFunc              func);
 static void     gtk_tree_view_adjustment_changed             (GtkAdjustment     *adjustment,
                                                              GtkTreeView       *tree_view);
-static gint     gtk_tree_view_insert_iter_height             (GtkTreeView       *tree_view,
-                                                             GtkRBTree         *tree,
-                                                             GtkTreeIter       *iter,
-                                                             gint               depth);
 static void     gtk_tree_view_build_tree                     (GtkTreeView       *tree_view,
                                                              GtkRBTree         *tree,
                                                              GtkTreeIter       *iter,
                                                              gint               depth,
-                                                             gboolean           recurse,
-                                                             gboolean           calc_bounds);
-static void     gtk_tree_view_calc_size                      (GtkTreeView       *priv,
-                                                             GtkRBTree         *tree,
-                                                             GtkTreeIter       *iter,
-                                                             gint               depth);
+                                                             gboolean           recurse);
 static gboolean gtk_tree_view_discover_dirty_iter            (GtkTreeView       *tree_view,
                                                              GtkTreeIter       *iter,
                                                              gint               depth,
@@ -322,13 +312,13 @@ static void     gtk_tree_view_discover_dirty                 (GtkTreeView
                                                              GtkRBTree         *tree,
                                                              GtkTreeIter       *iter,
                                                              gint               depth);
-static void     gtk_tree_view_check_dirty                    (GtkTreeView       *tree_view);
 static void     gtk_tree_view_clamp_node_visible             (GtkTreeView       *tree_view,
                                                              GtkRBTree         *tree,
                                                              GtkRBNode         *node);
+static void     gtk_tree_view_clamp_column_visible           (GtkTreeView       *tree_view,
+                                                             GtkTreeViewColumn *column);
 static gboolean gtk_tree_view_maybe_begin_dragging_row       (GtkTreeView       *tree_view,
                                                              GdkEventMotion    *event);
-static void     _gtk_tree_view_update_col_width              (GtkTreeView       *tree_view);
 static void     gtk_tree_view_focus_to_cursor                (GtkTreeView       *tree_view);
 static void     gtk_tree_view_move_cursor_up_down            (GtkTreeView       *tree_view,
                                                              gint               count);
@@ -341,17 +331,18 @@ static void     gtk_tree_view_move_cursor_start_end          (GtkTreeView
 static gboolean gtk_tree_view_real_collapse_row              (GtkTreeView       *tree_view,
                                                              GtkTreePath       *path,
                                                              GtkRBTree         *tree,
-                                                             GtkRBNode         *node);
+                                                             GtkRBNode         *node,
+                                                             gboolean           animate);
 static gboolean gtk_tree_view_real_expand_row                (GtkTreeView       *tree_view,
                                                              GtkTreePath       *path,
                                                              GtkRBTree         *tree,
                                                              GtkRBNode         *node,
-                                                             gboolean           open_all);
+                                                             gboolean           open_all,
+                                                             gboolean           animate);
 static void     gtk_tree_view_real_set_cursor                (GtkTreeView       *tree_view,
                                                              GtkTreePath       *path,
                                                              gboolean           clear_and_select);
 
-
 /* interactive search */
 static void     gtk_tree_view_search_dialog_destroy     (GtkWidget        *search_dialog,
                                                         GtkTreeView      *tree_view);
@@ -371,22 +362,38 @@ static void     gtk_tree_view_search_move               (GtkWidget        *windo
                                                         gboolean          up);
 static gboolean gtk_tree_view_search_equal_func         (GtkTreeModel     *model,
                                                         gint              column,
-                                                        gchar            *key,
-                                                        GtkTreeIter      *iter);
+                                                        const gchar      *key,
+                                                        GtkTreeIter      *iter,
+                                                        gpointer          search_data);
 static gboolean gtk_tree_view_search_iter               (GtkTreeModel     *model,
                                                         GtkTreeSelection *selection,
                                                         GtkTreeIter      *iter,
-                                                        gchar            *text,
+                                                        const gchar      *text,
                                                         gint             *count,
                                                         gint              n);
 static void     gtk_tree_view_search_init               (GtkWidget        *entry,
                                                         GtkTreeView      *tree_view);
-static void     gtk_tree_view_interactive_search        (GtkTreeView      *tree_view,
-                                                        GdkEventKey      *key);
+static void     gtk_tree_view_put                       (GtkTreeView      *tree_view,
+                                                        GtkWidget        *child_widget,
+                                                        gint              x,
+                                                        gint              y,
+                                                        gint              width,
+                                                        gint              height);
+static gboolean gtk_tree_view_start_editing             (GtkTreeView      *tree_view,
+                                                        GtkTreePath      *cursor_path);
+static void gtk_tree_view_real_start_editing (GtkTreeView       *tree_view,
+                                             GtkTreeViewColumn *column,
+                                             GtkTreePath       *path,
+                                             GtkCellEditable   *cell_editable,
+                                             GdkRectangle      *cell_area,
+                                             GdkEvent          *event,
+                                             guint              flags);
+static void gtk_tree_view_stop_editing                  (GtkTreeView *tree_view);
+static void gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view);
 
 
 static GtkContainerClass *parent_class = NULL;
-static guint tree_view_signals[LAST_SIGNAL] = { 0 };
+static guint tree_view_signals [LAST_SIGNAL] = { 0 };
 
 \f
 
@@ -475,15 +482,13 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   container_class->set_focus_child = gtk_tree_view_set_focus_child;
 
   class->set_scroll_adjustments = gtk_tree_view_set_adjustments;
-  class->begin_extended_selection = gtk_tree_view_real_begin_extended_selection;
-  class->end_extended_selection = gtk_tree_view_real_end_extended_selection;
-  class->begin_free_motion = gtk_tree_view_real_begin_free_motion;
-  class->end_free_motion = gtk_tree_view_real_end_free_motion;
   class->move_cursor = gtk_tree_view_real_move_cursor;
+  class->select_all = gtk_tree_view_real_select_all;
   class->select_cursor_row = gtk_tree_view_real_select_cursor_row;
   class->toggle_cursor_row = gtk_tree_view_real_toggle_cursor_row;
   class->expand_collapse_cursor_row = gtk_tree_view_real_expand_collapse_cursor_row;
   class->select_cursor_parent = gtk_tree_view_real_select_cursor_parent;
+  class->start_interactive_search = gtk_tree_view_real_start_interactive_search;
 
   /* Properties */
 
@@ -558,7 +563,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                                                           _("View allows user to search through columns interactively"),
                                                           TRUE,
                                                           G_PARAM_READWRITE));
-    
+
     g_object_class_install_property (o_class,
                                     PROP_SEARCH_COLUMN,
                                     g_param_spec_int ("search_column",
@@ -568,47 +573,59 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                                                       G_MAXINT,
                                                       0,
                                                       G_PARAM_READWRITE));
-    
+
   /* Style properties */
-  /* the width of the column resize windows */
 #define _TREE_VIEW_EXPANDER_SIZE 10
 #define _TREE_VIEW_VERTICAL_SEPARATOR 2
-#define _TREE_VIEW_HORIZONTAL_SEPARATOR 0
-
+#define _TREE_VIEW_HORIZONTAL_SEPARATOR 2
+    
   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,
                                                             G_PARAM_READABLE));
-  
+
   gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_int ("vertical_separator",
                                                             _("Vertical Separator Width"),
-                                                            _("Vertical space between cells"),
+                                                            _("Vertical space between cells.  Must be an even number."),
                                                             0,
                                                             G_MAXINT,
                                                             _TREE_VIEW_VERTICAL_SEPARATOR,
                                                             G_PARAM_READABLE));
-  
+
   gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_int ("horizontal_separator",
                                                             _("Horizontal Separator Width"),
-                                                            _("Horizontal space between cells"),
+                                                            _("Horizontal space between cells.  Must be an even number."),
                                                             0,
                                                             G_MAXINT,
                                                             _TREE_VIEW_HORIZONTAL_SEPARATOR,
                                                             G_PARAM_READABLE));
 
+  gtk_widget_class_install_style_property (widget_class,
+                                          g_param_spec_boolean ("allow_rules",
+                                                                _("Allow Rules"),
+                                                                _("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."),
+                                                                TRUE,
+                                                                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_marshal_VOID__OBJECT_OBJECT,
                    GTK_TYPE_NONE, 2,
                    GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
 
@@ -617,7 +634,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
                    GTK_SIGNAL_OFFSET (GtkTreeViewClass, row_activated),
-                   gtk_marshal_VOID__BOXED_OBJECT,
+                   _gtk_marshal_VOID__BOXED_OBJECT,
                    GTK_TYPE_NONE, 2,
                    GTK_TYPE_TREE_PATH,
                    GTK_TYPE_TREE_VIEW_COLUMN);
@@ -628,7 +645,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                   G_SIGNAL_RUN_LAST,
                   G_STRUCT_OFFSET (GtkTreeViewClass, test_expand_row),
                   _gtk_boolean_handled_accumulator, NULL,
-                  gtk_marshal_BOOLEAN__BOXED_BOXED,
+                  _gtk_marshal_BOOLEAN__BOXED_BOXED,
                   G_TYPE_BOOLEAN, 2,
                   GTK_TYPE_TREE_ITER,
                   GTK_TYPE_TREE_PATH);
@@ -639,7 +656,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                   G_SIGNAL_RUN_LAST,
                   G_STRUCT_OFFSET (GtkTreeViewClass, test_collapse_row),
                   _gtk_boolean_handled_accumulator, NULL,
-                  gtk_marshal_BOOLEAN__BOXED_BOXED,
+                  _gtk_marshal_BOOLEAN__BOXED_BOXED,
                   G_TYPE_BOOLEAN, 2,
                   GTK_TYPE_TREE_ITER,
                   GTK_TYPE_TREE_PATH);
@@ -650,7 +667,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                   G_SIGNAL_RUN_LAST,
                   G_STRUCT_OFFSET (GtkTreeViewClass, row_expanded),
                   NULL, NULL,
-                  gtk_marshal_VOID__BOXED_BOXED,
+                  _gtk_marshal_VOID__BOXED_BOXED,
                   GTK_TYPE_NONE, 2,
                   GTK_TYPE_TREE_ITER,
                   GTK_TYPE_TREE_PATH);
@@ -661,7 +678,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                   G_SIGNAL_RUN_LAST,
                   G_STRUCT_OFFSET (GtkTreeViewClass, row_collapsed),
                   NULL, NULL,
-                  gtk_marshal_VOID__BOXED_BOXED,
+                  _gtk_marshal_VOID__BOXED_BOXED,
                   GTK_TYPE_NONE, 2,
                   GTK_TYPE_TREE_ITER,
                   GTK_TYPE_TREE_PATH);
@@ -672,43 +689,16 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                   G_SIGNAL_RUN_LAST,
                   G_STRUCT_OFFSET (GtkTreeViewClass, columns_changed),
                   NULL, NULL,
-                  gtk_marshal_NONE__NONE,
+                  _gtk_marshal_NONE__NONE,
                   G_TYPE_NONE, 0);
 
-  tree_view_signals[BEGIN_EXTENDED_SELECTION] =
-    g_signal_new ("begin_extended_selection",
+  tree_view_signals[CURSOR_CHANGED] =
+    g_signal_new ("cursor_changed",
                   G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, begin_extended_selection),
-                  NULL, NULL,
-                  gtk_marshal_NONE__NONE,
-                  G_TYPE_NONE, 0);
-
-  tree_view_signals[END_EXTENDED_SELECTION] =
-    g_signal_new ("end_extended_selection",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, end_extended_selection),
-                  NULL, NULL,
-                  gtk_marshal_NONE__NONE,
-                  G_TYPE_NONE, 0);
-
-  tree_view_signals[BEGIN_FREE_MOTION] =
-    g_signal_new ("begin_free_motion",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, begin_free_motion),
-                  NULL, NULL,
-                  gtk_marshal_NONE__NONE,
-                  G_TYPE_NONE, 0);
-
-  tree_view_signals[END_FREE_MOTION] =
-    g_signal_new ("end_free_motion",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, end_free_motion),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GtkTreeViewClass, cursor_changed),
                   NULL, NULL,
-                  gtk_marshal_NONE__NONE,
+                  _gtk_marshal_NONE__NONE,
                   G_TYPE_NONE, 0);
 
   tree_view_signals[MOVE_CURSOR] =
@@ -717,17 +707,27 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                   G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
                   G_STRUCT_OFFSET (GtkTreeViewClass, move_cursor),
                   NULL, NULL,
-                  gtk_marshal_VOID__ENUM_INT,
+                  _gtk_marshal_VOID__ENUM_INT,
                   GTK_TYPE_NONE, 2, GTK_TYPE_MOVEMENT_STEP, GTK_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);
+
   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_NONE__NONE,
-                  GTK_TYPE_NONE, 0);
+                  _gtk_marshal_VOID__BOOLEAN,
+                  GTK_TYPE_NONE, 1,
+                 G_TYPE_BOOLEAN);
 
   tree_view_signals[TOGGLE_CURSOR_ROW] =
     g_signal_new ("toggle_cursor_row",
@@ -735,7 +735,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                   G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
                   G_STRUCT_OFFSET (GtkTreeViewClass, toggle_cursor_row),
                   NULL, NULL,
-                  gtk_marshal_NONE__NONE,
+                  _gtk_marshal_NONE__NONE,
                   GTK_TYPE_NONE, 0);
 
   tree_view_signals[EXPAND_COLLAPSE_CURSOR_ROW] =
@@ -744,7 +744,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *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_marshal_VOID__BOOLEAN_BOOLEAN_BOOLEAN,
                   GTK_TYPE_NONE, 3, GTK_TYPE_BOOL, GTK_TYPE_BOOL, GTK_TYPE_BOOL);
 
   tree_view_signals[SELECT_CURSOR_PARENT] =
@@ -753,19 +753,19 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                   G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
                   G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_parent),
                   NULL, NULL,
-                  gtk_marshal_NONE__NONE,
+                  _gtk_marshal_NONE__NONE,
                   GTK_TYPE_NONE, 0);
 
-  /* Key bindings */
-  gtk_binding_entry_add_signal (binding_set, GDK_Shift_L, 0, "begin_extended_selection", 0);
-  gtk_binding_entry_add_signal (binding_set, GDK_Shift_L, GDK_SHIFT_MASK | GDK_RELEASE_MASK, "end_extended_selection", 0);
-  gtk_binding_entry_add_signal (binding_set, GDK_Control_L, 0, "begin_free_motion", 0);
-  gtk_binding_entry_add_signal (binding_set, GDK_Control_L, GDK_CONTROL_MASK | GDK_RELEASE_MASK, "end_free_motion", 0);
-  gtk_binding_entry_add_signal (binding_set, GDK_Shift_R, 0, "begin_extended_selection", 0);
-  gtk_binding_entry_add_signal (binding_set, GDK_Shift_R, GDK_SHIFT_MASK | GDK_RELEASE_MASK, "end_extended_selection", 0);
-  gtk_binding_entry_add_signal (binding_set, GDK_Control_R, 0, "begin_free_motion", 0);
-  gtk_binding_entry_add_signal (binding_set, GDK_Control_R, GDK_CONTROL_MASK | GDK_RELEASE_MASK, "end_free_motion", 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);
 
+  /* Key bindings */
   gtk_tree_view_add_move_binding (binding_set, GDK_Up, 0,
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
 
@@ -798,6 +798,22 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                                GTK_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
                                GTK_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);
+
+  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);
+
+  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);
+
+  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);
+
   gtk_binding_entry_add_signal (binding_set, GDK_f, GDK_CONTROL_MASK, "move_cursor", 2,
                                GTK_TYPE_ENUM, GTK_MOVEMENT_LOGICAL_POSITIONS,
                                GTK_TYPE_INT, 1);
@@ -808,7 +824,13 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
 
   gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK, "toggle_cursor_row", 0);
 
-  gtk_binding_entry_add_signal (binding_set, GDK_space, 0, "select_cursor_row", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK, "select_all", 0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_SHIFT_MASK, "select_cursor_row", 1,
+                               GTK_TYPE_BOOL, TRUE);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_space, 0, "select_cursor_row", 1,
+                               GTK_TYPE_BOOL, TRUE);
 
   /* expand and collapse rows */
   gtk_binding_entry_add_signal (binding_set, GDK_plus, 0, "expand_collapse_cursor_row", 3,
@@ -860,13 +882,15 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
 
   gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0, "select_cursor_parent", 0);
 
+  gtk_binding_entry_add_signal (binding_set, GDK_s, GDK_CONTROL_MASK, "start_interactive_search", 0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_S, GDK_CONTROL_MASK, "start_interactive_search", 0);
 }
 
 static void
 gtk_tree_view_init (GtkTreeView *tree_view)
 {
   tree_view->priv = g_new0 (GtkTreeViewPrivate, 1);
-
   GTK_WIDGET_SET_FLAGS (tree_view, GTK_CAN_FOCUS);
 
   tree_view->priv->flags = GTK_TREE_VIEW_IS_LIST | GTK_TREE_VIEW_SHOW_EXPANDERS | GTK_TREE_VIEW_DRAW_KEYFOCUS | GTK_TREE_VIEW_HEADERS_VISIBLE;
@@ -874,7 +898,7 @@ gtk_tree_view_init (GtkTreeView *tree_view)
 
   /* We need some padding */
   tree_view->priv->tab_offset += EXPANDER_EXTRA_PADDING;
-  
+  tree_view->priv->dy = 0;
   tree_view->priv->n_columns = 0;
   tree_view->priv->header_height = 1;
   tree_view->priv->x_drag = 0;
@@ -884,9 +908,9 @@ gtk_tree_view_init (GtkTreeView *tree_view)
   tree_view->priv->press_start_x = -1;
   tree_view->priv->press_start_y = -1;
   tree_view->priv->reorderable = FALSE;
+  tree_view->priv->presize_handler_timer = 0;
   gtk_tree_view_set_adjustments (tree_view, NULL, NULL);
   tree_view->priv->selection = _gtk_tree_selection_new_with_tree_view (tree_view);
-  _gtk_tree_view_update_size (tree_view);
   tree_view->priv->enable_search = TRUE;
   tree_view->priv->search_column = -1;
   tree_view->priv->search_dialog_position_func = gtk_tree_view_search_position_func;
@@ -945,10 +969,10 @@ gtk_tree_view_set_property (GObject         *object,
 }
 
 static void
-gtk_tree_view_get_property (GObject         *object,
-                           guint            prop_id,
-                           GValue          *value,
-                           GParamSpec      *pspec)
+gtk_tree_view_get_property (GObject    *object,
+                           guint       prop_id,
+                           GValue     *value,
+                           GParamSpec *pspec)
 {
   GtkTreeView *tree_view;
 
@@ -957,7 +981,7 @@ gtk_tree_view_get_property (GObject         *object,
   switch (prop_id)
     {
     case PROP_MODEL:
-      g_value_set_object (value, G_OBJECT (tree_view->priv->model));
+      g_value_set_object (value, tree_view->priv->model);
       break;
     case PROP_HADJUSTMENT:
       g_value_set_object (value, G_OBJECT (tree_view->priv->hadjustment));
@@ -969,7 +993,7 @@ gtk_tree_view_get_property (GObject         *object,
       g_value_set_boolean (value, gtk_tree_view_get_headers_visible (tree_view));
       break;
     case PROP_EXPANDER_COLUMN:
-      g_value_set_object (value, G_OBJECT (tree_view->priv->expander_column));
+      g_value_set_object (value, tree_view->priv->expander_column);
       break;
     case PROP_REORDERABLE:
       g_value_set_boolean (value, tree_view->priv->reorderable);
@@ -1012,11 +1036,18 @@ gtk_tree_view_destroy (GtkObject *object)
   GtkWidget *search_dialog;
   GList *list;
 
- if (tree_view->priv->columns != NULL)
+  gtk_tree_view_stop_editing (tree_view);
+
+  if (tree_view->priv->columns != NULL)
     {
-      for (list = tree_view->priv->columns; list; list = list->next)
-       g_object_unref (G_OBJECT (list->data));
-      g_list_free (tree_view->priv->columns);
+      list = tree_view->priv->columns;
+      while (list)
+       {
+         GtkTreeViewColumn *column;
+         column = GTK_TREE_VIEW_COLUMN (list->data);
+         list = list->next;
+         gtk_tree_view_remove_column (tree_view, column);
+       }
       tree_view->priv->columns = NULL;
     }
 
@@ -1054,7 +1085,7 @@ gtk_tree_view_destroy (GtkObject *object)
       tree_view->priv->drag_dest_row = NULL;
     }
 
-  
+
   if (tree_view->priv->column_drop_func_data &&
       tree_view->priv->column_drop_func_data_destroy)
     {
@@ -1076,11 +1107,17 @@ 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), "search-dialog");
+  search_dialog = gtk_object_get_data (GTK_OBJECT (tree_view),
+                                      GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
   if (search_dialog)
     gtk_tree_view_search_dialog_destroy (search_dialog,
-                                                    tree_view);
+                                        tree_view);
 
+  if (tree_view->priv->search_user_data)
+    {
+      (* tree_view->priv->search_destroy) (tree_view->priv->search_user_data);
+      tree_view->priv->search_user_data = NULL;
+    }
   if (GTK_OBJECT_CLASS (parent_class)->destroy)
     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
 }
@@ -1114,7 +1151,7 @@ gtk_tree_view_map_buttons (GtkTreeView *tree_view)
          column = list->data;
          if (column->visible == FALSE)
            continue;
-         if (column->column_type == GTK_TREE_VIEW_COLUMN_RESIZABLE)
+         if (column->resizable)
            {
              gdk_window_raise (column->window);
              gdk_window_show (column->window);
@@ -1170,7 +1207,6 @@ gtk_tree_view_realize (GtkWidget *widget)
 
   tree_view = GTK_TREE_VIEW (widget);
 
-  gtk_tree_view_check_dirty (GTK_TREE_VIEW (widget));
   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
 
   /* Make the main, clipping window */
@@ -1194,7 +1230,7 @@ gtk_tree_view_realize (GtkWidget *widget)
   attributes.x = 0;
   attributes.y = 0;
   attributes.width = tree_view->priv->width;
-  attributes.height = tree_view->priv->height + TREE_VIEW_HEADER_HEIGHT (tree_view);
+  attributes.height = widget->allocation.height;
   attributes.event_mask = GDK_EXPOSURE_MASK |
     GDK_SCROLL_MASK |
     GDK_POINTER_MOTION_MASK |
@@ -1230,11 +1266,7 @@ gtk_tree_view_realize (GtkWidget *widget)
                       widget->style->black:widget->style->white);
   values.function = GDK_XOR;
   values.subwindow_mode = GDK_INCLUDE_INFERIORS;
-  tree_view->priv->xor_gc = gdk_gc_new_with_values (widget->window,
-                                                   &values,
-                                                   GDK_GC_FOREGROUND |
-                                                   GDK_GC_FUNCTION |
-                                                   GDK_GC_SUBWINDOW);
+
   /* Add them all up. */
   widget->style = gtk_style_attach (widget->style, widget->window);
   gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
@@ -1253,23 +1285,10 @@ gtk_tree_view_realize (GtkWidget *widget)
   for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
     _gtk_tree_view_column_realize_button (GTK_TREE_VIEW_COLUMN (tmp_list->data));
 
-  _gtk_tree_view_update_size (GTK_TREE_VIEW (widget));
+  install_presize_handler (tree_view); 
 
-  if (tree_view->priv->scroll_to_path != NULL ||
-      tree_view->priv->scroll_to_column != NULL)
-    {
-      gtk_tree_view_scroll_to_cell (tree_view,
-                                   tree_view->priv->scroll_to_path,
-                                   tree_view->priv->scroll_to_column,
-                                   tree_view->priv->scroll_to_row_align,
-                                   tree_view->priv->scroll_to_col_align);
-      if (tree_view->priv->scroll_to_path)
-       {
-         gtk_tree_path_free (tree_view->priv->scroll_to_path);
-         tree_view->priv->scroll_to_path = NULL;
-       }
-      tree_view->priv->scroll_to_column = NULL;
-    }
+  if (GTK_WIDGET_CLASS (parent_class)->map)
+    (* GTK_WIDGET_CLASS (parent_class)->map) (widget);
 }
 
 static void
@@ -1300,6 +1319,12 @@ gtk_tree_view_unrealize (GtkWidget *widget)
       tree_view->priv->expand_collapse_timeout = 0;
     }
   
+  if (tree_view->priv->presize_handler_timer != 0)
+    {
+      gtk_timeout_remove (tree_view->priv->presize_handler_timer);
+      tree_view->priv->presize_handler_timer = 0;
+    }
+
   for (list = tree_view->priv->columns; list; list = list->next)
     _gtk_tree_view_column_unrealize_button (GTK_TREE_VIEW_COLUMN (list->data));
 
@@ -1325,18 +1350,6 @@ gtk_tree_view_unrealize (GtkWidget *widget)
       tree_view->priv->drag_highlight_window = NULL;
     }
 
-  if (tree_view->priv->cursor_drag)
-    {
-      gdk_cursor_destroy (tree_view->priv->cursor_drag);
-      tree_view->priv->cursor_drag = NULL;
-    }
-
-  if (tree_view->priv->xor_gc)
-    {
-      gdk_gc_destroy (tree_view->priv->xor_gc);
-      tree_view->priv->xor_gc = NULL;
-    }
-
   /* GtkWidget::unrealize destroys children and widget->window */
   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
@@ -1344,11 +1357,11 @@ gtk_tree_view_unrealize (GtkWidget *widget)
 
 /* GtkWidget::size_request helper */
 static void
-gtk_tree_view_size_request_buttons (GtkTreeView *tree_view)
+gtk_tree_view_size_request_columns (GtkTreeView *tree_view)
 {
   GList *list;
 
-  tree_view->priv->header_height = 1;
+  tree_view->priv->header_height = 0;
 
   if (tree_view->priv->model)
     {
@@ -1361,15 +1374,69 @@ gtk_tree_view_size_request_buttons (GtkTreeView *tree_view)
            continue;
 
           column = list->data;
-
+         
           gtk_widget_size_request (column->button, &requisition);
-
-          _gtk_tree_view_column_set_width (column, MAX (column->width, requisition.width));
+         column->button_request = requisition.width;
           tree_view->priv->header_height = MAX (tree_view->priv->header_height, requisition.height);
         }
     }
 }
 
+
+static void
+gtk_tree_view_update_size (GtkTreeView *tree_view)
+{
+  GList *list;
+  GtkTreeViewColumn *column;
+  gint i;
+
+  if (tree_view->priv->model == NULL)
+    {
+      tree_view->priv->width = 0;
+      tree_view->priv->height = 0;
+      return;
+    }
+
+  tree_view->priv->width = 0;
+  /* keep this in sync with size_allocate below */
+  for (list = tree_view->priv->columns, i = 0; list; list = list->next, i++)
+    {
+      gint real_requested_width = 0;
+      column = list->data;
+      if (!column->visible)
+       continue;
+
+      if (column->use_resized_width)
+       {
+         real_requested_width = column->resized_width;
+       }
+      else if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
+       {
+         real_requested_width = column->fixed_width;
+       }
+      else if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE))
+       {
+         real_requested_width = MAX (column->requested_width, column->button_request);
+       }
+      else
+       {
+         real_requested_width = column->requested_width;
+       }
+
+      if (column->min_width != -1)
+       real_requested_width = MAX (real_requested_width, column->min_width);
+      if (column->max_width != -1)
+       real_requested_width = MIN (real_requested_width, column->max_width);
+
+      tree_view->priv->width += real_requested_width;
+    }
+
+  if (tree_view->priv->tree == NULL)
+    tree_view->priv->height = 0;
+  else
+    tree_view->priv->height = tree_view->priv->tree->root->offset;
+}
+
 static void
 gtk_tree_view_size_request (GtkWidget      *widget,
                            GtkRequisition *requisition)
@@ -1381,6 +1448,9 @@ gtk_tree_view_size_request (GtkWidget      *widget,
 
   tree_view = GTK_TREE_VIEW (widget);
 
+  gtk_tree_view_size_request_columns (tree_view);
+  gtk_tree_view_update_size (GTK_TREE_VIEW (widget));
+
   requisition->width = tree_view->priv->width;
   requisition->height = tree_view->priv->height + tree_view->priv->header_height;
 
@@ -1396,37 +1466,70 @@ gtk_tree_view_size_request (GtkWidget      *widget,
       if (GTK_WIDGET_VISIBLE (child->widget))
         gtk_widget_size_request (child->widget, &child_requisition);
     }
-
-  gtk_tree_view_size_request_buttons (tree_view);
 }
 
 /* GtkWidget::size_allocate helper */
 static void
-gtk_tree_view_size_allocate_buttons (GtkWidget *widget)
+gtk_tree_view_size_allocate_columns (GtkWidget *widget)
 {
   GtkTreeView *tree_view;
-  GList *list;
+  GList *list, *last_column;
   GtkTreeViewColumn *column;
   GtkAllocation allocation;
   gint width = 0;
 
   tree_view = GTK_TREE_VIEW (widget);
 
+  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)
+    ;
+  if (last_column == NULL)
+    return;
+
   allocation.y = 0;
   allocation.height = tree_view->priv->header_height;
 
-  for (list = tree_view->priv->columns; list != NULL; list = list->next)
+  for (list = tree_view->priv->columns; list != last_column->next; list = list->next)
     {
+      gint real_requested_width = 0;
       column = list->data;
-
       if (!column->visible)
        continue;
 
+      if (column->use_resized_width)
+       {
+         real_requested_width = column->resized_width;
+       }
+      else if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
+       {
+         real_requested_width = column->fixed_width;
+       }
+      else if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE))
+       {
+         real_requested_width = MAX (column->requested_width, column->button_request);
+       }
+      else
+       {
+         real_requested_width = column->requested_width;
+       }
+
+      if (column->min_width != -1)
+       real_requested_width = MAX (real_requested_width, column->min_width);
+      if (column->max_width != -1)
+       real_requested_width = MIN (real_requested_width, column->max_width);
+
       allocation.x = width;
-      allocation.width = column->displayed_width;
+      column->width = real_requested_width;
+      if (list == last_column &&
+         width + real_requested_width < widget->allocation.width)
+       {
+         column->width += (widget->allocation.width - column->width - width);
+       }
+      g_object_notify (G_OBJECT (column), "width");
+      allocation.width = column->width;
       width += column->width;
       gtk_widget_size_allocate (column->button, &allocation);
-
       if (column->window)
        gdk_window_move_resize (column->window,
                                 allocation.x + allocation.width - TREE_VIEW_DRAG_WIDTH/2,
@@ -1448,24 +1551,20 @@ gtk_tree_view_size_allocate (GtkWidget     *widget,
 
   tree_view = GTK_TREE_VIEW (widget);
 
-  gtk_tree_view_check_dirty (tree_view);
-
   tmp_list = tree_view->priv->children;
 
   while (tmp_list)
     {
       GtkAllocation allocation;
-      GtkRequisition requisition;
 
       GtkTreeViewChild *child = tmp_list->data;
       tmp_list = tmp_list->next;
 
+      /* totally ignore our childs requisition */
       allocation.x = child->x;
       allocation.y = child->y;
-      gtk_widget_get_child_requisition (child->widget, &requisition);
-      allocation.width = requisition.width;
-      allocation.height = requisition.height;
-
+      allocation.width = child->width;
+      allocation.height = child->height;
       gtk_widget_size_allocate (child->widget, &allocation);
     }
 
@@ -1477,15 +1576,12 @@ gtk_tree_view_size_allocate (GtkWidget     *widget,
       gdk_window_resize (tree_view->priv->header_window,
                         MAX (tree_view->priv->width, allocation->width),
                         tree_view->priv->header_height);
-      if (tree_view->priv->width < allocation->width)
-         gdk_window_resize (tree_view->priv->bin_window,
-                            allocation->width,
-                            tree_view->priv->height + TREE_VIEW_HEADER_HEIGHT (tree_view));
-
-      _gtk_tree_view_update_col_width (tree_view);
+      gdk_window_resize (tree_view->priv->bin_window,
+                        MAX (tree_view->priv->width, allocation->width),
+                        allocation->height);
     }
 
-  gtk_tree_view_size_allocate_buttons (widget);
+  gtk_tree_view_size_allocate_columns (widget);
 
   tree_view->priv->hadjustment->page_size = allocation->width;
   tree_view->priv->hadjustment->page_increment = allocation->width;
@@ -1495,7 +1591,7 @@ gtk_tree_view_size_allocate (GtkWidget     *widget,
 
   if (tree_view->priv->hadjustment->value + allocation->width > tree_view->priv->width)
     tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
-  gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->hadjustment), "changed");
+  gtk_adjustment_changed (tree_view->priv->hadjustment);
 
   tree_view->priv->vadjustment->page_size = allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view);
   tree_view->priv->vadjustment->step_increment = (tree_view->priv->vadjustment->page_size) / 10;
@@ -1506,9 +1602,24 @@ gtk_tree_view_size_allocate (GtkWidget     *widget,
   if (tree_view->priv->vadjustment->value + allocation->height > tree_view->priv->height)
     gtk_adjustment_set_value (tree_view->priv->vadjustment,
                              MAX (tree_view->priv->height - allocation->height, 0));
+  gtk_adjustment_changed (tree_view->priv->vadjustment);
 
-  gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->vadjustment), "changed");
-
+  if (tree_view->priv->scroll_to_path != NULL ||
+      tree_view->priv->scroll_to_column != NULL)
+    {
+      gtk_tree_view_scroll_to_cell (tree_view,
+                                   tree_view->priv->scroll_to_path,
+                                   tree_view->priv->scroll_to_column,
+                                   tree_view->priv->scroll_to_use_align,
+                                   tree_view->priv->scroll_to_row_align,
+                                   tree_view->priv->scroll_to_col_align);
+      if (tree_view->priv->scroll_to_path)
+       {
+         gtk_tree_path_free (tree_view->priv->scroll_to_path);
+         tree_view->priv->scroll_to_path = NULL;
+       }
+      tree_view->priv->scroll_to_column = NULL;
+    }
 }
 
 static gboolean
@@ -1522,12 +1633,17 @@ gtk_tree_view_button_press (GtkWidget      *widget,
   GdkRectangle background_area;
   GdkRectangle cell_area;
   gint vertical_separator;
+  gint horizontal_separator;
 
   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
   g_return_val_if_fail (event != NULL, FALSE);
 
   tree_view = GTK_TREE_VIEW (widget);
-  gtk_widget_style_get (widget, "vertical_separator", &vertical_separator, NULL);
+  gtk_tree_view_stop_editing (tree_view);
+  gtk_widget_style_get (widget,
+                       "vertical_separator", &vertical_separator,
+                       "horizontal_separator", &horizontal_separator,
+                       NULL);
 
   if (event->window == tree_view->priv->bin_window)
     {
@@ -1539,6 +1655,7 @@ gtk_tree_view_button_press (GtkWidget      *widget,
       gint new_y;
       gint y_offset;
       GtkTreeViewColumn *column = NULL;
+      gint column_handled_click = FALSE;
 
       if (!GTK_WIDGET_HAS_FOCUS (widget))
        gtk_widget_grab_focus (widget);
@@ -1563,11 +1680,10 @@ gtk_tree_view_button_press (GtkWidget      *widget,
        }
 
       /* find the node that was clicked */
-      new_y = ((gint)event->y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):(gint)event->y;
-      y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree,
-                                           TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, new_y),
-                                          &tree,
-                                          &node) + new_y - (gint)event->y;
+      new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
+      if (new_y < 0)
+       new_y = 0;
+      y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
 
       if (node == NULL)
        /* We clicked in dead space */
@@ -1576,41 +1692,67 @@ gtk_tree_view_button_press (GtkWidget      *widget,
       /* Get the path and the node */
       path = _gtk_tree_view_find_path (tree_view, tree, node);
       depth = gtk_tree_path_get_depth (path);
-      background_area.y = y_offset + event->y + vertical_separator;
-      background_area.height = GTK_RBNODE_GET_HEIGHT (node) - vertical_separator;
+      background_area.y = y_offset + event->y;
+      background_area.height = GTK_RBNODE_GET_HEIGHT (node);
       background_area.x = 0;
 
       /* Let the column have a chance at selecting it. */
       for (list = tree_view->priv->columns; list; list = list->next)
        {
-         GtkTreeIter iter;
-
          column = list->data;
 
          if (!column->visible)
            continue;
 
-         background_area.width = column->displayed_width;
+         background_area.width = column->width;
+         if ((background_area.x > (gint) event->x) ||
+             (background_area.x + background_area.width <= (gint) event->x))
+           {
+             background_area.x += background_area.width;
+             continue;
+           }
+
+         /* we found the focus column */
+         cell_area = background_area;
+         cell_area.width -= horizontal_separator;
+         cell_area.height -= vertical_separator;
+         cell_area.x += horizontal_separator/2;
+         cell_area.y += vertical_separator/2;
          if (gtk_tree_view_is_expander_column (tree_view, column) &&
               TREE_VIEW_DRAW_EXPANDERS(tree_view))
            {
-             cell_area = background_area;
              cell_area.x += depth*tree_view->priv->tab_offset;
              cell_area.width -= depth*tree_view->priv->tab_offset;
            }
-         else
-           {
-             cell_area = background_area;
-           }
+         break;
+       }
 
-         if ((background_area.x > (gint) event->x) ||
-             (background_area.y > (gint) event->y) ||
-             (background_area.x + background_area.width <= (gint) event->x) ||
-             (background_area.y + background_area.height <= (gint) event->y))
-           {
-             background_area.x += background_area.width;
-             continue;
-           }
+      if (column == NULL)
+       return FALSE;
+
+      tree_view->priv->focus_column = column;
+      if (event->state & GDK_CONTROL_MASK)
+       {
+         gtk_tree_view_real_set_cursor (tree_view, path, FALSE);
+         gtk_tree_view_real_toggle_cursor_row (tree_view);
+       }
+      else if (event->state & GDK_SHIFT_MASK)
+       {
+         gtk_tree_view_real_set_cursor (tree_view, path, FALSE);
+         gtk_tree_view_real_select_cursor_row (tree_view, FALSE);
+       }
+      else
+       {
+         gtk_tree_view_real_set_cursor (tree_view, path, TRUE);
+       }
+
+      if (event->type == GDK_BUTTON_PRESS &&
+         !event->state)
+       {
+         GtkCellEditable *cell_editable = NULL;
+         /* FIXME: get the right flags */
+         guint flags = 0;
+         GtkTreeIter iter;
 
          gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
          gtk_tree_view_column_cell_set_cell_data (column,
@@ -1621,53 +1763,54 @@ gtk_tree_view_button_press (GtkWidget      *widget,
 
          path_string = gtk_tree_path_to_string (path);
 
-         if (gtk_tree_view_column_cell_event (column,
-                                              (GdkEvent *)event,
-                                              path_string,
-                                              &background_area,
-                                              &cell_area, 0))
-           {
-             g_free (path_string);
-             gtk_tree_path_free (path);
-             return TRUE;
-           }
-         else
+         if (_gtk_tree_view_column_cell_event (column,
+                                               &cell_editable,
+                                               (GdkEvent *)event,
+                                               path_string,
+                                               &background_area,
+                                               &cell_area, flags))
            {
-             g_free (path_string);
-             break;
+             if (cell_editable != NULL)
+               {
+                 gtk_tree_view_real_start_editing (tree_view,
+                                                   column,
+                                                   path,
+                                                   cell_editable,
+                                                   &cell_area,
+                                                   (GdkEvent *)event,
+                                                   flags);
+
+               }
+             column_handled_click = TRUE;
            }
+         g_free (path_string);
        }
 
-      if (column == NULL)
-       return FALSE;
-
-      /* The columns didn't want the event.  We handle it */
-
       /* Save press to possibly begin a drag
        */
-      if (tree_view->priv->pressed_button < 0)
+      if (!column_handled_click &&
+         tree_view->priv->pressed_button < 0)
         {
           tree_view->priv->pressed_button = event->button;
           tree_view->priv->press_start_x = event->x;
           tree_view->priv->press_start_y = event->y;
         }
 
-      gtk_tree_view_real_set_cursor (tree_view, path, TRUE);
-      
       if (event->button == 1 && event->type == GDK_2BUTTON_PRESS)
        {
          if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
            {
              if (node->children == NULL)
                gtk_tree_view_real_expand_row (tree_view, path,
-                                              tree, node, FALSE);
+                                              tree, node, FALSE, TRUE);
              else
                gtk_tree_view_real_collapse_row (GTK_TREE_VIEW (widget), path,
-                                                tree, node);
+                                                tree, node, TRUE);
            }
-         gtk_tree_view_row_activated (tree_view, path, column);
 
+         gtk_tree_view_row_activated (tree_view, path, column);
        }
+      GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
       gtk_tree_path_free (path);
       return TRUE;
     }
@@ -1678,7 +1821,7 @@ gtk_tree_view_button_press (GtkWidget      *widget,
     {
       column = list->data;
       if (event->window == column->window &&
-         column->column_type == GTK_TREE_VIEW_COLUMN_RESIZABLE &&
+         column->resizable &&
          column->window)
        {
          gpointer drag_data;
@@ -1692,6 +1835,8 @@ gtk_tree_view_button_press (GtkWidget      *widget,
 
          gtk_grab_add (widget);
          GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE);
+         column->resized_width = column->width;
+         column->use_resized_width = TRUE;
 
          /* block attached dnd signal handler */
          drag_data = gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data");
@@ -1703,6 +1848,7 @@ gtk_tree_view_button_press (GtkWidget      *widget,
 
          tree_view->priv->drag_pos = i;
          tree_view->priv->x_drag = (column->button->allocation.x + column->button->allocation.width);
+         break;
        }
     }
   return TRUE;
@@ -1758,7 +1904,6 @@ gtk_tree_view_button_release_column_resize (GtkWidget      *widget,
 {
   GtkTreeView *tree_view;
   gpointer drag_data;
-  gint width;
   gint x;
   gint i;
 
@@ -1777,9 +1922,6 @@ gtk_tree_view_button_release_column_resize (GtkWidget      *widget,
   gtk_grab_remove (widget);
   gdk_pointer_ungrab (event->time);
 
-  width = gtk_tree_view_new_column_width (GTK_TREE_VIEW (widget), i, &x);
-  _gtk_tree_view_column_set_width (gtk_tree_view_get_column (GTK_TREE_VIEW (widget), i), width);
-
   return TRUE;
 }
 
@@ -1822,11 +1964,11 @@ gtk_tree_view_button_release (GtkWidget      *widget,
            gtk_tree_view_real_expand_row (tree_view, path,
                                           tree_view->priv->button_pressed_tree,
                                           tree_view->priv->button_pressed_node,
-                                          FALSE);
+                                          FALSE, TRUE);
          else
            gtk_tree_view_real_collapse_row (GTK_TREE_VIEW (widget), path,
                                             tree_view->priv->button_pressed_tree,
-                                            tree_view->priv->button_pressed_node);
+                                            tree_view->priv->button_pressed_node, TRUE);
          gtk_tree_path_free (path);
        }
 
@@ -1845,7 +1987,7 @@ static gboolean
 coords_are_over_arrow (GtkTreeView *tree_view,
                        GtkRBTree   *tree,
                        GtkRBNode   *node,
-                       /* these are in tree window coords */
+                       /* these are in window coords */
                        gint         x,
                        gint         y)
 {
@@ -1862,14 +2004,14 @@ coords_are_over_arrow (GtkTreeView *tree_view,
 
   arrow.height = BACKGROUND_HEIGHT (node);
 
-  gtk_tree_view_get_arrow_xrange (tree_view, &arrow.x, &x2);
+  gtk_tree_view_get_arrow_xrange (tree_view, tree, &arrow.x, &x2);
 
   arrow.width = x2 - arrow.x;
 
   return (x >= arrow.x &&
           x < (arrow.x + arrow.width) &&
-          y >= arrow.y &&
-          y < (arrow.y + arrow.height));
+         y >= arrow.y &&
+         y < (arrow.y + arrow.height));
 }
 
 static void
@@ -1909,12 +2051,14 @@ static void
 do_prelight (GtkTreeView *tree_view,
              GtkRBTree   *tree,
              GtkRBNode   *node,
-             /* these are in tree window coords */
+            /* these are in tree_window coords */
              gint         x,
              gint         y)
 {
   if (coords_are_over_arrow (tree_view, tree, node, x, y))
-    GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
+    {
+      GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
+    }
 
   tree_view->priv->prelight_node = node;
   tree_view->priv->prelight_tree = tree;
@@ -1931,6 +2075,7 @@ ensure_unprelighted (GtkTreeView *tree_view)
 
 
 
+
 /* Our motion arrow is either a box (in the case of the original spot)
  * or an arrow.  It is expander_size wide.
  */
@@ -2042,7 +2187,7 @@ gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
                            NULL);
 
       width = expander_size;
-      
+
       /* Get x, y, width, height of arrow */
       if (reorder->left_column)
        {
@@ -2117,7 +2262,7 @@ gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
                            NULL);
 
       width = expander_size;
-      
+
       /* Get x, y, width, height of arrow */
       width = width/2; /* remember, the arrow only takes half the available width */
       gdk_window_get_origin (widget->window, &x, &y);
@@ -2198,6 +2343,9 @@ gtk_tree_view_motion_resize_column (GtkWidget      *widget,
 {
   gint x;
   gint new_width;
+  GtkTreeViewColumn *column;
+
+  column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), GTK_TREE_VIEW (widget)->priv->drag_pos);
 
   if (event->is_hint || event->window != widget->window)
     gtk_widget_get_pointer (widget, &x, NULL);
@@ -2206,11 +2354,13 @@ gtk_tree_view_motion_resize_column (GtkWidget      *widget,
 
   new_width = gtk_tree_view_new_column_width (GTK_TREE_VIEW (widget),
                                              GTK_TREE_VIEW (widget)->priv->drag_pos, &x);
-  if (x != GTK_TREE_VIEW (widget)->priv->x_drag)
-    _gtk_tree_view_column_set_width (gtk_tree_view_get_column (GTK_TREE_VIEW (widget), GTK_TREE_VIEW (widget)->priv->drag_pos), new_width);
+  if (x != GTK_TREE_VIEW (widget)->priv->x_drag &&
+      (new_width != column->fixed_width));
+    {
+      column->resized_width = new_width;
+      gtk_widget_queue_resize (widget);
+    }
 
-  /* FIXME: Do we need to scroll */
-  _gtk_tree_view_update_size (GTK_TREE_VIEW (widget));
   return FALSE;
 }
 
@@ -2318,14 +2468,12 @@ gtk_tree_view_motion_bin_window (GtkWidget      *widget,
   old_prelight_tree = tree_view->priv->prelight_tree;
   old_prelight_node = tree_view->priv->prelight_node;
   old_arrow_prelit = GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
-  do_unprelight (tree_view, event->x, event->y);
 
-  new_y = ((gint)event->y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):(gint)event->y;
-
-  _gtk_rbtree_find_offset (tree_view->priv->tree,
-                           TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, new_y),
-                           &tree,
-                           &node);
+  new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
+  if (new_y < 0)
+    new_y = 0;
+  do_unprelight (tree_view, event->x, event->y);
+  _gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
 
   if (tree == NULL)
     return TRUE;
@@ -2336,29 +2484,34 @@ gtk_tree_view_motion_bin_window (GtkWidget      *widget,
     return TRUE;
 
 
-  do_prelight (tree_view, tree, node, event->x, new_y);
+  do_prelight (tree_view, tree, node, event->x, event->y);
 
   if (old_prelight_node != tree_view->priv->prelight_node)
     {
       if (old_prelight_node)
-        gtk_tree_view_queue_draw_node (tree_view,
+       {
+         gtk_tree_view_queue_draw_node (tree_view,
                                        old_prelight_tree,
                                        old_prelight_node,
                                        NULL);
-
+       }
       if (tree_view->priv->prelight_node)
-        gtk_tree_view_queue_draw_node (tree_view,
+       {
+         gtk_tree_view_queue_draw_node (tree_view,
                                        tree_view->priv->prelight_tree,
                                        tree_view->priv->prelight_node,
                                        NULL);
+       }
     }
   else if (old_arrow_prelit != GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
     {
       if (tree_view->priv->prelight_node)
-        gtk_tree_view_queue_draw_node (tree_view,
-                                       tree_view->priv->prelight_tree,
-                                       tree_view->priv->prelight_node,
-                                       NULL);
+       {
+         gtk_tree_view_queue_draw_node (tree_view,
+                                        tree_view->priv->prelight_tree,
+                                        tree_view->priv->prelight_node,
+                                        NULL);
+       }
     }
   return TRUE;
 }
@@ -2386,95 +2539,11 @@ gtk_tree_view_motion (GtkWidget      *widget,
   return FALSE;
 }
 
-/* Draws the focus rectangle around the cursor row */
-static void
-gtk_tree_view_draw_focus (GtkWidget *widget)
-{
-  GtkTreeView *tree_view;
-  GtkTreePath *cursor_path;
-  GtkRBTree *tree = NULL;
-  GtkRBNode *node = NULL;
-  gint x, y;
-  gint width, height;
-  gint vertical_separator;
-
-  g_return_if_fail (GTK_IS_TREE_VIEW (widget));
-
-  tree_view = GTK_TREE_VIEW (widget);
-
-  gtk_widget_style_get (widget,        "vertical_separator", &vertical_separator, NULL);
-
-  if (! GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS))
-    return;
-
-  if (! gtk_tree_row_reference_valid (tree_view->priv->cursor))
-    return;
-
-  cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
-
-  _gtk_tree_view_find_node (tree_view, cursor_path, &tree, &node);
-
-  if (tree == NULL)
-    {
-      gtk_tree_path_free (cursor_path);
-      return;
-    }
-
-  gdk_drawable_get_size (tree_view->priv->bin_window,
-                         &width, NULL);
-
-
-  x = 0;
-  y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
-  gdk_drawable_get_size (tree_view->priv->bin_window,
-                        &width, NULL);
-  width = width - 1;
-  height = BACKGROUND_HEIGHT (node) - 1;
-  if (tree_view->priv->focus_column != NULL)
-    {
-      GtkTreeIter iter;
-
-      gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path);
-      gtk_tree_view_column_cell_set_cell_data (tree_view->priv->focus_column,
-                                              tree_view->priv->model,
-                                              &iter,
-                                              GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
-                                              node->children?TRUE:FALSE);
-
-      if (gtk_tree_view_column_cell_can_focus (tree_view->priv->focus_column))
-       {
-         GdkRectangle cell_area;
-         gint x_offset;
-         gint y_offset;
-
-         cell_area.x = tree_view->priv->focus_column->button->allocation.x;
-         cell_area.y = y;
-         cell_area.width = tree_view->priv->focus_column->displayed_width;
-         cell_area.height = CELL_HEIGHT (node, vertical_separator);
-
-         gtk_tree_view_column_cell_get_size (tree_view->priv->focus_column,
-                                             &cell_area, &x_offset, &y_offset, &width, &height);
-
-         width += 2;
-         height += 2;
-
-         x = cell_area.x + x_offset - 1;
-         y = cell_area.y + y_offset - 1 + vertical_separator/2;
-       }
-    }
-
-  gtk_paint_focus (widget->style,
-                  tree_view->priv->bin_window,
-                  NULL,
-                  widget,
-                  "treeview",
-                  x, y, width, height);
-
-  gtk_tree_path_free (cursor_path);
-}
-
 /* Warning: Very scary function.
  * Modify at your own risk
+ *
+ * KEEP IN SYNC WITH gtk_tree_view_create_row_drag_icon()!
+ * FIXME: It's not...
  */
 static gboolean
 gtk_tree_view_bin_expose (GtkWidget      *widget,
@@ -2503,28 +2572,39 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
   GtkTreePath *drag_dest_path;
   GList *last_column;
   gint vertical_separator;
+  gint horizontal_separator;
+  gboolean allow_rules;
 
   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
 
   tree_view = GTK_TREE_VIEW (widget);
-  gtk_widget_style_get (widget, "vertical_separator", &vertical_separator, NULL);
+
+  gtk_widget_style_get (widget,
+                       "horizontal_separator", &horizontal_separator,
+                       "vertical_separator", &vertical_separator,
+                       "allow_rules", &allow_rules,
+                       NULL);
 
   if (tree_view->priv->tree == NULL)
     return TRUE;
 
-  gtk_tree_view_check_dirty (GTK_TREE_VIEW (widget));
-  /* we want to account for a potential HEADER offset.
-   * That is, if the header exists, we want to offset our event by its
-   * height to find the right node.
-   */
-  new_y = (event->area.y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):event->area.y;
+  /* clip event->area to the visible area */
+  if (event->area.y < TREE_VIEW_HEADER_HEIGHT (tree_view))
+    {
+      event->area.height -= (TREE_VIEW_HEADER_HEIGHT (tree_view) - event->area.y);
+      event->area.y = TREE_VIEW_HEADER_HEIGHT (tree_view);
+
+      if (event->area.height < 0)
+       return TRUE;
+    }
 
-  /* y_offset is the */
+  validate_visible_area (tree_view);
+  
+  new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, event->area.y);
+  if (new_y < 0)
+    new_y = 0;
+  y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
 
-  y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree,
-                                       TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, new_y),
-                                      &tree,
-                                      &node) + new_y - event->area.y;
   if (node == NULL)
     return TRUE;
 
@@ -2582,6 +2662,7 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
 
       background_area.y = y_offset + event->area.y;
       background_area.height = max_height;
+
       flags = 0;
 
       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PRELIT))
@@ -2591,19 +2672,20 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
         flags |= GTK_CELL_RENDERER_SELECTED;
 
       parity = _gtk_rbtree_node_find_parity (tree, node);
-      
+
       for (list = tree_view->priv->columns; list; list = list->next)
        {
          GtkTreeViewColumn *column = list->data;
          const gchar *detail = NULL;
+         GtkStateType state;
 
          if (!column->visible)
             continue;
 
          if (cell_offset > event->area.x + event->area.width ||
-             cell_offset + column->displayed_width < event->area.x)
+             cell_offset + column->width < event->area.x)
            {
-             cell_offset += column->displayed_width;
+             cell_offset += column->width;
              continue;
            }
 
@@ -2620,21 +2702,19 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
 
 
          background_area.x = cell_offset;
-         background_area.width = column->displayed_width;
+         background_area.width = column->width;
 
           cell_area = background_area;
           cell_area.y += vertical_separator / 2;
+          cell_area.x += horizontal_separator / 2;
           cell_area.height -= vertical_separator;
+         cell_area.width -= horizontal_separator;
 
           /* Select the detail for drawing the cell.  relevant
            * factors are parity, sortedness, and whether to
            * display rules.
            */
-
-          /* FIXME when we have style properties, clean this up.
-           */
-
-          if (tree_view->priv->has_rules)
+          if (allow_rules && tree_view->priv->has_rules)
             {
               if (flags & GTK_CELL_RENDERER_SORTED)
                 {
@@ -2671,11 +2751,15 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
 
           g_assert (detail);
 
-          /* Draw background */
+         if (flags & GTK_CELL_RENDERER_SELECTED)
+           state = GTK_STATE_SELECTED;
+         else
+           state = GTK_STATE_NORMAL;
+
+         /* Draw background */
           gtk_paint_flat_box (widget->style,
                               event->window,
-                              (flags & GTK_CELL_RENDERER_SELECTED) ?
-                              GTK_STATE_SELECTED : GTK_STATE_NORMAL,
+                             state,
                               GTK_SHADOW_NONE,
                               &event->area,
                               widget,
@@ -2696,7 +2780,6 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                * level of the tree we're dropping at.
                */
               highlight_x = cell_area.x;
-
              gtk_tree_view_column_cell_render (column,
                                                event->window,
                                                &background_area,
@@ -2722,11 +2805,22 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                                                &event->area,
                                                flags);
            }
-         cell_offset += column->displayed_width;
+         if (node == cursor &&
+             ((column == tree_view->priv->focus_column &&
+               GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS) &&
+               GTK_WIDGET_HAS_FOCUS (widget)) ||
+              (column == tree_view->priv->edited_column)))
+           {
+             gtk_tree_view_column_cell_draw_focus (column,
+                                                   event->window,
+                                                   &background_area,
+                                                   &cell_area,
+                                                   &event->area,
+                                                   flags);
+           }
+         cell_offset += column->width;
        }
 
-      if (node == cursor && GTK_WIDGET_HAS_FOCUS (widget))
-       gtk_tree_view_draw_focus (widget);
 
       if (node == drag_highlight)
         {
@@ -2757,11 +2851,12 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                                     &width, NULL);
              gtk_paint_focus (widget->style,
                               tree_view->priv->bin_window,
+                              GTK_WIDGET_STATE (widget),
                               NULL,
                               widget,
                               "treeview-drop-indicator",
                               0, BACKGROUND_FIRST_PIXEL (tree_view, tree, node),
-                              width - 1, BACKGROUND_HEIGHT (node) - 1);
+                              width, BACKGROUND_HEIGHT (node));
 
               break;
             }
@@ -2820,9 +2915,8 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                  node = tree->parent_node;
                  tree = tree->parent_tree;
                  if (tree == NULL)
-                   /* we've run out of tree.  It's okay to return though, as
-                    * we'd only break out of the while loop below. */
-                   return TRUE;
+                   /* we should go to done to free some memory */
+                   goto done;
                  has_parent = gtk_tree_model_iter_parent (tree_view->priv->model,
                                                           &iter,
                                                           &parent_iter);
@@ -2837,13 +2931,14 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
     }
   while (y_offset < event->area.height);
 
+ done:
   if (cursor_path)
     gtk_tree_path_free (cursor_path);
 
   if (drag_dest_path)
     gtk_tree_path_free (drag_dest_path);
 
-  return TRUE;
+  return FALSE;
 }
 
 static gboolean
@@ -2858,6 +2953,20 @@ gtk_tree_view_expose (GtkWidget      *widget,
 
   if (event->window == tree_view->priv->bin_window)
     return gtk_tree_view_bin_expose (widget, event);
+  else if (event->window == tree_view->priv->header_window)
+    {
+      GList *list;
+      
+      for (list = tree_view->priv->columns; list != NULL; list = list->next)
+       {
+         GtkTreeViewColumn *column = list->data;
+         
+         if (column->visible)
+           gtk_container_propagate_expose (GTK_CONTAINER (tree_view),
+                                           column->button,
+                                           event);
+       }
+    }
 
   return TRUE;
 }
@@ -2867,7 +2976,6 @@ gtk_tree_view_key_press (GtkWidget   *widget,
                         GdkEventKey *event)
 {
   GtkTreeView *tree_view = (GtkTreeView *) widget;
-  gint retval;
 
   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
     {
@@ -2879,12 +2987,7 @@ gtk_tree_view_key_press (GtkWidget   *widget,
       return TRUE;
     }
 
-  retval = (* GTK_WIDGET_CLASS (parent_class)->key_press_event) (widget, event);
-
-  if (! retval)
-    gtk_tree_view_interactive_search (tree_view, event);
-
-  return retval;
+  return (* GTK_WIDGET_CLASS (parent_class)->key_press_event) (widget, event);
 }
 
 /* FIXME Is this function necessary? Can I get an enter_notify event
@@ -2915,17 +3018,15 @@ gtk_tree_view_enter_notify (GtkWidget        *widget,
     return TRUE;
 
   /* find the node internally */
-  new_y = ((gint)event->y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):(gint)event->y;
-
-  _gtk_rbtree_find_offset (tree_view->priv->tree,
-                           TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, new_y),
-                           &tree,
-                           &node);
+  new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
+  if (new_y < 0)
+    new_y = 0;
+  _gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
 
   if (node == NULL)
     return FALSE;
 
-  do_prelight (tree_view, tree, node, event->x, new_y);
+  do_prelight (tree_view, tree, node, event->x, event->y);
 
   if (tree_view->priv->prelight_node)
     gtk_tree_view_queue_draw_node (tree_view,
@@ -2940,10 +3041,13 @@ static gboolean
 gtk_tree_view_leave_notify (GtkWidget        *widget,
                            GdkEventCrossing *event)
 {
+  GtkWidget *search_dialog;
   GtkTreeView *tree_view;
 
   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
 
+  if (event->mode == GDK_CROSSING_GRAB)
+    return TRUE;
   tree_view = GTK_TREE_VIEW (widget);
 
   if (tree_view->priv->prelight_node)
@@ -2953,7 +3057,13 @@ gtk_tree_view_leave_notify (GtkWidget        *widget,
                                    NULL);
 
   ensure_unprelighted (tree_view);
-  
+
+  /* destroy interactive search dialog */
+  search_dialog = gtk_object_get_data (GTK_OBJECT (widget),
+                                      GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
+  if (search_dialog)
+    gtk_tree_view_search_dialog_destroy (search_dialog, GTK_TREE_VIEW (widget));
+
 return TRUE;
 }
 
@@ -2989,149 +3099,467 @@ gtk_tree_view_focus_out (GtkWidget     *widget,
   GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
 
   gtk_widget_queue_draw (widget);
-  GTK_TREE_VIEW (widget)->priv->in_extended_selection = FALSE;
-  GTK_TREE_VIEW (widget)->priv->in_free_motion = FALSE;
 
   /* destroy interactive search dialog */
-  search_dialog = gtk_object_get_data (GTK_OBJECT (widget), "search-dialog");
+  search_dialog = gtk_object_get_data (GTK_OBJECT (widget),
+                                      GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
   if (search_dialog)
-    gtk_tree_view_search_dialog_destroy (search_dialog,
-                                                    GTK_TREE_VIEW (widget));
+    gtk_tree_view_search_dialog_destroy (search_dialog, GTK_TREE_VIEW (widget));
   return FALSE;
 }
 
 
-/* Drag-and-drop */
-
-static void
-set_source_row (GdkDragContext *context,
-                GtkTreeModel   *model,
-                GtkTreePath    *source_row)
-{
-  g_object_set_data_full (G_OBJECT (context),
-                          "gtk-tree-view-source-row",
-                          source_row ? gtk_tree_row_reference_new (model, source_row) : NULL,
-                          (GDestroyNotify) (source_row ? gtk_tree_row_reference_free : NULL));
-}
-
-static GtkTreePath*
-get_source_row (GdkDragContext *context)
-{
-  GtkTreeRowReference *ref =
-    g_object_get_data (G_OBJECT (context), "gtk-tree-view-source-row");
-
-  if (ref)
-    return gtk_tree_row_reference_get_path (ref);
-  else
-    return NULL;
-}
-
-
-static void
-set_dest_row (GdkDragContext *context,
-              GtkTreeModel   *model,
-              GtkTreePath    *dest_row)
-{
-  g_object_set_data_full (G_OBJECT (context),
-                          "gtk-tree-view-dest-row",
-                          dest_row ? gtk_tree_row_reference_new (model, dest_row) : NULL,
-                          (GDestroyNotify) (dest_row ? gtk_tree_row_reference_free : NULL));
-}
-
-static GtkTreePath*
-get_dest_row (GdkDragContext *context)
-{
-  GtkTreeRowReference *ref =
-    g_object_get_data (G_OBJECT (context), "gtk-tree-view-dest-row");
-
-  if (ref)
-    return gtk_tree_row_reference_get_path (ref);
-  else
-    return NULL;
-}
+/* Incremental Reflow
+ */
 
-/* Get/set whether drag_motion requested the drag data and
- * drag_data_received should thus not actually insert the data,
- * since the data doesn't result from a drop.
+/* Returns TRUE if it updated the size
  */
-static void
-set_status_pending (GdkDragContext *context,
-                    GdkDragAction   suggested_action)
+static gboolean
+validate_row (GtkTreeView *tree_view,
+             GtkRBTree   *tree,
+             GtkRBNode   *node,
+             GtkTreeIter *iter,
+             GtkTreePath *path)
 {
-  g_object_set_data (G_OBJECT (context),
-                     "gtk-tree-view-status-pending",
-                     GINT_TO_POINTER (suggested_action));
-}
+  GtkTreeViewColumn *column;
+  GList *list;
+  gint height = 0;
+  gint horizontal_separator;
+  gint depth = gtk_tree_path_get_depth (path);
+  gboolean retval = FALSE;
 
-static GdkDragAction
-get_status_pending (GdkDragContext *context)
-{
-  return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
-                                             "gtk-tree-view-status-pending"));
-}
 
-static TreeViewDragInfo*
-get_info (GtkTreeView *tree_view)
-{
-  return g_object_get_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info");
-}
+  /* double check the row needs validating */
+  if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) &&
+      ! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
+    return FALSE;
 
-static void
-clear_source_info (TreeViewDragInfo *di)
-{
-  if (di->source_target_list)
-    gtk_target_list_unref (di->source_target_list);
+  gtk_widget_style_get (GTK_WIDGET (tree_view),
+                       "horizontal_separator", &horizontal_separator,
+                       NULL);
 
-  if (di->row_draggable_closure)
-    g_closure_unref (di->row_draggable_closure);
+  for (list = tree_view->priv->columns; list; list = list->next)
+    {
+      gint tmp_width;
+      gint tmp_height;
 
-  di->source_target_list = NULL;
-  di->row_draggable_closure = NULL;
-}
+      column = list->data;
 
-static void
-clear_dest_info (TreeViewDragInfo *di)
-{
-  if (di->location_droppable_closure)
-    g_closure_unref (di->location_droppable_closure);
+      if (! column->visible)
+       continue;
 
-  if (di->dest_target_list)
-    gtk_target_list_unref (di->dest_target_list);
+      if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID) && !column->dirty)
+       continue;
 
-  di->location_droppable_closure = NULL;
-  di->dest_target_list = NULL;
-}
+      if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
+       continue;
 
-static void
-destroy_info (TreeViewDragInfo *di)
-{
-  clear_source_info (di);
-  clear_dest_info (di);
-  g_free (di);
-}
+      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);
+      gtk_tree_view_column_cell_get_size (column,
+                                         NULL, NULL, NULL,
+                                         &tmp_width, &tmp_height);
+      height = MAX (height, tmp_height);
 
-static TreeViewDragInfo*
-ensure_info (GtkTreeView *tree_view)
-{
-  TreeViewDragInfo *di;
+      if (gtk_tree_view_is_expander_column (tree_view, column) && TREE_VIEW_DRAW_EXPANDERS (tree_view))
+       tmp_width = tmp_width + horizontal_separator + depth * tree_view->priv->tab_offset;
+      else
+       tmp_width = tmp_width + horizontal_separator;
 
-  di = get_info (tree_view);
+      if (tmp_width > column->requested_width)
+       {
+         retval = TRUE;
+         column->requested_width = tmp_width;
+       }
+    }
 
-  if (di == NULL)
+  if (height != GTK_RBNODE_GET_HEIGHT (node))
     {
-      di = g_new0 (TreeViewDragInfo, 1);
-
-      g_object_set_data_full (G_OBJECT (tree_view),
-                              "gtk-tree-view-drag-info",
-                              di,
-                              (GDestroyNotify) destroy_info);
+      retval = TRUE;
+      _gtk_rbtree_node_set_height (tree, node, height);
     }
+  _gtk_rbtree_node_mark_valid (tree, node);
 
-  return di;
+  return retval;
 }
 
+
 static void
-remove_info (GtkTreeView *tree_view)
+validate_visible_area (GtkTreeView *tree_view)
+{
+  GtkTreePath *path;
+  GtkTreeIter iter;
+  GtkRBTree *tree;
+  GtkRBNode *node;
+  gint y, height, offset;
+  gboolean validated_area = FALSE;
+  gboolean size_changed = FALSE;
+  
+  if (tree_view->priv->tree == NULL)
+    return;
+  
+  if (! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
+    return;
+  
+  height = GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
+
+  y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, TREE_VIEW_HEADER_HEIGHT (tree_view));
+
+  offset = _gtk_rbtree_find_offset (tree_view->priv->tree, y,
+                                   &tree, &node);
+  if (node == NULL)
+    {
+      path = gtk_tree_path_new_root ();
+      _gtk_tree_view_find_node (tree_view, path, &tree, &node);
+    }
+  else
+    {
+      path = _gtk_tree_view_find_path (tree_view, tree, node);
+      height += offset;
+    }
+
+  gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
+  do
+    {
+      gint old_height;
+
+      if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
+         GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
+       {
+         validated_area = TRUE;
+         if (validate_row (tree_view, tree, node, &iter, path))
+           size_changed = TRUE;
+       }
+      height -= GTK_RBNODE_GET_HEIGHT (node);
+
+      if (node->children)
+       {
+         GtkTreeIter parent = iter;
+         gboolean has_child;
+
+         tree = node->children;
+         node = tree->root;
+
+          g_assert (node != tree->nil);
+
+         while (node->left != tree->nil)
+           node = node->left;
+         has_child = gtk_tree_model_iter_children (tree_view->priv->model,
+                                                   &iter,
+                                                   &parent);
+         TREE_VIEW_INTERNAL_ASSERT_VOID (has_child);
+         gtk_tree_path_append_index (path, 0);
+       }
+      else
+       {
+         gboolean done = FALSE;
+         do
+           {
+             node = _gtk_rbtree_next (tree, node);
+             if (node != NULL)
+               {
+                 gboolean has_next = gtk_tree_model_iter_next (tree_view->priv->model, &iter);
+                 done = TRUE;
+
+                 /* Sanity Check! */
+                 TREE_VIEW_INTERNAL_ASSERT_VOID (has_next);
+               }
+             else
+               {
+                 GtkTreeIter parent_iter = iter;
+                 gboolean has_parent;
+
+                 node = tree->parent_node;
+                 tree = tree->parent_tree;
+                 if (tree == NULL)
+                   break;
+                 has_parent = gtk_tree_model_iter_parent (tree_view->priv->model,
+                                                          &iter,
+                                                          &parent_iter);
+
+                 /* Sanity check */
+                 TREE_VIEW_INTERNAL_ASSERT_VOID (has_parent);
+               }
+           }
+         while (!done);
+       }
+    }
+  while (node && height > 0);
+
+  if (size_changed)
+    gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+  if (validated_area)
+    gtk_widget_queue_draw (GTK_WIDGET (tree_view));
+}
+
+/* Our strategy for finding nodes to validate is a little convoluted.  We find
+ * the left-most uninvalidated node.  We then try walking right, validating
+ * nodes.  Once we find a valid node, we repeat the previous process of finding
+ * the first invalid node.
+ */
+
+static gboolean
+validate_rows_handler (GtkTreeView *tree_view)
+{
+  GtkRBTree *tree = NULL;
+  GtkRBNode *node = NULL;
+  gboolean validated_area = FALSE;
+  gint retval = TRUE;
+  GtkTreePath *path = NULL;
+  GtkTreeIter iter;
+  gint i = 0;
+  g_assert (tree_view);
+  g_return_val_if_fail (tree_view->priv->tree != NULL, FALSE);
+
+  GDK_THREADS_ENTER ();
+
+  do
+    {
+
+      if (! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
+       {
+         retval = FALSE;
+         goto done;
+       }
+
+      if (path != NULL)
+       {
+         node = _gtk_rbtree_next (tree, node);
+         if (node != NULL)
+           {
+             TREE_VIEW_INTERNAL_ASSERT (gtk_tree_model_iter_next (tree_view->priv->model, &iter), FALSE);
+             gtk_tree_path_next (path);
+           }
+         else
+           {
+             gtk_tree_path_free (path);
+             path = NULL;
+           }
+       }
+
+      if (path == NULL)
+       {
+         tree = tree_view->priv->tree;
+         node = tree_view->priv->tree->root;
+
+         g_assert (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_DESCENDANTS_INVALID));
+
+         do
+           {
+             if (node->left != tree->nil &&
+                 GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID))
+               {
+                 node = node->left;
+               }
+             else if (node->right != tree->nil &&
+                      GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID))
+               {
+                 node = node->right;
+               }
+             else if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
+                      GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
+               {
+                 break;
+               }
+             else if (node->children != NULL)
+               {
+                 tree = node->children;
+                 node = tree->root;
+               }
+             else
+               /* RBTree corruption!  All bad */
+               g_assert_not_reached ();
+           }
+         while (TRUE);
+         path = _gtk_tree_view_find_path (tree_view, tree, node);
+         gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
+       }
+      validated_area = validate_row (tree_view, tree, node, &iter, path) | validated_area;
+      i++;
+    }
+  while (i < GTK_TREE_VIEW_NUM_ROWS_PER_IDLE);
+  
+ done:
+  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;
+
+  GDK_THREADS_LEAVE ();
+
+  return retval;
+}
+
+static gboolean
+presize_handler_callback (gpointer data)
+{
+  GtkTreeView *tree_view = GTK_TREE_VIEW (data);
+
+  GDK_THREADS_ENTER ();
+
+  if (tree_view->priv->mark_rows_col_dirty)
+    {
+      if (tree_view->priv->tree)
+       _gtk_rbtree_column_invalid (tree_view->priv->tree);
+      tree_view->priv->mark_rows_col_dirty = FALSE;
+    }
+  validate_visible_area (tree_view);
+  tree_view->priv->presize_handler_timer = 0;
+                  
+  GDK_THREADS_LEAVE ();
+
+  return FALSE;
+}
+
+static void
+install_presize_handler (GtkTreeView *tree_view)
+{
+  if (! tree_view->priv->presize_handler_timer)
+    {
+      tree_view->priv->presize_handler_timer =
+       g_idle_add_full (GTK_PRIORITY_RESIZE - 2, presize_handler_callback, tree_view, NULL);
+    }
+  if (! tree_view->priv->validate_rows_timer)
+    {
+      tree_view->priv->validate_rows_timer =
+       g_idle_add_full (GTK_TREE_VIEW_PRIORITY_VALIDATE, (GSourceFunc) validate_rows_handler, tree_view, NULL);
+    }
+}
+
+
+void
+_gtk_tree_view_install_mark_rows_col_dirty (GtkTreeView *tree_view)
+{
+  tree_view->priv->mark_rows_col_dirty = TRUE;
+
+  install_presize_handler (tree_view);
+}
+
+/* Drag-and-drop */
+
+static void
+set_source_row (GdkDragContext *context,
+                GtkTreeModel   *model,
+                GtkTreePath    *source_row)
+{
+  g_object_set_data_full (G_OBJECT (context),
+                          "gtk-tree-view-source-row",
+                          source_row ? gtk_tree_row_reference_new (model, source_row) : NULL,
+                          (GDestroyNotify) (source_row ? gtk_tree_row_reference_free : NULL));
+}
+
+static GtkTreePath*
+get_source_row (GdkDragContext *context)
+{
+  GtkTreeRowReference *ref =
+    g_object_get_data (G_OBJECT (context), "gtk-tree-view-source-row");
+
+  if (ref)
+    return gtk_tree_row_reference_get_path (ref);
+  else
+    return NULL;
+}
+
+
+static void
+set_dest_row (GdkDragContext *context,
+              GtkTreeModel   *model,
+              GtkTreePath    *dest_row)
+{
+  g_object_set_data_full (G_OBJECT (context),
+                          "gtk-tree-view-dest-row",
+                          dest_row ? gtk_tree_row_reference_new (model, dest_row) : NULL,
+                          (GDestroyNotify) (dest_row ? gtk_tree_row_reference_free : NULL));
+}
+
+static GtkTreePath*
+get_dest_row (GdkDragContext *context)
+{
+  GtkTreeRowReference *ref =
+    g_object_get_data (G_OBJECT (context), "gtk-tree-view-dest-row");
+
+  if (ref)
+    return gtk_tree_row_reference_get_path (ref);
+  else
+    return NULL;
+}
+
+/* Get/set whether drag_motion requested the drag data and
+ * drag_data_received should thus not actually insert the data,
+ * since the data doesn't result from a drop.
+ */
+static void
+set_status_pending (GdkDragContext *context,
+                    GdkDragAction   suggested_action)
+{
+  g_object_set_data (G_OBJECT (context),
+                     "gtk-tree-view-status-pending",
+                     GINT_TO_POINTER (suggested_action));
+}
+
+static GdkDragAction
+get_status_pending (GdkDragContext *context)
+{
+  return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
+                                             "gtk-tree-view-status-pending"));
+}
+
+static TreeViewDragInfo*
+get_info (GtkTreeView *tree_view)
+{
+  return g_object_get_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info");
+}
+
+static void
+clear_source_info (TreeViewDragInfo *di)
+{
+  if (di->source_target_list)
+    gtk_target_list_unref (di->source_target_list);
+
+  di->source_target_list = NULL;
+}
+
+static void
+clear_dest_info (TreeViewDragInfo *di)
+{
+  if (di->dest_target_list)
+    gtk_target_list_unref (di->dest_target_list);
+
+  di->dest_target_list = NULL;
+}
+
+static void
+destroy_info (TreeViewDragInfo *di)
+{
+  clear_source_info (di);
+  clear_dest_info (di);
+  g_free (di);
+}
+
+static TreeViewDragInfo*
+ensure_info (GtkTreeView *tree_view)
+{
+  TreeViewDragInfo *di;
+
+  di = get_info (tree_view);
+
+  if (di == NULL)
+    {
+      di = g_new0 (TreeViewDragInfo, 1);
+
+      g_object_set_data_full (G_OBJECT (tree_view),
+                              "gtk-tree-view-drag-info",
+                              di,
+                              (GDestroyNotify) destroy_info);
+    }
+
+  return di;
+}
+
+static void
+remove_info (GtkTreeView *tree_view)
 {
   g_object_set_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info", NULL);
 }
@@ -3175,6 +3603,7 @@ drag_scan_timeout (gpointer data)
           gtk_tree_view_scroll_to_cell (tree_view,
                                         path,
                                         column,
+                                       TRUE,
                                         0.5, 0.5);
 
           gtk_tree_path_free (path);
@@ -3240,7 +3669,7 @@ open_row_timeout (gpointer data)
   gboolean result = FALSE;
 
   GDK_THREADS_ENTER ();
-  
+
   gtk_tree_view_get_drag_dest_row (tree_view,
                                    &dest_path,
                                    &pos);
@@ -3258,10 +3687,10 @@ open_row_timeout (gpointer data)
     {
       if (dest_path)
         gtk_tree_path_free (dest_path);
-      
+
       result = TRUE;
     }
-  
+
   GDK_THREADS_LEAVE ();
 
   return result;
@@ -3418,31 +3847,31 @@ gtk_tree_view_maybe_begin_dragging_row (GtkTreeView      *tree_view,
   gint button;
   gint cell_x, cell_y;
   GtkTreeModel *model;
+  gboolean retval = FALSE;
 
   di = get_info (tree_view);
 
   if (di == NULL)
-    return FALSE;
+    goto out;
 
   if (tree_view->priv->pressed_button < 0)
-    return FALSE;
+    goto out;
 
   if (!gtk_drag_check_threshold (GTK_WIDGET (tree_view),
                                  tree_view->priv->press_start_x,
                                  tree_view->priv->press_start_y,
                                  event->x, event->y))
-    return FALSE;
+    goto out;
 
   model = gtk_tree_view_get_model (tree_view);
 
   if (model == NULL)
-    return FALSE;
+    goto out;
 
   button = tree_view->priv->pressed_button;
   tree_view->priv->pressed_button = -1;
 
   gtk_tree_view_get_path_at_pos (tree_view,
-                                 tree_view->priv->bin_window,
                                  tree_view->priv->press_start_x,
                                  tree_view->priv->press_start_y,
                                  &path,
@@ -3451,16 +3880,21 @@ gtk_tree_view_maybe_begin_dragging_row (GtkTreeView      *tree_view,
                                  &cell_y);
 
   if (path == NULL)
-    return FALSE;
+    goto out;
 
-  /* FIXME if the path doesn't match the row_draggable predicate,
-   * return FALSE and free path
-   */
+  if (!GTK_IS_TREE_DRAG_SOURCE (model) ||
+      !gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (model),
+                                          path))
+    goto out;
 
   /* FIXME Check whether we're a start button, if not return FALSE and
    * free path
    */
 
+  /* Now we can begin the drag */
+
+  retval = TRUE;
+
   context = gtk_drag_begin (GTK_WIDGET (tree_view),
                             di->source_target_list,
                             di->source_actions,
@@ -3487,9 +3921,12 @@ gtk_tree_view_maybe_begin_dragging_row (GtkTreeView      *tree_view,
   }
 
   set_source_row (context, model, path);
-  gtk_tree_path_free (path);
 
-  return TRUE;
+ out:
+  if (path)
+    gtk_tree_path_free (path);
+
+  return retval;
 }
 
 
@@ -3551,9 +3988,9 @@ gtk_tree_view_drag_data_get (GtkWidget        *widget,
   /* If drag_data_get does nothing, try providing row data. */
   if (selection_data->target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
     {
-      gtk_selection_data_set_tree_row (selection_data,
-                                       model,
-                                       source_row);
+      gtk_tree_set_row_drag_data (selection_data,
+                                 model,
+                                 source_row);
     }
 
  done:
@@ -3631,8 +4068,6 @@ gtk_tree_view_drag_motion (GtkWidget        *widget,
   if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
     return FALSE;
 
-  //  gtk_tree_view_ensure_scroll_timeout (tree_view);
-
   gtk_tree_view_get_drag_dest_row (tree_view, &path, &pos);
 
   if (path == NULL)
@@ -3778,24 +4213,10 @@ gtk_tree_view_drag_data_received (GtkWidget        *widget,
 
       if (suggested_action)
         {
-          GtkTreeModel *src_model = NULL;
-          GtkTreePath *src_path = NULL;
-
-          if (!gtk_selection_data_get_tree_row (selection_data,
-                                                &src_model,
-                                                &src_path))
-            suggested_action = 0;
-
-          if (suggested_action)
-            {
-              if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
-                                                         src_model,
-                                                         src_path,
-                                                         path))
-                suggested_action = 0;
-
-              gtk_tree_path_free (src_path);
-            }
+         if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
+                                                    path,
+                                                    selection_data))
+           suggested_action = 0;
         }
 
       gdk_drag_status (context, suggested_action, time);
@@ -3946,6 +4367,8 @@ gtk_tree_view_header_focus (GtkTreeView      *tree_view,
   while (last_column)
     {
       if (GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (last_column->data)->button) &&
+         GTK_TREE_VIEW_COLUMN (last_column->data)->clickable &&
+         GTK_TREE_VIEW_COLUMN (last_column->data)->reorderable &&
          GTK_TREE_VIEW_COLUMN (last_column->data)->visible)
        break;
       last_column = last_column->prev;
@@ -3960,6 +4383,8 @@ gtk_tree_view_header_focus (GtkTreeView      *tree_view,
   while (first_column)
     {
       if (GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (first_column->data)->button) &&
+         GTK_TREE_VIEW_COLUMN (first_column->data)->clickable &&
+         GTK_TREE_VIEW_COLUMN (last_column->data)->reorderable &&
          GTK_TREE_VIEW_COLUMN (first_column->data)->visible)
        break;
       first_column = first_column->next;
@@ -4081,16 +4506,6 @@ gtk_tree_view_header_focus (GtkTreeView      *tree_view,
   return (focus_child != NULL);
 }
 
-/* We make the assumption that if container->focus_child != NULL, the focus must
- * be in the header.  For now, this is accurate.  It may not be in the future.
- */
-
-/* The sordid relationship between focus_column and scroll_column:
- *
- * The focus_column represents the column that currently has keyboard focus, and
- * is used when navigating columns by keyboard.  scroll_column is used for
- * handling scrolling by keyboard, such that in cases.
- */
 static gint
 gtk_tree_view_focus (GtkWidget        *widget,
                     GtkDirectionType  direction)
@@ -4110,6 +4525,7 @@ gtk_tree_view_focus (GtkWidget        *widget,
 
   focus_child = container->focus_child;
 
+  gtk_tree_view_stop_editing (GTK_TREE_VIEW (widget));
   /* Case 1.  Headers currently have focus. */
   if (focus_child)
     {
@@ -4243,29 +4659,6 @@ gtk_tree_view_set_adjustments (GtkTreeView   *tree_view,
     gtk_tree_view_adjustment_changed (NULL, tree_view);
 }
 
-static void
-gtk_tree_view_real_begin_extended_selection (GtkTreeView *tree_view)
-{
-  tree_view->priv->in_extended_selection = TRUE;
-}
-
-static void
-gtk_tree_view_real_end_extended_selection (GtkTreeView *tree_view)
-{
-  tree_view->priv->in_extended_selection = FALSE;
-}
-
-static void
-gtk_tree_view_real_begin_free_motion (GtkTreeView *tree_view)
-{
-  tree_view->priv->in_free_motion = TRUE;
-}
-
-static void
-gtk_tree_view_real_end_free_motion (GtkTreeView *tree_view)
-{
-  tree_view->priv->in_free_motion = FALSE;
-}
 
 static void
 gtk_tree_view_real_move_cursor (GtkTreeView       *tree_view,
@@ -4281,7 +4674,7 @@ gtk_tree_view_real_move_cursor (GtkTreeView       *tree_view,
 
   if (tree_view->priv->tree == NULL)
     return;
-
+  gtk_tree_view_stop_editing (tree_view);
   GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
 
@@ -4306,25 +4699,86 @@ gtk_tree_view_real_move_cursor (GtkTreeView       *tree_view,
     }
 }
 
+static void
+gtk_tree_view_put (GtkTreeView *tree_view,
+                  GtkWidget   *child_widget,
+                  gint         x,
+                  gint         y,
+                  gint         width,
+                  gint         height)
+{
+  GtkTreeViewChild *child;
+
+  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+  g_return_if_fail (GTK_IS_WIDGET (child_widget));
+
+  child = g_new (GtkTreeViewChild, 1);
+
+  child->widget = child_widget;
+  child->x = x;
+  child->y = y;
+  child->width = width;
+  child->height = height;
+
+  tree_view->priv->children = g_list_append (tree_view->priv->children, child);
+
+  if (GTK_WIDGET_REALIZED (tree_view))
+    gtk_widget_set_parent_window (child->widget, tree_view->priv->bin_window);
+
+  gtk_widget_set_parent (child_widget, GTK_WIDGET (tree_view));
+}
+
+void
+_gtk_tree_view_child_move_resize (GtkTreeView *tree_view,
+                                 GtkWidget   *widget,
+                                 gint         x,
+                                 gint         y,
+                                 gint         width,
+                                 gint         height)
+{
+  GtkTreeViewChild *child = NULL;
+  GList *list;
+  GdkRectangle allocation;
+
+  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  for (list = tree_view->priv->children; list; list = list->next)
+    {
+      if (((GtkTreeViewChild *)list->data)->widget == widget)
+       {
+         child = list->data;
+         break;
+       }
+    }
+  if (child == NULL)
+    return;
+
+  allocation.x = child->x = x;
+  allocation.y = child->y = y;
+  allocation.width = child->width = width;
+  allocation.height = child->height = height;
+
+  if (GTK_WIDGET_REALIZED (widget))
+    gtk_widget_size_allocate (widget, &allocation);
+}
+
+
 /* TreeModel Callbacks
  */
 
 static void
-gtk_tree_view_range_changed (GtkTreeModel *model,
-                            GtkTreePath  *path,
-                            GtkTreeIter  *iter,
-                            GtkTreePath  *end_path,
-                            GtkTreeIter  *end_iter,
-                            gpointer      data)
+gtk_tree_view_row_changed (GtkTreeModel *model,
+                          GtkTreePath  *path,
+                          GtkTreeIter  *iter,
+                          gpointer      data)
 {
   GtkTreeView *tree_view = (GtkTreeView *)data;
   GtkRBTree *tree;
   GtkRBNode *node;
-  gint height;
-  gboolean dirty_marked;
   gboolean free_path = FALSE;
   gint vertical_separator;
-
+  GList *list;
 
   g_return_if_fail (path != NULL || iter != NULL);
 
@@ -4348,22 +4802,21 @@ gtk_tree_view_range_changed (GtkTreeModel *model,
   if (tree == NULL)
     goto done;
 
-  dirty_marked = gtk_tree_view_discover_dirty_iter (tree_view,
-                                                   iter,
-                                                   gtk_tree_path_get_depth (path),
-                                                   &height,
-                                                   node);
-
-  if (GTK_RBNODE_GET_HEIGHT (node) != height + vertical_separator)
+  _gtk_rbtree_node_mark_invalid (tree, node);
+  for (list = tree_view->priv->columns; list; list = list->next)
     {
-      _gtk_rbtree_node_set_height (tree, node, height + vertical_separator);
-      gtk_widget_queue_resize (GTK_WIDGET (data));
-      goto done;
+      GtkTreeViewColumn *column;
+
+      column = list->data;
+      if (! column->visible)
+       continue;
+
+      if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
+       {
+         gtk_tree_view_column_cell_set_dirty (column);
+       }
     }
-  if (dirty_marked)
-    gtk_widget_queue_resize (GTK_WIDGET (data));
-  else
-    gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
+  install_presize_handler (tree_view);
 
  done:
   if (free_path)
@@ -4371,24 +4824,19 @@ gtk_tree_view_range_changed (GtkTreeModel *model,
 }
 
 static void
-gtk_tree_view_inserted (GtkTreeModel *model,
-                       GtkTreePath  *path,
-                       GtkTreeIter  *iter,
-                       gpointer      data)
+gtk_tree_view_row_inserted (GtkTreeModel *model,
+                           GtkTreePath  *path,
+                           GtkTreeIter  *iter,
+                           gpointer      data)
 {
   GtkTreeView *tree_view = (GtkTreeView *) data;
   gint *indices;
   GtkRBTree *tmptree, *tree;
   GtkRBNode *tmpnode = NULL;
-  gint max_height;
   gint depth;
   gint i = 0;
   gboolean free_path = FALSE;
 
-  if (tree_view->priv->tree == NULL)
-    tree_view->priv->tree = _gtk_rbtree_new ();
-
-  tmptree = tree = tree_view->priv->tree;
   g_return_if_fail (path != NULL || iter != NULL);
 
   if (path == NULL)
@@ -4399,9 +4847,13 @@ gtk_tree_view_inserted (GtkTreeModel *model,
   else if (iter == NULL)
     gtk_tree_model_get_iter (model, iter, path);
 
+  if (tree_view->priv->tree == NULL)
+    tree_view->priv->tree = _gtk_rbtree_new ();
+
+  tmptree = tree = tree_view->priv->tree;
+
   /* Update all row-references */
   gtk_tree_row_reference_inserted (G_OBJECT (data), path);
-
   depth = gtk_tree_path_get_depth (path);
   indices = gtk_tree_path_get_indices (path);
 
@@ -4431,7 +4883,7 @@ gtk_tree_view_inserted (GtkTreeModel *model,
          GtkTreePath *tmppath = _gtk_tree_view_find_path (tree_view,
                                                           tree,
                                                           tmpnode);
-         gtk_tree_view_has_child_toggled (model, tmppath, NULL, data);
+         gtk_tree_view_row_has_child_toggled (model, tmppath, NULL, data);
          gtk_tree_path_free (tmppath);
           goto done;
        }
@@ -4446,22 +4898,17 @@ gtk_tree_view_inserted (GtkTreeModel *model,
 
   /* ref the node */
   gtk_tree_model_ref_node (tree_view->priv->model, iter);
-  max_height = gtk_tree_view_insert_iter_height (tree_view,
-                                                tree,
-                                                iter,
-                                                depth);
   if (indices[depth - 1] == 0)
     {
       tmpnode = _gtk_rbtree_find_count (tree, 1);
-      _gtk_rbtree_insert_before (tree, tmpnode, max_height);
+      _gtk_rbtree_insert_before (tree, tmpnode, 0, FALSE);
     }
   else
     {
       tmpnode = _gtk_rbtree_find_count (tree, indices[depth - 1]);
-      _gtk_rbtree_insert_after (tree, tmpnode, max_height);
+      _gtk_rbtree_insert_after (tree, tmpnode, 0, FALSE);
     }
-
-  _gtk_tree_view_update_size (tree_view);
+  install_presize_handler (tree_view);
 
  done:
   if (free_path)
@@ -4469,10 +4916,10 @@ gtk_tree_view_inserted (GtkTreeModel *model,
 }
 
 static void
-gtk_tree_view_has_child_toggled (GtkTreeModel *model,
-                                GtkTreePath  *path,
-                                GtkTreeIter  *iter,
-                                gpointer      data)
+gtk_tree_view_row_has_child_toggled (GtkTreeModel *model,
+                                    GtkTreePath  *path,
+                                    GtkTreeIter  *iter,
+                                    gpointer      data)
 {
   GtkTreeView *tree_view = (GtkTreeView *)data;
   GtkTreeIter real_iter;
@@ -4526,6 +4973,7 @@ gtk_tree_view_has_child_toggled (GtkTreeModel *model,
            if (GTK_TREE_VIEW_COLUMN (list->data)->visible)
              {
                GTK_TREE_VIEW_COLUMN (list->data)->dirty = TRUE;
+               gtk_tree_view_column_cell_set_dirty (GTK_TREE_VIEW_COLUMN (list->data));
                break;
              }
        }
@@ -4553,33 +5001,33 @@ count_children_helper (GtkRBTree *tree,
 }
 
 static void
-gtk_tree_view_deleted (GtkTreeModel *model,
-                      GtkTreePath  *path,
-                      gpointer      data)
+gtk_tree_view_row_deleted (GtkTreeModel *model,
+                          GtkTreePath  *path,
+                          gpointer      data)
 {
   GtkTreeView *tree_view = (GtkTreeView *)data;
   GtkRBTree *tree;
   GtkRBNode *node;
   GList *list;
+  gint selection_changed;
 
   g_return_if_fail (path != NULL);
 
+  gtk_tree_row_reference_deleted (G_OBJECT (data), path);
+
   if (_gtk_tree_view_find_node (tree_view, path, &tree, &node))
     return;
 
   if (tree == NULL)
     return;
 
-  gtk_tree_row_reference_deleted (G_OBJECT (data), path);
-
   /* Change the selection */
-  if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
-    g_signal_emit_by_name (G_OBJECT (tree_view->priv->selection), "changed");
+  selection_changed = GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED);
 
   for (list = tree_view->priv->columns; list; list = list->next)
     if (((GtkTreeViewColumn *)list->data)->visible &&
        ((GtkTreeViewColumn *)list->data)->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
-      ((GtkTreeViewColumn *)list->data)->dirty = TRUE;
+      gtk_tree_view_column_cell_set_dirty ((GtkTreeViewColumn *)list->data);
 
   /* Ensure we don't have a dangling pointer to a dead node */
   ensure_unprelighted (tree_view);
@@ -4595,7 +5043,7 @@ gtk_tree_view_deleted (GtkTreeModel *model,
       GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_EXPANDED);
       tree_view->priv->expanded_collapsed_node = NULL;
     }
-  
+
   if (tree_view->priv->destroy_count_func)
     {
       gint child_count = 0;
@@ -4616,16 +5064,19 @@ gtk_tree_view_deleted (GtkTreeModel *model,
       _gtk_rbtree_remove_node (tree, node);
     }
 
-  _gtk_tree_view_update_size (GTK_TREE_VIEW (data));
+  gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+
+  if (selection_changed)
+    g_signal_emit_by_name (G_OBJECT (tree_view->priv->selection), "changed");
 }
 
 
 static void
-gtk_tree_view_reordered (GtkTreeModel *model,
-                        GtkTreePath  *parent,
-                        GtkTreeIter  *iter,
-                        gint         *new_order,
-                        gpointer      data)
+gtk_tree_view_rows_reordered (GtkTreeModel *model,
+                             GtkTreePath  *parent,
+                             GtkTreeIter  *iter,
+                             gint         *new_order,
+                             gpointer      data)
 {
   GtkTreeView *tree_view = GTK_TREE_VIEW (data);
   GtkRBTree *tree;
@@ -4664,63 +5115,16 @@ gtk_tree_view_reordered (GtkTreeModel *model,
 }
 
 
-/* Internal tree functions
- */
-
-
-static void
-gtk_tree_view_get_background_xrange (GtkTreeView       *tree_view,
-                                     GtkRBTree         *tree,
-                                     GtkTreeViewColumn *column,
-                                     gint              *x1,
-                                     gint              *x2)
-{
-  GtkTreeViewColumn *tmp_column = NULL;
-  gint total_width;
-  GList *list;
-
-  if (x1)
-    *x1 = 0;
-
-  if (x2)
-    *x2 = 0;
-
-  total_width = 0;
-  for (list = tree_view->priv->columns; list; list = list->next)
-    {
-      tmp_column = list->data;
-
-      if (tmp_column == column)
-        break;
-
-      if (tmp_column->visible)
-        total_width += tmp_column->width;
-    }
-
-  if (tmp_column != column)
-    {
-      g_warning (G_STRLOC": passed-in column isn't in the tree");
-      return;
-    }
-
-  if (x1)
-    *x1 = total_width;
-
-  if (x2)
-    {
-      if (column->visible)
-        *x2 = total_width + column->width;
-      else
-        *x2 = total_width; /* width of 0 */
-    }
-}
-
+/* Internal tree functions
+ */
+
+
 static void
-gtk_tree_view_get_cell_xrange (GtkTreeView       *tree_view,
-                               GtkRBTree         *tree,
-                               GtkTreeViewColumn *column,
-                               gint              *x1,
-                               gint              *x2)
+gtk_tree_view_get_background_xrange (GtkTreeView       *tree_view,
+                                     GtkRBTree         *tree,
+                                     GtkTreeViewColumn *column,
+                                     gint              *x1,
+                                     gint              *x2)
 {
   GtkTreeViewColumn *tmp_column = NULL;
   gint total_width;
@@ -4750,27 +5154,20 @@ gtk_tree_view_get_cell_xrange (GtkTreeView       *tree_view,
       return;
     }
 
-  /* Remember we're getting the cell range, i.e. the cell_area passed
-   * to the cell renderer.
-   */
-
-  if (gtk_tree_view_is_expander_column (tree_view, column))
-    total_width += tree_view->priv->tab_offset * _gtk_rbtree_get_depth (tree);
-
   if (x1)
     *x1 = total_width;
 
   if (x2)
     {
       if (column->visible)
-        *x2 = total_width + column->displayed_width;
+        *x2 = total_width + column->width;
       else
         *x2 = total_width; /* width of 0 */
     }
 }
-
 static void
 gtk_tree_view_get_arrow_xrange (GtkTreeView *tree_view,
+                               GtkRBTree   *tree,
                                 gint        *x1,
                                 gint        *x2)
 {
@@ -4778,6 +5175,7 @@ gtk_tree_view_get_arrow_xrange (GtkTreeView *tree_view,
   GList *list;
   GtkTreeViewColumn *tmp_column = NULL;
   gint total_width;
+  gboolean indent_expanders;
 
   total_width = 0;
   for (list = tree_view->priv->columns; list; list = list->next)
@@ -4794,6 +5192,13 @@ gtk_tree_view_get_arrow_xrange (GtkTreeView *tree_view,
         total_width += tmp_column->width;
     }
 
+  gtk_widget_style_get (GTK_WIDGET (tree_view),
+                       "indent_expanders", &indent_expanders,
+                       NULL);
+
+  if (indent_expanders)
+    x_offset += tree_view->priv->tab_offset * _gtk_rbtree_get_depth (tree);
+
   if (x1)
     *x1 = x_offset;
 
@@ -4811,71 +5216,19 @@ gtk_tree_view_get_arrow_xrange (GtkTreeView *tree_view,
     }
 }
 
-static gint
-gtk_tree_view_insert_iter_height (GtkTreeView *tree_view,
-                                 GtkRBTree   *tree,
-                                 GtkTreeIter *iter,
-                                 gint         depth)
-{
-  GtkTreeViewColumn *column;
-  GList *list;
-  gint max_height = 0;
-  gint vertical_separator;
-  
-  gtk_widget_style_get (GTK_WIDGET (tree_view),        "vertical_separator", &vertical_separator, NULL);
-  
-  /* do stuff with node */
-  for (list = tree_view->priv->columns; list; list = list->next)
-    {
-      gint height = 0, width = 0;
-      column = list->data;
-
-      if (!column->visible)
-       continue;
-
-      if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
-        continue;
-
-      gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, iter,
-                                              gtk_tree_model_iter_has_child (tree_view->priv->model, iter),
-                                              FALSE);
-
-      gtk_tree_view_column_cell_get_size (column, NULL, NULL, NULL, &width, &height);
-      max_height = MAX (max_height, vertical_separator + height);
-
-      if (gtk_tree_view_is_expander_column (tree_view, column) &&
-          TREE_VIEW_DRAW_EXPANDERS (tree_view))
-       _gtk_tree_view_column_set_width (column,
-                                        MAX (column->width, depth * tree_view->priv->tab_offset + width));
-      else
-        _gtk_tree_view_column_set_width (column,
-                                        MAX (column->width, width));
-    }
-  return max_height;
-}
-
 static void
 gtk_tree_view_build_tree (GtkTreeView *tree_view,
                          GtkRBTree   *tree,
                          GtkTreeIter *iter,
                          gint         depth,
-                         gboolean     recurse,
-                         gboolean     calc_bounds)
+                         gboolean     recurse)
 {
   GtkRBNode *temp = NULL;
-  gint max_height;
 
   do
     {
-      max_height = 0;
-      if (calc_bounds)
-       max_height = gtk_tree_view_insert_iter_height (tree_view,
-                                                      tree,
-                                                      iter,
-                                                      depth);
-
       gtk_tree_model_ref_node (tree_view->priv->model, iter);
-      temp = _gtk_rbtree_insert_after (tree, temp, max_height);
+      temp = _gtk_rbtree_insert_after (tree, temp, 0, FALSE);
       if (recurse)
        {
          GtkTreeIter child;
@@ -4885,7 +5238,7 @@ gtk_tree_view_build_tree (GtkTreeView *tree_view,
              temp->children = _gtk_rbtree_new ();
              temp->children->parent_tree = tree;
              temp->children->parent_node = temp;
-             gtk_tree_view_build_tree (tree_view, temp->children, &child, depth + 1, recurse, calc_bounds);
+             gtk_tree_view_build_tree (tree_view, temp->children, &child, depth + 1, recurse);
            }
        }
       if (gtk_tree_model_iter_has_child (tree_view->priv->model, iter))
@@ -4898,71 +5251,9 @@ gtk_tree_view_build_tree (GtkTreeView *tree_view,
   while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
 }
 
-static void
-gtk_tree_view_calc_size (GtkTreeView *tree_view,
-                        GtkRBTree   *tree,
-                        GtkTreeIter *iter,
-                        gint         depth)
-{
-  GtkRBNode *temp;
-  GtkTreeIter child;
-  GList *list;
-  GtkTreeViewColumn *column;
-  gint max_height;
-  gint vertical_separator;
-  
-  TREE_VIEW_INTERNAL_ASSERT_VOID (tree != NULL);
-
-  gtk_widget_style_get (GTK_WIDGET (tree_view),        "vertical_separator", &vertical_separator, NULL);
-
-  temp = tree->root;
-  while (temp->left != tree->nil)
-    temp = temp->left;
-
-  do
-    {
-      max_height = 0;
-      /* Do stuff with node */
-      for (list = tree_view->priv->columns; list; list = list->next)
-       {
-         gint height = 0, width = 0;
-         column = list->data;
-
-         if (!column->visible)
-           continue;
-
-         gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, iter,
-                                                  GTK_RBNODE_FLAG_SET (temp, GTK_RBNODE_IS_PARENT),
-                                                  temp->children?TRUE:FALSE);
-         gtk_tree_view_column_cell_get_size (column, NULL, NULL, NULL, &width, &height);
-         max_height = MAX (max_height, vertical_separator + height);
-
-         /* FIXME: I'm getting the width of all nodes here. )-: */
-         if (column->dirty == FALSE)
-           continue;
-
-         if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
-           {
-             continue;
-           }
-         if (gtk_tree_view_is_expander_column (tree_view, column) &&
-              TREE_VIEW_DRAW_EXPANDERS (tree_view))
-            _gtk_tree_view_column_set_width (column,
-                                            MAX (column->width, depth * tree_view->priv->tab_offset + width));
-         else
-            _gtk_tree_view_column_set_width (column, MAX (column->width, width));
-       }
-
-      _gtk_rbtree_node_set_height (tree, temp, max_height);
-
-      if (temp->children != NULL &&
-         gtk_tree_model_iter_children (tree_view->priv->model, &child, iter))
-       gtk_tree_view_calc_size (tree_view, temp->children, &child, depth + 1);
-      temp = _gtk_rbtree_next (tree, temp);
-    }
-  while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
-}
-
+/* If height is non-NULL, then we set it to be the new height.  if it's all
+ * dirty, then height is -1.  We know we'll remeasure dirty rows, anyways.
+ */
 static gboolean
 gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view,
                                   GtkTreeIter *iter,
@@ -4974,24 +5265,31 @@ gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view,
   GList *list;
   gboolean retval = FALSE;
   gint tmpheight;
-  
+  gint horizontal_separator;
+
+  gtk_widget_style_get (GTK_WIDGET (tree_view),
+                       "horizontal_separator", &horizontal_separator,
+                       NULL);
+
+
   if (height)
-    *height = 0;
+    *height = -1;
 
   for (list = tree_view->priv->columns; list; list = list->next)
     {
       gint width;
       column = list->data;
-      if (column->dirty == TRUE || column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
+      if (column->dirty == TRUE)
+       continue;
+      if (height == NULL && column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
        continue;
       if (!column->visible)
        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);
 
-
       if (height)
        {
          gtk_tree_view_column_cell_get_size (column,
@@ -5005,20 +5303,21 @@ gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view,
                                              NULL, NULL, NULL,
                                              &width, NULL);
        }
+
       if (gtk_tree_view_is_expander_column (tree_view, column) &&
           TREE_VIEW_DRAW_EXPANDERS (tree_view))
        {
-         if (depth * tree_view->priv->tab_offset + width > column->width)
+         if (depth * tree_view->priv->tab_offset + horizontal_separator + width > column->requested_width)
            {
-             column->dirty = TRUE;
+             gtk_tree_view_column_cell_set_dirty (column);
              retval = TRUE;
            }
        }
       else
        {
-         if (width > column->width)
+         if (horizontal_separator + width > column->requested_width)
            {
-             column->dirty = TRUE;
+             gtk_tree_view_column_cell_set_dirty (column);
              retval = TRUE;
            }
        }
@@ -5064,7 +5363,7 @@ gtk_tree_view_discover_dirty (GtkTreeView *tree_view,
       gtk_tree_view_discover_dirty_iter (tree_view,
                                         iter,
                                         depth,
-                                        FALSE,
+                                        NULL,
                                         temp);
       if (gtk_tree_model_iter_children (tree_view->priv->model, &child, iter) &&
          temp->children != NULL)
@@ -5075,55 +5374,6 @@ gtk_tree_view_discover_dirty (GtkTreeView *tree_view,
 }
 
 
-static void
-gtk_tree_view_check_dirty (GtkTreeView *tree_view)
-{
-  GtkTreePath *path;
-  gboolean dirty = FALSE;
-  GList *list;
-  GtkTreeViewColumn *column;
-  GtkTreeIter iter;
-
-  for (list = tree_view->priv->columns; list; list = list->next)
-    {
-      column = list->data;
-      if (column->dirty)
-       {
-         dirty = TRUE;
-         if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
-           {
-              gint w = 1;
-
-              if (column->button)
-                w = MAX (w, column->button->requisition.width);
-
-              _gtk_tree_view_column_set_width (column, w);
-           }
-       }
-    }
-
-  if (dirty == FALSE)
-    return;
-
-  if (tree_view->priv->model == NULL)
-    return;
-
-  path = gtk_tree_path_new_root ();
-  if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, path))
-    {
-      gtk_tree_view_calc_size (tree_view, tree_view->priv->tree, &iter, 1);
-      _gtk_tree_view_update_size (tree_view);
-    }
-
-  gtk_tree_path_free (path);
-
-  for (list = tree_view->priv->columns; list; list = list->next)
-    {
-      column = list->data;
-      column->dirty = FALSE;
-    }
-}
-
 /* Make sure the node is visible vertically */
 static void
 gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view,
@@ -5154,10 +5404,24 @@ gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view,
 
 }
 
-/* This function could be more efficient.
- * I'll optimize it if profiling seems to imply that
- * it's important
- */
+static void
+gtk_tree_view_clamp_column_visible (GtkTreeView       *tree_view,
+                                   GtkTreeViewColumn *column)
+{
+  if (column == NULL)
+    return;
+  if ((tree_view->priv->hadjustment->value + tree_view->priv->hadjustment->page_size) <
+      (column->button->allocation.x + column->button->allocation.width))
+    gtk_adjustment_set_value (tree_view->priv->hadjustment,
+                             column->button->allocation.x + column->button->allocation.width -
+                             tree_view->priv->hadjustment->page_size);
+  else if (tree_view->priv->hadjustment->value > column->button->allocation.x)
+    gtk_adjustment_set_value (tree_view->priv->hadjustment,
+                             column->button->allocation.x);
+}
+
+/* This function could be more efficient.  I'll optimize it if profiling seems
+ * to imply that it is important */
 GtkTreePath *
 _gtk_tree_view_find_path (GtkTreeView *tree_view,
                          GtkRBTree   *tree,
@@ -5251,6 +5515,9 @@ gtk_tree_view_is_expander_column (GtkTreeView       *tree_view,
 {
   GList *list;
 
+  if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IS_LIST))
+    return FALSE;
+
   if (tree_view->priv->expander_column != NULL)
     {
       if (tree_view->priv->expander_column == column)
@@ -5346,6 +5613,9 @@ gtk_tree_view_unref_and_check_selection_tree (GtkTreeView *tree_view,
   GtkRBNode *node;
   gint retval;
 
+  if (!tree)
+    return FALSE;
+
   node = tree->root;
   while (node && node->left != tree->nil)
     node = node->left;
@@ -5514,7 +5784,7 @@ _gtk_tree_view_column_start_drag (GtkTreeView       *tree_view,
   send_event.button.axes = NULL;
   send_event.button.state = 0;
   send_event.button.button = 1;
-  send_event.button.device = gdk_core_pointer;
+  send_event.button.device = gdk_device_get_core_pointer ();
   send_event.button.x_root = 0;
   send_event.button.y_root = 0;
 
@@ -5573,9 +5843,9 @@ gtk_tree_view_queue_draw_arrow (GtkTreeView      *tree_view,
   if (clip_rect)
     {
       GdkRectangle new_rect;
-      
+
       gdk_rectangle_intersect (clip_rect, &rect, &new_rect);
-      
+
       gdk_window_invalidate_rect (tree_view->priv->bin_window, &new_rect, TRUE);
     }
   else
@@ -5645,7 +5915,7 @@ gtk_tree_view_draw_arrow (GtkTreeView *tree_view,
   gint vertical_separator;
   gint expander_size;
   GtkExpanderStyle expander_style;
-  
+
   gtk_widget_style_get (GTK_WIDGET (tree_view),
                        "vertical_separator", &vertical_separator,
                        "expander_size", &expander_size,
@@ -5656,7 +5926,7 @@ gtk_tree_view_draw_arrow (GtkTreeView *tree_view,
 
   widget = GTK_WIDGET (tree_view);
 
-  gtk_tree_view_get_arrow_xrange (tree_view, &x_offset, NULL);
+  gtk_tree_view_get_arrow_xrange (tree_view, tree, &x_offset, NULL);
 
   area.x = x_offset;
   area.y = CELL_FIRST_PIXEL (tree_view, tree, node, vertical_separator);
@@ -5700,37 +5970,6 @@ gtk_tree_view_draw_arrow (GtkTreeView *tree_view,
                      expander_style);
 }
 
-
-static void
-_gtk_tree_view_update_col_width (GtkTreeView *tree_view)
-{
-  GList *list, *last_column;
-  GtkTreeViewColumn *column;
-  gint width = 0;
-
-  for (last_column = g_list_last (tree_view->priv->columns);
-       last_column &&
-        !(GTK_TREE_VIEW_COLUMN (last_column->data)->visible) &&
-        GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (last_column->data)->button);
-       last_column = last_column->prev)
-    ;
-
-  if (last_column == NULL)
-    return;
-
-  for (list = tree_view->priv->columns; list != last_column; list = list->next)
-    {
-      column = GTK_TREE_VIEW_COLUMN (list->data);
-      if (! column->visible)
-       continue;
-
-      width += column->width;
-      column->displayed_width = (CLAMP (column->width, (column->min_width!=-1)?column->min_width:column->width, (column->max_width!=-1)?column->max_width:column->width));
-    }
-  column = GTK_TREE_VIEW_COLUMN (last_column->data);
-  column->displayed_width = MAX (GTK_WIDGET (tree_view)->allocation.width, tree_view->priv->width) - width;
-}
-
 static void
 gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view)
 
@@ -5750,21 +5989,28 @@ gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view)
 
   if (cursor_path == NULL)
     {
-      GtkTreePath *tmp_path = gtk_tree_path_new_root ();
-      /* FIXME: Get the first one visible!!! */
-      if (tree_view->priv->cursor)
-       gtk_tree_row_reference_free (tree_view->priv->cursor);
+      cursor_path = gtk_tree_path_new_root ();
+      gtk_tree_row_reference_free (tree_view->priv->cursor);
+      tree_view->priv->cursor = NULL;
 
-      tree_view->priv->cursor =
-       gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, tmp_path);
-      cursor_path = tmp_path;
+      if (tree_view->priv->selection->type == GTK_SELECTION_MULTIPLE)
+       gtk_tree_view_real_set_cursor (tree_view, cursor_path, FALSE);
+      else
+       gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE);
     }
-
-  if (tree_view->priv->selection->type == GTK_TREE_SELECTION_SINGLE)
-    gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE);
-  else
-    gtk_tree_view_real_set_cursor (tree_view, cursor_path, FALSE);
   gtk_tree_path_free (cursor_path);
+  if (tree_view->priv->focus_column == NULL)
+    {
+      GList *list;
+      for (list = tree_view->priv->columns; list; list = list->next)
+       {
+         if (GTK_TREE_VIEW_COLUMN (list->data)->visible)
+           {
+             tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (list->data);
+             break;
+           }
+       }
+    }
 }
 
 static void
@@ -5845,9 +6091,7 @@ gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
   _gtk_rbtree_find_offset (tree_view->priv->tree, y, &cursor_tree, &cursor_node);
   cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
   g_return_if_fail (cursor_path != NULL);
-  gtk_tree_view_real_set_cursor (tree_view,
-                                cursor_path,
-                                TRUE);
+  gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE);
 }
 
 static void
@@ -5857,19 +6101,69 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
   GtkRBTree *cursor_tree = NULL;
   GtkRBNode *cursor_node = NULL;
   GtkTreePath *cursor_path = NULL;
-
-  g_print ("gtk_tree_view_move_cursor_left_right\n");
+  GtkTreeViewColumn *column;
+  GtkTreeIter iter;
+  GList *list;
+  gboolean found_column = FALSE;
 
   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
   else
     return;
 
-  _gtk_tree_view_find_node (tree_view, cursor_path,
-                           &cursor_tree, &cursor_node);
+  _gtk_tree_view_find_node (tree_view, cursor_path, &cursor_tree, &cursor_node);
+  if (cursor_tree == NULL)
+    return;
+  if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path) == FALSE)
+    {
+      gtk_tree_path_free (cursor_path);
+      return;
+    }
   gtk_tree_path_free (cursor_path);
 
+  list = tree_view->priv->columns;
+  if (tree_view->priv->focus_column)
+    {
+      for (list = tree_view->priv->columns; list; list = list->next)
+       {
+         if (list->data == tree_view->priv->focus_column)
+           break;
+       }
+    }
+
+  while (list)
+    {
+      column = list->data;
+      if (column->visible == FALSE)
+       goto loop_end;
+
+      gtk_tree_view_column_cell_set_cell_data (column,
+                                              tree_view->priv->model,
+                                              &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))
+       {
+         tree_view->priv->focus_column = column;
+         found_column = TRUE;
+         break;
+       }
+    loop_end:
+      if (count == 1)
+       list = list->next;
+      else
+       list = list->prev;
+    }
 
+  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);
+    }
+  gtk_tree_view_clamp_column_visible (tree_view, tree_view->priv->focus_column);
 }
 
 static void
@@ -5919,13 +6213,23 @@ gtk_tree_view_move_cursor_start_end (GtkTreeView *tree_view,
 }
 
 static void
-gtk_tree_view_real_select_cursor_row (GtkTreeView *tree_view)
+gtk_tree_view_real_select_all (GtkTreeView *tree_view)
+{
+  if (tree_view->priv->selection->type != GTK_SELECTION_MULTIPLE)
+    return;
+  gtk_tree_selection_select_all (tree_view->priv->selection);
+}
+
+static void
+gtk_tree_view_real_select_cursor_row (GtkTreeView *tree_view,
+                                     gboolean     start_editing)
 {
   GtkRBTree *cursor_tree = NULL;
   GtkRBNode *cursor_node = NULL;
   GtkTreePath *cursor_path = NULL;
-
+  GdkModifierType state = 0;
   cursor_path = NULL;
+
   if (tree_view->priv->cursor)
     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
 
@@ -5934,22 +6238,35 @@ gtk_tree_view_real_select_cursor_row (GtkTreeView *tree_view)
 
   _gtk_tree_view_find_node (tree_view, cursor_path,
                            &cursor_tree, &cursor_node);
+
   if (cursor_tree == NULL)
     {
       gtk_tree_path_free (cursor_path);
       return;
     }
-  
+
+  gtk_get_current_event_state (&state);
+
+  if (start_editing && tree_view->priv->focus_column)
+    {
+      if (gtk_tree_view_start_editing (tree_view, cursor_path))
+       {
+         gtk_tree_path_free (cursor_path);
+         return;
+       }
+    }
   _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
                                            cursor_node,
                                            cursor_tree,
                                            cursor_path,
-                                           0);
+                                           state);
 
   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
 
   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
-  gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
+  gtk_tree_view_queue_draw_node (tree_view, cursor_tree, cursor_node, NULL);
+  gtk_tree_view_row_activated (tree_view, cursor_path, tree_view->priv->focus_column);
+
   gtk_tree_path_free (cursor_path);
 }
 
@@ -5997,6 +6314,8 @@ gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView *tree_view,
                                               gboolean     open_all)
 {
   GtkTreePath *cursor_path = NULL;
+  GtkRBTree *tree;
+  GtkRBNode *node;
 
   cursor_path = NULL;
   if (tree_view->priv->cursor)
@@ -6005,13 +6324,17 @@ gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView *tree_view,
   if (cursor_path == NULL)
     return;
 
+  if (_gtk_tree_view_find_node (tree_view, cursor_path, &tree, &node))
+    return;
+  
+  gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+  gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
+
   if (expand)
-    gtk_tree_view_expand_row (tree_view, cursor_path, open_all);
+    gtk_tree_view_real_expand_row (tree_view, cursor_path, tree, node, open_all, TRUE);
   else
-    gtk_tree_view_collapse_row (tree_view, cursor_path);
+    gtk_tree_view_real_collapse_row (tree_view, cursor_path, tree, node, TRUE);
 
-  gtk_widget_grab_focus (GTK_WIDGET (tree_view));
-  gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
   gtk_tree_path_free (cursor_path);
 }
 
@@ -6060,62 +6383,64 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
   gtk_tree_path_free (cursor_path);
 }
 
-void
-_gtk_tree_view_update_size (GtkTreeView *tree_view)
+static void
+gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view)
 {
-  gint width, height;
-  GList *list;
-  GtkTreeViewColumn *column;
-  gint vertical_separator;
-  gint i;
-
-  gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical_separator", &vertical_separator, NULL);
+  GtkWidget *window;
+  GtkWidget *entry;
+  GtkWidget *search_dialog;
 
-  if (tree_view->priv->model == NULL)
-    {
-      tree_view->priv->width = 0;
-      tree_view->priv->height = 0;
-      gtk_widget_queue_draw (GTK_WIDGET (tree_view));
-      return;
-    }
+  if (tree_view->priv->enable_search == FALSE ||
+      tree_view->priv->search_column < 0)
+    return;
 
-  width = 0;
-  for (list = tree_view->priv->columns, i = 0; list; list = list->next, i++)
-    {
-      column = list->data;
-      if (!column->visible)
-       continue;
-      width += TREE_VIEW_COLUMN_WIDTH (column);
-    }
+  search_dialog = gtk_object_get_data (GTK_OBJECT (tree_view),
+                                      GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
+  if (search_dialog)
+    return;
 
-  if (tree_view->priv->tree == NULL)
-    height = 0;
-  else
-    height = tree_view->priv->tree->root->offset + vertical_separator;
+  /* set up window */
+  window = gtk_window_new (GTK_WINDOW_POPUP);
+  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);
+  gtk_signal_connect
+    (GTK_OBJECT (window), "delete_event",
+     GTK_SIGNAL_FUNC (gtk_tree_view_search_delete_event),
+     tree_view);
+  gtk_signal_connect
+    (GTK_OBJECT (window), "key_press_event",
+     GTK_SIGNAL_FUNC (gtk_tree_view_search_key_press_event),
+     tree_view);
+  gtk_signal_connect
+    (GTK_OBJECT (window), "button_press_event",
+     GTK_SIGNAL_FUNC (gtk_tree_view_search_button_press_event),
+     tree_view);
 
-  if (tree_view->priv->width != width)
-    {
-      tree_view->priv->width = width;
-      tree_view->priv->hadjustment->upper = width;
-      gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->hadjustment), "changed");
-    }
+  /* add entry */
+  entry = gtk_entry_new ();
+  gtk_widget_show (entry);
+  gtk_signal_connect
+    (GTK_OBJECT (entry), "changed",
+     GTK_SIGNAL_FUNC (gtk_tree_view_search_init),
+     tree_view);
+  gtk_container_add (GTK_CONTAINER (window), entry);
 
-  if (tree_view->priv->height != height)
-    {
-      tree_view->priv->height = height;
-      tree_view->priv->vadjustment->upper = tree_view->priv->height;
-      gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->vadjustment), "changed");
-    }
+  /* done, show it */
+  tree_view->priv->search_dialog_position_func (tree_view, window);
+  gtk_widget_show_all (window);
+  gtk_widget_grab_focus (entry);
 
-  if (GTK_WIDGET_REALIZED (tree_view))
-    {
-      gdk_window_resize (tree_view->priv->bin_window, MAX (width, GTK_WIDGET (tree_view)->allocation.width), height + TREE_VIEW_HEADER_HEIGHT (tree_view));
-      gdk_window_resize (tree_view->priv->header_window, MAX (width, GTK_WIDGET (tree_view)->allocation.width), tree_view->priv->header_height);
+  /* position window */
 
-      _gtk_tree_view_update_col_width (tree_view);
-    }
+  gtk_object_set_data_full (GTK_OBJECT (window), "gtk-tree-view-text",
+                           g_strdup (gtk_entry_get_text (GTK_ENTRY (entry))),
+                           (GDestroyNotify) g_free);
+  gtk_object_set_data (GTK_OBJECT (tree_view),
+                      GTK_TREE_VIEW_SEARCH_DIALOG_KEY, window);
 
-  gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+  /* search first matching iter */
+  gtk_tree_view_search_init (entry, tree_view);
 }
 
 /* this function returns the new width of the column being resized given
@@ -6159,12 +6484,16 @@ gtk_tree_view_adjustment_changed (GtkAdjustment *adjustment,
 {
   if (GTK_WIDGET_REALIZED (tree_view))
     {
+      gint dy;
       gdk_window_move (tree_view->priv->bin_window,
                       - tree_view->priv->hadjustment->value,
-                      - tree_view->priv->vadjustment->value);
+                      0);
       gdk_window_move (tree_view->priv->header_window,
                       - tree_view->priv->hadjustment->value,
                       0);
+      dy = tree_view->priv->dy - (int) tree_view->priv->vadjustment->value;
+      gdk_window_scroll (tree_view->priv->bin_window, 0, dy);
+      tree_view->priv->dy = (int) tree_view->priv->vadjustment->value;
 
       gdk_window_process_updates (tree_view->priv->bin_window, TRUE);
       gdk_window_process_updates (tree_view->priv->header_window, TRUE);
@@ -6219,10 +6548,10 @@ gtk_tree_view_new_with_model (GtkTreeModel *model)
  * gtk_tree_view_get_model:
  * @tree_view: a #GtkTreeView
  *
- * Returns the model the the #GtkTreeView is based on.  Returns NULL if the
+ * Returns the model the the #GtkTreeView is based on.  Returns %NULL if the
  * model is unset.
  *
- * Return value: A #GtkTreeModel, or NULL if none is currently being used.
+ * Return value: A #GtkTreeModel, or %NULL if none is currently being used.
  **/
 GtkTreeModel *
 gtk_tree_view_get_model (GtkTreeView *tree_view)
@@ -6238,7 +6567,7 @@ gtk_tree_view_get_model (GtkTreeView *tree_view)
  * @model: The model.
  *
  * Sets the model for a #GtkTreeView.  If the @tree_view already has a model
- * set, it will remove it before setting the new model.  If @model is NULL, then
+ * set, it will remove it before setting the new model.  If @model is %NULL, then
  * it will unset the old model.
  **/
 void
@@ -6252,26 +6581,30 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
 
   if (tree_view->priv->model)
     {
+      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),
-                                           gtk_tree_view_range_changed, tree_view);
+                                           gtk_tree_view_row_changed, tree_view);
       g_signal_handlers_disconnect_by_func (G_OBJECT (tree_view->priv->model),
-                                           gtk_tree_view_inserted, tree_view);
+                                           gtk_tree_view_row_inserted, tree_view);
       g_signal_handlers_disconnect_by_func (G_OBJECT (tree_view->priv->model),
-                                           gtk_tree_view_has_child_toggled, tree_view);
+                                           gtk_tree_view_row_has_child_toggled, tree_view);
       g_signal_handlers_disconnect_by_func (G_OBJECT (tree_view->priv->model),
-                                           gtk_tree_view_deleted, tree_view);
+                                           gtk_tree_view_row_deleted, tree_view);
       g_signal_handlers_disconnect_by_func (G_OBJECT (tree_view->priv->model),
-                                           gtk_tree_view_reordered, tree_view);
+                                           gtk_tree_view_rows_reordered, tree_view);
       if (tree_view->priv->tree)
        {
          _gtk_rbtree_free (tree_view->priv->tree);
          tree_view->priv->tree = NULL;
        }
-      if (tree_view->priv->drag_dest_row)
-       {
-         gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
-         tree_view->priv->drag_dest_row = NULL;
-       }
+      gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
+      tree_view->priv->drag_dest_row = NULL;
+      gtk_tree_row_reference_free (tree_view->priv->cursor);
+      tree_view->priv->cursor = NULL;
+      gtk_tree_row_reference_free (tree_view->priv->anchor);
+      tree_view->priv->anchor = NULL;
+
       g_object_unref (tree_view->priv->model);
       tree_view->priv->search_column = -1;
     }
@@ -6299,40 +6632,41 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
        }
       g_object_ref (tree_view->priv->model);
       g_signal_connect (tree_view->priv->model,
-                       "range_changed",
-                       G_CALLBACK (gtk_tree_view_range_changed),
+                       "row_changed",
+                       G_CALLBACK (gtk_tree_view_row_changed),
                        tree_view);
       g_signal_connect (tree_view->priv->model,
-                       "inserted",
-                       G_CALLBACK (gtk_tree_view_inserted),
+                       "row_inserted",
+                       G_CALLBACK (gtk_tree_view_row_inserted),
                        tree_view);
       g_signal_connect (tree_view->priv->model,
-                       "has_child_toggled",
-                       G_CALLBACK (gtk_tree_view_has_child_toggled),
+                       "row_has_child_toggled",
+                       G_CALLBACK (gtk_tree_view_row_has_child_toggled),
                        tree_view);
       g_signal_connect (tree_view->priv->model,
-                       "deleted",
-                       G_CALLBACK (gtk_tree_view_deleted),
+                       "row_deleted",
+                       G_CALLBACK (gtk_tree_view_row_deleted),
                        tree_view);
       g_signal_connect (tree_view->priv->model,
-                       "reordered",
-                       G_CALLBACK (gtk_tree_view_reordered),
+                       "rows_reordered",
+                       G_CALLBACK (gtk_tree_view_rows_reordered),
                        tree_view);
 
       path = gtk_tree_path_new_root ();
       if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, path))
        {
          tree_view->priv->tree = _gtk_rbtree_new ();
-         gtk_tree_view_build_tree (tree_view, tree_view->priv->tree, &iter, 1, FALSE, GTK_WIDGET_REALIZED (tree_view));
+         gtk_tree_view_build_tree (tree_view, tree_view->priv->tree, &iter, 1, FALSE);
        }
       gtk_tree_path_free (path);
 
       /*  FIXME: do I need to do this? gtk_tree_view_create_buttons (tree_view); */
     }
 
-  if (GTK_WIDGET_REALIZED (tree_view))
-    _gtk_tree_view_update_size (tree_view);
   g_object_notify (G_OBJECT (tree_view), "model");
+
+  if (GTK_WIDGET_REALIZED (tree_view))
+    gtk_widget_queue_resize (GTK_WIDGET (tree_view));
 }
 
 /**
@@ -6357,7 +6691,7 @@ gtk_tree_view_get_selection (GtkTreeView *tree_view)
  *
  * Gets the #GtkAdjustment currently being used for the horizontal aspect.
  *
- * Return value: A #GtkAdjustment object, or NULL if none is currently being
+ * Return value: A #GtkAdjustment object, or %NULL if none is currently being
  * used.
  **/
 GtkAdjustment *
@@ -6374,7 +6708,7 @@ gtk_tree_view_get_hadjustment (GtkTreeView *tree_view)
 /**
  * gtk_tree_view_set_hadjustment:
  * @tree_view: A #GtkTreeView
- * @adjustment: The #GtkAdjustment to set, or NULL
+ * @adjustment: The #GtkAdjustment to set, or %NULL
  *
  * Sets the #GtkAdjustment for the current horizontal aspect.
  **/
@@ -6397,7 +6731,7 @@ gtk_tree_view_set_hadjustment (GtkTreeView   *tree_view,
  *
  * Gets the #GtkAdjustment currently being used for the vertical aspect.
  *
- * Return value: A #GtkAdjustment object, or NULL if none is currently being
+ * Return value: A #GtkAdjustment object, or %NULL if none is currently being
  * used.
  **/
 GtkAdjustment *
@@ -6414,7 +6748,7 @@ gtk_tree_view_get_vadjustment (GtkTreeView *tree_view)
 /**
  * gtk_tree_view_set_vadjustment:
  * @tree_view: A #GtkTreeView
- * @adjustment: The #GtkAdjustment to set, or NULL
+ * @adjustment: The #GtkAdjustment to set, or %NULL
  *
  * Sets the #GtkAdjustment for the current vertical aspect.
  **/
@@ -6437,7 +6771,7 @@ gtk_tree_view_set_vadjustment (GtkTreeView   *tree_view,
  * gtk_tree_view_get_headers_visible:
  * @tree_view: A #GtkTreeView.
  *
- * Returns TRUE if the headers on the @tree_view are visible.
+ * Returns %TRUE if the headers on the @tree_view are visible.
  *
  * Return value: Whether the headers are visible or not.
  **/
@@ -6452,7 +6786,7 @@ gtk_tree_view_get_headers_visible (GtkTreeView *tree_view)
 /**
  * gtk_tree_view_set_headers_visible:
  * @tree_view: A #GtkTreeView.
- * @headers_visible: TRUE if the headers are visible
+ * @headers_visible: %TRUE if the headers are visible
  *
  * Sets the the visibility state of the headers.
  **/
@@ -6531,7 +6865,7 @@ gtk_tree_view_columns_autosize (GtkTreeView *tree_view)
       column = list->data;
       if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
        continue;
-      column->dirty = TRUE;
+      gtk_tree_view_column_cell_set_dirty (column);
       dirty = TRUE;
     }
 
@@ -6542,7 +6876,7 @@ gtk_tree_view_columns_autosize (GtkTreeView *tree_view)
 /**
  * gtk_tree_view_set_headers_clickable:
  * @tree_view: A #GtkTreeView.
- * @setting: TRUE if the columns are clickable.
+ * @setting: %TRUE if the columns are clickable.
  *
  * Allow the column title buttons to be clicked.
  **/
@@ -6570,7 +6904,7 @@ gtk_tree_view_set_headers_clickable (GtkTreeView *tree_view,
  * This function tells GTK+ that the user interface for your
  * application requires users to read across tree rows and associate
  * cells with one another. By default, GTK+ will then render the tree
- * with alternating row colors. <emphasis>DO NOT</emphasis> use it
+ * with alternating row colors. Do <emphasis>not</emphasis> use it
  * just because you prefer the appearance of the ruled tree; that's a
  * question for the theme. Some themes will draw tree rows in
  * alternating colors even when rules are turned off, and users who
@@ -6674,7 +7008,7 @@ gtk_tree_view_remove_column (GtkTreeView       *tree_view,
 
          tmp_column = GTK_TREE_VIEW_COLUMN (list->data);
          if (tmp_column->visible)
-           tmp_column->dirty = TRUE;
+           gtk_tree_view_column_cell_set_dirty (tmp_column);
        }
 
       if (tree_view->priv->n_columns == 0 &&
@@ -6736,7 +7070,7 @@ gtk_tree_view_insert_column (GtkTreeView       *tree_view,
        {
          column = GTK_TREE_VIEW_COLUMN (list->data);
          if (column->visible)
-           column->dirty = TRUE;
+           gtk_tree_view_column_cell_set_dirty (column);
        }
       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
     }
@@ -6752,7 +7086,7 @@ gtk_tree_view_insert_column (GtkTreeView       *tree_view,
  * @position: The position to insert the new column in.
  * @title: The title to set the header to.
  * @cell: The #GtkCellRenderer.
- * @Varargs: A NULL terminated list of attributes.
+ * @Varargs: A %NULL-terminated list of attributes.
  *
  * Creates a new #GtkTreeViewColumn and inserts it into the @tree_view at
  * @position.  If @position is -1, then the newly created column is inserted at
@@ -6777,7 +7111,7 @@ gtk_tree_view_insert_column_with_attributes (GtkTreeView     *tree_view,
   column = gtk_tree_view_column_new ();
 
   gtk_tree_view_column_set_title (column, title);
-  gtk_tree_view_column_set_cell_renderer (column, cell);
+  gtk_tree_view_column_pack_start (column, cell, TRUE);
 
   va_start (args, cell);
 
@@ -6810,7 +7144,7 @@ gtk_tree_view_insert_column_with_attributes (GtkTreeView     *tree_view,
  * Convenience function that inserts a new column into the #GtkTreeView
  * with the given cell renderer and a #GtkCellDataFunc to set cell renderer
  * attributes (normally using data from the model). See also
- * gtk_tree_view_column_set_cell_data_func(), gtk_tree_view_column_set_cell_renderer().
+ * gtk_tree_view_column_set_cell_data_func(), gtk_tree_view_column_pack_start().
  *
  * Return value: number of columns in the tree view post-insert
  **/
@@ -6830,7 +7164,7 @@ gtk_tree_view_insert_column_with_data_func  (GtkTreeView               *tree_vie
   column = gtk_tree_view_column_new ();
 
   gtk_tree_view_column_set_title (column, title);
-  gtk_tree_view_column_set_cell_renderer (column, cell);
+  gtk_tree_view_column_pack_start (column, cell, TRUE);
   gtk_tree_view_column_set_cell_data_func (column, cell, func, data, dnotify);
 
   gtk_tree_view_insert_column (tree_view, column, position);
@@ -6845,7 +7179,7 @@ gtk_tree_view_insert_column_with_data_func  (GtkTreeView               *tree_vie
  *
  * Gets the #GtkTreeViewColumn at the given position in the #tree_view.
  *
- * Return value: The #GtkTreeViewColumn, or NULL if the position is outside the
+ * Return value: The #GtkTreeViewColumn, or %NULL if the position is outside the
  * range of columns.
  **/
 GtkTreeViewColumn *
@@ -6884,9 +7218,9 @@ gtk_tree_view_get_columns (GtkTreeView *tree_view)
  * gtk_tree_view_move_column_after:
  * @tree_view: A #GtkTreeView
  * @column: The #GtkTreeViewColumn to be moved.
- * @base_column: The #GtkTreeViewColumn to be moved relative to.
+ * @base_column: The #GtkTreeViewColumn to be moved relative to, or %NULL.
  *
- * Moves @column to be after to @base_column.  If @base_column is NULL, then
+ * Moves @column to be after to @base_column.  If @base_column is %NULL, then
  * @column is placed in the first position.
  **/
 void
@@ -6930,9 +7264,8 @@ gtk_tree_view_move_column_after (GtkTreeView       *tree_view,
 
   if (GTK_WIDGET_REALIZED (tree_view))
     {
-      //gtk_widget_queue_resize (GTK_WIDGET (tree_view));
-      _gtk_tree_view_update_size (tree_view);
-      gtk_tree_view_size_allocate_buttons (GTK_WIDGET (tree_view));
+      gtk_widget_queue_resize (GTK_WIDGET (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);
@@ -6941,10 +7274,11 @@ gtk_tree_view_move_column_after (GtkTreeView       *tree_view,
 /**
  * gtk_tree_view_set_expander_column:
  * @tree_view: A #GtkTreeView
- * @column: NULL, or the column to draw the expander arrow at.
- * 
+ * @column: %NULL, or the column to draw the expander arrow at.
+ *
  * Sets the column to draw the expander arrow at. It must be in @tree_view.  If
- * @column is %NULL, then the expander arrow is fixed at the first column.
+ * @column is %NULL, then the expander arrow is always at the first visible
+ * column.
  **/
 void
 gtk_tree_view_set_expander_column (GtkTreeView       *tree_view,
@@ -6984,18 +7318,23 @@ gtk_tree_view_set_expander_column (GtkTreeView       *tree_view,
 GtkTreeViewColumn *
 gtk_tree_view_get_expander_column (GtkTreeView *tree_view)
 {
+  GList *list;
+
   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
 
-  return tree_view->priv->expander_column;
+  for (list = tree_view->priv->columns; list; list = list->data)
+    if (gtk_tree_view_is_expander_column (tree_view, GTK_TREE_VIEW_COLUMN (list->data)))
+      return (GtkTreeViewColumn *) list->data;
+  return NULL;
 }
 
 
 /**
  * gtk_tree_view_set_column_drag_function:
  * @tree_view: A #GtkTreeView.
- * @func: A function to determine which columns are reorderable, or NULL.
- * @user_data: User data to be passed to @func, or NULL
- * @destroy: Destroy notifier for @user_data, or NULL
+ * @func: A function to determine which columns are reorderable, or %NULL.
+ * @user_data: User data to be passed to @func, or %NULL
+ * @destroy: Destroy notifier for @user_data, or %NULL
  *
  * Sets a user function for determining where a column may be dropped when
  * dragged.  This function is called on every column pair in turn at the
@@ -7003,7 +7342,7 @@ gtk_tree_view_get_expander_column (GtkTreeView *tree_view)
  * arguments passed to @func are: the @tree_view, the #GtkTreeViewColumn being
  * dragged, the two #GtkTreeViewColumn s determining the drop spot, and
  * @user_data.  If either of the #GtkTreeViewColumn arguments for the drop spot
- * are NULL, then they indicate an edge.  If @func is set to be NULL, then
+ * are %NULL, then they indicate an edge.  If @func is set to be %NULL, then
  * @tree_view reverts to the default behavior of allowing all columns to be
  * dropped everywhere.
  **/
@@ -7032,8 +7371,8 @@ gtk_tree_view_set_column_drag_function (GtkTreeView               *tree_view,
  * Scrolls the tree view such that the top-left corner of the visible
  * area is @tree_x, @tree_y, where @tree_x and @tree_y are specified
  * in tree window coordinates.  The @tree_view must be realized before
- * this function is called.  If it isn't, you probably want ot be
- * using gtk_tree_view_scroll_to_cell.
+ * this function is called.  If it isn't, you probably want to be
+ * using gtk_tree_view_scroll_to_cell().
  **/
 void
 gtk_tree_view_scroll_to_point (GtkTreeView *tree_view,
@@ -7049,36 +7388,40 @@ gtk_tree_view_scroll_to_point (GtkTreeView *tree_view,
   hadj = tree_view->priv->hadjustment;
   vadj = tree_view->priv->vadjustment;
 
-  gtk_adjustment_set_value (hadj, CLAMP (tree_x, hadj->lower, hadj->upper));
-  gtk_adjustment_set_value (vadj, CLAMP (tree_y, vadj->lower, vadj->upper));
+  gtk_adjustment_set_value (hadj, CLAMP (tree_x, hadj->lower, hadj->upper - hadj->page_size));
+  gtk_adjustment_set_value (vadj, CLAMP (tree_y, vadj->lower, vadj->upper - vadj->page_size));
 }
 
 /**
  * gtk_tree_view_scroll_to_cell
  * @tree_view: A #GtkTreeView.
- * @path: The path of the row to move to.
- * @column: The #GtkTreeViewColumn to move horizontally to.
+ * @path: The path of the row to move to, or %NULL.
+ * @column: The #GtkTreeViewColumn to move horizontally to, or %NULL.
+ * @use_align: whether to use alignment arguments, or %FALSE.
  * @row_align: The vertical alignment of the row specified by @path.
  * @col_align: The horizontal alignment of the column specified by @column.
  *
- * Moves the alignments of @tree_view to the position specified by
- * @column and @path.  If @column is NULL, then no horizontal
- * scrolling occurs.  Likewise, if @path is NULL no vertical scrolling
- * occurs.  @row_align determines where the row is placed, and
- * @col_align determines where @column is placed.  Both are expected
- * to be between 0.0 and 1.0. 0.0 means left/top alignment, 1.0 means
- * right/bottom alignment, 0.5 means center.
+ * Moves the alignments of @tree_view to the position specified by @column and
+ * @path.  If @column is %NULL, then no horizontal scrolling occurs.  Likewise,
+ * if @path is %NULL no vertical scrolling occurs.  @row_align determines where
+ * the row is placed, and @col_align determines where @column is placed.  Both
+ * are expected to be between 0.0 and 1.0. 0.0 means left/top alignment, 1.0
+ * means right/bottom alignment, 0.5 means center.  If @use_align is %FALSE,
+ * then the alignment arguments are ignored, and the tree does the minimum
+ * amount of work to scroll the cell onto the screen.
  **/
 void
 gtk_tree_view_scroll_to_cell (GtkTreeView       *tree_view,
                               GtkTreePath       *path,
                               GtkTreeViewColumn *column,
+                             gboolean           use_align,
                               gfloat             row_align,
                               gfloat             col_align)
 {
   GdkRectangle cell_rect;
   GdkRectangle vis_rect;
   gint dest_x, dest_y;
+  gfloat within_margin = 0;
 
   /* FIXME work on unmapped/unrealized trees? maybe implement when
    * we do incremental reflow for trees
@@ -7098,6 +7441,7 @@ gtk_tree_view_scroll_to_cell (GtkTreeView       *tree_view,
        tree_view->priv->scroll_to_path = gtk_tree_path_copy (path);
       if (column)
        tree_view->priv->scroll_to_column = column;
+      tree_view->priv->scroll_to_use_align = use_align;
       tree_view->priv->scroll_to_row_align = row_align;
       tree_view->priv->scroll_to_col_align = col_align;
 
@@ -7110,18 +7454,34 @@ gtk_tree_view_scroll_to_cell (GtkTreeView       *tree_view,
   dest_x = vis_rect.x;
   dest_y = vis_rect.y;
 
-  if (path)
+  if (column)
     {
-      dest_x = cell_rect.x +
-        cell_rect.width * row_align -
-        vis_rect.width * row_align;
+      if (use_align)
+       {
+         dest_x = cell_rect.x + cell_rect.width * row_align - vis_rect.width * row_align;
+       }
+      else
+       {
+         if (cell_rect.x < vis_rect.x)
+           dest_x = cell_rect.x - vis_rect.width * within_margin;
+         else if (cell_rect.x + cell_rect.width > vis_rect.x + vis_rect.width)
+           dest_x = cell_rect.x + cell_rect.width - vis_rect.width * (1 - within_margin);
+       }
     }
 
-  if (column)
+  if (path)
     {
-      dest_y = cell_rect.y +
-        cell_rect.height * col_align -
-        vis_rect.height * col_align;
+      if (use_align)
+       {
+         dest_y = cell_rect.y + cell_rect.height * col_align - vis_rect.height * col_align;
+       }
+      else
+       {
+         if (cell_rect.y < vis_rect.y)
+           dest_y = cell_rect.y - vis_rect.height * within_margin;
+         else if (cell_rect.y + cell_rect.height > vis_rect.y + vis_rect.height)
+           dest_y = cell_rect.y + cell_rect.height - vis_rect.height * (1 - within_margin);
+       }
     }
 
   gtk_tree_view_scroll_to_point (tree_view, dest_x, dest_y);
@@ -7143,8 +7503,6 @@ gtk_tree_view_row_activated (GtkTreeView       *tree_view,
 {
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
 
-  /* FIXME: Actually activate the path internally, not just emit the signal */
-  /*  g_warning ("FIXME: Actually activate the path internally, not just emit the signal\n"); */
   g_signal_emit (G_OBJECT(tree_view), tree_view_signals[ROW_ACTIVATED], 0, path, column);
 }
 
@@ -7178,8 +7536,7 @@ gtk_tree_view_expand_all_helper (GtkRBTree  *tree,
                                node->children,
                                &child,
                                gtk_tree_path_get_depth (path) + 1,
-                               TRUE,
-                               GTK_WIDGET_REALIZED (tree_view));
+                               TRUE);
       gtk_tree_path_free (path);
     }
 }
@@ -7201,37 +7558,6 @@ gtk_tree_view_expand_all (GtkTreeView *tree_view)
                        G_PRE_ORDER,
                        gtk_tree_view_expand_all_helper,
                        tree_view);
-
-  _gtk_tree_view_update_size (tree_view);
-}
-
-static void
-gtk_tree_view_collapse_all_helper (GtkRBTree  *tree,
-                                  GtkRBNode  *node,
-                                  gpointer    data)
-{
-  if (node->children)
-    {
-      GtkTreePath *path;
-      GtkTreeIter iter;
-
-      path = _gtk_tree_view_find_path (GTK_TREE_VIEW (data),
-                                      node->children,
-                                      node->children->root);
-      gtk_tree_model_get_iter (GTK_TREE_VIEW (data)->priv->model,
-                              &iter,
-                              path);
-      gtk_tree_view_discover_dirty (GTK_TREE_VIEW (data),
-                                   node->children,
-                                   &iter,
-                                   gtk_tree_path_get_depth (path));
-
-      /* Ensure we don't have a dangling pointer to a dead node */
-      ensure_unprelighted (GTK_TREE_VIEW (data));
-
-      _gtk_rbtree_remove (node->children);
-      gtk_tree_path_free (path);
-    }
 }
 
 /* Timeout to animate the expander during expands and collapses */
@@ -7245,13 +7571,13 @@ expand_collapse_timeout (gpointer data)
   gboolean redraw;
 
   GDK_THREADS_ENTER ();
-  
+
   redraw = FALSE;
   expanding = TRUE;
 
   node = tree_view->priv->expanded_collapsed_node;
   tree = tree_view->priv->expanded_collapsed_tree;
-  
+
   if (node->children == NULL)
     expanding = FALSE;
 
@@ -7263,7 +7589,7 @@ expand_collapse_timeout (gpointer data)
          GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_EXPANDED);
 
          redraw = TRUE;
-         
+
        }
       else if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SEMI_EXPANDED))
        {
@@ -7313,17 +7639,32 @@ expand_collapse_timeout (gpointer data)
 void
 gtk_tree_view_collapse_all (GtkTreeView *tree_view)
 {
+  GtkRBTree *tree;
+  GtkRBNode *node;
+  GtkTreePath *path;
+  guint *indices;
+
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
   g_return_if_fail (tree_view->priv->tree != NULL);
 
-  _gtk_rbtree_traverse (tree_view->priv->tree,
-                       tree_view->priv->tree->root,
-                       G_PRE_ORDER,
-                       gtk_tree_view_collapse_all_helper,
-                       tree_view);
+  path = gtk_tree_path_new ();
+  gtk_tree_path_append_index (path, 0);
+  indices = gtk_tree_path_get_indices (path);
 
-  if (GTK_WIDGET_MAPPED (tree_view))
-    gtk_widget_queue_draw (GTK_WIDGET (tree_view));
+  tree = tree_view->priv->tree;
+  node = tree->root;
+  while (node && node->left != tree->nil)
+    node = node->left;
+
+  while (node)
+    {
+      if (node->children)
+       gtk_tree_view_real_collapse_row (tree_view, path, tree, node, FALSE);
+      indices[0]++;
+      node = _gtk_rbtree_next (tree, node);
+    }
+
+  gtk_tree_path_free (path);
 }
 
 /* FIXME the bool return values for expand_row and collapse_row are
@@ -7337,14 +7678,18 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
                               GtkTreePath *path,
                               GtkRBTree   *tree,
                               GtkRBNode   *node,
-                              gboolean     open_all)
+                              gboolean     open_all,
+                              gboolean     animate)
 {
   GtkTreeIter iter;
   GtkTreeIter temp;
   gboolean expand;
 
+
   if (node->children)
     return TRUE;
+  if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
+    return FALSE;
 
   gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
   if (! gtk_tree_model_iter_has_child (tree_view->priv->model, &iter))
@@ -7365,32 +7710,35 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
                            node->children,
                            &temp,
                            gtk_tree_path_get_depth (path) + 1,
-                           open_all,
-                           GTK_WIDGET_REALIZED (tree_view));
+                           open_all);
 
   if (tree_view->priv->expand_collapse_timeout)
-    gtk_timeout_remove (tree_view->priv->expand_collapse_timeout);
-  
+    {
+      gtk_timeout_remove (tree_view->priv->expand_collapse_timeout);
+      tree_view->priv->expand_collapse_timeout = 0;
+    }
+
   if (tree_view->priv->expanded_collapsed_node != NULL)
     {
       GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_EXPANDED);
       GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_COLLAPSED);
-    }
 
-  tree_view->priv->expand_collapse_timeout = gtk_timeout_add (50, expand_collapse_timeout, tree_view);
-  tree_view->priv->expanded_collapsed_node = node;
-  tree_view->priv->expanded_collapsed_tree = tree;
-  
-  GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_COLLAPSED);
+      tree_view->priv->expanded_collapsed_node = NULL;
+    }
 
-  if (GTK_WIDGET_MAPPED (tree_view))
+  if (animate)
     {
-      gtk_widget_queue_draw (GTK_WIDGET (tree_view));
-      _gtk_tree_view_update_size (tree_view);
+      tree_view->priv->expand_collapse_timeout = gtk_timeout_add (50, expand_collapse_timeout, tree_view);
+      tree_view->priv->expanded_collapsed_node = node;
+      tree_view->priv->expanded_collapsed_tree = tree;
+
+      GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_COLLAPSED);
     }
 
-  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[ROW_EXPANDED], 0, &iter, path);
+  if (GTK_WIDGET_MAPPED (tree_view))
+    install_presize_handler (tree_view);
 
+  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[ROW_EXPANDED], 0, &iter, path);
   return TRUE;
 }
 
@@ -7401,7 +7749,7 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
  * @path: path to a row
  * @open_all: whether to recursively expand, or just expand immediate children
  *
- * Opens the row so its children are visible
+ * Opens the row so its children are visible.
  *
  * Return value: %TRUE if the row existed and had children
  **/
@@ -7424,7 +7772,7 @@ gtk_tree_view_expand_row (GtkTreeView *tree_view,
     return FALSE;
 
   if (tree != NULL)
-    return gtk_tree_view_real_expand_row (tree_view, path, tree, node, open_all);
+    return gtk_tree_view_real_expand_row (tree_view, path, tree, node, open_all, FALSE);
   else
     return FALSE;
 }
@@ -7433,12 +7781,17 @@ static gboolean
 gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
                                 GtkTreePath *path,
                                 GtkRBTree   *tree,
-                                GtkRBNode   *node)
+                                GtkRBNode   *node,
+                                gboolean     animate)
 {
   GtkTreeIter iter;
   GtkTreeIter children;
   gboolean collapse;
   gint x, y;
+  GList *list;
+
+  if (node->children == NULL)
+    return FALSE;
 
   gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
 
@@ -7449,7 +7802,7 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
 
   /* if the prelighted node is a child of us, we want to unprelight it.  We have
    * a chance to prelight the correct node below */
-  
+
   if (tree_view->priv->prelight_tree)
     {
       GtkRBTree *parent_tree;
@@ -7471,10 +7824,15 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
 
   TREE_VIEW_INTERNAL_ASSERT (gtk_tree_model_iter_children (tree_view->priv->model, &children, &iter), FALSE);
 
-  gtk_tree_view_discover_dirty (tree_view,
-                               node->children,
-                               &children,
-                               gtk_tree_path_get_depth (path));
+  for (list = tree_view->priv->columns; list; list = list->next)
+    {
+      GtkTreeViewColumn *column = list->data;
+
+      if (column->visible == FALSE)
+       continue;
+      if (gtk_tree_view_column_get_sizing (column) == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
+       gtk_tree_view_column_cell_set_dirty (column);
+    }
 
   if (tree_view->priv->destroy_count_func)
     {
@@ -7493,24 +7851,31 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
   _gtk_rbtree_remove (node->children);
 
   if (tree_view->priv->expand_collapse_timeout)
-    gtk_timeout_remove (tree_view->priv->expand_collapse_timeout);
-
+    {
+      gtk_timeout_remove (tree_view->priv->expand_collapse_timeout);
+      tree_view->priv->expand_collapse_timeout = 0;
+    }
+  
   if (tree_view->priv->expanded_collapsed_node != NULL)
     {
       GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_EXPANDED);
       GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_COLLAPSED);
+      
+      tree_view->priv->expanded_collapsed_node = NULL;
     }
 
-  tree_view->priv->expand_collapse_timeout = gtk_timeout_add (50, expand_collapse_timeout, tree_view);
-  tree_view->priv->expanded_collapsed_node = node;
-  tree_view->priv->expanded_collapsed_tree = tree;
+  if (animate)
+    {
+      tree_view->priv->expand_collapse_timeout = gtk_timeout_add (50, expand_collapse_timeout, tree_view);
+      tree_view->priv->expanded_collapsed_node = node;
+      tree_view->priv->expanded_collapsed_tree = tree;
 
-  GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_EXPANDED);
+      GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_EXPANDED);
+    }
   
   if (GTK_WIDGET_MAPPED (tree_view))
     {
-      gtk_widget_queue_draw (GTK_WIDGET (tree_view));
-      _gtk_tree_view_update_size (tree_view);
+      gtk_widget_queue_resize (GTK_WIDGET (tree_view));
     }
 
   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
@@ -7564,7 +7929,7 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
  * @tree_view: a #GtkTreeView
  * @path: path to a row in the @tree_view
  *
- * Collapses a row (hides its child rows, if they exist.)
+ * Collapses a row (hides its child rows, if they exist).
  *
  * Return value: %TRUE if the row was collapsed.
  **/
@@ -7588,7 +7953,7 @@ gtk_tree_view_collapse_row (GtkTreeView *tree_view,
   if (tree == NULL || node->children == NULL)
     return FALSE;
 
-  return gtk_tree_view_real_collapse_row (tree_view, path, tree, node);
+  return gtk_tree_view_real_collapse_row (tree_view, path, tree, node, FALSE);
 }
 
 static void
@@ -7660,10 +8025,10 @@ gtk_tree_view_map_expanded_rows (GtkTreeView            *tree_view,
  * gtk_tree_view_row_expanded:
  * @tree_view: A #GtkTreeView.
  * @path: A #GtkTreePath to test expansion state.
- * 
- * Returns TRUE if the node pointed to by @path is expanded in @tree_view.
- * 
- * Return value: TRUE if #path is expanded.
+ *
+ * Returns %TRUE if the node pointed to by @path is expanded in @tree_view.
+ *
+ * Return value: %TRUE if #path is expanded.
  **/
 gboolean
 gtk_tree_view_row_expanded (GtkTreeView *tree_view,
@@ -7708,13 +8073,13 @@ gtk_tree_view_get_reorderable (GtkTreeView *tree_view)
 /**
  * gtk_tree_view_set_reorderable:
  * @tree_view: A #GtkTreeView.
- * @reorderable: TRUE, if the tree can be reordered.
+ * @reorderable: %TRUE, if the tree can be reordered.
  *
  * This function is a convenience function to allow you to reorder models that
  * support the #GtkDragSourceIface and the #GtkDragDestIface.  Both
- * #GtkTreeStore and #GtkListStore support these.  If @reorderable is TRUE, then
+ * #GtkTreeStore and #GtkListStore support these.  If @reorderable is %TRUE, then
  * the user can reorder the model by dragging and dropping columns.  The
- * developer will can listen to these changes by connecting to the model's
+ * developer can listen to these changes by connecting to the model's
  * signals.
  *
  * This function does not give you any degree of control over the order -- any
@@ -7727,20 +8092,30 @@ gtk_tree_view_set_reorderable (GtkTreeView *tree_view,
 {
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
 
-  if (tree_view->priv->reorderable == (reorderable?TRUE:FALSE))
+  reorderable = reorderable != FALSE;
+
+  if (tree_view->priv->reorderable == reorderable)
     return;
 
-  gtk_tree_view_set_rows_drag_source (tree_view,
-                                      GDK_BUTTON1_MASK,
-                                      row_targets,
-                                      G_N_ELEMENTS (row_targets),
-                                      GDK_ACTION_MOVE,
-                                      NULL, NULL);
-  gtk_tree_view_set_rows_drag_dest (tree_view,
-                                    row_targets,
-                                    G_N_ELEMENTS (row_targets),
-                                    GDK_ACTION_MOVE,
-                                    NULL, NULL);
+  tree_view->priv->reorderable = reorderable;
+
+  if (reorderable)
+    {
+      gtk_tree_view_enable_model_drag_source (tree_view,
+                                             GDK_BUTTON1_MASK,
+                                             row_targets,
+                                             G_N_ELEMENTS (row_targets),
+                                             GDK_ACTION_MOVE);
+      gtk_tree_view_enable_model_drag_dest (tree_view,
+                                           row_targets,
+                                           G_N_ELEMENTS (row_targets),
+                                           GDK_ACTION_MOVE);
+    }
+  else
+    {
+      gtk_tree_view_unset_rows_drag_source (tree_view);
+      gtk_tree_view_unset_rows_drag_dest (tree_view);
+    }
 
   g_object_notify (G_OBJECT (tree_view), "reorderable");
 }
@@ -7752,6 +8127,7 @@ gtk_tree_view_real_set_cursor (GtkTreeView     *tree_view,
 {
   GtkRBTree *tree = NULL;
   GtkRBNode *node = NULL;
+  GdkModifierType state = 0;
 
   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
     {
@@ -7760,49 +8136,127 @@ gtk_tree_view_real_set_cursor (GtkTreeView     *tree_view,
       gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
       gtk_tree_path_free (cursor_path);
     }
+
   gtk_tree_row_reference_free (tree_view->priv->cursor);
+  gtk_get_current_event_state (&state);
 
   tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
                                                              tree_view->priv->model,
                                                              path);
   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
-  if (tree == NULL)
-    return;
+  if (tree != NULL)
+    {
+      if (clear_and_select && !((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK))
+       _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
+                                                 node, tree, path,
+                                                 state);
+      gtk_tree_view_clamp_node_visible (tree_view, tree, node);
+      gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
+    }
+
+  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[CURSOR_CHANGED], 0);
+}
+
+/**
+ * gtk_tree_view_get_cursor:
+ * @tree_view: A #GtkTreeView
+ * @path: A pointer to be filled with the current cursor path, or %NULL
+ * @focus_column: A pointer to be filled with the current focus column, or %NULL
+ *
+ * Fills in @path and @focus_column with the current path and focus column.  If
+ * the cursor isn't currently set, then *@path will be %NULL.  If no column
+ * currently has focus, then *@focus_column will be %NULL.
+ **/
+void
+gtk_tree_view_get_cursor (GtkTreeView        *tree_view,
+                         GtkTreePath       **path,
+                         GtkTreeViewColumn **focus_column)
+{
+  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+
+  if (path)
+    {
+      if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
+       *path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
+      else
+       *path = NULL;
+    }
 
-  if (clear_and_select && !tree_view->priv->in_free_motion)
-    _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
-                                             node, tree, path,
-                                             tree_view->priv->in_extended_selection?GDK_SHIFT_MASK:0);
-  gtk_tree_view_clamp_node_visible (tree_view, tree, node);
-  gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
+  if (focus_column)
+    {
+      *focus_column = tree_view->priv->focus_column;
+    }
 }
 
 /**
  * gtk_tree_view_set_cursor:
  * @tree_view: A #GtkTreeView
  * @path: A #GtkTreePath
+ * @focus_column: A #GtkTreeViewColumn, 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
- * you want to give the user keyboard focus in the tree_view, you should use
- * this function to set the correct path, and gtk_widget_grab_focus (GTK_WIDGET
- * (tree_view)) to actually give focus to the @tree_view.
+ * @column is not %NULL, then focus is given to the column specified by it.
+ * Additionally, if @column is specified, and @start_editing is %TRUE, then
+ * editing should be started in the specified cell.  Keyboard focus is given to
+ * the widget after this is called.  Please note that editing can only happen
+ * when the widget is realized.
  **/
 void
-gtk_tree_view_set_cursor (GtkTreeView *tree_view,
-                         GtkTreePath *path)
+gtk_tree_view_set_cursor (GtkTreeView       *tree_view,
+                         GtkTreePath       *path,
+                         GtkTreeViewColumn *focus_column,
+                         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));
 
   gtk_tree_view_real_set_cursor (tree_view, path, TRUE);
+
+  gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+  if (focus_column && focus_column->visible)
+    {
+      GList *list;
+      gboolean column_in_tree = FALSE;
+
+      for (list = tree_view->priv->columns; list; list = list->next)
+       if (list->data == focus_column)
+         {
+           column_in_tree = TRUE;
+           break;
+         }
+      g_return_if_fail (column_in_tree);
+      tree_view->priv->focus_column = focus_column;
+      if (start_editing)
+       gtk_tree_view_start_editing (tree_view, path);
+    }
 }
 
 
+/**
+ * gtk_tree_view_get_bin_window:
+ * @tree_view: A #GtkTreeView
+ * 
+ * Returns the window that @tree_view renders to.  This is used primarily to
+ * compare to <literal>event->window</literal> to confirm that the event on
+ * @tree_view is on the right window.
+ * 
+ * Return value: A #GdkWindow, or %NULL when @tree_view hasn't been realized yet
+ **/
+GdkWindow *
+gtk_tree_view_get_bin_window (GtkTreeView *tree_view)
+{
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
+
+  return tree_view->priv->bin_window;
+}
+
 /**
  * gtk_tree_view_get_path_at_pos:
  * @tree_view: A #GtkTreeView.
- * @window: The #GdkWindow to check against.
  * @x: The x position to be identified.
  * @y: The y position to be identified.
  * @path: A pointer to a #GtkTreePath pointer to be filled in, or %NULL
@@ -7810,22 +8264,20 @@ gtk_tree_view_set_cursor (GtkTreeView *tree_view,
  * @cell_x: A pointer where the X coordinate relative to the cell can be placed, or %NULL
  * @cell_y: A pointer where the Y coordinate relative to the cell can be placed, or %NULL
  *
- * Finds the path at the point (@x, @y) relative to @window.  If @window is
- * NULL, then the point is found relative to the widget coordinates.  This
- * function is expected to be called after an event, with event->window being
- * passed in as @window.  It is primarily for things like popup menus.  If @path
- * is non-NULL, then it will be filled with the #GtkTreePath at that point.
- * This path should be freed with #gtk_tree_path_free.  If @column is non-NULL,
- * then it will be filled with the column at that point. @cell_x and @cell_y
- * return the coordinates relative to the cell background (i.e. the
- * background_area passed to gtk_cell_renderer_render()).  This function only
- * works if @tree_view is realized.
+ * Finds the path at the point (@x, @y), relative to widget coordinates.  That
+ * is, @x and @y are relative to an events coordinates.  It is primarily for
+ * things like popup menus.  If @path is non-%NULL, then it will be filled with
+ * the #GtkTreePath at that point.  This path should be freed with
+ * gtk_tree_path_free().  If @column is non-%NULL, then it will be filled with
+ * the column at that point. @cell_x and @cell_y return the coordinates relative
+ * to the cell background (i.e. the @background_area passed to
+ * gtk_cell_renderer_render()).  This function is only meaningful if @tree_view
+ * is realized.
  *
- * Return value: TRUE if a row exists at that coordinate.
+ * Return value: %TRUE if a row exists at that coordinate.
  **/
 gboolean
 gtk_tree_view_get_path_at_pos (GtkTreeView        *tree_view,
-                              GdkWindow          *window,
                               gint                x,
                               gint                y,
                               GtkTreePath       **path,
@@ -7838,17 +8290,16 @@ gtk_tree_view_get_path_at_pos (GtkTreeView        *tree_view,
   gint y_offset;
 
   g_return_val_if_fail (tree_view != NULL, FALSE);
-  g_return_val_if_fail (tree_view->priv->tree != NULL, FALSE);
   g_return_val_if_fail (tree_view->priv->bin_window != NULL, FALSE);
 
-  if (window)
-    g_return_val_if_fail (window == tree_view->priv->bin_window, FALSE);
-
   if (path)
     *path = NULL;
   if (column)
     *column = NULL;
 
+  if (tree_view->priv->tree == NULL)
+    return FALSE;
+
   if (x > tree_view->priv->hadjustment->upper)
     return FALSE;
 
@@ -7896,21 +8347,12 @@ gtk_tree_view_get_path_at_pos (GtkTreeView        *tree_view,
         }
     }
 
-  if (window)
-    {
-      y_offset = _gtk_rbtree_find_offset (tree_view->priv->tree,
-                                          TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y),
-                                          &tree, &node);
-    }
-  else
-    {
-      if (y < TREE_VIEW_HEADER_HEIGHT (tree_view))
-       return FALSE;
+  if (y < TREE_VIEW_HEADER_HEIGHT (tree_view))
+    return FALSE;
 
-      y_offset = _gtk_rbtree_find_offset (tree_view->priv->tree,
-                                          TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y + tree_view->priv->vadjustment->value),
-                                          &tree, &node);
-    }
+  y_offset = _gtk_rbtree_find_offset (tree_view->priv->tree,
+                                     TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y + tree_view->priv->vadjustment->value),
+                                     &tree, &node);
 
   if (tree == NULL)
     return FALSE;
@@ -7934,12 +8376,13 @@ gtk_tree_view_get_path_at_pos (GtkTreeView        *tree_view,
  *
  * Fills the bounding rectangle in tree window coordinates for the cell at the
  * row specified by @path and the column specified by @column.  If @path is
- * %NULL, the y and height fields of the rectangle will be filled with 0. If
- * @column is %NULL, the x and width fields will be filled with 0.  The sum of
- * all cell rects does not cover the entire tree; there are extra pixels in
- * between rows, for example. The returned rectangle is equivalent to the
- * @cell_area passed to gtk_cell_renderer_render().  This function is only valid
- * if #tree_view is realized.
+ * %NULL, or points to a path not currently displayed, the @y and @height fields
+ * of the rectangle will be filled with 0. If @column is %NULL, the @x and @width
+ * fields will be filled with 0.  The sum of all cell rects does not cover the
+ * entire tree; there are extra pixels in between rows, for example. The
+ * returned rectangle is equivalent to the @cell_area passed to
+ * gtk_cell_renderer_render().  This function is only valid if #tree_view is
+ * realized.
  **/
 void
 gtk_tree_view_get_cell_area (GtkTreeView        *tree_view,
@@ -7950,44 +8393,48 @@ gtk_tree_view_get_cell_area (GtkTreeView        *tree_view,
   GtkRBTree *tree = NULL;
   GtkRBNode *node = NULL;
   gint vertical_separator;
+  gint horizontal_separator;
 
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
   g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column));
   g_return_if_fail (rect != NULL);
-  g_return_if_fail (column->tree_view == tree_view);
+  g_return_if_fail (!column || column->tree_view == (GtkWidget *) tree_view);
   g_return_if_fail (GTK_WIDGET_REALIZED (tree_view));
 
-  gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical_separator", &vertical_separator, NULL);
+  gtk_widget_style_get (GTK_WIDGET (tree_view),
+                       "vertical_separator", &vertical_separator,
+                       "horizontal_separator", &horizontal_separator,
+                       NULL);
 
   rect->x = 0;
   rect->y = 0;
   rect->width = 0;
   rect->height = 0;
 
-  if (path)
+  if (column)
     {
-      /* Get vertical coords */
-
-      _gtk_tree_view_find_node (tree_view, path, &tree, &node);
-
-      if (tree == NULL)
-        {
-          g_warning (G_STRLOC": no row corresponding to path");
-          return;
-        }
+      rect->x = column->button->allocation.x + horizontal_separator/2;
+      rect->width = column->button->allocation.width - horizontal_separator;
+    }
 
-      /* Remember that the rbtree stores node height including the vertical
-       * separator, see comment at top of file.
-       */
-      rect->y = CELL_FIRST_PIXEL (tree_view, tree, node, vertical_separator);
+  if (path)
+    {
+      /* Get vertical coords */
+      if (_gtk_tree_view_find_node (tree_view, path, &tree, &node) &&
+         tree != NULL)
+       return;
 
+      rect->y = CELL_FIRST_PIXEL (tree_view, tree, node, vertical_separator);
       rect->height = CELL_HEIGHT (node, vertical_separator);
-    }
 
-  if (column)
-    {
-      rect->x = column->button->allocation.x;
-      rect->width = column->button->allocation.width;
+      if (gtk_tree_view_is_expander_column (tree_view, column) &&
+         TREE_VIEW_DRAW_EXPANDERS (tree_view))
+       {
+         gint depth = gtk_tree_path_get_depth (path) - 1;
+         rect->x += depth * tree_view->priv->tab_offset;
+         rect->width -= depth * tree_view->priv->tab_offset;
+         rect->width = MAX (rect->width, 0);
+       }
     }
 }
 
@@ -7998,17 +8445,16 @@ gtk_tree_view_get_cell_area (GtkTreeView        *tree_view,
  * @column: a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordiantes
  * @rect: rectangle to fill with cell background rect
  *
- * Fills the bounding rectangle in tree window coordinates for the
- * cell at the row specified by @path and the column specified by
- * @column.  If @path is %NULL, the y and height fields of the
- * rectangle will be filled with 0. If @column is %NULL, the x and
- * width fields will be filled with 0.  The returned rectangle is
- * equivalent to the @background_area passed to
- * gtk_cell_renderer_render().  These background areas tile to cover
- * the entire tree window (except for the area used for header
- * buttons). Contrast with the cell_area, returned by
- * gtk_tree_view_get_cell_area(), which returns only the cell itself,
- * excluding surrounding borders and the tree expander area.
+ * Fills the bounding rectangle in tree window coordinates for the cell at the
+ * row specified by @path and the column specified by @column.  If @path is
+ * %NULL, or points to a node not found in the tree, the @y and @height fields of
+ * the rectangle will be filled with 0. If @column is %NULL, the @x and @width
+ * fields will be filled with 0.  The returned rectangle is equivalent to the
+ * @background_area passed to gtk_cell_renderer_render().  These background
+ * areas tile to cover the entire tree window (except for the area used for
+ * header buttons). Contrast with the @cell_area, returned by
+ * gtk_tree_view_get_cell_area(), which returns only the cell itself, excluding
+ * surrounding borders and the tree expander area.
  *
  **/
 void
@@ -8033,13 +8479,9 @@ gtk_tree_view_get_background_area (GtkTreeView        *tree_view,
     {
       /* Get vertical coords */
 
-      _gtk_tree_view_find_node (tree_view, path, &tree, &node);
-
-      if (tree == NULL)
-        {
-          g_warning (G_STRLOC": no row corresponding to path");
-          return;
-        }
+      if (_gtk_tree_view_find_node (tree_view, path, &tree, &node) &&
+         tree != NULL)
+       return;
 
       rect->y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
 
@@ -8107,14 +8549,9 @@ gtk_tree_view_widget_to_tree_coords (GtkTreeView *tree_view,
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
 
   if (tx)
-    {
-      *tx = wx + tree_view->priv->hadjustment->value;
-    }
-
+    *tx = wx + tree_view->priv->hadjustment->value;
   if (ty)
-    {
-      *ty = wy + tree_view->priv->vadjustment->value;
-    }
+    *ty = wy + tree_view->priv->vadjustment->value;
 }
 
 /**
@@ -8139,25 +8576,27 @@ gtk_tree_view_tree_to_widget_coords (GtkTreeView *tree_view,
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
 
   if (wx)
-    {
-      *wx = tx - tree_view->priv->hadjustment->value;
-    }
-
+    *wx = tx - tree_view->priv->hadjustment->value;
   if (wy)
+    *wy = ty - tree_view->priv->vadjustment->value;
+}
+
+static void
+unset_reorderable (GtkTreeView *tree_view)
+{
+  if (tree_view->priv->reorderable)
     {
-      *wy = ty - tree_view->priv->vadjustment->value;
+      tree_view->priv->reorderable = FALSE;
+      g_object_notify (G_OBJECT (tree_view), "reorderable");
     }
 }
 
-
 void
-gtk_tree_view_set_rows_drag_source (GtkTreeView              *tree_view,
-                                    GdkModifierType           start_button_mask,
-                                    const GtkTargetEntry     *targets,
-                                    gint                      n_targets,
-                                    GdkDragAction             actions,
-                                    GtkTreeViewDraggableFunc  row_draggable_func,
-                                    gpointer                  user_data)
+gtk_tree_view_enable_model_drag_source (GtkTreeView              *tree_view,
+                                       GdkModifierType           start_button_mask,
+                                       const GtkTargetEntry     *targets,
+                                       gint                      n_targets,
+                                       GdkDragAction             actions)
 {
   TreeViewDragInfo *di;
 
@@ -8170,24 +8609,16 @@ gtk_tree_view_set_rows_drag_source (GtkTreeView              *tree_view,
   di->source_target_list = gtk_target_list_new (targets, n_targets);
   di->source_actions = actions;
 
-  if (row_draggable_func)
-    {
-      di->row_draggable_closure = g_cclosure_new ((GCallback) row_draggable_func,
-                                                  user_data, NULL);
-      g_closure_ref (di->row_draggable_closure);
-      g_closure_sink (di->row_draggable_closure);
-    }
-
   di->source_set = TRUE;
+
+  unset_reorderable (tree_view);
 }
 
 void
-gtk_tree_view_set_rows_drag_dest (GtkTreeView              *tree_view,
-                                  const GtkTargetEntry     *targets,
-                                  gint                      n_targets,
-                                  GdkDragAction             actions,
-                                  GtkTreeViewDroppableFunc  location_droppable_func,
-                                  gpointer                  user_data)
+gtk_tree_view_enable_model_drag_dest (GtkTreeView              *tree_view,
+                                     const GtkTargetEntry     *targets,
+                                     gint                      n_targets,
+                                     GdkDragAction             actions)
 {
   TreeViewDragInfo *di;
 
@@ -8205,15 +8636,9 @@ gtk_tree_view_set_rows_drag_dest (GtkTreeView              *tree_view,
   if (targets)
     di->dest_target_list = gtk_target_list_new (targets, n_targets);
 
-  if (location_droppable_func)
-    {
-      di->location_droppable_closure = g_cclosure_new ((GCallback) location_droppable_func,
-                                                       user_data, NULL);
-      g_closure_ref (di->location_droppable_closure);
-      g_closure_sink (di->location_droppable_closure);
-    }
-
   di->dest_set = TRUE;
+
+  unset_reorderable (tree_view);
 }
 
 void
@@ -8236,6 +8661,8 @@ gtk_tree_view_unset_rows_drag_source (GtkTreeView *tree_view)
       if (!di->dest_set && !di->source_set)
         remove_info (tree_view);
     }
+  
+  unset_reorderable (tree_view);
 }
 
 void
@@ -8259,6 +8686,8 @@ gtk_tree_view_unset_rows_drag_dest (GtkTreeView *tree_view)
       if (!di->dest_set && !di->source_set)
         remove_info (tree_view);
     }
+
+  unset_reorderable (tree_view);
 }
 
 void
@@ -8360,7 +8789,6 @@ gtk_tree_view_get_dest_row_at_pos (GtkTreeView             *tree_view,
    */
 
   if (!gtk_tree_view_get_path_at_pos (tree_view,
-                                      tree_view->priv->bin_window,
                                       x, y,
                                       &tmp_path,
                                       &column,
@@ -8413,10 +8841,10 @@ gtk_tree_view_get_dest_row_at_pos (GtkTreeView             *tree_view,
  * @tree_view: a #GtkTreeView
  * @path: a #GtkTreePath in @tree_view
  *
- * Creates a GdkPixmap representation of the row at @path.  This image is used
+ * Creates a #GdkPixmap representation of the row at @path.  This image is used
  * for a drag icon.
  *
- * Return value: a newly allocatdd pixmap of the drag icon.
+ * Return value: a newly-allocated pixmap of the drag icon.
  **/
 GdkPixmap *
 gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
@@ -8428,6 +8856,7 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
   gint cell_offset;
   GList *list;
   GdkRectangle background_area;
+  GdkRectangle expose_area;
   GtkWidget *widget;
   gint depth;
   /* start drawing inside the black outline */
@@ -8465,6 +8894,11 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
                              background_area.height + 2,
                              -1);
 
+  expose_area.x = 0;
+  expose_area.y = 0;
+  expose_area.width = bin_window_width + 2;
+  expose_area.height = background_area.height + 2;
+
   gdk_draw_rectangle (drawable,
                       widget->style->base_gc [GTK_WIDGET_STATE (widget)],
                       TRUE,
@@ -8493,7 +8927,7 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
                                               node->children?TRUE:FALSE);
 
       background_area.x = cell_offset;
-      background_area.width = column->displayed_width;
+      background_area.width = column->width;
 
       cell_area = background_area;
 
@@ -8513,10 +8947,10 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
                                          drawable,
                                          &background_area,
                                          &cell_area,
-                                         NULL,
+                                         &expose_area,
                                          0);
 
-      cell_offset += column->displayed_width;
+      cell_offset += column->width;
     }
 
   return drawable;
@@ -8526,10 +8960,10 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
 /**
  * gtk_tree_view_set_destroy_count_func:
  * @tree_view: A #GtkTreeView
- * @func: Function to be called when a view row is destroyed, or NULL
- * @data: User data to be passed to @func, or NULL
- * @destroy: Destroy notifier for @data, or NULL
- * 
+ * @func: Function to be called when a view row is destroyed, or %NULL
+ * @data: User data to be passed to @func, or %NULL
+ * @destroy: Destroy notifier for @data, or %NULL
+ *
  * This function should almost never be used.  It is meant for private use by
  * ATK for determining the number of visible children that are removed when the
  * user collapses a row, or a row is deleted.
@@ -8552,7 +8986,7 @@ gtk_tree_view_set_destroy_count_func (GtkTreeView             *tree_view,
 
 
 /*
- * Interactive search 
+ * Interactive search
  */
 
 /**
@@ -8601,7 +9035,7 @@ gint
 gtk_tree_view_get_search_column (GtkTreeView *tree_view)
 {
   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), 0);
-  
+
   return (tree_view->priv->search_column);
 }
 
@@ -8624,7 +9058,7 @@ gtk_tree_view_set_search_column (GtkTreeView *tree_view,
     return;
 
   tree_view->priv->search_column = column;
-  
+
 }
 
 /**
@@ -8647,10 +9081,12 @@ gtk_tree_view_get_search_equal_func (GtkTreeView *tree_view)
 /**
  * gtk_tree_view_set_search_equal_func:
  * @tree_view: A #GtkTreeView
- * @compare_func: the compare function to use during the search
+ * @search_equal_func: the compare function to use during the search
+ * @search_user_data: user data to pass to @search_equal_func, or %NULL
+ * @search_destroy: Destroy notifier for @search_user_data, or %NULL
  *
- * Sets the compare function to use to search the TreeView.
- */
+ * Sets the compare function for the interactive search capabilities.
+ **/
 void
 gtk_tree_view_set_search_equal_func (GtkTreeView                *tree_view,
                                     GtkTreeViewSearchEqualFunc  search_equal_func,
@@ -8675,8 +9111,9 @@ gtk_tree_view_search_dialog_destroy (GtkWidget   *search_dialog,
                                     GtkTreeView *tree_view)
 {
   /* remove data from tree_view */
-  gtk_object_remove_data (GTK_OBJECT (tree_view), "search-dialog");
-  
+  gtk_object_remove_data (GTK_OBJECT (tree_view),
+                         GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
+
   gtk_widget_destroy (search_dialog);
 }
 
@@ -8700,84 +9137,6 @@ gtk_tree_view_search_position_func (GtkTreeView *tree_view,
                   tree_y + tree_height);
 }
 
-static void
-gtk_tree_view_interactive_search (GtkTreeView *tree_view,
-                                 GdkEventKey *event)
-{
-  GtkWidget *window;
-  GtkWidget *entry;
-  
-  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
-  switch (event->keyval)
-    {
-    case GDK_Shift_L:
-    case GDK_Shift_R:
-    case GDK_Control_L:
-    case GDK_Control_R:
-    case GDK_Caps_Lock:
-    case GDK_Shift_Lock:
-    case GDK_Meta_L:
-    case GDK_Meta_R:
-    case GDK_Alt_L:
-    case GDK_Alt_R:
-    case GDK_Super_L:
-    case GDK_Super_R:
-    case GDK_Hyper_L:
-    case GDK_Hyper_R:
-    case GDK_Mode_switch:
-      return;
-    default:
-      break;
-    }
-
-  if (tree_view->priv->enable_search == FALSE ||
-      tree_view->priv->search_column < 0)
-    return;
-
-  /* set up window */
-  window = gtk_window_new (GTK_WINDOW_POPUP);
-  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);
-  gtk_signal_connect 
-    (GTK_OBJECT (window), "delete_event",
-     GTK_SIGNAL_FUNC (gtk_tree_view_search_delete_event),
-     tree_view);
-  gtk_signal_connect 
-    (GTK_OBJECT (window), "key_press_event",
-     GTK_SIGNAL_FUNC (gtk_tree_view_search_key_press_event),
-     tree_view);
-  gtk_signal_connect
-    (GTK_OBJECT (window), "button_press_event",
-     GTK_SIGNAL_FUNC (gtk_tree_view_search_button_press_event),
-     tree_view);
-
-  /* add entry */
-  entry = gtk_entry_new ();
-  gtk_widget_show (entry);
-  gtk_signal_connect
-    (GTK_OBJECT (entry), "changed",
-     GTK_SIGNAL_FUNC (gtk_tree_view_search_init),
-     tree_view);
-  gtk_container_add (GTK_CONTAINER (window), entry);
-
-  /* done, show it */
-  tree_view->priv->search_dialog_position_func (tree_view, window);
-  gtk_widget_show_all (window);
-  gtk_widget_grab_focus (entry);
-
-  gtk_widget_event (entry, (GdkEvent *) event);
-
-  /* position window */
-
-  gtk_object_set_data (GTK_OBJECT (window), "text",
-                       gtk_entry_get_text (GTK_ENTRY (entry)));
-  gtk_object_set_data (GTK_OBJECT (tree_view), "search-dialog", window);
-
-  /* search first matching iter */
-  gtk_tree_view_search_init (entry, tree_view);
-}
-
 static gboolean
 gtk_tree_view_search_delete_event (GtkWidget *widget,
                                   GdkEventAny *event,
@@ -8786,7 +9145,7 @@ gtk_tree_view_search_delete_event (GtkWidget *widget,
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
   gtk_tree_view_search_dialog_destroy (widget, tree_view);
-  
+
   return TRUE;
 }
 
@@ -8798,7 +9157,7 @@ gtk_tree_view_search_button_press_event (GtkWidget *widget,
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
   gtk_tree_view_search_dialog_destroy (widget, tree_view);
-  
+
   return TRUE;
 }
 
@@ -8809,10 +9168,11 @@ gtk_tree_view_search_key_press_event (GtkWidget *widget,
 {
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
-  
+
   /* close window */
-  if (event->keyval == GDK_Escape || event->keyval == GDK_Return
-      || event->keyval == GDK_Tab)
+  if (event->keyval == GDK_Escape ||
+      event->keyval == GDK_Return ||
+      event->keyval == GDK_Tab)
     {
       gtk_tree_view_search_dialog_destroy (widget, tree_view);
       return TRUE;
@@ -8821,20 +9181,17 @@ gtk_tree_view_search_key_press_event (GtkWidget *widget,
   /* select previous matching iter */
   if (event->keyval == GDK_Up)
     {
-      gtk_tree_view_search_move (widget,
-                                tree_view,
-                                TRUE);
+      gtk_tree_view_search_move (widget, tree_view, TRUE);
       return TRUE;
     }
 
   /* select next matching iter */
   if (event->keyval == GDK_Down)
     {
-      gtk_tree_view_search_move (widget,
-                                tree_view,
-                                FALSE);
+      gtk_tree_view_search_move (widget, tree_view, FALSE);
       return TRUE;
     }
+
   return FALSE;
 }
 
@@ -8852,8 +9209,8 @@ gtk_tree_view_search_move (GtkWidget   *window,
   GtkTreeModel *model;
   GtkTreeSelection *selection;
 
-  text = gtk_object_get_data (GTK_OBJECT (window), "text");
-  selected_iter = gtk_object_get_data (GTK_OBJECT (window), "selected-iter");
+  text = gtk_object_get_data (GTK_OBJECT (window), "gtk-tree-view-text");
+  selected_iter = gtk_object_get_data (GTK_OBJECT (window), "gtk-tree-view-selected-iter");
 
   g_return_if_fail (text != NULL);
 
@@ -8861,23 +9218,25 @@ gtk_tree_view_search_move (GtkWidget   *window,
     return;
 
   len = strlen (text);
-  
+
   if (len < 1)
     return;
 
   model = gtk_tree_view_get_model (tree_view);
   selection = gtk_tree_view_get_selection (tree_view);
-  
+
   /* search */
   gtk_tree_selection_unselect_all (selection);
   gtk_tree_model_get_iter_root (model, &iter);
-  
+
   ret = gtk_tree_view_search_iter (model, selection, &iter, text,
                                   &count, up?((*selected_iter) - 1):((*selected_iter + 1)));
-  
+
   if (ret)
-    /* found */
-    *selected_iter += up?(-1):(1);
+    {
+      /* found */
+      *selected_iter += up?(-1):(1);
+    }
   else
     {
       /* return to old iter */
@@ -8886,15 +9245,15 @@ gtk_tree_view_search_move (GtkWidget   *window,
       gtk_tree_view_search_iter (model, selection,
                                 &iter, text,
                                 &count, *selected_iter);
-
     }
 }
 
 static gboolean
 gtk_tree_view_search_equal_func (GtkTreeModel *model,
                                 gint          column,
-                                gchar        *key,
-                                GtkTreeIter  *iter)
+                                const gchar  *key,
+                                GtkTreeIter  *iter,
+                                gpointer      search_data)
 {
   gboolean retval = TRUE;
   gchar *normalized_string;
@@ -8909,12 +9268,12 @@ gtk_tree_view_search_equal_func (GtkTreeModel *model,
   normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
   case_normalized_string = g_utf8_casefold (normalized_string, -1);
   case_normalized_key = g_utf8_casefold (normalized_key, -1);
-  
+
   key_len = strlen (case_normalized_key);
 
   if (!strncmp (case_normalized_key, case_normalized_string, key_len))
     retval = FALSE;
-  
+
   g_value_unset (&value);
   g_free (normalized_key);
   g_free (normalized_string);
@@ -8928,81 +9287,111 @@ static gboolean
 gtk_tree_view_search_iter (GtkTreeModel     *model,
                           GtkTreeSelection *selection,
                           GtkTreeIter      *iter,
-                          gchar            *text,
+                          const gchar      *text,
                           gint             *count,
                           gint              n)
 {
+  GtkRBTree *tree = NULL;
+  GtkRBNode *node = NULL;
+  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);
-  
-  if (! tree_view->priv->search_equal_func (model, tree_view->priv->search_column, text, iter))
-    {
-      (*count)++;
-      
-      if (*count == n)
-        {
-          GtkTreePath *path;
-          
-          gtk_tree_selection_select_iter (selection, iter);
-          
-          path = gtk_tree_model_get_path (model, iter);
-         gtk_tree_view_scroll_to_cell (tree_view, path, column, 0.5, 0.5);
-         gtk_tree_view_real_set_cursor (tree_view, path, FALSE);
-          gtk_tree_path_free (path);
-          
-          return TRUE;
-        }
-    }
-  
-  if (gtk_tree_model_iter_has_child (model, iter))
-    {
-      gboolean ret;
-      GtkTreeIter child;
-      
-      gtk_tree_model_iter_children (model, &child, iter);
-      ret = gtk_tree_view_search_iter (model, selection,
-                                      &child, text,
-                                      count, n);
-      
-      if (ret)
-        return TRUE; /* iter found and selected */
-    }
-  
-  while (gtk_tree_model_iter_next (model, iter))
+
+  path = gtk_tree_model_get_path (model, iter);
+  _gtk_tree_view_find_node (tree_view, path, &tree, &node);
+
+  do
     {
-      if (! tree_view->priv->search_equal_func (model, tree_view->priv->search_column, text, iter))
+      if (! tree_view->priv->search_equal_func (model, tree_view->priv->search_column, text, iter, tree_view->priv->search_user_data))
         {
           (*count)++;
           if (*count == n)
             {
-              GtkTreePath *path;
-              
               gtk_tree_selection_select_iter (selection, iter);
-              
-              path = gtk_tree_model_get_path (model, iter);
-              gtk_tree_view_scroll_to_cell (tree_view, path, column, 0.5, 0.5);
+              gtk_tree_view_scroll_to_cell (tree_view, path, column,
+                                           TRUE, 0.5, 0.5);
              gtk_tree_view_real_set_cursor (tree_view, path, FALSE);
-              gtk_tree_path_free (path);
-              
+
+             if (path)
+               gtk_tree_path_free (path);
+
               return TRUE;
             }
         }
-      
-      if (gtk_tree_model_iter_has_child (model, iter))
-        {
-          gboolean ret;
-          GtkTreeIter child;
-          
-          gtk_tree_model_iter_children (model, &child, iter);
-          ret = gtk_tree_view_search_iter (model, selection,
-                                          &child, text,
-                                          count, n);
-
-          if (ret)
-            return TRUE; /* iter found and selected */
-        }
+
+      if (node->children)
+       {
+         gboolean has_child;
+         GtkTreeIter tmp;
+
+         tree = node->children;
+         node = tree->root;
+
+         while (node->left != tree->nil)
+           node = node->left;
+
+         tmp = *iter;
+         has_child = gtk_tree_model_iter_children (model, iter, &tmp);
+         gtk_tree_path_append_index (path, 0);
+
+         /* sanity check */
+         TREE_VIEW_INTERNAL_ASSERT (has_child, FALSE);
+       }
+      else
+       {
+         gboolean done = FALSE;
+
+         do
+           {
+             node = _gtk_rbtree_next (tree, node);
+
+             if (node)
+               {
+                 gboolean has_next;
+
+                 has_next = gtk_tree_model_iter_next (model, iter);
+
+                 done = TRUE;
+                 gtk_tree_path_next (path);
+
+                 /* sanity check */
+                 TREE_VIEW_INTERNAL_ASSERT (has_next, FALSE);
+               }
+             else
+               {
+                 gboolean has_parent;
+                 GtkTreeIter tmp_iter = *iter;
+
+                 node = tree->parent_node;
+                 tree = tree->parent_tree;
+
+                 if (!tree)
+                   {
+                     if (path)
+                       gtk_tree_path_free (path);
+
+                     /* we've run out of tree, done with this func */
+                     return FALSE;
+                   }
+
+                 has_parent = gtk_tree_model_iter_parent (model,
+                                                          iter,
+                                                          &tmp_iter);
+                 gtk_tree_path_up (path);
+
+                 /* sanity check */
+                 TREE_VIEW_INTERNAL_ASSERT (has_parent, FALSE);
+               }
+           }
+         while (!done);
+       }
     }
+  while (1);
+
+  if (path)
+    gtk_tree_path_free (path);
 
   return FALSE;
 }
@@ -9015,15 +9404,15 @@ gtk_tree_view_search_init (GtkWidget   *entry,
   gint *selected_iter;
   gint len;
   gint count = 0;
-  gchar *text;
+  const gchar *text;
   GtkWidget *window;
   GtkTreeIter iter;
   GtkTreeModel *model;
   GtkTreeSelection *selection;
-  
+
   g_return_if_fail (GTK_IS_ENTRY (entry));
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
-  
+
   window = gtk_widget_get_parent (entry);
   text = gtk_entry_get_text (GTK_ENTRY (entry));
   len = strlen (text);
@@ -9032,25 +9421,133 @@ gtk_tree_view_search_init (GtkWidget   *entry,
 
   /* search */
   gtk_tree_selection_unselect_all (selection);
-  selected_iter = gtk_object_get_data (GTK_OBJECT (window), "selected-iter");
+  selected_iter = gtk_object_get_data (GTK_OBJECT (window), "gtk-tree-view-selected-iter");
   if (selected_iter)
     g_free (selected_iter);
-  gtk_object_remove_data (GTK_OBJECT (window), "selected-iter");
+  gtk_object_remove_data (GTK_OBJECT (window), "gtk-tree-view-selected-iter");
 
   if (len < 1)
     return;
-  
+
   gtk_tree_model_get_iter_root (model, &iter);
-  
+
   ret = gtk_tree_view_search_iter (model, selection,
                                   &iter, text,
                                   &count, 1);
 
-  if (ret) 
+  if (ret)
     {
       selected_iter = g_malloc (sizeof (int));
       *selected_iter = 1;
-      gtk_object_set_data (GTK_OBJECT (window), "selected-iter",
+      gtk_object_set_data (GTK_OBJECT (window), "gtk-tree-view-selected-iter",
                            selected_iter);
     }
 }
+
+static void
+gtk_tree_view_remove_widget (GtkCellEditable *cell_editable,
+                            GtkTreeView     *tree_view)
+{
+  g_return_if_fail (tree_view->priv->edited_column != NULL);
+  _gtk_tree_view_column_stop_editing (tree_view->priv->edited_column);
+  tree_view->priv->edited_column = NULL;
+
+  gtk_container_remove (GTK_CONTAINER (tree_view),
+                       GTK_WIDGET (cell_editable));
+  gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+}
+
+static gboolean
+gtk_tree_view_start_editing (GtkTreeView *tree_view,
+                            GtkTreePath *cursor_path)
+{
+  GtkTreeIter iter;
+  GdkRectangle background_area;
+  GdkRectangle cell_area;
+  GtkCellEditable *editable_widget = NULL;
+  gchar *path_string;
+  guint flags = 0; /* can be 0, as the flags are primarily for rendering */
+  gint retval = FALSE;
+  GtkRBTree *cursor_tree;
+  GtkRBNode *cursor_node;
+
+  g_assert (tree_view->priv->focus_column);
+
+  if (! GTK_WIDGET_REALIZED (tree_view))
+    return FALSE;
+
+  if (_gtk_tree_view_find_node (tree_view, cursor_path, &cursor_tree, &cursor_node) ||
+      cursor_node == NULL)
+    return FALSE;
+
+  path_string = gtk_tree_path_to_string (cursor_path);
+  gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path);
+  gtk_tree_view_column_cell_set_cell_data (tree_view->priv->focus_column,
+                                          tree_view->priv->model,
+                                          &iter,
+                                          GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT),
+                                          cursor_node->children?TRUE:FALSE);
+  gtk_tree_view_get_background_area (tree_view,
+                                    cursor_path,
+                                    tree_view->priv->focus_column,
+                                    &background_area);
+  gtk_tree_view_get_cell_area (tree_view,
+                              cursor_path,
+                              tree_view->priv->focus_column,
+                              &cell_area);
+  if (_gtk_tree_view_column_cell_event (tree_view->priv->focus_column,
+                                       &editable_widget,
+                                       NULL,
+                                       path_string,
+                                       &background_area,
+                                       &cell_area,
+                                       flags))
+    {
+      retval = TRUE;
+      if (editable_widget != NULL)
+       {
+         gtk_tree_view_real_start_editing (tree_view,
+                                           tree_view->priv->focus_column,
+                                           cursor_path,
+                                           editable_widget,
+                                           &cell_area,
+                                           NULL,
+                                           flags);
+       }
+
+    }
+  g_free (path_string);
+  return retval;
+}
+
+static void
+gtk_tree_view_real_start_editing (GtkTreeView       *tree_view,
+                                 GtkTreeViewColumn *column,
+                                 GtkTreePath       *path,
+                                 GtkCellEditable   *cell_editable,
+                                 GdkRectangle      *cell_area,
+                                 GdkEvent          *event,
+                                 guint              flags)
+{
+  tree_view->priv->edited_column = column;
+  _gtk_tree_view_column_start_editing (column, GTK_CELL_EDITABLE (cell_editable));
+  gtk_tree_view_real_set_cursor (tree_view, path, FALSE);
+  GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
+  gtk_tree_view_put (tree_view,
+                    GTK_WIDGET (cell_editable),
+                    cell_area->x, cell_area->y, cell_area->width, cell_area->height);
+  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);
+}
+
+static void
+gtk_tree_view_stop_editing (GtkTreeView *tree_view)
+{
+  if (tree_view->priv->edited_column == NULL)
+    return;
+
+  gtk_cell_editable_editing_done (tree_view->priv->edited_column->editable_widget);
+  gtk_cell_editable_remove_widget (tree_view->priv->edited_column->editable_widget);
+}