]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktreeview.c
Convert input to filename encoding and construct an URI from that. Add
[~andy/gtk] / gtk / gtktreeview.c
index 925ac7a42bde2dca16b58c16ee7e12fd27f5ae44..dd0eddbb64d59e77f98a8e21e370b5bea5debe91 100644 (file)
@@ -133,12 +133,14 @@ enum {
   PROP_SEARCH_COLUMN,
   PROP_FIXED_HEIGHT_MODE,
   PROP_HOVER_SELECTION,
-  PROP_HOVER_EXPAND
+  PROP_HOVER_EXPAND,
+  PROP_SHOW_EXPANDERS,
+  PROP_LEVEL_INDENTATION,
+  PROP_RUBBER_BANDING,
+  PROP_ENABLE_GRID_LINES,
+  PROP_ENABLE_TREE_LINES
 };
 
-static void     gtk_tree_view_class_init           (GtkTreeViewClass *klass);
-static void     gtk_tree_view_init                 (GtkTreeView      *tree_view);
-
 /* object signals */
 static void     gtk_tree_view_finalize             (GObject          *object);
 static void     gtk_tree_view_set_property         (GObject         *object,
@@ -177,6 +179,8 @@ static gboolean gtk_tree_view_button_press         (GtkWidget        *widget,
                                                    GdkEventButton   *event);
 static gboolean gtk_tree_view_button_release       (GtkWidget        *widget,
                                                    GdkEventButton   *event);
+static gboolean gtk_tree_view_grab_broken          (GtkWidget          *widget,
+                                                   GdkEventGrabBroken *event);
 #if 0
 static gboolean gtk_tree_view_configure            (GtkWidget         *widget,
                                                    GdkEventConfigure *event);
@@ -301,6 +305,7 @@ static gboolean gtk_tree_view_is_expander_column             (GtkTreeView
 static void     gtk_tree_view_add_move_binding               (GtkBindingSet     *binding_set,
                                                              guint              keyval,
                                                              guint              modmask,
+                                                             gboolean           add_shifted_binding,
                                                              GtkMovementStep    step,
                                                              gint               count);
 static gint     gtk_tree_view_unref_and_check_selection_tree (GtkTreeView       *tree_view,
@@ -377,13 +382,15 @@ static void     column_sizing_notify                         (GObject
                                                               gpointer           data);
 static gboolean expand_collapse_timeout                      (gpointer           data);
 static gboolean do_expand_collapse                           (GtkTreeView       *tree_view);
+static void     gtk_tree_view_stop_rubber_band                (GtkTreeView       *tree_view);
 
 /* interactive search */
 static void     gtk_tree_view_ensure_interactive_directory (GtkTreeView *tree_view);
 static void     gtk_tree_view_search_dialog_hide     (GtkWidget        *search_dialog,
                                                         GtkTreeView      *tree_view);
 static void     gtk_tree_view_search_position_func      (GtkTreeView      *tree_view,
-                                                        GtkWidget        *search_dialog);
+                                                        GtkWidget        *search_dialog,
+                                                        gpointer          user_data);
 static void     gtk_tree_view_search_disable_popdown    (GtkEntry         *entry,
                                                         GtkMenu          *menu,
                                                         gpointer          data);
@@ -400,6 +407,9 @@ static gboolean gtk_tree_view_search_delete_event       (GtkWidget        *widge
 static gboolean gtk_tree_view_search_button_press_event (GtkWidget        *widget,
                                                         GdkEventButton   *event,
                                                         GtkTreeView      *tree_view);
+static gboolean gtk_tree_view_search_scroll_event       (GtkWidget        *entry,
+                                                        GdkEventScroll   *event,
+                                                        GtkTreeView      *tree_view);
 static gboolean gtk_tree_view_search_key_press_event    (GtkWidget        *entry,
                                                         GdkEventKey      *event,
                                                         GtkTreeView      *tree_view);
@@ -449,8 +459,9 @@ static void gtk_tree_view_tree_window_to_tree_coords (GtkTreeView *tree_view,
                                                      gint        *tx,
                                                      gint        *ty);
 
+static gint scroll_row_timeout                       (gpointer     data);
+static void remove_scroll_timeout                    (GtkTreeView *tree_view);
 
-static GtkContainerClass *parent_class = NULL;
 static guint tree_view_signals [LAST_SIGNAL] = { 0 };
 
 \f
@@ -458,33 +469,7 @@ static guint tree_view_signals [LAST_SIGNAL] = { 0 };
 /* GType Methods
  */
 
-GType
-gtk_tree_view_get_type (void)
-{
-  static GType tree_view_type = 0;
-
-  if (!tree_view_type)
-    {
-      static const GTypeInfo tree_view_info =
-      {
-        sizeof (GtkTreeViewClass),
-       NULL,           /* base_init */
-       NULL,           /* base_finalize */
-        (GClassInitFunc) gtk_tree_view_class_init,
-       NULL,           /* class_finalize */
-       NULL,           /* class_data */
-        sizeof (GtkTreeView),
-       0,              /* n_preallocs */
-        (GInstanceInitFunc) gtk_tree_view_init
-      };
-
-      tree_view_type =
-       g_type_register_static (GTK_TYPE_CONTAINER, "GtkTreeView",
-                               &tree_view_info, 0);
-    }
-
-  return tree_view_type;
-}
+G_DEFINE_TYPE (GtkTreeView, gtk_tree_view, GTK_TYPE_CONTAINER)
 
 static void
 gtk_tree_view_class_init (GtkTreeViewClass *class)
@@ -495,7 +480,6 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   GtkContainerClass *container_class;
   GtkBindingSet *binding_set;
 
-  parent_class = g_type_class_peek_parent (class);
   binding_set = gtk_binding_set_by_class (class);
 
   o_class = (GObjectClass *) class;
@@ -519,6 +503,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   widget_class->size_allocate = gtk_tree_view_size_allocate;
   widget_class->button_press_event = gtk_tree_view_button_press;
   widget_class->button_release_event = gtk_tree_view_button_release;
+  widget_class->grab_broken_event = gtk_tree_view_grab_broken;
   /*widget_class->configure_event = gtk_tree_view_configure;*/
   widget_class->motion_notify_event = gtk_tree_view_motion;
   widget_class->expose_event = gtk_tree_view_expose;
@@ -700,6 +685,48 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                                                            FALSE,
                                                            GTK_PARAM_READWRITE));
 
+    g_object_class_install_property (o_class,
+                                    PROP_SHOW_EXPANDERS,
+                                    g_param_spec_boolean ("show-expanders",
+                                                          P_("Show Expanders"),
+                                                          P_("View has expanders"),
+                                                          TRUE,
+                                                          GTK_PARAM_READWRITE));
+
+    g_object_class_install_property (o_class,
+                                    PROP_LEVEL_INDENTATION,
+                                    g_param_spec_int ("level-indentation",
+                                                      P_("Level Indentation"),
+                                                      P_("Extra indentation for each level"),
+                                                      0,
+                                                      G_MAXINT,
+                                                      0,
+                                                      GTK_PARAM_READWRITE));
+
+    g_object_class_install_property (o_class,
+                                     PROP_RUBBER_BANDING,
+                                     g_param_spec_boolean ("rubber-banding",
+                                                           P_("Rubber Banding"),
+                                                           P_("Whether to enable selection of multiple items by dragging the mouse pointer"),
+                                                           FALSE,
+                                                           GTK_PARAM_READWRITE));
+
+    g_object_class_install_property (o_class,
+                                     PROP_ENABLE_GRID_LINES,
+                                     g_param_spec_boolean ("enable-grid-lines",
+                                                           P_("Enable Grid Lines"),
+                                                           P_("Whether grid lines should be drawn in the tree view"),
+                                                           FALSE,
+                                                           GTK_PARAM_READWRITE));
+
+    g_object_class_install_property (o_class,
+                                     PROP_ENABLE_TREE_LINES,
+                                     g_param_spec_boolean ("enable-tree-lines",
+                                                           P_("Enable Tree Lines"),
+                                                           P_("Whether tree lines should be drawn in the tree view"),
+                                                           FALSE,
+                                                           GTK_PARAM_READWRITE));
+
   /* Style properties */
 #define _TREE_VIEW_EXPANDER_SIZE 12
 #define _TREE_VIEW_VERTICAL_SEPARATOR 2
@@ -760,9 +787,44 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                                                               GDK_TYPE_COLOR,
                                                               GTK_PARAM_READABLE));
 
+  gtk_widget_class_install_style_property (widget_class,
+                                          g_param_spec_boolean ("row-ending-details",
+                                                                P_("Row Ending details"),
+                                                                P_("Enable extended row background theming"),
+                                                                FALSE,
+                                                                GTK_PARAM_READABLE));
+
+  gtk_widget_class_install_style_property (widget_class,
+                                          g_param_spec_int ("grid-line-width",
+                                                            P_("Grid line width"),
+                                                            P_("Width, in pixels, of the tree view grid lines"),
+                                                            0, G_MAXINT, 1,
+                                                            GTK_PARAM_READABLE));
+
+  gtk_widget_class_install_style_property (widget_class,
+                                          g_param_spec_int ("tree-line-width",
+                                                            P_("Tree line width"),
+                                                            P_("Width, in pixels, of the tree view lines"),
+                                                            0, G_MAXINT, 1,
+                                                            GTK_PARAM_READABLE));
+
+  gtk_widget_class_install_style_property (widget_class,
+                                          g_param_spec_string ("grid-line-pattern",
+                                                               P_("Grid line pattern"),
+                                                               P_("Dash pattern used to draw the tree view grid lines"),
+                                                               "\1\1",
+                                                               GTK_PARAM_READABLE));
+
+  gtk_widget_class_install_style_property (widget_class,
+                                          g_param_spec_string ("tree-line-pattern",
+                                                               P_("Tree line pattern"),
+                                                               P_("Dash pattern used to draw the tree view lines"),
+                                                               "\1\1",
+                                                               GTK_PARAM_READABLE));
+
   /* Signals */
   widget_class->set_scroll_adjustments_signal =
-    g_signal_new ("set_scroll_adjustments",
+    g_signal_new (I_("set_scroll_adjustments"),
                  G_TYPE_FROM_CLASS (o_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, set_scroll_adjustments),
@@ -772,8 +834,23 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                  GTK_TYPE_ADJUSTMENT,
                  GTK_TYPE_ADJUSTMENT);
 
+  /**
+   * GtkTreeView::row-activated:
+   * @tree_view: the object on which the signal is emitted
+   * @path: the #GtkTreePath for the activated row
+   * @column: the #GtkTreeViewColumn in which the activation occurred
+   *
+   * The "row-activated" signal is emitted when the method
+   * gtk_tree_view_row_activated() is called or the user double clicks 
+   * a treeview row. It is also emitted when a non-editable row is 
+   * selected and one of the keys: Space, Shift+Space, Return or 
+   * Enter is pressed.
+   * 
+   * For selection handling refer to the <link linkend="TreeWidget">tree 
+   * widget conceptual overview</link> as well as #GtkTreeSelection.
+   */
   tree_view_signals[ROW_ACTIVATED] =
-    g_signal_new ("row_activated",
+    g_signal_new (I_("row_activated"),
                  G_TYPE_FROM_CLASS (o_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, row_activated),
@@ -783,8 +860,19 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                  GTK_TYPE_TREE_PATH,
                  GTK_TYPE_TREE_VIEW_COLUMN);
 
+  /**
+   * GtkTreeView::test-expand-row:
+   * @tree_view: the object on which the signal is emitted
+   * @iter: the tree iter of the row to expand
+   * @path: a tree path that points to the row 
+   * 
+   * The given row is about to be expanded (show its children nodes). Use this
+   * signal if you need to control the expandability of individual rows.
+   *
+   * Returns: %TRUE to allow expansion, %FALSE to reject
+   */
   tree_view_signals[TEST_EXPAND_ROW] =
-    g_signal_new ("test_expand_row",
+    g_signal_new (I_("test-expand-row"),
                  G_TYPE_FROM_CLASS (o_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkTreeViewClass, test_expand_row),
@@ -794,8 +882,19 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                  GTK_TYPE_TREE_ITER,
                  GTK_TYPE_TREE_PATH);
 
+  /**
+   * GtkTreeView::test-collapse-row:
+   * @tree_view: the object on which the signal is emitted
+   * @iter: the tree iter of the row to collapse
+   * @path: a tree path that points to the row 
+   * 
+   * The given row is about to be collapsed (hide its children nodes). Use this
+   * signal if you need to control the collapsibility of individual rows.
+   *
+   * Returns: %TRUE to allow expansion, %FALSE to reject
+   */
   tree_view_signals[TEST_COLLAPSE_ROW] =
-    g_signal_new ("test_collapse_row",
+    g_signal_new (I_("test-collapse-row"),
                  G_TYPE_FROM_CLASS (o_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkTreeViewClass, test_collapse_row),
@@ -805,8 +904,16 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                  GTK_TYPE_TREE_ITER,
                  GTK_TYPE_TREE_PATH);
 
+  /**
+   * GtkTreeView::row-expanded:
+   * @tree_view: the object on which the signal is emitted
+   * @iter: the tree iter of the expanded row
+   * @path: a tree path that points to the row 
+   * 
+   * The given row has been expanded (child nodes are shown).
+   */
   tree_view_signals[ROW_EXPANDED] =
-    g_signal_new ("row_expanded",
+    g_signal_new (I_("row-expanded"),
                  G_TYPE_FROM_CLASS (o_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkTreeViewClass, row_expanded),
@@ -816,8 +923,16 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                  GTK_TYPE_TREE_ITER,
                  GTK_TYPE_TREE_PATH);
 
+  /**
+   * GtkTreeView::row-collapsed:
+   * @tree_view: the object on which the signal is emitted
+   * @iter: the tree iter of the collapsed row
+   * @path: a tree path that points to the row 
+   * 
+   * The given row has been collapsed (child nodes are hidden).
+   */
   tree_view_signals[ROW_COLLAPSED] =
-    g_signal_new ("row_collapsed",
+    g_signal_new (I_("row-collapsed"),
                  G_TYPE_FROM_CLASS (o_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkTreeViewClass, row_collapsed),
@@ -827,8 +942,14 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                  GTK_TYPE_TREE_ITER,
                  GTK_TYPE_TREE_PATH);
 
+  /**
+   * GtkTreeView::columns-changed:
+   * @tree_view: the object on which the signal is emitted 
+   * 
+   * The number of columns of the treeview has changed.
+   */
   tree_view_signals[COLUMNS_CHANGED] =
-    g_signal_new ("columns_changed",
+    g_signal_new (I_("columns-changed"),
                  G_TYPE_FROM_CLASS (o_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkTreeViewClass, columns_changed),
@@ -836,8 +957,14 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                  _gtk_marshal_NONE__NONE,
                  G_TYPE_NONE, 0);
 
+  /**
+   * GtkTreeView::cursor-changed:
+   * @tree_view: the object on which the signal is emitted
+   * 
+   * The position of the cursor (focused cell) has changed.
+   */
   tree_view_signals[CURSOR_CHANGED] =
-    g_signal_new ("cursor_changed",
+    g_signal_new (I_("cursor-changed"),
                  G_TYPE_FROM_CLASS (o_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkTreeViewClass, cursor_changed),
@@ -846,7 +973,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                  G_TYPE_NONE, 0);
 
   tree_view_signals[MOVE_CURSOR] =
-    g_signal_new ("move_cursor",
+    g_signal_new (I_("move_cursor"),
                  G_TYPE_FROM_CLASS (object_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, move_cursor),
@@ -857,7 +984,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                  G_TYPE_INT);
 
   tree_view_signals[SELECT_ALL] =
-    g_signal_new ("select_all",
+    g_signal_new (I_("select_all"),
                  G_TYPE_FROM_CLASS (object_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, select_all),
@@ -866,7 +993,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                  G_TYPE_BOOLEAN, 0);
 
   tree_view_signals[UNSELECT_ALL] =
-    g_signal_new ("unselect_all",
+    g_signal_new (I_("unselect_all"),
                  G_TYPE_FROM_CLASS (object_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, unselect_all),
@@ -875,7 +1002,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                  G_TYPE_BOOLEAN, 0);
 
   tree_view_signals[SELECT_CURSOR_ROW] =
-    g_signal_new ("select_cursor_row",
+    g_signal_new (I_("select_cursor_row"),
                  G_TYPE_FROM_CLASS (object_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_row),
@@ -885,7 +1012,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                  G_TYPE_BOOLEAN);
 
   tree_view_signals[TOGGLE_CURSOR_ROW] =
-    g_signal_new ("toggle_cursor_row",
+    g_signal_new (I_("toggle_cursor_row"),
                  G_TYPE_FROM_CLASS (object_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, toggle_cursor_row),
@@ -894,7 +1021,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                  G_TYPE_BOOLEAN, 0);
 
   tree_view_signals[EXPAND_COLLAPSE_CURSOR_ROW] =
-    g_signal_new ("expand_collapse_cursor_row",
+    g_signal_new (I_("expand_collapse_cursor_row"),
                  G_TYPE_FROM_CLASS (object_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, expand_collapse_cursor_row),
@@ -906,7 +1033,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                  G_TYPE_BOOLEAN);
 
   tree_view_signals[SELECT_CURSOR_PARENT] =
-    g_signal_new ("select_cursor_parent",
+    g_signal_new (I_("select_cursor_parent"),
                  G_TYPE_FROM_CLASS (object_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_parent),
@@ -915,7 +1042,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                  G_TYPE_BOOLEAN, 0);
 
   tree_view_signals[START_INTERACTIVE_SEARCH] =
-    g_signal_new ("start_interactive_search",
+    g_signal_new (I_("start_interactive_search"),
                  G_TYPE_FROM_CLASS (object_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, start_interactive_search),
@@ -924,40 +1051,40 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                  G_TYPE_BOOLEAN, 0);
 
   /* Key bindings */
-  gtk_tree_view_add_move_binding (binding_set, GDK_Up, 0,
+  gtk_tree_view_add_move_binding (binding_set, GDK_Up, 0, TRUE,
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
-  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Up, 0,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Up, 0, TRUE,
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
 
-  gtk_tree_view_add_move_binding (binding_set, GDK_Down, 0,
+  gtk_tree_view_add_move_binding (binding_set, GDK_Down, 0, TRUE,
                                  GTK_MOVEMENT_DISPLAY_LINES, 1);
-  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Down, 0,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Down, 0, TRUE,
                                  GTK_MOVEMENT_DISPLAY_LINES, 1);
 
-  gtk_tree_view_add_move_binding (binding_set, GDK_p, GDK_CONTROL_MASK,
+  gtk_tree_view_add_move_binding (binding_set, GDK_p, GDK_CONTROL_MASK, FALSE,
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
 
-  gtk_tree_view_add_move_binding (binding_set, GDK_n, GDK_CONTROL_MASK,
+  gtk_tree_view_add_move_binding (binding_set, GDK_n, GDK_CONTROL_MASK, FALSE,
                                  GTK_MOVEMENT_DISPLAY_LINES, 1);
 
-  gtk_tree_view_add_move_binding (binding_set, GDK_Home, 0,
+  gtk_tree_view_add_move_binding (binding_set, GDK_Home, 0, TRUE,
                                  GTK_MOVEMENT_BUFFER_ENDS, -1);
-  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Home, 0,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Home, 0, TRUE,
                                  GTK_MOVEMENT_BUFFER_ENDS, -1);
 
-  gtk_tree_view_add_move_binding (binding_set, GDK_End, 0,
+  gtk_tree_view_add_move_binding (binding_set, GDK_End, 0, TRUE,
                                  GTK_MOVEMENT_BUFFER_ENDS, 1);
-  gtk_tree_view_add_move_binding (binding_set, GDK_KP_End, 0,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KP_End, 0, TRUE,
                                  GTK_MOVEMENT_BUFFER_ENDS, 1);
 
-  gtk_tree_view_add_move_binding (binding_set, GDK_Page_Up, 0,
+  gtk_tree_view_add_move_binding (binding_set, GDK_Page_Up, 0, TRUE,
                                  GTK_MOVEMENT_PAGES, -1);
-  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Page_Up, 0,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Page_Up, 0, TRUE,
                                  GTK_MOVEMENT_PAGES, -1);
 
-  gtk_tree_view_add_move_binding (binding_set, GDK_Page_Down, 0,
+  gtk_tree_view_add_move_binding (binding_set, GDK_Page_Down, 0, TRUE,
                                  GTK_MOVEMENT_PAGES, 1);
-  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Page_Down, 0,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Page_Down, 0, TRUE,
                                  GTK_MOVEMENT_PAGES, 1);
 
 
@@ -1125,16 +1252,20 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                                G_TYPE_BOOLEAN, TRUE);
 
   gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0, "select_cursor_parent", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_CONTROL_MASK, "select_cursor_parent", 0);
 
   gtk_binding_entry_add_signal (binding_set, GDK_f, GDK_CONTROL_MASK, "start_interactive_search", 0);
 
   gtk_binding_entry_add_signal (binding_set, GDK_F, GDK_CONTROL_MASK, "start_interactive_search", 0);
+
+  g_type_class_add_private (o_class, sizeof (GtkTreeViewPrivate));
 }
 
 static void
 gtk_tree_view_init (GtkTreeView *tree_view)
 {
-  tree_view->priv = g_new0 (GtkTreeViewPrivate, 1);
+  tree_view->priv = G_TYPE_INSTANCE_GET_PRIVATE (tree_view, GTK_TYPE_TREE_VIEW, GtkTreeViewPrivate);
+
   GTK_WIDGET_SET_FLAGS (tree_view, GTK_CAN_FOCUS);
 
   gtk_widget_set_redraw_on_allocate (GTK_WIDGET (tree_view), FALSE);
@@ -1163,14 +1294,22 @@ gtk_tree_view_init (GtkTreeView *tree_view)
   tree_view->priv->selection = _gtk_tree_selection_new_with_tree_view (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;
+  tree_view->priv->search_position_func = gtk_tree_view_search_position_func;
   tree_view->priv->search_equal_func = gtk_tree_view_search_equal_func;
+  tree_view->priv->search_custom_entry_set = FALSE;
   tree_view->priv->typeselect_flush_timeout = 0;
   tree_view->priv->init_hadjust_value = TRUE;    
   tree_view->priv->width = 0;
           
   tree_view->priv->hover_selection = FALSE;
   tree_view->priv->hover_expand = FALSE;
+
+  tree_view->priv->level_indentation = 0;
+
+  tree_view->priv->rubber_banding_enable = FALSE;
+
+  tree_view->priv->grid_lines = GTK_TREE_VIEW_GRID_LINES_NONE;
+  tree_view->priv->tree_lines_enabled = FALSE;
 }
 
 \f
@@ -1229,6 +1368,24 @@ gtk_tree_view_set_property (GObject         *object,
     case PROP_HOVER_EXPAND:
       tree_view->priv->hover_expand = g_value_get_boolean (value);
       break;
+    case PROP_SHOW_EXPANDERS:
+      if (g_value_get_boolean (value))
+       GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_SHOW_EXPANDERS);
+      else
+       GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_SHOW_EXPANDERS);
+      break;
+    case PROP_LEVEL_INDENTATION:
+      tree_view->priv->level_indentation = g_value_get_int (value);
+      break;
+    case PROP_RUBBER_BANDING:
+      tree_view->priv->rubber_banding_enable = g_value_get_boolean (value);
+      break;
+    case PROP_ENABLE_GRID_LINES:
+      gtk_tree_view_set_grid_lines (tree_view, g_value_get_boolean (value));
+      break;
+    case PROP_ENABLE_TREE_LINES:
+      gtk_tree_view_set_enable_tree_lines (tree_view, g_value_get_boolean (value));
+      break;
     default:
       break;
     }
@@ -1258,6 +1415,9 @@ gtk_tree_view_get_property (GObject    *object,
     case PROP_HEADERS_VISIBLE:
       g_value_set_boolean (value, gtk_tree_view_get_headers_visible (tree_view));
       break;
+    case PROP_HEADERS_CLICKABLE:
+      g_value_set_boolean (value, gtk_tree_view_get_headers_clickable (tree_view));
+      break;
     case PROP_EXPANDER_COLUMN:
       g_value_set_object (value, tree_view->priv->expander_column);
       break;
@@ -1282,6 +1442,21 @@ gtk_tree_view_get_property (GObject    *object,
     case PROP_HOVER_EXPAND:
       g_value_set_boolean (value, tree_view->priv->hover_expand);
       break;
+    case PROP_SHOW_EXPANDERS:
+      g_value_set_boolean (value, GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_SHOW_EXPANDERS));
+      break;
+    case PROP_LEVEL_INDENTATION:
+      g_value_set_int (value, tree_view->priv->level_indentation);
+      break;
+    case PROP_RUBBER_BANDING:
+      g_value_set_boolean (value, tree_view->priv->rubber_banding_enable);
+      break;
+    case PROP_ENABLE_GRID_LINES:
+      g_value_set_boolean (value, tree_view->priv->grid_lines);
+      break;
+    case PROP_ENABLE_TREE_LINES:
+      g_value_set_boolean (value, tree_view->priv->tree_lines_enabled);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1291,11 +1466,7 @@ gtk_tree_view_get_property (GObject    *object,
 static void
 gtk_tree_view_finalize (GObject *object)
 {
-  GtkTreeView *tree_view = (GtkTreeView *) object;
-
-  g_free (tree_view->priv);
-
-  (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+  (* G_OBJECT_CLASS (gtk_tree_view_parent_class)->finalize) (object);
 }
 
 \f
@@ -1303,6 +1474,20 @@ gtk_tree_view_finalize (GObject *object)
 /* GtkObject Methods
  */
 
+static void
+gtk_tree_view_free_rbtree (GtkTreeView *tree_view)
+{
+  _gtk_rbtree_free (tree_view->priv->tree);
+  
+  tree_view->priv->tree = NULL;
+  tree_view->priv->button_pressed_node = NULL;
+  tree_view->priv->button_pressed_tree = NULL;
+  tree_view->priv->prelight_tree = NULL;
+  tree_view->priv->prelight_node = NULL;
+  tree_view->priv->expanded_collapsed_node = NULL;
+  tree_view->priv->expanded_collapsed_tree = NULL;
+}
+
 static void
 gtk_tree_view_destroy (GtkObject *object)
 {
@@ -1327,8 +1512,8 @@ gtk_tree_view_destroy (GtkObject *object)
   if (tree_view->priv->tree != NULL)
     {
       gtk_tree_view_unref_and_check_selection_tree (tree_view, tree_view->priv->tree);
-      _gtk_rbtree_free (tree_view->priv->tree);
-      tree_view->priv->tree = NULL;
+
+      gtk_tree_view_free_rbtree (tree_view);
     }
 
   if (tree_view->priv->selection != NULL)
@@ -1401,13 +1586,19 @@ gtk_tree_view_destroy (GtkObject *object)
        }
     }
 
-  if (tree_view->priv->search_destroy)
+  if (tree_view->priv->search_destroy && 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 (tree_view->priv->row_separator_destroy)
+  if (tree_view->priv->search_position_destroy && tree_view->priv->search_position_user_data)
+    {
+      (* tree_view->priv->search_position_destroy) (tree_view->priv->search_position_user_data);
+      tree_view->priv->search_position_user_data = NULL;
+    }
+
+  if (tree_view->priv->row_separator_destroy && tree_view->priv->row_separator_data)
     {
       (* tree_view->priv->row_separator_destroy) (tree_view->priv->row_separator_data);
       tree_view->priv->row_separator_data = NULL;
@@ -1426,8 +1617,8 @@ gtk_tree_view_destroy (GtkObject *object)
       tree_view->priv->vadjustment = NULL;
     }
 
-  if (GTK_OBJECT_CLASS (parent_class)->destroy)
-    (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+  if (GTK_OBJECT_CLASS (gtk_tree_view_parent_class)->destroy)
+    (* GTK_OBJECT_CLASS (gtk_tree_view_parent_class)->destroy) (object);
 }
 
 \f
@@ -1507,7 +1698,6 @@ gtk_tree_view_realize (GtkWidget *widget)
 {
   GList *tmp_list;
   GtkTreeView *tree_view;
-  GdkGCValues values;
   GdkWindowAttr attributes;
   gint attributes_mask;
 
@@ -1569,15 +1759,9 @@ gtk_tree_view_realize (GtkWidget *widget)
                                                   &attributes, attributes_mask);
   gdk_window_set_user_data (tree_view->priv->header_window, widget);
 
-
-  values.foreground = (widget->style->white.pixel==0 ?
-                      widget->style->black:widget->style->white);
-  values.function = GDK_XOR;
-  values.subwindow_mode = GDK_INCLUDE_INFERIORS;
-
   /* Add them all up. */
   widget->style = gtk_style_attach (widget->style, widget->window);
-  gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
+  gdk_window_set_back_pixmap (widget->window, NULL, FALSE);
   gdk_window_set_background (tree_view->priv->bin_window, &widget->style->base[widget->state]);
   gtk_style_set_background (widget->style, tree_view->priv->header_window, GTK_STATE_NORMAL);
 
@@ -1593,6 +1777,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));
 
+  /* Need to call those here, since they craete GCs */
+  gtk_tree_view_set_grid_lines (tree_view, tree_view->priv->grid_lines);
+  gtk_tree_view_set_enable_tree_lines (tree_view, tree_view->priv->tree_lines_enabled);
+
   install_presize_handler (tree_view); 
 }
 
@@ -1674,8 +1862,8 @@ gtk_tree_view_unrealize (GtkWidget *widget)
     }
 
   /* GtkWidget::unrealize destroys children and widget->window */
-  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
-    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+  if (GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->unrealize)
+    (* GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->unrealize) (widget);
 }
 
 /* GtkWidget::size_request helper */
@@ -1900,6 +2088,7 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
   gint extra, extra_per_column;
   gint full_requested_width = 0;
   gint number_of_expand_columns = 0;
+  gboolean column_changed = FALSE;
   gboolean rtl;
   
   tree_view = GTK_TREE_VIEW (widget);
@@ -2002,7 +2191,7 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
       width += column->width;
 
       if (column->width > old_width)
-       invalidate_column (tree_view, column);
+        column_changed = TRUE;
 
       gtk_widget_size_allocate (column->button, &allocation);
 
@@ -2012,6 +2201,9 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
                                allocation.y,
                                 TREE_VIEW_DRAG_WIDTH, allocation.height);
     }
+
+  if (column_changed)
+    gtk_widget_queue_draw (GTK_WIDGET (tree_view));
 }
 
 
@@ -2092,7 +2284,12 @@ gtk_tree_view_size_allocate (GtkWidget     *widget,
   gtk_adjustment_changed (tree_view->priv->vadjustment);
 
   /* now the adjustments and window sizes are in sync, we can sync toprow/dy again */
-  if (gtk_tree_row_reference_valid (tree_view->priv->top_row))
+  if (tree_view->priv->height <= tree_view->priv->vadjustment->page_size)
+    gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment), 0);
+  else if (tree_view->priv->vadjustment->value + tree_view->priv->vadjustment->page_size > tree_view->priv->height)
+    gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment),
+                              tree_view->priv->height - tree_view->priv->vadjustment->page_size);
+  else if (gtk_tree_row_reference_valid (tree_view->priv->top_row))
     gtk_tree_view_top_row_to_dy (tree_view);
   else
     gtk_tree_view_dy_to_top_row (tree_view);
@@ -2198,6 +2395,7 @@ gtk_tree_view_button_press (GtkWidget      *widget,
       gint column_handled_click = FALSE;
       gboolean row_double_click = FALSE;
       gboolean rtl;
+      gboolean node_selected;
 
       /* Empty tree? */
       if (tree_view->priv->tree == NULL)
@@ -2208,7 +2406,8 @@ gtk_tree_view_button_press (GtkWidget      *widget,
 
       /* are we in an arrow? */
       if (tree_view->priv->prelight_node &&
-          GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
+          GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT) &&
+         TREE_VIEW_DRAW_EXPANDERS (tree_view))
        {
          if (event->button == 1)
            {
@@ -2252,12 +2451,12 @@ gtk_tree_view_button_press (GtkWidget      *widget,
       for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
           list; list = (rtl ? list->prev : list->next))
        {
-         column = list->data;
+         GtkTreeViewColumn *candidate = list->data;
 
-         if (!column->visible)
+         if (!candidate->visible)
            continue;
 
-         background_area.width = column->width;
+         background_area.width = candidate->width;
          if ((background_area.x > (gint) event->x) ||
              (background_area.x + background_area.width <= (gint) event->x))
            {
@@ -2266,16 +2465,24 @@ gtk_tree_view_button_press (GtkWidget      *widget,
            }
 
          /* we found the focus column */
+         column = candidate;
          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))
+         if (gtk_tree_view_is_expander_column (tree_view, column))
            {
-             cell_area.x += depth * tree_view->priv->expander_size;
-             cell_area.width -= depth * tree_view->priv->expander_size;
+             if (!rtl)
+               cell_area.x += (depth - 1) * tree_view->priv->level_indentation;
+             cell_area.width -= (depth - 1) * tree_view->priv->level_indentation;
+
+              if (TREE_VIEW_DRAW_EXPANDERS (tree_view))
+               {
+                 if (!rtl)
+                   cell_area.x += depth * tree_view->priv->expander_size;
+                 cell_area.width -= depth * tree_view->priv->expander_size;
+               }
            }
          break;
        }
@@ -2357,6 +2564,7 @@ gtk_tree_view_button_press (GtkWidget      *widget,
        }
 
       /* select */
+      node_selected = GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED);
       pre_val = tree_view->priv->vadjustment->value;
 
       /* we only handle selection modifications on the first button press
@@ -2409,6 +2617,21 @@ gtk_tree_view_button_press (GtkWidget      *widget,
           tree_view->priv->pressed_button = event->button;
           tree_view->priv->press_start_x = event->x;
           tree_view->priv->press_start_y = event->y;
+
+         if (tree_view->priv->rubber_banding_enable
+             && !node_selected
+             && tree_view->priv->selection->type == GTK_SELECTION_MULTIPLE)
+           {
+             tree_view->priv->press_start_y += tree_view->priv->dy;
+             tree_view->priv->rubber_band_x = event->x;
+             tree_view->priv->rubber_band_y = event->y + tree_view->priv->dy;
+             tree_view->priv->rubber_band_status = RUBBER_BAND_MAYBE_START;
+
+             if ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
+               tree_view->priv->rubber_band_ctrl = TRUE;
+             if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
+               tree_view->priv->rubber_band_shift = TRUE;
+           }
         }
 
       /* Test if a double click happened on the same row. */
@@ -2624,6 +2847,9 @@ gtk_tree_view_button_release (GtkWidget      *widget,
   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
     return gtk_tree_view_button_release_drag_column (widget, event);
 
+  if (tree_view->priv->rubber_band_status)
+    gtk_tree_view_stop_rubber_band (tree_view);
+
   if (tree_view->priv->pressed_button == event->button)
     tree_view->priv->pressed_button = -1;
 
@@ -2664,6 +2890,26 @@ gtk_tree_view_button_release (GtkWidget      *widget,
   return TRUE;
 }
 
+static gboolean
+gtk_tree_view_grab_broken (GtkWidget          *widget,
+                          GdkEventGrabBroken *event)
+{
+  GtkTreeView *tree_view;
+
+  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);
+
+  if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
+    gtk_tree_view_button_release_drag_column (widget, (GdkEventButton *)event);
+
+  if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE))
+    gtk_tree_view_button_release_column_resize (widget, (GdkEventButton *)event);
+
+  return TRUE;
+}
+
 #if 0
 static gboolean
 gtk_tree_view_configure (GtkWidget *widget,
@@ -2672,7 +2918,7 @@ gtk_tree_view_configure (GtkWidget *widget,
   GtkTreeView *tree_view;
 
   tree_view = GTK_TREE_VIEW (widget);
-  tree_view->priv->search_dialog_position_func (tree_view, tree_view->priv->search_window);
+  tree_view->priv->search_position_func (tree_view, tree_view->priv->search_window);
 
   return FALSE;
 }
@@ -2765,7 +3011,7 @@ do_prelight (GtkTreeView *tree_view,
       /*  We are still on the same node,
          but we might need to take care of the arrow  */
 
-      if (tree && node)
+      if (tree && node && TREE_VIEW_DRAW_EXPANDERS (tree_view))
        {
          gboolean over_arrow;
          gboolean flag_set;
@@ -2797,7 +3043,8 @@ do_prelight (GtkTreeView *tree_view,
       GTK_RBNODE_UNSET_FLAG (tree_view->priv->prelight_node,
                             GTK_RBNODE_IS_PRELIT);
 
-      if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
+      if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT)
+         && TREE_VIEW_DRAW_EXPANDERS (tree_view))
        {
          GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
          
@@ -2827,7 +3074,8 @@ do_prelight (GtkTreeView *tree_view,
 
   /*  Prelight the new node and arrow  */
 
-  if (coords_are_over_arrow (tree_view, tree, node, x, y))
+  if (TREE_VIEW_DRAW_EXPANDERS (tree_view)
+      && coords_are_over_arrow (tree_view, tree, node, x, y))
     {
       GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
 
@@ -3182,7 +3430,7 @@ gtk_tree_view_motion_resize_column (GtkWidget      *widget,
   new_width = gtk_tree_view_new_column_width (tree_view,
                                              tree_view->priv->drag_pos, &x);
   if (x != tree_view->priv->x_drag &&
-      (new_width != column->fixed_width));
+      (new_width != column->fixed_width))
     {
       column->use_resized_width = TRUE;
       column->resized_width = new_width;
@@ -3300,6 +3548,335 @@ gtk_tree_view_motion_drag_column (GtkWidget      *widget,
   return TRUE;
 }
 
+static void
+gtk_tree_view_stop_rubber_band (GtkTreeView *tree_view)
+{
+  remove_scroll_timeout (tree_view);
+  gtk_grab_remove (GTK_WIDGET (tree_view));
+
+  gtk_widget_queue_draw (GTK_WIDGET (tree_view));
+
+  if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
+    {
+      GtkTreePath *tmp_path;
+
+      /* The anchor path should be set to the start path */
+      tmp_path = _gtk_tree_view_find_path (tree_view,
+                                          tree_view->priv->rubber_band_start_tree,
+                                          tree_view->priv->rubber_band_start_node);
+
+      if (tree_view->priv->anchor)
+       gtk_tree_row_reference_free (tree_view->priv->anchor);
+
+      tree_view->priv->anchor =
+       gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
+                                         tree_view->priv->model,
+                                         tmp_path);
+
+      gtk_tree_path_free (tmp_path);
+
+      /* ... and the cursor to the end path */
+      tmp_path = _gtk_tree_view_find_path (tree_view,
+                                          tree_view->priv->rubber_band_end_tree,
+                                          tree_view->priv->rubber_band_end_node);
+      gtk_tree_view_real_set_cursor (GTK_TREE_VIEW (tree_view), tmp_path, FALSE, FALSE);
+      gtk_tree_path_free (tmp_path);
+
+      _gtk_tree_selection_emit_changed (tree_view->priv->selection);
+    }
+
+  /* Clear status variables */
+  tree_view->priv->rubber_band_status = RUBBER_BAND_OFF;
+  tree_view->priv->rubber_band_shift = 0;
+  tree_view->priv->rubber_band_ctrl = 0;
+
+  tree_view->priv->rubber_band_start_node = NULL;
+  tree_view->priv->rubber_band_start_tree = NULL;
+  tree_view->priv->rubber_band_end_node = NULL;
+  tree_view->priv->rubber_band_end_tree = NULL;
+}
+
+static void
+gtk_tree_view_update_rubber_band_selection_range (GtkTreeView *tree_view,
+                                                GtkRBTree   *start_tree,
+                                                GtkRBNode   *start_node,
+                                                GtkRBTree   *end_tree,
+                                                GtkRBNode   *end_node,
+                                                gboolean     select,
+                                                gboolean     skip_start,
+                                                gboolean     skip_end)
+{
+  if (start_node == end_node)
+    return;
+
+  /* We skip the first node and jump inside the loop */
+  if (skip_start)
+    goto skip_first;
+
+  do
+    {
+      if (select)
+        {
+         if (tree_view->priv->rubber_band_shift)
+           GTK_RBNODE_SET_FLAG (start_node, GTK_RBNODE_IS_SELECTED);
+         else if (tree_view->priv->rubber_band_ctrl)
+           {
+             /* Toggle the selection state */
+             if (GTK_RBNODE_FLAG_SET (start_node, GTK_RBNODE_IS_SELECTED))
+               GTK_RBNODE_UNSET_FLAG (start_node, GTK_RBNODE_IS_SELECTED);
+             else
+               GTK_RBNODE_SET_FLAG (start_node, GTK_RBNODE_IS_SELECTED);
+           }
+         else
+           GTK_RBNODE_SET_FLAG (start_node, GTK_RBNODE_IS_SELECTED);
+       }
+      else
+        {
+         /* Mirror the above */
+         if (tree_view->priv->rubber_band_shift)
+           GTK_RBNODE_UNSET_FLAG (start_node, GTK_RBNODE_IS_SELECTED);
+         else if (tree_view->priv->rubber_band_ctrl)
+           {
+             /* Toggle the selection state */
+             if (GTK_RBNODE_FLAG_SET (start_node, GTK_RBNODE_IS_SELECTED))
+               GTK_RBNODE_UNSET_FLAG (start_node, GTK_RBNODE_IS_SELECTED);
+             else
+               GTK_RBNODE_SET_FLAG (start_node, GTK_RBNODE_IS_SELECTED);
+           }
+         else
+           GTK_RBNODE_UNSET_FLAG (start_node, GTK_RBNODE_IS_SELECTED);
+       }
+
+      _gtk_tree_view_queue_draw_node (tree_view, start_tree, start_node, NULL);
+
+      if (start_node == end_node)
+       break;
+
+skip_first:
+
+      if (start_node->children)
+        {
+         start_tree = start_node->children;
+         start_node = start_tree->root;
+         while (start_node->left != start_tree->nil)
+           start_node = start_node->left;
+       }
+      else
+        {
+         _gtk_rbtree_next_full (start_tree, start_node, &start_tree, &start_node);
+
+         if (!start_tree)
+           /* Ran out of tree */
+           break;
+       }
+
+      if (skip_end && start_node == end_node)
+       break;
+    }
+  while (TRUE);
+}
+
+static void
+gtk_tree_view_update_rubber_band_selection (GtkTreeView *tree_view)
+{
+  GtkRBTree *start_tree, *end_tree;
+  GtkRBNode *start_node, *end_node;
+
+  _gtk_rbtree_find_offset (tree_view->priv->tree, MIN (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y), &start_tree, &start_node);
+  _gtk_rbtree_find_offset (tree_view->priv->tree, MAX (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y), &end_tree, &end_node);
+
+  /* Handle the start area first */
+  if (!tree_view->priv->rubber_band_start_node)
+    {
+      gtk_tree_view_update_rubber_band_selection_range (tree_view,
+                                                      start_tree,
+                                                      start_node,
+                                                      end_tree,
+                                                      end_node,
+                                                      TRUE,
+                                                      FALSE,
+                                                      FALSE);
+    }
+  else if (_gtk_rbtree_node_find_offset (start_tree, start_node) <
+           _gtk_rbtree_node_find_offset (tree_view->priv->rubber_band_start_tree, tree_view->priv->rubber_band_start_node))
+    {
+      /* New node is above the old one; selection became bigger */
+      gtk_tree_view_update_rubber_band_selection_range (tree_view,
+                                                      start_tree,
+                                                      start_node,
+                                                      tree_view->priv->rubber_band_start_tree,
+                                                      tree_view->priv->rubber_band_start_node,
+                                                      TRUE,
+                                                      FALSE,
+                                                      TRUE);
+    }
+  else if (_gtk_rbtree_node_find_offset (start_tree, start_node) >
+           _gtk_rbtree_node_find_offset (tree_view->priv->rubber_band_start_tree, tree_view->priv->rubber_band_start_node))
+    {
+      /* New node is below the old one; selection became smaller */
+      gtk_tree_view_update_rubber_band_selection_range (tree_view,
+                                                      tree_view->priv->rubber_band_start_tree,
+                                                      tree_view->priv->rubber_band_start_node,
+                                                      start_tree,
+                                                      start_node,
+                                                      FALSE,
+                                                      FALSE,
+                                                      TRUE);
+    }
+
+  tree_view->priv->rubber_band_start_tree = start_tree;
+  tree_view->priv->rubber_band_start_node = start_node;
+
+  /* Next, handle the end area */
+  if (!tree_view->priv->rubber_band_end_node)
+    {
+      /* In the event this happens, start_node was also NULL; this case is
+       * handled above.
+       */
+    }
+  else if (!end_node)
+    {
+      /* Find the last node in the tree */
+      _gtk_rbtree_find_offset (tree_view->priv->tree, tree_view->priv->height - 1,
+                              &end_tree, &end_node);
+
+      /* Selection reached end of the tree */
+      gtk_tree_view_update_rubber_band_selection_range (tree_view,
+                                                      tree_view->priv->rubber_band_end_tree,
+                                                      tree_view->priv->rubber_band_end_node,
+                                                      end_tree,
+                                                      end_node,
+                                                      TRUE,
+                                                      TRUE,
+                                                      FALSE);
+    }
+  else if (_gtk_rbtree_node_find_offset (end_tree, end_node) >
+           _gtk_rbtree_node_find_offset (tree_view->priv->rubber_band_end_tree, tree_view->priv->rubber_band_end_node))
+    {
+      /* New node is below the old one; selection became bigger */
+      gtk_tree_view_update_rubber_band_selection_range (tree_view,
+                                                      tree_view->priv->rubber_band_end_tree,
+                                                      tree_view->priv->rubber_band_end_node,
+                                                      end_tree,
+                                                      end_node,
+                                                      TRUE,
+                                                      TRUE,
+                                                      FALSE);
+    }
+  else if (_gtk_rbtree_node_find_offset (end_tree, end_node) <
+           _gtk_rbtree_node_find_offset (tree_view->priv->rubber_band_end_tree, tree_view->priv->rubber_band_end_node))
+    {
+      /* New node is above the old one; selection became smaller */
+      gtk_tree_view_update_rubber_band_selection_range (tree_view,
+                                                      end_tree,
+                                                      end_node,
+                                                      tree_view->priv->rubber_band_end_tree,
+                                                      tree_view->priv->rubber_band_end_node,
+                                                      FALSE,
+                                                      TRUE,
+                                                      FALSE);
+    }
+
+  tree_view->priv->rubber_band_end_tree = end_tree;
+  tree_view->priv->rubber_band_end_node = end_node;
+}
+
+static void
+gtk_tree_view_update_rubber_band (GtkTreeView *tree_view)
+{
+  gint x, y;
+  GdkRectangle old_area;
+  GdkRectangle new_area;
+  GdkRectangle common;
+  GdkRegion *invalid_region;
+
+  old_area.x = MIN (tree_view->priv->press_start_x, tree_view->priv->rubber_band_x);
+  old_area.y = MIN (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y) - tree_view->priv->dy;
+  old_area.width = ABS (tree_view->priv->rubber_band_x - tree_view->priv->press_start_x) + 1;
+  old_area.height = ABS (tree_view->priv->rubber_band_y - tree_view->priv->press_start_y) + 1;
+
+  gdk_window_get_pointer (tree_view->priv->bin_window, &x, &y, NULL);
+
+  x = MAX (x, 0);
+  y = MAX (y, 0) + tree_view->priv->dy;
+
+  new_area.x = MIN (tree_view->priv->press_start_x, x);
+  new_area.y = MIN (tree_view->priv->press_start_y, y) - tree_view->priv->dy;
+  new_area.width = ABS (x - tree_view->priv->press_start_x) + 1;
+  new_area.height = ABS (y - tree_view->priv->press_start_y) + 1;
+
+  invalid_region = gdk_region_rectangle (&old_area);
+  gdk_region_union_with_rect (invalid_region, &new_area);
+
+  gdk_rectangle_intersect (&old_area, &new_area, &common);
+  if (common.width > 2 && common.height > 2)
+    {
+      GdkRegion *common_region;
+
+      /* make sure the border is invalidated */
+      common.x += 1;
+      common.y += 1;
+      common.width -= 2;
+      common.height -= 2;
+
+      common_region = gdk_region_rectangle (&common);
+
+      gdk_region_subtract (invalid_region, common_region);
+      gdk_region_destroy (common_region);
+    }
+
+  gdk_window_invalidate_region (tree_view->priv->bin_window, invalid_region, TRUE);
+
+  gdk_region_destroy (invalid_region);
+
+  tree_view->priv->rubber_band_x = x;
+  tree_view->priv->rubber_band_y = y;
+
+  gtk_tree_view_update_rubber_band_selection (tree_view);
+}
+
+static void
+gtk_tree_view_paint_rubber_band (GtkTreeView  *tree_view,
+                               GdkRectangle *area)
+{
+  cairo_t *cr;
+  GdkRectangle rect;
+  GdkRectangle rubber_rect;
+
+  rubber_rect.x = MIN (tree_view->priv->press_start_x, tree_view->priv->rubber_band_x);
+  rubber_rect.y = MIN (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y) - tree_view->priv->dy;
+  rubber_rect.width = ABS (tree_view->priv->press_start_x - tree_view->priv->rubber_band_x) + 1;
+  rubber_rect.height = ABS (tree_view->priv->press_start_y - tree_view->priv->rubber_band_y) + 1;
+
+  if (!gdk_rectangle_intersect (&rubber_rect, area, &rect))
+    return;
+
+  cr = gdk_cairo_create (tree_view->priv->bin_window);
+  cairo_set_line_width (cr, 1.0);
+
+  cairo_set_source_rgba (cr,
+                        GTK_WIDGET (tree_view)->style->fg[GTK_STATE_NORMAL].red / 65535.,
+                        GTK_WIDGET (tree_view)->style->fg[GTK_STATE_NORMAL].green / 65535.,
+                        GTK_WIDGET (tree_view)->style->fg[GTK_STATE_NORMAL].blue / 65535.,
+                        .25);
+
+  gdk_cairo_rectangle (cr, &rect);
+  cairo_clip (cr);
+  cairo_paint (cr);
+
+  cairo_set_source_rgb (cr,
+                       GTK_WIDGET (tree_view)->style->fg[GTK_STATE_NORMAL].red / 65535.,
+                       GTK_WIDGET (tree_view)->style->fg[GTK_STATE_NORMAL].green / 65535.,
+                       GTK_WIDGET (tree_view)->style->fg[GTK_STATE_NORMAL].blue / 65535.);
+
+  cairo_rectangle (cr,
+                  rubber_rect.x + 0.5, rubber_rect.y + 0.5,
+                  rubber_rect.width - 1, rubber_rect.height - 1);
+  cairo_stroke (cr);
+
+  cairo_destroy (cr);
+}
+
 static gboolean
 gtk_tree_view_motion_bin_window (GtkWidget      *widget,
                                 GdkEventMotion *event)
@@ -3314,8 +3891,26 @@ gtk_tree_view_motion_bin_window (GtkWidget      *widget,
   if (tree_view->priv->tree == NULL)
     return FALSE;
 
+  if (tree_view->priv->rubber_band_status == RUBBER_BAND_MAYBE_START)
+    {
+      gtk_grab_add (GTK_WIDGET (tree_view));
+      gtk_tree_view_update_rubber_band (tree_view);
+
+      tree_view->priv->rubber_band_status = RUBBER_BAND_ACTIVE;
+    }
+  else if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
+    {
+      gtk_tree_view_update_rubber_band (tree_view);
+
+      if (tree_view->priv->scroll_timeout == 0)
+        {
+         tree_view->priv->scroll_timeout = g_timeout_add (150, scroll_row_timeout, tree_view);
+       }
+    }
+
   /* only check for an initiated drag when a button is pressed */
-  if (tree_view->priv->pressed_button >= 0)
+  if (tree_view->priv->pressed_button >= 0
+      && !tree_view->priv->rubber_band_status)
     gtk_tree_view_maybe_begin_dragging_row (tree_view, event);
 
   new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
@@ -3400,6 +3995,40 @@ draw_empty_focus (GtkTreeView *tree_view, GdkRectangle *clip_area)
                     1, 1, w, h);
 }
 
+static void
+gtk_tree_view_draw_grid_lines (GtkTreeView    *tree_view,
+                              GdkEventExpose *event,
+                              gint            n_visible_columns)
+{
+  GList *list = tree_view->priv->columns;
+  gint i = 0;
+  gint current_x = 0;
+
+  if (tree_view->priv->grid_lines != GTK_TREE_VIEW_GRID_LINES_VERTICAL
+      && tree_view->priv->grid_lines != GTK_TREE_VIEW_GRID_LINES_BOTH)
+    return;
+
+  /* Only draw the lines for visible rows and columns */
+  for (list = tree_view->priv->columns; list; list = list->next, i++)
+    {
+      GtkTreeViewColumn *column = list->data;
+
+      /* We don't want a line for the list column */
+      if (i == n_visible_columns - 1)
+       break;
+
+      if (! column->visible)
+       continue;
+
+      current_x += column->width;
+
+      gdk_draw_line (event->window,
+                    tree_view->priv->grid_line_gc,
+                    current_x - 1, 0,
+                    current_x - 1, tree_view->priv->height);
+    }
+}
+
 /* Warning: Very scary function.
  * Modify at your own risk
  *
@@ -3421,14 +4050,16 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
   GtkRBTree *drag_highlight_tree = NULL;
   GtkTreeIter iter;
   gint new_y;
-  gint y_offset, x_offset, cell_offset;
+  gint y_offset, cell_offset;
   gint max_height;
   gint depth;
   GdkRectangle background_area;
   GdkRectangle cell_area;
   guint flags;
   gint highlight_x;
+  gint expander_cell_width;
   gint bin_window_width;
+  gint bin_window_height;
   GtkTreePath *cursor_path;
   GtkTreePath *drag_dest_path;
   GList *last_column;
@@ -3441,6 +4072,7 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
   gint n_visible_columns;
   gint pointer_x, pointer_y;
   gboolean got_pointer = FALSE;
+  gboolean row_ending_details;
 
   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
 
@@ -3453,6 +4085,7 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                        "vertical-separator", &vertical_separator,
                        "allow-rules", &allow_rules,
                        "focus-line-width", &focus_line_width,
+                       "row-ending-details", &row_ending_details,
                        NULL);
 
   if (tree_view->priv->tree == NULL)
@@ -3472,6 +4105,21 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
   if (new_y < 0)
     new_y = 0;
   y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
+  gdk_drawable_get_size (tree_view->priv->bin_window,
+                         &bin_window_width, &bin_window_height);
+
+  if (tree_view->priv->height < bin_window_height)
+    {
+      gtk_paint_flat_box (widget->style,
+                          event->window,
+                          widget->state,
+                          GTK_SHADOW_NONE,
+                          &event->area,
+                          widget,
+                          "cell_even",
+                          0, tree_view->priv->height,
+                          bin_window_width, bin_window_height);
+    }
 
   if (node == NULL)
     return TRUE;
@@ -3503,9 +4151,6 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
     _gtk_tree_view_find_node (tree_view, drag_dest_path,
                               &drag_highlight_tree, &drag_highlight);
 
-  gdk_drawable_get_size (tree_view->priv->bin_window,
-                         &bin_window_width, NULL);
-
   
   n_visible_columns = 0;
   for (list = tree_view->priv->columns; list; list = list->next)
@@ -3532,6 +4177,8 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
     {
       gboolean parity;
       gboolean is_separator = FALSE;
+      gboolean is_first = FALSE;
+      gboolean is_last = FALSE;
       
       if (tree_view->priv->row_separator_func)
        {
@@ -3542,9 +4189,9 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
 
       max_height = ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node));
 
-      x_offset = -event->area.x;
       cell_offset = 0;
       highlight_x = 0; /* should match x coord of first cell */
+      expander_cell_width = 0;
 
       background_area.y = y_offset + event->area.y;
       background_area.height = max_height;
@@ -3559,12 +4206,28 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
 
       parity = _gtk_rbtree_node_find_parity (tree, node);
 
-      has_special_cell = gtk_tree_view_has_special_cell (tree_view);
-
+      /* we *need* to set cell data on all cells before the call
+       * to _has_special_cell, else _has_special_cell() does not
+       * return a correct value.
+       */
       for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
           list;
           list = (rtl ? list->prev : list->next))
-       {
+        {
+         GtkTreeViewColumn *column = list->data;
+         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);
+        }
+
+      has_special_cell = gtk_tree_view_has_special_cell (tree_view);
+
+      for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
+          list;
+          list = (rtl ? list->prev : list->next))
+       {
          GtkTreeViewColumn *column = list->data;
          const gchar *detail = NULL;
          GtkStateType state;
@@ -3661,30 +4324,146 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
            state = GTK_STATE_NORMAL;
 
          /* Draw background */
-          gtk_paint_flat_box (widget->style,
-                              event->window,
-                             state,
-                              GTK_SHADOW_NONE,
-                              &event->area,
-                              widget,
-                              detail,
-                              background_area.x,
-                              background_area.y,
-                              background_area.width,
-                              background_area.height);
+         if (row_ending_details)
+           {
+             char new_detail[128];
+
+             is_first = (rtl ? !list->next : !list->prev);
+             is_last = (rtl ? !list->prev : !list->next);
+
+             /* (I don't like the snprintfs either, but couldn't find a
+              * less messy way).
+              */
+             if (is_first && is_last)
+               snprintf (new_detail, 127, "%s", detail);
+             else if (is_first)
+               snprintf (new_detail, 127, "%s_start", detail);
+             else if (is_last)
+               snprintf (new_detail, 127, "%s_end", detail);
+             else
+               snprintf (new_detail, 128, "%s_middle", detail);
+
+             gtk_paint_flat_box (widget->style,
+                                 event->window,
+                                 state,
+                                 GTK_SHADOW_NONE,
+                                 &event->area,
+                                 widget,
+                                 new_detail,
+                                 background_area.x,
+                                 background_area.y,
+                                 background_area.width,
+                                 background_area.height);
+           }
+         else
+           {
+             gtk_paint_flat_box (widget->style,
+                                 event->window,
+                                 state,
+                                 GTK_SHADOW_NONE,
+                                 &event->area,
+                                 widget,
+                                 detail,
+                                 background_area.x,
+                                 background_area.y,
+                                 background_area.width,
+                                 background_area.height);
+           }
+
+         if (tree_view->priv->grid_lines == GTK_TREE_VIEW_GRID_LINES_HORIZONTAL
+             || tree_view->priv->grid_lines == GTK_TREE_VIEW_GRID_LINES_BOTH)
+           {
+             if (background_area.y > 0)
+               gdk_draw_line (event->window,
+                              tree_view->priv->grid_line_gc,
+                              background_area.x, background_area.y,
+                              background_area.x + background_area.width,
+                              background_area.y);
+           }
 
          if (gtk_tree_view_is_expander_column (tree_view, column) &&
-              TREE_VIEW_DRAW_EXPANDERS(tree_view))
+             tree_view->priv->tree_lines_enabled)
+           {
+             if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT
+                 && depth > 1)
+               {
+                 gdk_draw_line (event->window,
+                                tree_view->priv->tree_line_gc,
+                                background_area.x + tree_view->priv->expander_size * (depth - 1.5),
+                                background_area.y + background_area.height / 2,
+                                background_area.x + tree_view->priv->expander_size * (depth - 1.1),
+                                background_area.y + background_area.height / 2);
+               }
+             else if (depth > 1)
+               {
+                 gdk_draw_line (event->window,
+                                tree_view->priv->tree_line_gc,
+                                background_area.x + tree_view->priv->expander_size * (depth - 1.5),
+                                background_area.y + background_area.height / 2,
+                                background_area.x + tree_view->priv->expander_size * (depth - 0.5),
+                                background_area.y + background_area.height / 2);
+               }
+
+             if (depth > 1)
+               {
+                 gint i;
+                 GtkRBNode *tmp_node;
+                 GtkRBTree *tmp_tree;
+
+                 if (!_gtk_rbtree_next (tree, node))
+                   gdk_draw_line (event->window,
+                                  tree_view->priv->tree_line_gc,
+                                  background_area.x + tree_view->priv->expander_size * (depth - 1.5),
+                                  background_area.y,
+                                  background_area.x + tree_view->priv->expander_size * (depth - 1.5),
+                                  background_area.y + background_area.height / 2);
+                 else
+                   gdk_draw_line (event->window,
+                                  tree_view->priv->tree_line_gc,
+                                  background_area.x + tree_view->priv->expander_size * (depth - 1.5),
+                                  background_area.y,
+                                  background_area.x + tree_view->priv->expander_size * (depth - 1.5),
+                                  background_area.y + background_area.height);
+
+                 tmp_node = tree->parent_node;
+                 tmp_tree = tree->parent_tree;
+
+                 for (i = depth - 2; i > 0; i--)
+                   {
+                     if (_gtk_rbtree_next (tmp_tree, tmp_node))
+                       gdk_draw_line (event->window,
+                                      tree_view->priv->tree_line_gc,
+                                      background_area.x + tree_view->priv->expander_size * (i - 0.5),
+                                      background_area.y,
+                                      background_area.x + tree_view->priv->expander_size * (i - 0.5),
+                                      background_area.y + background_area.height);
+
+                     tmp_node = tmp_tree->parent_node;
+                     tmp_tree = tmp_tree->parent_tree;
+                   }
+               }
+           }
+
+         if (gtk_tree_view_is_expander_column (tree_view, column))
            {
              if (!rtl)
-               cell_area.x += depth * tree_view->priv->expander_size;
-             cell_area.width -= depth * tree_view->priv->expander_size;
+               cell_area.x += (depth - 1) * tree_view->priv->level_indentation;
+             cell_area.width -= (depth - 1) * tree_view->priv->level_indentation;
+
+              if (TREE_VIEW_DRAW_EXPANDERS(tree_view))
+               {
+                 if (!rtl)
+                   cell_area.x += depth * tree_view->priv->expander_size;
+                 cell_area.width -= depth * tree_view->priv->expander_size;
+               }
 
               /* If we have an expander column, the highlight underline
                * starts with that column, so that it indicates which
                * level of the tree we're dropping at.
                */
               highlight_x = cell_area.x;
+             expander_cell_width = cell_area.width;
+
              if (is_separator)
                gtk_paint_hline (widget->style,
                                 event->window,
@@ -3702,7 +4481,8 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                                                   &cell_area,
                                                   &event->area,
                                                   flags);
-             if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT)
+             if (TREE_VIEW_DRAW_EXPANDERS(tree_view)
+                 && (node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT)
                {
                  if (!got_pointer)
                    {
@@ -3761,7 +4541,6 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
          GtkRBTree *tree = NULL;
          GtkRBNode *node = NULL;
          gint width;
-         gint focus_line_width;
 
           switch (tree_view->priv->drag_dest_pos)
             {
@@ -3783,27 +4562,41 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                break;
              gdk_drawable_get_size (tree_view->priv->bin_window,
                                     &width, NULL);
-             gtk_widget_style_get (widget, "focus-line-width", &focus_line_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)
-                              - focus_line_width / 2,
-                              width, ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node))
+
+             if (row_ending_details)
+               gtk_paint_focus (widget->style,
+                                tree_view->priv->bin_window,
+                                GTK_WIDGET_STATE (widget),
+                                NULL,
+                                widget,
+                                (is_first
+                                 ? (is_last ? "treeview-drop-indicator" : "treeview-drop-indicator-left" )
+                                 : (is_last ? "treeview-drop-indicator-right" : "tree-view-drop-indicator-middle" )),
+                                0, BACKGROUND_FIRST_PIXEL (tree_view, tree, node)
+                                - focus_line_width / 2,
+                                width, ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node))
                               - focus_line_width + 1);
+             else
+               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)
+                                - focus_line_width / 2,
+                                width, ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node))
+                                - focus_line_width + 1);
               break;
             }
 
           if (highlight_y >= 0)
             {
               gdk_draw_line (event->window,
-                             widget->style->black_gc,
-                             highlight_x,
+                             widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+                             rtl ? highlight_x + expander_cell_width : highlight_x,
                              highlight_y,
-                             bin_window_width - highlight_x,
+                             rtl ? 0 : bin_window_width,
                              highlight_y);
             }
         }
@@ -3824,16 +4617,31 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
 
          gdk_drawable_get_size (tree_view->priv->bin_window,
                                 &width, NULL);
-         gtk_paint_focus (widget->style,
-                          tree_view->priv->bin_window,
-                          focus_rect_state,
-                          NULL,
-                          widget,
-                          "treeview",
-                          0,
-                          BACKGROUND_FIRST_PIXEL (tree_view, tree, node),
-                          width,
-                          ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node)));
+         
+         if (row_ending_details)
+           gtk_paint_focus (widget->style,
+                            tree_view->priv->bin_window,
+                            focus_rect_state,
+                            NULL,
+                            widget,
+                            (is_first
+                             ? (is_last ? "treeview" : "treeview-left" )
+                             : (is_last ? "treeview-right" : "treeview-middle" )),
+                            0,
+                            BACKGROUND_FIRST_PIXEL (tree_view, tree, node),
+                            width,
+                            ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node)));
+         else
+           gtk_paint_focus (widget->style,
+                            tree_view->priv->bin_window,
+                            focus_rect_state,
+                            NULL,
+                            widget,
+                            "treeview",
+                            0,
+                            BACKGROUND_FIRST_PIXEL (tree_view, tree, node),
+                            width,
+                            ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node)));
        }
 
       y_offset += max_height;
@@ -3860,6 +4668,7 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
       else
        {
          gboolean done = FALSE;
+
          do
            {
              node = _gtk_rbtree_next (tree, node);
@@ -3895,7 +4704,24 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
     }
   while (y_offset < event->area.height);
 
- done:
+done:
+  gtk_tree_view_draw_grid_lines (tree_view, event, n_visible_columns);
+
+ if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
+   {
+     GdkRectangle *rectangles;
+     gint n_rectangles;
+
+     gdk_region_get_rectangles (event->region,
+                               &rectangles,
+                               &n_rectangles);
+
+     while (n_rectangles--)
+       gtk_tree_view_paint_rubber_band (tree_view, &rectangles[n_rectangles]);
+
+     g_free (rectangles);
+   }
+
   if (cursor_path)
     gtk_tree_path_free (cursor_path);
 
@@ -4194,9 +5020,10 @@ gtk_tree_view_key_press (GtkWidget   *widget,
       return TRUE;
     }
 
-  if (tree_view->priv->columns && (event->state & GDK_SHIFT_MASK)
-      && (event->keyval == GDK_Left || event->keyval == GDK_KP_Left
-          || event->keyval == GDK_Right || event->keyval == GDK_KP_Right))
+  if (tree_view->priv->columns && 
+      (event->state & GDK_SHIFT_MASK) && (event->state & GDK_MOD1_MASK) &&
+      (event->keyval == GDK_Left || event->keyval == GDK_KP_Left
+       || event->keyval == GDK_Right || event->keyval == GDK_KP_Right))
     {
       list = tree_view->priv->columns;
       while (list)
@@ -4246,7 +5073,7 @@ gtk_tree_view_key_press (GtkWidget   *widget,
        }
     }
 
-  if (tree_view->priv->columns && (event->state & GDK_CONTROL_MASK) &&
+  if (tree_view->priv->columns && (event->state & GDK_MOD1_MASK) &&
       (event->keyval == GDK_Left || event->keyval == GDK_KP_Left
        || event->keyval == GDK_Right || event->keyval == GDK_KP_Right
        || event->keyval == GDK_Home || event->keyval == GDK_KP_Home
@@ -4356,12 +5183,13 @@ gtk_tree_view_key_press (GtkWidget   *widget,
     }
 
   /* Chain up to the parent class.  It handles the keybindings. */
-  if ((* GTK_WIDGET_CLASS (parent_class)->key_press_event) (widget, event))
+  if ((* GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->key_press_event) (widget, event))
     return TRUE;
                                                            
   /* We pass the event to the search_entry.  If its text changes, then we start
    * the typeahead find capabilities. */
-  if (tree_view->priv->enable_search)
+  if (tree_view->priv->enable_search
+      && !tree_view->priv->search_custom_entry_set)
     {
       GdkEvent *new_event;
       char *old_text;
@@ -4376,7 +5204,8 @@ gtk_tree_view_key_press (GtkWidget   *widget,
       /* Make a copy of the current text */
       old_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (tree_view->priv->search_entry)));
       new_event = gdk_event_copy ((GdkEvent *) event);
-      ((GdkEventKey *) new_event)->window = tree_view->priv->search_entry->window;
+      g_object_unref (((GdkEventKey *) new_event)->window);
+      ((GdkEventKey *) new_event)->window = g_object_ref (tree_view->priv->search_window->window);
       gtk_widget_realize (tree_view->priv->search_window);
 
       popup_menu_id = g_signal_connect (tree_view->priv->search_entry, 
@@ -4392,7 +5221,8 @@ gtk_tree_view_key_press (GtkWidget   *widget,
       /* Send the event to the window.  If the preedit_changed signal is emitted
        * during this event, we will set priv->imcontext_changed  */
       tree_view->priv->imcontext_changed = FALSE;
-      retval = gtk_widget_event (tree_view->priv->search_entry, new_event);
+      retval = gtk_widget_event (tree_view->priv->search_window, new_event);
+      gdk_event_free (new_event);
       gtk_widget_hide (tree_view->priv->search_window);
 
       g_signal_handler_disconnect (tree_view->priv->search_entry, 
@@ -4427,7 +5257,7 @@ static gboolean
 gtk_tree_view_key_release (GtkWidget   *widget,
                           GdkEventKey *event)
 {
-  return (* GTK_WIDGET_CLASS (parent_class)->key_release_event) (widget, event);
+  return (* GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->key_release_event) (widget, event);
 }
 
 /* FIXME Is this function necessary? Can I get an enter_notify event
@@ -4472,12 +5302,11 @@ gtk_tree_view_leave_notify (GtkWidget        *widget,
 {
   GtkTreeView *tree_view;
 
-  tree_view = GTK_TREE_VIEW (widget);
-  tree_view->priv->pressed_button = -1;
-
   if (event->mode == GDK_CROSSING_GRAB)
     return TRUE;
 
+  tree_view = GTK_TREE_VIEW (widget);
+
   if (tree_view->priv->prelight_node)
     _gtk_tree_view_queue_draw_node (tree_view,
                                    tree_view->priv->prelight_tree,
@@ -4530,6 +5359,25 @@ gtk_tree_view_node_queue_redraw (GtkTreeView *tree_view,
                              GTK_RBNODE_GET_HEIGHT (node));
 }
 
+static gboolean
+node_is_visible (GtkTreeView *tree_view,
+                GtkRBTree   *tree,
+                GtkRBNode   *node)
+{
+  int y;
+  int height;
+
+  y = _gtk_rbtree_node_find_offset (tree, node);
+  height = ROW_HEIGHT (tree_view, GTK_RBNODE_GET_HEIGHT (node));
+
+  if (y >= tree_view->priv->vadjustment->value &&
+      y + height <= (tree_view->priv->vadjustment->value
+                    + tree_view->priv->vadjustment->page_size))
+    return TRUE;
+
+  return FALSE;
+}
+
 /* Returns TRUE if it updated the size
  */
 static gboolean
@@ -4543,11 +5391,13 @@ validate_row (GtkTreeView *tree_view,
   GList *list;
   gint height = 0;
   gint horizontal_separator;
+  gint vertical_separator;
+  gint focus_line_width;
   gint depth = gtk_tree_path_get_depth (path);
   gboolean retval = FALSE;
   gboolean is_separator = FALSE;
   gint focus_pad;
-      
+
   /* double check the row needs validating */
   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) &&
       ! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
@@ -4562,7 +5412,9 @@ validate_row (GtkTreeView *tree_view,
 
   gtk_widget_style_get (GTK_WIDGET (tree_view),
                        "focus-padding", &focus_pad,
+                       "focus-line-width", &focus_line_width,
                        "horizontal-separator", &horizontal_separator,
+                       "vertical-separator", &vertical_separator,
                        NULL);
   
   for (list = tree_view->priv->columns; list; list = list->next)
@@ -4587,15 +5439,19 @@ validate_row (GtkTreeView *tree_view,
 
       if (!is_separator)
        {
+          tmp_height += vertical_separator;
          height = MAX (height, tmp_height);
          height = MAX (height, tree_view->priv->expander_size);
        }
       else
        height = 2 + 2 * focus_pad;
 
-      if (gtk_tree_view_is_expander_column (tree_view, column) && TREE_VIEW_DRAW_EXPANDERS (tree_view))
+      if (gtk_tree_view_is_expander_column (tree_view, column))
         {
-         tmp_width = tmp_width + horizontal_separator + depth * (tree_view->priv->expander_size);
+         tmp_width = tmp_width + horizontal_separator + (depth - 1) * tree_view->priv->level_indentation;
+
+         if (TREE_VIEW_DRAW_EXPANDERS (tree_view))
+           tmp_width += depth * tree_view->priv->expander_size;
        }
       else
        tmp_width = tmp_width + horizontal_separator;
@@ -4659,7 +5515,7 @@ validate_visible_area (GtkTreeView *tree_view)
          if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
              GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
            {
-             need_redraw = TRUE;
+             _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
              if (validate_row (tree_view, tree, node, &iter, path))
                size_changed = TRUE;
            }
@@ -4685,8 +5541,8 @@ validate_visible_area (GtkTreeView *tree_view)
              dy = _gtk_rbtree_node_find_offset (tree, node);
 
              if (dy >= tree_view->priv->vadjustment->value &&
-                 dy < (tree_view->priv->vadjustment->value
-                       + tree_view->priv->vadjustment->page_size))
+                 dy + height <= (tree_view->priv->vadjustment->value
+                                 + tree_view->priv->vadjustment->page_size))
                {
                  /* row visible: keep the row at the same position */
                  area_above = dy - tree_view->priv->vadjustment->value;
@@ -4774,7 +5630,7 @@ validate_visible_area (GtkTreeView *tree_view)
       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
          GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
        {
-         need_redraw = TRUE;
+         _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
          if (validate_row (tree_view, tree, node, &iter, path))
            size_changed = TRUE;
        }
@@ -4812,7 +5668,7 @@ validate_visible_area (GtkTreeView *tree_view)
       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
           GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
         {
-          need_redraw = TRUE;
+         _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
           if (validate_row (tree_view, tree, node, &iter, path))
             size_changed = TRUE;
         }
@@ -4893,7 +5749,7 @@ validate_visible_area (GtkTreeView *tree_view)
        {
           gint old_height = new_height;
 
-         need_redraw = TRUE;
+         _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
          if (validate_row (tree_view, tree, node, &iter, path))
             {
               new_height = GTK_RBNODE_GET_HEIGHT (node);
@@ -4937,7 +5793,7 @@ validate_visible_area (GtkTreeView *tree_view)
        {
           gint old_height = new_height;
 
-         need_redraw = TRUE;
+         _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
          if (validate_row (tree_view, tree, node, &iter, above_path))
             {
               new_height = GTK_RBNODE_GET_HEIGHT (node);
@@ -4975,6 +5831,11 @@ validate_visible_area (GtkTreeView *tree_view)
       gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment), 0);
       gtk_tree_view_dy_to_top_row (tree_view);
     }
+  else if (tree_view->priv->vadjustment->value + tree_view->priv->vadjustment->page_size > tree_view->priv->height)
+    {
+      gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment), tree_view->priv->height - tree_view->priv->vadjustment->page_size);
+      gtk_tree_view_dy_to_top_row (tree_view);
+    }
   else
     gtk_tree_view_top_row_to_dy (tree_view);
 
@@ -5040,7 +5901,7 @@ initialize_fixed_height_mode (GtkTreeView *tree_view)
     }
 
    _gtk_rbtree_set_fixed_height (tree_view->priv->tree,
-                                 tree_view->priv->fixed_height);
+                                 tree_view->priv->fixed_height, TRUE);
 }
 
 /* Our strategy for finding nodes to validate is a little convoluted.  We find
@@ -5158,7 +6019,7 @@ do_validate_rows (GtkTreeView *tree_view, gboolean queue_resize)
   if (!tree_view->priv->fixed_height_check)
    {
      if (fixed_height)
-       _gtk_rbtree_set_fixed_height (tree_view->priv->tree, prev_height);
+       _gtk_rbtree_set_fixed_height (tree_view->priv->tree, prev_height, FALSE);
 
      tree_view->priv->fixed_height_check = 1;
    }
@@ -5178,7 +6039,7 @@ do_validate_rows (GtkTreeView *tree_view, gboolean queue_resize)
       gtk_adjustment_changed (tree_view->priv->vadjustment);
 
       if (queue_resize)
-        gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+        gtk_widget_queue_resize_no_redraw (GTK_WIDGET (tree_view));
     }
 
   if (path) gtk_tree_path_free (path);
@@ -5236,7 +6097,6 @@ do_presize_handler (GtkTreeView *tree_view)
   if (tree_view->priv->fixed_height_mode)
     {
       GtkRequisition requisition;
-      gint height_old = tree_view->priv->height;
 
       gtk_widget_size_request (GTK_WIDGET (tree_view), &requisition);
 
@@ -5383,6 +6243,10 @@ gtk_tree_view_top_row_to_dy (GtkTreeView *tree_view)
 
   tree_view->priv->dy = _gtk_rbtree_node_find_offset (tree, node);
   tree_view->priv->dy += tree_view->priv->top_row_dy;
+
+  if (tree_view->priv->dy + tree_view->priv->vadjustment->page_size > tree_view->priv->height)
+    tree_view->priv->dy = tree_view->priv->height - tree_view->priv->vadjustment->page_size;
+
   gtk_adjustment_set_value (tree_view->priv->vadjustment,
                            (gdouble)tree_view->priv->dy);
 }
@@ -5426,7 +6290,7 @@ set_source_row (GdkDragContext *context,
                 GtkTreePath    *source_row)
 {
   g_object_set_data_full (G_OBJECT (context),
-                          "gtk-tree-view-source-row",
+                          I_("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));
 }
@@ -5474,7 +6338,7 @@ set_dest_row (GdkDragContext *context,
 
   if (!dest_row)
     {
-      g_object_set_data_full (G_OBJECT (context), "gtk-tree-view-dest-row",
+      g_object_set_data_full (G_OBJECT (context), I_("gtk-tree-view-dest-row"),
                               NULL, NULL);
       return;
     }
@@ -5486,7 +6350,7 @@ set_dest_row (GdkDragContext *context,
   dr->empty_view_drop = empty_view_drop;
   dr->drop_append_mode = drop_append_mode;
 
-  g_object_set_data_full (G_OBJECT (context), "gtk-tree-view-dest-row",
+  g_object_set_data_full (G_OBJECT (context), I_("gtk-tree-view-dest-row"),
                           dr, (GDestroyNotify) dest_row_free);
 }
 
@@ -5529,7 +6393,7 @@ set_status_pending (GdkDragContext *context,
                     GdkDragAction   suggested_action)
 {
   g_object_set_data (G_OBJECT (context),
-                     "gtk-tree-view-status-pending",
+                     I_("gtk-tree-view-status-pending"),
                      GINT_TO_POINTER (suggested_action));
 }
 
@@ -5584,7 +6448,7 @@ ensure_info (GtkTreeView *tree_view)
       di = g_new0 (TreeViewDragInfo, 1);
 
       g_object_set_data_full (G_OBJECT (tree_view),
-                              "gtk-tree-view-drag-info",
+                              I_("gtk-tree-view-drag-info"),
                               di,
                               (GDestroyNotify) destroy_info);
     }
@@ -5595,7 +6459,7 @@ ensure_info (GtkTreeView *tree_view)
 static void
 remove_info (GtkTreeView *tree_view)
 {
-  g_object_set_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info", NULL);
+  g_object_set_data (G_OBJECT (tree_view), I_("gtk-tree-view-drag-info"), NULL);
 }
 
 #if 0
@@ -5659,6 +6523,7 @@ remove_scroll_timeout (GtkTreeView *tree_view)
       tree_view->priv->scroll_timeout = 0;
     }
 }
+
 static gboolean
 check_model_dnd (GtkTreeModel *model,
                  GType         required_iface,
@@ -5739,6 +6604,9 @@ scroll_row_timeout (gpointer data)
 
   gtk_tree_view_vertical_autoscroll (tree_view);
 
+  if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
+    gtk_tree_view_update_rubber_band (tree_view);
+
   GDK_THREADS_LEAVE ();
 
   return TRUE;
@@ -6010,11 +6878,14 @@ gtk_tree_view_drag_begin (GtkWidget      *widget,
   GtkTreePath *path = NULL;
   gint cell_x, cell_y;
   GdkPixmap *row_pix;
+  TreeViewDragInfo *di;
 
   tree_view = GTK_TREE_VIEW (widget);
 
-  /* if the user uses a custom DnD impl, we don't set the icon here */
-  if (!get_info (tree_view))
+  /* if the user uses a custom DND source impl, we don't set the icon here */
+  di = get_info (tree_view);
+
+  if (di == NULL || !di->source_set)
     return;
 
   gtk_tree_view_get_path_at_pos (tree_view,
@@ -6091,7 +6962,7 @@ gtk_tree_view_drag_data_get (GtkWidget        *widget,
     goto done;
 
   /* If drag_data_get does nothing, try providing row data. */
-  if (selection_data->target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
+  if (selection_data->target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
     {
       gtk_tree_set_row_drag_data (selection_data,
                                  model,
@@ -6141,10 +7012,6 @@ gtk_tree_view_drag_leave (GtkWidget      *widget,
                           GdkDragContext *context,
                           guint             time)
 {
-  TreeViewDragInfo *di;
-
-  di = get_info (GTK_TREE_VIEW (widget));
-
   /* unset any highlight row */
   gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
                                    NULL,
@@ -6164,7 +7031,6 @@ gtk_tree_view_drag_motion (GtkWidget        *widget,
 {
   gboolean empty;
   GtkTreePath *path = NULL;
-  GtkTreeModel *model;
   GtkTreeViewDropPosition pos;
   GtkTreeView *tree_view;
   GdkDragAction suggested_action = 0;
@@ -6178,7 +7044,6 @@ gtk_tree_view_drag_motion (GtkWidget        *widget,
   gtk_tree_view_get_drag_dest_row (tree_view, &path, &pos);
 
   /* we only know this *after* set_desination_row */
-  model = gtk_tree_view_get_model (tree_view);
   empty = tree_view->priv->empty_view_drop;
 
   if (path == NULL && !empty)
@@ -6201,7 +7066,7 @@ gtk_tree_view_drag_motion (GtkWidget        *widget,
            g_timeout_add (150, scroll_row_timeout, tree_view);
        }
 
-      if (target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
+      if (target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
         {
           /* Request data so we can use the source row when
            * determining whether to accept the drop
@@ -6611,7 +7476,6 @@ gtk_tree_view_header_focus (GtkTreeView      *tree_view,
                            GtkDirectionType  dir)
 {
   GtkWidget *focus_child;
-  GtkContainer *container;
 
   GList *last_column, *first_column;
   GList *tmp_list;
@@ -6621,7 +7485,6 @@ gtk_tree_view_header_focus (GtkTreeView      *tree_view,
     return FALSE;
 
   focus_child = GTK_CONTAINER (tree_view)->focus_child;
-  container = GTK_CONTAINER (tree_view);
 
   first_column = tree_view->priv->columns;
   while (first_column)
@@ -6750,9 +7613,10 @@ gtk_tree_view_header_focus (GtkTreeView      *tree_view,
     {
       for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
        if (GTK_TREE_VIEW_COLUMN (tmp_list->data)->button == focus_child)
-         break;
-
-      tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
+         {
+           tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
+           break;
+         }
 
       /* If the following isn't true, then the view is smaller then the scrollpane.
        */
@@ -6838,7 +7702,7 @@ gtk_tree_view_focus (GtkWidget        *widget,
 static void
 gtk_tree_view_grab_focus (GtkWidget *widget)
 {
-  (* GTK_WIDGET_CLASS (parent_class)->grab_focus) (widget);
+  (* GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->grab_focus) (widget);
 
   gtk_tree_view_focus_to_cursor (GTK_TREE_VIEW (widget));
 }
@@ -6857,8 +7721,11 @@ gtk_tree_view_style_set (GtkWidget *widget,
 
   if (GTK_WIDGET_REALIZED (widget))
     {
-      gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
+      gdk_window_set_back_pixmap (widget->window, NULL, FALSE);
       gdk_window_set_background (tree_view->priv->bin_window, &widget->style->base[widget->state]);
+
+      gtk_tree_view_set_grid_lines (tree_view, tree_view->priv->grid_lines);
+      gtk_tree_view_set_enable_tree_lines (tree_view, tree_view->priv->tree_lines_enabled);
     }
 
   gtk_widget_style_get (widget,
@@ -6895,7 +7762,7 @@ gtk_tree_view_set_focus_child (GtkContainer *container,
        }
     }
 
-  (* parent_class->set_focus_child) (container, child);
+  GTK_CONTAINER_CLASS (gtk_tree_view_parent_class)->set_focus_child (container, child);
 }
 
 static void
@@ -6935,8 +7802,7 @@ gtk_tree_view_set_adjustments (GtkTreeView   *tree_view,
   if (tree_view->priv->hadjustment != hadj)
     {
       tree_view->priv->hadjustment = hadj;
-      g_object_ref (tree_view->priv->hadjustment);
-      gtk_object_sink (GTK_OBJECT (tree_view->priv->hadjustment));
+      g_object_ref_sink (tree_view->priv->hadjustment);
 
       g_signal_connect (tree_view->priv->hadjustment, "value_changed",
                        G_CALLBACK (gtk_tree_view_adjustment_changed),
@@ -6947,8 +7813,7 @@ gtk_tree_view_set_adjustments (GtkTreeView   *tree_view,
   if (tree_view->priv->vadjustment != vadj)
     {
       tree_view->priv->vadjustment = vadj;
-      g_object_ref (tree_view->priv->vadjustment);
-      gtk_object_sink (GTK_OBJECT (tree_view->priv->vadjustment));
+      g_object_ref_sink (tree_view->priv->vadjustment);
 
       g_signal_connect (tree_view->priv->vadjustment, "value_changed",
                        G_CALLBACK (gtk_tree_view_adjustment_changed),
@@ -7185,6 +8050,7 @@ gtk_tree_view_row_inserted (GtkTreeModel *model,
   gint i = 0;
   gint height;
   gboolean free_path = FALSE;
+  gboolean node_visible = TRUE;
 
   g_return_if_fail (path != NULL || iter != NULL);
 
@@ -7218,6 +8084,7 @@ gtk_tree_view_row_inserted (GtkTreeModel *model,
       if (tmptree == NULL)
        {
          /* We aren't showing the node */
+         node_visible = FALSE;
           goto done;
        }
 
@@ -7249,24 +8116,35 @@ gtk_tree_view_row_inserted (GtkTreeModel *model,
     }
 
   if (tree == NULL)
-    goto done;
+    {
+      node_visible = FALSE;
+      goto done;
+    }
 
   /* ref the node */
   gtk_tree_model_ref_node (tree_view->priv->model, iter);
   if (indices[depth - 1] == 0)
     {
       tmpnode = _gtk_rbtree_find_count (tree, 1);
-      _gtk_rbtree_insert_before (tree, tmpnode, height, FALSE);
+      tmpnode = _gtk_rbtree_insert_before (tree, tmpnode, height, FALSE);
     }
   else
     {
       tmpnode = _gtk_rbtree_find_count (tree, indices[depth - 1]);
-      _gtk_rbtree_insert_after (tree, tmpnode, height, FALSE);
-    } 
+      tmpnode = _gtk_rbtree_insert_after (tree, tmpnode, height, FALSE);
+    }
 
  done:
   if (height > 0)
-    gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+    {
+      if (tree)
+        _gtk_rbtree_node_mark_valid (tree, tmpnode);
+
+      if (node_visible && node_is_visible (tree_view, tree, tmpnode))
+       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+      else
+       gtk_widget_queue_resize_no_redraw (GTK_WIDGET (tree_view));
+    }
   else
     install_presize_handler (tree_view);
   if (free_path)
@@ -7619,23 +8497,14 @@ gtk_tree_view_get_arrow_xrange (GtkTreeView *tree_view,
       else
        x_offset += tree_view->priv->expander_size * _gtk_rbtree_get_depth (tree);
     }
-  if (x1)
-    {
-      *x1 = x_offset;
-    }
 
+  *x1 = x_offset;
+  
   if (tmp_column && tmp_column->visible)
-    {
-      /* +1 because x2 isn't included in the range. */
-      if (x2)
-        *x2 = *x1 + tree_view->priv->expander_size + 1;
-    }
+    /* +1 because x2 isn't included in the range. */
+    *x2 = *x1 + tree_view->priv->expander_size + 1;
   else
-    {
-      /* return an empty range, the expander column is hidden */
-      if (x2)
-        *x2 = *x1;
-    }
+    *x2 = *x1;
 }
 
 static void
@@ -7646,6 +8515,7 @@ gtk_tree_view_build_tree (GtkTreeView *tree_view,
                          gboolean     recurse)
 {
   GtkRBNode *temp = NULL;
+  GtkTreePath *path = NULL;
   gboolean is_list = GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IS_LIST);
 
   do
@@ -7656,7 +8526,10 @@ gtk_tree_view_build_tree (GtkTreeView *tree_view,
       if (tree_view->priv->fixed_height > 0)
         {
           if (GTK_RBNODE_FLAG_SET (temp, GTK_RBNODE_INVALID))
-            _gtk_rbtree_node_set_height (tree, temp, tree_view->priv->fixed_height);
+           {
+              _gtk_rbtree_node_set_height (tree, temp, tree_view->priv->fixed_height);
+             _gtk_rbtree_node_mark_valid (tree, temp);
+           }
         }
 
       if (is_list)
@@ -7666,14 +8539,27 @@ gtk_tree_view_build_tree (GtkTreeView *tree_view,
        {
          GtkTreeIter child;
 
+         if (!path)
+           path = gtk_tree_model_get_path (tree_view->priv->model, iter);
+         else
+           gtk_tree_path_next (path);
+
          if (gtk_tree_model_iter_children (tree_view->priv->model, &child, iter))
            {
-             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);
+             gboolean expand;
+
+             g_signal_emit (tree_view, tree_view_signals[TEST_EXPAND_ROW], 0, &iter, path, &expand);
+
+             if (!expand)
+               {
+                 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);
+               }
            }
        }
+
       if (gtk_tree_model_iter_has_child (tree_view->priv->model, iter))
        {
          if ((temp->flags&GTK_RBNODE_IS_PARENT) != GTK_RBNODE_IS_PARENT)
@@ -7681,6 +8567,9 @@ gtk_tree_view_build_tree (GtkTreeView *tree_view,
        }
     }
   while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
+
+  if (path)
+    gtk_tree_path_free (path);
 }
 
 /* If height is non-NULL, then we set it to be the new height.  if it's all
@@ -7735,10 +8624,15 @@ gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view,
                                              &width, NULL);
        }
 
-      if (gtk_tree_view_is_expander_column (tree_view, column) &&
-          TREE_VIEW_DRAW_EXPANDERS (tree_view))
+      if (gtk_tree_view_is_expander_column (tree_view, column))
        {
-         if (depth * tree_view->priv->expander_size + horizontal_separator + width > column->requested_width)
+         int tmp = 0;
+
+         tmp = horizontal_separator + width + (depth - 1) * tree_view->priv->level_indentation;
+         if (TREE_VIEW_DRAW_EXPANDERS (tree_view))
+           tmp += depth * tree_view->priv->expander_size;
+
+         if (tmp > column->requested_width)
            {
              _gtk_tree_view_column_cell_set_dirty (column, TRUE);
              retval = TRUE;
@@ -7811,13 +8705,22 @@ gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view,
                                  GtkRBTree   *tree,
                                  GtkRBNode   *node)
 {
+  gint node_dy, height;
   GtkTreePath *path = NULL;
 
   if (!GTK_WIDGET_REALIZED (tree_view))
     return;
 
-  path = _gtk_tree_view_find_path (tree_view, tree, node);
+  /* just return if the node is visible, avoiding a costly expose */
+  node_dy = _gtk_rbtree_node_find_offset (tree, node);
+  height = ROW_HEIGHT (tree_view, GTK_RBNODE_GET_HEIGHT (node));
+  if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID)
+      && node_dy >= tree_view->priv->vadjustment->value
+      && node_dy + height <= (tree_view->priv->vadjustment->value
+                              + tree_view->priv->vadjustment->page_size))
+    return;
 
+  path = _gtk_tree_view_find_path (tree_view, tree, node);
   if (path)
     {
       /* We process updates because we want to clear old selected items when we scroll.
@@ -7965,6 +8868,7 @@ static void
 gtk_tree_view_add_move_binding (GtkBindingSet  *binding_set,
                                guint           keyval,
                                guint           modmask,
+                               gboolean        add_shifted_binding,
                                GtkMovementStep step,
                                gint            count)
 {
@@ -7974,10 +8878,11 @@ gtk_tree_view_add_move_binding (GtkBindingSet  *binding_set,
                                 G_TYPE_ENUM, step,
                                 G_TYPE_INT, count);
 
-  gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
-                                "move_cursor", 2,
-                                G_TYPE_ENUM, step,
-                                G_TYPE_INT, count);
+  if (add_shifted_binding)
+    gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
+                                 "move_cursor", 2,
+                                 G_TYPE_ENUM, step,
+                                 G_TYPE_INT, count);
 
   if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
    return;
@@ -8123,9 +9028,10 @@ gtk_tree_view_set_column_drag_info (GtkTreeView       *tree_view,
 
   /* We know there are always 2 slots possbile, as you can always return column. */
   /* If that's all there is, return */
-  if (tree_view->priv->column_drag_info->next->next == NULL &&
-      ((GtkTreeViewColumnReorder *)tree_view->priv->column_drag_info->data)->right_column == column &&
-      ((GtkTreeViewColumnReorder *)tree_view->priv->column_drag_info->next->data)->left_column == column)
+  if (tree_view->priv->column_drag_info->next == NULL || 
+      (tree_view->priv->column_drag_info->next->next == NULL &&
+       ((GtkTreeViewColumnReorder *)tree_view->priv->column_drag_info->data)->right_column == column &&
+       ((GtkTreeViewColumnReorder *)tree_view->priv->column_drag_info->next->data)->left_column == column))
     {
       for (tmp_list = tree_view->priv->column_drag_info; tmp_list; tmp_list = tmp_list->next)
        g_free (tmp_list->data);
@@ -8276,7 +9182,7 @@ gtk_tree_view_queue_draw_arrow (GtkTreeView      *tree_view,
     return;
 
   rect.x = 0;
-  rect.width = MAX (tree_view->priv->expander_size, GTK_WIDGET (tree_view)->allocation.width);
+  rect.width = MAX (tree_view->priv->expander_size, MAX (tree_view->priv->width, GTK_WIDGET (tree_view)->allocation.width));
 
   rect.y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
   rect.height = ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node));
@@ -8353,6 +9259,7 @@ gtk_tree_view_draw_arrow (GtkTreeView *tree_view,
   GtkStateType state;
   GtkWidget *widget;
   gint x_offset = 0;
+  gint x2;
   gint vertical_separator;
   gint expander_size;
   GtkExpanderStyle expander_style;
@@ -8367,7 +9274,7 @@ gtk_tree_view_draw_arrow (GtkTreeView *tree_view,
 
   widget = GTK_WIDGET (tree_view);
 
-  gtk_tree_view_get_arrow_xrange (tree_view, tree, &x_offset, NULL);
+  gtk_tree_view_get_arrow_xrange (tree_view, tree, &x_offset, &x2);
 
   area.x = x_offset;
   area.y = CELL_FIRST_PIXEL (tree_view, tree, node, vertical_separator);
@@ -8478,6 +9385,7 @@ static void
 gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
                                   gint         count)
 {
+  gint selection_count;
   GtkRBTree *cursor_tree = NULL;
   GtkRBNode *cursor_node = NULL;
   GtkRBTree *new_cursor_tree = NULL;
@@ -8500,12 +9408,23 @@ gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
   if (cursor_tree == NULL)
     /* FIXME: we lost the cursor; should we get the first? */
     return;
-  if (count == -1)
-    _gtk_rbtree_prev_full (cursor_tree, cursor_node,
-                          &new_cursor_tree, &new_cursor_node);
+
+  selection_count = gtk_tree_selection_count_selected_rows (tree_view->priv->selection);
+
+  if (selection_count == 0 && !tree_view->priv->ctrl_pressed)
+    {
+      new_cursor_tree = cursor_tree;
+      new_cursor_node = cursor_node;
+    }
   else
-    _gtk_rbtree_next_full (cursor_tree, cursor_node,
-                          &new_cursor_tree, &new_cursor_node);
+    {
+      if (count == -1)
+       _gtk_rbtree_prev_full (cursor_tree, cursor_node,
+                              &new_cursor_tree, &new_cursor_node);
+      else
+       _gtk_rbtree_next_full (cursor_tree, cursor_node,
+                              &new_cursor_tree, &new_cursor_node);
+    }
 
   /*
    * If the list has only one item and multi-selection is set then select
@@ -8554,6 +9473,7 @@ gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
   GtkRBNode *cursor_node = NULL;
   GtkTreePath *cursor_path = NULL;
   gint y;
+  gint window_y;
   gint vertical_separator;
 
   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
@@ -8577,22 +9497,21 @@ gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
   g_return_if_fail (cursor_node != NULL);
 
   y = _gtk_rbtree_node_find_offset (cursor_tree, cursor_node);
-  y += count * tree_view->priv->vadjustment->page_size;
-  if (count > 0)
-    y -= ROW_HEIGHT (tree_view, GTK_RBNODE_GET_HEIGHT (cursor_node));
-  else if (count < 0)
-    y += ROW_HEIGHT (tree_view, GTK_RBNODE_GET_HEIGHT (cursor_node));
+  window_y = RBTREE_Y_TO_TREE_WINDOW_Y (tree_view, y);
+  y += count * (int)tree_view->priv->vadjustment->page_increment;
   y = CLAMP (y, (gint)tree_view->priv->vadjustment->lower,  (gint)tree_view->priv->vadjustment->upper - vertical_separator);
 
   if (y >= tree_view->priv->height)
     y = tree_view->priv->height - 1;
 
-  _gtk_rbtree_find_offset (tree_view->priv->tree, y, &cursor_tree, &cursor_node);
+  y -= _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, TRUE);
-  gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
+  gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE);
   gtk_tree_path_free (cursor_path);
+
+  y -= window_y;
+  gtk_tree_view_scroll_to_point (tree_view, -1, y);
 }
 
 static void
@@ -8628,10 +9547,10 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
     }
   gtk_tree_path_free (cursor_path);
 
-  list = tree_view->priv->columns;
+  list = rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns);
   if (tree_view->priv->focus_column)
     {
-      for (list = tree_view->priv->columns; list; list = list->next)
+      for (; list; list = (rtl ? list->prev : list->next))
        {
          if (list->data == tree_view->priv->focus_column)
            break;
@@ -8640,6 +9559,8 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
 
   while (list)
     {
+      gboolean left, right;
+
       column = list->data;
       if (column->visible == FALSE)
        goto loop_end;
@@ -8649,9 +9570,19 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
                                               &iter,
                                               GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT),
                                               cursor_node->children?TRUE:FALSE);
-      if (_gtk_tree_view_column_cell_focus (column, count,
-                                           list->prev?TRUE:FALSE,
-                                           list->next?TRUE:FALSE))
+
+      if (rtl)
+        {
+         right = list->prev ? TRUE : FALSE;
+         left = list->next ? TRUE : FALSE;
+       }
+      else
+        {
+         left = list->prev ? TRUE : FALSE;
+         right = list->next ? TRUE : FALSE;
+        }
+
+      if (_gtk_tree_view_column_cell_focus (column, count, left, right))
        {
          tree_view->priv->focus_column = column;
          found_column = TRUE;
@@ -8897,6 +9828,7 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
   GtkRBTree *cursor_tree = NULL;
   GtkRBNode *cursor_node = NULL;
   GtkTreePath *cursor_path = NULL;
+  GdkModifierType state;
 
   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
     return FALSE;
@@ -8916,6 +9848,12 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
       return FALSE;
     }
 
+  if (gtk_get_current_event_state (&state))
+    {
+      if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
+        tree_view->priv->ctrl_pressed = TRUE;
+    }
+
   if (cursor_tree->parent_node)
     {
       gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
@@ -8923,14 +9861,8 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
       cursor_tree = cursor_tree->parent_tree;
 
       gtk_tree_path_up (cursor_path);
-      gtk_tree_row_reference_free (tree_view->priv->cursor);
-      tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, cursor_path);
-      _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
-                                               cursor_node,
-                                               cursor_tree,
-                                               cursor_path,
-                                                0,
-                                               FALSE);
+
+      gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE);
     }
 
   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
@@ -8939,6 +9871,8 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
   gtk_tree_path_free (cursor_path);
 
+  tree_view->priv->ctrl_pressed = FALSE;
+
   return TRUE;
 }
 static gboolean
@@ -8951,7 +9885,7 @@ gtk_tree_view_search_entry_flush_timeout (GtkTreeView *tree_view)
 
   GDK_THREADS_LEAVE ();
 
-  return TRUE;
+  return FALSE;
 }
 
 /* Cut and paste from gtkwindow.c */
@@ -8985,6 +9919,9 @@ gtk_tree_view_ensure_interactive_directory (GtkTreeView *tree_view)
 {
   GtkWidget *frame, *vbox, *toplevel;
 
+  if (tree_view->priv->search_custom_entry_set)
+    return;
+
   toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tree_view));
 
    if (tree_view->priv->search_window != NULL)
@@ -9014,6 +9951,9 @@ gtk_tree_view_ensure_interactive_directory (GtkTreeView *tree_view)
   g_signal_connect (tree_view->priv->search_window, "button_press_event",
                    G_CALLBACK (gtk_tree_view_search_button_press_event),
                    tree_view);
+  g_signal_connect (tree_view->priv->search_window, "scroll_event",
+                   G_CALLBACK (gtk_tree_view_search_scroll_event),
+                   tree_view);
 
   frame = gtk_frame_new (NULL);
   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
@@ -9062,6 +10002,9 @@ gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view,
   if (!tree_view->priv->enable_search && !keybinding)
     return FALSE;
 
+  if (tree_view->priv->search_custom_entry_set)
+    return FALSE;
+
   if (tree_view->priv->search_window != NULL &&
       GTK_WIDGET_VISIBLE (tree_view->priv->search_window))
     return TRUE;
@@ -9096,7 +10039,7 @@ gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view,
     gtk_entry_set_text (GTK_ENTRY (tree_view->priv->search_entry), "");
 
   /* done, show it */
-  tree_view->priv->search_dialog_position_func (tree_view, tree_view->priv->search_window);
+  tree_view->priv->search_position_func (tree_view, tree_view->priv->search_window, tree_view->priv->search_position_user_data);
   gtk_widget_show (tree_view->priv->search_window);
   if (tree_view->priv->search_entry_changed_id == 0)
     {
@@ -9131,6 +10074,7 @@ gtk_tree_view_start_interactive_search (GtkTreeView *tree_view)
 {
   return gtk_tree_view_real_start_interactive_search (tree_view, TRUE);
 }
+
 /* this function returns the new width of the column being resized given
  * the column and x position of the cursor; the x cursor position is passed
  * in as a pointer and automagicly corrected if it's beyond min/max limits
@@ -9159,7 +10103,7 @@ gtk_tree_view_new_column_width (GtkTreeView *tree_view,
     width = MAX (column->min_width,
                 width);
   if (column->max_width != -1)
-    width = MIN (width, column->max_width != -1);
+    width = MIN (width, column->max_width);
 
   *x = rtl ? (column->button->allocation.x + column->button->allocation.width - width) : (column->button->allocation.x + width);
  
@@ -9357,6 +10301,12 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
   if (model == tree_view->priv->model)
     return;
 
+  if (tree_view->priv->scroll_to_path)
+    {
+      gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
+      tree_view->priv->scroll_to_path = NULL;
+    }
+
   if (tree_view->priv->model)
     {
       GList *tmplist = tree_view->priv->columns;
@@ -9385,15 +10335,7 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
                                           tree_view->priv->model);
 
       if (tree_view->priv->tree)
-       {
-         _gtk_rbtree_free (tree_view->priv->tree);
-         tree_view->priv->tree = NULL;
-       }
-
-      tree_view->priv->prelight_node = NULL;
-      tree_view->priv->prelight_tree = NULL;
-      tree_view->priv->button_pressed_node = NULL;
-      tree_view->priv->button_pressed_tree = NULL;
+       gtk_tree_view_free_rbtree (tree_view);
 
       gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
       tree_view->priv->drag_dest_row = NULL;
@@ -9422,7 +10364,6 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
 
   tree_view->priv->model = model;
 
-
   if (tree_view->priv->model)
     {
       gint i;
@@ -9486,6 +10427,9 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
 
   g_object_notify (G_OBJECT (tree_view), "model");
 
+  if (tree_view->priv->selection)
+  _gtk_tree_selection_emit_changed (tree_view->priv->selection);
+
   if (GTK_WIDGET_REALIZED (tree_view))
     gtk_widget_queue_resize (GTK_WIDGET (tree_view));
 }
@@ -9716,6 +10660,30 @@ gtk_tree_view_set_headers_clickable (GtkTreeView *tree_view,
 }
 
 
+/**
+ * gtk_tree_view_get_headers_clickable:
+ * @tree_view: A #GtkTreeView.
+ *
+ * Returns whether all header columns are clickable.
+ *
+ * Return value: %TRUE if all header columns are clickable, otherwise %FALSE
+ *
+ * Since: 2.10
+ **/
+gboolean 
+gtk_tree_view_get_headers_clickable (GtkTreeView *tree_view)
+{
+  GList *list;
+  
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
+
+  for (list = tree_view->priv->columns; list; list = list->next)
+    if (!GTK_TREE_VIEW_COLUMN (list->data)->clickable)
+      return FALSE;
+
+  return TRUE;
+}
+
 /**
  * gtk_tree_view_set_rules_hint
  * @tree_view: a #GtkTreeView
@@ -9884,8 +10852,7 @@ gtk_tree_view_insert_column (GtkTreeView       *tree_view,
     g_return_val_if_fail (gtk_tree_view_column_get_sizing (column)
                           == GTK_TREE_VIEW_COLUMN_FIXED, -1);
 
-  g_object_ref (column);
-  gtk_object_sink (GTK_OBJECT (column));
+  g_object_ref_sink (column);
 
   if (tree_view->priv->n_columns == 0 &&
       GTK_WIDGET_REALIZED (tree_view) &&
@@ -9934,7 +10901,7 @@ gtk_tree_view_insert_column (GtkTreeView       *tree_view,
  * 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
  * the end.  The column is initialized with the attributes given. If @tree_view
- * has "fixed_height" mode enabled, then @column must have its sizing
+ * has "fixed_height" mode enabled, then the new column will have its sizing
  * property set to be GTK_TREE_VIEW_COLUMN_FIXED.
  *
  * Return value: The number of columns in @tree_view after insertion.
@@ -9954,6 +10921,8 @@ gtk_tree_view_insert_column_with_attributes (GtkTreeView     *tree_view,
   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
 
   column = gtk_tree_view_column_new ();
+  if (tree_view->priv->fixed_height_mode)
+    gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
 
   gtk_tree_view_column_set_title (column, title);
   gtk_tree_view_column_pack_start (column, cell, TRUE);
@@ -9990,7 +10959,7 @@ gtk_tree_view_insert_column_with_attributes (GtkTreeView     *tree_view,
  * 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_pack_start().
- * If @tree_view has "fixed_height" mode enabled, then @column must have its
+ * If @tree_view has "fixed_height" mode enabled, then the new column will have its
  * "sizing" property set to be GTK_TREE_VIEW_COLUMN_FIXED.
  *
  * Return value: number of columns in the tree view post-insert
@@ -10009,6 +10978,8 @@ gtk_tree_view_insert_column_with_data_func  (GtkTreeView               *tree_vie
   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
 
   column = gtk_tree_view_column_new ();
+  if (tree_view->priv->fixed_height_mode)
+    gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
 
   gtk_tree_view_column_set_title (column, title);
   gtk_tree_view_column_pack_start (column, cell, TRUE);
@@ -10300,6 +11271,7 @@ gtk_tree_view_scroll_to_cell (GtkTreeView       *tree_view,
    * it is much slower than just going to the point.
    */
   if (! GTK_WIDGET_VISIBLE (tree_view) ||
+      ! GTK_WIDGET_REALIZED (tree_view) ||
       GTK_WIDGET_ALLOC_NEEDED (tree_view) || 
       GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
     {
@@ -10615,6 +11587,11 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
   GtkTreeIter temp;
   gboolean expand;
 
+  if (animate)
+    g_object_get (gtk_widget_get_settings (GTK_WIDGET (tree_view)),
+                  "gtk-enable-animations", &animate,
+                  NULL);
+
   remove_auto_expand_timeout (tree_view);
 
   if (node->children && !open_all)
@@ -10700,6 +11677,14 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
   install_presize_handler (tree_view);
 
   g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
+  if (open_all)
+    {
+      _gtk_rbtree_traverse (node->children,
+                            node->children->root,
+                            G_PRE_ORDER,
+                            gtk_tree_view_expand_all_emission_helper,
+                            tree_view);
+    }
   return TRUE;
 }
 
@@ -10750,9 +11735,13 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
   gboolean collapse;
   gint x, y;
   GList *list;
-  GdkDisplay *display;
   GdkWindow *child, *parent;
 
+  if (animate)
+    g_object_get (gtk_widget_get_settings (GTK_WIDGET (tree_view)),
+                  "gtk-enable-animations", &animate,
+                  NULL);
+
   remove_auto_expand_timeout (tree_view);
 
   if (node->children == NULL)
@@ -10858,6 +11847,14 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
       gtk_tree_path_free (lsc);
     }
 
+  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;
+    }
+
   if (gtk_tree_view_unref_and_check_selection_tree (tree_view, node->children))
     {
       _gtk_rbtree_remove (node->children);
@@ -10872,14 +11869,6 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
       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;
-    }
-
   if (animate)
     {
       tree_view->priv->expand_collapse_timeout = g_timeout_add (50, expand_collapse_timeout, tree_view);
@@ -10901,7 +11890,6 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
       /* now that we've collapsed all rows, we want to try to set the prelight
        * again. To do this, we fake a motion event and send it to ourselves. */
 
-      display = gdk_drawable_get_display (tree_view->priv->bin_window);
       child = tree_view->priv->bin_window;
       parent = gdk_window_get_parent (child);
 
@@ -11507,13 +12495,24 @@ gtk_tree_view_get_cell_area (GtkTreeView        *tree_view,
       rect->height = MAX (CELL_HEIGHT (node, vertical_separator), tree_view->priv->expander_size - vertical_separator);
 
       if (column &&
-         gtk_tree_view_is_expander_column (tree_view, column) &&
-         TREE_VIEW_DRAW_EXPANDERS (tree_view))
+         gtk_tree_view_is_expander_column (tree_view, column))
        {
-         gint depth = gtk_tree_path_get_depth (path) - 1;
+         gint depth = gtk_tree_path_get_depth (path);
+         gboolean rtl;
+
+         rtl = gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL;
+
+         if (!rtl)
+           rect->x += (depth - 1) * tree_view->priv->level_indentation;
+         rect->width -= (depth - 1) * tree_view->priv->level_indentation;
+
+         if (TREE_VIEW_DRAW_EXPANDERS (tree_view))
+           {
+             if (!rtl)
+               rect->x += depth * tree_view->priv->expander_size;
+             rect->width -= depth * tree_view->priv->expander_size;
+           }
 
-         rect->x += depth * tree_view->priv->expander_size;
-         rect->width -= depth * tree_view->priv->expander_size;
          rect->width = MAX (rect->width, 0);
        }
     }
@@ -11677,6 +12676,58 @@ gtk_tree_view_tree_to_widget_coords (GtkTreeView *tree_view,
     *wy = ty - tree_view->priv->dy;
 }
 
+/**
+ * gtk_tree_view_get_visible_range:
+ * @tree_view: A #GtkTreeView
+ * @start_path: Return location for start of region, or %NULL.
+ * @end_path: Return location for end of region, or %NULL.
+ *
+ * Sets @start_path and @end_path to be the first and last visible path.
+ * Note that there may be invisible paths in between.
+ *
+ * The paths should be freed with gtk_tree_path_free() after use.
+ *
+ * Returns: %TRUE, if valid paths were placed in @start_path and @end_path.
+ *
+ * Since: 2.8
+ **/
+gboolean
+gtk_tree_view_get_visible_range (GtkTreeView  *tree_view,
+                                 GtkTreePath **start_path,
+                                 GtkTreePath **end_path)
+{
+  GtkRBTree *tree;
+  GtkRBNode *node;
+
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
+
+  if (!tree_view->priv->tree)
+    return FALSE;
+
+  if (start_path)
+    {
+      _gtk_rbtree_find_offset (tree_view->priv->tree,
+                               TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, 0),
+                               &tree, &node);
+      *start_path = _gtk_tree_view_find_path (tree_view, tree, node);
+    }
+
+  if (end_path)
+    {
+      gint y;
+
+      if (tree_view->priv->height < tree_view->priv->vadjustment->page_size)
+        y = tree_view->priv->height - 1;
+      else
+        y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, tree_view->priv->vadjustment->page_size) - 1;
+
+      _gtk_rbtree_find_offset (tree_view->priv->tree, y, &tree, &node);
+      *end_path = _gtk_tree_view_find_path (tree_view, tree, node);
+    }
+
+  return TRUE;
+}
+
 static void
 unset_reorderable (GtkTreeView *tree_view)
 {
@@ -12037,8 +13088,8 @@ 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
- * for a drag icon.
+ * Creates a #GdkPixmap representation of the row at @path.  
+ * This image is used for a drag icon.
  *
  * Return value: a newly-allocated pixmap of the drag icon.
  **/
@@ -12060,9 +13111,16 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
   GdkDrawable *drawable;
   gint bin_window_width;
   gboolean is_separator = FALSE;
+  gboolean rtl;
+
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
+  g_return_val_if_fail (path != NULL, NULL);
 
   widget = GTK_WIDGET (tree_view);
 
+  if (!GTK_WIDGET_REALIZED (tree_view))
+    return NULL;
+
   depth = gtk_tree_path_get_depth (path);
 
   _gtk_tree_view_find_node (tree_view,
@@ -12110,7 +13168,11 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
                       bin_window_width + 2,
                       background_area.height + 2);
 
-  for (list = tree_view->priv->columns; list; list = list->next)
+  rtl = gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL;
+
+  for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
+      list;
+      list = (rtl ? list->prev : list->next))
     {
       GtkTreeViewColumn *column = list->data;
       GdkRectangle cell_area;
@@ -12126,17 +13188,27 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
       background_area.x = cell_offset;
       background_area.width = column->width;
 
+      gtk_widget_style_get (widget,
+                           "vertical-separator", &vertical_separator,
+                           NULL);
+
       cell_area = background_area;
 
-      gtk_widget_style_get (widget, "vertical-separator", &vertical_separator, NULL);
       cell_area.y += vertical_separator / 2;
       cell_area.height -= vertical_separator;
 
-      if (gtk_tree_view_is_expander_column (tree_view, column) &&
-          TREE_VIEW_DRAW_EXPANDERS(tree_view))
+      if (gtk_tree_view_is_expander_column (tree_view, column))
         {
-          cell_area.x += depth * tree_view->priv->expander_size;
-          cell_area.width -= depth * tree_view->priv->expander_size;
+         if (!rtl)
+           cell_area.x += (depth - 1) * tree_view->priv->level_indentation;
+         cell_area.width -= (depth - 1) * tree_view->priv->level_indentation;
+
+          if (TREE_VIEW_DRAW_EXPANDERS(tree_view))
+           {
+             if (!rtl)
+               cell_area.x += depth * tree_view->priv->expander_size;
+             cell_area.width -= depth * tree_view->priv->expander_size;
+           }
         }
 
       if (gtk_tree_view_column_cell_is_visible (column))
@@ -12328,7 +13400,7 @@ gtk_tree_view_set_search_equal_func (GtkTreeView                *tree_view,
                                     GtkDestroyNotify            search_destroy)
 {
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
-  g_return_if_fail (search_equal_func !=NULL);
+  g_return_if_fail (search_equal_func != NULL);
 
   if (tree_view->priv->search_destroy)
     (* tree_view->priv->search_destroy) (tree_view->priv->search_user_data);
@@ -12340,6 +13412,146 @@ gtk_tree_view_set_search_equal_func (GtkTreeView                *tree_view,
     tree_view->priv->search_equal_func = gtk_tree_view_search_equal_func;
 }
 
+/**
+ * gtk_tree_view_get_search_entry:
+ * @tree_view: A #GtkTreeView
+ *
+ * Returns the GtkEntry which is currently in use as interactive search
+ * entry for @tree_view.  In case the built-in entry is being used, %NULL
+ * will be returned.
+ *
+ * Return value: the entry currently in use as search entry.
+ *
+ * Since: 2.10
+ */
+GtkEntry *
+gtk_tree_view_get_search_entry (GtkTreeView *tree_view)
+{
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
+
+  if (tree_view->priv->search_custom_entry_set)
+    return GTK_ENTRY (tree_view->priv->search_entry);
+
+  return NULL;
+}
+
+/**
+ * gtk_tree_view_set_search_entry:
+ * @tree_view: A #GtkTreeView
+ * @entry: the entry the interactive search code of @tree_view should use or %NULL
+ *
+ * Sets the entry which the interactive search code will use for this
+ * @tree_view.  This is useful when you want to provide a search entry
+ * in our interface at all time at a fixed position.  Passing %NULL for
+ * @entry will make the interactive search code use the built-in popup
+ * entry again.
+ *
+ * Since: 2.10
+ */
+void
+gtk_tree_view_set_search_entry (GtkTreeView *tree_view,
+                               GtkEntry    *entry)
+{
+  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+  if (entry != NULL)
+    g_return_if_fail (GTK_IS_ENTRY (entry));
+
+  if (tree_view->priv->search_custom_entry_set)
+    {
+      if (tree_view->priv->search_entry_changed_id)
+        {
+         g_signal_handler_disconnect (tree_view->priv->search_entry,
+                                      tree_view->priv->search_entry_changed_id);
+         tree_view->priv->search_entry_changed_id = 0;
+       }
+      g_signal_handlers_disconnect_by_func (tree_view->priv->search_entry,
+                                           G_CALLBACK (gtk_tree_view_search_key_press_event),
+                                           tree_view);
+
+      g_object_unref (tree_view->priv->search_entry);
+    }
+  else if (tree_view->priv->search_window)
+    {
+      gtk_widget_destroy (tree_view->priv->search_window);
+
+      tree_view->priv->search_window = NULL;
+    }
+
+  if (entry)
+    {
+      tree_view->priv->search_entry = g_object_ref (entry);
+      tree_view->priv->search_custom_entry_set = TRUE;
+
+      if (tree_view->priv->search_entry_changed_id == 0)
+        {
+          tree_view->priv->search_entry_changed_id =
+           g_signal_connect (tree_view->priv->search_entry, "changed",
+                             G_CALLBACK (gtk_tree_view_search_init),
+                             tree_view);
+       }
+      
+        g_signal_connect (tree_view->priv->search_entry, "key_press_event",
+                         G_CALLBACK (gtk_tree_view_search_key_press_event),
+                         tree_view);
+
+       gtk_tree_view_search_init (tree_view->priv->search_entry, tree_view);
+    }
+  else
+    {
+      tree_view->priv->search_entry = NULL;
+      tree_view->priv->search_custom_entry_set = FALSE;
+    }
+}
+
+/**
+ * gtk_tree_view_set_search_position_func:
+ * @tree_view: A #GtkTreeView
+ * @func: the function to use to position the search dialog, or %NULL
+ *    to use the default search position function
+ * @data: user data to pass to @func, or %NULL
+ * @destroy: Destroy notifier for @data, or %NULL
+ *
+ * Sets the function to use when positioning the seach dialog.
+ *
+ * Since: 2.10
+ **/
+void
+gtk_tree_view_set_search_position_func (GtkTreeView                   *tree_view,
+                                       GtkTreeViewSearchPositionFunc  func,
+                                       gpointer                       user_data,
+                                       GDestroyNotify                 destroy)
+{
+  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+
+  if (tree_view->priv->search_position_destroy)
+    (* tree_view->priv->search_position_destroy) (tree_view->priv->search_position_user_data);
+
+  tree_view->priv->search_position_func = func;
+  tree_view->priv->search_position_user_data = user_data;
+  tree_view->priv->search_position_destroy = destroy;
+  if (tree_view->priv->search_position_func == NULL)
+    tree_view->priv->search_position_func = gtk_tree_view_search_position_func;
+}
+
+/**
+ * gtk_tree_view_get_search_position_func:
+ * @tree_view: A #GtkTreeView
+ *
+ * Returns the positioning function currently in use.
+ *
+ * Return value: the currently used function for positioning the search dialog.
+ *
+ * Since: 2.10
+ */
+GtkTreeViewSearchPositionFunc
+gtk_tree_view_get_search_position_func (GtkTreeView *tree_view)
+{
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
+
+  return tree_view->priv->search_position_func;
+}
+
+
 static void
 gtk_tree_view_search_dialog_hide (GtkWidget   *search_dialog,
                                  GtkTreeView *tree_view)
@@ -12367,7 +13579,8 @@ gtk_tree_view_search_dialog_hide (GtkWidget   *search_dialog,
 
 static void
 gtk_tree_view_search_position_func (GtkTreeView *tree_view,
-                                   GtkWidget   *search_dialog)
+                                   GtkWidget   *search_dialog,
+                                   gpointer     user_data)
 {
   gint x, y;
   gint tree_x, tree_y;
@@ -12389,14 +13602,14 @@ gtk_tree_view_search_position_func (GtkTreeView *tree_view,
                         &tree_height);
   gtk_widget_size_request (search_dialog, &requisition);
 
-  if (tree_x + tree_width - requisition.width > gdk_screen_get_width (screen))
+  if (tree_x + tree_width > gdk_screen_get_width (screen))
     x = gdk_screen_get_width (screen) - requisition.width;
   else if (tree_x + tree_width - requisition.width < 0)
     x = 0;
   else
     x = tree_x + tree_width - requisition.width;
 
-  if (tree_y + tree_height > gdk_screen_get_height (screen))
+  if (tree_y + tree_height + requisition.height > gdk_screen_get_height (screen))
     y = gdk_screen_get_height (screen) - requisition.height;
   else if (tree_y + tree_height < 0) /* isn't really possible ... */
     y = 0;
@@ -12505,9 +13718,33 @@ gtk_tree_view_search_button_press_event (GtkWidget *widget,
 
   gtk_tree_view_search_dialog_hide (widget, tree_view);
 
+  if (event->window == tree_view->priv->bin_window)
+    gtk_tree_view_button_press (GTK_WIDGET (tree_view), event);
+
   return TRUE;
 }
 
+static gboolean
+gtk_tree_view_search_scroll_event (GtkWidget *widget,
+                                  GdkEventScroll *event,
+                                  GtkTreeView *tree_view)
+{
+  gboolean retval = FALSE;
+
+  if (event->direction == GDK_SCROLL_UP)
+    {
+      gtk_tree_view_search_move (widget, tree_view, TRUE);
+      retval = TRUE;
+    }
+  else if (event->direction == GDK_SCROLL_DOWN)
+    {
+      gtk_tree_view_search_move (widget, tree_view, FALSE);
+      retval = TRUE;
+    }
+
+  return retval;
+}
+
 static gboolean
 gtk_tree_view_search_key_press_event (GtkWidget *widget,
                                      GdkEventKey *event,
@@ -12519,8 +13756,11 @@ gtk_tree_view_search_key_press_event (GtkWidget *widget,
   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
 
   /* close window and cancel the search */
-  if (event->keyval == GDK_Escape ||
-      event->keyval == GDK_Tab)
+  if (!tree_view->priv->search_custom_entry_set
+      && (event->keyval == GDK_Escape ||
+          event->keyval == GDK_Tab ||
+           event->keyval == GDK_KP_Tab ||
+           event->keyval == GDK_ISO_Left_Tab))
     {
       gtk_tree_view_search_dialog_hide (widget, tree_view);
       return TRUE;
@@ -12533,6 +13773,13 @@ gtk_tree_view_search_key_press_event (GtkWidget *widget,
       retval = TRUE;
     }
 
+  if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == (GDK_CONTROL_MASK | GDK_SHIFT_MASK))
+      && (event->keyval == GDK_g || event->keyval == GDK_G))
+    {
+      gtk_tree_view_search_move (widget, tree_view, TRUE);
+      retval = TRUE;
+    }
+
   /* select next matching iter */
   if (event->keyval == GDK_Down || event->keyval == GDK_KP_Down)
     {
@@ -12540,8 +13787,16 @@ gtk_tree_view_search_key_press_event (GtkWidget *widget,
       retval = TRUE;
     }
 
+  if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK)
+      && (event->keyval == GDK_g || event->keyval == GDK_G))
+    {
+      gtk_tree_view_search_move (widget, tree_view, FALSE);
+      retval = TRUE;
+    }
+
   /* renew the flush timeout */
-  if (retval && tree_view->priv->typeselect_flush_timeout)
+  if (retval && tree_view->priv->typeselect_flush_timeout
+      && !tree_view->priv->search_custom_entry_set)
     {
       g_source_remove (tree_view->priv->typeselect_flush_timeout);
       tree_view->priv->typeselect_flush_timeout =
@@ -12791,7 +14046,8 @@ gtk_tree_view_search_init (GtkWidget   *entry,
 
   /* search */
   gtk_tree_selection_unselect_all (selection);
-  if (tree_view->priv->typeselect_flush_timeout)
+  if (tree_view->priv->typeselect_flush_timeout
+      && tree_view->priv->search_custom_entry_set)
     {
       g_source_remove (tree_view->priv->typeselect_flush_timeout);
       tree_view->priv->typeselect_flush_timeout =
@@ -12880,12 +14136,6 @@ gtk_tree_view_start_editing (GtkTreeView *tree_view,
                               tree_view->priv->focus_column,
                               &cell_area);
 
-  if (gtk_tree_view_is_expander_column (tree_view, tree_view->priv->focus_column) && TREE_VIEW_DRAW_EXPANDERS (tree_view))
-    {
-      cell_area.x += tree_view->priv->expander_size;
-      cell_area.width -= tree_view->priv->expander_size;
-    }
-
   if (_gtk_tree_view_column_cell_event (tree_view->priv->focus_column,
                                        &editable_widget,
                                        NULL,
@@ -12903,6 +14153,7 @@ gtk_tree_view_start_editing (GtkTreeView *tree_view,
 
          area = cell_area;
          cell = _gtk_tree_view_column_get_edited_cell (tree_view->priv->focus_column);
+
          _gtk_tree_view_column_get_neighbor_sizes (tree_view->priv->focus_column, cell, &left, &right);
 
          area.x += left;
@@ -13069,6 +14320,49 @@ gtk_tree_view_get_hover_expand (GtkTreeView *tree_view)
   return tree_view->priv->hover_expand;
 }
 
+/**
+ * gtk_tree_view_set_rubber_banding:
+ * @tree_view: a #GtkTreeView
+ * @enable: %TRUE to enable rubber banding
+ *
+ * Enables or disables rubber banding in @tree_view.  If the selection mode
+ * is #GTK_SELECTION_MULTIPLE, rubber banding will allow the user to select
+ * multiple rows by dragging the mouse.
+ * 
+ * Since: 2.10
+ **/
+void
+gtk_tree_view_set_rubber_banding (GtkTreeView *tree_view,
+                                 gboolean     enable)
+{
+  enable = enable != FALSE;
+
+  if (enable != tree_view->priv->rubber_banding_enable)
+    {
+      tree_view->priv->rubber_banding_enable = enable;
+
+      g_object_notify (G_OBJECT (tree_view), "rubber-banding");
+    }
+}
+
+/**
+ * gtk_tree_view_get_rubber_banding:
+ * @tree_view: a #GtkTreeView
+ * 
+ * Returns whether rubber banding is turned on for @tree_view.  If the
+ * selection mode is #GTK_SELECTION_MULTIPLE, rubber banding will allow the
+ * user to select multiple rows by dragging the mouse.
+ * 
+ * Return value: %TRUE if rubber banding in @tree_view is enabled.
+ *
+ * Since: 2.10
+ **/
+gboolean
+gtk_tree_view_get_rubber_banding (GtkTreeView *tree_view)
+{
+  return tree_view->priv->rubber_banding_enable;
+}
+
 /**
  * gtk_tree_view_get_row_separator_func:
  * @tree_view: a #GtkTreeView
@@ -13135,12 +14429,161 @@ gtk_tree_view_state_changed (GtkWidget      *widget,
 
   if (GTK_WIDGET_REALIZED (widget))
     {
-      gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
+      gdk_window_set_back_pixmap (widget->window, NULL, FALSE);
       gdk_window_set_background (tree_view->priv->bin_window, &widget->style->base[widget->state]);
     }
 
   gtk_widget_queue_draw (widget);
 }
 
+/**
+ * gtk_tree_view_get_grid_lines:
+ * @tree_view: a #GtkTreeView
+ *
+ * Returns which grid lines are enabled in @tree_view.
+ *
+ * Return value: a #GtkTreeViewGridLines value indicating which grid lines
+ * are enabled.
+ *
+ * Since: 2.10
+ */
+GtkTreeViewGridLines
+gtk_tree_view_get_grid_lines (GtkTreeView *tree_view)
+{
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), 0);
+
+  return tree_view->priv->grid_lines;
+}
+
+/**
+ * gtk_tree_view_set_grid_lines:
+ * @tree_view: a #GtkTreeView
+ * @grid_lines: a #GtkTreeViewGridLines value indicating which grid lines to
+ * enable.
+ *
+ * Sets which grid lines to draw in @tree_view.
+ *
+ * Since: 2.10
+ */
+void
+gtk_tree_view_set_grid_lines (GtkTreeView           *tree_view,
+                             GtkTreeViewGridLines   grid_lines)
+{
+  gint line_width;
+  guint8 *dash_list;
+  GtkWidget *widget;
+
+  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+
+  widget = GTK_WIDGET (tree_view);
+
+  if (!GTK_WIDGET_REALIZED (widget))
+    {
+      tree_view->priv->grid_lines = grid_lines;
+      return;
+    }
+
+  gtk_widget_style_get (widget,
+                       "grid-line-width", &line_width,
+                       "grid-line-pattern", (gchar *)&dash_list,
+                       NULL);
+
+  if (tree_view->priv->grid_line_gc)
+    g_object_unref (tree_view->priv->grid_line_gc);
+
+  tree_view->priv->grid_lines = grid_lines;
+  if (grid_lines == GTK_TREE_VIEW_GRID_LINES_NONE)
+    {
+      tree_view->priv->grid_line_gc = NULL;
+      g_free (dash_list);
+      return;
+    }
+
+  tree_view->priv->grid_line_gc = gdk_gc_new (widget->window);
+  gdk_gc_copy (tree_view->priv->grid_line_gc,
+              widget->style->black_gc);
+
+  gdk_gc_set_line_attributes (tree_view->priv->grid_line_gc, line_width,
+                             GDK_LINE_ON_OFF_DASH,
+                             GDK_CAP_BUTT, GDK_JOIN_MITER);
+  gdk_gc_set_dashes (tree_view->priv->grid_line_gc, 0, dash_list, 2);
+  g_free (dash_list);
+
+  gtk_widget_queue_draw (GTK_WIDGET (tree_view));
+}
+
+/**
+ * gtk_tree_view_get_enable_tree_lines:
+ * @tree_view: a #GtkTreeView.
+ *
+ * Returns whether or not tree lines are drawn in @tree_view.
+ *
+ * Return value: %TRUE if tree lines are drawn in @tree_view, %FALSE
+ * otherwise.
+ *
+ * Since: 2.10
+ */
+gboolean
+gtk_tree_view_get_enable_tree_lines (GtkTreeView *tree_view)
+{
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
+
+  return tree_view->priv->tree_lines_enabled;
+}
+
+/**
+ * gtk_tree_view_set_enable_tree_lines:
+ * @tree_view: a #GtkTreeView
+ * @enabled: %TRUE to enable tree line drawing, %FALSE otherwise.
+ *
+ * Sets whether to draw lines interconnecting the expanders in @tree_view.
+ * This does not have any visible effects for lists.
+ *
+ * Since: 2.10
+ */
+void
+gtk_tree_view_set_enable_tree_lines (GtkTreeView *tree_view,
+                                    gboolean     enabled)
+{
+  gint line_width;
+  guint8 *dash_list;
+  GtkWidget *widget;
+
+  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+
+  widget = GTK_WIDGET (tree_view);
+
+  if (!GTK_WIDGET_REALIZED (widget))
+    {
+      tree_view->priv->tree_lines_enabled = enabled;
+      return;
+    }
+
+  gtk_widget_style_get (widget,
+                       "tree-line-width", &line_width,
+                       "tree-line-pattern", (gchar *)&dash_list,
+                       NULL);
+
+  if (tree_view->priv->tree_line_gc)
+    g_object_unref (tree_view->priv->tree_line_gc);
+
+  if (!enabled)
+    {
+      tree_view->priv->tree_line_gc = NULL;
+      return;
+    }
+
+  tree_view->priv->tree_line_gc = gdk_gc_new (widget->window);
+  gdk_gc_copy (tree_view->priv->tree_line_gc,
+              widget->style->black_gc);
+
+  gdk_gc_set_line_attributes (tree_view->priv->tree_line_gc, line_width,
+                             GDK_LINE_ON_OFF_DASH,
+                             GDK_CAP_BUTT, GDK_JOIN_MITER);
+  gdk_gc_set_dashes (tree_view->priv->tree_line_gc, 0, dash_list, 2);
+
+  gtk_widget_queue_draw (GTK_WIDGET (tree_view));
+}
+
 #define __GTK_TREE_VIEW_C__
 #include "gtkaliasdef.c"