]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeview.c
(Note: This is not exactly the same as the patch which went in gtk-2-2).
[~andy/gtk] / gtk / gtktreeview.c
1 /* gtktreeview.c
2  * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20
21 #include <string.h>
22 #include <gdk/gdkkeysyms.h>
23
24 #include "gtktreeview.h"
25 #include "gtkrbtree.h"
26 #include "gtktreednd.h"
27 #include "gtktreeprivate.h"
28 #include "gtkcellrenderer.h"
29 #include "gtkmain.h"
30 #include "gtkmarshalers.h"
31 #include "gtkbutton.h"
32 #include "gtkalignment.h"
33 #include "gtklabel.h"
34 #include "gtkhbox.h"
35 #include "gtkarrow.h"
36 #include "gtkintl.h"
37 #include "gtkbindings.h"
38 #include "gtkcontainer.h"
39 #include "gtkentry.h"
40 #include "gtktreemodelsort.h"
41
42 #define GTK_TREE_VIEW_SEARCH_DIALOG_KEY "gtk-tree-view-search-dialog"
43 #define GTK_TREE_VIEW_PRIORITY_VALIDATE (GDK_PRIORITY_REDRAW + 5)
44 #define GTK_TREE_VIEW_PRIORITY_SCROLL_SYNC (GTK_TREE_VIEW_PRIORITY_VALIDATE + 2)
45 #define GTK_TREE_VIEW_NUM_ROWS_PER_IDLE 500
46 #define SCROLL_EDGE_SIZE 15
47 #define EXPANDER_EXTRA_PADDING 4
48
49 /* The "background" areas of all rows/cells add up to cover the entire tree.
50  * The background includes all inter-row and inter-cell spacing.
51  * The "cell" areas are the cell_area passed in to gtk_cell_renderer_render(),
52  * i.e. just the cells, no spacing.
53  */
54
55 #define BACKGROUND_HEIGHT(node) (GTK_RBNODE_GET_HEIGHT (node))
56 #define CELL_HEIGHT(node, separator) ((BACKGROUND_HEIGHT (node)) - (separator))
57
58 #define TREE_WINDOW_Y_TO_RBTREE_Y(tree_view,y) ((y) + tree_view->priv->dy)
59 #define RBTREE_Y_TO_TREE_WINDOW_Y(tree_view,y) ((y) - tree_view->priv->dy)
60
61 /* This is in Window coordinates */
62 #define BACKGROUND_FIRST_PIXEL(tree_view,tree,node) (RBTREE_Y_TO_TREE_WINDOW_Y (tree_view, _gtk_rbtree_node_find_offset ((tree), (node))))
63 #define CELL_FIRST_PIXEL(tree_view,tree,node,separator) (BACKGROUND_FIRST_PIXEL (tree_view,tree,node) + separator/2)
64
65
66 typedef struct _GtkTreeViewChild GtkTreeViewChild;
67 struct _GtkTreeViewChild
68 {
69   GtkWidget *widget;
70   gint x;
71   gint y;
72   gint width;
73   gint height;
74 };
75
76
77 typedef struct _TreeViewDragInfo TreeViewDragInfo;
78 struct _TreeViewDragInfo
79 {
80   GdkModifierType start_button_mask;
81   GtkTargetList *source_target_list;
82   GdkDragAction source_actions;
83
84   GtkTargetList *dest_target_list;
85
86   guint source_set : 1;
87   guint dest_set : 1;
88 };
89
90
91 /* Signals */
92 enum
93 {
94   ROW_ACTIVATED,
95   TEST_EXPAND_ROW,
96   TEST_COLLAPSE_ROW,
97   ROW_EXPANDED,
98   ROW_COLLAPSED,
99   COLUMNS_CHANGED,
100   CURSOR_CHANGED,
101   MOVE_CURSOR,
102   SELECT_ALL,
103   UNSELECT_ALL,
104   SELECT_CURSOR_ROW,
105   TOGGLE_CURSOR_ROW,
106   EXPAND_COLLAPSE_CURSOR_ROW,
107   SELECT_CURSOR_PARENT,
108   START_INTERACTIVE_SEARCH,
109   LAST_SIGNAL
110 };
111
112 /* Properties */
113 enum {
114   PROP_0,
115   PROP_MODEL,
116   PROP_HADJUSTMENT,
117   PROP_VADJUSTMENT,
118   PROP_HEADERS_VISIBLE,
119   PROP_HEADERS_CLICKABLE,
120   PROP_EXPANDER_COLUMN,
121   PROP_REORDERABLE,
122   PROP_RULES_HINT,
123   PROP_ENABLE_SEARCH,
124   PROP_SEARCH_COLUMN
125 };
126
127 static void     gtk_tree_view_class_init           (GtkTreeViewClass *klass);
128 static void     gtk_tree_view_init                 (GtkTreeView      *tree_view);
129
130 /* object signals */
131 static void     gtk_tree_view_finalize             (GObject          *object);
132 static void     gtk_tree_view_set_property         (GObject         *object,
133                                                     guint            prop_id,
134                                                     const GValue    *value,
135                                                     GParamSpec      *pspec);
136 static void     gtk_tree_view_get_property         (GObject         *object,
137                                                     guint            prop_id,
138                                                     GValue          *value,
139                                                     GParamSpec      *pspec);
140
141 /* gtkobject signals */
142 static void     gtk_tree_view_destroy              (GtkObject        *object);
143
144 /* gtkwidget signals */
145 static void     gtk_tree_view_realize              (GtkWidget        *widget);
146 static void     gtk_tree_view_unrealize            (GtkWidget        *widget);
147 static void     gtk_tree_view_map                  (GtkWidget        *widget);
148 static void     gtk_tree_view_size_request         (GtkWidget        *widget,
149                                                     GtkRequisition   *requisition);
150 static void     gtk_tree_view_size_allocate        (GtkWidget        *widget,
151                                                     GtkAllocation    *allocation);
152 static gboolean gtk_tree_view_expose               (GtkWidget        *widget,
153                                                     GdkEventExpose   *event);
154 static gboolean gtk_tree_view_key_press            (GtkWidget        *widget,
155                                                     GdkEventKey      *event);
156 static gboolean gtk_tree_view_motion               (GtkWidget        *widget,
157                                                     GdkEventMotion   *event);
158 static gboolean gtk_tree_view_enter_notify         (GtkWidget        *widget,
159                                                     GdkEventCrossing *event);
160 static gboolean gtk_tree_view_leave_notify         (GtkWidget        *widget,
161                                                     GdkEventCrossing *event);
162 static gboolean gtk_tree_view_button_press         (GtkWidget        *widget,
163                                                     GdkEventButton   *event);
164 static gboolean gtk_tree_view_button_release       (GtkWidget        *widget,
165                                                     GdkEventButton   *event);
166 static void     gtk_tree_view_set_focus_child      (GtkContainer     *container,
167                                                     GtkWidget        *child);
168 static gint     gtk_tree_view_focus_out            (GtkWidget        *widget,
169                                                     GdkEventFocus    *event);
170 static gint     gtk_tree_view_focus                (GtkWidget        *widget,
171                                                     GtkDirectionType  direction);
172 static void     gtk_tree_view_grab_focus           (GtkWidget        *widget);
173 static void     gtk_tree_view_style_set            (GtkWidget        *widget,
174                                                     GtkStyle         *previous_style);
175
176 /* container signals */
177 static void     gtk_tree_view_remove               (GtkContainer     *container,
178                                                     GtkWidget        *widget);
179 static void     gtk_tree_view_forall               (GtkContainer     *container,
180                                                     gboolean          include_internals,
181                                                     GtkCallback       callback,
182                                                     gpointer          callback_data);
183
184 /* Source side drag signals */
185 static void gtk_tree_view_drag_begin       (GtkWidget        *widget,
186                                             GdkDragContext   *context);
187 static void gtk_tree_view_drag_end         (GtkWidget        *widget,
188                                             GdkDragContext   *context);
189 static void gtk_tree_view_drag_data_get    (GtkWidget        *widget,
190                                             GdkDragContext   *context,
191                                             GtkSelectionData *selection_data,
192                                             guint             info,
193                                             guint             time);
194 static void gtk_tree_view_drag_data_delete (GtkWidget        *widget,
195                                             GdkDragContext   *context);
196
197 /* Target side drag signals */
198 static void     gtk_tree_view_drag_leave         (GtkWidget        *widget,
199                                                   GdkDragContext   *context,
200                                                   guint             time);
201 static gboolean gtk_tree_view_drag_motion        (GtkWidget        *widget,
202                                                   GdkDragContext   *context,
203                                                   gint              x,
204                                                   gint              y,
205                                                   guint             time);
206 static gboolean gtk_tree_view_drag_drop          (GtkWidget        *widget,
207                                                   GdkDragContext   *context,
208                                                   gint              x,
209                                                   gint              y,
210                                                   guint             time);
211 static void     gtk_tree_view_drag_data_received (GtkWidget        *widget,
212                                                   GdkDragContext   *context,
213                                                   gint              x,
214                                                   gint              y,
215                                                   GtkSelectionData *selection_data,
216                                                   guint             info,
217                                                   guint             time);
218
219 /* tree_model signals */
220 static void gtk_tree_view_set_adjustments                 (GtkTreeView     *tree_view,
221                                                            GtkAdjustment   *hadj,
222                                                            GtkAdjustment   *vadj);
223 static gboolean gtk_tree_view_real_move_cursor            (GtkTreeView     *tree_view,
224                                                            GtkMovementStep  step,
225                                                            gint             count);
226 static gboolean gtk_tree_view_real_select_all             (GtkTreeView     *tree_view);
227 static gboolean gtk_tree_view_real_unselect_all           (GtkTreeView     *tree_view);
228 static gboolean gtk_tree_view_real_select_cursor_row      (GtkTreeView     *tree_view,
229                                                            gboolean         start_editing);
230 static gboolean gtk_tree_view_real_toggle_cursor_row      (GtkTreeView     *tree_view);
231 static gboolean gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView     *tree_view,
232                                                                gboolean         logical,
233                                                                gboolean         expand,
234                                                                gboolean         open_all);
235 static gboolean gtk_tree_view_real_select_cursor_parent   (GtkTreeView     *tree_view);
236 static void gtk_tree_view_row_changed                     (GtkTreeModel    *model,
237                                                            GtkTreePath     *path,
238                                                            GtkTreeIter     *iter,
239                                                            gpointer         data);
240 static void gtk_tree_view_row_inserted                    (GtkTreeModel    *model,
241                                                            GtkTreePath     *path,
242                                                            GtkTreeIter     *iter,
243                                                            gpointer         data);
244 static void gtk_tree_view_row_has_child_toggled           (GtkTreeModel    *model,
245                                                            GtkTreePath     *path,
246                                                            GtkTreeIter     *iter,
247                                                            gpointer         data);
248 static void gtk_tree_view_row_deleted                     (GtkTreeModel    *model,
249                                                            GtkTreePath     *path,
250                                                            gpointer         data);
251 static void gtk_tree_view_rows_reordered                  (GtkTreeModel    *model,
252                                                            GtkTreePath     *parent,
253                                                            GtkTreeIter     *iter,
254                                                            gint            *new_order,
255                                                            gpointer         data);
256
257 /* Incremental reflow */
258 static gboolean validate_row             (GtkTreeView *tree_view,
259                                           GtkRBTree   *tree,
260                                           GtkRBNode   *node,
261                                           GtkTreeIter *iter,
262                                           GtkTreePath *path);
263 static void     validate_visible_area    (GtkTreeView *tree_view);
264 static gboolean validate_rows_handler    (GtkTreeView *tree_view);
265 static gboolean validate_rows            (GtkTreeView *tree_view);
266 static gboolean presize_handler_callback (gpointer     data);
267 static void     install_presize_handler  (GtkTreeView *tree_view);
268 static void     install_scroll_sync_handler (GtkTreeView *tree_view);
269 static void     gtk_tree_view_dy_to_top_row (GtkTreeView *tree_view);
270 static void     gtk_tree_view_top_row_to_dy (GtkTreeView *tree_view);
271
272
273 /* Internal functions */
274 static gboolean gtk_tree_view_is_expander_column             (GtkTreeView       *tree_view,
275                                                               GtkTreeViewColumn *column);
276 static void     gtk_tree_view_add_move_binding               (GtkBindingSet     *binding_set,
277                                                               guint              keyval,
278                                                               guint              modmask,
279                                                               GtkMovementStep    step,
280                                                               gint               count);
281 static gint     gtk_tree_view_unref_and_check_selection_tree (GtkTreeView       *tree_view,
282                                                               GtkRBTree         *tree);
283 static void     gtk_tree_view_queue_draw_path                (GtkTreeView       *tree_view,
284                                                               GtkTreePath       *path,
285                                                               GdkRectangle      *clip_rect);
286 static void     gtk_tree_view_queue_draw_arrow               (GtkTreeView       *tree_view,
287                                                               GtkRBTree         *tree,
288                                                               GtkRBNode         *node,
289                                                               GdkRectangle      *clip_rect);
290 static void     gtk_tree_view_draw_arrow                     (GtkTreeView       *tree_view,
291                                                               GtkRBTree         *tree,
292                                                               GtkRBNode         *node,
293                                                               gint               x,
294                                                               gint               y);
295 static void     gtk_tree_view_get_arrow_xrange               (GtkTreeView       *tree_view,
296                                                               GtkRBTree         *tree,
297                                                               gint              *x1,
298                                                               gint              *x2);
299 static gint     gtk_tree_view_new_column_width               (GtkTreeView       *tree_view,
300                                                               gint               i,
301                                                               gint              *x);
302 static void     gtk_tree_view_adjustment_changed             (GtkAdjustment     *adjustment,
303                                                               GtkTreeView       *tree_view);
304 static void     gtk_tree_view_build_tree                     (GtkTreeView       *tree_view,
305                                                               GtkRBTree         *tree,
306                                                               GtkTreeIter       *iter,
307                                                               gint               depth,
308                                                               gboolean           recurse);
309 static gboolean gtk_tree_view_discover_dirty_iter            (GtkTreeView       *tree_view,
310                                                               GtkTreeIter       *iter,
311                                                               gint               depth,
312                                                               gint              *height,
313                                                               GtkRBNode         *node);
314 static void     gtk_tree_view_discover_dirty                 (GtkTreeView       *tree_view,
315                                                               GtkRBTree         *tree,
316                                                               GtkTreeIter       *iter,
317                                                               gint               depth);
318 static void     gtk_tree_view_clamp_node_visible             (GtkTreeView       *tree_view,
319                                                               GtkRBTree         *tree,
320                                                               GtkRBNode         *node);
321 static void     gtk_tree_view_clamp_column_visible           (GtkTreeView       *tree_view,
322                                                               GtkTreeViewColumn *column);
323 static gboolean gtk_tree_view_maybe_begin_dragging_row       (GtkTreeView       *tree_view,
324                                                               GdkEventMotion    *event);
325 static void     gtk_tree_view_focus_to_cursor                (GtkTreeView       *tree_view);
326 static void     gtk_tree_view_move_cursor_up_down            (GtkTreeView       *tree_view,
327                                                               gint               count);
328 static void     gtk_tree_view_move_cursor_page_up_down       (GtkTreeView       *tree_view,
329                                                               gint               count);
330 static void     gtk_tree_view_move_cursor_left_right         (GtkTreeView       *tree_view,
331                                                               gint               count);
332 static void     gtk_tree_view_move_cursor_start_end          (GtkTreeView       *tree_view,
333                                                               gint               count);
334 static gboolean gtk_tree_view_real_collapse_row              (GtkTreeView       *tree_view,
335                                                               GtkTreePath       *path,
336                                                               GtkRBTree         *tree,
337                                                               GtkRBNode         *node,
338                                                               gboolean           animate);
339 static gboolean gtk_tree_view_real_expand_row                (GtkTreeView       *tree_view,
340                                                               GtkTreePath       *path,
341                                                               GtkRBTree         *tree,
342                                                               GtkRBNode         *node,
343                                                               gboolean           open_all,
344                                                               gboolean           animate);
345 static void     gtk_tree_view_real_set_cursor                (GtkTreeView       *tree_view,
346                                                               GtkTreePath       *path,
347                                                               gboolean           clear_and_select,
348                                                               gboolean           clamp_node);
349 static gboolean gtk_tree_view_has_special_cell               (GtkTreeView       *tree_view);
350
351 static gboolean expand_collapse_timeout                      (gpointer           data);
352 static gboolean do_expand_collapse                           (GtkTreeView       *tree_view);
353
354 /* interactive search */
355 static void     gtk_tree_view_search_dialog_destroy     (GtkWidget        *search_dialog,
356                                                          GtkTreeView      *tree_view);
357 static void     gtk_tree_view_search_position_func      (GtkTreeView      *tree_view,
358                                                          GtkWidget        *search_dialog);
359 static void     gtk_tree_view_search_disable_popdown    (GtkEntry         *entry,
360                                                          GtkMenu          *menu,
361                                                          gpointer          data);
362 static gboolean gtk_tree_view_real_search_enable_popdown(gpointer          data);
363 static void     gtk_tree_view_search_enable_popdown     (GtkWidget        *widget,
364                                                          gpointer          data);
365 static gboolean gtk_tree_view_search_delete_event       (GtkWidget        *widget,
366                                                          GdkEventAny      *event,
367                                                          GtkTreeView      *tree_view);
368 static gboolean gtk_tree_view_search_button_press_event (GtkWidget        *widget,
369                                                          GdkEventButton   *event,
370                                                          GtkTreeView      *tree_view);
371 static gboolean gtk_tree_view_search_key_press_event    (GtkWidget        *entry,
372                                                          GdkEventKey      *event,
373                                                          GtkTreeView      *tree_view);
374 static void     gtk_tree_view_search_move               (GtkWidget        *window,
375                                                          GtkTreeView      *tree_view,
376                                                          gboolean          up);
377 static gboolean gtk_tree_view_search_equal_func         (GtkTreeModel     *model,
378                                                          gint              column,
379                                                          const gchar      *key,
380                                                          GtkTreeIter      *iter,
381                                                          gpointer          search_data);
382 static gboolean gtk_tree_view_search_iter               (GtkTreeModel     *model,
383                                                          GtkTreeSelection *selection,
384                                                          GtkTreeIter      *iter,
385                                                          const gchar      *text,
386                                                          gint             *count,
387                                                          gint              n);
388 static void     gtk_tree_view_search_init               (GtkWidget        *entry,
389                                                          GtkTreeView      *tree_view);
390 static void     gtk_tree_view_put                       (GtkTreeView      *tree_view,
391                                                          GtkWidget        *child_widget,
392                                                          gint              x,
393                                                          gint              y,
394                                                          gint              width,
395                                                          gint              height);
396 static gboolean gtk_tree_view_start_editing             (GtkTreeView      *tree_view,
397                                                          GtkTreePath      *cursor_path);
398 static void gtk_tree_view_real_start_editing (GtkTreeView       *tree_view,
399                                               GtkTreeViewColumn *column,
400                                               GtkTreePath       *path,
401                                               GtkCellEditable   *cell_editable,
402                                               GdkRectangle      *cell_area,
403                                               GdkEvent          *event,
404                                               guint              flags);
405 static void gtk_tree_view_stop_editing                  (GtkTreeView *tree_view,
406                                                          gboolean     cancel_editing);
407 static gboolean gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view);
408 static GtkTreeViewColumn *gtk_tree_view_get_drop_column (GtkTreeView       *tree_view,
409                                                          GtkTreeViewColumn *column,
410                                                          gint               drop_position);
411
412
413 static GtkContainerClass *parent_class = NULL;
414 static guint tree_view_signals [LAST_SIGNAL] = { 0 };
415
416 \f
417
418 /* GType Methods
419  */
420
421 GType
422 gtk_tree_view_get_type (void)
423 {
424   static GType tree_view_type = 0;
425
426   if (!tree_view_type)
427     {
428       static const GTypeInfo tree_view_info =
429       {
430         sizeof (GtkTreeViewClass),
431         NULL,           /* base_init */
432         NULL,           /* base_finalize */
433         (GClassInitFunc) gtk_tree_view_class_init,
434         NULL,           /* class_finalize */
435         NULL,           /* class_data */
436         sizeof (GtkTreeView),
437         0,              /* n_preallocs */
438         (GInstanceInitFunc) gtk_tree_view_init
439       };
440
441       tree_view_type =
442         g_type_register_static (GTK_TYPE_CONTAINER, "GtkTreeView",
443                                 &tree_view_info, 0);
444     }
445
446   return tree_view_type;
447 }
448
449 static void
450 gtk_tree_view_class_init (GtkTreeViewClass *class)
451 {
452   GObjectClass *o_class;
453   GtkObjectClass *object_class;
454   GtkWidgetClass *widget_class;
455   GtkContainerClass *container_class;
456   GtkBindingSet *binding_set;
457
458   parent_class = g_type_class_peek_parent (class);
459   binding_set = gtk_binding_set_by_class (class);
460
461   o_class = (GObjectClass *) class;
462   object_class = (GtkObjectClass *) class;
463   widget_class = (GtkWidgetClass *) class;
464   container_class = (GtkContainerClass *) class;
465
466   /* GObject signals */
467   o_class->set_property = gtk_tree_view_set_property;
468   o_class->get_property = gtk_tree_view_get_property;
469   o_class->finalize = gtk_tree_view_finalize;
470
471   /* GtkObject signals */
472   object_class->destroy = gtk_tree_view_destroy;
473
474   /* GtkWidget signals */
475   widget_class->map = gtk_tree_view_map;
476   widget_class->realize = gtk_tree_view_realize;
477   widget_class->unrealize = gtk_tree_view_unrealize;
478   widget_class->size_request = gtk_tree_view_size_request;
479   widget_class->size_allocate = gtk_tree_view_size_allocate;
480   widget_class->button_press_event = gtk_tree_view_button_press;
481   widget_class->button_release_event = gtk_tree_view_button_release;
482   widget_class->motion_notify_event = gtk_tree_view_motion;
483   widget_class->expose_event = gtk_tree_view_expose;
484   widget_class->key_press_event = gtk_tree_view_key_press;
485   widget_class->enter_notify_event = gtk_tree_view_enter_notify;
486   widget_class->leave_notify_event = gtk_tree_view_leave_notify;
487   widget_class->focus_out_event = gtk_tree_view_focus_out;
488   widget_class->drag_begin = gtk_tree_view_drag_begin;
489   widget_class->drag_end = gtk_tree_view_drag_end;
490   widget_class->drag_data_get = gtk_tree_view_drag_data_get;
491   widget_class->drag_data_delete = gtk_tree_view_drag_data_delete;
492   widget_class->drag_leave = gtk_tree_view_drag_leave;
493   widget_class->drag_motion = gtk_tree_view_drag_motion;
494   widget_class->drag_drop = gtk_tree_view_drag_drop;
495   widget_class->drag_data_received = gtk_tree_view_drag_data_received;
496   widget_class->focus = gtk_tree_view_focus;
497   widget_class->grab_focus = gtk_tree_view_grab_focus;
498   widget_class->style_set = gtk_tree_view_style_set;
499
500   /* GtkContainer signals */
501   container_class->remove = gtk_tree_view_remove;
502   container_class->forall = gtk_tree_view_forall;
503   container_class->set_focus_child = gtk_tree_view_set_focus_child;
504
505   class->set_scroll_adjustments = gtk_tree_view_set_adjustments;
506   class->move_cursor = gtk_tree_view_real_move_cursor;
507   class->select_all = gtk_tree_view_real_select_all;
508   class->unselect_all = gtk_tree_view_real_unselect_all;
509   class->select_cursor_row = gtk_tree_view_real_select_cursor_row;
510   class->toggle_cursor_row = gtk_tree_view_real_toggle_cursor_row;
511   class->expand_collapse_cursor_row = gtk_tree_view_real_expand_collapse_cursor_row;
512   class->select_cursor_parent = gtk_tree_view_real_select_cursor_parent;
513   class->start_interactive_search = gtk_tree_view_real_start_interactive_search;
514
515   /* Properties */
516
517   g_object_class_install_property (o_class,
518                                    PROP_MODEL,
519                                    g_param_spec_object ("model",
520                                                         _("TreeView Model"),
521                                                         _("The model for the tree view"),
522                                                         GTK_TYPE_TREE_MODEL,
523                                                         G_PARAM_READWRITE));
524
525   g_object_class_install_property (o_class,
526                                    PROP_HADJUSTMENT,
527                                    g_param_spec_object ("hadjustment",
528                                                         _("Horizontal Adjustment"),
529                                                         _("Horizontal Adjustment for the widget"),
530                                                         GTK_TYPE_ADJUSTMENT,
531                                                         G_PARAM_READWRITE));
532
533   g_object_class_install_property (o_class,
534                                    PROP_VADJUSTMENT,
535                                    g_param_spec_object ("vadjustment",
536                                                         _("Vertical Adjustment"),
537                                                         _("Vertical Adjustment for the widget"),
538                                                         GTK_TYPE_ADJUSTMENT,
539                                                         G_PARAM_READWRITE));
540
541   g_object_class_install_property (o_class,
542                                    PROP_HEADERS_VISIBLE,
543                                    g_param_spec_boolean ("headers_visible",
544                                                          _("Visible"),
545                                                          _("Show the column header buttons"),
546                                                          TRUE,
547                                                          G_PARAM_READWRITE));
548
549   g_object_class_install_property (o_class,
550                                    PROP_HEADERS_CLICKABLE,
551                                    g_param_spec_boolean ("headers_clickable",
552                                                          _("Headers Clickable"),
553                                                          _("Column headers respond to click events"),
554                                                          FALSE,
555                                                          G_PARAM_WRITABLE));
556
557   g_object_class_install_property (o_class,
558                                    PROP_EXPANDER_COLUMN,
559                                    g_param_spec_object ("expander_column",
560                                                         _("Expander Column"),
561                                                         _("Set the column for the expander column"),
562                                                         GTK_TYPE_TREE_VIEW_COLUMN,
563                                                         G_PARAM_READWRITE));
564
565   g_object_class_install_property (o_class,
566                                    PROP_REORDERABLE,
567                                    g_param_spec_boolean ("reorderable",
568                                                          _("Reorderable"),
569                                                          _("View is reorderable"),
570                                                          FALSE,
571                                                          G_PARAM_READWRITE));
572
573   g_object_class_install_property (o_class,
574                                    PROP_RULES_HINT,
575                                    g_param_spec_boolean ("rules_hint",
576                                                          _("Rules Hint"),
577                                                          _("Set a hint to the theme engine to draw rows in alternating colors"),
578                                                          FALSE,
579                                                          G_PARAM_READWRITE));
580
581     g_object_class_install_property (o_class,
582                                      PROP_ENABLE_SEARCH,
583                                      g_param_spec_boolean ("enable_search",
584                                                            _("Enable Search"),
585                                                            _("View allows user to search through columns interactively"),
586                                                            TRUE,
587                                                            G_PARAM_READWRITE));
588
589     g_object_class_install_property (o_class,
590                                      PROP_SEARCH_COLUMN,
591                                      g_param_spec_int ("search_column",
592                                                        _("Search Column"),
593                                                        _("Model column to search through when searching through code"),
594                                                        -1,
595                                                        G_MAXINT,
596                                                        0,
597                                                        G_PARAM_READWRITE));
598
599   /* Style properties */
600 #define _TREE_VIEW_EXPANDER_SIZE 10
601 #define _TREE_VIEW_VERTICAL_SEPARATOR 2
602 #define _TREE_VIEW_HORIZONTAL_SEPARATOR 2
603     
604   gtk_widget_class_install_style_property (widget_class,
605                                            g_param_spec_int ("expander_size",
606                                                              _("Expander Size"),
607                                                              _("Size of the expander arrow"),
608                                                              0,
609                                                              G_MAXINT,
610                                                              _TREE_VIEW_EXPANDER_SIZE,
611                                                              G_PARAM_READABLE));
612
613   gtk_widget_class_install_style_property (widget_class,
614                                            g_param_spec_int ("vertical_separator",
615                                                              _("Vertical Separator Width"),
616                                                              _("Vertical space between cells.  Must be an even number"),
617                                                              0,
618                                                              G_MAXINT,
619                                                              _TREE_VIEW_VERTICAL_SEPARATOR,
620                                                              G_PARAM_READABLE));
621
622   gtk_widget_class_install_style_property (widget_class,
623                                            g_param_spec_int ("horizontal_separator",
624                                                              _("Horizontal Separator Width"),
625                                                              _("Horizontal space between cells.  Must be an even number"),
626                                                              0,
627                                                              G_MAXINT,
628                                                              _TREE_VIEW_HORIZONTAL_SEPARATOR,
629                                                              G_PARAM_READABLE));
630
631   gtk_widget_class_install_style_property (widget_class,
632                                            g_param_spec_boolean ("allow_rules",
633                                                                  _("Allow Rules"),
634                                                                  _("Allow drawing of alternating color rows"),
635                                                                  TRUE,
636                                                                  G_PARAM_READABLE));
637
638   gtk_widget_class_install_style_property (widget_class,
639                                            g_param_spec_boolean ("indent_expanders",
640                                                                  _("Indent Expanders"),
641                                                                  _("Make the expanders indented"),
642                                                                  TRUE,
643                                                                  G_PARAM_READABLE));
644
645   gtk_widget_class_install_style_property (widget_class,
646                                            g_param_spec_boxed ("even_row_color",
647                                                                _("Even Row Color"),
648                                                                _("Color to use for even rows"),
649                                                                GDK_TYPE_COLOR,
650 G_PARAM_READABLE));
651
652   gtk_widget_class_install_style_property (widget_class,
653                                            g_param_spec_boxed ("odd_row_color",
654                                                                _("Odd Row Color"),
655                                                                _("Color to use for odd rows"),
656                                                                GDK_TYPE_COLOR,
657 G_PARAM_READABLE));
658
659   /* Signals */
660   widget_class->set_scroll_adjustments_signal =
661     g_signal_new ("set_scroll_adjustments",
662                   G_TYPE_FROM_CLASS (o_class),
663                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
664                   G_STRUCT_OFFSET (GtkTreeViewClass, set_scroll_adjustments),
665                   NULL, NULL,
666                   _gtk_marshal_VOID__OBJECT_OBJECT,
667                   G_TYPE_NONE, 2,
668                   GTK_TYPE_ADJUSTMENT,
669                   GTK_TYPE_ADJUSTMENT);
670
671   tree_view_signals[ROW_ACTIVATED] =
672     g_signal_new ("row_activated",
673                   G_TYPE_FROM_CLASS (o_class),
674                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
675                   G_STRUCT_OFFSET (GtkTreeViewClass, row_activated),
676                   NULL, NULL,
677                   _gtk_marshal_VOID__BOXED_OBJECT,
678                   G_TYPE_NONE, 2,
679                   GTK_TYPE_TREE_PATH,
680                   GTK_TYPE_TREE_VIEW_COLUMN);
681
682   tree_view_signals[TEST_EXPAND_ROW] =
683     g_signal_new ("test_expand_row",
684                   G_TYPE_FROM_CLASS (o_class),
685                   G_SIGNAL_RUN_LAST,
686                   G_STRUCT_OFFSET (GtkTreeViewClass, test_expand_row),
687                   _gtk_boolean_handled_accumulator, NULL,
688                   _gtk_marshal_BOOLEAN__BOXED_BOXED,
689                   G_TYPE_BOOLEAN, 2,
690                   GTK_TYPE_TREE_ITER,
691                   GTK_TYPE_TREE_PATH);
692
693   tree_view_signals[TEST_COLLAPSE_ROW] =
694     g_signal_new ("test_collapse_row",
695                   G_TYPE_FROM_CLASS (o_class),
696                   G_SIGNAL_RUN_LAST,
697                   G_STRUCT_OFFSET (GtkTreeViewClass, test_collapse_row),
698                   _gtk_boolean_handled_accumulator, NULL,
699                   _gtk_marshal_BOOLEAN__BOXED_BOXED,
700                   G_TYPE_BOOLEAN, 2,
701                   GTK_TYPE_TREE_ITER,
702                   GTK_TYPE_TREE_PATH);
703
704   tree_view_signals[ROW_EXPANDED] =
705     g_signal_new ("row_expanded",
706                   G_TYPE_FROM_CLASS (o_class),
707                   G_SIGNAL_RUN_LAST,
708                   G_STRUCT_OFFSET (GtkTreeViewClass, row_expanded),
709                   NULL, NULL,
710                   _gtk_marshal_VOID__BOXED_BOXED,
711                   G_TYPE_NONE, 2,
712                   GTK_TYPE_TREE_ITER,
713                   GTK_TYPE_TREE_PATH);
714
715   tree_view_signals[ROW_COLLAPSED] =
716     g_signal_new ("row_collapsed",
717                   G_TYPE_FROM_CLASS (o_class),
718                   G_SIGNAL_RUN_LAST,
719                   G_STRUCT_OFFSET (GtkTreeViewClass, row_collapsed),
720                   NULL, NULL,
721                   _gtk_marshal_VOID__BOXED_BOXED,
722                   G_TYPE_NONE, 2,
723                   GTK_TYPE_TREE_ITER,
724                   GTK_TYPE_TREE_PATH);
725
726   tree_view_signals[COLUMNS_CHANGED] =
727     g_signal_new ("columns_changed",
728                   G_TYPE_FROM_CLASS (o_class),
729                   G_SIGNAL_RUN_LAST,
730                   G_STRUCT_OFFSET (GtkTreeViewClass, columns_changed),
731                   NULL, NULL,
732                   _gtk_marshal_NONE__NONE,
733                   G_TYPE_NONE, 0);
734
735   tree_view_signals[CURSOR_CHANGED] =
736     g_signal_new ("cursor_changed",
737                   G_TYPE_FROM_CLASS (o_class),
738                   G_SIGNAL_RUN_LAST,
739                   G_STRUCT_OFFSET (GtkTreeViewClass, cursor_changed),
740                   NULL, NULL,
741                   _gtk_marshal_NONE__NONE,
742                   G_TYPE_NONE, 0);
743
744   tree_view_signals[MOVE_CURSOR] =
745     g_signal_new ("move_cursor",
746                   G_TYPE_FROM_CLASS (object_class),
747                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
748                   G_STRUCT_OFFSET (GtkTreeViewClass, move_cursor),
749                   NULL, NULL,
750                   _gtk_marshal_BOOLEAN__ENUM_INT,
751                   G_TYPE_BOOLEAN, 2,
752                   GTK_TYPE_MOVEMENT_STEP,
753                   G_TYPE_INT);
754
755   tree_view_signals[SELECT_ALL] =
756     g_signal_new ("select_all",
757                   G_TYPE_FROM_CLASS (object_class),
758                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
759                   G_STRUCT_OFFSET (GtkTreeViewClass, select_all),
760                   NULL, NULL,
761                   _gtk_marshal_BOOLEAN__NONE,
762                   G_TYPE_BOOLEAN, 0);
763
764   tree_view_signals[UNSELECT_ALL] =
765     g_signal_new ("unselect_all",
766                   G_TYPE_FROM_CLASS (object_class),
767                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
768                   G_STRUCT_OFFSET (GtkTreeViewClass, unselect_all),
769                   NULL, NULL,
770                   _gtk_marshal_BOOLEAN__NONE,
771                   G_TYPE_BOOLEAN, 0);
772
773   tree_view_signals[SELECT_CURSOR_ROW] =
774     g_signal_new ("select_cursor_row",
775                   G_TYPE_FROM_CLASS (object_class),
776                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
777                   G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_row),
778                   NULL, NULL,
779                   _gtk_marshal_BOOLEAN__BOOLEAN,
780                   G_TYPE_BOOLEAN, 1,
781                   G_TYPE_BOOLEAN);
782
783   tree_view_signals[TOGGLE_CURSOR_ROW] =
784     g_signal_new ("toggle_cursor_row",
785                   G_TYPE_FROM_CLASS (object_class),
786                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
787                   G_STRUCT_OFFSET (GtkTreeViewClass, toggle_cursor_row),
788                   NULL, NULL,
789                   _gtk_marshal_BOOLEAN__NONE,
790                   G_TYPE_BOOLEAN, 0);
791
792   tree_view_signals[EXPAND_COLLAPSE_CURSOR_ROW] =
793     g_signal_new ("expand_collapse_cursor_row",
794                   G_TYPE_FROM_CLASS (object_class),
795                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
796                   G_STRUCT_OFFSET (GtkTreeViewClass, expand_collapse_cursor_row),
797                   NULL, NULL,
798                   _gtk_marshal_BOOLEAN__BOOLEAN_BOOLEAN_BOOLEAN,
799                   G_TYPE_BOOLEAN, 3,
800                   G_TYPE_BOOLEAN,
801                   G_TYPE_BOOLEAN,
802                   G_TYPE_BOOLEAN);
803
804   tree_view_signals[SELECT_CURSOR_PARENT] =
805     g_signal_new ("select_cursor_parent",
806                   G_TYPE_FROM_CLASS (object_class),
807                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
808                   G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_parent),
809                   NULL, NULL,
810                   _gtk_marshal_BOOLEAN__NONE,
811                   G_TYPE_BOOLEAN, 0);
812
813   tree_view_signals[START_INTERACTIVE_SEARCH] =
814     g_signal_new ("start_interactive_search",
815                   G_TYPE_FROM_CLASS (object_class),
816                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
817                   G_STRUCT_OFFSET (GtkTreeViewClass, start_interactive_search),
818                   NULL, NULL,
819                   _gtk_marshal_BOOLEAN__NONE,
820                   G_TYPE_BOOLEAN, 0);
821
822   /* Key bindings */
823   gtk_tree_view_add_move_binding (binding_set, GDK_Up, 0,
824                                   GTK_MOVEMENT_DISPLAY_LINES, -1);
825   gtk_tree_view_add_move_binding (binding_set, GDK_KP_Up, 0,
826                                   GTK_MOVEMENT_DISPLAY_LINES, -1);
827
828   gtk_tree_view_add_move_binding (binding_set, GDK_Down, 0,
829                                   GTK_MOVEMENT_DISPLAY_LINES, 1);
830   gtk_tree_view_add_move_binding (binding_set, GDK_KP_Down, 0,
831                                   GTK_MOVEMENT_DISPLAY_LINES, 1);
832
833   gtk_tree_view_add_move_binding (binding_set, GDK_p, GDK_CONTROL_MASK,
834                                   GTK_MOVEMENT_DISPLAY_LINES, -1);
835
836   gtk_tree_view_add_move_binding (binding_set, GDK_n, GDK_CONTROL_MASK,
837                                   GTK_MOVEMENT_DISPLAY_LINES, 1);
838
839   gtk_tree_view_add_move_binding (binding_set, GDK_Home, 0,
840                                   GTK_MOVEMENT_BUFFER_ENDS, -1);
841   gtk_tree_view_add_move_binding (binding_set, GDK_KP_Home, 0,
842                                   GTK_MOVEMENT_BUFFER_ENDS, -1);
843
844   gtk_tree_view_add_move_binding (binding_set, GDK_End, 0,
845                                   GTK_MOVEMENT_BUFFER_ENDS, 1);
846   gtk_tree_view_add_move_binding (binding_set, GDK_KP_End, 0,
847                                   GTK_MOVEMENT_BUFFER_ENDS, 1);
848
849   gtk_tree_view_add_move_binding (binding_set, GDK_Page_Up, 0,
850                                   GTK_MOVEMENT_PAGES, -1);
851   gtk_tree_view_add_move_binding (binding_set, GDK_KP_Page_Up, 0,
852                                   GTK_MOVEMENT_PAGES, -1);
853
854   gtk_tree_view_add_move_binding (binding_set, GDK_Page_Down, 0,
855                                   GTK_MOVEMENT_PAGES, 1);
856   gtk_tree_view_add_move_binding (binding_set, GDK_KP_Page_Down, 0,
857                                   GTK_MOVEMENT_PAGES, 1);
858
859
860   gtk_binding_entry_add_signal (binding_set, GDK_Right, 0, "move_cursor", 2,
861                                 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
862                                 G_TYPE_INT, 1);
863
864   gtk_binding_entry_add_signal (binding_set, GDK_Left, 0, "move_cursor", 2,
865                                 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
866                                 G_TYPE_INT, -1);
867
868   gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0, "move_cursor", 2,
869                                 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
870                                 G_TYPE_INT, 1);
871
872   gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0, "move_cursor", 2,
873                                 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
874                                 G_TYPE_INT, -1);
875
876   gtk_binding_entry_add_signal (binding_set, GDK_Right, GDK_CONTROL_MASK,
877                                 "move_cursor", 2,
878                                 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
879                                 G_TYPE_INT, 1);
880
881   gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_CONTROL_MASK,
882                                 "move_cursor", 2,
883                                 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
884                                 G_TYPE_INT, -1);
885
886   gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, GDK_CONTROL_MASK,
887                                 "move_cursor", 2,
888                                 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
889                                 G_TYPE_INT, 1);
890
891   gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, GDK_CONTROL_MASK,
892                                 "move_cursor", 2,
893                                 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
894                                 G_TYPE_INT, -1);
895
896   gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK, "toggle_cursor_row", 0);
897
898   gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK, "select_all", 0);
899   gtk_binding_entry_add_signal (binding_set, GDK_slash, GDK_CONTROL_MASK, "select_all", 0);
900
901   gtk_binding_entry_add_signal (binding_set, GDK_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "unselect_all", 0);
902   gtk_binding_entry_add_signal (binding_set, GDK_backslash, GDK_CONTROL_MASK, "unselect_all", 0);
903
904   gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_SHIFT_MASK, "select_cursor_row", 1,
905                                 G_TYPE_BOOLEAN, TRUE);
906
907   gtk_binding_entry_add_signal (binding_set, GDK_space, 0, "select_cursor_row", 1,
908                                 G_TYPE_BOOLEAN, TRUE);
909   gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "select_cursor_row", 1,
910                                 G_TYPE_BOOLEAN, TRUE);
911   gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0, "select_cursor_row", 1,
912                                 G_TYPE_BOOLEAN, TRUE);
913   gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "select_cursor_row", 1,
914                                 G_TYPE_BOOLEAN, TRUE);
915
916   /* expand and collapse rows */
917   gtk_binding_entry_add_signal (binding_set, GDK_plus, 0, "expand_collapse_cursor_row", 3,
918                                 G_TYPE_BOOLEAN, FALSE,
919                                 G_TYPE_BOOLEAN, TRUE,
920                                 G_TYPE_BOOLEAN, FALSE);
921   /* Not doable on US keyboards */
922   gtk_binding_entry_add_signal (binding_set, GDK_plus, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
923                                 G_TYPE_BOOLEAN, FALSE,
924                                 G_TYPE_BOOLEAN, TRUE,
925                                 G_TYPE_BOOLEAN, TRUE);
926   gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, 0, "expand_collapse_cursor_row", 3,
927                                 G_TYPE_BOOLEAN, FALSE,
928                                 G_TYPE_BOOLEAN, TRUE,
929                                 G_TYPE_BOOLEAN, FALSE);
930   gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
931                                 G_TYPE_BOOLEAN, FALSE,
932                                 G_TYPE_BOOLEAN, TRUE,
933                                 G_TYPE_BOOLEAN, TRUE);
934   gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
935                                 G_TYPE_BOOLEAN, FALSE,
936                                 G_TYPE_BOOLEAN, TRUE,
937                                 G_TYPE_BOOLEAN, TRUE);
938   gtk_binding_entry_add_signal (binding_set, GDK_Right, GDK_SHIFT_MASK,
939                                 "expand_collapse_cursor_row", 3,
940                                 G_TYPE_BOOLEAN, TRUE,
941                                 G_TYPE_BOOLEAN, TRUE,
942                                 G_TYPE_BOOLEAN, TRUE);
943   gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, GDK_SHIFT_MASK,
944                                 "expand_collapse_cursor_row", 3,
945                                 G_TYPE_BOOLEAN, TRUE,
946                                 G_TYPE_BOOLEAN, TRUE,
947                                 G_TYPE_BOOLEAN, TRUE);
948   gtk_binding_entry_add_signal (binding_set, GDK_Right,
949                                 GDK_CONTROL_MASK | GDK_SHIFT_MASK,
950                                 "expand_collapse_cursor_row", 3,
951                                 G_TYPE_BOOLEAN, TRUE,
952                                 G_TYPE_BOOLEAN, TRUE,
953                                 G_TYPE_BOOLEAN, TRUE);
954   gtk_binding_entry_add_signal (binding_set, GDK_KP_Right,
955                                 GDK_CONTROL_MASK | GDK_SHIFT_MASK,
956                                 "expand_collapse_cursor_row", 3,
957                                 G_TYPE_BOOLEAN, TRUE,
958                                 G_TYPE_BOOLEAN, TRUE,
959                                 G_TYPE_BOOLEAN, TRUE);
960
961   gtk_binding_entry_add_signal (binding_set, GDK_minus, 0, "expand_collapse_cursor_row", 3,
962                                 G_TYPE_BOOLEAN, FALSE,
963                                 G_TYPE_BOOLEAN, FALSE,
964                                 G_TYPE_BOOLEAN, FALSE);
965   gtk_binding_entry_add_signal (binding_set, GDK_minus, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
966                                 G_TYPE_BOOLEAN, FALSE,
967                                 G_TYPE_BOOLEAN, FALSE,
968                                 G_TYPE_BOOLEAN, TRUE);
969   gtk_binding_entry_add_signal (binding_set, GDK_KP_Subtract, 0, "expand_collapse_cursor_row", 3,
970                                 G_TYPE_BOOLEAN, FALSE,
971                                 G_TYPE_BOOLEAN, FALSE,
972                                 G_TYPE_BOOLEAN, FALSE);
973   gtk_binding_entry_add_signal (binding_set, GDK_KP_Subtract, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
974                                 G_TYPE_BOOLEAN, FALSE,
975                                 G_TYPE_BOOLEAN, FALSE,
976                                 G_TYPE_BOOLEAN, TRUE);
977   gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_SHIFT_MASK,
978                                 "expand_collapse_cursor_row", 3,
979                                 G_TYPE_BOOLEAN, FALSE,
980                                 G_TYPE_BOOLEAN, FALSE,
981                                 G_TYPE_BOOLEAN, TRUE);
982   gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, GDK_SHIFT_MASK,
983                                 "expand_collapse_cursor_row", 3,
984                                 G_TYPE_BOOLEAN, FALSE,
985                                 G_TYPE_BOOLEAN, FALSE,
986                                 G_TYPE_BOOLEAN, TRUE);
987   gtk_binding_entry_add_signal (binding_set, GDK_Left,
988                                 GDK_CONTROL_MASK | GDK_SHIFT_MASK,
989                                 "expand_collapse_cursor_row", 3,
990                                 G_TYPE_BOOLEAN, FALSE,
991                                 G_TYPE_BOOLEAN, FALSE,
992                                 G_TYPE_BOOLEAN, TRUE);
993   gtk_binding_entry_add_signal (binding_set, GDK_KP_Left,
994                                 GDK_CONTROL_MASK | GDK_SHIFT_MASK,
995                                 "expand_collapse_cursor_row", 3,
996                                 G_TYPE_BOOLEAN, FALSE,
997                                 G_TYPE_BOOLEAN, FALSE,
998                                 G_TYPE_BOOLEAN, TRUE);
999
1000   gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0, "select_cursor_parent", 0);
1001
1002   gtk_binding_entry_add_signal (binding_set, GDK_f, GDK_CONTROL_MASK, "start_interactive_search", 0);
1003
1004   gtk_binding_entry_add_signal (binding_set, GDK_F, GDK_CONTROL_MASK, "start_interactive_search", 0);
1005 }
1006
1007 static void
1008 gtk_tree_view_init (GtkTreeView *tree_view)
1009 {
1010   tree_view->priv = g_new0 (GtkTreeViewPrivate, 1);
1011   GTK_WIDGET_SET_FLAGS (tree_view, GTK_CAN_FOCUS);
1012
1013   gtk_widget_set_redraw_on_allocate (GTK_WIDGET (tree_view), FALSE);
1014
1015   tree_view->priv->flags = GTK_TREE_VIEW_IS_LIST | GTK_TREE_VIEW_SHOW_EXPANDERS | GTK_TREE_VIEW_DRAW_KEYFOCUS | GTK_TREE_VIEW_HEADERS_VISIBLE;
1016
1017   /* We need some padding */
1018   tree_view->priv->dy = 0;
1019   tree_view->priv->n_columns = 0;
1020   tree_view->priv->header_height = 1;
1021   tree_view->priv->x_drag = 0;
1022   tree_view->priv->drag_pos = -1;
1023   tree_view->priv->header_has_focus = FALSE;
1024   tree_view->priv->pressed_button = -1;
1025   tree_view->priv->press_start_x = -1;
1026   tree_view->priv->press_start_y = -1;
1027   tree_view->priv->reorderable = FALSE;
1028   tree_view->priv->presize_handler_timer = 0;
1029   tree_view->priv->scroll_sync_timer = 0;
1030   tree_view->priv->fixed_height_check = 0;
1031   gtk_tree_view_set_adjustments (tree_view, NULL, NULL);
1032   tree_view->priv->selection = _gtk_tree_selection_new_with_tree_view (tree_view);
1033   tree_view->priv->enable_search = TRUE;
1034   tree_view->priv->search_column = -1;
1035   tree_view->priv->search_dialog_position_func = gtk_tree_view_search_position_func;
1036   tree_view->priv->search_equal_func = gtk_tree_view_search_equal_func;
1037 }
1038
1039 \f
1040
1041 /* GObject Methods
1042  */
1043
1044 static void
1045 gtk_tree_view_set_property (GObject         *object,
1046                             guint            prop_id,
1047                             const GValue    *value,
1048                             GParamSpec      *pspec)
1049 {
1050   GtkTreeView *tree_view;
1051
1052   tree_view = GTK_TREE_VIEW (object);
1053
1054   switch (prop_id)
1055     {
1056     case PROP_MODEL:
1057       gtk_tree_view_set_model (tree_view, g_value_get_object (value));
1058       break;
1059     case PROP_HADJUSTMENT:
1060       gtk_tree_view_set_hadjustment (tree_view, g_value_get_object (value));
1061       break;
1062     case PROP_VADJUSTMENT:
1063       gtk_tree_view_set_vadjustment (tree_view, g_value_get_object (value));
1064       break;
1065     case PROP_HEADERS_VISIBLE:
1066       gtk_tree_view_set_headers_visible (tree_view, g_value_get_boolean (value));
1067       break;
1068     case PROP_HEADERS_CLICKABLE:
1069       gtk_tree_view_set_headers_clickable (tree_view, g_value_get_boolean (value));
1070       break;
1071     case PROP_EXPANDER_COLUMN:
1072       gtk_tree_view_set_expander_column (tree_view, g_value_get_object (value));
1073       break;
1074     case PROP_REORDERABLE:
1075       gtk_tree_view_set_reorderable (tree_view, g_value_get_boolean (value));
1076       break;
1077     case PROP_RULES_HINT:
1078       gtk_tree_view_set_rules_hint (tree_view, g_value_get_boolean (value));
1079       break;
1080     case PROP_ENABLE_SEARCH:
1081       gtk_tree_view_set_enable_search (tree_view, g_value_get_boolean (value));
1082       break;
1083     case PROP_SEARCH_COLUMN:
1084       gtk_tree_view_set_search_column (tree_view, g_value_get_int (value));
1085       break;
1086     default:
1087       break;
1088     }
1089 }
1090
1091 static void
1092 gtk_tree_view_get_property (GObject    *object,
1093                             guint       prop_id,
1094                             GValue     *value,
1095                             GParamSpec *pspec)
1096 {
1097   GtkTreeView *tree_view;
1098
1099   tree_view = GTK_TREE_VIEW (object);
1100
1101   switch (prop_id)
1102     {
1103     case PROP_MODEL:
1104       g_value_set_object (value, tree_view->priv->model);
1105       break;
1106     case PROP_HADJUSTMENT:
1107       g_value_set_object (value, tree_view->priv->hadjustment);
1108       break;
1109     case PROP_VADJUSTMENT:
1110       g_value_set_object (value, tree_view->priv->vadjustment);
1111       break;
1112     case PROP_HEADERS_VISIBLE:
1113       g_value_set_boolean (value, gtk_tree_view_get_headers_visible (tree_view));
1114       break;
1115     case PROP_EXPANDER_COLUMN:
1116       g_value_set_object (value, tree_view->priv->expander_column);
1117       break;
1118     case PROP_REORDERABLE:
1119       g_value_set_boolean (value, tree_view->priv->reorderable);
1120       break;
1121     case PROP_RULES_HINT:
1122       g_value_set_boolean (value, tree_view->priv->has_rules);
1123       break;
1124     case PROP_ENABLE_SEARCH:
1125       g_value_set_boolean (value, tree_view->priv->enable_search);
1126       break;
1127     case PROP_SEARCH_COLUMN:
1128       g_value_set_int (value, tree_view->priv->search_column);
1129       break;
1130     default:
1131       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1132       break;
1133     }
1134 }
1135
1136 static void
1137 gtk_tree_view_finalize (GObject *object)
1138 {
1139   GtkTreeView *tree_view = (GtkTreeView *) object;
1140
1141   g_free (tree_view->priv);
1142
1143   if (G_OBJECT_CLASS (parent_class)->finalize)
1144     (* G_OBJECT_CLASS (parent_class)->finalize) (object);
1145 }
1146
1147 \f
1148
1149 /* GtkObject Methods
1150  */
1151
1152 static void
1153 gtk_tree_view_destroy (GtkObject *object)
1154 {
1155   GtkTreeView *tree_view = GTK_TREE_VIEW (object);
1156   GtkWidget *search_dialog;
1157   GList *list;
1158
1159   gtk_tree_view_stop_editing (tree_view, TRUE);
1160
1161   if (tree_view->priv->columns != NULL)
1162     {
1163       list = tree_view->priv->columns;
1164       while (list)
1165         {
1166           GtkTreeViewColumn *column;
1167           column = GTK_TREE_VIEW_COLUMN (list->data);
1168           list = list->next;
1169           gtk_tree_view_remove_column (tree_view, column);
1170         }
1171       tree_view->priv->columns = NULL;
1172     }
1173
1174   if (tree_view->priv->tree != NULL)
1175     {
1176       gtk_tree_view_unref_and_check_selection_tree (tree_view, tree_view->priv->tree);
1177       _gtk_rbtree_free (tree_view->priv->tree);
1178       tree_view->priv->tree = NULL;
1179     }
1180
1181   if (tree_view->priv->selection != NULL)
1182     {
1183       _gtk_tree_selection_set_tree_view (tree_view->priv->selection, NULL);
1184       g_object_unref (tree_view->priv->selection);
1185       tree_view->priv->selection = NULL;
1186     }
1187
1188   if (tree_view->priv->scroll_to_path != NULL)
1189     {
1190       gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
1191       tree_view->priv->scroll_to_path = NULL;
1192     }
1193
1194   if (tree_view->priv->drag_dest_row != NULL)
1195     {
1196       gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
1197       tree_view->priv->drag_dest_row = NULL;
1198     }
1199
1200   if (tree_view->priv->last_button_press != NULL)
1201     {
1202       gtk_tree_row_reference_free (tree_view->priv->last_button_press);
1203       tree_view->priv->last_button_press = NULL;
1204     }
1205
1206   if (tree_view->priv->last_button_press_2 != NULL)
1207     {
1208       gtk_tree_row_reference_free (tree_view->priv->last_button_press_2);
1209       tree_view->priv->last_button_press_2 = NULL;
1210     }
1211
1212   if (tree_view->priv->top_row != NULL)
1213     {
1214       gtk_tree_row_reference_free (tree_view->priv->top_row);
1215       tree_view->priv->top_row = NULL;
1216     }
1217
1218   if (tree_view->priv->column_drop_func_data &&
1219       tree_view->priv->column_drop_func_data_destroy)
1220     {
1221       (* tree_view->priv->column_drop_func_data_destroy) (tree_view->priv->column_drop_func_data);
1222       tree_view->priv->column_drop_func_data = NULL;
1223     }
1224
1225   if (tree_view->priv->destroy_count_destroy &&
1226       tree_view->priv->destroy_count_data)
1227     {
1228       (* tree_view->priv->destroy_count_destroy) (tree_view->priv->destroy_count_data);
1229       tree_view->priv->destroy_count_data = NULL;
1230     }
1231
1232   gtk_tree_row_reference_free (tree_view->priv->cursor);
1233   tree_view->priv->cursor = NULL;
1234
1235   gtk_tree_row_reference_free (tree_view->priv->anchor);
1236   tree_view->priv->anchor = NULL;
1237
1238   /* destroy interactive search dialog */
1239   search_dialog = g_object_get_data (G_OBJECT (tree_view),
1240                                      GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
1241   if (search_dialog)
1242     gtk_tree_view_search_dialog_destroy (search_dialog,
1243                                          tree_view);
1244
1245   if (tree_view->priv->search_destroy)
1246     {
1247       (* tree_view->priv->search_destroy) (tree_view->priv->search_user_data);
1248       tree_view->priv->search_user_data = NULL;
1249     }
1250
1251   gtk_tree_view_set_model (tree_view, NULL);
1252
1253   if (GTK_OBJECT_CLASS (parent_class)->destroy)
1254     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
1255 }
1256
1257 \f
1258
1259 /* GtkWidget Methods
1260  */
1261
1262 /* GtkWidget::map helper */
1263 static void
1264 gtk_tree_view_map_buttons (GtkTreeView *tree_view)
1265 {
1266   GList *list;
1267
1268   g_return_if_fail (GTK_WIDGET_MAPPED (tree_view));
1269
1270   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE))
1271     {
1272       GtkTreeViewColumn *column;
1273
1274       for (list = tree_view->priv->columns; list; list = list->next)
1275         {
1276           column = list->data;
1277           if (GTK_WIDGET_VISIBLE (column->button) &&
1278               !GTK_WIDGET_MAPPED (column->button))
1279             gtk_widget_map (column->button);
1280         }
1281       for (list = tree_view->priv->columns; list; list = list->next)
1282         {
1283           column = list->data;
1284           if (column->visible == FALSE)
1285             continue;
1286           if (column->resizable)
1287             {
1288               gdk_window_raise (column->window);
1289               gdk_window_show (column->window);
1290             }
1291           else
1292             gdk_window_hide (column->window);
1293         }
1294       gdk_window_show (tree_view->priv->header_window);
1295     }
1296 }
1297
1298 static void
1299 gtk_tree_view_map (GtkWidget *widget)
1300 {
1301   GList *tmp_list;
1302   GtkTreeView *tree_view;
1303
1304   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
1305
1306   tree_view = GTK_TREE_VIEW (widget);
1307
1308   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1309
1310   tmp_list = tree_view->priv->children;
1311   while (tmp_list)
1312     {
1313       GtkTreeViewChild *child = tmp_list->data;
1314       tmp_list = tmp_list->next;
1315
1316       if (GTK_WIDGET_VISIBLE (child->widget))
1317         {
1318           if (!GTK_WIDGET_MAPPED (child->widget))
1319             gtk_widget_map (child->widget);
1320         }
1321     }
1322   gdk_window_show (tree_view->priv->bin_window);
1323
1324   gtk_tree_view_map_buttons (tree_view);
1325
1326   gdk_window_show (widget->window);
1327 }
1328
1329 static void
1330 gtk_tree_view_realize (GtkWidget *widget)
1331 {
1332   GList *tmp_list;
1333   GtkTreeView *tree_view;
1334   GdkGCValues values;
1335   GdkWindowAttr attributes;
1336   gint attributes_mask;
1337
1338   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
1339
1340   tree_view = GTK_TREE_VIEW (widget);
1341
1342   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1343
1344   /* Make the main, clipping window */
1345   attributes.window_type = GDK_WINDOW_CHILD;
1346   attributes.x = widget->allocation.x;
1347   attributes.y = widget->allocation.y;
1348   attributes.width = widget->allocation.width;
1349   attributes.height = widget->allocation.height;
1350   attributes.wclass = GDK_INPUT_OUTPUT;
1351   attributes.visual = gtk_widget_get_visual (widget);
1352   attributes.colormap = gtk_widget_get_colormap (widget);
1353   attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
1354
1355   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1356
1357   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
1358                                    &attributes, attributes_mask);
1359   gdk_window_set_user_data (widget->window, widget);
1360
1361   /* Make the window for the tree */
1362   attributes.x = 0;
1363   attributes.y = TREE_VIEW_HEADER_HEIGHT (tree_view);
1364   attributes.width = tree_view->priv->width;
1365   attributes.height = widget->allocation.height;
1366   attributes.event_mask = GDK_EXPOSURE_MASK |
1367     GDK_SCROLL_MASK |
1368     GDK_POINTER_MOTION_MASK |
1369     GDK_ENTER_NOTIFY_MASK |
1370     GDK_LEAVE_NOTIFY_MASK |
1371     GDK_BUTTON_PRESS_MASK |
1372     GDK_BUTTON_RELEASE_MASK |
1373     gtk_widget_get_events (widget);
1374
1375   tree_view->priv->bin_window = gdk_window_new (widget->window,
1376                                                 &attributes, attributes_mask);
1377   gdk_window_set_user_data (tree_view->priv->bin_window, widget);
1378
1379   /* Make the column header window */
1380   attributes.x = 0;
1381   attributes.y = 0;
1382   attributes.width = MAX (tree_view->priv->width, widget->allocation.width);
1383   attributes.height = tree_view->priv->header_height;
1384   attributes.event_mask = (GDK_EXPOSURE_MASK |
1385                            GDK_SCROLL_MASK |
1386                            GDK_BUTTON_PRESS_MASK |
1387                            GDK_BUTTON_RELEASE_MASK |
1388                            GDK_KEY_PRESS_MASK |
1389                            GDK_KEY_RELEASE_MASK) |
1390     gtk_widget_get_events (widget);
1391
1392   tree_view->priv->header_window = gdk_window_new (widget->window,
1393                                                    &attributes, attributes_mask);
1394   gdk_window_set_user_data (tree_view->priv->header_window, widget);
1395
1396
1397   values.foreground = (widget->style->white.pixel==0 ?
1398                        widget->style->black:widget->style->white);
1399   values.function = GDK_XOR;
1400   values.subwindow_mode = GDK_INCLUDE_INFERIORS;
1401
1402   /* Add them all up. */
1403   widget->style = gtk_style_attach (widget->style, widget->window);
1404   gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
1405   gdk_window_set_background (tree_view->priv->bin_window, &widget->style->base[widget->state]);
1406   gtk_style_set_background (widget->style, tree_view->priv->header_window, GTK_STATE_NORMAL);
1407
1408   tmp_list = tree_view->priv->children;
1409   while (tmp_list)
1410     {
1411       GtkTreeViewChild *child = tmp_list->data;
1412       tmp_list = tmp_list->next;
1413
1414       gtk_widget_set_parent_window (child->widget, tree_view->priv->bin_window);
1415     }
1416
1417   for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
1418     _gtk_tree_view_column_realize_button (GTK_TREE_VIEW_COLUMN (tmp_list->data));
1419
1420   install_presize_handler (tree_view); 
1421 }
1422
1423 static void
1424 gtk_tree_view_unrealize (GtkWidget *widget)
1425 {
1426   GtkTreeView *tree_view;
1427   GList *list;
1428
1429   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
1430
1431   tree_view = GTK_TREE_VIEW (widget);
1432
1433   if (tree_view->priv->scroll_timeout != 0)
1434     {
1435       g_source_remove (tree_view->priv->scroll_timeout);
1436       tree_view->priv->scroll_timeout = 0;
1437     }
1438
1439   if (tree_view->priv->open_dest_timeout != 0)
1440     {
1441       g_source_remove (tree_view->priv->open_dest_timeout);
1442       tree_view->priv->open_dest_timeout = 0;
1443     }
1444
1445   if (tree_view->priv->expand_collapse_timeout != 0)
1446     {
1447       g_source_remove (tree_view->priv->expand_collapse_timeout);
1448       tree_view->priv->expand_collapse_timeout = 0;
1449     }
1450   
1451   if (tree_view->priv->presize_handler_timer != 0)
1452     {
1453       g_source_remove (tree_view->priv->presize_handler_timer);
1454       tree_view->priv->presize_handler_timer = 0;
1455     }
1456
1457   if (tree_view->priv->validate_rows_timer != 0)
1458     {
1459       g_source_remove (tree_view->priv->validate_rows_timer);
1460       tree_view->priv->validate_rows_timer = 0;
1461     }
1462
1463   if (tree_view->priv->scroll_sync_timer != 0)
1464     {
1465       g_source_remove (tree_view->priv->scroll_sync_timer);
1466       tree_view->priv->scroll_sync_timer = 0;
1467     }
1468
1469   for (list = tree_view->priv->columns; list; list = list->next)
1470     _gtk_tree_view_column_unrealize_button (GTK_TREE_VIEW_COLUMN (list->data));
1471
1472   gdk_window_set_user_data (tree_view->priv->bin_window, NULL);
1473   gdk_window_destroy (tree_view->priv->bin_window);
1474   tree_view->priv->bin_window = NULL;
1475
1476   gdk_window_set_user_data (tree_view->priv->header_window, NULL);
1477   gdk_window_destroy (tree_view->priv->header_window);
1478   tree_view->priv->header_window = NULL;
1479
1480   if (tree_view->priv->drag_window)
1481     {
1482       gdk_window_set_user_data (tree_view->priv->drag_window, NULL);
1483       gdk_window_destroy (tree_view->priv->drag_window);
1484       tree_view->priv->drag_window = NULL;
1485     }
1486
1487   if (tree_view->priv->drag_highlight_window)
1488     {
1489       gdk_window_set_user_data (tree_view->priv->drag_highlight_window, NULL);
1490       gdk_window_destroy (tree_view->priv->drag_highlight_window);
1491       tree_view->priv->drag_highlight_window = NULL;
1492     }
1493
1494   /* GtkWidget::unrealize destroys children and widget->window */
1495   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1496     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1497 }
1498
1499 /* GtkWidget::size_request helper */
1500 static void
1501 gtk_tree_view_size_request_columns (GtkTreeView *tree_view)
1502 {
1503   GList *list;
1504
1505   tree_view->priv->header_height = 0;
1506
1507   if (tree_view->priv->model)
1508     {
1509       for (list = tree_view->priv->columns; list; list = list->next)
1510         {
1511           GtkRequisition requisition;
1512           GtkTreeViewColumn *column = list->data;
1513
1514           if (column->button == NULL)
1515             continue;
1516
1517           column = list->data;
1518           
1519           gtk_widget_size_request (column->button, &requisition);
1520           column->button_request = requisition.width;
1521           tree_view->priv->header_height = MAX (tree_view->priv->header_height, requisition.height);
1522         }
1523     }
1524 }
1525
1526
1527 /* Called only by ::size_request */
1528 static void
1529 gtk_tree_view_update_size (GtkTreeView *tree_view)
1530 {
1531   GList *list;
1532   GtkTreeViewColumn *column;
1533   gint i;
1534
1535   if (tree_view->priv->model == NULL)
1536     {
1537       tree_view->priv->width = 0;
1538       tree_view->priv->height = 0;
1539       return;
1540     }
1541
1542   tree_view->priv->width = 0;
1543   /* keep this in sync with size_allocate below */
1544   for (list = tree_view->priv->columns, i = 0; list; list = list->next, i++)
1545     {
1546       gint real_requested_width = 0;
1547       column = list->data;
1548       if (!column->visible)
1549         continue;
1550
1551       if (column->use_resized_width)
1552         {
1553           real_requested_width = column->resized_width;
1554         }
1555       else if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
1556         {
1557           real_requested_width = column->fixed_width;
1558         }
1559       else if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE))
1560         {
1561           real_requested_width = MAX (column->requested_width, column->button_request);
1562         }
1563       else
1564         {
1565           real_requested_width = column->requested_width;
1566         }
1567
1568       if (column->min_width != -1)
1569         real_requested_width = MAX (real_requested_width, column->min_width);
1570       if (column->max_width != -1)
1571         real_requested_width = MIN (real_requested_width, column->max_width);
1572
1573       tree_view->priv->width += real_requested_width;
1574     }
1575
1576   if (tree_view->priv->tree == NULL)
1577     tree_view->priv->height = 0;
1578   else
1579     tree_view->priv->height = tree_view->priv->tree->root->offset;
1580 }
1581
1582 static void
1583 gtk_tree_view_size_request (GtkWidget      *widget,
1584                             GtkRequisition *requisition)
1585 {
1586   GtkTreeView *tree_view;
1587   GList *tmp_list;
1588
1589   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
1590
1591   tree_view = GTK_TREE_VIEW (widget);
1592
1593   /* we validate GTK_TREE_VIEW_NUM_ROWS_PER_IDLE rows initially just to make
1594    * sure we have some size. In practice, with a lot of static lists, this
1595    * should get a good width.
1596    */
1597   validate_rows (tree_view);
1598   gtk_tree_view_size_request_columns (tree_view);
1599   gtk_tree_view_update_size (GTK_TREE_VIEW (widget));
1600
1601   requisition->width = tree_view->priv->width;
1602   requisition->height = tree_view->priv->height + TREE_VIEW_HEADER_HEIGHT (tree_view);
1603
1604   tmp_list = tree_view->priv->children;
1605
1606   while (tmp_list)
1607     {
1608       GtkTreeViewChild *child = tmp_list->data;
1609       GtkRequisition child_requisition;
1610
1611       tmp_list = tmp_list->next;
1612
1613       if (GTK_WIDGET_VISIBLE (child->widget))
1614         gtk_widget_size_request (child->widget, &child_requisition);
1615     }
1616 }
1617
1618
1619 static void
1620 invalidate_column (GtkTreeView       *tree_view,
1621                    GtkTreeViewColumn *column)
1622 {
1623   gint column_offset = 0;
1624   GList *list;
1625   GtkWidget *widget = GTK_WIDGET (tree_view);
1626   gboolean rtl;
1627
1628   if (!GTK_WIDGET_REALIZED (widget))
1629     return;
1630
1631   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
1632   for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
1633        list;
1634        list = (rtl ? list->prev : list->next))
1635     {
1636       GtkTreeViewColumn *tmpcolumn = list->data;
1637       if (tmpcolumn == column)
1638         {
1639           GdkRectangle invalid_rect;
1640           
1641           invalid_rect.x = column_offset;
1642           invalid_rect.y = 0;
1643           invalid_rect.width = column->width;
1644           invalid_rect.height = widget->allocation.height;
1645           
1646           gdk_window_invalidate_rect (widget->window, &invalid_rect, TRUE);
1647           break;
1648         }
1649       
1650       column_offset += tmpcolumn->width;
1651     }
1652 }
1653
1654 static void
1655 invalidate_last_column (GtkTreeView *tree_view)
1656 {
1657   GList *last_column;
1658   gboolean rtl;
1659
1660   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
1661
1662   for (last_column = (rtl ? g_list_first (tree_view->priv->columns) : g_list_last (tree_view->priv->columns));
1663        last_column;
1664        last_column = (rtl ? last_column->next : last_column->prev))
1665     {
1666       if (GTK_TREE_VIEW_COLUMN (last_column->data)->visible)
1667         {
1668           invalidate_column (tree_view, last_column->data);
1669           return;
1670         }
1671     }
1672 }
1673
1674 static gint
1675 gtk_tree_view_get_real_requested_width_from_column (GtkTreeView       *tree_view,
1676                                                     GtkTreeViewColumn *column)
1677 {
1678   gint real_requested_width;
1679
1680   if (column->use_resized_width)
1681     {
1682       real_requested_width = column->resized_width;
1683     }
1684   else if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
1685     {
1686       real_requested_width = column->fixed_width;
1687     }
1688   else if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE))
1689     {
1690       real_requested_width = MAX (column->requested_width, column->button_request);
1691     }
1692   else
1693     {
1694       real_requested_width = column->requested_width;
1695       if (real_requested_width < 0)
1696         real_requested_width = 0;
1697     }
1698
1699   if (column->min_width != -1)
1700     real_requested_width = MAX (real_requested_width, column->min_width);
1701   if (column->max_width != -1)
1702     real_requested_width = MIN (real_requested_width, column->max_width);
1703
1704   return real_requested_width;
1705 }
1706
1707 /* GtkWidget::size_allocate helper */
1708 static void
1709 gtk_tree_view_size_allocate_columns (GtkWidget *widget)
1710 {
1711   GtkTreeView *tree_view;
1712   GList *list, *first_column, *last_column;
1713   GtkTreeViewColumn *column;
1714   GtkAllocation allocation;
1715   gint width = 0;
1716   gint extra, extra_per_column;
1717   gint full_requested_width = 0;
1718   gint number_of_expand_columns = 0;
1719   gboolean rtl;
1720   
1721   tree_view = GTK_TREE_VIEW (widget);
1722
1723   for (last_column = g_list_last (tree_view->priv->columns);
1724        last_column && !(GTK_TREE_VIEW_COLUMN (last_column->data)->visible);
1725        last_column = last_column->prev)
1726     ;
1727   if (last_column == NULL)
1728     return;
1729
1730   for (first_column = g_list_first (tree_view->priv->columns);
1731        first_column && !(GTK_TREE_VIEW_COLUMN (first_column->data)->visible);
1732        first_column = first_column->next)
1733     ;
1734
1735   allocation.y = 0;
1736   allocation.height = tree_view->priv->header_height;
1737
1738   rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
1739
1740   /* find out how many extra space and expandable columns we have */
1741   for (list = tree_view->priv->columns; list != last_column->next; list = list->next)
1742     {
1743       column = (GtkTreeViewColumn *)list->data;
1744
1745       if (!column->visible)
1746         continue;
1747
1748       full_requested_width += gtk_tree_view_get_real_requested_width_from_column (tree_view, column);
1749
1750       if (column->expand)
1751         number_of_expand_columns++;
1752     }
1753
1754   extra = MAX (widget->allocation.width - full_requested_width, 0);
1755   if (number_of_expand_columns > 0)
1756     extra_per_column = extra/number_of_expand_columns;
1757   else
1758     extra_per_column = 0;
1759
1760   for (list = (rtl ? last_column : first_column); 
1761        list != (rtl ? first_column->prev : last_column->next);
1762        list = (rtl ? list->prev : list->next)) 
1763     {
1764       gint real_requested_width = 0;
1765       gint old_width;
1766
1767       column = list->data;
1768       old_width = column->width;
1769
1770       if (!column->visible)
1771         continue;
1772
1773       /* We need to handle the dragged button specially.
1774        */
1775       if (column == tree_view->priv->drag_column)
1776         {
1777           GtkAllocation drag_allocation;
1778           gdk_drawable_get_size (tree_view->priv->drag_window,
1779                                  &(drag_allocation.width),
1780                                  &(drag_allocation.height));
1781           drag_allocation.x = 0;
1782           drag_allocation.y = 0;
1783           gtk_widget_size_allocate (tree_view->priv->drag_column->button,
1784                                     &drag_allocation);
1785           width += drag_allocation.width;
1786           continue;
1787         }
1788
1789       real_requested_width = gtk_tree_view_get_real_requested_width_from_column (tree_view, column);
1790
1791       allocation.x = width;
1792       column->width = real_requested_width;
1793
1794       if (column->expand)
1795         {
1796           if (number_of_expand_columns == 1)
1797             {
1798               /* We add the remander to the last column as
1799                * */
1800               column->width += extra;
1801             }
1802           else
1803             {
1804               column->width += extra_per_column;
1805               extra -= extra_per_column;
1806               number_of_expand_columns --;
1807             }
1808         }
1809       else if (number_of_expand_columns == 0 &&
1810                list == last_column)
1811         {
1812           column->width += extra;
1813         }
1814
1815       g_object_notify (G_OBJECT (column), "width");
1816
1817       allocation.width = column->width;
1818       width += column->width;
1819
1820       if (column->width > old_width)
1821         invalidate_column (tree_view, column);
1822
1823       gtk_widget_size_allocate (column->button, &allocation);
1824
1825       if (column->window)
1826         gdk_window_move_resize (column->window,
1827                                 allocation.x + allocation.width - TREE_VIEW_DRAG_WIDTH/2,
1828                                 allocation.y,
1829                                 TREE_VIEW_DRAG_WIDTH, allocation.height);
1830     }
1831 }
1832
1833
1834 static void
1835 gtk_tree_view_size_allocate (GtkWidget     *widget,
1836                              GtkAllocation *allocation)
1837 {
1838   GList *tmp_list;
1839   GtkTreeView *tree_view;
1840   gboolean width_changed = FALSE;
1841   gboolean dy_changed = FALSE;
1842
1843   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
1844
1845   if (allocation->width != widget->allocation.width)
1846     width_changed = TRUE;
1847   
1848   widget->allocation = *allocation;
1849
1850   tree_view = GTK_TREE_VIEW (widget);
1851
1852   tmp_list = tree_view->priv->children;
1853
1854   while (tmp_list)
1855     {
1856       GtkAllocation allocation;
1857
1858       GtkTreeViewChild *child = tmp_list->data;
1859       tmp_list = tmp_list->next;
1860
1861       /* totally ignore our childs requisition */
1862       allocation.x = child->x;
1863       allocation.y = child->y;
1864       allocation.width = child->width;
1865       allocation.height = child->height;
1866       gtk_widget_size_allocate (child->widget, &allocation);
1867     }
1868
1869
1870   tree_view->priv->hadjustment->page_size = allocation->width;
1871   tree_view->priv->hadjustment->page_increment = allocation->width * 0.9;
1872   tree_view->priv->hadjustment->step_increment = allocation->width * 0.1;
1873   tree_view->priv->hadjustment->lower = 0;
1874   tree_view->priv->hadjustment->upper = MAX (tree_view->priv->hadjustment->page_size, tree_view->priv->width);
1875
1876   if (tree_view->priv->hadjustment->value + allocation->width > tree_view->priv->width)
1877     tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
1878   gtk_adjustment_changed (tree_view->priv->hadjustment);
1879
1880   tree_view->priv->vadjustment->page_size = allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view);
1881   tree_view->priv->vadjustment->step_increment = tree_view->priv->vadjustment->page_size * 0.1;
1882   tree_view->priv->vadjustment->page_increment = tree_view->priv->vadjustment->page_size * 0.9;
1883   tree_view->priv->vadjustment->lower = 0;
1884   tree_view->priv->vadjustment->upper = MAX (tree_view->priv->vadjustment->page_size, tree_view->priv->height);
1885
1886   if (tree_view->priv->vadjustment->value + allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view) > tree_view->priv->height)
1887     {
1888       dy_changed = TRUE;
1889       gtk_adjustment_set_value (tree_view->priv->vadjustment,
1890                                 MAX (tree_view->priv->height - tree_view->priv->vadjustment->page_size, 0));
1891     }
1892
1893   gtk_adjustment_changed (tree_view->priv->vadjustment);
1894   
1895   if (GTK_WIDGET_REALIZED (widget))
1896     {
1897       gdk_window_move_resize (widget->window,
1898                               allocation->x, allocation->y,
1899                               allocation->width, allocation->height);
1900       gdk_window_move_resize (tree_view->priv->header_window,
1901                               - (gint) tree_view->priv->hadjustment->value,
1902                               0,
1903                               MAX (tree_view->priv->width, allocation->width),
1904                               tree_view->priv->header_height);
1905       gdk_window_move_resize (tree_view->priv->bin_window,
1906                               - (gint) tree_view->priv->hadjustment->value,
1907                               TREE_VIEW_HEADER_HEIGHT (tree_view),
1908                               MAX (tree_view->priv->width, allocation->width),
1909                               allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view));
1910     }
1911
1912   gtk_tree_view_size_allocate_columns (widget);
1913
1914   if (GTK_WIDGET_REALIZED (widget))
1915     {
1916       gboolean has_expand_column = FALSE;
1917       for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
1918         {
1919           if (gtk_tree_view_column_get_expand (GTK_TREE_VIEW_COLUMN (tmp_list->data)))
1920             {
1921               has_expand_column = TRUE;
1922               break;
1923             }
1924         }
1925
1926       /* This little hack only works if we have an LTR locale, and no column has the  */
1927       if (width_changed)
1928         {
1929           if (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_LTR &&
1930               ! has_expand_column)
1931             invalidate_last_column (tree_view);
1932           else
1933             gtk_widget_queue_draw (widget);
1934         }
1935       
1936       if (dy_changed)
1937         gtk_widget_queue_draw (widget);
1938     }
1939 }
1940
1941 static gboolean
1942 gtk_tree_view_button_press (GtkWidget      *widget,
1943                             GdkEventButton *event)
1944 {
1945   GtkTreeView *tree_view;
1946   GList *list;
1947   GtkTreeViewColumn *column = NULL;
1948   gint i;
1949   GdkRectangle background_area;
1950   GdkRectangle cell_area;
1951   gint vertical_separator;
1952   gint horizontal_separator;
1953
1954   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
1955   g_return_val_if_fail (event != NULL, FALSE);
1956
1957   tree_view = GTK_TREE_VIEW (widget);
1958   gtk_tree_view_stop_editing (tree_view, FALSE);
1959   gtk_widget_style_get (widget,
1960                         "vertical_separator", &vertical_separator,
1961                         "horizontal_separator", &horizontal_separator,
1962                         NULL);
1963
1964   /* put this separate, because the user might remove the latest
1965    * treeview node in the focus-in-event callback. If so, the code
1966    * flow won't enter the second if.
1967    */
1968   if (event->window == tree_view->priv->bin_window &&
1969       tree_view->priv->tree != NULL)
1970     {
1971       if (!GTK_WIDGET_HAS_FOCUS (widget))
1972         gtk_widget_grab_focus (widget);
1973       GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
1974     }
1975
1976   if (event->window == tree_view->priv->bin_window &&
1977       tree_view->priv->tree != NULL)
1978     {
1979       GtkRBNode *node;
1980       GtkRBTree *tree;
1981       GtkTreePath *path;
1982       gchar *path_string;
1983       gint depth;
1984       gint new_y;
1985       gint y_offset;
1986       gint dval;
1987       gint pre_val, aft_val;
1988       GtkTreeViewColumn *column = NULL;
1989       GtkCellRenderer *focus_cell = NULL;
1990       gint column_handled_click = FALSE;
1991       gboolean emit_row_activated = FALSE;
1992       gboolean rtl;
1993
1994       /* are we in an arrow? */
1995       if (tree_view->priv->prelight_node &&
1996           GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
1997         {
1998           if (event->button == 1)
1999             {
2000               gtk_grab_add (widget);
2001               tree_view->priv->button_pressed_node = tree_view->priv->prelight_node;
2002               tree_view->priv->button_pressed_tree = tree_view->priv->prelight_tree;
2003               gtk_tree_view_draw_arrow (GTK_TREE_VIEW (widget),
2004                                         tree_view->priv->prelight_tree,
2005                                         tree_view->priv->prelight_node,
2006                                         event->x,
2007                                         event->y);
2008             }
2009           return TRUE;
2010         }
2011
2012       /* find the node that was clicked */
2013       new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
2014       if (new_y < 0)
2015         new_y = 0;
2016       y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
2017
2018       if (node == NULL)
2019         /* We clicked in dead space */
2020         return TRUE;
2021
2022       /* Get the path and the node */
2023       path = _gtk_tree_view_find_path (tree_view, tree, node);
2024       depth = gtk_tree_path_get_depth (path);
2025       background_area.y = y_offset + event->y;
2026       background_area.height = MAX (GTK_RBNODE_GET_HEIGHT (node),
2027                                     tree_view->priv->expander_size);
2028       background_area.x = 0;
2029
2030       /* Let the column have a chance at selecting it. */
2031       rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
2032       for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
2033            list; list = (rtl ? list->prev : list->next))
2034         {
2035           column = list->data;
2036
2037           if (!column->visible)
2038             continue;
2039
2040           background_area.width = column->width;
2041           if ((background_area.x > (gint) event->x) ||
2042               (background_area.x + background_area.width <= (gint) event->x))
2043             {
2044               background_area.x += background_area.width;
2045               continue;
2046             }
2047
2048           /* we found the focus column */
2049           cell_area = background_area;
2050           cell_area.width -= horizontal_separator;
2051           cell_area.height -= vertical_separator;
2052           cell_area.x += horizontal_separator/2;
2053           cell_area.y += vertical_separator/2;
2054           if (gtk_tree_view_is_expander_column (tree_view, column) &&
2055               TREE_VIEW_DRAW_EXPANDERS(tree_view))
2056             {
2057               cell_area.x += depth * tree_view->priv->expander_size;
2058               cell_area.width -= depth * tree_view->priv->expander_size;
2059             }
2060           break;
2061         }
2062
2063       if (column == NULL)
2064         {
2065           gtk_tree_path_free (path);
2066
2067           return FALSE;
2068         }
2069
2070       tree_view->priv->focus_column = column;
2071
2072       /* decide if we edit */
2073       if (event->type == GDK_BUTTON_PRESS &&
2074           !(event->state & gtk_accelerator_get_default_mod_mask ()))
2075         {
2076           GtkTreePath *anchor;
2077           GtkTreeIter iter;
2078
2079           if (tree_view->priv->anchor)
2080             {
2081               anchor = gtk_tree_row_reference_get_path (tree_view->priv->anchor);
2082               gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
2083               gtk_tree_view_column_cell_set_cell_data (column,
2084                                                        tree_view->priv->model,
2085                                                        &iter,
2086                                                        GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
2087                                                        node->children?TRUE:FALSE);
2088             }
2089           else
2090             anchor = NULL;
2091
2092           if ((anchor && !gtk_tree_path_compare (anchor, path))
2093               || !_gtk_tree_view_column_has_editable_cell (column))
2094             {
2095               GtkCellEditable *cell_editable = NULL;
2096
2097               /* FIXME: get the right flags */
2098               guint flags = 0;
2099
2100               path_string = gtk_tree_path_to_string (path);
2101
2102               if (_gtk_tree_view_column_cell_event (column,
2103                                                     &cell_editable,
2104                                                     (GdkEvent *)event,
2105                                                     path_string,
2106                                                     &background_area,
2107                                                     &cell_area, flags))
2108                 {
2109                   if (cell_editable != NULL)
2110                     {
2111                       gint left, right;
2112                       GdkRectangle area;
2113
2114                       area = cell_area;
2115                       _gtk_tree_view_column_get_neighbor_sizes (column, _gtk_tree_view_column_get_edited_cell (column), &left, &right);
2116
2117                       area.x += left;
2118                       area.width -= right + left;
2119
2120                       gtk_tree_view_real_start_editing (tree_view,
2121                                                         column,
2122                                                         path,
2123                                                         cell_editable,
2124                                                         &area,
2125                                                         (GdkEvent *)event,
2126                                                         flags);
2127                       g_free (path_string);
2128                       gtk_tree_path_free (path);
2129                       gtk_tree_path_free (anchor);
2130                       return TRUE;
2131                     }
2132                   column_handled_click = TRUE;
2133                 }
2134               g_free (path_string);
2135             }
2136           if (anchor)
2137             gtk_tree_path_free (anchor);
2138         }
2139
2140       /* select */
2141       pre_val = tree_view->priv->vadjustment->value;
2142
2143       focus_cell = _gtk_tree_view_column_get_cell_at_pos (column, event->x - background_area.x);
2144       if (focus_cell)
2145         gtk_tree_view_column_focus_cell (column, focus_cell);
2146
2147       if (event->state & GDK_CONTROL_MASK)
2148         {
2149           gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
2150           gtk_tree_view_real_toggle_cursor_row (tree_view);
2151         }
2152       else if (event->state & GDK_SHIFT_MASK)
2153         {
2154           gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
2155           gtk_tree_view_real_select_cursor_row (tree_view, FALSE);
2156         }
2157       else
2158         {
2159           gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
2160         }
2161
2162       /* the treeview may have been scrolled because of _set_cursor,
2163        * correct here
2164        */
2165
2166       aft_val = tree_view->priv->vadjustment->value;
2167       dval = pre_val - aft_val;
2168
2169       cell_area.y += dval;
2170       background_area.y += dval;
2171
2172       /* Save press to possibly begin a drag
2173        */
2174       if (!column_handled_click &&
2175           tree_view->priv->pressed_button < 0)
2176         {
2177           tree_view->priv->pressed_button = event->button;
2178           tree_view->priv->press_start_x = event->x;
2179           tree_view->priv->press_start_y = event->y;
2180         }
2181
2182       if (event->button == 1 && event->type == GDK_2BUTTON_PRESS &&
2183           tree_view->priv->last_button_press)
2184         {
2185           GtkTreePath *lsc;
2186
2187           lsc = gtk_tree_row_reference_get_path (tree_view->priv->last_button_press);
2188
2189           if (tree_view->priv->last_button_press)
2190             gtk_tree_row_reference_free (tree_view->priv->last_button_press);
2191           if (tree_view->priv->last_button_press_2)
2192             gtk_tree_row_reference_free (tree_view->priv->last_button_press_2);
2193           tree_view->priv->last_button_press = NULL;
2194           tree_view->priv->last_button_press_2 = NULL;
2195
2196           if (lsc)
2197             {
2198               if (!gtk_tree_path_compare (lsc, path))
2199                 emit_row_activated = TRUE;
2200               gtk_tree_path_free (lsc);
2201             }
2202         }
2203       else if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
2204         {
2205           if (tree_view->priv->last_button_press)
2206             gtk_tree_row_reference_free (tree_view->priv->last_button_press);
2207           tree_view->priv->last_button_press = tree_view->priv->last_button_press_2;
2208           tree_view->priv->last_button_press_2 = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
2209         }
2210
2211       GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
2212
2213       if (emit_row_activated)
2214         {
2215           gtk_grab_remove (widget);
2216           gtk_tree_view_row_activated (tree_view, path, column);
2217
2218           if (tree_view->priv->pressed_button == event->button)
2219             tree_view->priv->pressed_button = -1;
2220         }
2221
2222       gtk_tree_path_free (path);
2223
2224       return TRUE;
2225     }
2226
2227   /* We didn't click in the window.  Let's check to see if we clicked on a column resize window.
2228    */
2229   for (i = 0, list = tree_view->priv->columns; list; list = list->next, i++)
2230     {
2231       column = list->data;
2232       if (event->window == column->window &&
2233           column->resizable &&
2234           column->window)
2235         {
2236           gpointer drag_data;
2237
2238           if (event->type == GDK_2BUTTON_PRESS &&
2239               gtk_tree_view_column_get_sizing (column) != GTK_TREE_VIEW_COLUMN_AUTOSIZE)
2240             {
2241               _gtk_tree_view_column_autosize (tree_view, column);
2242               break;
2243             }
2244
2245           if (gdk_pointer_grab (column->window, FALSE,
2246                                 GDK_POINTER_MOTION_HINT_MASK |
2247                                 GDK_BUTTON1_MOTION_MASK |
2248                                 GDK_BUTTON_RELEASE_MASK,
2249                                 NULL, NULL, event->time))
2250             return FALSE;
2251
2252           gtk_grab_add (widget);
2253           GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE);
2254           column->resized_width = column->width;
2255           column->use_resized_width = TRUE;
2256
2257           /* block attached dnd signal handler */
2258           drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
2259           if (drag_data)
2260             g_signal_handlers_block_matched (widget,
2261                                              G_SIGNAL_MATCH_DATA,
2262                                              0, 0, NULL, NULL,
2263                                              drag_data);
2264
2265           if (!GTK_WIDGET_HAS_FOCUS (widget))
2266             gtk_widget_grab_focus (widget);
2267
2268           tree_view->priv->drag_pos = i;
2269           tree_view->priv->x_drag = (column->button->allocation.x + column->button->allocation.width);
2270           break;
2271         }
2272     }
2273   return TRUE;
2274 }
2275
2276 /* GtkWidget::button_release_event helper */
2277 static gboolean
2278 gtk_tree_view_button_release_drag_column (GtkWidget      *widget,
2279                                           GdkEventButton *event)
2280 {
2281   GtkTreeView *tree_view;
2282   gboolean rtl;
2283
2284   tree_view = GTK_TREE_VIEW (widget);
2285
2286   rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
2287   gdk_display_pointer_ungrab (gtk_widget_get_display (widget), GDK_CURRENT_TIME);
2288   gdk_display_keyboard_ungrab (gtk_widget_get_display (widget), GDK_CURRENT_TIME);
2289
2290   /* Move the button back */
2291   g_object_ref (tree_view->priv->drag_column->button);
2292   gtk_container_remove (GTK_CONTAINER (tree_view), tree_view->priv->drag_column->button);
2293   gtk_widget_set_parent_window (tree_view->priv->drag_column->button, tree_view->priv->header_window);
2294   gtk_widget_set_parent (tree_view->priv->drag_column->button, GTK_WIDGET (tree_view));
2295   g_object_unref (tree_view->priv->drag_column->button);
2296   gtk_widget_queue_resize (widget);
2297   if (tree_view->priv->drag_column->resizable)
2298     {
2299       gdk_window_raise (tree_view->priv->drag_column->window);
2300       gdk_window_show (tree_view->priv->drag_column->window);
2301     }
2302   else
2303     gdk_window_hide (tree_view->priv->drag_column->window);
2304
2305   gtk_widget_grab_focus (tree_view->priv->drag_column->button);
2306
2307   if (rtl)
2308     {
2309       if (tree_view->priv->cur_reorder &&
2310           tree_view->priv->cur_reorder->right_column != tree_view->priv->drag_column)
2311         gtk_tree_view_move_column_after (tree_view, tree_view->priv->drag_column,
2312                                          tree_view->priv->cur_reorder->right_column);
2313     }
2314   else
2315     {
2316       if (tree_view->priv->cur_reorder &&
2317           tree_view->priv->cur_reorder->left_column != tree_view->priv->drag_column)
2318         gtk_tree_view_move_column_after (tree_view, tree_view->priv->drag_column,
2319                                          tree_view->priv->cur_reorder->left_column);
2320     }
2321   tree_view->priv->drag_column = NULL;
2322   gdk_window_hide (tree_view->priv->drag_window);
2323
2324   g_list_foreach (tree_view->priv->column_drag_info, (GFunc) g_free, NULL);
2325   g_list_free (tree_view->priv->column_drag_info);
2326   tree_view->priv->column_drag_info = NULL;
2327
2328   gdk_window_hide (tree_view->priv->drag_highlight_window);
2329
2330   /* Reset our flags */
2331   tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_UNSET;
2332   GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG);
2333
2334   return TRUE;
2335 }
2336
2337 /* GtkWidget::button_release_event helper */
2338 static gboolean
2339 gtk_tree_view_button_release_column_resize (GtkWidget      *widget,
2340                                             GdkEventButton *event)
2341 {
2342   GtkTreeView *tree_view;
2343   gpointer drag_data;
2344   gint x;
2345   gint i;
2346
2347   tree_view = GTK_TREE_VIEW (widget);
2348
2349   i = tree_view->priv->drag_pos;
2350   tree_view->priv->drag_pos = -1;
2351
2352       /* unblock attached dnd signal handler */
2353   drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
2354   if (drag_data)
2355     g_signal_handlers_unblock_matched (widget,
2356                                        G_SIGNAL_MATCH_DATA,
2357                                        0, 0, NULL, NULL,
2358                                        drag_data);
2359
2360   GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE);
2361   gtk_widget_get_pointer (widget, &x, NULL);
2362   gtk_grab_remove (widget);
2363   gdk_display_pointer_ungrab (gdk_drawable_get_display (event->window),
2364                               event->time);
2365   return TRUE;
2366 }
2367
2368 static gboolean
2369 gtk_tree_view_button_release (GtkWidget      *widget,
2370                               GdkEventButton *event)
2371 {
2372   GtkTreeView *tree_view;
2373
2374   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
2375   g_return_val_if_fail (event != NULL, FALSE);
2376
2377   tree_view = GTK_TREE_VIEW (widget);
2378
2379   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
2380     return gtk_tree_view_button_release_drag_column (widget, event);
2381
2382   if (tree_view->priv->pressed_button == event->button)
2383     tree_view->priv->pressed_button = -1;
2384
2385   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE))
2386     return gtk_tree_view_button_release_column_resize (widget, event);
2387
2388   if (tree_view->priv->button_pressed_node == NULL)
2389     return FALSE;
2390
2391   if (event->button == 1)
2392     {
2393       gtk_grab_remove (widget);
2394       if (tree_view->priv->button_pressed_node == tree_view->priv->prelight_node &&
2395           GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
2396         {
2397           GtkTreePath *path = NULL;
2398
2399           path = _gtk_tree_view_find_path (tree_view,
2400                                            tree_view->priv->button_pressed_tree,
2401                                            tree_view->priv->button_pressed_node);
2402           /* Actually activate the node */
2403           if (tree_view->priv->button_pressed_node->children == NULL)
2404             gtk_tree_view_real_expand_row (tree_view, path,
2405                                            tree_view->priv->button_pressed_tree,
2406                                            tree_view->priv->button_pressed_node,
2407                                            FALSE, TRUE);
2408           else
2409             gtk_tree_view_real_collapse_row (GTK_TREE_VIEW (widget), path,
2410                                              tree_view->priv->button_pressed_tree,
2411                                              tree_view->priv->button_pressed_node, TRUE);
2412           gtk_tree_path_free (path);
2413         }
2414
2415       tree_view->priv->button_pressed_tree = NULL;
2416       tree_view->priv->button_pressed_node = NULL;
2417     }
2418
2419   return TRUE;
2420 }
2421
2422
2423 /* GtkWidget::motion_event function set.
2424  */
2425
2426 static gboolean
2427 coords_are_over_arrow (GtkTreeView *tree_view,
2428                        GtkRBTree   *tree,
2429                        GtkRBNode   *node,
2430                        /* these are in window coords */
2431                        gint         x,
2432                        gint         y)
2433 {
2434   GdkRectangle arrow;
2435   gint x2;
2436
2437   if (!GTK_WIDGET_REALIZED (tree_view))
2438     return FALSE;
2439
2440   if ((node->flags & GTK_RBNODE_IS_PARENT) == 0)
2441     return FALSE;
2442
2443   arrow.y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
2444
2445   arrow.height = MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size);
2446
2447   gtk_tree_view_get_arrow_xrange (tree_view, tree, &arrow.x, &x2);
2448
2449   arrow.width = x2 - arrow.x;
2450
2451   return (x >= arrow.x &&
2452           x < (arrow.x + arrow.width) &&
2453           y >= arrow.y &&
2454           y < (arrow.y + arrow.height));
2455 }
2456
2457 static void
2458 do_prelight (GtkTreeView *tree_view,
2459              GtkRBTree   *tree,
2460              GtkRBNode   *node,
2461              /* these are in tree_window coords */
2462              gint         x,
2463              gint         y)
2464 {
2465   if (tree_view->priv->prelight_tree == tree &&
2466       tree_view->priv->prelight_node == node)
2467     {
2468       /*  We are still on the same node,
2469           but we might need to take care of the arrow  */
2470
2471       if (tree && node)
2472         {
2473           gboolean over_arrow;
2474           gboolean flag_set;
2475
2476           over_arrow = coords_are_over_arrow (tree_view, tree, node, x, y);
2477           flag_set = GTK_TREE_VIEW_FLAG_SET (tree_view,
2478                                              GTK_TREE_VIEW_ARROW_PRELIT);
2479
2480           if (over_arrow != flag_set)
2481             {
2482               if (over_arrow)
2483                 GTK_TREE_VIEW_SET_FLAG (tree_view,
2484                                         GTK_TREE_VIEW_ARROW_PRELIT);
2485               else
2486                 GTK_TREE_VIEW_UNSET_FLAG (tree_view,
2487                                           GTK_TREE_VIEW_ARROW_PRELIT);
2488
2489               gtk_tree_view_draw_arrow (tree_view, tree, node, x, y);
2490             }
2491         }
2492
2493       return;
2494     }
2495
2496   if (tree_view->priv->prelight_tree && tree_view->priv->prelight_node)
2497     {
2498       /*  Unprelight the old node and arrow  */
2499
2500       GTK_RBNODE_UNSET_FLAG (tree_view->priv->prelight_node,
2501                              GTK_RBNODE_IS_PRELIT);
2502
2503       if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
2504         {
2505           GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
2506           
2507           gtk_tree_view_draw_arrow (tree_view,
2508                                     tree_view->priv->prelight_tree,
2509                                     tree_view->priv->prelight_node,
2510                                     x,
2511                                     y);
2512         }
2513
2514       _gtk_tree_view_queue_draw_node (tree_view,
2515                                       tree_view->priv->prelight_tree,
2516                                       tree_view->priv->prelight_node,
2517                                       NULL);
2518     }
2519
2520
2521   /*  Set the new prelight values  */
2522
2523   tree_view->priv->prelight_node = node;
2524   tree_view->priv->prelight_tree = tree;
2525
2526   if (!node || !tree)
2527     return;
2528
2529   /*  Prelight the new node and arrow  */
2530
2531   if (coords_are_over_arrow (tree_view, tree, node, x, y))
2532     {
2533       GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
2534
2535       gtk_tree_view_draw_arrow (tree_view, tree, node, x, y);
2536     }
2537
2538   GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_PRELIT);
2539
2540   _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
2541 }
2542
2543 static void
2544 ensure_unprelighted (GtkTreeView *tree_view)
2545 {
2546   do_prelight (tree_view,
2547                NULL, NULL,
2548                -1000, -1000); /* coords not possibly over an arrow */
2549
2550   g_assert (tree_view->priv->prelight_node == NULL);
2551 }
2552
2553
2554
2555
2556 /* Our motion arrow is either a box (in the case of the original spot)
2557  * or an arrow.  It is expander_size wide.
2558  */
2559 /*
2560  * 11111111111111
2561  * 01111111111110
2562  * 00111111111100
2563  * 00011111111000
2564  * 00001111110000
2565  * 00000111100000
2566  * 00000111100000
2567  * 00000111100000
2568  * ~ ~ ~ ~ ~ ~ ~
2569  * 00000111100000
2570  * 00000111100000
2571  * 00000111100000
2572  * 00001111110000
2573  * 00011111111000
2574  * 00111111111100
2575  * 01111111111110
2576  * 11111111111111
2577  */
2578
2579 static void
2580 gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
2581 {
2582   GtkTreeViewColumnReorder *reorder = tree_view->priv->cur_reorder;
2583   GtkWidget *widget = GTK_WIDGET (tree_view);
2584   GdkBitmap *mask = NULL;
2585   gint x;
2586   gint y;
2587   gint width;
2588   gint height;
2589   gint arrow_type = DRAG_COLUMN_WINDOW_STATE_UNSET;
2590   GdkWindowAttr attributes;
2591   guint attributes_mask;
2592
2593   if (!reorder ||
2594       reorder->left_column == tree_view->priv->drag_column ||
2595       reorder->right_column == tree_view->priv->drag_column)
2596     arrow_type = DRAG_COLUMN_WINDOW_STATE_ORIGINAL;
2597   else if (reorder->left_column || reorder->right_column)
2598     {
2599       GdkRectangle visible_rect;
2600       gtk_tree_view_get_visible_rect (tree_view, &visible_rect);
2601       if (reorder->left_column)
2602         x = reorder->left_column->button->allocation.x + reorder->left_column->button->allocation.width;
2603       else
2604         x = reorder->right_column->button->allocation.x;
2605
2606       if (x < visible_rect.x)
2607         arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT;
2608       else if (x > visible_rect.x + visible_rect.width)
2609         arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT;
2610       else
2611         arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW;
2612     }
2613
2614   /* We want to draw the rectangle over the initial location. */
2615   if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ORIGINAL)
2616     {
2617       GdkGC *gc;
2618       GdkColor col;
2619
2620       if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ORIGINAL)
2621         {
2622           if (tree_view->priv->drag_highlight_window)
2623             {
2624               gdk_window_set_user_data (tree_view->priv->drag_highlight_window,
2625                                         NULL);
2626               gdk_window_destroy (tree_view->priv->drag_highlight_window);
2627             }
2628
2629           attributes.window_type = GDK_WINDOW_CHILD;
2630           attributes.wclass = GDK_INPUT_OUTPUT;
2631           attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
2632           attributes.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
2633           attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
2634           attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
2635           tree_view->priv->drag_highlight_window = gdk_window_new (tree_view->priv->header_window, &attributes, attributes_mask);
2636           gdk_window_set_user_data (tree_view->priv->drag_highlight_window, GTK_WIDGET (tree_view));
2637
2638           width = tree_view->priv->drag_column->button->allocation.width;
2639           height = tree_view->priv->drag_column->button->allocation.height;
2640           gdk_window_move_resize (tree_view->priv->drag_highlight_window,
2641                                   tree_view->priv->drag_column_x, 0, width, height);
2642
2643           mask = gdk_pixmap_new (tree_view->priv->drag_highlight_window, width, height, 1);
2644           gc = gdk_gc_new (mask);
2645           col.pixel = 1;
2646           gdk_gc_set_foreground (gc, &col);
2647           gdk_draw_rectangle (mask, gc, TRUE, 0, 0, width, height);
2648           col.pixel = 0;
2649           gdk_gc_set_foreground(gc, &col);
2650           gdk_draw_rectangle (mask, gc, TRUE, 2, 2, width - 4, height - 4);
2651           g_object_unref (gc);
2652
2653           gdk_window_shape_combine_mask (tree_view->priv->drag_highlight_window,
2654                                          mask, 0, 0);
2655           if (mask) g_object_unref (mask);
2656           tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_ORIGINAL;
2657         }
2658     }
2659   else if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW)
2660     {
2661       gint i, j = 1;
2662       GdkGC *gc;
2663       GdkColor col;
2664
2665       width = tree_view->priv->expander_size;
2666
2667       /* Get x, y, width, height of arrow */
2668       gdk_window_get_origin (tree_view->priv->header_window, &x, &y);
2669       if (reorder->left_column)
2670         {
2671           x += reorder->left_column->button->allocation.x + reorder->left_column->button->allocation.width - width/2;
2672           height = reorder->left_column->button->allocation.height;
2673         }
2674       else
2675         {
2676           x += reorder->right_column->button->allocation.x - width/2;
2677           height = reorder->right_column->button->allocation.height;
2678         }
2679       y -= tree_view->priv->expander_size/2; /* The arrow takes up only half the space */
2680       height += tree_view->priv->expander_size;
2681
2682       /* Create the new window */
2683       if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW)
2684         {
2685           if (tree_view->priv->drag_highlight_window)
2686             {
2687               gdk_window_set_user_data (tree_view->priv->drag_highlight_window,
2688                                         NULL);
2689               gdk_window_destroy (tree_view->priv->drag_highlight_window);
2690             }
2691
2692           attributes.window_type = GDK_WINDOW_TEMP;
2693           attributes.wclass = GDK_INPUT_OUTPUT;
2694           attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
2695           attributes.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
2696           attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
2697           attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
2698           attributes.width = width;
2699           attributes.height = height;
2700           tree_view->priv->drag_highlight_window = gdk_window_new (gtk_widget_get_root_window (widget),
2701                                                                    &attributes, attributes_mask);
2702           gdk_window_set_user_data (tree_view->priv->drag_highlight_window, GTK_WIDGET (tree_view));
2703
2704           mask = gdk_pixmap_new (tree_view->priv->drag_highlight_window, width, height, 1);
2705           gc = gdk_gc_new (mask);
2706           col.pixel = 1;
2707           gdk_gc_set_foreground (gc, &col);
2708           gdk_draw_rectangle (mask, gc, TRUE, 0, 0, width, height);
2709
2710           /* Draw the 2 arrows as per above */
2711           col.pixel = 0;
2712           gdk_gc_set_foreground (gc, &col);
2713           for (i = 0; i < width; i ++)
2714             {
2715               if (i == (width/2 - 1))
2716                 continue;
2717               gdk_draw_line (mask, gc, i, j, i, height - j);
2718               if (i < (width/2 - 1))
2719                 j++;
2720               else
2721                 j--;
2722             }
2723           g_object_unref (gc);
2724           gdk_window_shape_combine_mask (tree_view->priv->drag_highlight_window,
2725                                          mask, 0, 0);
2726           if (mask) g_object_unref (mask);
2727         }
2728
2729       tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_ARROW;
2730       gdk_window_move (tree_view->priv->drag_highlight_window, x, y);
2731     }
2732   else if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT ||
2733            arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
2734     {
2735       gint i, j = 1;
2736       GdkGC *gc;
2737       GdkColor col;
2738
2739       width = tree_view->priv->expander_size;
2740
2741       /* Get x, y, width, height of arrow */
2742       width = width/2; /* remember, the arrow only takes half the available width */
2743       gdk_window_get_origin (widget->window, &x, &y);
2744       if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
2745         x += widget->allocation.width - width;
2746
2747       if (reorder->left_column)
2748         height = reorder->left_column->button->allocation.height;
2749       else
2750         height = reorder->right_column->button->allocation.height;
2751
2752       y -= tree_view->priv->expander_size;
2753       height += 2*tree_view->priv->expander_size;
2754
2755       /* Create the new window */
2756       if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT &&
2757           tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
2758         {
2759           if (tree_view->priv->drag_highlight_window)
2760             {
2761               gdk_window_set_user_data (tree_view->priv->drag_highlight_window,
2762                                         NULL);
2763               gdk_window_destroy (tree_view->priv->drag_highlight_window);
2764             }
2765
2766           attributes.window_type = GDK_WINDOW_TEMP;
2767           attributes.wclass = GDK_INPUT_OUTPUT;
2768           attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
2769           attributes.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
2770           attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
2771           attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
2772           attributes.width = width;
2773           attributes.height = height;
2774           tree_view->priv->drag_highlight_window = gdk_window_new (NULL, &attributes, attributes_mask);
2775           gdk_window_set_user_data (tree_view->priv->drag_highlight_window, GTK_WIDGET (tree_view));
2776
2777           mask = gdk_pixmap_new (tree_view->priv->drag_highlight_window, width, height, 1);
2778           gc = gdk_gc_new (mask);
2779           col.pixel = 1;
2780           gdk_gc_set_foreground (gc, &col);
2781           gdk_draw_rectangle (mask, gc, TRUE, 0, 0, width, height);
2782
2783           /* Draw the 2 arrows as per above */
2784           col.pixel = 0;
2785           gdk_gc_set_foreground (gc, &col);
2786           j = tree_view->priv->expander_size;
2787           for (i = 0; i < width; i ++)
2788             {
2789               gint k;
2790               if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT)
2791                 k = width - i - 1;
2792               else
2793                 k = i;
2794               gdk_draw_line (mask, gc, k, j, k, height - j);
2795               gdk_draw_line (mask, gc, k, 0, k, tree_view->priv->expander_size - j);
2796               gdk_draw_line (mask, gc, k, height, k, height - tree_view->priv->expander_size + j);
2797               j--;
2798             }
2799           g_object_unref (gc);
2800           gdk_window_shape_combine_mask (tree_view->priv->drag_highlight_window,
2801                                          mask, 0, 0);
2802           if (mask) g_object_unref (mask);
2803         }
2804
2805       tree_view->priv->drag_column_window_state = arrow_type;
2806       gdk_window_move (tree_view->priv->drag_highlight_window, x, y);
2807    }
2808   else
2809     {
2810       g_warning (G_STRLOC"Invalid GtkTreeViewColumnReorder struct");
2811       gdk_window_hide (tree_view->priv->drag_highlight_window);
2812       return;
2813     }
2814
2815   gdk_window_show (tree_view->priv->drag_highlight_window);
2816   gdk_window_raise (tree_view->priv->drag_highlight_window);
2817 }
2818
2819 static gboolean
2820 gtk_tree_view_motion_resize_column (GtkWidget      *widget,
2821                                     GdkEventMotion *event)
2822 {
2823   gint x;
2824   gint new_width;
2825   GtkTreeViewColumn *column;
2826   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
2827
2828   column = gtk_tree_view_get_column (tree_view, tree_view->priv->drag_pos);
2829
2830   if (event->is_hint || event->window != widget->window)
2831     gtk_widget_get_pointer (widget, &x, NULL);
2832   else
2833     x = event->x;
2834
2835   if (tree_view->priv->hadjustment)
2836     x += tree_view->priv->hadjustment->value;
2837
2838   new_width = gtk_tree_view_new_column_width (tree_view,
2839                                               tree_view->priv->drag_pos, &x);
2840   if (x != tree_view->priv->x_drag &&
2841       (new_width != column->fixed_width));
2842     {
2843       column->resized_width = new_width;
2844       gtk_widget_queue_resize (widget);
2845     }
2846
2847   return FALSE;
2848 }
2849
2850
2851 static void
2852 gtk_tree_view_update_current_reorder (GtkTreeView *tree_view)
2853 {
2854   GtkTreeViewColumnReorder *reorder = NULL;
2855   GList *list;
2856   gint mouse_x;
2857
2858   gdk_window_get_pointer (tree_view->priv->header_window, &mouse_x, NULL, NULL);
2859   for (list = tree_view->priv->column_drag_info; list; list = list->next)
2860     {
2861       reorder = (GtkTreeViewColumnReorder *) list->data;
2862       if (mouse_x >= reorder->left_align && mouse_x < reorder->right_align)
2863         break;
2864       reorder = NULL;
2865     }
2866
2867   /*  if (reorder && reorder == tree_view->priv->cur_reorder)
2868       return;*/
2869
2870   tree_view->priv->cur_reorder = reorder;
2871   gtk_tree_view_motion_draw_column_motion_arrow (tree_view);
2872 }
2873
2874 static void
2875 gtk_tree_view_vertical_autoscroll (GtkTreeView *tree_view)
2876 {
2877   GdkRectangle visible_rect;
2878   gint y;
2879   gint offset;
2880   gfloat value;
2881
2882   gdk_window_get_pointer (tree_view->priv->bin_window, NULL, &y, NULL);
2883   y += tree_view->priv->dy;
2884
2885   gtk_tree_view_get_visible_rect (tree_view, &visible_rect);
2886
2887   /* see if we are near the edge. */
2888   offset = y - (visible_rect.y + 2 * SCROLL_EDGE_SIZE);
2889   if (offset > 0)
2890     {
2891       offset = y - (visible_rect.y + visible_rect.height - 2 * SCROLL_EDGE_SIZE);
2892       if (offset < 0)
2893         return;
2894     }
2895
2896   value = CLAMP (tree_view->priv->vadjustment->value + offset, 0.0,
2897                  tree_view->priv->vadjustment->upper - tree_view->priv->vadjustment->page_size);
2898   gtk_adjustment_set_value (tree_view->priv->vadjustment, value);
2899 }
2900
2901 static gboolean
2902 gtk_tree_view_horizontal_autoscroll (GtkTreeView *tree_view)
2903 {
2904   GdkRectangle visible_rect;
2905   gint x;
2906   gint offset;
2907   gfloat value;
2908
2909   gdk_window_get_pointer (tree_view->priv->bin_window, &x, NULL, NULL);
2910
2911   gtk_tree_view_get_visible_rect (tree_view, &visible_rect);
2912
2913   /* See if we are near the edge. */
2914   offset = x - (visible_rect.x + SCROLL_EDGE_SIZE);
2915   if (offset > 0)
2916     {
2917       offset = x - (visible_rect.x + visible_rect.width - SCROLL_EDGE_SIZE);
2918       if (offset < 0)
2919         return TRUE;
2920     }
2921   offset = offset/3;
2922
2923   value = CLAMP (tree_view->priv->hadjustment->value + offset,
2924                  0.0, tree_view->priv->hadjustment->upper - tree_view->priv->hadjustment->page_size);
2925   gtk_adjustment_set_value (tree_view->priv->hadjustment, value);
2926
2927   return TRUE;
2928
2929 }
2930
2931 static gboolean
2932 gtk_tree_view_motion_drag_column (GtkWidget      *widget,
2933                                   GdkEventMotion *event)
2934 {
2935   GtkTreeView *tree_view = (GtkTreeView *) widget;
2936   GtkTreeViewColumn *column = tree_view->priv->drag_column;
2937   gint x, y;
2938
2939   /* Sanity Check */
2940   if ((column == NULL) ||
2941       (event->window != tree_view->priv->drag_window))
2942     return FALSE;
2943
2944   /* Handle moving the header */
2945   gdk_window_get_position (tree_view->priv->drag_window, &x, &y);
2946   x = CLAMP (x + (gint)event->x - column->drag_x, 0,
2947              MAX (tree_view->priv->width, GTK_WIDGET (tree_view)->allocation.width) - column->button->allocation.width);
2948   gdk_window_move (tree_view->priv->drag_window, x, y);
2949   
2950   /* autoscroll, if needed */
2951   gtk_tree_view_horizontal_autoscroll (tree_view);
2952   /* Update the current reorder position and arrow; */
2953   gtk_tree_view_update_current_reorder (tree_view);
2954
2955   return TRUE;
2956 }
2957
2958 static gboolean
2959 gtk_tree_view_motion_bin_window (GtkWidget      *widget,
2960                                  GdkEventMotion *event)
2961 {
2962   GtkTreeView *tree_view;
2963   GtkRBTree *tree;
2964   GtkRBNode *node;
2965   gint new_y;
2966
2967   tree_view = (GtkTreeView *) widget;
2968
2969   if (tree_view->priv->tree == NULL)
2970     return FALSE;
2971
2972   /* only check for an initiated drag when a button is pressed */
2973   if (tree_view->priv->pressed_button >= 0)
2974     gtk_tree_view_maybe_begin_dragging_row (tree_view, event);
2975
2976   new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
2977   if (new_y < 0)
2978     new_y = 0;
2979
2980   _gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
2981
2982   /* If we are currently pressing down a button, we don't want to prelight anything else. */
2983   if ((tree_view->priv->button_pressed_node != NULL) &&
2984       (tree_view->priv->button_pressed_node != node))
2985     node = NULL;
2986
2987   do_prelight (tree_view, tree, node, event->x, event->y);
2988
2989   return TRUE;
2990 }
2991
2992 static gboolean
2993 gtk_tree_view_motion (GtkWidget      *widget,
2994                       GdkEventMotion *event)
2995 {
2996   GtkTreeView *tree_view;
2997
2998   tree_view = (GtkTreeView *) widget;
2999
3000   /* Resizing a column */
3001   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE))
3002     return gtk_tree_view_motion_resize_column (widget, event);
3003
3004   /* Drag column */
3005   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
3006     return gtk_tree_view_motion_drag_column (widget, event);
3007
3008   /* Sanity check it */
3009   if (event->window == tree_view->priv->bin_window)
3010     return gtk_tree_view_motion_bin_window (widget, event);
3011
3012   return FALSE;
3013 }
3014
3015 /* Warning: Very scary function.
3016  * Modify at your own risk
3017  *
3018  * KEEP IN SYNC WITH gtk_tree_view_create_row_drag_icon()!
3019  * FIXME: It's not...
3020  */
3021 static gboolean
3022 gtk_tree_view_bin_expose (GtkWidget      *widget,
3023                           GdkEventExpose *event)
3024 {
3025   GtkTreeView *tree_view;
3026   GtkTreePath *path;
3027   GtkRBTree *tree;
3028   GList *list;
3029   GtkRBNode *node;
3030   GtkRBNode *cursor = NULL;
3031   GtkRBTree *cursor_tree = NULL;
3032   GtkRBNode *drag_highlight = NULL;
3033   GtkRBTree *drag_highlight_tree = NULL;
3034   GtkTreeIter iter;
3035   gint new_y;
3036   gint y_offset, x_offset, cell_offset;
3037   gint max_height;
3038   gint depth;
3039   GdkRectangle background_area;
3040   GdkRectangle cell_area;
3041   guint flags;
3042   gint highlight_x;
3043   gint bin_window_width;
3044   GtkTreePath *cursor_path;
3045   GtkTreePath *drag_dest_path;
3046   GList *last_column;
3047   gint vertical_separator;
3048   gint horizontal_separator;
3049   gint focus_line_width;
3050   gboolean allow_rules;
3051   gboolean has_special_cell;
3052   gboolean rtl;
3053
3054   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
3055
3056   rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
3057
3058   tree_view = GTK_TREE_VIEW (widget);
3059
3060   gtk_widget_style_get (widget,
3061                         "horizontal_separator", &horizontal_separator,
3062                         "vertical_separator", &vertical_separator,
3063                         "allow_rules", &allow_rules,
3064                         "focus-line-width", &focus_line_width,
3065                         NULL);
3066
3067   if (tree_view->priv->tree == NULL)
3068     return TRUE;
3069
3070   /* clip event->area to the visible area */
3071   if (event->area.height < 0)
3072     return TRUE;
3073
3074   validate_visible_area (tree_view);
3075
3076   new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, event->area.y);
3077
3078   if (new_y < 0)
3079     new_y = 0;
3080   y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
3081
3082   if (node == NULL)
3083     return TRUE;
3084
3085   /* find the path for the node */
3086   path = _gtk_tree_view_find_path ((GtkTreeView *)widget,
3087                                    tree,
3088                                    node);
3089   gtk_tree_model_get_iter (tree_view->priv->model,
3090                            &iter,
3091                            path);
3092   depth = gtk_tree_path_get_depth (path);
3093   gtk_tree_path_free (path);
3094
3095   cursor_path = NULL;
3096   drag_dest_path = NULL;
3097
3098   if (tree_view->priv->cursor)
3099     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
3100
3101   if (cursor_path)
3102     _gtk_tree_view_find_node (tree_view, cursor_path,
3103                               &cursor_tree, &cursor);
3104
3105   if (tree_view->priv->drag_dest_row)
3106     drag_dest_path = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
3107
3108   if (drag_dest_path)
3109     _gtk_tree_view_find_node (tree_view, drag_dest_path,
3110                               &drag_highlight_tree, &drag_highlight);
3111
3112   gdk_drawable_get_size (tree_view->priv->bin_window,
3113                          &bin_window_width, NULL);
3114
3115   for (last_column = rtl ? g_list_first (tree_view->priv->columns) : g_list_last (tree_view->priv->columns);
3116        last_column &&
3117          !(GTK_TREE_VIEW_COLUMN (last_column->data)->visible) &&
3118          GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (last_column->data)->button);
3119        last_column = rtl ? last_column->next : last_column->prev)
3120     ;
3121
3122   /* Actually process the expose event.  To do this, we want to
3123    * start at the first node of the event, and walk the tree in
3124    * order, drawing each successive node.
3125    */
3126
3127   do
3128     {
3129       gboolean parity;
3130
3131       max_height = MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size);
3132
3133       x_offset = -event->area.x;
3134       cell_offset = 0;
3135       highlight_x = 0; /* should match x coord of first cell */
3136
3137       background_area.y = y_offset + event->area.y;
3138       background_area.height = max_height;
3139
3140       flags = 0;
3141
3142       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PRELIT))
3143         flags |= GTK_CELL_RENDERER_PRELIT;
3144
3145       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
3146         flags |= GTK_CELL_RENDERER_SELECTED;
3147
3148       parity = _gtk_rbtree_node_find_parity (tree, node);
3149
3150       has_special_cell = gtk_tree_view_has_special_cell (tree_view);
3151
3152       for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
3153            list;
3154            list = (rtl ? list->prev : list->next))
3155         {
3156           GtkTreeViewColumn *column = list->data;
3157           const gchar *detail = NULL;
3158           GtkStateType state;
3159
3160           if (!column->visible)
3161             continue;
3162
3163           if (cell_offset > event->area.x + event->area.width ||
3164               cell_offset + column->width < event->area.x)
3165             {
3166               cell_offset += column->width;
3167               continue;
3168             }
3169
3170           if (column->show_sort_indicator)
3171             flags |= GTK_CELL_RENDERER_SORTED;
3172           else
3173             flags &= ~GTK_CELL_RENDERER_SORTED;
3174
3175           if (cursor == node)
3176             flags |= GTK_CELL_RENDERER_FOCUSED;
3177           else
3178             flags &= ~GTK_CELL_RENDERER_FOCUSED;
3179
3180           background_area.x = cell_offset;
3181           background_area.width = column->width;
3182
3183           cell_area = background_area;
3184           cell_area.y += vertical_separator / 2;
3185           cell_area.x += horizontal_separator / 2;
3186           cell_area.height -= vertical_separator;
3187           cell_area.width -= horizontal_separator;
3188
3189           if (gdk_region_rect_in (event->region, &background_area) == GDK_OVERLAP_RECTANGLE_OUT)
3190             {
3191               cell_offset += column->width;
3192               continue;
3193             }
3194
3195           gtk_tree_view_column_cell_set_cell_data (column,
3196                                                    tree_view->priv->model,
3197                                                    &iter,
3198                                                    GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
3199                                                    node->children?TRUE:FALSE);
3200
3201           /* Select the detail for drawing the cell.  relevant
3202            * factors are parity, sortedness, and whether to
3203            * display rules.
3204            */
3205           if (allow_rules && tree_view->priv->has_rules)
3206             {
3207               if (flags & GTK_CELL_RENDERER_SORTED)
3208                 {
3209                   if (parity)
3210                     detail = "cell_odd_ruled_sorted";
3211                   else
3212                     detail = "cell_even_ruled_sorted";
3213                 }
3214               else
3215                 {
3216                   if (parity)
3217                     detail = "cell_odd_ruled";
3218                   else
3219                     detail = "cell_even_ruled";
3220                 }
3221             }
3222           else
3223             {
3224               if (flags & GTK_CELL_RENDERER_SORTED)
3225                 {
3226                   if (parity)
3227                     detail = "cell_odd_sorted";
3228                   else
3229                     detail = "cell_even_sorted";
3230                 }
3231               else
3232                 {
3233                   if (parity)
3234                     detail = "cell_odd";
3235                   else
3236                     detail = "cell_even";
3237                 }
3238             }
3239
3240           g_assert (detail);
3241
3242           if (flags & GTK_CELL_RENDERER_SELECTED)
3243             state = GTK_STATE_SELECTED;
3244           else
3245             state = GTK_STATE_NORMAL;
3246
3247           /* Draw background */
3248           gtk_paint_flat_box (widget->style,
3249                               event->window,
3250                               state,
3251                               GTK_SHADOW_NONE,
3252                               &event->area,
3253                               widget,
3254                               detail,
3255                               background_area.x,
3256                               background_area.y,
3257                               background_area.width,
3258                               background_area.height);
3259
3260           if (gtk_tree_view_is_expander_column (tree_view, column) &&
3261               TREE_VIEW_DRAW_EXPANDERS(tree_view))
3262             {
3263               if (!rtl)
3264                 cell_area.x += depth * tree_view->priv->expander_size;
3265               cell_area.width -= depth * tree_view->priv->expander_size;
3266
3267               /* If we have an expander column, the highlight underline
3268                * starts with that column, so that it indicates which
3269                * level of the tree we're dropping at.
3270                */
3271               highlight_x = cell_area.x;
3272               _gtk_tree_view_column_cell_render (column,
3273                                                  event->window,
3274                                                  &background_area,
3275                                                  &cell_area,
3276                                                  &event->area,
3277                                                  flags);
3278               if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT)
3279                 {
3280                   gint x, y;
3281                   gdk_window_get_pointer (tree_view->priv->bin_window, &x, &y, 0);
3282                   gtk_tree_view_draw_arrow (GTK_TREE_VIEW (widget),
3283                                             tree,
3284                                             node,
3285                                             x, y);
3286                 }
3287             }
3288           else
3289             {
3290               _gtk_tree_view_column_cell_render (column,
3291                                                  event->window,
3292                                                  &background_area,
3293                                                  &cell_area,
3294                                                  &event->area,
3295                                                  flags);
3296             }
3297           if (node == cursor && has_special_cell &&
3298               ((column == tree_view->priv->focus_column &&
3299                 GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS) &&
3300                 GTK_WIDGET_HAS_FOCUS (widget)) ||
3301                (column == tree_view->priv->edited_column)))
3302             {
3303               _gtk_tree_view_column_cell_draw_focus (column,
3304                                                      event->window,
3305                                                      &background_area,
3306                                                      &cell_area,
3307                                                      &event->area,
3308                                                      flags);
3309             }
3310           cell_offset += column->width;
3311         }
3312
3313       if (node == drag_highlight)
3314         {
3315           /* Draw indicator for the drop
3316            */
3317           gint highlight_y = -1;
3318           GtkRBTree *tree = NULL;
3319           GtkRBNode *node = NULL;
3320           gint width;
3321           gint focus_line_width;
3322
3323           switch (tree_view->priv->drag_dest_pos)
3324             {
3325             case GTK_TREE_VIEW_DROP_BEFORE:
3326               highlight_y = background_area.y - 1;
3327               if (highlight_y < 0)
3328                       highlight_y = 0;
3329               break;
3330
3331             case GTK_TREE_VIEW_DROP_AFTER:
3332               highlight_y = background_area.y + background_area.height - 1;
3333               break;
3334
3335             case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
3336             case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
3337               _gtk_tree_view_find_node (tree_view, drag_dest_path, &tree, &node);
3338
3339               if (tree == NULL)
3340                 break;
3341               gdk_drawable_get_size (tree_view->priv->bin_window,
3342                                      &width, NULL);
3343               gtk_widget_style_get (widget, "focus-line-width", &focus_line_width, NULL);
3344               gtk_paint_focus (widget->style,
3345                                tree_view->priv->bin_window,
3346                                GTK_WIDGET_STATE (widget),
3347                                NULL,
3348                                widget,
3349                                "treeview-drop-indicator",
3350                                0, BACKGROUND_FIRST_PIXEL (tree_view, tree, node)
3351                                - focus_line_width / 2,
3352                                width, MAX(BACKGROUND_HEIGHT (node),
3353                                           tree_view->priv->expander_size)
3354                                - focus_line_width + 1);
3355               break;
3356             }
3357
3358           if (highlight_y >= 0)
3359             {
3360               gdk_draw_line (event->window,
3361                              widget->style->black_gc,
3362                              highlight_x,
3363                              highlight_y,
3364                              bin_window_width - highlight_x,
3365                              highlight_y);
3366             }
3367         }
3368
3369       /* draw the big row-spanning focus rectangle, if needed */
3370       if (!has_special_cell && node == cursor &&
3371           GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS) &&
3372           GTK_WIDGET_HAS_FOCUS (widget))
3373         {
3374           gint width;
3375           GtkStateType focus_rect_state;
3376
3377           focus_rect_state =
3378             flags & GTK_CELL_RENDERER_SELECTED ? GTK_STATE_SELECTED :
3379             (flags & GTK_CELL_RENDERER_PRELIT ? GTK_STATE_PRELIGHT :
3380              (flags & GTK_CELL_RENDERER_INSENSITIVE ? GTK_STATE_INSENSITIVE :
3381               GTK_STATE_NORMAL));
3382
3383           gdk_drawable_get_size (tree_view->priv->bin_window,
3384                                  &width, NULL);
3385           gtk_paint_focus (widget->style,
3386                            tree_view->priv->bin_window,
3387                            focus_rect_state,
3388                            NULL,
3389                            widget,
3390                            "treeview",
3391                            0,
3392                            BACKGROUND_FIRST_PIXEL (tree_view, tree, node),
3393                            width,
3394                            MAX (BACKGROUND_HEIGHT (node),
3395                                 tree_view->priv->expander_size));
3396         }
3397
3398       y_offset += max_height;
3399       if (node->children)
3400         {
3401           GtkTreeIter parent = iter;
3402           gboolean has_child;
3403
3404           tree = node->children;
3405           node = tree->root;
3406
3407           g_assert (node != tree->nil);
3408
3409           while (node->left != tree->nil)
3410             node = node->left;
3411           has_child = gtk_tree_model_iter_children (tree_view->priv->model,
3412                                                     &iter,
3413                                                     &parent);
3414           depth++;
3415
3416           /* Sanity Check! */
3417           TREE_VIEW_INTERNAL_ASSERT (has_child, FALSE);
3418         }
3419       else
3420         {
3421           gboolean done = FALSE;
3422           do
3423             {
3424               node = _gtk_rbtree_next (tree, node);
3425               if (node != NULL)
3426                 {
3427                   gboolean has_next = gtk_tree_model_iter_next (tree_view->priv->model, &iter);
3428                   done = TRUE;
3429
3430                   /* Sanity Check! */
3431                   TREE_VIEW_INTERNAL_ASSERT (has_next, FALSE);
3432                 }
3433               else
3434                 {
3435                   GtkTreeIter parent_iter = iter;
3436                   gboolean has_parent;
3437
3438                   node = tree->parent_node;
3439                   tree = tree->parent_tree;
3440                   if (tree == NULL)
3441                     /* we should go to done to free some memory */
3442                     goto done;
3443                   has_parent = gtk_tree_model_iter_parent (tree_view->priv->model,
3444                                                            &iter,
3445                                                            &parent_iter);
3446                   depth--;
3447
3448                   /* Sanity check */
3449                   TREE_VIEW_INTERNAL_ASSERT (has_parent, FALSE);
3450                 }
3451             }
3452           while (!done);
3453         }
3454     }
3455   while (y_offset < event->area.height);
3456
3457  done:
3458   if (cursor_path)
3459     gtk_tree_path_free (cursor_path);
3460
3461   if (drag_dest_path)
3462     gtk_tree_path_free (drag_dest_path);
3463
3464   return FALSE;
3465 }
3466
3467 static gboolean
3468 gtk_tree_view_expose (GtkWidget      *widget,
3469                       GdkEventExpose *event)
3470 {
3471   GtkTreeView *tree_view;
3472
3473   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
3474
3475   tree_view = GTK_TREE_VIEW (widget);
3476
3477   if (event->window == tree_view->priv->bin_window)
3478     return gtk_tree_view_bin_expose (widget, event);
3479   else if (event->window == tree_view->priv->header_window)
3480     {
3481       GList *list;
3482       
3483       for (list = tree_view->priv->columns; list != NULL; list = list->next)
3484         {
3485           GtkTreeViewColumn *column = list->data;
3486
3487           if (column == tree_view->priv->drag_column)
3488             continue;
3489
3490           if (column->visible)
3491             gtk_container_propagate_expose (GTK_CONTAINER (tree_view),
3492                                             column->button,
3493                                             event);
3494         }
3495     }
3496   else if (event->window == tree_view->priv->drag_window)
3497     {
3498       gtk_container_propagate_expose (GTK_CONTAINER (tree_view),
3499                                       tree_view->priv->drag_column->button,
3500                                       event);
3501     }
3502   return TRUE;
3503 }
3504
3505 enum
3506 {
3507   DROP_HOME,
3508   DROP_RIGHT,
3509   DROP_LEFT,
3510   DROP_END
3511 };
3512
3513 /* returns 0x1 when no column has been found -- yes it's hackish */
3514 static GtkTreeViewColumn *
3515 gtk_tree_view_get_drop_column (GtkTreeView       *tree_view,
3516                                GtkTreeViewColumn *column,
3517                                gint               drop_position)
3518 {
3519   GtkTreeViewColumn *left_column = NULL;
3520   GtkTreeViewColumn *cur_column = NULL;
3521   GList *tmp_list;
3522
3523   if (!column->reorderable)
3524     return (GtkTreeViewColumn *)0x1;
3525
3526   switch (drop_position)
3527     {
3528       case DROP_HOME:
3529         /* find first column where we can drop */
3530         tmp_list = tree_view->priv->columns;
3531         if (column == GTK_TREE_VIEW_COLUMN (tmp_list->data))
3532           return (GtkTreeViewColumn *)0x1;
3533
3534         while (tmp_list)
3535           {
3536             g_assert (tmp_list);
3537
3538             cur_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
3539             tmp_list = tmp_list->next;
3540
3541             if (left_column && left_column->visible == FALSE)
3542               continue;
3543
3544             if (!tree_view->priv->column_drop_func)
3545               return left_column;
3546
3547             if (!(*tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
3548               {
3549                 left_column = cur_column;
3550                 continue;
3551               }
3552
3553             return cur_column;
3554           }
3555
3556         if (!tree_view->priv->column_drop_func)
3557           return left_column;
3558
3559         if ((*tree_view->priv->column_drop_func) (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data))
3560           return left_column;
3561         else
3562           return (GtkTreeViewColumn *)0x1;
3563         break;
3564
3565       case DROP_RIGHT:
3566         /* find first column after column where we can drop */
3567         tmp_list = tree_view->priv->columns;
3568
3569         for (; tmp_list; tmp_list = tmp_list->next)
3570           if (GTK_TREE_VIEW_COLUMN (tmp_list->data) == column)
3571             break;
3572
3573         if (!tmp_list || !tmp_list->next)
3574           return (GtkTreeViewColumn *)0x1;
3575
3576         tmp_list = tmp_list->next;
3577         left_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
3578         tmp_list = tmp_list->next;
3579
3580         while (tmp_list)
3581           {
3582             g_assert (tmp_list);
3583
3584             cur_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
3585             tmp_list = tmp_list->next;
3586
3587             if (left_column && left_column->visible == FALSE)
3588               {
3589                 left_column = cur_column;
3590                 if (tmp_list)
3591                   tmp_list = tmp_list->next;
3592                 continue;
3593               }
3594
3595             if (!tree_view->priv->column_drop_func)
3596               return left_column;
3597
3598             if (!(*tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
3599               {
3600                 left_column = cur_column;
3601                 continue;
3602               }
3603
3604             return cur_column;
3605           }
3606
3607         if (!tree_view->priv->column_drop_func)
3608           return left_column;
3609
3610         if ((*tree_view->priv->column_drop_func) (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data))
3611           return left_column;
3612         else
3613           return (GtkTreeViewColumn *)0x1;
3614         break;
3615
3616       case DROP_LEFT:
3617         /* find first column before column where we can drop */
3618         tmp_list = tree_view->priv->columns;
3619
3620         for (; tmp_list; tmp_list = tmp_list->next)
3621           if (GTK_TREE_VIEW_COLUMN (tmp_list->data) == column)
3622             break;
3623
3624         if (!tmp_list || !tmp_list->prev)
3625           return (GtkTreeViewColumn *)0x1;
3626
3627         tmp_list = tmp_list->prev;
3628         cur_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
3629         tmp_list = tmp_list->prev;
3630
3631         while (tmp_list)
3632           {
3633             g_assert (tmp_list);
3634
3635             left_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
3636
3637             if (left_column && !left_column->visible)
3638               {
3639                 /*if (!tmp_list->prev)
3640                   return (GtkTreeViewColumn *)0x1;
3641                   */
3642 /*
3643                 cur_column = GTK_TREE_VIEW_COLUMN (tmp_list->prev->data);
3644                 tmp_list = tmp_list->prev->prev;
3645                 continue;*/
3646
3647                 cur_column = left_column;
3648                 if (tmp_list)
3649                   tmp_list = tmp_list->prev;
3650                 continue;
3651               }
3652
3653             if (!tree_view->priv->column_drop_func)
3654               return left_column;
3655
3656             if ((*tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
3657               return left_column;
3658
3659             cur_column = left_column;
3660             tmp_list = tmp_list->prev;
3661           }
3662
3663         if (!tree_view->priv->column_drop_func)
3664           return NULL;
3665
3666         if ((*tree_view->priv->column_drop_func) (tree_view, column, NULL, cur_column, tree_view->priv->column_drop_func_data))
3667           return NULL;
3668         else
3669           return (GtkTreeViewColumn *)0x1;
3670         break;
3671
3672       case DROP_END:
3673         /* same as DROP_HOME case, but doing it backwards */
3674         tmp_list = g_list_last (tree_view->priv->columns);
3675         cur_column = NULL;
3676
3677         if (column == GTK_TREE_VIEW_COLUMN (tmp_list->data))
3678           return (GtkTreeViewColumn *)0x1;
3679
3680         while (tmp_list)
3681           {
3682             g_assert (tmp_list);
3683
3684             left_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
3685
3686             if (left_column && !left_column->visible)
3687               {
3688                 cur_column = left_column;
3689                 tmp_list = tmp_list->prev;
3690               }
3691
3692             if (!tree_view->priv->column_drop_func)
3693               return left_column;
3694
3695             if ((*tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
3696               return left_column;
3697
3698             cur_column = left_column;
3699             tmp_list = tmp_list->prev;
3700           }
3701
3702         if (!tree_view->priv->column_drop_func)
3703           return NULL;
3704
3705         if ((*tree_view->priv->column_drop_func) (tree_view, column, NULL, cur_column, tree_view->priv->column_drop_func_data))
3706           return NULL;
3707         else
3708           return (GtkTreeViewColumn *)0x1;
3709         break;
3710     }
3711
3712   return (GtkTreeViewColumn *)0x1;
3713 }
3714
3715 static gboolean
3716 gtk_tree_view_key_press (GtkWidget   *widget,
3717                          GdkEventKey *event)
3718 {
3719   GtkTreeView *tree_view = (GtkTreeView *) widget;
3720   GList *list;
3721   gboolean rtl;
3722
3723   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
3724
3725   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
3726     {
3727       if (event->keyval == GDK_Escape)
3728         {
3729           tree_view->priv->cur_reorder = NULL;
3730           gtk_tree_view_button_release_drag_column (widget, NULL);
3731         }
3732       return TRUE;
3733     }
3734
3735   if (tree_view->priv->columns && (event->state & GDK_SHIFT_MASK)
3736       && (event->keyval == GDK_Left || event->keyval == GDK_KP_Left
3737           || event->keyval == GDK_Right || event->keyval == GDK_KP_Right))
3738     {
3739       list = tree_view->priv->columns;
3740       while (list)
3741         {
3742           GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (list->data);
3743           if (GTK_WIDGET_HAS_FOCUS (column->button))
3744             {
3745               if (!column->resizable)
3746                 return TRUE;
3747
3748               if (event->keyval == GDK_Left || event->keyval == GDK_KP_Left)
3749                 {
3750                   column->resized_width = MAX (column->resized_width,
3751                                                column->width);
3752                   column->resized_width -= 2;
3753                   if (column->resized_width < 0)
3754                     column->resized_width = 0;
3755
3756                   if (column->min_width == -1)
3757                     column->resized_width = MAX (column->button->requisition.width, column->resized_width);
3758                   else
3759                     column->resized_width = MAX (column->min_width, column->resized_width);
3760
3761                   if (column->max_width != -1)
3762                     column->resized_width = MIN (column->resized_width, column->max_width);
3763
3764                   column->use_resized_width = TRUE;
3765                   gtk_widget_queue_resize (widget);
3766                   return TRUE;
3767                 }
3768               else if (event->keyval == GDK_Right
3769                        || event->keyval == GDK_KP_Right)
3770                 {
3771                   column->resized_width = MAX (column->resized_width,
3772                                                column->width);
3773                   column->resized_width += 2;
3774
3775                   if (column->max_width != -1)
3776                     column->resized_width = MIN (column->resized_width, column->max_width);
3777
3778                   column->use_resized_width = TRUE;
3779                   gtk_widget_queue_resize (widget);
3780                   return TRUE;
3781                 }
3782             }
3783           list = list->next;
3784         }
3785     }
3786
3787   if (tree_view->priv->columns && (event->state & GDK_CONTROL_MASK) &&
3788       (event->keyval == GDK_Left || event->keyval == GDK_KP_Left
3789        || event->keyval == GDK_Right || event->keyval == GDK_KP_Right
3790        || event->keyval == GDK_Home || event->keyval == GDK_KP_Home
3791        || event->keyval == GDK_End || event->keyval == GDK_KP_End))
3792     {
3793       list = tree_view->priv->columns;
3794       while (list)
3795         {
3796           GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (list->data);
3797           if (GTK_WIDGET_HAS_FOCUS (column->button))
3798             {
3799               if (event->keyval == (rtl ? GDK_Right : GDK_Left)
3800                   || event->keyval == (rtl ? GDK_KP_Right : GDK_KP_Left))
3801                 {
3802                   GtkTreeViewColumn *col;
3803                   col = gtk_tree_view_get_drop_column (tree_view, column, DROP_LEFT);
3804                   if (col != (GtkTreeViewColumn *)0x1)
3805                     gtk_tree_view_move_column_after (tree_view, column, col);
3806                   return TRUE;
3807                 }
3808               else if (event->keyval == (rtl ? GDK_Left : GDK_Right)
3809                        || event->keyval == (rtl ? GDK_KP_Left : GDK_KP_Right))
3810                 {
3811                   GtkTreeViewColumn *col;
3812                   col = gtk_tree_view_get_drop_column (tree_view, column, DROP_RIGHT);
3813                   if (col != (GtkTreeViewColumn *)0x1)
3814                     gtk_tree_view_move_column_after (tree_view, column, col);
3815                   return TRUE;
3816                 }
3817               else if (event->keyval == GDK_Home
3818                        || event->keyval == GDK_KP_Home)
3819                 {
3820                   GtkTreeViewColumn *col;
3821                   col = gtk_tree_view_get_drop_column (tree_view, column, DROP_HOME);
3822                   if (col != (GtkTreeViewColumn *)0x1)
3823                     gtk_tree_view_move_column_after (tree_view, column, col);
3824                   return TRUE;
3825                 }
3826               else if (event->keyval == GDK_End || event->keyval == GDK_KP_End)
3827                 {
3828                   GtkTreeViewColumn *col;
3829                   col = gtk_tree_view_get_drop_column (tree_view, column, DROP_END);
3830                   if (col != (GtkTreeViewColumn *)0x1)
3831                     gtk_tree_view_move_column_after (tree_view, column, col);
3832                   return TRUE;
3833                 }
3834             }
3835           list = list->next;
3836         }
3837     }
3838
3839   if (tree_view->priv->columns &&
3840       GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE) &&
3841       (event->keyval == GDK_Left || event->keyval == GDK_KP_Left
3842        || event->keyval == GDK_Right || event->keyval == GDK_KP_Right))
3843     {
3844       gint width = 0;
3845       list = tree_view->priv->columns;
3846       while (list)
3847         {
3848           GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (list->data);
3849           if (GTK_WIDGET_HAS_FOCUS (column->button))
3850             {
3851               if ((event->keyval == (rtl ? GDK_Right : GDK_Left)
3852                    || event->keyval == (rtl ? GDK_KP_Right : GDK_KP_Left))
3853                   && list->prev)
3854                 {
3855                   GList *tmp;
3856
3857                   for (tmp = list->prev; tmp; tmp = tmp->prev)
3858                     if (GTK_TREE_VIEW_COLUMN (tmp->data)->visible)
3859                       break;
3860
3861                   if (!tmp)
3862                     return FALSE;
3863
3864                   tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (tmp->data);
3865                   gtk_widget_grab_focus (tree_view->priv->focus_column->button);
3866                   width -= tree_view->priv->focus_column->width;
3867                   gtk_adjustment_set_value (tree_view->priv->hadjustment, CLAMP (width, tree_view->priv->hadjustment->lower, tree_view->priv->hadjustment->upper - tree_view->priv->hadjustment->page_size));
3868                   return TRUE;
3869                 }
3870               else if ((event->keyval == (rtl ? GDK_Left : GDK_Right)
3871                         || event->keyval == (rtl ? GDK_KP_Left : GDK_KP_Right))
3872                        && list->next)
3873                 {
3874                   GList *tmp;
3875
3876                   for (tmp = list->next; tmp; tmp = tmp->next)
3877                     if (GTK_TREE_VIEW_COLUMN (tmp->data)->visible)
3878                       break;
3879
3880                   if (!tmp)
3881                     return FALSE;
3882
3883                   tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (tmp->data);
3884
3885                   gtk_widget_grab_focus (tree_view->priv->focus_column->button);
3886                   width += tree_view->priv->focus_column->width;
3887                   gtk_adjustment_set_value (tree_view->priv->hadjustment, CLAMP (width, tree_view->priv->hadjustment->lower, tree_view->priv->hadjustment->upper - tree_view->priv->hadjustment->page_size));
3888                   return TRUE;
3889                 }
3890             }
3891           width += GTK_TREE_VIEW_COLUMN (list->data)->width;
3892           list = list->next;
3893         }
3894     }
3895
3896   return (* GTK_WIDGET_CLASS (parent_class)->key_press_event) (widget, event);
3897 }
3898
3899 /* FIXME Is this function necessary? Can I get an enter_notify event
3900  * w/o either an expose event or a mouse motion event?
3901  */
3902 static gboolean
3903 gtk_tree_view_enter_notify (GtkWidget        *widget,
3904                             GdkEventCrossing *event)
3905 {
3906   GtkTreeView *tree_view;
3907   GtkRBTree *tree;
3908   GtkRBNode *node;
3909   gint new_y;
3910
3911   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
3912
3913   tree_view = GTK_TREE_VIEW (widget);
3914
3915   /* Sanity check it */
3916   if (event->window != tree_view->priv->bin_window)
3917     return FALSE;
3918
3919   if (tree_view->priv->tree == NULL)
3920     return FALSE;
3921
3922   if ((tree_view->priv->button_pressed_node != NULL) &&
3923       (tree_view->priv->button_pressed_node != node))
3924     return TRUE;
3925
3926   /* find the node internally */
3927   new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
3928   if (new_y < 0)
3929     new_y = 0;
3930   _gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
3931
3932   do_prelight (tree_view, tree, node, event->x, event->y);
3933
3934   return TRUE;
3935 }
3936
3937 static gboolean
3938 gtk_tree_view_leave_notify (GtkWidget        *widget,
3939                             GdkEventCrossing *event)
3940 {
3941   GtkTreeView *tree_view;
3942
3943   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
3944
3945   if (event->mode == GDK_CROSSING_GRAB)
3946     return TRUE;
3947   tree_view = GTK_TREE_VIEW (widget);
3948
3949   if (tree_view->priv->prelight_node)
3950     _gtk_tree_view_queue_draw_node (tree_view,
3951                                    tree_view->priv->prelight_tree,
3952                                    tree_view->priv->prelight_node,
3953                                    NULL);
3954
3955   ensure_unprelighted (tree_view);
3956
3957   return TRUE;
3958 }
3959
3960
3961 static gint
3962 gtk_tree_view_focus_out (GtkWidget     *widget,
3963                          GdkEventFocus *event)
3964 {
3965   GtkWidget   *search_dialog;
3966
3967   gtk_widget_queue_draw (widget);
3968
3969   /* destroy interactive search dialog */
3970   search_dialog = g_object_get_data (G_OBJECT (widget),
3971                                      GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
3972   if (search_dialog)
3973     gtk_tree_view_search_dialog_destroy (search_dialog, GTK_TREE_VIEW (widget));
3974
3975   return FALSE;
3976 }
3977
3978
3979 /* Incremental Reflow
3980  */
3981
3982 /* Returns TRUE if it updated the size
3983  */
3984 static gboolean
3985 validate_row (GtkTreeView *tree_view,
3986               GtkRBTree   *tree,
3987               GtkRBNode   *node,
3988               GtkTreeIter *iter,
3989               GtkTreePath *path)
3990 {
3991   GtkTreeViewColumn *column;
3992   GList *list;
3993   gint height = 0;
3994   gint horizontal_separator;
3995   gint depth = gtk_tree_path_get_depth (path);
3996   gboolean retval = FALSE;
3997
3998   /* double check the row needs validating */
3999   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) &&
4000       ! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
4001     return FALSE;
4002
4003   gtk_widget_style_get (GTK_WIDGET (tree_view),
4004                         "horizontal_separator", &horizontal_separator,
4005                         NULL);
4006
4007   for (list = tree_view->priv->columns; list; list = list->next)
4008     {
4009       gint tmp_width;
4010       gint tmp_height;
4011
4012       column = list->data;
4013
4014       if (! column->visible)
4015         continue;
4016
4017       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID) && !column->dirty)
4018         continue;
4019
4020       gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, iter,
4021                                                GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
4022                                                node->children?TRUE:FALSE);
4023       gtk_tree_view_column_cell_get_size (column,
4024                                           NULL, NULL, NULL,
4025                                           &tmp_width, &tmp_height);
4026
4027       height = MAX (height, tmp_height);
4028       height = MAX (height, tree_view->priv->expander_size);
4029
4030       if (gtk_tree_view_is_expander_column (tree_view, column) && TREE_VIEW_DRAW_EXPANDERS (tree_view))
4031         {
4032           tmp_width = tmp_width + horizontal_separator + depth * (tree_view->priv->expander_size);
4033         }
4034       else
4035         tmp_width = tmp_width + horizontal_separator;
4036
4037       if (tmp_width > column->requested_width)
4038         {
4039           retval = TRUE;
4040           column->requested_width = tmp_width;
4041         }
4042     }
4043
4044   if (height != GTK_RBNODE_GET_HEIGHT (node))
4045     {
4046       retval = TRUE;
4047       _gtk_rbtree_node_set_height (tree, node, height);
4048     }
4049   _gtk_rbtree_node_mark_valid (tree, node);
4050
4051   return retval;
4052 }
4053
4054
4055 static void
4056 validate_visible_area (GtkTreeView *tree_view)
4057 {
4058   GtkTreePath *path = NULL;
4059   GtkTreePath *above_path = NULL;
4060   GtkTreeIter iter;
4061   GtkRBTree *tree = NULL;
4062   GtkRBNode *node = NULL;
4063   gboolean need_redraw = FALSE;
4064   gboolean size_changed = FALSE;
4065   gboolean update_dy = FALSE;
4066   gint total_height;
4067   gint area_above = 0;
4068   gint area_below = 0;
4069
4070   if (tree_view->priv->tree == NULL)
4071     return;
4072
4073   if (! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID) &&
4074       tree_view->priv->scroll_to_path == NULL)
4075     return;
4076
4077   total_height = GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
4078
4079   if (total_height == 0)
4080     return;
4081
4082   /* First, we check to see if we need to scroll anywhere
4083    */
4084   if (tree_view->priv->scroll_to_path)
4085     {
4086       path = gtk_tree_row_reference_get_path (tree_view->priv->scroll_to_path);
4087       if (path && !_gtk_tree_view_find_node (tree_view, path, &tree, &node))
4088         {
4089           gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
4090           if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
4091               GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
4092             {
4093               need_redraw = TRUE;
4094               if (validate_row (tree_view, tree, node, &iter, path))
4095                 size_changed = TRUE;
4096             }
4097
4098           if (tree_view->priv->scroll_to_use_align)
4099             {
4100               gint height = MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
4101               area_above = (total_height - height) *
4102                 tree_view->priv->scroll_to_row_align;
4103               area_below = total_height - area_above - height;
4104               area_above = MAX (area_above, 0);
4105               area_below = MAX (area_below, 0);
4106             }
4107           else
4108             {
4109               /* two cases:
4110                * 1) row not visible
4111                * 2) row visible
4112                */
4113               gint dy;
4114               gint height = MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
4115
4116               dy = _gtk_rbtree_node_find_offset (tree, node);
4117
4118               if (dy >= tree_view->priv->vadjustment->value &&
4119                   dy < (tree_view->priv->vadjustment->value
4120                         + tree_view->priv->vadjustment->page_size))
4121                 {
4122                   /* row visible: keep the row at the same position */
4123                   area_above = dy - tree_view->priv->vadjustment->value;
4124                   area_below = (tree_view->priv->vadjustment->value +
4125                                 tree_view->priv->vadjustment->page_size)
4126                                - dy - height;
4127                 }
4128               else
4129                 {
4130                   /* row not visible */
4131                   update_dy = TRUE;
4132
4133                   if (dy >= 0 && dy <= tree_view->priv->vadjustment->page_size)
4134                     {
4135                       /* row at the beginning -- fixed */
4136                       area_above = dy;
4137                       area_below = tree_view->priv->vadjustment->page_size
4138                                    - area_above - height;
4139                     }
4140                   else if (dy >= (tree_view->priv->vadjustment->upper -
4141                                   tree_view->priv->vadjustment->page_size)
4142                            && dy <= tree_view->priv->vadjustment->upper)
4143                     {
4144                       /* row at the end -- fixed */
4145                       area_above = dy - (tree_view->priv->vadjustment->upper -
4146                                    tree_view->priv->vadjustment->page_size);
4147                       area_below = tree_view->priv->vadjustment->page_size -
4148                                    area_above - height;
4149
4150                       if (area_below < 0)
4151                         {
4152                           area_above += area_below;
4153                           area_below = 0;
4154                         }
4155                     }
4156                   else
4157                     {
4158                       /* row somewhere in the middle, bring it to the top
4159                        * of the view
4160                        */
4161                       area_above = 0;
4162                       area_below = total_height - height;
4163                     }
4164                 }
4165             }
4166         }
4167       else
4168         /* the scroll to isn't valid; ignore it.
4169          */
4170         {
4171           if (tree_view->priv->scroll_to_path && !path)
4172             {
4173               gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
4174               tree_view->priv->scroll_to_path = NULL;
4175             }
4176           if (path)
4177             gtk_tree_path_free (path);
4178           path = NULL;
4179         }      
4180     }
4181
4182   /* We didn't have a scroll_to set, so we just handle things normally
4183    */
4184   if (path == NULL)
4185     {
4186       gint offset;
4187
4188       offset = _gtk_rbtree_find_offset (tree_view->priv->tree,
4189                                         TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, 0),
4190                                         &tree, &node);
4191       if (node == NULL)
4192         {
4193           /* In this case, nothing has been validated */
4194           path = gtk_tree_path_new_first ();
4195           _gtk_tree_view_find_node (tree_view, path, &tree, &node);
4196         }
4197       else
4198         {
4199           path = _gtk_tree_view_find_path (tree_view, tree, node);
4200           total_height += offset;
4201         }
4202
4203       gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
4204
4205       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
4206           GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
4207         {
4208           need_redraw = TRUE;
4209           if (validate_row (tree_view, tree, node, &iter, path))
4210             size_changed = TRUE;
4211         }
4212       area_above = 0;
4213       area_below = total_height - MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
4214     }
4215
4216   above_path = gtk_tree_path_copy (path);
4217
4218   /* Now, we walk forwards and backwards, measuring rows. Unfortunately,
4219    * backwards is much slower then forward, as there is no iter_prev function.
4220    * We go forwards first in case we run out of tree.  Then we go backwards to
4221    * fill out the top.
4222    */
4223   while (node && area_below > 0)
4224     {
4225       gint new_height;
4226
4227       if (node->children)
4228         {
4229           GtkTreeIter parent = iter;
4230           gboolean has_child;
4231
4232           tree = node->children;
4233           node = tree->root;
4234
4235           g_assert (node != tree->nil);
4236
4237           while (node->left != tree->nil)
4238             node = node->left;
4239           has_child = gtk_tree_model_iter_children (tree_view->priv->model,
4240                                                     &iter,
4241                                                     &parent);
4242           TREE_VIEW_INTERNAL_ASSERT_VOID (has_child);
4243           gtk_tree_path_down (path);
4244         }
4245       else
4246         {
4247           gboolean done = FALSE;
4248           do
4249             {
4250               node = _gtk_rbtree_next (tree, node);
4251               if (node != NULL)
4252                 {
4253                   gboolean has_next = gtk_tree_model_iter_next (tree_view->priv->model, &iter);
4254                   done = TRUE;
4255                   gtk_tree_path_next (path);
4256
4257                   /* Sanity Check! */
4258                   TREE_VIEW_INTERNAL_ASSERT_VOID (has_next);
4259                 }
4260               else
4261                 {
4262                   GtkTreeIter parent_iter = iter;
4263                   gboolean has_parent;
4264
4265                   node = tree->parent_node;
4266                   tree = tree->parent_tree;
4267                   if (tree == NULL)
4268                     break;
4269                   has_parent = gtk_tree_model_iter_parent (tree_view->priv->model,
4270                                                            &iter,
4271                                                            &parent_iter);
4272                   gtk_tree_path_up (path);
4273
4274                   /* Sanity check */
4275                   TREE_VIEW_INTERNAL_ASSERT_VOID (has_parent);
4276                 }
4277             }
4278           while (!done);
4279         }
4280
4281       if (!node)
4282         break;
4283
4284       new_height = GTK_RBNODE_GET_HEIGHT (node);
4285
4286       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
4287           GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
4288         {
4289           gint old_height = new_height;
4290
4291           need_redraw = TRUE;
4292           if (validate_row (tree_view, tree, node, &iter, path))
4293             {
4294               new_height = GTK_RBNODE_GET_HEIGHT (node);
4295               size_changed = TRUE;
4296
4297               area_below -= new_height - old_height;
4298             }
4299         }
4300
4301       area_below -= MAX (new_height, tree_view->priv->expander_size);
4302     }
4303   gtk_tree_path_free (path);
4304
4305   /* If we ran out of tree, and have extra area_below left, we need to add it
4306    * to area_above */
4307   if (area_below > 0)
4308     area_above += area_below;
4309
4310   _gtk_tree_view_find_node (tree_view, above_path, &tree, &node);
4311
4312   /* We walk backwards */
4313   while (area_above > 0)
4314     {
4315       gint new_height;
4316
4317       _gtk_rbtree_prev_full (tree, node, &tree, &node);
4318       if (! gtk_tree_path_prev (above_path) && node != NULL)
4319         {
4320           gtk_tree_path_free (above_path);
4321           above_path = _gtk_tree_view_find_path (tree_view, tree, node);
4322         }
4323       gtk_tree_model_get_iter (tree_view->priv->model, &iter, above_path);
4324
4325       if (node == NULL)
4326         break;
4327
4328       new_height = GTK_RBNODE_GET_HEIGHT (node);
4329
4330       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
4331           GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
4332         {
4333           gint old_height = new_height;
4334
4335           need_redraw = TRUE;
4336           if (validate_row (tree_view, tree, node, &iter, above_path))
4337             {
4338               new_height = GTK_RBNODE_GET_HEIGHT (node);
4339               size_changed = TRUE;
4340
4341               area_above -= new_height - old_height;
4342             }
4343         }
4344       area_above -= MAX (new_height, tree_view->priv->expander_size);
4345       update_dy = TRUE;
4346     }
4347
4348   if (size_changed)
4349     {
4350       GtkRequisition requisition;
4351
4352       /* We temporarily guess a size, under the assumption that it will be the
4353        * same when we get our next size_allocate.  If we don't do this, we'll be
4354        * in an inconsistent state if we call top_row_to_dy. */
4355       gtk_widget_size_request (GTK_WIDGET (tree_view), &requisition);
4356       tree_view->priv->hadjustment->upper = MAX (tree_view->priv->hadjustment->upper, (gfloat)requisition.width);
4357       tree_view->priv->vadjustment->upper = MAX (tree_view->priv->vadjustment->upper, (gfloat)requisition.height);
4358       gtk_adjustment_changed (tree_view->priv->hadjustment);
4359       gtk_adjustment_changed (tree_view->priv->vadjustment);
4360       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
4361     }
4362
4363   /* if we scroll at all, always update dy and kill the top_row */
4364   if (tree_view->priv->scroll_to_path &&
4365       ! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
4366     {
4367       update_dy = TRUE;
4368       if (tree_view->priv->top_row)
4369         {
4370           gtk_tree_row_reference_free (tree_view->priv->top_row);
4371           tree_view->priv->top_row = NULL;
4372         }
4373     }
4374
4375   /* if we walk backwards at all, then we need to reset our dy. */
4376   if (update_dy)
4377     {
4378       gint dy;
4379       if (node != NULL)
4380         {
4381           dy = _gtk_rbtree_node_find_offset (tree, node) - area_above;
4382         }
4383       else
4384         {
4385           dy = 0;
4386         }
4387
4388       gtk_adjustment_set_value (tree_view->priv->vadjustment, dy);
4389       need_redraw = TRUE;
4390     }
4391
4392   if (tree_view->priv->scroll_to_path)
4393     {
4394       gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
4395       tree_view->priv->scroll_to_path = NULL;
4396     }
4397
4398   if (above_path)
4399     gtk_tree_path_free (above_path);
4400
4401   if (tree_view->priv->scroll_to_column)
4402     {
4403       tree_view->priv->scroll_to_column = NULL;
4404     }
4405   if (need_redraw)
4406     gtk_widget_queue_draw (GTK_WIDGET (tree_view));
4407 }
4408
4409
4410 /* Our strategy for finding nodes to validate is a little convoluted.  We find
4411  * the left-most uninvalidated node.  We then try walking right, validating
4412  * nodes.  Once we find a valid node, we repeat the previous process of finding
4413  * the first invalid node.
4414  */
4415
4416 static gboolean
4417 do_validate_rows (GtkTreeView *tree_view)
4418 {
4419   GtkRBTree *tree = NULL;
4420   GtkRBNode *node = NULL;
4421   gboolean validated_area = FALSE;
4422   gint retval = TRUE;
4423   GtkTreePath *path = NULL;
4424   GtkTreeIter iter;
4425   gint i = 0;
4426
4427   gint prev_height = -1;
4428   gboolean fixed_height = TRUE;
4429
4430   g_assert (tree_view);
4431
4432   if (tree_view->priv->tree == NULL)
4433       return FALSE;
4434
4435   do
4436     {
4437       if (! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
4438         {
4439           retval = FALSE;
4440           goto done;
4441         }
4442
4443       if (path != NULL)
4444         {
4445           node = _gtk_rbtree_next (tree, node);
4446           if (node != NULL)
4447             {
4448               TREE_VIEW_INTERNAL_ASSERT (gtk_tree_model_iter_next (tree_view->priv->model, &iter), FALSE);
4449               gtk_tree_path_next (path);
4450             }
4451           else
4452             {
4453               gtk_tree_path_free (path);
4454               path = NULL;
4455             }
4456         }
4457
4458       if (path == NULL)
4459         {
4460           tree = tree_view->priv->tree;
4461           node = tree_view->priv->tree->root;
4462
4463           g_assert (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_DESCENDANTS_INVALID));
4464
4465           do
4466             {
4467               if (node->left != tree->nil &&
4468                   GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID))
4469                 {
4470                   node = node->left;
4471                 }
4472               else if (node->right != tree->nil &&
4473                        GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID))
4474                 {
4475                   node = node->right;
4476                 }
4477               else if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
4478                        GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
4479                 {
4480                   break;
4481                 }
4482               else if (node->children != NULL)
4483                 {
4484                   tree = node->children;
4485                   node = tree->root;
4486                 }
4487               else
4488                 /* RBTree corruption!  All bad */
4489                 g_assert_not_reached ();
4490             }
4491           while (TRUE);
4492           path = _gtk_tree_view_find_path (tree_view, tree, node);
4493           gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
4494         }
4495       validated_area = validate_row (tree_view, tree, node, &iter, path) ||
4496                        validated_area;
4497
4498       if (!tree_view->priv->fixed_height_check)
4499         {
4500           gint height;
4501
4502           height = MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
4503           if (prev_height < 0)
4504             prev_height = height;
4505           else if (prev_height != height)
4506             fixed_height = FALSE;
4507         }
4508
4509       i++;
4510     }
4511   while (i < GTK_TREE_VIEW_NUM_ROWS_PER_IDLE);
4512
4513   if (!tree_view->priv->fixed_height_check)
4514    {
4515      if (fixed_height)
4516        _gtk_rbtree_set_fixed_height (tree_view->priv->tree, prev_height);
4517
4518      tree_view->priv->fixed_height_check = 1;
4519    }
4520   
4521  done:
4522   if (validated_area)
4523     {
4524       GtkRequisition requisition;
4525       /* We temporarily guess a size, under the assumption that it will be the
4526        * same when we get our next size_allocate.  If we don't do this, we'll be
4527        * in an inconsistent state when we call top_row_to_dy. */
4528       gtk_widget_size_request (GTK_WIDGET (tree_view), &requisition);
4529       tree_view->priv->hadjustment->upper = MAX (tree_view->priv->hadjustment->upper, (gfloat)requisition.width);
4530       tree_view->priv->vadjustment->upper = MAX (tree_view->priv->vadjustment->upper, (gfloat)requisition.height);
4531       gtk_adjustment_changed (tree_view->priv->hadjustment);
4532       gtk_adjustment_changed (tree_view->priv->vadjustment);
4533       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
4534     }
4535
4536   if (gtk_tree_row_reference_valid (tree_view->priv->top_row))
4537     gtk_tree_view_top_row_to_dy (tree_view);
4538   else
4539     gtk_tree_view_dy_to_top_row (tree_view);
4540
4541   if (path) gtk_tree_path_free (path);
4542
4543   return retval;
4544 }
4545
4546 static gboolean
4547 validate_rows (GtkTreeView *tree_view)
4548 {
4549   gboolean retval;
4550   
4551   retval = do_validate_rows (tree_view);
4552   
4553   if (! retval && tree_view->priv->validate_rows_timer)
4554     {
4555       g_source_remove (tree_view->priv->validate_rows_timer);
4556       tree_view->priv->validate_rows_timer = 0;
4557     }
4558
4559   return retval;
4560 }
4561
4562 static gboolean
4563 validate_rows_handler (GtkTreeView *tree_view)
4564 {
4565   gboolean retval;
4566
4567   GDK_THREADS_ENTER ();
4568
4569   retval = do_validate_rows (tree_view);
4570   if (! retval && tree_view->priv->validate_rows_timer)
4571     {
4572       g_source_remove (tree_view->priv->validate_rows_timer);
4573       tree_view->priv->validate_rows_timer = 0;
4574     }
4575
4576   GDK_THREADS_LEAVE ();
4577
4578   return retval;
4579 }
4580
4581 static gboolean
4582 do_presize_handler (GtkTreeView *tree_view)
4583 {
4584   if (tree_view->priv->mark_rows_col_dirty)
4585     {
4586       if (tree_view->priv->tree)
4587         _gtk_rbtree_column_invalid (tree_view->priv->tree);
4588       tree_view->priv->mark_rows_col_dirty = FALSE;
4589     }
4590   validate_visible_area (tree_view);
4591   tree_view->priv->presize_handler_timer = 0;
4592                    
4593   return FALSE;
4594 }
4595
4596 static gboolean
4597 presize_handler_callback (gpointer data)
4598 {
4599   GDK_THREADS_ENTER ();
4600
4601   do_presize_handler (GTK_TREE_VIEW (data));
4602                    
4603   GDK_THREADS_LEAVE ();
4604
4605   return FALSE;
4606 }
4607
4608 static void
4609 install_presize_handler (GtkTreeView *tree_view)
4610 {
4611   if (! GTK_WIDGET_REALIZED (tree_view))
4612     return;
4613
4614   if (! tree_view->priv->presize_handler_timer)
4615     {
4616       tree_view->priv->presize_handler_timer =
4617         g_idle_add_full (GTK_PRIORITY_RESIZE - 2, presize_handler_callback, tree_view, NULL);
4618     }
4619   if (! tree_view->priv->validate_rows_timer)
4620     {
4621       tree_view->priv->validate_rows_timer =
4622         g_idle_add_full (GTK_TREE_VIEW_PRIORITY_VALIDATE, (GSourceFunc) validate_rows_handler, tree_view, NULL);
4623     }
4624 }
4625
4626 static gboolean
4627 scroll_sync_handler (GtkTreeView *tree_view)
4628 {
4629
4630   GDK_THREADS_ENTER ();
4631
4632   if (gtk_tree_row_reference_valid (tree_view->priv->top_row))
4633     gtk_tree_view_top_row_to_dy (tree_view);
4634   else
4635     gtk_tree_view_dy_to_top_row (tree_view);
4636
4637   tree_view->priv->scroll_sync_timer = 0;
4638
4639   GDK_THREADS_LEAVE ();
4640
4641   return FALSE;
4642 }
4643
4644 static void
4645 install_scroll_sync_handler (GtkTreeView *tree_view)
4646 {
4647   if (! GTK_WIDGET_REALIZED (tree_view))
4648     return;
4649
4650   if (!tree_view->priv->scroll_sync_timer)
4651     {
4652       tree_view->priv->scroll_sync_timer =
4653         g_idle_add_full (GTK_TREE_VIEW_PRIORITY_SCROLL_SYNC, (GSourceFunc) scroll_sync_handler, tree_view, NULL);
4654     }
4655 }
4656
4657 /* Always call this iff dy is in the visible range.  If the tree is empty, then
4658  * it's set to be NULL, and top_row_dy is 0;
4659  */
4660 static void
4661 gtk_tree_view_dy_to_top_row (GtkTreeView *tree_view)
4662 {
4663   GtkTreePath *path;
4664   GtkRBTree *tree;
4665   GtkRBNode *node;
4666
4667   gtk_tree_row_reference_free (tree_view->priv->top_row);
4668   if (tree_view->priv->tree == NULL)
4669     tree = NULL;
4670   else
4671     tree_view->priv->top_row_dy = _gtk_rbtree_find_offset (tree_view->priv->tree,
4672                                                            tree_view->priv->dy,
4673                                                            &tree, &node);
4674   if (tree == NULL)
4675     {
4676       tree_view->priv->top_row = NULL;
4677       tree_view->priv->top_row_dy = 0;
4678       return;
4679     }
4680       
4681   path = _gtk_tree_view_find_path (tree_view, tree, node);
4682   tree_view->priv->top_row = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
4683   gtk_tree_path_free (path);
4684 }
4685
4686 static void
4687 gtk_tree_view_top_row_to_dy (GtkTreeView *tree_view)
4688 {
4689   GtkTreePath *path;
4690   GtkRBTree *tree;
4691   GtkRBNode *node;
4692
4693   if (tree_view->priv->top_row)
4694     path = gtk_tree_row_reference_get_path (tree_view->priv->top_row);
4695   else
4696     path = NULL;
4697
4698   if (!path)
4699     tree = NULL;
4700   else
4701     _gtk_tree_view_find_node (tree_view, path, &tree, &node);
4702
4703   if (path)
4704     gtk_tree_path_free (path);
4705
4706   if (tree == NULL)
4707     {
4708       /* keep dy and set new toprow */
4709       gtk_tree_row_reference_free (tree_view->priv->top_row);
4710       tree_view->priv->top_row = NULL;
4711       tree_view->priv->top_row_dy = 0;
4712       /* DO NOT install the idle handler */
4713       gtk_tree_view_dy_to_top_row (tree_view);
4714       return;
4715     }
4716
4717   if (MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size)
4718       < tree_view->priv->top_row_dy)
4719     {
4720       /* new top row -- do NOT install the idle handler */
4721       gtk_tree_view_dy_to_top_row (tree_view);
4722       return;
4723     }
4724
4725   tree_view->priv->dy = _gtk_rbtree_node_find_offset (tree, node);
4726   tree_view->priv->dy += tree_view->priv->top_row_dy;
4727   gtk_adjustment_set_value (tree_view->priv->vadjustment,
4728                             (gdouble)tree_view->priv->dy);
4729 }
4730
4731
4732 void
4733 _gtk_tree_view_install_mark_rows_col_dirty (GtkTreeView *tree_view)
4734 {
4735   tree_view->priv->mark_rows_col_dirty = TRUE;
4736
4737   install_presize_handler (tree_view);
4738 }
4739
4740 /*
4741  * This function works synchronously (due to the while (validate_rows...)
4742  * loop).
4743  *
4744  * There was a check for column_type != GTK_TREE_VIEW_COLUMN_AUTOSIZE
4745  * here. You now need to check that yourself.
4746  */
4747 void
4748 _gtk_tree_view_column_autosize (GtkTreeView *tree_view,
4749                                 GtkTreeViewColumn *column)
4750 {
4751   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
4752   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (column));
4753
4754   _gtk_tree_view_column_cell_set_dirty (column, FALSE);
4755
4756   do_presize_handler (tree_view);
4757   while (validate_rows (tree_view));
4758
4759   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
4760 }
4761
4762 /* Drag-and-drop */
4763
4764 static void
4765 set_source_row (GdkDragContext *context,
4766                 GtkTreeModel   *model,
4767                 GtkTreePath    *source_row)
4768 {
4769   g_object_set_data_full (G_OBJECT (context),
4770                           "gtk-tree-view-source-row",
4771                           source_row ? gtk_tree_row_reference_new (model, source_row) : NULL,
4772                           (GDestroyNotify) (source_row ? gtk_tree_row_reference_free : NULL));
4773 }
4774
4775 static GtkTreePath*
4776 get_source_row (GdkDragContext *context)
4777 {
4778   GtkTreeRowReference *ref =
4779     g_object_get_data (G_OBJECT (context), "gtk-tree-view-source-row");
4780
4781   if (ref)
4782     return gtk_tree_row_reference_get_path (ref);
4783   else
4784     return NULL;
4785 }
4786
4787
4788 static void
4789 set_dest_row (GdkDragContext *context,
4790               GtkTreeModel   *model,
4791               GtkTreePath    *dest_row)
4792 {
4793   g_object_set_data_full (G_OBJECT (context),
4794                           "gtk-tree-view-dest-row",
4795                           dest_row ? gtk_tree_row_reference_new (model, dest_row) : NULL,
4796                           (GDestroyNotify) (dest_row ? gtk_tree_row_reference_free : NULL));
4797 }
4798
4799 static GtkTreePath*
4800 get_dest_row (GdkDragContext *context)
4801 {
4802   GtkTreeRowReference *ref =
4803     g_object_get_data (G_OBJECT (context), "gtk-tree-view-dest-row");
4804
4805   if (ref)
4806     return gtk_tree_row_reference_get_path (ref);
4807   else
4808     return NULL;
4809 }
4810
4811 /* Get/set whether drag_motion requested the drag data and
4812  * drag_data_received should thus not actually insert the data,
4813  * since the data doesn't result from a drop.
4814  */
4815 static void
4816 set_status_pending (GdkDragContext *context,
4817                     GdkDragAction   suggested_action)
4818 {
4819   g_object_set_data (G_OBJECT (context),
4820                      "gtk-tree-view-status-pending",
4821                      GINT_TO_POINTER (suggested_action));
4822 }
4823
4824 static GdkDragAction
4825 get_status_pending (GdkDragContext *context)
4826 {
4827   return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
4828                                              "gtk-tree-view-status-pending"));
4829 }
4830
4831 static TreeViewDragInfo*
4832 get_info (GtkTreeView *tree_view)
4833 {
4834   return g_object_get_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info");
4835 }
4836
4837 static void
4838 clear_source_info (TreeViewDragInfo *di)
4839 {
4840   if (di->source_target_list)
4841     gtk_target_list_unref (di->source_target_list);
4842
4843   di->source_target_list = NULL;
4844 }
4845
4846 static void
4847 clear_dest_info (TreeViewDragInfo *di)
4848 {
4849   if (di->dest_target_list)
4850     gtk_target_list_unref (di->dest_target_list);
4851
4852   di->dest_target_list = NULL;
4853 }
4854
4855 static void
4856 destroy_info (TreeViewDragInfo *di)
4857 {
4858   clear_source_info (di);
4859   clear_dest_info (di);
4860   g_free (di);
4861 }
4862
4863 static TreeViewDragInfo*
4864 ensure_info (GtkTreeView *tree_view)
4865 {
4866   TreeViewDragInfo *di;
4867
4868   di = get_info (tree_view);
4869
4870   if (di == NULL)
4871     {
4872       di = g_new0 (TreeViewDragInfo, 1);
4873
4874       g_object_set_data_full (G_OBJECT (tree_view),
4875                               "gtk-tree-view-drag-info",
4876                               di,
4877                               (GDestroyNotify) destroy_info);
4878     }
4879
4880   return di;
4881 }
4882
4883 static void
4884 remove_info (GtkTreeView *tree_view)
4885 {
4886   g_object_set_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info", NULL);
4887 }
4888
4889 #if 0
4890 static gint
4891 drag_scan_timeout (gpointer data)
4892 {
4893   GtkTreeView *tree_view;
4894   gint x, y;
4895   GdkModifierType state;
4896   GtkTreePath *path = NULL;
4897   GtkTreeViewColumn *column = NULL;
4898   GdkRectangle visible_rect;
4899
4900   GDK_THREADS_ENTER ();
4901
4902   tree_view = GTK_TREE_VIEW (data);
4903
4904   gdk_window_get_pointer (tree_view->priv->bin_window,
4905                           &x, &y, &state);
4906
4907   gtk_tree_view_get_visible_rect (tree_view, &visible_rect);
4908
4909   /* See if we are near the edge. */
4910   if ((x - visible_rect.x) < SCROLL_EDGE_SIZE ||
4911       (visible_rect.x + visible_rect.width - x) < SCROLL_EDGE_SIZE ||
4912       (y - visible_rect.y) < SCROLL_EDGE_SIZE ||
4913       (visible_rect.y + visible_rect.height - y) < SCROLL_EDGE_SIZE)
4914     {
4915       gtk_tree_view_get_path_at_pos (tree_view,
4916                                      tree_view->priv->bin_window,
4917                                      x, y,
4918                                      &path,
4919                                      &column,
4920                                      NULL,
4921                                      NULL);
4922
4923       if (path != NULL)
4924         {
4925           gtk_tree_view_scroll_to_cell (tree_view,
4926                                         path,
4927                                         column,
4928                                         TRUE,
4929                                         0.5, 0.5);
4930
4931           gtk_tree_path_free (path);
4932         }
4933     }
4934
4935   GDK_THREADS_LEAVE ();
4936
4937   return TRUE;
4938 }
4939 #endif /* 0 */
4940
4941 static void
4942 remove_scroll_timeout (GtkTreeView *tree_view)
4943 {
4944   if (tree_view->priv->scroll_timeout != 0)
4945     {
4946       g_source_remove (tree_view->priv->scroll_timeout);
4947       tree_view->priv->scroll_timeout = 0;
4948     }
4949 }
4950 static gboolean
4951 check_model_dnd (GtkTreeModel *model,
4952                  GType         required_iface,
4953                  const gchar  *signal)
4954 {
4955   if (model == NULL || !G_TYPE_CHECK_INSTANCE_TYPE ((model), required_iface))
4956     {
4957       g_warning ("You must override the default '%s' handler "
4958                  "on GtkTreeView when using models that don't support "
4959                  "the %s interface and enabling drag-and-drop. The simplest way to do this "
4960                  "is to connect to '%s' and call "
4961                  "g_signal_stop_emission_by_name() in your signal handler to prevent "
4962                  "the default handler from running. Look at the source code "
4963                  "for the default handler in gtktreeview.c to get an idea what "
4964                  "your handler should do. (gtktreeview.c is in the GTK source "
4965                  "code.) If you're using GTK from a language other than C, "
4966                  "there may be a more natural way to override default handlers, e.g. via derivation.",
4967                  signal, g_type_name (required_iface), signal);
4968       return FALSE;
4969     }
4970   else
4971     return TRUE;
4972 }
4973
4974 static void
4975 remove_open_timeout (GtkTreeView *tree_view)
4976 {
4977   if (tree_view->priv->open_dest_timeout != 0)
4978     {
4979       g_source_remove (tree_view->priv->open_dest_timeout);
4980       tree_view->priv->open_dest_timeout = 0;
4981     }
4982 }
4983
4984
4985 static gint
4986 open_row_timeout (gpointer data)
4987 {
4988   GtkTreeView *tree_view = data;
4989   GtkTreePath *dest_path = NULL;
4990   GtkTreeViewDropPosition pos;
4991   gboolean result = FALSE;
4992
4993   GDK_THREADS_ENTER ();
4994
4995   gtk_tree_view_get_drag_dest_row (tree_view,
4996                                    &dest_path,
4997                                    &pos);
4998
4999   if (dest_path &&
5000       (pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
5001        pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE))
5002     {
5003       gtk_tree_view_expand_row (tree_view, dest_path, FALSE);
5004       tree_view->priv->open_dest_timeout = 0;
5005
5006       gtk_tree_path_free (dest_path);
5007     }
5008   else
5009     {
5010       if (dest_path)
5011         gtk_tree_path_free (dest_path);
5012
5013       result = TRUE;
5014     }
5015
5016   GDK_THREADS_LEAVE ();
5017
5018   return result;
5019 }
5020
5021 static gint
5022 scroll_row_timeout (gpointer data)
5023 {
5024   GtkTreeView *tree_view = data;
5025
5026   GDK_THREADS_ENTER ();
5027
5028   gtk_tree_view_vertical_autoscroll (tree_view);
5029
5030   GDK_THREADS_LEAVE ();
5031
5032   return TRUE;
5033 }
5034
5035 /* Returns TRUE if event should not be propagated to parent widgets */
5036 static gboolean
5037 set_destination_row (GtkTreeView    *tree_view,
5038                      GdkDragContext *context,
5039                      gint            x,
5040                      gint            y,
5041                      GdkDragAction  *suggested_action,
5042                      GdkAtom        *target)
5043 {
5044   GtkTreePath *path = NULL;
5045   GtkTreeViewDropPosition pos;
5046   GtkTreeViewDropPosition old_pos;
5047   TreeViewDragInfo *di;
5048   GtkWidget *widget;
5049   GtkTreePath *old_dest_path = NULL;
5050
5051   *suggested_action = 0;
5052   *target = GDK_NONE;
5053
5054   widget = GTK_WIDGET (tree_view);
5055
5056   di = get_info (tree_view);
5057
5058   if (di == NULL || y - TREE_VIEW_HEADER_HEIGHT (tree_view) < 0)
5059     {
5060       /* someone unset us as a drag dest, note that if
5061        * we return FALSE drag_leave isn't called
5062        */
5063
5064       gtk_tree_view_set_drag_dest_row (tree_view,
5065                                        NULL,
5066                                        GTK_TREE_VIEW_DROP_BEFORE);
5067
5068       remove_scroll_timeout (GTK_TREE_VIEW (widget));
5069       remove_open_timeout (GTK_TREE_VIEW (widget));
5070
5071       return FALSE; /* no longer a drop site */
5072     }
5073
5074   *target = gtk_drag_dest_find_target (widget, context, di->dest_target_list);
5075   if (*target == GDK_NONE)
5076     {
5077       return FALSE;
5078     }
5079
5080   if (!gtk_tree_view_get_dest_row_at_pos (tree_view,
5081                                           x, y,
5082                                           &path,
5083                                           &pos))
5084     {
5085       /* can't drop here */
5086       remove_open_timeout (tree_view);
5087
5088       gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
5089                                        NULL,
5090                                        GTK_TREE_VIEW_DROP_BEFORE);
5091
5092       if (path)
5093         gtk_tree_path_free (path);
5094
5095       /* don't propagate to parent though */
5096       return TRUE;
5097     }
5098
5099   g_assert (path);
5100
5101   /* If we left the current row's "open" zone, unset the timeout for
5102    * opening the row
5103    */
5104   gtk_tree_view_get_drag_dest_row (tree_view,
5105                                    &old_dest_path,
5106                                    &old_pos);
5107
5108   if (old_dest_path &&
5109       (gtk_tree_path_compare (path, old_dest_path) != 0 ||
5110        !(pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
5111          pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)))
5112     remove_open_timeout (tree_view);
5113
5114   if (old_dest_path)
5115     gtk_tree_path_free (old_dest_path);
5116
5117   if (TRUE /* FIXME if the location droppable predicate */)
5118     {
5119       GtkWidget *source_widget;
5120
5121       *suggested_action = context->suggested_action;
5122
5123       source_widget = gtk_drag_get_source_widget (context);
5124
5125       if (source_widget == widget)
5126         {
5127           /* Default to MOVE, unless the user has
5128            * pressed ctrl or alt to affect available actions
5129            */
5130           if ((context->actions & GDK_ACTION_MOVE) != 0)
5131             *suggested_action = GDK_ACTION_MOVE;
5132         }
5133
5134       gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
5135                                        path, pos);
5136     }
5137   else
5138     {
5139       /* can't drop here */
5140       remove_open_timeout (tree_view);
5141
5142       gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
5143                                        NULL,
5144                                        GTK_TREE_VIEW_DROP_BEFORE);
5145     }
5146
5147   if (path)
5148     gtk_tree_path_free (path);
5149
5150   return TRUE;
5151 }
5152 static GtkTreePath*
5153 get_logical_dest_row (GtkTreeView *tree_view)
5154
5155 {
5156   /* adjust path to point to the row the drop goes in front of */
5157   GtkTreePath *path = NULL;
5158   GtkTreeViewDropPosition pos;
5159
5160   gtk_tree_view_get_drag_dest_row (tree_view, &path, &pos);
5161
5162   if (path == NULL)
5163     return NULL;
5164
5165   if (pos == GTK_TREE_VIEW_DROP_BEFORE)
5166     ; /* do nothing */
5167   else if (pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE ||
5168            pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
5169     {
5170       /* get first child, drop before it */
5171       gtk_tree_path_down (path);
5172     }
5173   else
5174     {
5175       GtkTreeIter iter;
5176       GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
5177
5178       g_assert (pos == GTK_TREE_VIEW_DROP_AFTER);
5179
5180       gtk_tree_model_get_iter (model, &iter, path);
5181
5182       if (!gtk_tree_model_iter_next (model, &iter))
5183         g_object_set_data (G_OBJECT (model), "gtk-tree-model-drop-append",
5184                            GINT_TO_POINTER (1));
5185       else
5186         {
5187           g_object_set_data (G_OBJECT (model), "gtk-tree-model-drop-append",
5188                              NULL);
5189           gtk_tree_path_next (path);
5190         }
5191     }
5192
5193   return path;
5194 }
5195
5196 static gboolean
5197 gtk_tree_view_maybe_begin_dragging_row (GtkTreeView      *tree_view,
5198                                         GdkEventMotion   *event)
5199 {
5200   GdkDragContext *context;
5201   TreeViewDragInfo *di;
5202   GtkTreePath *path = NULL;
5203   gint button;
5204   gint cell_x, cell_y;
5205   GtkTreeModel *model;
5206   gboolean retval = FALSE;
5207
5208   di = get_info (tree_view);
5209
5210   if (di == NULL)
5211     goto out;
5212
5213   if (tree_view->priv->pressed_button < 0)
5214     goto out;
5215
5216   if (!gtk_drag_check_threshold (GTK_WIDGET (tree_view),
5217                                  tree_view->priv->press_start_x,
5218                                  tree_view->priv->press_start_y,
5219                                  event->x, event->y))
5220     goto out;
5221
5222   model = gtk_tree_view_get_model (tree_view);
5223
5224   if (model == NULL)
5225     goto out;
5226
5227   button = tree_view->priv->pressed_button;
5228   tree_view->priv->pressed_button = -1;
5229
5230   gtk_tree_view_get_path_at_pos (tree_view,
5231                                  tree_view->priv->press_start_x,
5232                                  tree_view->priv->press_start_y,
5233                                  &path,
5234                                  NULL,
5235                                  &cell_x,
5236                                  &cell_y);
5237
5238   if (path == NULL)
5239     goto out;
5240
5241   if (!GTK_IS_TREE_DRAG_SOURCE (model) ||
5242       !gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (model),
5243                                            path))
5244     goto out;
5245
5246   /* FIXME Check whether we're a start button, if not return FALSE and
5247    * free path
5248    */
5249
5250   /* Now we can begin the drag */
5251
5252   retval = TRUE;
5253
5254   context = gtk_drag_begin (GTK_WIDGET (tree_view),
5255                             di->source_target_list,
5256                             di->source_actions,
5257                             button,
5258                             (GdkEvent*)event);
5259
5260   set_source_row (context, model, path);
5261
5262  out:
5263   if (path)
5264     gtk_tree_path_free (path);
5265
5266   return retval;
5267 }
5268
5269
5270 static void
5271 gtk_tree_view_drag_begin (GtkWidget      *widget,
5272                           GdkDragContext *context)
5273 {
5274   GtkTreeView *tree_view;
5275   GtkTreePath *path = NULL;
5276   gint cell_x, cell_y;
5277   GdkPixmap *row_pix;
5278
5279   tree_view = GTK_TREE_VIEW (widget);
5280
5281   /* if the user uses a custom DnD impl, we don't set the icon here */
5282   if (!get_info (tree_view))
5283     return;
5284
5285   gtk_tree_view_get_path_at_pos (tree_view,
5286                                  tree_view->priv->press_start_x,
5287                                  tree_view->priv->press_start_y,
5288                                  &path,
5289                                  NULL,
5290                                  &cell_x,
5291                                  &cell_y);
5292
5293   g_return_if_fail (path != NULL);
5294
5295   row_pix = gtk_tree_view_create_row_drag_icon (tree_view,
5296                                                 path);
5297
5298   gtk_drag_set_icon_pixmap (context,
5299                             gdk_drawable_get_colormap (row_pix),
5300                             row_pix,
5301                             NULL,
5302                             /* the + 1 is for the black border in the icon */
5303                             tree_view->priv->press_start_x + 1,
5304                             cell_y + 1);
5305
5306   g_object_unref (row_pix);
5307   gtk_tree_path_free (path);
5308 }
5309
5310 static void
5311 gtk_tree_view_drag_end (GtkWidget      *widget,
5312                         GdkDragContext *context)
5313 {
5314   /* do nothing */
5315 }
5316
5317 /* Default signal implementations for the drag signals */
5318 static void
5319 gtk_tree_view_drag_data_get (GtkWidget        *widget,
5320                              GdkDragContext   *context,
5321                              GtkSelectionData *selection_data,
5322                              guint             info,
5323                              guint             time)
5324 {
5325   GtkTreeView *tree_view;
5326   GtkTreeModel *model;
5327   TreeViewDragInfo *di;
5328   GtkTreePath *source_row;
5329
5330   tree_view = GTK_TREE_VIEW (widget);
5331
5332   model = gtk_tree_view_get_model (tree_view);
5333
5334   if (model == NULL)
5335     return;
5336
5337   di = get_info (GTK_TREE_VIEW (widget));
5338
5339   if (di == NULL)
5340     return;
5341
5342   source_row = get_source_row (context);
5343
5344   if (source_row == NULL)
5345     return;
5346
5347   /* We can implement the GTK_TREE_MODEL_ROW target generically for
5348    * any model; for DragSource models there are some other targets
5349    * we also support.
5350    */
5351
5352   if (GTK_IS_TREE_DRAG_SOURCE (model) &&
5353       gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (model),
5354                                           source_row,
5355                                           selection_data))
5356     goto done;
5357
5358   /* If drag_data_get does nothing, try providing row data. */
5359   if (selection_data->target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
5360     {
5361       gtk_tree_set_row_drag_data (selection_data,
5362                                   model,
5363                                   source_row);
5364     }
5365
5366  done:
5367   gtk_tree_path_free (source_row);
5368 }
5369
5370
5371 static void
5372 gtk_tree_view_drag_data_delete (GtkWidget      *widget,
5373                                 GdkDragContext *context)
5374 {
5375   TreeViewDragInfo *di;
5376   GtkTreeModel *model;
5377   GtkTreeView *tree_view;
5378   GtkTreePath *source_row;
5379
5380   tree_view = GTK_TREE_VIEW (widget);
5381   model = gtk_tree_view_get_model (tree_view);
5382
5383   if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_SOURCE, "drag_data_delete"))
5384     return;
5385
5386   di = get_info (tree_view);
5387
5388   if (di == NULL)
5389     return;
5390
5391   source_row = get_source_row (context);
5392
5393   if (source_row == NULL)
5394     return;
5395
5396   gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (model),
5397                                          source_row);
5398
5399   gtk_tree_path_free (source_row);
5400
5401   set_source_row (context, NULL, NULL);
5402 }
5403
5404 static void
5405 gtk_tree_view_drag_leave (GtkWidget      *widget,
5406                           GdkDragContext *context,
5407                           guint             time)
5408 {
5409   TreeViewDragInfo *di;
5410
5411   di = get_info (GTK_TREE_VIEW (widget));
5412
5413   /* unset any highlight row */
5414   gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
5415                                    NULL,
5416                                    GTK_TREE_VIEW_DROP_BEFORE);
5417
5418   remove_scroll_timeout (GTK_TREE_VIEW (widget));
5419   remove_open_timeout (GTK_TREE_VIEW (widget));
5420 }
5421
5422
5423 static gboolean
5424 gtk_tree_view_drag_motion (GtkWidget        *widget,
5425                            GdkDragContext   *context,
5426                            gint              x,
5427                            gint              y,
5428                            guint             time)
5429 {
5430   GtkTreePath *path = NULL;
5431   GtkTreeViewDropPosition pos;
5432   GtkTreeView *tree_view;
5433   GdkDragAction suggested_action = 0;
5434   GdkAtom target;
5435
5436   tree_view = GTK_TREE_VIEW (widget);
5437
5438   if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
5439     return FALSE;
5440
5441   gtk_tree_view_get_drag_dest_row (tree_view, &path, &pos);
5442
5443   if (path == NULL)
5444     {
5445       /* Can't drop here. */
5446       gdk_drag_status (context, 0, time);
5447     }
5448   else
5449     {
5450       if (tree_view->priv->open_dest_timeout == 0 &&
5451           (pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
5452            pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE))
5453         {
5454           tree_view->priv->open_dest_timeout =
5455             g_timeout_add (500, open_row_timeout, tree_view);
5456         }
5457       else if (tree_view->priv->scroll_timeout == 0)
5458         {
5459           tree_view->priv->scroll_timeout =
5460             g_timeout_add (150, scroll_row_timeout, tree_view);
5461         }
5462
5463       if (target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
5464         {
5465           /* Request data so we can use the source row when
5466            * determining whether to accept the drop
5467            */
5468           set_status_pending (context, suggested_action);
5469           gtk_drag_get_data (widget, context, target, time);
5470         }
5471       else
5472         {
5473           set_status_pending (context, 0);
5474           gdk_drag_status (context, suggested_action, time);
5475         }
5476     }
5477
5478   if (path)
5479     gtk_tree_path_free (path);
5480
5481   return TRUE;
5482 }
5483
5484
5485 static gboolean
5486 gtk_tree_view_drag_drop (GtkWidget        *widget,
5487                          GdkDragContext   *context,
5488                          gint              x,
5489                          gint              y,
5490                          guint             time)
5491 {
5492   GtkTreeView *tree_view;
5493   GtkTreePath *path;
5494   GdkDragAction suggested_action = 0;
5495   GdkAtom target = GDK_NONE;
5496   TreeViewDragInfo *di;
5497   GtkTreeModel *model;
5498
5499   tree_view = GTK_TREE_VIEW (widget);
5500
5501   model = gtk_tree_view_get_model (tree_view);
5502
5503   remove_scroll_timeout (GTK_TREE_VIEW (widget));
5504   remove_open_timeout (GTK_TREE_VIEW (widget));
5505
5506   di = get_info (tree_view);
5507
5508   if (di == NULL)
5509     return FALSE;
5510
5511   if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag_drop"))
5512     return FALSE;
5513
5514   if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
5515     return FALSE;
5516
5517   path = get_logical_dest_row (tree_view);
5518
5519   if (target != GDK_NONE && path != NULL)
5520     {
5521       /* in case a motion had requested drag data, change things so we
5522        * treat drag data receives as a drop.
5523        */
5524       set_status_pending (context, 0);
5525
5526       set_dest_row (context, model, path);
5527     }
5528
5529   if (path)
5530     gtk_tree_path_free (path);
5531
5532   /* Unset this thing */
5533   gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
5534                                    NULL,
5535                                    GTK_TREE_VIEW_DROP_BEFORE);
5536
5537   if (target != GDK_NONE)
5538     {
5539       gtk_drag_get_data (widget, context, target, time);
5540       return TRUE;
5541     }
5542   else
5543     return FALSE;
5544 }
5545
5546 static void
5547 gtk_tree_view_drag_data_received (GtkWidget        *widget,
5548                                   GdkDragContext   *context,
5549                                   gint              x,
5550                                   gint              y,
5551                                   GtkSelectionData *selection_data,
5552                                   guint             info,
5553                                   guint             time)
5554 {
5555   GtkTreePath *path;
5556   TreeViewDragInfo *di;
5557   gboolean accepted = FALSE;
5558   GtkTreeModel *model;
5559   GtkTreeView *tree_view;
5560   GtkTreePath *dest_row;
5561   GdkDragAction suggested_action;
5562
5563   tree_view = GTK_TREE_VIEW (widget);
5564
5565   model = gtk_tree_view_get_model (tree_view);
5566
5567   if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag_data_received"))
5568     return;
5569
5570   di = get_info (tree_view);
5571
5572   if (di == NULL)
5573     return;
5574
5575   suggested_action = get_status_pending (context);
5576
5577   if (suggested_action)
5578     {
5579       /* We are getting this data due to a request in drag_motion,
5580        * rather than due to a request in drag_drop, so we are just
5581        * supposed to call drag_status, not actually paste in the
5582        * data.
5583        */
5584       path = get_logical_dest_row (tree_view);
5585
5586       if (path == NULL)
5587         suggested_action = 0;
5588
5589       if (suggested_action)
5590         {
5591           if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
5592                                                      path,
5593                                                      selection_data))
5594             suggested_action = 0;
5595         }
5596
5597       gdk_drag_status (context, suggested_action, time);
5598
5599       if (path)
5600         gtk_tree_path_free (path);
5601
5602       /* If you can't drop, remove user drop indicator until the next motion */
5603       if (suggested_action == 0)
5604         gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
5605                                          NULL,
5606                                          GTK_TREE_VIEW_DROP_BEFORE);
5607
5608       return;
5609     }
5610
5611   dest_row = get_dest_row (context);
5612
5613   if (dest_row == NULL)
5614     return;
5615
5616   if (selection_data->length >= 0)
5617     {
5618       if (gtk_tree_drag_dest_drag_data_received (GTK_TREE_DRAG_DEST (model),
5619                                                  dest_row,
5620                                                  selection_data))
5621         accepted = TRUE;
5622     }
5623
5624   gtk_drag_finish (context,
5625                    accepted,
5626                    (context->action == GDK_ACTION_MOVE),
5627                    time);
5628
5629   if (gtk_tree_path_get_depth (dest_row) == 1
5630       && gtk_tree_path_get_indices (dest_row)[0] == 0)
5631     {
5632       /* special special case drag to "0", scroll to first item */
5633       if (!tree_view->priv->scroll_to_path)
5634         gtk_tree_view_scroll_to_cell (tree_view, dest_row, NULL, FALSE, 0.0, 0.0);
5635     }
5636
5637   gtk_tree_path_free (dest_row);
5638
5639   /* drop dest_row */
5640   set_dest_row (context, NULL, NULL);
5641 }
5642
5643
5644
5645 /* GtkContainer Methods
5646  */
5647
5648
5649 static void
5650 gtk_tree_view_remove (GtkContainer *container,
5651                       GtkWidget    *widget)
5652 {
5653   GtkTreeView *tree_view;
5654   GtkTreeViewChild *child = NULL;
5655   GList *tmp_list;
5656
5657   g_return_if_fail (GTK_IS_TREE_VIEW (container));
5658
5659   tree_view = GTK_TREE_VIEW (container);
5660
5661   tmp_list = tree_view->priv->children;
5662   while (tmp_list)
5663     {
5664       child = tmp_list->data;
5665       if (child->widget == widget)
5666         {
5667           gtk_widget_unparent (widget);
5668
5669           tree_view->priv->children = g_list_remove_link (tree_view->priv->children, tmp_list);
5670           g_list_free_1 (tmp_list);
5671           g_free (child);
5672           return;
5673         }
5674
5675       tmp_list = tmp_list->next;
5676     }
5677
5678   tmp_list = tree_view->priv->columns;
5679
5680   while (tmp_list)
5681     {
5682       GtkTreeViewColumn *column;
5683       column = tmp_list->data;
5684       if (column->button == widget)
5685         {
5686           gtk_widget_unparent (widget);
5687           return;
5688         }
5689       tmp_list = tmp_list->next;
5690     }
5691 }
5692
5693 static void
5694 gtk_tree_view_forall (GtkContainer *container,
5695                       gboolean      include_internals,
5696                       GtkCallback   callback,
5697                       gpointer      callback_data)
5698 {
5699   GtkTreeView *tree_view;
5700   GtkTreeViewChild *child = NULL;
5701   GtkTreeViewColumn *column;
5702   GList *tmp_list;
5703
5704   g_return_if_fail (GTK_IS_TREE_VIEW (container));
5705   g_return_if_fail (callback != NULL);
5706
5707   tree_view = GTK_TREE_VIEW (container);
5708
5709   tmp_list = tree_view->priv->children;
5710   while (tmp_list)
5711     {
5712       child = tmp_list->data;
5713       tmp_list = tmp_list->next;
5714
5715       (* callback) (child->widget, callback_data);
5716     }
5717   if (include_internals == FALSE)
5718     return;
5719
5720   for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
5721     {
5722       column = tmp_list->data;
5723
5724       if (column->button)
5725         (* callback) (column->button, callback_data);
5726     }
5727 }
5728
5729 /* Returns TRUE if the treeview contains no "special" (editable or activatable)
5730  * cells. If so we draw one big row-spanning focus rectangle.
5731  */
5732 static gboolean
5733 gtk_tree_view_has_special_cell (GtkTreeView *tree_view)
5734 {
5735   GList *list;
5736
5737   for (list = tree_view->priv->columns; list; list = list->next)
5738     {
5739       if (!((GtkTreeViewColumn *)list->data)->visible)
5740         continue;
5741       if (_gtk_tree_view_column_count_special_cells (list->data))
5742         return TRUE;
5743     }
5744
5745   return FALSE;
5746 }
5747
5748 /* Returns TRUE if the focus is within the headers, after the focus operation is
5749  * done
5750  */
5751 static gboolean
5752 gtk_tree_view_header_focus (GtkTreeView      *tree_view,
5753                             GtkDirectionType  dir)
5754 {
5755   GtkWidget *focus_child;
5756   GtkContainer *container;
5757
5758   GList *last_column, *first_column;
5759   GList *tmp_list;
5760   gboolean rtl;
5761
5762   if (! GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE))
5763     return FALSE;
5764
5765   focus_child = GTK_CONTAINER (tree_view)->focus_child;
5766   container = GTK_CONTAINER (tree_view);
5767
5768   first_column = tree_view->priv->columns;
5769   while (first_column)
5770     {
5771       if (GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (first_column->data)->button) &&
5772           GTK_TREE_VIEW_COLUMN (first_column->data)->visible &&
5773           (GTK_TREE_VIEW_COLUMN (first_column->data)->clickable ||
5774            GTK_TREE_VIEW_COLUMN (first_column->data)->reorderable))
5775         break;
5776       first_column = first_column->next;
5777     }
5778
5779   /* No headers are visible, or are focusable.  We can't focus in or out.
5780    */
5781   if (first_column == NULL)
5782     return FALSE;
5783
5784   last_column = g_list_last (tree_view->priv->columns);
5785   while (last_column)
5786     {
5787       if (GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (last_column->data)->button) &&
5788           GTK_TREE_VIEW_COLUMN (last_column->data)->visible &&
5789           (GTK_TREE_VIEW_COLUMN (last_column->data)->clickable ||
5790            GTK_TREE_VIEW_COLUMN (last_column->data)->reorderable))
5791         break;
5792       last_column = last_column->prev;
5793     }
5794
5795
5796    rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
5797    if (rtl) {
5798      GList *temp = first_column;
5799      first_column = last_column;
5800      last_column = temp;
5801    }
5802
5803   switch (dir)
5804     {
5805     case GTK_DIR_TAB_BACKWARD:
5806     case GTK_DIR_TAB_FORWARD:
5807     case GTK_DIR_UP:
5808     case GTK_DIR_DOWN:
5809       if (focus_child == NULL)
5810         {
5811           if (tree_view->priv->focus_column != NULL)
5812             focus_child = tree_view->priv->focus_column->button;
5813           else
5814             focus_child = GTK_TREE_VIEW_COLUMN (first_column->data)->button;
5815           gtk_widget_grab_focus (focus_child);
5816           break;
5817         }
5818       return FALSE;
5819
5820     case GTK_DIR_LEFT:
5821     case GTK_DIR_RIGHT:
5822       if (focus_child == NULL)
5823         {
5824           if (tree_view->priv->focus_column != NULL)
5825             focus_child = tree_view->priv->focus_column->button;
5826           else if (dir == GTK_DIR_LEFT)
5827             focus_child = GTK_TREE_VIEW_COLUMN (last_column->data)->button;
5828           else
5829             focus_child = GTK_TREE_VIEW_COLUMN (first_column->data)->button;
5830           gtk_widget_grab_focus (focus_child);
5831           break;
5832         }
5833
5834       if (gtk_widget_child_focus (focus_child, dir))
5835         {
5836           /* The focus moves inside the button. */
5837           /* This is probably a great example of bad UI */
5838           break;
5839         }
5840
5841       /* We need to move the focus among the row of buttons. */
5842       for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
5843         if (GTK_TREE_VIEW_COLUMN (tmp_list->data)->button == focus_child)
5844           break;
5845
5846       if (tmp_list == first_column && dir == GTK_DIR_LEFT)
5847         {
5848           focus_child = GTK_TREE_VIEW_COLUMN (last_column->data)->button;
5849           gtk_widget_grab_focus (focus_child);
5850           break;
5851         }
5852       else if (tmp_list == last_column && dir == GTK_DIR_RIGHT)
5853         {
5854           focus_child = GTK_TREE_VIEW_COLUMN (first_column->data)->button;
5855           gtk_widget_grab_focus (focus_child);
5856           break;
5857         }
5858
5859       while (tmp_list)
5860         {
5861           GtkTreeViewColumn *column;
5862
5863           if (dir == GTK_DIR_RIGHT)
5864             tmp_list = tmp_list->next;
5865           else
5866             tmp_list = tmp_list->prev;
5867
5868           if (tmp_list == NULL)
5869             {
5870               g_warning ("Internal button not found");
5871               break;
5872             }
5873           column = tmp_list->data;
5874           if (column->button &&
5875               column->visible &&
5876               GTK_WIDGET_CAN_FOCUS (column->button))
5877             {
5878               focus_child = column->button;
5879               gtk_widget_grab_focus (column->button);
5880               break;
5881             }
5882         }
5883       break;
5884     default:
5885       g_assert_not_reached ();
5886       break;
5887     }
5888
5889   /* if focus child is non-null, we assume it's been set to the current focus child
5890    */
5891   if (focus_child)
5892     {
5893       for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
5894         if (GTK_TREE_VIEW_COLUMN (tmp_list->data)->button == focus_child)
5895           break;
5896
5897       tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
5898
5899       /* If the following isn't true, then the view is smaller then the scrollpane.
5900        */
5901       if ((focus_child->allocation.x + focus_child->allocation.width) <=
5902           (tree_view->priv->hadjustment->upper))
5903         {
5904           /* Scroll to the button, if needed */
5905           if ((tree_view->priv->hadjustment->value + tree_view->priv->hadjustment->page_size) <
5906               (focus_child->allocation.x + focus_child->allocation.width))
5907             gtk_adjustment_set_value (tree_view->priv->hadjustment,
5908                                       focus_child->allocation.x + focus_child->allocation.width -
5909                                       tree_view->priv->hadjustment->page_size);
5910           else if (tree_view->priv->hadjustment->value > focus_child->allocation.x)
5911             gtk_adjustment_set_value (tree_view->priv->hadjustment,
5912                                       focus_child->allocation.x);
5913         }
5914     }
5915
5916   return (focus_child != NULL);
5917 }
5918
5919 static gint
5920 gtk_tree_view_focus (GtkWidget        *widget,
5921                      GtkDirectionType  direction)
5922 {
5923   GtkTreeView *tree_view;
5924   GtkWidget *focus_child;
5925   GtkContainer *container;
5926
5927   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
5928   g_return_val_if_fail (GTK_WIDGET_VISIBLE (widget), FALSE);
5929
5930   container = GTK_CONTAINER (widget);
5931   tree_view = GTK_TREE_VIEW (widget);
5932
5933   if (!GTK_WIDGET_IS_SENSITIVE (container))
5934     return FALSE;
5935
5936   focus_child = container->focus_child;
5937
5938   gtk_tree_view_stop_editing (GTK_TREE_VIEW (widget), FALSE);
5939   /* Case 1.  Headers currently have focus. */
5940   if (focus_child)
5941     {
5942       switch (direction)
5943         {
5944         case GTK_DIR_LEFT:
5945         case GTK_DIR_RIGHT:
5946           gtk_tree_view_header_focus (tree_view, direction);
5947           return TRUE;
5948         case GTK_DIR_TAB_BACKWARD:
5949         case GTK_DIR_UP:
5950           return FALSE;
5951         case GTK_DIR_TAB_FORWARD:
5952         case GTK_DIR_DOWN:
5953           if (tree_view->priv->tree == NULL)
5954             return FALSE;
5955           gtk_widget_grab_focus (widget);
5956           return TRUE;
5957         }
5958     }
5959
5960   /* Case 2. We don't have focus at all. */
5961   if (!GTK_WIDGET_HAS_FOCUS (container))
5962     {
5963       if (tree_view->priv->tree == NULL &&
5964           (direction == GTK_DIR_TAB_BACKWARD ||
5965            direction == GTK_DIR_UP))
5966         return gtk_tree_view_header_focus (tree_view, direction);
5967       if (((direction == GTK_DIR_TAB_FORWARD) ||
5968            (direction == GTK_DIR_RIGHT) ||
5969            (direction == GTK_DIR_DOWN) ||
5970            (direction == GTK_DIR_LEFT)) &&
5971           gtk_tree_view_header_focus (tree_view, direction))
5972         return TRUE;
5973
5974       if (tree_view->priv->tree == NULL)
5975         return FALSE;
5976       gtk_widget_grab_focus (widget);
5977       return TRUE;
5978     }
5979
5980   /* Case 3. We have focus already. */
5981   if (tree_view->priv->tree == NULL)
5982     return gtk_tree_view_header_focus (tree_view, direction);
5983
5984   if (direction == GTK_DIR_TAB_BACKWARD)
5985     return (gtk_tree_view_header_focus (tree_view, direction));
5986   else if (direction == GTK_DIR_TAB_FORWARD)
5987     return FALSE;
5988
5989   /* Other directions caught by the keybindings */
5990   gtk_widget_grab_focus (widget);
5991   return TRUE;
5992 }
5993
5994 static void
5995 gtk_tree_view_grab_focus (GtkWidget *widget)
5996 {
5997   (* GTK_WIDGET_CLASS (parent_class)->grab_focus) (widget);
5998
5999   gtk_tree_view_focus_to_cursor (GTK_TREE_VIEW (widget));
6000 }
6001
6002 static void
6003 gtk_tree_view_style_set (GtkWidget *widget,
6004                          GtkStyle *previous_style)
6005 {
6006   GtkTreeView *tree_view;
6007   GList *list;
6008   GtkTreeViewColumn *column;
6009
6010   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
6011
6012   tree_view = GTK_TREE_VIEW (widget);
6013
6014   if (GTK_WIDGET_REALIZED (widget))
6015     {
6016       gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
6017       gdk_window_set_background (tree_view->priv->bin_window, &widget->style->base[widget->state]);
6018     }
6019
6020   gtk_widget_style_get (widget,
6021                         "expander_size", &tree_view->priv->expander_size,
6022                         NULL);
6023   tree_view->priv->expander_size += EXPANDER_EXTRA_PADDING;
6024
6025   for (list = tree_view->priv->columns; list; list = list->next)
6026     {
6027       column = list->data;
6028       _gtk_tree_view_column_cell_set_dirty (column, TRUE);
6029     }
6030
6031   _gtk_rbtree_mark_invalid (tree_view->priv->tree);
6032
6033   gtk_widget_queue_resize (widget);
6034 }
6035
6036
6037 static void
6038 gtk_tree_view_set_focus_child (GtkContainer *container,
6039                                GtkWidget    *child)
6040 {
6041   GtkTreeView *tree_view = GTK_TREE_VIEW (container);
6042   GList *list;
6043
6044   for (list = tree_view->priv->columns; list; list = list->next)
6045     {
6046       if (GTK_TREE_VIEW_COLUMN (list->data)->button == child)
6047         {
6048           tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (list->data);
6049           break;
6050         }
6051     }
6052
6053   (* parent_class->set_focus_child) (container, child);
6054 }
6055
6056 static void
6057 gtk_tree_view_set_adjustments (GtkTreeView   *tree_view,
6058                                GtkAdjustment *hadj,
6059                                GtkAdjustment *vadj)
6060 {
6061   gboolean need_adjust = FALSE;
6062
6063   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
6064
6065   if (hadj)
6066     g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
6067   else
6068     hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
6069   if (vadj)
6070     g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
6071   else
6072     vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
6073
6074   if (tree_view->priv->hadjustment && (tree_view->priv->hadjustment != hadj))
6075     {
6076       g_signal_handlers_disconnect_by_func (tree_view->priv->hadjustment,
6077                                             gtk_tree_view_adjustment_changed,
6078                                             tree_view);
6079       g_object_unref (tree_view->priv->hadjustment);
6080     }
6081
6082   if (tree_view->priv->vadjustment && (tree_view->priv->vadjustment != vadj))
6083     {
6084       g_signal_handlers_disconnect_by_func (tree_view->priv->vadjustment,
6085                                             gtk_tree_view_adjustment_changed,
6086                                             tree_view);
6087       g_object_unref (tree_view->priv->vadjustment);
6088     }
6089
6090   if (tree_view->priv->hadjustment != hadj)
6091     {
6092       tree_view->priv->hadjustment = hadj;
6093       g_object_ref (tree_view->priv->hadjustment);
6094       gtk_object_sink (GTK_OBJECT (tree_view->priv->hadjustment));
6095
6096       g_signal_connect (tree_view->priv->hadjustment, "value_changed",
6097                         G_CALLBACK (gtk_tree_view_adjustment_changed),
6098                         tree_view);
6099       need_adjust = TRUE;
6100     }
6101
6102   if (tree_view->priv->vadjustment != vadj)
6103     {
6104       tree_view->priv->vadjustment = vadj;
6105       g_object_ref (tree_view->priv->vadjustment);
6106       gtk_object_sink (GTK_OBJECT (tree_view->priv->vadjustment));
6107
6108       g_signal_connect (tree_view->priv->vadjustment, "value_changed",
6109                         G_CALLBACK (gtk_tree_view_adjustment_changed),
6110                         tree_view);
6111       need_adjust = TRUE;
6112     }
6113
6114   if (need_adjust)
6115     gtk_tree_view_adjustment_changed (NULL, tree_view);
6116 }
6117
6118
6119 static gboolean
6120 gtk_tree_view_real_move_cursor (GtkTreeView       *tree_view,
6121                                 GtkMovementStep    step,
6122                                 gint               count)
6123 {
6124   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
6125   g_return_val_if_fail (step == GTK_MOVEMENT_LOGICAL_POSITIONS ||
6126                         step == GTK_MOVEMENT_VISUAL_POSITIONS ||
6127                         step == GTK_MOVEMENT_DISPLAY_LINES ||
6128                         step == GTK_MOVEMENT_PAGES ||
6129                         step == GTK_MOVEMENT_BUFFER_ENDS, FALSE);
6130
6131   if (tree_view->priv->tree == NULL)
6132     return FALSE;
6133   if (!GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (tree_view)))
6134     return FALSE;
6135
6136   gtk_tree_view_stop_editing (tree_view, FALSE);
6137   GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
6138   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
6139
6140   switch (step)
6141     {
6142       /* currently we make no distinction.  When we go bi-di, we need to */
6143     case GTK_MOVEMENT_LOGICAL_POSITIONS:
6144     case GTK_MOVEMENT_VISUAL_POSITIONS:
6145       gtk_tree_view_move_cursor_left_right (tree_view, count);
6146       break;
6147     case GTK_MOVEMENT_DISPLAY_LINES:
6148       gtk_tree_view_move_cursor_up_down (tree_view, count);
6149       break;
6150     case GTK_MOVEMENT_PAGES:
6151       gtk_tree_view_move_cursor_page_up_down (tree_view, count);
6152       break;
6153     case GTK_MOVEMENT_BUFFER_ENDS:
6154       gtk_tree_view_move_cursor_start_end (tree_view, count);
6155       break;
6156     default:
6157       g_assert_not_reached ();
6158     }
6159
6160   return TRUE;
6161 }
6162
6163 static void
6164 gtk_tree_view_put (GtkTreeView *tree_view,
6165                    GtkWidget   *child_widget,
6166                    gint         x,
6167                    gint         y,
6168                    gint         width,
6169                    gint         height)
6170 {
6171   GtkTreeViewChild *child;
6172
6173   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
6174   g_return_if_fail (GTK_IS_WIDGET (child_widget));
6175
6176   child = g_new (GtkTreeViewChild, 1);
6177
6178   child->widget = child_widget;
6179   child->x = x;
6180   child->y = y;
6181   child->width = width;
6182   child->height = height;
6183
6184   tree_view->priv->children = g_list_append (tree_view->priv->children, child);
6185
6186   if (GTK_WIDGET_REALIZED (tree_view))
6187     gtk_widget_set_parent_window (child->widget, tree_view->priv->bin_window);
6188
6189   gtk_widget_set_parent (child_widget, GTK_WIDGET (tree_view));
6190 }
6191
6192 void
6193 _gtk_tree_view_child_move_resize (GtkTreeView *tree_view,
6194                                   GtkWidget   *widget,
6195                                   gint         x,
6196                                   gint         y,
6197                                   gint         width,
6198                                   gint         height)
6199 {
6200   GtkTreeViewChild *child = NULL;
6201   GList *list;
6202   GdkRectangle allocation;
6203
6204   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
6205   g_return_if_fail (GTK_IS_WIDGET (widget));
6206
6207   for (list = tree_view->priv->children; list; list = list->next)
6208     {
6209       if (((GtkTreeViewChild *)list->data)->widget == widget)
6210         {
6211           child = list->data;
6212           break;
6213         }
6214     }
6215   if (child == NULL)
6216     return;
6217
6218   allocation.x = child->x = x;
6219   allocation.y = child->y = y;
6220   allocation.width = child->width = width;
6221   allocation.height = child->height = height;
6222
6223   if (GTK_WIDGET_REALIZED (widget))
6224     gtk_widget_size_allocate (widget, &allocation);
6225 }
6226
6227
6228 /* TreeModel Callbacks
6229  */
6230
6231 static void
6232 gtk_tree_view_row_changed (GtkTreeModel *model,
6233                            GtkTreePath  *path,
6234                            GtkTreeIter  *iter,
6235                            gpointer      data)
6236 {
6237   GtkTreeView *tree_view = (GtkTreeView *)data;
6238   GtkRBTree *tree;
6239   GtkRBNode *node;
6240   gboolean free_path = FALSE;
6241   gint vertical_separator;
6242   GList *list;
6243
6244   g_return_if_fail (path != NULL || iter != NULL);
6245
6246   if (!GTK_WIDGET_REALIZED (tree_view))
6247     /* We can just ignore ::changed signals if we aren't realized, as we don't care about sizes
6248      */
6249     return;
6250
6251   if (tree_view->priv->edited_column)
6252     gtk_tree_view_stop_editing (tree_view, TRUE);
6253
6254   gtk_widget_style_get (GTK_WIDGET (data), "vertical_separator", &vertical_separator, NULL);
6255
6256   if (path == NULL)
6257     {
6258       path = gtk_tree_model_get_path (model, iter);
6259       free_path = TRUE;
6260     }
6261   else if (iter == NULL)
6262     gtk_tree_model_get_iter (model, iter, path);
6263
6264   if (_gtk_tree_view_find_node (tree_view,
6265                                 path,
6266                                 &tree,
6267                                 &node))
6268     /* We aren't actually showing the node */
6269     goto done;
6270
6271   if (tree == NULL)
6272     goto done;
6273
6274   _gtk_rbtree_node_mark_invalid (tree, node);
6275   for (list = tree_view->priv->columns; list; list = list->next)
6276     {
6277       GtkTreeViewColumn *column;
6278
6279       column = list->data;
6280       if (! column->visible)
6281         continue;
6282
6283       if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
6284         {
6285           _gtk_tree_view_column_cell_set_dirty (column, TRUE);
6286         }
6287     }
6288
6289  done:
6290   install_presize_handler (tree_view);
6291   if (free_path)
6292     gtk_tree_path_free (path);
6293 }
6294
6295 static void
6296 gtk_tree_view_row_inserted (GtkTreeModel *model,
6297                             GtkTreePath  *path,
6298                             GtkTreeIter  *iter,
6299                             gpointer      data)
6300 {
6301   GtkTreeView *tree_view = (GtkTreeView *) data;
6302   gint *indices;
6303   GtkRBTree *tmptree, *tree;
6304   GtkRBNode *tmpnode = NULL;
6305   gint depth;
6306   gint i = 0;
6307   gboolean free_path = FALSE;
6308
6309   g_return_if_fail (path != NULL || iter != NULL);
6310
6311   if (path == NULL)
6312     {
6313       path = gtk_tree_model_get_path (model, iter);
6314       free_path = TRUE;
6315     }
6316   else if (iter == NULL)
6317     gtk_tree_model_get_iter (model, iter, path);
6318
6319   if (tree_view->priv->tree == NULL)
6320     tree_view->priv->tree = _gtk_rbtree_new ();
6321
6322   tmptree = tree = tree_view->priv->tree;
6323
6324   /* Update all row-references */
6325   gtk_tree_row_reference_inserted (G_OBJECT (data), path);
6326   depth = gtk_tree_path_get_depth (path);
6327   indices = gtk_tree_path_get_indices (path);
6328
6329   /* First, find the parent tree */
6330   while (i < depth - 1)
6331     {
6332       if (tmptree == NULL)
6333         {
6334           /* We aren't showing the node */
6335           goto done;
6336         }
6337
6338       tmpnode = _gtk_rbtree_find_count (tmptree, indices[i] + 1);
6339       if (tmpnode == NULL)
6340         {
6341           g_warning ("A node was inserted with a parent that's not in the tree.\n" \
6342                      "This possibly means that a GtkTreeModel inserted a child node\n" \
6343                      "before the parent was inserted.");
6344           goto done;
6345         }
6346       else if (!GTK_RBNODE_FLAG_SET (tmpnode, GTK_RBNODE_IS_PARENT))
6347         {
6348           /* FIXME enforce correct behavior on model, probably */
6349           /* In theory, the model should have emitted has_child_toggled here.  We
6350            * try to catch it anyway, just to be safe, in case the model hasn't.
6351            */
6352           GtkTreePath *tmppath = _gtk_tree_view_find_path (tree_view,
6353                                                            tree,
6354                                                            tmpnode);
6355           gtk_tree_view_row_has_child_toggled (model, tmppath, NULL, data);
6356           gtk_tree_path_free (tmppath);
6357           goto done;
6358         }
6359
6360       tmptree = tmpnode->children;
6361       tree = tmptree;
6362       i++;
6363     }
6364
6365   if (tree == NULL)
6366     goto done;
6367
6368   /* ref the node */
6369   gtk_tree_model_ref_node (tree_view->priv->model, iter);
6370   if (indices[depth - 1] == 0)
6371     {
6372       tmpnode = _gtk_rbtree_find_count (tree, 1);
6373       _gtk_rbtree_insert_before (tree, tmpnode, 0, FALSE);
6374     }
6375   else
6376     {
6377       tmpnode = _gtk_rbtree_find_count (tree, indices[depth - 1]);
6378       _gtk_rbtree_insert_after (tree, tmpnode, 0, FALSE);
6379     }
6380
6381  done:
6382   install_presize_handler (tree_view);
6383   if (free_path)
6384     gtk_tree_path_free (path);
6385 }
6386
6387 static void
6388 gtk_tree_view_row_has_child_toggled (GtkTreeModel *model,
6389                                      GtkTreePath  *path,
6390                                      GtkTreeIter  *iter,
6391                                      gpointer      data)
6392 {
6393   GtkTreeView *tree_view = (GtkTreeView *)data;
6394   GtkTreeIter real_iter;
6395   gboolean has_child;
6396   GtkRBTree *tree;
6397   GtkRBNode *node;
6398   gboolean free_path = FALSE;
6399
6400   g_return_if_fail (path != NULL || iter != NULL);
6401
6402   if (iter)
6403     real_iter = *iter;
6404
6405   if (path == NULL)
6406     {
6407       path = gtk_tree_model_get_path (model, iter);
6408       free_path = TRUE;
6409     }
6410   else if (iter == NULL)
6411     gtk_tree_model_get_iter (model, &real_iter, path);
6412
6413   if (_gtk_tree_view_find_node (tree_view,
6414                                 path,
6415                                 &tree,
6416                                 &node))
6417     /* We aren't actually showing the node */
6418     goto done;
6419
6420   if (tree == NULL)
6421     goto done;
6422
6423   has_child = gtk_tree_model_iter_has_child (model, &real_iter);
6424   /* Sanity check.
6425    */
6426   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT) == has_child)
6427     goto done;
6428
6429   if (has_child)
6430     GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_PARENT);
6431   else
6432     GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_IS_PARENT);
6433
6434   if (has_child && GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IS_LIST))
6435     {
6436       GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IS_LIST);
6437       if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_SHOW_EXPANDERS))
6438         {
6439           GList *list;
6440
6441           for (list = tree_view->priv->columns; list; list = list->next)
6442             if (GTK_TREE_VIEW_COLUMN (list->data)->visible)
6443               {
6444                 GTK_TREE_VIEW_COLUMN (list->data)->dirty = TRUE;
6445                 _gtk_tree_view_column_cell_set_dirty (GTK_TREE_VIEW_COLUMN (list->data), TRUE);
6446                 break;
6447               }
6448         }
6449       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
6450     }
6451   else
6452     {
6453       _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
6454     }
6455
6456  done:
6457   if (free_path)
6458     gtk_tree_path_free (path);
6459 }
6460
6461 static void
6462 count_children_helper (GtkRBTree *tree,
6463                        GtkRBNode *node,
6464                        gpointer   data)
6465 {
6466   if (node->children)
6467     _gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, count_children_helper, data);
6468   (*((gint *)data))++;
6469 }
6470
6471 static void
6472 check_selection_helper (GtkRBTree *tree,
6473                         GtkRBNode *node,
6474                         gpointer   data)
6475 {
6476   gint *value = (gint *)data;
6477
6478   *value = GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED);
6479
6480   if (node->children && !*value)
6481     _gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, check_selection_helper, data);
6482 }
6483
6484 static void
6485 gtk_tree_view_row_deleted (GtkTreeModel *model,
6486                            GtkTreePath  *path,
6487                            gpointer      data)
6488 {
6489   GtkTreeView *tree_view = (GtkTreeView *)data;
6490   GtkRBTree *tree;
6491   GtkRBNode *node;
6492   GList *list;
6493   gint selection_changed = FALSE;
6494
6495   g_return_if_fail (path != NULL);
6496
6497   gtk_tree_row_reference_deleted (G_OBJECT (data), path);
6498
6499   if (_gtk_tree_view_find_node (tree_view, path, &tree, &node))
6500     return;
6501
6502   if (tree == NULL)
6503     return;
6504
6505   /* check if the selection has been changed */
6506   _gtk_rbtree_traverse (tree, node, G_POST_ORDER,
6507                         check_selection_helper, &selection_changed);
6508
6509   for (list = tree_view->priv->columns; list; list = list->next)
6510     if (((GtkTreeViewColumn *)list->data)->visible &&
6511         ((GtkTreeViewColumn *)list->data)->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
6512       _gtk_tree_view_column_cell_set_dirty ((GtkTreeViewColumn *)list->data, TRUE);
6513
6514   /* Ensure we don't have a dangling pointer to a dead node */
6515   ensure_unprelighted (tree_view);
6516
6517   /* Cancel editting if we've started */
6518   gtk_tree_view_stop_editing (tree_view, TRUE);
6519
6520   /* If we have a node expanded/collapsed timeout, remove it */
6521   if (tree_view->priv->expand_collapse_timeout != 0)
6522     {
6523       g_source_remove (tree_view->priv->expand_collapse_timeout);
6524       tree_view->priv->expand_collapse_timeout = 0;
6525
6526       /* Reset node */
6527       GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_COLLAPSED);
6528       GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_EXPANDED);
6529       tree_view->priv->expanded_collapsed_node = NULL;
6530     }
6531
6532   if (tree_view->priv->destroy_count_func)
6533     {
6534       gint child_count = 0;
6535       if (node->children)
6536         _gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, count_children_helper, &child_count);
6537       (* tree_view->priv->destroy_count_func) (tree_view, path, child_count, tree_view->priv->destroy_count_data);
6538     }
6539
6540   if (tree->root->count == 1)
6541     {
6542       if (tree_view->priv->tree == tree)
6543         tree_view->priv->tree = NULL;
6544
6545       _gtk_rbtree_remove (tree);
6546     }
6547   else
6548     {
6549       _gtk_rbtree_remove_node (tree, node);
6550     }
6551
6552   if (! gtk_tree_row_reference_valid (tree_view->priv->top_row))
6553     {
6554       gtk_tree_row_reference_free (tree_view->priv->top_row);
6555       tree_view->priv->top_row = NULL;
6556     }
6557
6558   install_scroll_sync_handler (tree_view);
6559
6560   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
6561
6562   if (selection_changed)
6563     g_signal_emit_by_name (tree_view->priv->selection, "changed");
6564 }
6565
6566 static void
6567 cancel_arrow_animation (GtkTreeView *tree_view)
6568 {
6569   if (tree_view->priv->expand_collapse_timeout)
6570     while (do_expand_collapse (tree_view));
6571   tree_view->priv->expand_collapse_timeout = 0;
6572 }
6573
6574 static void
6575 gtk_tree_view_rows_reordered (GtkTreeModel *model,
6576                               GtkTreePath  *parent,
6577                               GtkTreeIter  *iter,
6578                               gint         *new_order,
6579                               gpointer      data)
6580 {
6581   GtkTreeView *tree_view = GTK_TREE_VIEW (data);
6582   GtkRBTree *tree;
6583   GtkRBNode *node;
6584   gint len;
6585
6586   len = gtk_tree_model_iter_n_children (model, iter);
6587
6588   if (len < 2)
6589     return;
6590
6591   gtk_tree_row_reference_reordered (G_OBJECT (data),
6592                                     parent,
6593                                     iter,
6594                                     new_order);
6595
6596   if (_gtk_tree_view_find_node (tree_view,
6597                                 parent,
6598                                 &tree,
6599                                 &node))
6600     return;
6601
6602   /* We need to special case the parent path */
6603   if (tree == NULL)
6604     tree = tree_view->priv->tree;
6605   else
6606     tree = node->children;
6607
6608   if (tree == NULL)
6609     return;
6610
6611   if (tree_view->priv->edited_column)
6612     gtk_tree_view_stop_editing (tree_view, TRUE);
6613
6614   /* we need to be unprelighted */
6615   ensure_unprelighted (tree_view);
6616
6617   /* clear the timeout */
6618   cancel_arrow_animation (tree_view);
6619   
6620   _gtk_rbtree_reorder (tree, new_order, len);
6621
6622   gtk_widget_queue_draw (GTK_WIDGET (tree_view));
6623
6624   gtk_tree_view_dy_to_top_row (tree_view);
6625 }
6626
6627
6628 /* Internal tree functions
6629  */
6630
6631
6632 static void
6633 gtk_tree_view_get_background_xrange (GtkTreeView       *tree_view,
6634                                      GtkRBTree         *tree,
6635                                      GtkTreeViewColumn *column,
6636                                      gint              *x1,
6637                                      gint              *x2)
6638 {
6639   GtkTreeViewColumn *tmp_column = NULL;
6640   gint total_width;
6641   GList *list;
6642   gboolean rtl;
6643
6644   if (x1)
6645     *x1 = 0;
6646
6647   if (x2)
6648     *x2 = 0;
6649
6650   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
6651
6652   total_width = 0;
6653   for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
6654        list;
6655        list = (rtl ? list->prev : list->next))
6656     {
6657       tmp_column = list->data;
6658
6659       if (tmp_column == column)
6660         break;
6661
6662       if (tmp_column->visible)
6663         total_width += tmp_column->width;
6664     }
6665
6666   if (tmp_column != column)
6667     {
6668       g_warning (G_STRLOC": passed-in column isn't in the tree");
6669       return;
6670     }
6671
6672   if (x1)
6673     *x1 = total_width;
6674
6675   if (x2)
6676     {
6677       if (column->visible)
6678         *x2 = total_width + column->width;
6679       else
6680         *x2 = total_width; /* width of 0 */
6681     }
6682 }
6683 static void
6684 gtk_tree_view_get_arrow_xrange (GtkTreeView *tree_view,
6685                                 GtkRBTree   *tree,
6686                                 gint        *x1,
6687                                 gint        *x2)
6688 {
6689   gint x_offset = 0;
6690   GList *list;
6691   GtkTreeViewColumn *tmp_column = NULL;
6692   gint total_width;
6693   gboolean indent_expanders;
6694   gboolean rtl;
6695
6696   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
6697
6698   total_width = 0;
6699   for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
6700        list;
6701        list = (rtl ? list->prev : list->next))
6702     {
6703       tmp_column = list->data;
6704
6705       if (gtk_tree_view_is_expander_column (tree_view, tmp_column))
6706         {
6707           if (rtl)
6708             x_offset = total_width + tmp_column->width - tree_view->priv->expander_size;
6709           else
6710             x_offset = total_width;
6711           break;
6712         }
6713
6714       if (tmp_column->visible)
6715         total_width += tmp_column->width;
6716     }
6717
6718   gtk_widget_style_get (GTK_WIDGET (tree_view),
6719                         "indent_expanders", &indent_expanders,
6720                         NULL);
6721
6722   if (indent_expanders)
6723     {
6724       if (rtl)
6725         x_offset -= tree_view->priv->expander_size * _gtk_rbtree_get_depth (tree);
6726       else
6727         x_offset += tree_view->priv->expander_size * _gtk_rbtree_get_depth (tree);
6728     }
6729   if (x1)
6730     {
6731       *x1 = x_offset;
6732     }
6733
6734   if (tmp_column && tmp_column->visible)
6735     {
6736       /* +1 because x2 isn't included in the range. */
6737       if (x2)
6738         *x2 = *x1 + tree_view->priv->expander_size + 1;
6739     }
6740   else
6741     {
6742       /* return an empty range, the expander column is hidden */
6743       if (x2)
6744         *x2 = *x1;
6745     }
6746 }
6747
6748 static void
6749 gtk_tree_view_build_tree (GtkTreeView *tree_view,
6750                           GtkRBTree   *tree,
6751                           GtkTreeIter *iter,
6752                           gint         depth,
6753                           gboolean     recurse)
6754 {
6755   GtkRBNode *temp = NULL;
6756
6757   do
6758     {
6759       gtk_tree_model_ref_node (tree_view->priv->model, iter);
6760       temp = _gtk_rbtree_insert_after (tree, temp, 0, FALSE);
6761       if (recurse)
6762         {
6763           GtkTreeIter child;
6764
6765           if (gtk_tree_model_iter_children (tree_view->priv->model, &child, iter))
6766             {
6767               temp->children = _gtk_rbtree_new ();
6768               temp->children->parent_tree = tree;
6769               temp->children->parent_node = temp;
6770               gtk_tree_view_build_tree (tree_view, temp->children, &child, depth + 1, recurse);
6771             }
6772         }
6773       if (gtk_tree_model_iter_has_child (tree_view->priv->model, iter))
6774         {
6775           if ((temp->flags&GTK_RBNODE_IS_PARENT) != GTK_RBNODE_IS_PARENT)
6776             temp->flags ^= GTK_RBNODE_IS_PARENT;
6777           GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IS_LIST);
6778         }
6779     }
6780   while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
6781 }
6782
6783 /* If height is non-NULL, then we set it to be the new height.  if it's all
6784  * dirty, then height is -1.  We know we'll remeasure dirty rows, anyways.
6785  */
6786 static gboolean
6787 gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view,
6788                                    GtkTreeIter *iter,
6789                                    gint         depth,
6790                                    gint        *height,
6791                                    GtkRBNode   *node)
6792 {
6793   GtkTreeViewColumn *column;
6794   GList *list;
6795   gboolean retval = FALSE;
6796   gint tmpheight;
6797   gint horizontal_separator;
6798
6799   gtk_widget_style_get (GTK_WIDGET (tree_view),
6800                         "horizontal_separator", &horizontal_separator,
6801                         NULL);
6802
6803   if (height)
6804     *height = -1;
6805
6806   for (list = tree_view->priv->columns; list; list = list->next)
6807     {
6808       gint width;
6809       column = list->data;
6810       if (column->dirty == TRUE)
6811         continue;
6812       if (height == NULL && column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
6813         continue;
6814       if (!column->visible)
6815         continue;
6816
6817       gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, iter,
6818                                                GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
6819                                                node->children?TRUE:FALSE);
6820
6821       if (height)
6822         {
6823           gtk_tree_view_column_cell_get_size (column,
6824                                               NULL, NULL, NULL,
6825                                               &width, &tmpheight);
6826           *height = MAX (*height, tmpheight);
6827         }
6828       else
6829         {
6830           gtk_tree_view_column_cell_get_size (column,
6831                                               NULL, NULL, NULL,
6832                                               &width, NULL);
6833         }
6834
6835       if (gtk_tree_view_is_expander_column (tree_view, column) &&
6836           TREE_VIEW_DRAW_EXPANDERS (tree_view))
6837         {
6838           if (depth * tree_view->priv->expander_size + horizontal_separator + width > column->requested_width)
6839             {
6840               _gtk_tree_view_column_cell_set_dirty (column, TRUE);
6841               retval = TRUE;
6842             }
6843         }
6844       else
6845         {
6846           if (horizontal_separator + width > column->requested_width)
6847             {
6848               _gtk_tree_view_column_cell_set_dirty (column, TRUE);
6849               retval = TRUE;
6850             }
6851         }
6852     }
6853
6854   return retval;
6855 }
6856
6857 static void
6858 gtk_tree_view_discover_dirty (GtkTreeView *tree_view,
6859                               GtkRBTree   *tree,
6860                               GtkTreeIter *iter,
6861                               gint         depth)
6862 {
6863   GtkRBNode *temp = tree->root;
6864   GtkTreeViewColumn *column;
6865   GList *list;
6866   GtkTreeIter child;
6867   gboolean is_all_dirty;
6868
6869   TREE_VIEW_INTERNAL_ASSERT_VOID (tree != NULL);
6870
6871   while (temp->left != tree->nil)
6872     temp = temp->left;
6873
6874   do
6875     {
6876       TREE_VIEW_INTERNAL_ASSERT_VOID (temp != NULL);
6877       is_all_dirty = TRUE;
6878       for (list = tree_view->priv->columns; list; list = list->next)
6879         {
6880           column = list->data;
6881           if (column->dirty == FALSE)
6882             {
6883               is_all_dirty = FALSE;
6884               break;
6885             }
6886         }
6887
6888       if (is_all_dirty)
6889         return;
6890
6891       gtk_tree_view_discover_dirty_iter (tree_view,
6892                                          iter,
6893                                          depth,
6894                                          NULL,
6895                                          temp);
6896       if (gtk_tree_model_iter_children (tree_view->priv->model, &child, iter) &&
6897           temp->children != NULL)
6898         gtk_tree_view_discover_dirty (tree_view, temp->children, &child, depth + 1);
6899       temp = _gtk_rbtree_next (tree, temp);
6900     }
6901   while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
6902 }
6903
6904
6905 /* Make sure the node is visible vertically */
6906 static void
6907 gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view,
6908                                   GtkRBTree   *tree,
6909                                   GtkRBNode   *node)
6910 {
6911   GtkTreePath *path = NULL;
6912
6913   if (!GTK_WIDGET_REALIZED (tree_view))
6914     return;
6915
6916   path = _gtk_tree_view_find_path (tree_view, tree, node);
6917
6918   if (path)
6919     {
6920       /* We process updates because we want to clear old selected items when we scroll.
6921        * if this is removed, we get a "selection streak" at the bottom. */
6922       gdk_window_process_updates (tree_view->priv->bin_window, TRUE);
6923       gtk_tree_view_scroll_to_cell (tree_view, path, NULL, FALSE, 0.0, 0.0);
6924       gtk_tree_path_free (path);
6925     }
6926 }
6927
6928 static void
6929 gtk_tree_view_clamp_column_visible (GtkTreeView       *tree_view,
6930                                     GtkTreeViewColumn *column)
6931 {
6932   if (column == NULL)
6933     return;
6934   if ((tree_view->priv->hadjustment->value + tree_view->priv->hadjustment->page_size) <
6935       (column->button->allocation.x + column->button->allocation.width))
6936     gtk_adjustment_set_value (tree_view->priv->hadjustment,
6937                               column->button->allocation.x + column->button->allocation.width -
6938                               tree_view->priv->hadjustment->page_size);
6939   else if (tree_view->priv->hadjustment->value > column->button->allocation.x)
6940     gtk_adjustment_set_value (tree_view->priv->hadjustment,
6941                               column->button->allocation.x);
6942 }
6943
6944 /* This function could be more efficient.  I'll optimize it if profiling seems
6945  * to imply that it is important */
6946 GtkTreePath *
6947 _gtk_tree_view_find_path (GtkTreeView *tree_view,
6948                           GtkRBTree   *tree,
6949                           GtkRBNode   *node)
6950 {
6951   GtkTreePath *path;
6952   GtkRBTree *tmp_tree;
6953   GtkRBNode *tmp_node, *last;
6954   gint count;
6955
6956   path = gtk_tree_path_new ();
6957
6958   g_return_val_if_fail (node != NULL, path);
6959   g_return_val_if_fail (node != tree->nil, path);
6960
6961   count = 1 + node->left->count;
6962
6963   last = node;
6964   tmp_node = node->parent;
6965   tmp_tree = tree;
6966   while (tmp_tree)
6967     {
6968       while (tmp_node != tmp_tree->nil)
6969         {
6970           if (tmp_node->right == last)
6971             count += 1 + tmp_node->left->count;
6972           last = tmp_node;
6973           tmp_node = tmp_node->parent;
6974         }
6975       gtk_tree_path_prepend_index (path, count - 1);
6976       last = tmp_tree->parent_node;
6977       tmp_tree = tmp_tree->parent_tree;
6978       if (last)
6979         {
6980           count = 1 + last->left->count;
6981           tmp_node = last->parent;
6982         }
6983     }
6984   return path;
6985 }
6986
6987 /* Returns TRUE if we ran out of tree before finding the path.  If the path is
6988  * invalid (ie. points to a node that's not in the tree), *tree and *node are
6989  * both set to NULL.
6990  */
6991 gboolean
6992 _gtk_tree_view_find_node (GtkTreeView  *tree_view,
6993                           GtkTreePath  *path,
6994                           GtkRBTree   **tree,
6995                           GtkRBNode   **node)
6996 {
6997   GtkRBNode *tmpnode = NULL;
6998   GtkRBTree *tmptree = tree_view->priv->tree;
6999   gint *indices = gtk_tree_path_get_indices (path);
7000   gint depth = gtk_tree_path_get_depth (path);
7001   gint i = 0;
7002
7003   *node = NULL;
7004   *tree = NULL;
7005
7006   if (depth == 0 || tmptree == NULL)
7007     return FALSE;
7008   do
7009     {
7010       tmpnode = _gtk_rbtree_find_count (tmptree, indices[i] + 1);
7011       ++i;
7012       if (tmpnode == NULL)
7013         {
7014           *tree = NULL;
7015           *node = NULL;
7016           return FALSE;
7017         }
7018       if (i >= depth)
7019         {
7020           *tree = tmptree;
7021           *node = tmpnode;
7022           return FALSE;
7023         }
7024       *tree = tmptree;
7025       *node = tmpnode;
7026       tmptree = tmpnode->children;
7027       if (tmptree == NULL)
7028         return TRUE;
7029     }
7030   while (1);
7031 }
7032
7033 static gboolean
7034 gtk_tree_view_is_expander_column (GtkTreeView       *tree_view,
7035                                   GtkTreeViewColumn *column)
7036 {
7037   GList *list;
7038
7039   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IS_LIST))
7040     return FALSE;
7041
7042   if (tree_view->priv->expander_column != NULL)
7043     {
7044       if (tree_view->priv->expander_column == column)
7045         return TRUE;
7046       return FALSE;
7047     }
7048   else
7049     {
7050       for (list = tree_view->priv->columns;
7051            list;
7052            list = list->next)
7053         if (((GtkTreeViewColumn *)list->data)->visible)
7054           break;
7055       if (list && list->data == column)
7056         return TRUE;
7057     }
7058   return FALSE;
7059 }
7060
7061 static void
7062 gtk_tree_view_add_move_binding (GtkBindingSet  *binding_set,
7063                                 guint           keyval,
7064                                 guint           modmask,
7065                                 GtkMovementStep step,
7066                                 gint            count)
7067 {
7068   
7069   gtk_binding_entry_add_signal (binding_set, keyval, modmask,
7070                                 "move_cursor", 2,
7071                                 G_TYPE_ENUM, step,
7072                                 G_TYPE_INT, count);
7073
7074   gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
7075                                 "move_cursor", 2,
7076                                 G_TYPE_ENUM, step,
7077                                 G_TYPE_INT, count);
7078
7079   if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
7080    return;
7081
7082   gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
7083                                 "move_cursor", 2,
7084                                 G_TYPE_ENUM, step,
7085                                 G_TYPE_INT, count);
7086
7087   gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK,
7088                                 "move_cursor", 2,
7089                                 G_TYPE_ENUM, step,
7090                                 G_TYPE_INT, count);
7091 }
7092
7093 static gint
7094 gtk_tree_view_unref_tree_helper (GtkTreeModel *model,
7095                                  GtkTreeIter  *iter,
7096                                  GtkRBTree    *tree,
7097                                  GtkRBNode    *node)
7098 {
7099   gint retval = FALSE;
7100   do
7101     {
7102       g_return_val_if_fail (node != NULL, FALSE);
7103
7104       if (node->children)
7105         {
7106           GtkTreeIter child;
7107           GtkRBTree *new_tree;
7108           GtkRBNode *new_node;
7109
7110           new_tree = node->children;
7111           new_node = new_tree->root;
7112
7113           while (new_node && new_node->left != new_tree->nil)
7114             new_node = new_node->left;
7115
7116           if (!gtk_tree_model_iter_children (model, &child, iter))
7117             return FALSE;
7118
7119           retval = retval || gtk_tree_view_unref_tree_helper (model, &child, new_tree, new_node);
7120         }
7121
7122       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
7123         retval = TRUE;
7124       gtk_tree_model_unref_node (model, iter);
7125       node = _gtk_rbtree_next (tree, node);
7126     }
7127   while (gtk_tree_model_iter_next (model, iter));
7128
7129   return retval;
7130 }
7131
7132 static gint
7133 gtk_tree_view_unref_and_check_selection_tree (GtkTreeView *tree_view,
7134                                               GtkRBTree   *tree)
7135 {
7136   GtkTreeIter iter;
7137   GtkTreePath *path;
7138   GtkRBNode *node;
7139   gint retval;
7140
7141   if (!tree)
7142     return FALSE;
7143
7144   node = tree->root;
7145   while (node && node->left != tree->nil)
7146     node = node->left;
7147
7148   g_return_val_if_fail (node != NULL, FALSE);
7149   path = _gtk_tree_view_find_path (tree_view, tree, node);
7150   gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_view->priv->model),
7151                            &iter, path);
7152   retval = gtk_tree_view_unref_tree_helper (GTK_TREE_MODEL (tree_view->priv->model), &iter, tree, node);
7153   gtk_tree_path_free (path);
7154
7155   return retval;
7156 }
7157
7158 static void
7159 gtk_tree_view_set_column_drag_info (GtkTreeView       *tree_view,
7160                                     GtkTreeViewColumn *column)
7161 {
7162   GtkTreeViewColumn *left_column;
7163   GtkTreeViewColumn *cur_column = NULL;
7164   GtkTreeViewColumnReorder *reorder;
7165   gboolean rtl;
7166   GList *tmp_list;
7167   gint left;
7168
7169   /* We want to precalculate the motion list such that we know what column slots
7170    * are available.
7171    */
7172   left_column = NULL;
7173   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
7174
7175   /* First, identify all possible drop spots */
7176   if (rtl)
7177     tmp_list = g_list_last (tree_view->priv->columns);
7178   else
7179     tmp_list = g_list_first (tree_view->priv->columns);
7180
7181   while (tmp_list)
7182     {
7183       cur_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
7184       tmp_list = rtl?g_list_previous (tmp_list):g_list_next (tmp_list);
7185
7186       if (cur_column->visible == FALSE)
7187         continue;
7188
7189       /* If it's not the column moving and func tells us to skip over the column, we continue. */
7190       if (left_column != column && cur_column != column &&
7191           tree_view->priv->column_drop_func &&
7192           ! (* tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
7193         {
7194           left_column = cur_column;
7195           continue;
7196         }
7197       reorder = g_new (GtkTreeViewColumnReorder, 1);
7198       reorder->left_column = left_column;
7199       left_column = reorder->right_column = cur_column;
7200
7201       tree_view->priv->column_drag_info = g_list_append (tree_view->priv->column_drag_info, reorder);
7202     }
7203
7204   /* Add the last one */
7205   if (tree_view->priv->column_drop_func == NULL ||
7206       ((left_column != column) &&
7207        (* tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data)))
7208     {
7209       reorder = g_new (GtkTreeViewColumnReorder, 1);
7210       reorder->left_column = left_column;
7211       reorder->right_column = NULL;
7212       tree_view->priv->column_drag_info = g_list_append (tree_view->priv->column_drag_info, reorder);
7213     }
7214
7215   /* We quickly check to see if it even makes sense to reorder columns. */
7216   /* If there is nothing that can be moved, then we return */
7217
7218   if (tree_view->priv->column_drag_info == NULL)
7219     return;
7220
7221   /* We know there are always 2 slots possbile, as you can always return column. */
7222   /* If that's all there is, return */
7223   if (tree_view->priv->column_drag_info->next->next == NULL &&
7224       ((GtkTreeViewColumnReorder *)tree_view->priv->column_drag_info->data)->right_column == column &&
7225       ((GtkTreeViewColumnReorder *)tree_view->priv->column_drag_info->next->data)->left_column == column)
7226     {
7227       for (tmp_list = tree_view->priv->column_drag_info; tmp_list; tmp_list = tmp_list->next)
7228         g_free (tmp_list->data);
7229       g_list_free (tree_view->priv->column_drag_info);
7230       tree_view->priv->column_drag_info = NULL;
7231       return;
7232     }
7233   /* We fill in the ranges for the columns, now that we've isolated them */
7234   left = - TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER (tree_view);
7235
7236   for (tmp_list = tree_view->priv->column_drag_info; tmp_list; tmp_list = tmp_list->next)
7237     {
7238       reorder = (GtkTreeViewColumnReorder *) tmp_list->data;
7239
7240       reorder->left_align = left;
7241       if (tmp_list->next != NULL)
7242         {
7243           g_assert (tmp_list->next->data);
7244           left = reorder->right_align = (reorder->right_column->button->allocation.x +
7245                                          reorder->right_column->button->allocation.width +
7246                                          ((GtkTreeViewColumnReorder *)tmp_list->next->data)->left_column->button->allocation.x)/2;
7247         }
7248       else
7249         {
7250           gint width;
7251
7252           gdk_drawable_get_size (tree_view->priv->header_window, &width, NULL);
7253           reorder->right_align = width + TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER (tree_view);
7254         }
7255     }
7256 }
7257
7258 void
7259 _gtk_tree_view_column_start_drag (GtkTreeView       *tree_view,
7260                                   GtkTreeViewColumn *column)
7261 {
7262   GdkEvent *send_event;
7263   GtkAllocation allocation;
7264   gint x, y, width, height;
7265   GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (tree_view));
7266   GdkDisplay *display = gdk_screen_get_display (screen);
7267
7268   g_return_if_fail (tree_view->priv->column_drag_info == NULL);
7269
7270   gtk_tree_view_set_column_drag_info (tree_view, column);
7271
7272   if (tree_view->priv->column_drag_info == NULL)
7273     return;
7274
7275   if (tree_view->priv->drag_window == NULL)
7276     {
7277       GdkWindowAttr attributes;
7278       guint attributes_mask;
7279
7280       attributes.window_type = GDK_WINDOW_CHILD;
7281       attributes.wclass = GDK_INPUT_OUTPUT;
7282       attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
7283       attributes.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
7284       attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
7285       attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
7286
7287       tree_view->priv->drag_window = gdk_window_new (tree_view->priv->bin_window,
7288                                                      &attributes,
7289                                                      attributes_mask);
7290       gdk_window_set_user_data (tree_view->priv->drag_window, GTK_WIDGET (tree_view));
7291     }
7292
7293   gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
7294   gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
7295
7296   gtk_grab_remove (column->button);
7297
7298   send_event = gdk_event_new (GDK_LEAVE_NOTIFY);
7299   send_event->crossing.send_event = TRUE;
7300   send_event->crossing.window = g_object_ref (column->button->window);
7301   send_event->crossing.subwindow = NULL;
7302   send_event->crossing.detail = GDK_NOTIFY_ANCESTOR;
7303   send_event->crossing.time = GDK_CURRENT_TIME;
7304
7305   gtk_propagate_event (column->button, send_event);
7306   gdk_event_free (send_event);
7307
7308   send_event = gdk_event_new (GDK_BUTTON_RELEASE);
7309   send_event->button.window = g_object_ref (gdk_screen_get_root_window (screen));
7310   send_event->button.send_event = TRUE;
7311   send_event->button.time = GDK_CURRENT_TIME;
7312   send_event->button.x = -1;
7313   send_event->button.y = -1;
7314   send_event->button.axes = NULL;
7315   send_event->button.state = 0;
7316   send_event->button.button = 1;
7317   send_event->button.device = gdk_display_get_core_pointer (display);
7318   send_event->button.x_root = 0;
7319   send_event->button.y_root = 0;
7320
7321   gtk_propagate_event (column->button, send_event);
7322   gdk_event_free (send_event);
7323
7324   gdk_window_move_resize (tree_view->priv->drag_window,
7325                           column->button->allocation.x,
7326                           0,
7327                           column->button->allocation.width,
7328                           column->button->allocation.height);
7329
7330   /* Kids, don't try this at home */
7331   g_object_ref (column->button);
7332   gtk_container_remove (GTK_CONTAINER (tree_view), column->button);
7333   gtk_widget_set_parent_window (column->button, tree_view->priv->drag_window);
7334   gtk_widget_set_parent (column->button, GTK_WIDGET (tree_view));
7335   g_object_unref (column->button);
7336
7337   tree_view->priv->drag_column_x = column->button->allocation.x;
7338   allocation = column->button->allocation;
7339   allocation.x = 0;
7340   gtk_widget_size_allocate (column->button, &allocation);
7341   gtk_widget_set_parent_window (column->button, tree_view->priv->drag_window);
7342
7343   tree_view->priv->drag_column = column;
7344   gdk_window_show (tree_view->priv->drag_window);
7345
7346   gdk_window_get_origin (tree_view->priv->header_window, &x, &y);
7347   gdk_drawable_get_size (tree_view->priv->header_window, &width, &height);
7348
7349   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
7350   while (gtk_events_pending ())
7351     gtk_main_iteration ();
7352
7353   GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG);
7354   gdk_pointer_grab (tree_view->priv->drag_window,
7355                     FALSE,
7356                     GDK_POINTER_MOTION_MASK|GDK_BUTTON_RELEASE_MASK,
7357                     NULL, NULL, GDK_CURRENT_TIME);
7358   gdk_keyboard_grab (tree_view->priv->drag_window,
7359                      FALSE,
7360                      GDK_CURRENT_TIME);
7361
7362 }
7363
7364 static void
7365 gtk_tree_view_queue_draw_arrow (GtkTreeView      *tree_view,
7366                                 GtkRBTree        *tree,
7367                                 GtkRBNode        *node,
7368                                 GdkRectangle     *clip_rect)
7369 {
7370   GdkRectangle rect;
7371
7372   if (!GTK_WIDGET_REALIZED (tree_view))
7373     return;
7374
7375   rect.x = 0;
7376   rect.width = MAX (tree_view->priv->expander_size, GTK_WIDGET (tree_view)->allocation.width);
7377
7378   rect.y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
7379   rect.height = MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size);
7380
7381   if (clip_rect)
7382     {
7383       GdkRectangle new_rect;
7384
7385       gdk_rectangle_intersect (clip_rect, &rect, &new_rect);
7386
7387       gdk_window_invalidate_rect (tree_view->priv->bin_window, &new_rect, TRUE);
7388     }
7389   else
7390     {
7391       gdk_window_invalidate_rect (tree_view->priv->bin_window, &rect, TRUE);
7392     }
7393 }
7394
7395 void
7396 _gtk_tree_view_queue_draw_node (GtkTreeView  *tree_view,
7397                                 GtkRBTree    *tree,
7398                                 GtkRBNode    *node,
7399                                 GdkRectangle *clip_rect)
7400 {
7401   GdkRectangle rect;
7402
7403   if (!GTK_WIDGET_REALIZED (tree_view))
7404     return;
7405
7406   rect.x = 0;
7407   rect.width = MAX (tree_view->priv->width, GTK_WIDGET (tree_view)->allocation.width);
7408
7409   rect.y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
7410   rect.height = MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size);
7411
7412   if (clip_rect)
7413     {
7414       GdkRectangle new_rect;
7415
7416       gdk_rectangle_intersect (clip_rect, &rect, &new_rect);
7417
7418       gdk_window_invalidate_rect (tree_view->priv->bin_window, &new_rect, TRUE);
7419     }
7420   else
7421     {
7422       gdk_window_invalidate_rect (tree_view->priv->bin_window, &rect, TRUE);
7423     }
7424 }
7425
7426 static void
7427 gtk_tree_view_queue_draw_path (GtkTreeView      *tree_view,
7428                                GtkTreePath      *path,
7429                                GdkRectangle     *clip_rect)
7430 {
7431   GtkRBTree *tree = NULL;
7432   GtkRBNode *node = NULL;
7433
7434   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
7435
7436   if (tree)
7437     _gtk_tree_view_queue_draw_node (tree_view, tree, node, clip_rect);
7438 }
7439
7440 /* x and y are the mouse position
7441  */
7442 static void
7443 gtk_tree_view_draw_arrow (GtkTreeView *tree_view,
7444                           GtkRBTree   *tree,
7445                           GtkRBNode   *node,
7446                           gint         x,
7447                           gint         y)
7448 {
7449   GdkRectangle area;
7450   GtkStateType state;
7451   GtkWidget *widget;
7452   gint x_offset = 0;
7453   gint vertical_separator;
7454   gint expander_size;
7455   GtkExpanderStyle expander_style;
7456
7457   gtk_widget_style_get (GTK_WIDGET (tree_view),
7458                         "vertical_separator", &vertical_separator,
7459                         NULL);
7460   expander_size = tree_view->priv->expander_size - EXPANDER_EXTRA_PADDING;
7461
7462   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
7463     return;
7464
7465   widget = GTK_WIDGET (tree_view);
7466
7467   gtk_tree_view_get_arrow_xrange (tree_view, tree, &x_offset, NULL);
7468
7469   area.x = x_offset;
7470   area.y = CELL_FIRST_PIXEL (tree_view, tree, node, vertical_separator);
7471   area.width = expander_size + 2;
7472   area.height = MAX (CELL_HEIGHT (node, vertical_separator), (expander_size - vertical_separator));
7473
7474   if (node == tree_view->priv->button_pressed_node)
7475     {
7476       if (x >= area.x && x <= (area.x + area.width) &&
7477           y >= area.y && y <= (area.y + area.height))
7478         state = GTK_STATE_ACTIVE;
7479       else
7480         state = GTK_STATE_NORMAL;
7481     }
7482   else
7483     {
7484       if (node == tree_view->priv->prelight_node &&
7485           GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
7486         state = GTK_STATE_PRELIGHT;
7487       else
7488         state = GTK_STATE_NORMAL;
7489     }
7490
7491   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SEMI_EXPANDED))
7492     expander_style = GTK_EXPANDER_SEMI_EXPANDED;
7493   else if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SEMI_COLLAPSED))
7494     expander_style = GTK_EXPANDER_SEMI_COLLAPSED;
7495   else if (node->children != NULL)
7496     expander_style = GTK_EXPANDER_EXPANDED;
7497   else
7498     expander_style = GTK_EXPANDER_COLLAPSED;
7499
7500   gtk_paint_expander (widget->style,
7501                       tree_view->priv->bin_window,
7502                       state,
7503                       &area,
7504                       widget,
7505                       "treeview",
7506                       area.x + area.width / 2,
7507                       area.y + area.height / 2,
7508                       expander_style);
7509 }
7510
7511 static void
7512 gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view)
7513
7514 {
7515   GtkTreePath *cursor_path;
7516
7517   if ((tree_view->priv->tree == NULL) ||
7518       (! GTK_WIDGET_REALIZED (tree_view)))
7519     return;
7520
7521   GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
7522
7523   cursor_path = NULL;
7524   if (tree_view->priv->cursor)
7525     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
7526
7527   if (cursor_path == NULL)
7528     {
7529       cursor_path = gtk_tree_path_new_first ();
7530       gtk_tree_row_reference_free (tree_view->priv->cursor);
7531       tree_view->priv->cursor = NULL;
7532
7533       if (tree_view->priv->selection->type == GTK_SELECTION_MULTIPLE)
7534         gtk_tree_view_real_set_cursor (tree_view, cursor_path, FALSE, FALSE);
7535       else
7536         gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE);
7537     }
7538   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
7539   gtk_tree_path_free (cursor_path);
7540
7541   if (tree_view->priv->focus_column == NULL)
7542     {
7543       GList *list;
7544       for (list = tree_view->priv->columns; list; list = list->next)
7545         {
7546           if (GTK_TREE_VIEW_COLUMN (list->data)->visible)
7547             {
7548               tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (list->data);
7549               break;
7550             }
7551         }
7552     }
7553 }
7554
7555 static void
7556 gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
7557                                    gint         count)
7558 {
7559   GtkRBTree *cursor_tree = NULL;
7560   GtkRBNode *cursor_node = NULL;
7561   GtkRBTree *new_cursor_tree = NULL;
7562   GtkRBNode *new_cursor_node = NULL;
7563   GtkTreePath *cursor_path = NULL;
7564
7565   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
7566     return;
7567
7568   cursor_path = NULL;
7569   if (!gtk_tree_row_reference_valid (tree_view->priv->cursor))
7570     /* FIXME: we lost the cursor; should we get the first? */
7571     return;
7572
7573   cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
7574   _gtk_tree_view_find_node (tree_view, cursor_path,
7575                             &cursor_tree, &cursor_node);
7576   gtk_tree_path_free (cursor_path);
7577
7578   if (cursor_tree == NULL)
7579     /* FIXME: we lost the cursor; should we get the first? */
7580     return;
7581   if (count == -1)
7582     _gtk_rbtree_prev_full (cursor_tree, cursor_node,
7583                            &new_cursor_tree, &new_cursor_node);
7584   else
7585     _gtk_rbtree_next_full (cursor_tree, cursor_node,
7586                            &new_cursor_tree, &new_cursor_node);
7587
7588   if (new_cursor_node)
7589     {
7590       cursor_path = _gtk_tree_view_find_path (tree_view, new_cursor_tree, new_cursor_node);
7591       gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE);
7592       gtk_tree_path_free (cursor_path);
7593     }
7594   else
7595     {
7596       gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
7597     }
7598
7599   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
7600 }
7601
7602 static void
7603 gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
7604                                         gint         count)
7605 {
7606   GtkRBTree *cursor_tree = NULL;
7607   GtkRBNode *cursor_node = NULL;
7608   GtkTreePath *cursor_path = NULL;
7609   gint y;
7610   gint vertical_separator;
7611
7612   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
7613     return;
7614
7615   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
7616     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
7617   else
7618     /* This is sorta weird.  Focus in should give us a cursor */
7619     return;
7620
7621   gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical_separator", &vertical_separator, NULL);
7622   _gtk_tree_view_find_node (tree_view, cursor_path,
7623                             &cursor_tree, &cursor_node);
7624
7625   gtk_tree_path_free (cursor_path);
7626
7627   if (cursor_tree == NULL)
7628     /* FIXME: we lost the cursor.  Should we try to get one? */
7629     return;
7630   g_return_if_fail (cursor_node != NULL);
7631
7632   y = _gtk_rbtree_node_find_offset (cursor_tree, cursor_node);
7633   y += count * tree_view->priv->vadjustment->page_size;
7634   if (count > 0)
7635     y -= MAX (GTK_RBNODE_GET_HEIGHT (cursor_node),
7636               tree_view->priv->expander_size);
7637   else if (count < 0)
7638     y += MAX (GTK_RBNODE_GET_HEIGHT (cursor_node),
7639               tree_view->priv->expander_size);
7640   y = CLAMP (y, (gint)tree_view->priv->vadjustment->lower,  (gint)tree_view->priv->vadjustment->upper - vertical_separator);
7641
7642   if (y > tree_view->priv->height)
7643     y = tree_view->priv->height - 1;
7644
7645   _gtk_rbtree_find_offset (tree_view->priv->tree, y, &cursor_tree, &cursor_node);
7646   cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
7647   g_return_if_fail (cursor_path != NULL);
7648   gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE);
7649   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
7650   gtk_tree_path_free (cursor_path);
7651 }
7652
7653 static void
7654 gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
7655                                       gint         count)
7656 {
7657   GtkRBTree *cursor_tree = NULL;
7658   GtkRBNode *cursor_node = NULL;
7659   GtkTreePath *cursor_path = NULL;
7660   GtkTreeViewColumn *column;
7661   GtkTreeIter iter;
7662   GList *list;
7663   gboolean found_column = FALSE;
7664   gboolean rtl;
7665
7666   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
7667
7668   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
7669     return;
7670
7671   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
7672     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
7673   else
7674     return;
7675
7676   _gtk_tree_view_find_node (tree_view, cursor_path, &cursor_tree, &cursor_node);
7677   if (cursor_tree == NULL)
7678     return;
7679   if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path) == FALSE)
7680     {
7681       gtk_tree_path_free (cursor_path);
7682       return;
7683     }
7684   gtk_tree_path_free (cursor_path);
7685
7686   list = tree_view->priv->columns;
7687   if (tree_view->priv->focus_column)
7688     {
7689       for (list = tree_view->priv->columns; list; list = list->next)
7690         {
7691           if (list->data == tree_view->priv->focus_column)
7692             break;
7693         }
7694     }
7695
7696   while (list)
7697     {
7698       column = list->data;
7699       if (column->visible == FALSE)
7700         goto loop_end;
7701
7702       gtk_tree_view_column_cell_set_cell_data (column,
7703                                                tree_view->priv->model,
7704                                                &iter,
7705                                                GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT),
7706                                                cursor_node->children?TRUE:FALSE);
7707       if (_gtk_tree_view_column_cell_focus (column, count,
7708                                             list->prev?TRUE:FALSE,
7709                                             list->next?TRUE:FALSE))
7710         {
7711           tree_view->priv->focus_column = column;
7712           found_column = TRUE;
7713           break;
7714         }
7715     loop_end:
7716       if (count == 1)
7717         list = rtl ? list->prev : list->next;
7718       else
7719         list = rtl ? list->next : list->prev;
7720     }
7721
7722   if (found_column)
7723     {
7724       if (!gtk_tree_view_has_special_cell (tree_view))
7725         _gtk_tree_view_queue_draw_node (tree_view,
7726                                         cursor_tree,
7727                                         cursor_node,
7728                                         NULL);
7729       g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
7730     }
7731   gtk_tree_view_clamp_column_visible (tree_view, tree_view->priv->focus_column);
7732 }
7733
7734 static void
7735 gtk_tree_view_move_cursor_start_end (GtkTreeView *tree_view,
7736                                      gint         count)
7737 {
7738   GtkRBTree *cursor_tree;
7739   GtkRBNode *cursor_node;
7740   GtkTreePath *path;
7741
7742   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
7743     return;
7744
7745   g_return_if_fail (tree_view->priv->tree != NULL);
7746
7747   if (count == -1)
7748     {
7749       cursor_tree = tree_view->priv->tree;
7750       cursor_node = cursor_tree->root;
7751       while (cursor_node && cursor_node->left != cursor_tree->nil)
7752         cursor_node = cursor_node->left;
7753     }
7754   else
7755     {
7756       cursor_tree = tree_view->priv->tree;
7757       cursor_node = cursor_tree->root;
7758       do
7759         {
7760           while (cursor_node && cursor_node->right != cursor_tree->nil)
7761             cursor_node = cursor_node->right;
7762           if (cursor_node->children == NULL)
7763             break;
7764
7765           cursor_tree = cursor_node->children;
7766           cursor_node = cursor_tree->root;
7767         }
7768       while (1);
7769     }
7770
7771   path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
7772   gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
7773   gtk_tree_path_free (path);
7774 }
7775
7776 static gboolean
7777 gtk_tree_view_real_select_all (GtkTreeView *tree_view)
7778 {
7779   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
7780     return FALSE;
7781
7782   if (tree_view->priv->selection->type != GTK_SELECTION_MULTIPLE)
7783     return FALSE;
7784
7785   gtk_tree_selection_select_all (tree_view->priv->selection);
7786
7787   return TRUE;
7788 }
7789
7790 static gboolean
7791 gtk_tree_view_real_unselect_all (GtkTreeView *tree_view)
7792 {
7793   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
7794     return FALSE;
7795
7796   if (tree_view->priv->selection->type != GTK_SELECTION_MULTIPLE)
7797     return FALSE;
7798
7799   gtk_tree_selection_unselect_all (tree_view->priv->selection);
7800
7801   return TRUE;
7802 }
7803
7804 static gboolean
7805 gtk_tree_view_real_select_cursor_row (GtkTreeView *tree_view,
7806                                       gboolean     start_editing)
7807 {
7808   GtkRBTree *cursor_tree = NULL;
7809   GtkRBNode *cursor_node = NULL;
7810   GtkTreePath *cursor_path = NULL;
7811   GdkModifierType state = 0;
7812   cursor_path = NULL;
7813
7814   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
7815     return FALSE;
7816
7817   if (tree_view->priv->cursor)
7818     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
7819
7820   if (cursor_path == NULL)
7821     return FALSE;
7822
7823   _gtk_tree_view_find_node (tree_view, cursor_path,
7824                             &cursor_tree, &cursor_node);
7825
7826   if (cursor_tree == NULL)
7827     {
7828       gtk_tree_path_free (cursor_path);
7829       return FALSE;
7830     }
7831
7832   gtk_get_current_event_state (&state);
7833
7834   if (! (state & GDK_SHIFT_MASK) &&
7835       start_editing &&
7836       tree_view->priv->focus_column)
7837     {
7838       if (gtk_tree_view_start_editing (tree_view, cursor_path))
7839         {
7840           gtk_tree_path_free (cursor_path);
7841           return TRUE;
7842         }
7843     }
7844   _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
7845                                             cursor_node,
7846                                             cursor_tree,
7847                                             cursor_path,
7848                                             state,
7849                                             FALSE);
7850
7851   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
7852
7853   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
7854   _gtk_tree_view_queue_draw_node (tree_view, cursor_tree, cursor_node, NULL);
7855
7856   if (! (state & GDK_SHIFT_MASK))
7857     gtk_tree_view_row_activated (tree_view, cursor_path, tree_view->priv->focus_column);
7858     
7859   gtk_tree_path_free (cursor_path);
7860
7861   return TRUE;
7862 }
7863
7864 static gboolean
7865 gtk_tree_view_real_toggle_cursor_row (GtkTreeView *tree_view)
7866 {
7867   GtkRBTree *cursor_tree = NULL;
7868   GtkRBNode *cursor_node = NULL;
7869   GtkTreePath *cursor_path = NULL;
7870
7871   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
7872     return FALSE;
7873
7874   cursor_path = NULL;
7875   if (tree_view->priv->cursor)
7876     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
7877
7878   if (cursor_path == NULL)
7879     return FALSE;
7880
7881   _gtk_tree_view_find_node (tree_view, cursor_path,
7882                             &cursor_tree, &cursor_node);
7883   if (cursor_tree == NULL)
7884     {
7885       gtk_tree_path_free (cursor_path);
7886       return FALSE;
7887     }
7888
7889   _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
7890                                             cursor_node,
7891                                             cursor_tree,
7892                                             cursor_path,
7893                                             GDK_CONTROL_MASK,
7894                                             FALSE);
7895
7896   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
7897
7898   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
7899   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
7900   gtk_tree_path_free (cursor_path);
7901
7902   return TRUE;
7903 }
7904
7905 static gboolean
7906 gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView *tree_view,
7907                                                gboolean     logical,
7908                                                gboolean     expand,
7909                                                gboolean     open_all)
7910 {
7911   GtkTreePath *cursor_path = NULL;
7912   GtkRBTree *tree;
7913   GtkRBNode *node;
7914
7915   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
7916     return FALSE;
7917
7918   cursor_path = NULL;
7919   if (tree_view->priv->cursor)
7920     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
7921
7922   if (cursor_path == NULL)
7923     return FALSE;
7924
7925   if (_gtk_tree_view_find_node (tree_view, cursor_path, &tree, &node))
7926     return FALSE;
7927   
7928   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
7929   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
7930
7931   if (expand)
7932     gtk_tree_view_real_expand_row (tree_view, cursor_path, tree, node, open_all, TRUE);
7933   else
7934     gtk_tree_view_real_collapse_row (tree_view, cursor_path, tree, node, TRUE);
7935
7936   gtk_tree_path_free (cursor_path);
7937
7938   return TRUE;
7939 }
7940
7941 static gboolean
7942 gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
7943 {
7944   GtkRBTree *cursor_tree = NULL;
7945   GtkRBNode *cursor_node = NULL;
7946   GtkTreePath *cursor_path = NULL;
7947
7948   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
7949     return FALSE;
7950
7951   cursor_path = NULL;
7952   if (tree_view->priv->cursor)
7953     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
7954
7955   if (cursor_path == NULL)
7956     return FALSE;
7957
7958   _gtk_tree_view_find_node (tree_view, cursor_path,
7959                             &cursor_tree, &cursor_node);
7960   if (cursor_tree == NULL)
7961     {
7962       gtk_tree_path_free (cursor_path);
7963       return FALSE;
7964     }
7965
7966   if (cursor_tree->parent_node)
7967     {
7968       gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
7969       cursor_node = cursor_tree->parent_node;
7970       cursor_tree = cursor_tree->parent_tree;
7971
7972       gtk_tree_path_up (cursor_path);
7973       gtk_tree_row_reference_free (tree_view->priv->cursor);
7974       tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, cursor_path);
7975       _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
7976                                                 cursor_node,
7977                                                 cursor_tree,
7978                                                 cursor_path,
7979                                                 0,
7980                                                 FALSE);
7981     }
7982
7983   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
7984
7985   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
7986   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
7987   gtk_tree_path_free (cursor_path);
7988
7989   return TRUE;
7990 }
7991
7992 /* Cut and paste from gtkwindow.c */
7993 static void
7994 send_focus_change (GtkWidget *widget,
7995                    gboolean   in)
7996 {
7997   GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
7998
7999   g_object_ref (widget);
8000    
8001  if (in)
8002     GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
8003   else
8004     GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
8005
8006   fevent->focus_change.type = GDK_FOCUS_CHANGE;
8007   fevent->focus_change.window = g_object_ref (widget->window);
8008   fevent->focus_change.in = in;
8009   
8010   gtk_widget_event (widget, fevent);
8011   
8012   g_object_notify (G_OBJECT (widget), "has_focus");
8013
8014   g_object_unref (widget);
8015   gdk_event_free (fevent);
8016 }
8017
8018 static gboolean
8019 gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view)
8020 {
8021   GtkWidget *window;
8022   GtkWidget *entry;
8023   GtkWidget *search_dialog;
8024
8025   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
8026     return FALSE;
8027
8028   if (tree_view->priv->enable_search == FALSE ||
8029       tree_view->priv->search_column < 0)
8030     return FALSE;
8031
8032   search_dialog = g_object_get_data (G_OBJECT (tree_view),
8033                                      GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
8034   if (search_dialog)
8035     return FALSE;
8036
8037   /* set up window */
8038   window = gtk_window_new (GTK_WINDOW_POPUP);
8039   gtk_window_set_title (GTK_WINDOW (window), "search dialog");
8040   gtk_container_set_border_width (GTK_CONTAINER (window), 3);
8041   gtk_window_set_modal (GTK_WINDOW (window), TRUE);
8042   g_signal_connect (window, "delete_event",
8043                     G_CALLBACK (gtk_tree_view_search_delete_event),
8044                     tree_view);
8045   g_signal_connect (window, "key_press_event",
8046                     G_CALLBACK (gtk_tree_view_search_key_press_event),
8047                     tree_view);
8048   g_signal_connect (window, "button_press_event",
8049                     G_CALLBACK (gtk_tree_view_search_button_press_event),
8050                     tree_view);
8051
8052   /* add entry */
8053   entry = gtk_entry_new ();
8054   gtk_widget_show (entry);
8055   g_signal_connect (entry, "changed",
8056                     G_CALLBACK (gtk_tree_view_search_init),
8057                     tree_view);
8058   g_signal_connect (entry, "populate_popup",
8059                     G_CALLBACK (gtk_tree_view_search_disable_popdown),
8060                     tree_view);
8061   gtk_container_add (GTK_CONTAINER (window), entry);
8062
8063   /* done, show it */
8064   tree_view->priv->search_dialog_position_func (tree_view, window);
8065   gtk_widget_show_all (window);
8066   gtk_widget_grab_focus (entry);
8067
8068   /* send focus-in event */
8069   send_focus_change (entry, TRUE);
8070
8071   /* position window */
8072
8073   /* yes, we point to the entry's private text thing here, a bit evil */
8074   g_object_set_data (G_OBJECT (window), "gtk-tree-view-text",
8075                      (gchar *) gtk_entry_get_text (GTK_ENTRY (entry)));
8076   g_object_set_data (G_OBJECT (tree_view),
8077                      GTK_TREE_VIEW_SEARCH_DIALOG_KEY, window);
8078
8079   /* search first matching iter */
8080   gtk_tree_view_search_init (entry, tree_view);
8081
8082   return TRUE;
8083 }
8084
8085 /* this function returns the new width of the column being resized given
8086  * the column and x position of the cursor; the x cursor position is passed
8087  * in as a pointer and automagicly corrected if it's beyond min/max limits
8088  */
8089 static gint
8090 gtk_tree_view_new_column_width (GtkTreeView *tree_view,
8091                                 gint       i,
8092                                 gint      *x)
8093 {
8094   GtkTreeViewColumn *column;
8095   gint width;
8096
8097   /* first translate the x position from widget->window
8098    * to clist->clist_window
8099    */
8100
8101   column = g_list_nth (tree_view->priv->columns, i)->data;
8102   width = *x - column->button->allocation.x;
8103
8104   /* Clamp down the value */
8105   if (column->min_width == -1)
8106     width = MAX (column->button->requisition.width,
8107                  width);
8108   else
8109     width = MAX (column->min_width,
8110                  width);
8111   if (column->max_width != -1)
8112     width = MIN (width, column->max_width != -1);
8113   *x = column->button->allocation.x + width;
8114
8115   return width;
8116 }
8117
8118
8119 /* Callbacks */
8120 static void
8121 gtk_tree_view_adjustment_changed (GtkAdjustment *adjustment,
8122                                   GtkTreeView   *tree_view)
8123 {
8124   if (GTK_WIDGET_REALIZED (tree_view))
8125     {
8126       gint dy;
8127         
8128       gdk_window_move (tree_view->priv->bin_window,
8129                        - tree_view->priv->hadjustment->value,
8130                        TREE_VIEW_HEADER_HEIGHT (tree_view));
8131       gdk_window_move (tree_view->priv->header_window,
8132                        - tree_view->priv->hadjustment->value,
8133                        0);
8134       dy = tree_view->priv->dy - (int) tree_view->priv->vadjustment->value;
8135       gdk_window_scroll (tree_view->priv->bin_window, 0, dy);
8136
8137       /* update our dy and top_row */
8138       tree_view->priv->dy = (int) tree_view->priv->vadjustment->value;
8139       gtk_tree_view_dy_to_top_row (tree_view);
8140     }
8141 }
8142
8143 \f
8144
8145 /* Public methods
8146  */
8147
8148 /**
8149  * gtk_tree_view_new:
8150  *
8151  * Creates a new #GtkTreeView widget.
8152  *
8153  * Return value: A newly created #GtkTreeView widget.
8154  **/
8155 GtkWidget *
8156 gtk_tree_view_new (void)
8157 {
8158   return g_object_new (GTK_TYPE_TREE_VIEW, NULL);
8159 }
8160
8161 /**
8162  * gtk_tree_view_new_with_model:
8163  * @model: the model.
8164  *
8165  * Creates a new #GtkTreeView widget with the model initialized to @model.
8166  *
8167  * Return value: A newly created #GtkTreeView widget.
8168  **/
8169 GtkWidget *
8170 gtk_tree_view_new_with_model (GtkTreeModel *model)
8171 {
8172   return g_object_new (GTK_TYPE_TREE_VIEW, "model", model, NULL);
8173 }
8174
8175 /* Public Accessors
8176  */
8177
8178 /**
8179  * gtk_tree_view_get_model:
8180  * @tree_view: a #GtkTreeView
8181  *
8182  * Returns the model the the #GtkTreeView is based on.  Returns %NULL if the
8183  * model is unset.
8184  *
8185  * Return value: A #GtkTreeModel, or %NULL if none is currently being used.
8186  **/
8187 GtkTreeModel *
8188 gtk_tree_view_get_model (GtkTreeView *tree_view)
8189 {
8190   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
8191
8192   return tree_view->priv->model;
8193 }
8194
8195 /**
8196  * gtk_tree_view_set_model:
8197  * @tree_view: A #GtkTreeNode.
8198  * @model: The model.
8199  *
8200  * Sets the model for a #GtkTreeView.  If the @tree_view already has a model
8201  * set, it will remove it before setting the new model.  If @model is %NULL, then
8202  * it will unset the old model.
8203  **/
8204 void
8205 gtk_tree_view_set_model (GtkTreeView  *tree_view,
8206                          GtkTreeModel *model)
8207 {
8208   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8209
8210   if (model == tree_view->priv->model)
8211     return;
8212
8213   if (tree_view->priv->model)
8214     {
8215       GList *tmplist = tree_view->priv->columns;
8216
8217       gtk_tree_view_unref_and_check_selection_tree (tree_view, tree_view->priv->tree);
8218
8219       g_signal_handlers_disconnect_by_func (tree_view->priv->model,
8220                                             gtk_tree_view_row_changed,
8221                                             tree_view);
8222       g_signal_handlers_disconnect_by_func (tree_view->priv->model,
8223                                             gtk_tree_view_row_inserted,
8224                                             tree_view);
8225       g_signal_handlers_disconnect_by_func (tree_view->priv->model,
8226                                             gtk_tree_view_row_has_child_toggled,
8227                                             tree_view);
8228       g_signal_handlers_disconnect_by_func (tree_view->priv->model,
8229                                             gtk_tree_view_row_deleted,
8230                                             tree_view);
8231       g_signal_handlers_disconnect_by_func (tree_view->priv->model,
8232                                             gtk_tree_view_rows_reordered,
8233                                             tree_view);
8234
8235       for (; tmplist; tmplist = tmplist->next)
8236         _gtk_tree_view_column_unset_model (tmplist->data,
8237                                            tree_view->priv->model);
8238
8239       if (tree_view->priv->tree)
8240         {
8241           _gtk_rbtree_free (tree_view->priv->tree);
8242           tree_view->priv->tree = NULL;
8243         }
8244
8245       tree_view->priv->prelight_node = NULL;
8246       tree_view->priv->prelight_tree = NULL;
8247       tree_view->priv->button_pressed_node = NULL;
8248       tree_view->priv->button_pressed_tree = NULL;
8249
8250       gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
8251       tree_view->priv->drag_dest_row = NULL;
8252       gtk_tree_row_reference_free (tree_view->priv->cursor);
8253       tree_view->priv->cursor = NULL;
8254       gtk_tree_row_reference_free (tree_view->priv->anchor);
8255       tree_view->priv->anchor = NULL;
8256       gtk_tree_row_reference_free (tree_view->priv->top_row);
8257       tree_view->priv->top_row = NULL;
8258       gtk_tree_row_reference_free (tree_view->priv->last_button_press);
8259       tree_view->priv->last_button_press = NULL;
8260       gtk_tree_row_reference_free (tree_view->priv->last_button_press_2);
8261       tree_view->priv->last_button_press_2 = NULL;
8262       gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
8263       tree_view->priv->scroll_to_path = NULL;
8264
8265       tree_view->priv->scroll_to_column = NULL;
8266
8267       g_object_unref (tree_view->priv->model);
8268
8269       tree_view->priv->search_column = -1;
8270       GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_IS_LIST);
8271       tree_view->priv->fixed_height_check = 0;
8272       tree_view->priv->dy = tree_view->priv->top_row_dy = 0;
8273     }
8274
8275   tree_view->priv->model = model;
8276
8277
8278   if (tree_view->priv->model)
8279     {
8280       gint i;
8281       GtkTreePath *path;
8282       GtkTreeIter iter;
8283
8284       if (tree_view->priv->search_column == -1)
8285         {
8286           for (i = 0; i < gtk_tree_model_get_n_columns (model); i++)
8287             {
8288               GType type = gtk_tree_model_get_column_type (model, i);
8289
8290               if (g_value_type_transformable (type, G_TYPE_STRING))
8291                 {
8292                   tree_view->priv->search_column = i;
8293                   break;
8294                 }
8295             }
8296         }
8297
8298       g_object_ref (tree_view->priv->model);
8299       g_signal_connect (tree_view->priv->model,
8300                         "row_changed",
8301                         G_CALLBACK (gtk_tree_view_row_changed),
8302                         tree_view);
8303       g_signal_connect (tree_view->priv->model,
8304                         "row_inserted",
8305                         G_CALLBACK (gtk_tree_view_row_inserted),
8306                         tree_view);
8307       g_signal_connect (tree_view->priv->model,
8308                         "row_has_child_toggled",
8309                         G_CALLBACK (gtk_tree_view_row_has_child_toggled),
8310                         tree_view);
8311       g_signal_connect (tree_view->priv->model,
8312                         "row_deleted",
8313                         G_CALLBACK (gtk_tree_view_row_deleted),
8314                         tree_view);
8315       g_signal_connect (tree_view->priv->model,
8316                         "rows_reordered",
8317                         G_CALLBACK (gtk_tree_view_rows_reordered),
8318                         tree_view);
8319
8320       path = gtk_tree_path_new_first ();
8321       if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, path))
8322         {
8323           tree_view->priv->tree = _gtk_rbtree_new ();
8324           gtk_tree_view_build_tree (tree_view, tree_view->priv->tree, &iter, 1, FALSE);
8325         }
8326       gtk_tree_path_free (path);
8327
8328       /*  FIXME: do I need to do this? gtk_tree_view_create_buttons (tree_view); */
8329       install_presize_handler (tree_view);
8330     }
8331
8332   g_object_notify (G_OBJECT (tree_view), "model");
8333
8334   if (GTK_WIDGET_REALIZED (tree_view))
8335     gtk_widget_queue_resize (GTK_WIDGET (tree_view));
8336 }
8337
8338 /**
8339  * gtk_tree_view_get_selection:
8340  * @tree_view: A #GtkTreeView.
8341  *
8342  * Gets the #GtkTreeSelection associated with @tree_view.
8343  *
8344  * Return value: A #GtkTreeSelection object.
8345  **/
8346 GtkTreeSelection *
8347 gtk_tree_view_get_selection (GtkTreeView *tree_view)
8348 {
8349   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
8350
8351   return tree_view->priv->selection;
8352 }
8353
8354 /**
8355  * gtk_tree_view_get_hadjustment:
8356  * @tree_view: A #GtkTreeView
8357  *
8358  * Gets the #GtkAdjustment currently being used for the horizontal aspect.
8359  *
8360  * Return value: A #GtkAdjustment object, or %NULL if none is currently being
8361  * used.
8362  **/
8363 GtkAdjustment *
8364 gtk_tree_view_get_hadjustment (GtkTreeView *tree_view)
8365 {
8366   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
8367
8368   if (tree_view->priv->hadjustment == NULL)
8369     gtk_tree_view_set_hadjustment (tree_view, NULL);
8370
8371   return tree_view->priv->hadjustment;
8372 }
8373
8374 /**
8375  * gtk_tree_view_set_hadjustment:
8376  * @tree_view: A #GtkTreeView
8377  * @adjustment: The #GtkAdjustment to set, or %NULL
8378  *
8379  * Sets the #GtkAdjustment for the current horizontal aspect.
8380  **/
8381 void
8382 gtk_tree_view_set_hadjustment (GtkTreeView   *tree_view,
8383                                GtkAdjustment *adjustment)
8384 {
8385   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8386
8387   gtk_tree_view_set_adjustments (tree_view,
8388                                  adjustment,
8389                                  tree_view->priv->vadjustment);
8390
8391   g_object_notify (G_OBJECT (tree_view), "hadjustment");
8392 }
8393
8394 /**
8395  * gtk_tree_view_get_vadjustment:
8396  * @tree_view: A #GtkTreeView
8397  *
8398  * Gets the #GtkAdjustment currently being used for the vertical aspect.
8399  *
8400  * Return value: A #GtkAdjustment object, or %NULL if none is currently being
8401  * used.
8402  **/
8403 GtkAdjustment *
8404 gtk_tree_view_get_vadjustment (GtkTreeView *tree_view)
8405 {
8406   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
8407
8408   if (tree_view->priv->vadjustment == NULL)
8409     gtk_tree_view_set_vadjustment (tree_view, NULL);
8410
8411   return tree_view->priv->vadjustment;
8412 }
8413
8414 /**
8415  * gtk_tree_view_set_vadjustment:
8416  * @tree_view: A #GtkTreeView
8417  * @adjustment: The #GtkAdjustment to set, or %NULL
8418  *
8419  * Sets the #GtkAdjustment for the current vertical aspect.
8420  **/
8421 void
8422 gtk_tree_view_set_vadjustment (GtkTreeView   *tree_view,
8423                                GtkAdjustment *adjustment)
8424 {
8425   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8426
8427   gtk_tree_view_set_adjustments (tree_view,
8428                                  tree_view->priv->hadjustment,
8429                                  adjustment);
8430
8431   g_object_notify (G_OBJECT (tree_view), "vadjustment");
8432 }
8433
8434 /* Column and header operations */
8435
8436 /**
8437  * gtk_tree_view_get_headers_visible:
8438  * @tree_view: A #GtkTreeView.
8439  *
8440  * Returns %TRUE if the headers on the @tree_view are visible.
8441  *
8442  * Return value: Whether the headers are visible or not.
8443  **/
8444 gboolean
8445 gtk_tree_view_get_headers_visible (GtkTreeView *tree_view)
8446 {
8447   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
8448
8449   return GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE);
8450 }
8451
8452 /**
8453  * gtk_tree_view_set_headers_visible:
8454  * @tree_view: A #GtkTreeView.
8455  * @headers_visible: %TRUE if the headers are visible
8456  *
8457  * Sets the the visibility state of the headers.
8458  **/
8459 void
8460 gtk_tree_view_set_headers_visible (GtkTreeView *tree_view,
8461                                    gboolean     headers_visible)
8462 {
8463   gint x, y;
8464   GList *list;
8465   GtkTreeViewColumn *column;
8466
8467   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8468
8469   headers_visible = !! headers_visible;
8470
8471   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE) == headers_visible)
8472     return;
8473
8474   if (headers_visible)
8475     GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE);
8476   else
8477     GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE);
8478
8479   if (GTK_WIDGET_REALIZED (tree_view))
8480     {
8481       gdk_window_get_position (tree_view->priv->bin_window, &x, &y);
8482       if (headers_visible)
8483         {
8484           gdk_window_move_resize (tree_view->priv->bin_window, x, y  + TREE_VIEW_HEADER_HEIGHT (tree_view), tree_view->priv->width, GTK_WIDGET (tree_view)->allocation.height -  + TREE_VIEW_HEADER_HEIGHT (tree_view));
8485
8486           if (GTK_WIDGET_MAPPED (tree_view))
8487             gtk_tree_view_map_buttons (tree_view);
8488         }
8489       else
8490         {
8491           gdk_window_move_resize (tree_view->priv->bin_window, x, y, tree_view->priv->width, tree_view->priv->height);
8492
8493           for (list = tree_view->priv->columns; list; list = list->next)
8494             {
8495               column = list->data;
8496               gtk_widget_unmap (column->button);
8497             }
8498           gdk_window_hide (tree_view->priv->header_window);
8499         }
8500     }
8501
8502   tree_view->priv->vadjustment->page_size = GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
8503   tree_view->priv->vadjustment->page_increment = (GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view)) / 2;
8504   tree_view->priv->vadjustment->lower = 0;
8505   tree_view->priv->vadjustment->upper = tree_view->priv->height;
8506   gtk_adjustment_changed (tree_view->priv->vadjustment);
8507
8508   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
8509
8510   g_object_notify (G_OBJECT (tree_view), "headers_visible");
8511 }
8512
8513 /**
8514  * gtk_tree_view_columns_autosize:
8515  * @tree_view: A #GtkTreeView.
8516  *
8517  * Resizes all columns to their optimal width. Only works after the
8518  * treeview has been realized.
8519  **/
8520 void
8521 gtk_tree_view_columns_autosize (GtkTreeView *tree_view)
8522 {
8523   gboolean dirty = FALSE;
8524   GList *list;
8525   GtkTreeViewColumn *column;
8526
8527   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8528
8529   for (list = tree_view->priv->columns; list; list = list->next)
8530     {
8531       column = list->data;
8532       if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
8533         continue;
8534       _gtk_tree_view_column_cell_set_dirty (column, TRUE);
8535       dirty = TRUE;
8536     }
8537
8538   if (dirty)
8539     gtk_widget_queue_resize (GTK_WIDGET (tree_view));
8540 }
8541
8542 /**
8543  * gtk_tree_view_set_headers_clickable:
8544  * @tree_view: A #GtkTreeView.
8545  * @setting: %TRUE if the columns are clickable.
8546  *
8547  * Allow the column title buttons to be clicked.
8548  **/
8549 void
8550 gtk_tree_view_set_headers_clickable (GtkTreeView *tree_view,
8551                                      gboolean   setting)
8552 {
8553   GList *list;
8554
8555   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8556   g_return_if_fail (tree_view->priv->model != NULL);
8557
8558   for (list = tree_view->priv->columns; list; list = list->next)
8559     gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (list->data), setting);
8560
8561   g_object_notify (G_OBJECT (tree_view), "headers_clickable");
8562 }
8563
8564
8565 /**
8566  * gtk_tree_view_set_rules_hint
8567  * @tree_view: a #GtkTreeView
8568  * @setting: %TRUE if the tree requires reading across rows
8569  *
8570  * This function tells GTK+ that the user interface for your
8571  * application requires users to read across tree rows and associate
8572  * cells with one another. By default, GTK+ will then render the tree
8573  * with alternating row colors. Do <emphasis>not</emphasis> use it
8574  * just because you prefer the appearance of the ruled tree; that's a
8575  * question for the theme. Some themes will draw tree rows in
8576  * alternating colors even when rules are turned off, and users who
8577  * prefer that appearance all the time can choose those themes. You
8578  * should call this function only as a <emphasis>semantic</emphasis>
8579  * hint to the theme engine that your tree makes alternating colors
8580  * useful from a functional standpoint (since it has lots of columns,
8581  * generally).
8582  *
8583  **/
8584 void
8585 gtk_tree_view_set_rules_hint (GtkTreeView  *tree_view,
8586                               gboolean      setting)
8587 {
8588   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8589
8590   setting = setting != FALSE;
8591
8592   if (tree_view->priv->has_rules != setting)
8593     {
8594       tree_view->priv->has_rules = setting;
8595       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
8596     }
8597
8598   g_object_notify (G_OBJECT (tree_view), "rules_hint");
8599 }
8600
8601 /**
8602  * gtk_tree_view_get_rules_hint
8603  * @tree_view: a #GtkTreeView
8604  *
8605  * Gets the setting set by gtk_tree_view_set_rules_hint().
8606  *
8607  * Return value: %TRUE if rules are useful for the user of this tree
8608  **/
8609 gboolean
8610 gtk_tree_view_get_rules_hint (GtkTreeView  *tree_view)
8611 {
8612   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
8613
8614   return tree_view->priv->has_rules;
8615 }
8616
8617 /* Public Column functions
8618  */
8619
8620 /**
8621  * gtk_tree_view_append_column:
8622  * @tree_view: A #GtkTreeView.
8623  * @column: The #GtkTreeViewColumn to add.
8624  *
8625  * Appends @column to the list of columns.
8626  *
8627  * Return value: The number of columns in @tree_view after appending.
8628  **/
8629 gint
8630 gtk_tree_view_append_column (GtkTreeView       *tree_view,
8631                              GtkTreeViewColumn *column)
8632 {
8633   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
8634   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
8635   g_return_val_if_fail (column->tree_view == NULL, -1);
8636
8637   return gtk_tree_view_insert_column (tree_view, column, -1);
8638 }
8639
8640
8641 /**
8642  * gtk_tree_view_remove_column:
8643  * @tree_view: A #GtkTreeView.
8644  * @column: The #GtkTreeViewColumn to remove.
8645  *
8646  * Removes @column from @tree_view.
8647  *
8648  * Return value: The number of columns in @tree_view after removing.
8649  **/
8650 gint
8651 gtk_tree_view_remove_column (GtkTreeView       *tree_view,
8652                              GtkTreeViewColumn *column)
8653 {
8654   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
8655   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
8656   g_return_val_if_fail (column->tree_view == GTK_WIDGET (tree_view), -1);
8657
8658   if (tree_view->priv->focus_column == column)
8659     tree_view->priv->focus_column = NULL;
8660
8661   if (tree_view->priv->edited_column == column)
8662     {
8663       gtk_tree_view_stop_editing (tree_view, TRUE);
8664
8665       /* no need to, but just to be sure ... */
8666       tree_view->priv->edited_column = NULL;
8667     }
8668
8669   _gtk_tree_view_column_unset_tree_view (column);
8670
8671   tree_view->priv->columns = g_list_remove (tree_view->priv->columns, column);
8672   tree_view->priv->n_columns--;
8673
8674   if (GTK_WIDGET_REALIZED (tree_view))
8675     {
8676       GList *list;
8677
8678       _gtk_tree_view_column_unrealize_button (column);
8679       for (list = tree_view->priv->columns; list; list = list->next)
8680         {
8681           GtkTreeViewColumn *tmp_column;
8682
8683           tmp_column = GTK_TREE_VIEW_COLUMN (list->data);
8684           if (tmp_column->visible)
8685             _gtk_tree_view_column_cell_set_dirty (tmp_column, TRUE);
8686         }
8687
8688       if (tree_view->priv->n_columns == 0 &&
8689           gtk_tree_view_get_headers_visible (tree_view))
8690         gdk_window_hide (tree_view->priv->header_window);
8691
8692       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
8693     }
8694
8695   g_object_unref (column);
8696   g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
8697
8698   return tree_view->priv->n_columns;
8699 }
8700
8701 /**
8702  * gtk_tree_view_insert_column:
8703  * @tree_view: A #GtkTreeView.
8704  * @column: The #GtkTreeViewColumn to be inserted.
8705  * @position: The position to insert @column in.
8706  *
8707  * This inserts the @column into the @tree_view at @position.  If @position is
8708  * -1, then the column is inserted at the end.
8709  *
8710  * Return value: The number of columns in @tree_view after insertion.
8711  **/
8712 gint
8713 gtk_tree_view_insert_column (GtkTreeView       *tree_view,
8714                              GtkTreeViewColumn *column,
8715                              gint               position)
8716 {
8717   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
8718   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
8719   g_return_val_if_fail (column->tree_view == NULL, -1);
8720
8721   g_object_ref (column);
8722   gtk_object_sink (GTK_OBJECT (column));
8723
8724   if (tree_view->priv->n_columns == 0 &&
8725       GTK_WIDGET_REALIZED (tree_view) &&
8726       gtk_tree_view_get_headers_visible (tree_view))
8727     {
8728       gdk_window_show (tree_view->priv->header_window);
8729     }
8730
8731   tree_view->priv->columns = g_list_insert (tree_view->priv->columns,
8732                                             column, position);
8733   tree_view->priv->n_columns++;
8734
8735   _gtk_tree_view_column_set_tree_view (column, tree_view);
8736
8737   if (GTK_WIDGET_REALIZED (tree_view))
8738     {
8739       GList *list;
8740
8741       _gtk_tree_view_column_realize_button (column);
8742
8743       for (list = tree_view->priv->columns; list; list = list->next)
8744         {
8745           column = GTK_TREE_VIEW_COLUMN (list->data);
8746           if (column->visible)
8747             _gtk_tree_view_column_cell_set_dirty (column, TRUE);
8748         }
8749       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
8750     }
8751
8752   g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
8753
8754   return tree_view->priv->n_columns;
8755 }
8756
8757 /**
8758  * gtk_tree_view_insert_column_with_attributes:
8759  * @tree_view: A #GtkTreeView
8760  * @position: The position to insert the new column in.
8761  * @title: The title to set the header to.
8762  * @cell: The #GtkCellRenderer.
8763  * @Varargs: A %NULL-terminated list of attributes.
8764  *
8765  * Creates a new #GtkTreeViewColumn and inserts it into the @tree_view at
8766  * @position.  If @position is -1, then the newly created column is inserted at
8767  * the end.  The column is initialized with the attributes given.
8768  *
8769  * Return value: The number of columns in @tree_view after insertion.
8770  **/
8771 gint
8772 gtk_tree_view_insert_column_with_attributes (GtkTreeView     *tree_view,
8773                                              gint             position,
8774                                              const gchar     *title,
8775                                              GtkCellRenderer *cell,
8776                                              ...)
8777 {
8778   GtkTreeViewColumn *column;
8779   gchar *attribute;
8780   va_list args;
8781   gint column_id;
8782
8783   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
8784
8785   column = gtk_tree_view_column_new ();
8786
8787   gtk_tree_view_column_set_title (column, title);
8788   gtk_tree_view_column_pack_start (column, cell, TRUE);
8789
8790   va_start (args, cell);
8791
8792   attribute = va_arg (args, gchar *);
8793
8794   while (attribute != NULL)
8795     {
8796       column_id = va_arg (args, gint);
8797       gtk_tree_view_column_add_attribute (column, cell, attribute, column_id);
8798       attribute = va_arg (args, gchar *);
8799     }
8800
8801   va_end (args);
8802
8803   gtk_tree_view_insert_column (tree_view, column, position);
8804
8805   return tree_view->priv->n_columns;
8806 }
8807
8808 /**
8809  * gtk_tree_view_insert_column_with_data_func:
8810  * @tree_view: a #GtkTreeView
8811  * @position: Position to insert, -1 for append
8812  * @title: column title
8813  * @cell: cell renderer for column
8814  * @func: function to set attributes of cell renderer
8815  * @data: data for @func
8816  * @dnotify: destroy notifier for @data
8817  *
8818  * Convenience function that inserts a new column into the #GtkTreeView
8819  * with the given cell renderer and a #GtkCellDataFunc to set cell renderer
8820  * attributes (normally using data from the model). See also
8821  * gtk_tree_view_column_set_cell_data_func(), gtk_tree_view_column_pack_start().
8822  *
8823  * Return value: number of columns in the tree view post-insert
8824  **/
8825 gint
8826 gtk_tree_view_insert_column_with_data_func  (GtkTreeView               *tree_view,
8827                                              gint                       position,
8828                                              const gchar               *title,
8829                                              GtkCellRenderer           *cell,
8830                                              GtkTreeCellDataFunc        func,
8831                                              gpointer                   data,
8832                                              GDestroyNotify             dnotify)
8833 {
8834   GtkTreeViewColumn *column;
8835
8836   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
8837
8838   column = gtk_tree_view_column_new ();
8839
8840   gtk_tree_view_column_set_title (column, title);
8841   gtk_tree_view_column_pack_start (column, cell, TRUE);
8842   gtk_tree_view_column_set_cell_data_func (column, cell, func, data, dnotify);
8843
8844   gtk_tree_view_insert_column (tree_view, column, position);
8845
8846   return tree_view->priv->n_columns;
8847 }
8848
8849 /**
8850  * gtk_tree_view_get_column:
8851  * @tree_view: A #GtkTreeView.
8852  * @n: The position of the column, counting from 0.
8853  *
8854  * Gets the #GtkTreeViewColumn at the given position in the #tree_view.
8855  *
8856  * Return value: The #GtkTreeViewColumn, or %NULL if the position is outside the
8857  * range of columns.
8858  **/
8859 GtkTreeViewColumn *
8860 gtk_tree_view_get_column (GtkTreeView *tree_view,
8861                           gint         n)
8862 {
8863   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
8864
8865   if (n < 0 || n >= tree_view->priv->n_columns)
8866     return NULL;
8867
8868   if (tree_view->priv->columns == NULL)
8869     return NULL;
8870
8871   return GTK_TREE_VIEW_COLUMN (g_list_nth (tree_view->priv->columns, n)->data);
8872 }
8873
8874 /**
8875  * gtk_tree_view_get_columns:
8876  * @tree_view: A #GtkTreeView
8877  *
8878  * Returns a #GList of all the #GtkTreeViewColumn s currently in @tree_view.
8879  * The returned list must be freed with g_list_free ().
8880  *
8881  * Return value: A list of #GtkTreeViewColumn s
8882  **/
8883 GList *
8884 gtk_tree_view_get_columns (GtkTreeView *tree_view)
8885 {
8886   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
8887
8888   return g_list_copy (tree_view->priv->columns);
8889 }
8890
8891 /**
8892  * gtk_tree_view_move_column_after:
8893  * @tree_view: A #GtkTreeView
8894  * @column: The #GtkTreeViewColumn to be moved.
8895  * @base_column: The #GtkTreeViewColumn to be moved relative to, or %NULL.
8896  *
8897  * Moves @column to be after to @base_column.  If @base_column is %NULL, then
8898  * @column is placed in the first position.
8899  **/
8900 void
8901 gtk_tree_view_move_column_after (GtkTreeView       *tree_view,
8902                                  GtkTreeViewColumn *column,
8903                                  GtkTreeViewColumn *base_column)
8904 {
8905   GList *column_list_el, *base_el = NULL;
8906
8907   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8908
8909   column_list_el = g_list_find (tree_view->priv->columns, column);
8910   g_return_if_fail (column_list_el != NULL);
8911
8912   if (base_column)
8913     {
8914       base_el = g_list_find (tree_view->priv->columns, base_column);
8915       g_return_if_fail (base_el != NULL);
8916     }
8917
8918   if (column_list_el->prev == base_el)
8919     return;
8920
8921   tree_view->priv->columns = g_list_remove_link (tree_view->priv->columns, column_list_el);
8922   if (base_el == NULL)
8923     {
8924       column_list_el->prev = NULL;
8925       column_list_el->next = tree_view->priv->columns;
8926       if (column_list_el->next)
8927         column_list_el->next->prev = column_list_el;
8928       tree_view->priv->columns = column_list_el;
8929     }
8930   else
8931     {
8932       column_list_el->prev = base_el;
8933       column_list_el->next = base_el->next;
8934       if (column_list_el->next)
8935         column_list_el->next->prev = column_list_el;
8936       base_el->next = column_list_el;
8937     }
8938
8939   if (GTK_WIDGET_REALIZED (tree_view))
8940     {
8941       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
8942       gtk_tree_view_size_allocate_columns (GTK_WIDGET (tree_view));
8943     }
8944
8945   g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
8946 }
8947
8948 /**
8949  * gtk_tree_view_set_expander_column:
8950  * @tree_view: A #GtkTreeView
8951  * @column: %NULL, or the column to draw the expander arrow at.
8952  *
8953  * Sets the column to draw the expander arrow at. It must be in @tree_view.  If
8954  * @column is %NULL, then the expander arrow is always at the first visible
8955  * column.
8956  **/
8957 void
8958 gtk_tree_view_set_expander_column (GtkTreeView       *tree_view,
8959                                    GtkTreeViewColumn *column)
8960 {
8961   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8962   if (column != NULL)
8963     g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (column));
8964
8965   if (tree_view->priv->expander_column != column)
8966     {
8967       GList *list;
8968
8969       if (column)
8970         {
8971           /* Confirm that column is in tree_view */
8972           for (list = tree_view->priv->columns; list; list = list->next)
8973             if (list->data == column)
8974               break;
8975           g_return_if_fail (list != NULL);
8976         }
8977
8978       tree_view->priv->expander_column = column;
8979       g_object_notify (G_OBJECT (tree_view), "expander_column");
8980     }
8981 }
8982
8983 /**
8984  * gtk_tree_view_get_expander_column:
8985  * @tree_view: A #GtkTreeView
8986  *
8987  * Returns the column that is the current expander column.  This
8988  * column has the expander arrow drawn next to it.
8989  *
8990  * Return value: The expander column.
8991  **/
8992 GtkTreeViewColumn *
8993 gtk_tree_view_get_expander_column (GtkTreeView *tree_view)
8994 {
8995   GList *list;
8996
8997   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
8998
8999   for (list = tree_view->priv->columns; list; list = list->next)
9000     if (gtk_tree_view_is_expander_column (tree_view, GTK_TREE_VIEW_COLUMN (list->data)))
9001       return (GtkTreeViewColumn *) list->data;
9002   return NULL;
9003 }
9004
9005
9006 /**
9007  * gtk_tree_view_set_column_drag_function:
9008  * @tree_view: A #GtkTreeView.
9009  * @func: A function to determine which columns are reorderable, or %NULL.
9010  * @user_data: User data to be passed to @func, or %NULL
9011  * @destroy: Destroy notifier for @user_data, or %NULL
9012  *
9013  * Sets a user function for determining where a column may be dropped when
9014  * dragged.  This function is called on every column pair in turn at the
9015  * beginning of a column drag to determine where a drop can take place.  The
9016  * arguments passed to @func are: the @tree_view, the #GtkTreeViewColumn being
9017  * dragged, the two #GtkTreeViewColumn s determining the drop spot, and
9018  * @user_data.  If either of the #GtkTreeViewColumn arguments for the drop spot
9019  * are %NULL, then they indicate an edge.  If @func is set to be %NULL, then
9020  * @tree_view reverts to the default behavior of allowing all columns to be
9021  * dropped everywhere.
9022  **/
9023 void
9024 gtk_tree_view_set_column_drag_function (GtkTreeView               *tree_view,
9025                                         GtkTreeViewColumnDropFunc  func,
9026                                         gpointer                   user_data,
9027                                         GtkDestroyNotify           destroy)
9028 {
9029   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
9030
9031   if (tree_view->priv->column_drop_func_data_destroy)
9032     (* tree_view->priv->column_drop_func_data_destroy) (tree_view->priv->column_drop_func_data);
9033
9034   tree_view->priv->column_drop_func = func;
9035   tree_view->priv->column_drop_func_data = user_data;
9036   tree_view->priv->column_drop_func_data_destroy = destroy;
9037 }
9038
9039 /**
9040  * gtk_tree_view_scroll_to_point:
9041  * @tree_view: a #GtkTreeView
9042  * @tree_x: X coordinate of new top-left pixel of visible area, or -1
9043  * @tree_y: Y coordinate of new top-left pixel of visible area, or -1
9044  *
9045  * Scrolls the tree view such that the top-left corner of the visible
9046  * area is @tree_x, @tree_y, where @tree_x and @tree_y are specified
9047  * in tree window coordinates.  The @tree_view must be realized before
9048  * this function is called.  If it isn't, you probably want to be
9049  * using gtk_tree_view_scroll_to_cell().
9050  *
9051  * If either @tree_x or @tree_y are -1, then that direction isn't scrolled.
9052  **/
9053 void
9054 gtk_tree_view_scroll_to_point (GtkTreeView *tree_view,
9055                                gint         tree_x,
9056                                gint         tree_y)
9057 {
9058   GtkAdjustment *hadj;
9059   GtkAdjustment *vadj;
9060
9061   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
9062   g_return_if_fail (GTK_WIDGET_REALIZED (tree_view));
9063
9064   hadj = tree_view->priv->hadjustment;
9065   vadj = tree_view->priv->vadjustment;
9066
9067   if (tree_x != -1)
9068     gtk_adjustment_set_value (hadj, CLAMP (tree_x, hadj->lower, hadj->upper - hadj->page_size));
9069   if (tree_y != -1)
9070     gtk_adjustment_set_value (vadj, CLAMP (tree_y, vadj->lower, vadj->upper - vadj->page_size));
9071 }
9072
9073 /**
9074  * gtk_tree_view_scroll_to_cell
9075  * @tree_view: A #GtkTreeView.
9076  * @path: The path of the row to move to, or %NULL.
9077  * @column: The #GtkTreeViewColumn to move horizontally to, or %NULL.
9078  * @use_align: whether to use alignment arguments, or %FALSE.
9079  * @row_align: The vertical alignment of the row specified by @path.
9080  * @col_align: The horizontal alignment of the column specified by @column.
9081  *
9082  * Moves the alignments of @tree_view to the position specified by @column and
9083  * @path.  If @column is %NULL, then no horizontal scrolling occurs.  Likewise,
9084  * if @path is %NULL no vertical scrolling occurs.  At a minimum, one of @column
9085  * or @path need to be non-%NULL.  @row_align determines where the row is
9086  * placed, and @col_align determines where @column is placed.  Both are expected
9087  * to be between 0.0 and 1.0. 0.0 means left/top alignment, 1.0 means
9088  * right/bottom alignment, 0.5 means center.
9089  *
9090  * If @use_align is %FALSE, then the alignment arguments are ignored, and the
9091  * tree does the minimum amount of work to scroll the cell onto the screen.
9092  * This means that the cell will be scrolled to the edge closest to its current
9093  * position.  If the cell is currently visible on the screen, nothing is done.
9094  *
9095  * This function only works if the model is set, and @path is a valid row on the
9096  * model.  If the model changes before the @tree_view is realized, the centered
9097  * path will be modified to reflect this change.
9098  **/
9099 void
9100 gtk_tree_view_scroll_to_cell (GtkTreeView       *tree_view,
9101                               GtkTreePath       *path,
9102                               GtkTreeViewColumn *column,
9103                               gboolean           use_align,
9104                               gfloat             row_align,
9105                               gfloat             col_align)
9106 {
9107   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
9108   g_return_if_fail (tree_view->priv->model != NULL);
9109   g_return_if_fail (tree_view->priv->tree != NULL);
9110   g_return_if_fail (row_align >= 0.0 && row_align <= 1.0);
9111   g_return_if_fail (col_align >= 0.0 && col_align <= 1.0);
9112   g_return_if_fail (path != NULL || column != NULL);
9113
9114 #if 0
9115   g_print ("gtk_tree_view_scroll_to_cell:\npath: %s\ncolumn: %s\nuse_align: %d\nrow_align: %f\ncol_align: %f\n",
9116            gtk_tree_path_to_string (path), column?"non-null":"null", use_align, row_align, col_align);
9117 #endif
9118   row_align = CLAMP (row_align, 0.0, 1.0);
9119   col_align = CLAMP (col_align, 0.0, 1.0);
9120
9121
9122   /* Note: Despite the benefits that come from having one code path for the
9123    * scrolling code, we short-circuit validate_visible_area's immplementation as
9124    * it is much slower than just going to the point.
9125    */
9126   if (! GTK_WIDGET_REALIZED (tree_view) ||
9127       GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
9128     {
9129       if (tree_view->priv->scroll_to_path)
9130         gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
9131
9132       tree_view->priv->scroll_to_path = NULL;
9133       tree_view->priv->scroll_to_column = NULL;
9134
9135       if (path)
9136         tree_view->priv->scroll_to_path = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
9137       if (column)
9138         tree_view->priv->scroll_to_column = column;
9139       tree_view->priv->scroll_to_use_align = use_align;
9140       tree_view->priv->scroll_to_row_align = row_align;
9141       tree_view->priv->scroll_to_col_align = col_align;
9142
9143       install_presize_handler (tree_view);
9144     }
9145   else
9146     {
9147       GdkRectangle cell_rect;
9148       GdkRectangle vis_rect;
9149       gint dest_x, dest_y;
9150
9151       gtk_tree_view_get_cell_area (tree_view, path, column, &cell_rect);
9152       gtk_tree_view_widget_to_tree_coords (tree_view, cell_rect.x, cell_rect.y, &(cell_rect.x), &(cell_rect.y));
9153       gtk_tree_view_get_visible_rect (tree_view, &vis_rect);
9154
9155       dest_x = vis_rect.x;
9156       dest_y = vis_rect.y;
9157
9158       if (column)
9159         {
9160           if (use_align)
9161             {
9162               dest_x = cell_rect.x - ((vis_rect.width - cell_rect.width) * col_align);
9163             }
9164           else
9165             {
9166               if (cell_rect.x < vis_rect.x)
9167                 dest_x = cell_rect.x;
9168               if (cell_rect.x + cell_rect.width > vis_rect.x + vis_rect.width)
9169                 dest_x = cell_rect.x + cell_rect.width - vis_rect.width;
9170             }
9171         }
9172
9173       if (path)
9174         {
9175           if (use_align)
9176             {
9177               dest_y = cell_rect.y - ((vis_rect.height - cell_rect.height) * row_align);
9178               dest_y = MAX (dest_y, 0);
9179             }
9180           else
9181             {
9182               if (cell_rect.y < vis_rect.y)
9183                 dest_y = cell_rect.y;
9184               if (cell_rect.y + cell_rect.height > vis_rect.y + vis_rect.height)
9185                 dest_y = cell_rect.y + cell_rect.height - vis_rect.height;
9186             }
9187         }
9188
9189       gtk_tree_view_scroll_to_point (tree_view, dest_x, dest_y);
9190     }
9191 }
9192
9193 /**
9194  * gtk_tree_view_row_activated:
9195  * @tree_view: A #GtkTreeView
9196  * @path: The #GtkTreePath to be activated.
9197  * @column: The #GtkTreeViewColumn to be activated.
9198  *
9199  * Activates the cell determined by @path and @column.
9200  **/
9201 void
9202 gtk_tree_view_row_activated (GtkTreeView       *tree_view,
9203                              GtkTreePath       *path,
9204                              GtkTreeViewColumn *column)
9205 {
9206   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
9207
9208   g_signal_emit (tree_view, tree_view_signals[ROW_ACTIVATED], 0, path, column);
9209 }
9210
9211
9212 static void
9213 gtk_tree_view_expand_all_emission_helper (GtkRBTree *tree,
9214                                           GtkRBNode *node,
9215                                           gpointer   data)
9216 {
9217   GtkTreeView *tree_view = data;
9218
9219   if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT &&
9220       node->children)
9221     {
9222       GtkTreePath *path;
9223       GtkTreeIter iter;
9224
9225       path = _gtk_tree_view_find_path (tree_view, tree, node);
9226       gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
9227
9228       g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
9229
9230       gtk_tree_path_free (path);
9231     }
9232
9233   if (node->children)
9234     _gtk_rbtree_traverse (node->children,
9235                           node->children->root,
9236                           G_PRE_ORDER,
9237                           gtk_tree_view_expand_all_emission_helper,
9238                           tree_view);
9239 }
9240
9241 static void
9242 gtk_tree_view_expand_all_helper (GtkRBTree  *tree,
9243                                  GtkRBNode  *node,
9244                                  gpointer  data)
9245 {
9246   GtkTreeView *tree_view = data;
9247
9248   if (node->children)
9249     _gtk_rbtree_traverse (node->children,
9250                           node->children->root,
9251                           G_PRE_ORDER,
9252                           gtk_tree_view_expand_all_helper,
9253                           data);
9254   else if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT && node->children == NULL)
9255     {
9256       GtkTreePath *path;
9257       GtkTreeIter iter;
9258       GtkTreeIter child;
9259
9260       node->children = _gtk_rbtree_new ();
9261       node->children->parent_tree = tree;
9262       node->children->parent_node = node;
9263       path = _gtk_tree_view_find_path (tree_view, tree, node);
9264       gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
9265       gtk_tree_model_iter_children (tree_view->priv->model, &child, &iter);
9266       gtk_tree_view_build_tree (tree_view,
9267                                 node->children,
9268                                 &child,
9269                                 gtk_tree_path_get_depth (path) + 1,
9270                                 TRUE);
9271
9272       g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
9273       _gtk_rbtree_traverse (node->children,
9274                             node->children->root,
9275                             G_PRE_ORDER,
9276                             gtk_tree_view_expand_all_emission_helper,
9277                             tree_view);
9278       gtk_tree_path_free (path);
9279     }
9280 }
9281
9282 /**
9283  * gtk_tree_view_expand_all:
9284  * @tree_view: A #GtkTreeView.
9285  *
9286  * Recursively expands all nodes in the @tree_view.
9287  **/
9288 void
9289 gtk_tree_view_expand_all (GtkTreeView *tree_view)
9290 {
9291   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
9292
9293   if (tree_view->priv->tree == NULL)
9294     return;
9295
9296   _gtk_rbtree_traverse (tree_view->priv->tree,
9297                         tree_view->priv->tree->root,
9298                         G_PRE_ORDER,
9299                         gtk_tree_view_expand_all_helper,
9300                         tree_view);
9301 }
9302
9303 /* Timeout to animate the expander during expands and collapses */
9304 static gboolean
9305 expand_collapse_timeout (gpointer data)
9306 {
9307   gboolean retval;
9308
9309   GDK_THREADS_ENTER ();
9310
9311   retval = do_expand_collapse (data);
9312
9313   GDK_THREADS_LEAVE ();
9314
9315   return retval;
9316 }
9317
9318 static gboolean
9319 do_expand_collapse (GtkTreeView *tree_view)
9320 {
9321   GtkRBNode *node;
9322   GtkRBTree *tree;
9323   gboolean expanding;
9324   gboolean redraw;
9325
9326   redraw = FALSE;
9327   expanding = TRUE;
9328
9329   node = tree_view->priv->expanded_collapsed_node;
9330   tree = tree_view->priv->expanded_collapsed_tree;
9331
9332   if (node->children == NULL)
9333     expanding = FALSE;
9334
9335   if (expanding)
9336     {
9337       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SEMI_COLLAPSED))
9338         {
9339           GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_IS_SEMI_COLLAPSED);
9340           GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_EXPANDED);
9341
9342           redraw = TRUE;
9343
9344         }
9345       else if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SEMI_EXPANDED))
9346         {
9347           GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_IS_SEMI_EXPANDED);
9348
9349           redraw = TRUE;
9350         }
9351     }
9352   else
9353     {
9354       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SEMI_EXPANDED))
9355         {
9356           GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_IS_SEMI_EXPANDED);
9357           GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_COLLAPSED);
9358
9359           redraw = TRUE;
9360         }
9361       else if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SEMI_COLLAPSED))
9362         {
9363           GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_IS_SEMI_COLLAPSED);
9364
9365           redraw = TRUE;
9366
9367         }
9368     }
9369
9370   if (redraw)
9371     {
9372       gtk_tree_view_queue_draw_arrow (tree_view, tree, node, NULL);
9373
9374       return TRUE;
9375     }
9376
9377   return FALSE;
9378 }
9379
9380 /**
9381  * gtk_tree_view_collapse_all:
9382  * @tree_view: A #GtkTreeView.
9383  *
9384  * Recursively collapses all visible, expanded nodes in @tree_view.
9385  **/
9386 void
9387 gtk_tree_view_collapse_all (GtkTreeView *tree_view)
9388 {
9389   GtkRBTree *tree;
9390   GtkRBNode *node;
9391   GtkTreePath *path;
9392   gint *indices;
9393
9394   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
9395
9396   if (tree_view->priv->tree == NULL)
9397     return;
9398
9399   path = gtk_tree_path_new ();
9400   gtk_tree_path_down (path);
9401   indices = gtk_tree_path_get_indices (path);
9402
9403   tree = tree_view->priv->tree;
9404   node = tree->root;
9405   while (node && node->left != tree->nil)
9406     node = node->left;
9407
9408   while (node)
9409     {
9410       if (node->children)
9411         gtk_tree_view_real_collapse_row (tree_view, path, tree, node, FALSE);
9412       indices[0]++;
9413       node = _gtk_rbtree_next (tree, node);
9414     }
9415
9416   gtk_tree_path_free (path);
9417 }
9418
9419 /**
9420  * gtk_tree_view_expand_to_path:
9421  * @tree_view: A #GtkTreeView.
9422  * @path: path to a row.
9423  *
9424  * Expands the row at @path. This will also expand all parent rows of
9425  * @path as necessary.
9426  *
9427  * Since: 2.2
9428  **/
9429 void
9430 gtk_tree_view_expand_to_path (GtkTreeView *tree_view,
9431                               GtkTreePath *path)
9432 {
9433   gint i, depth;
9434   gint *indices;
9435   GtkTreePath *tmp;
9436
9437   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
9438   g_return_if_fail (path != NULL);
9439
9440   depth = gtk_tree_path_get_depth (path);
9441   indices = gtk_tree_path_get_indices (path);
9442
9443   tmp = gtk_tree_path_new ();
9444   g_return_if_fail (tmp != NULL);
9445
9446   for (i = 0; i < depth; i++)
9447     {
9448       gtk_tree_path_append_index (tmp, indices[i]);
9449       gtk_tree_view_expand_row (tree_view, tmp, FALSE);
9450     }
9451
9452   gtk_tree_path_free (tmp);
9453 }
9454
9455 /* FIXME the bool return values for expand_row and collapse_row are
9456  * not analagous; they should be TRUE if the row had children and
9457  * was not already in the requested state.
9458  */
9459
9460
9461 static gboolean
9462 gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
9463                                GtkTreePath *path,
9464                                GtkRBTree   *tree,
9465                                GtkRBNode   *node,
9466                                gboolean     open_all,
9467                                gboolean     animate)
9468 {
9469   GtkTreeIter iter;
9470   GtkTreeIter temp;
9471   gboolean expand;
9472
9473   if (node->children && !open_all)
9474     return FALSE;
9475
9476   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
9477     return FALSE;
9478
9479   gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
9480   if (! gtk_tree_model_iter_has_child (tree_view->priv->model, &iter))
9481     return FALSE;
9482
9483
9484    if (node->children && open_all)
9485     {
9486       gboolean retval = FALSE;
9487       GtkTreePath *tmp_path = gtk_tree_path_copy (path);
9488
9489       gtk_tree_path_append_index (tmp_path, 0);
9490       tree = node->children;
9491       node = tree->root;
9492       while (node->left != tree->nil)
9493         node = node->left;
9494       /* try to expand the children */
9495       do
9496         {
9497          gboolean t;
9498          t = gtk_tree_view_real_expand_row (tree_view, tmp_path, tree, node,
9499                                             TRUE, animate);
9500          if (t)
9501            retval = TRUE;
9502
9503          gtk_tree_path_next (tmp_path);
9504          node = _gtk_rbtree_next (tree, node);
9505        }
9506       while (node != NULL);
9507
9508       gtk_tree_path_free (tmp_path);
9509
9510       return retval;
9511     }
9512
9513   g_signal_emit (tree_view, tree_view_signals[TEST_EXPAND_ROW], 0, &iter, path, &expand);
9514
9515   if (expand)
9516     return FALSE;
9517
9518   node->children = _gtk_rbtree_new ();
9519   node->children->parent_tree = tree;
9520   node->children->parent_node = node;
9521
9522   gtk_tree_model_iter_children (tree_view->priv->model, &temp, &iter);
9523
9524   gtk_tree_view_build_tree (tree_view,
9525                             node->children,
9526                             &temp,
9527                             gtk_tree_path_get_depth (path) + 1,
9528                             open_all);
9529
9530   if (tree_view->priv->expand_collapse_timeout)
9531     {
9532       g_source_remove (tree_view->priv->expand_collapse_timeout);
9533       tree_view->priv->expand_collapse_timeout = 0;
9534     }
9535
9536   if (tree_view->priv->expanded_collapsed_node != NULL)
9537     {
9538       GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_EXPANDED);
9539       GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_COLLAPSED);
9540
9541       tree_view->priv->expanded_collapsed_node = NULL;
9542     }
9543
9544   if (animate)
9545     {
9546       tree_view->priv->expand_collapse_timeout = g_timeout_add (50, expand_collapse_timeout, tree_view);
9547       tree_view->priv->expanded_collapsed_node = node;
9548       tree_view->priv->expanded_collapsed_tree = tree;
9549
9550       GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_COLLAPSED);
9551     }
9552
9553   install_presize_handler (tree_view);
9554
9555   g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
9556   return TRUE;
9557 }
9558
9559
9560 /**
9561  * gtk_tree_view_expand_row:
9562  * @tree_view: a #GtkTreeView
9563  * @path: path to a row
9564  * @open_all: whether to recursively expand, or just expand immediate children
9565  *
9566  * Opens the row so its children are visible.
9567  *
9568  * Return value: %TRUE if the row existed and had children
9569  **/
9570 gboolean
9571 gtk_tree_view_expand_row (GtkTreeView *tree_view,
9572                           GtkTreePath *path,
9573                           gboolean     open_all)
9574 {
9575   GtkRBTree *tree;
9576   GtkRBNode *node;
9577
9578   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
9579   g_return_val_if_fail (tree_view->priv->model != NULL, FALSE);
9580   g_return_val_if_fail (path != NULL, FALSE);
9581
9582   if (_gtk_tree_view_find_node (tree_view,
9583                                 path,
9584                                 &tree,
9585                                 &node))
9586     return FALSE;
9587
9588   if (tree != NULL)
9589     return gtk_tree_view_real_expand_row (tree_view, path, tree, node, open_all, FALSE);
9590   else
9591     return FALSE;
9592 }
9593
9594 static gboolean
9595 gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
9596                                  GtkTreePath *path,
9597                                  GtkRBTree   *tree,
9598                                  GtkRBNode   *node,
9599                                  gboolean     animate)
9600 {
9601   GtkTreeIter iter;
9602   GtkTreeIter children;
9603   gboolean collapse;
9604   gint x, y;
9605   GList *list;
9606   GdkDisplay *display;
9607   GdkWindow *child, *parent;
9608
9609   if (node->children == NULL)
9610     return FALSE;
9611
9612   gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
9613
9614   g_signal_emit (tree_view, tree_view_signals[TEST_COLLAPSE_ROW], 0, &iter, path, &collapse);
9615
9616   if (collapse)
9617     return FALSE;
9618
9619   /* if the prelighted node is a child of us, we want to unprelight it.  We have
9620    * a chance to prelight the correct node below */
9621
9622   if (tree_view->priv->prelight_tree)
9623     {
9624       GtkRBTree *parent_tree;
9625       GtkRBNode *parent_node;
9626
9627       parent_tree = tree_view->priv->prelight_tree->parent_tree;
9628       parent_node = tree_view->priv->prelight_tree->parent_node;
9629       while (parent_tree)
9630         {
9631           if (parent_tree == tree && parent_node == node)
9632             {
9633               ensure_unprelighted (tree_view);
9634               break;
9635             }
9636           parent_node = parent_tree->parent_node;
9637           parent_tree = parent_tree->parent_tree;
9638         }
9639     }
9640
9641   TREE_VIEW_INTERNAL_ASSERT (gtk_tree_model_iter_children (tree_view->priv->model, &children, &iter), FALSE);
9642
9643   for (list = tree_view->priv->columns; list; list = list->next)
9644     {
9645       GtkTreeViewColumn *column = list->data;
9646
9647       if (column->visible == FALSE)
9648         continue;
9649       if (gtk_tree_view_column_get_sizing (column) == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
9650         _gtk_tree_view_column_cell_set_dirty (column, TRUE);
9651     }
9652
9653   if (tree_view->priv->destroy_count_func)
9654     {
9655       GtkTreePath *child_path;
9656       gint child_count = 0;
9657       child_path = gtk_tree_path_copy (path);
9658       gtk_tree_path_down (child_path);
9659       if (node->children)
9660         _gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, count_children_helper, &child_count);
9661       (* tree_view->priv->destroy_count_func) (tree_view, child_path, child_count, tree_view->priv->destroy_count_data);
9662       gtk_tree_path_free (child_path);
9663     }
9664
9665   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
9666     {
9667       GtkTreePath *cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
9668
9669       if (gtk_tree_path_is_ancestor (path, cursor_path))
9670         {
9671           gtk_tree_row_reference_free (tree_view->priv->cursor);
9672           tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
9673                                                                       tree_view->priv->model,
9674                                                                       path);
9675         }
9676       gtk_tree_path_free (cursor_path);
9677     }
9678
9679   if (gtk_tree_row_reference_valid (tree_view->priv->anchor))
9680     {
9681       GtkTreePath *anchor_path = gtk_tree_row_reference_get_path (tree_view->priv->anchor);
9682       if (gtk_tree_path_is_ancestor (path, anchor_path))
9683         {
9684           gtk_tree_row_reference_free (tree_view->priv->anchor);
9685           tree_view->priv->anchor = NULL;
9686         }
9687       gtk_tree_path_free (anchor_path);
9688     }
9689
9690   if (gtk_tree_row_reference_valid (tree_view->priv->last_button_press))
9691     {
9692       GtkTreePath *lsc = gtk_tree_row_reference_get_path (tree_view->priv->last_button_press);
9693       if (gtk_tree_path_is_ancestor (path, lsc))
9694         {
9695           gtk_tree_row_reference_free (tree_view->priv->last_button_press);
9696           tree_view->priv->last_button_press = NULL;
9697         }
9698       gtk_tree_path_free (lsc);
9699     }
9700
9701   if (gtk_tree_row_reference_valid (tree_view->priv->last_button_press_2))
9702     {
9703       GtkTreePath *lsc = gtk_tree_row_reference_get_path (tree_view->priv->last_button_press_2);
9704       if (gtk_tree_path_is_ancestor (path, lsc))
9705         {
9706           gtk_tree_row_reference_free (tree_view->priv->last_button_press_2);
9707           tree_view->priv->last_button_press_2 = NULL;
9708         }
9709       gtk_tree_path_free (lsc);
9710     }
9711
9712   if (gtk_tree_view_unref_and_check_selection_tree (tree_view, node->children))
9713     {
9714       _gtk_rbtree_remove (node->children);
9715       g_signal_emit_by_name (tree_view->priv->selection, "changed");
9716     }
9717   else
9718     _gtk_rbtree_remove (node->children);
9719
9720   if (tree_view->priv->expand_collapse_timeout)
9721     {
9722       g_source_remove (tree_view->priv->expand_collapse_timeout);
9723       tree_view->priv->expand_collapse_timeout = 0;
9724     }
9725   
9726   if (tree_view->priv->expanded_collapsed_node != NULL)
9727     {
9728       GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_EXPANDED);
9729       GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_COLLAPSED);
9730       
9731       tree_view->priv->expanded_collapsed_node = NULL;
9732     }
9733
9734   if (animate)
9735     {
9736       tree_view->priv->expand_collapse_timeout = g_timeout_add (50, expand_collapse_timeout, tree_view);
9737       tree_view->priv->expanded_collapsed_node = node;
9738       tree_view->priv->expanded_collapsed_tree = tree;
9739
9740       GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_EXPANDED);
9741     }
9742   
9743   if (GTK_WIDGET_MAPPED (tree_view))
9744     {
9745       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
9746     }
9747
9748   g_signal_emit (tree_view, tree_view_signals[ROW_COLLAPSED], 0, &iter, path);
9749
9750   /* now that we've collapsed all rows, we want to try to set the prelight
9751    * again. To do this, we fake a motion event and send it to ourselves. */
9752
9753   display = gdk_drawable_get_display (tree_view->priv->bin_window);
9754   child = tree_view->priv->bin_window;
9755   parent = gdk_window_get_parent (child);
9756
9757   if (gdk_window_get_pointer (parent, &x, &y, NULL) == child)
9758     {
9759       GdkEventMotion event;
9760       gint child_x, child_y;
9761
9762       gdk_window_get_position (child, &child_x, &child_y);
9763
9764       event.window = tree_view->priv->bin_window;
9765       event.x = x - child_x;
9766       event.y = y - child_y;
9767
9768       /* despite the fact this isn't a real event, I'm almost positive it will
9769        * never trigger a drag event.  maybe_drag is the only function that uses
9770        * more than just event.x and event.y. */
9771       gtk_tree_view_motion_bin_window (GTK_WIDGET (tree_view), &event);
9772     }
9773   return TRUE;
9774 }
9775
9776 /**
9777  * gtk_tree_view_collapse_row:
9778  * @tree_view: a #GtkTreeView
9779  * @path: path to a row in the @tree_view
9780  *
9781  * Collapses a row (hides its child rows, if they exist).
9782  *
9783  * Return value: %TRUE if the row was collapsed.
9784  **/
9785 gboolean
9786 gtk_tree_view_collapse_row (GtkTreeView *tree_view,
9787                             GtkTreePath *path)
9788 {
9789   GtkRBTree *tree;
9790   GtkRBNode *node;
9791
9792   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
9793   g_return_val_if_fail (tree_view->priv->tree != NULL, FALSE);
9794   g_return_val_if_fail (path != NULL, FALSE);
9795
9796   if (_gtk_tree_view_find_node (tree_view,
9797                                 path,
9798                                 &tree,
9799                                 &node))
9800     return FALSE;
9801
9802   if (tree == NULL || node->children == NULL)
9803     return FALSE;
9804
9805   return gtk_tree_view_real_collapse_row (tree_view, path, tree, node, FALSE);
9806 }
9807
9808 static void
9809 gtk_tree_view_map_expanded_rows_helper (GtkTreeView            *tree_view,
9810                                         GtkRBTree              *tree,
9811                                         GtkTreePath            *path,
9812                                         GtkTreeViewMappingFunc  func,
9813                                         gpointer                user_data)
9814 {
9815   GtkRBNode *node;
9816
9817   if (tree == NULL || tree->root == NULL)
9818     return;
9819
9820   node = tree->root;
9821
9822   while (node && node->left != tree->nil)
9823     node = node->left;
9824
9825   while (node)
9826     {
9827       if (node->children)
9828         {
9829           (* func) (tree_view, path, user_data);
9830           gtk_tree_path_down (path);
9831           gtk_tree_view_map_expanded_rows_helper (tree_view, node->children, path, func, user_data);
9832           gtk_tree_path_up (path);
9833         }
9834       gtk_tree_path_next (path);
9835       node = _gtk_rbtree_next (tree, node);
9836     }
9837 }
9838
9839 /**
9840  * gtk_tree_view_map_expanded_rows:
9841  * @tree_view: A #GtkTreeView
9842  * @func: A function to be called
9843  * @data: User data to be passed to the function.
9844  *
9845  * Calls @func on all expanded rows.
9846  **/
9847 void
9848 gtk_tree_view_map_expanded_rows (GtkTreeView            *tree_view,
9849                                  GtkTreeViewMappingFunc  func,
9850                                  gpointer                user_data)
9851 {
9852   GtkTreePath *path;
9853
9854   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
9855   g_return_if_fail (func != NULL);
9856
9857   path = gtk_tree_path_new_first ();
9858
9859   gtk_tree_view_map_expanded_rows_helper (tree_view,
9860                                           tree_view->priv->tree,
9861                                           path, func, user_data);
9862
9863   gtk_tree_path_free (path);
9864 }
9865
9866 /**
9867  * gtk_tree_view_row_expanded:
9868  * @tree_view: A #GtkTreeView.
9869  * @path: A #GtkTreePath to test expansion state.
9870  *
9871  * Returns %TRUE if the node pointed to by @path is expanded in @tree_view.
9872  *
9873  * Return value: %TRUE if #path is expanded.
9874  **/
9875 gboolean
9876 gtk_tree_view_row_expanded (GtkTreeView *tree_view,
9877                             GtkTreePath *path)
9878 {
9879   GtkRBTree *tree;
9880   GtkRBNode *node;
9881
9882   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
9883   g_return_val_if_fail (path != NULL, FALSE);
9884
9885   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
9886
9887   if (node == NULL)
9888     return FALSE;
9889
9890   return (node->children != NULL);
9891 }
9892
9893 static const GtkTargetEntry row_targets[] = {
9894   { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, 0 }
9895 };
9896
9897
9898 /**
9899  * gtk_tree_view_get_reorderable:
9900  * @tree_view: a #GtkTreeView
9901  *
9902  * Retrieves whether the user can reorder the tree via drag-and-drop. See
9903  * gtk_tree_view_set_reorderable().
9904  *
9905  * Return value: %TRUE if the tree can be reordered.
9906  **/
9907 gboolean
9908 gtk_tree_view_get_reorderable (GtkTreeView *tree_view)
9909 {
9910   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
9911
9912   return tree_view->priv->reorderable;
9913 }
9914
9915 /**
9916  * gtk_tree_view_set_reorderable:
9917  * @tree_view: A #GtkTreeView.
9918  * @reorderable: %TRUE, if the tree can be reordered.
9919  *
9920  * This function is a convenience function to allow you to reorder models that
9921  * support the #GtkDragSourceIface and the #GtkDragDestIface.  Both
9922  * #GtkTreeStore and #GtkListStore support these.  If @reorderable is %TRUE, then
9923  * the user can reorder the model by dragging and dropping rows.  The
9924  * developer can listen to these changes by connecting to the model's
9925  * signals.
9926  *
9927  * This function does not give you any degree of control over the order -- any
9928  * reorderering is allowed.  If more control is needed, you should probably
9929  * handle drag and drop manually.
9930  **/
9931 void
9932 gtk_tree_view_set_reorderable (GtkTreeView *tree_view,
9933                                gboolean     reorderable)
9934 {
9935   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
9936
9937   reorderable = reorderable != FALSE;
9938
9939   if (tree_view->priv->reorderable == reorderable)
9940     return;
9941
9942   if (reorderable)
9943     {
9944       gtk_tree_view_enable_model_drag_source (tree_view,
9945                                               GDK_BUTTON1_MASK,
9946                                               row_targets,
9947                                               G_N_ELEMENTS (row_targets),
9948                                               GDK_ACTION_MOVE);
9949       gtk_tree_view_enable_model_drag_dest (tree_view,
9950                                             row_targets,
9951                                             G_N_ELEMENTS (row_targets),
9952                                             GDK_ACTION_MOVE);
9953     }
9954   else
9955     {
9956       gtk_tree_view_unset_rows_drag_source (tree_view);
9957       gtk_tree_view_unset_rows_drag_dest (tree_view);
9958     }
9959
9960   tree_view->priv->reorderable = reorderable;
9961
9962   g_object_notify (G_OBJECT (tree_view), "reorderable");
9963 }
9964
9965 static void
9966 gtk_tree_view_real_set_cursor (GtkTreeView     *tree_view,
9967                                GtkTreePath     *path,
9968                                gboolean         clear_and_select,
9969                                gboolean         clamp_node)
9970 {
9971   GtkRBTree *tree = NULL;
9972   GtkRBNode *node = NULL;
9973   GdkModifierType state = 0;
9974
9975   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
9976     {
9977       GtkTreePath *cursor_path;
9978       cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
9979       gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
9980       gtk_tree_path_free (cursor_path);
9981     }
9982
9983   gtk_tree_row_reference_free (tree_view->priv->cursor);
9984   gtk_get_current_event_state (&state);
9985
9986   tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
9987                                                               tree_view->priv->model,
9988                                                               path);
9989   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
9990   if (tree != NULL)
9991     {
9992       GtkRBTree *new_tree = NULL;
9993       GtkRBNode *new_node = NULL;
9994
9995       if (clear_and_select && !((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK))
9996         _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
9997                                                   node, tree, path,
9998                                                   state, FALSE);
9999
10000       /* We have to re-find tree and node here again, somebody might have
10001        * cleared the node or the whole tree in the GtkTreeSelection::changed
10002        * callback. If the nodes differ we bail out here.
10003        */
10004       _gtk_tree_view_find_node (tree_view, path, &new_tree, &new_node);
10005
10006       if (tree != new_tree || node != new_node)
10007         return;
10008
10009       if (clamp_node)
10010         {
10011           gtk_tree_view_clamp_node_visible (tree_view, tree, node);
10012           _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
10013         }
10014     }
10015
10016   g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
10017 }
10018
10019 /**
10020  * gtk_tree_view_get_cursor:
10021  * @tree_view: A #GtkTreeView
10022  * @path: A pointer to be filled with the current cursor path, or %NULL
10023  * @focus_column: A pointer to be filled with the current focus column, or %NULL
10024  *
10025  * Fills in @path and @focus_column with the current path and focus column.  If
10026  * the cursor isn't currently set, then *@path will be %NULL.  If no column
10027  * currently has focus, then *@focus_column will be %NULL.
10028  **/
10029 void
10030 gtk_tree_view_get_cursor (GtkTreeView        *tree_view,
10031                           GtkTreePath       **path,
10032                           GtkTreeViewColumn **focus_column)
10033 {
10034   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10035
10036   if (path)
10037     {
10038       if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
10039         *path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
10040       else
10041         *path = NULL;
10042     }
10043
10044   if (focus_column)
10045     {
10046       *focus_column = tree_view->priv->focus_column;
10047     }
10048 }
10049
10050 /**
10051  * gtk_tree_view_set_cursor:
10052  * @tree_view: A #GtkTreeView
10053  * @path: A #GtkTreePath
10054  * @focus_column: A #GtkTreeViewColumn, or %NULL
10055  * @start_editing: %TRUE if the specified cell should start being edited.
10056  *
10057  * Sets the current keyboard focus to be at @path, and selects it.  This is
10058  * useful when you want to focus the user's attention on a particular row.  If
10059  * @focus_column is not %NULL, then focus is given to the column specified by 
10060  * it. Additionally, if @focus_column is specified, and @start_editing is 
10061  * %TRUE, then editing should be started in the specified cell.  
10062  * This function is often followed by @gtk_widget_grab_focus (@tree_view) 
10063  * in order to give keyboard focus to the widget.  Please note that editing 
10064  * can only happen when the widget is realized.
10065  **/
10066 void
10067 gtk_tree_view_set_cursor (GtkTreeView       *tree_view,
10068                           GtkTreePath       *path,
10069                           GtkTreeViewColumn *focus_column,
10070                           gboolean           start_editing)
10071 {
10072   gtk_tree_view_set_cursor_on_cell (tree_view, path, focus_column,
10073                                     NULL, start_editing);
10074 }
10075
10076 /**
10077  * gtk_tree_view_set_cursor_on_cell:
10078  * @tree_view: A #GtkTreeView
10079  * @path: A #GtkTreePath
10080  * @focus_column: A #GtkTreeViewColumn, or %NULL
10081  * @focus_cell: A #GtkCellRenderer, or %NULL
10082  * @start_editing: %TRUE if the specified cell should start being edited.
10083  *
10084  * Sets the current keyboard focus to be at @path, and selects it.  This is
10085  * useful when you want to focus the user's attention on a particular row.  If
10086  * @focus_column is not %NULL, then focus is given to the column specified by
10087  * it. If @focus_column and @focus_cell are not %NULL, and @focus_column
10088  * contains 2 or more editable or activatable cells, then focus is given to
10089  * the cell specified by @focus_cell. Additionally, if @focus_column is
10090  * specified, and @start_editing is %TRUE, then editing should be started in
10091  * the specified cell.  This function is often followed by
10092  * @gtk_widget_grab_focus (@tree_view) in order to give keyboard focus to the
10093  * widget.  Please note that editing can only happen when the widget is
10094  * realized.
10095  *
10096  * Since: 2.2
10097  **/
10098 void
10099 gtk_tree_view_set_cursor_on_cell (GtkTreeView       *tree_view,
10100                                   GtkTreePath       *path,
10101                                   GtkTreeViewColumn *focus_column,
10102                                   GtkCellRenderer   *focus_cell,
10103                                   gboolean           start_editing)
10104 {
10105   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10106   g_return_if_fail (path != NULL);
10107   if (focus_column)
10108     g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (focus_column));
10109   if (focus_cell)
10110     {
10111       g_return_if_fail (focus_column);
10112       g_return_if_fail (GTK_IS_CELL_RENDERER (focus_cell));
10113     }
10114
10115   /* cancel the current editing, if it exists */
10116   if (tree_view->priv->edited_column &&
10117       tree_view->priv->edited_column->editable_widget)
10118     gtk_tree_view_stop_editing (tree_view, TRUE);
10119
10120   gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
10121
10122   if (focus_column && focus_column->visible)
10123     {
10124       GList *list;
10125       gboolean column_in_tree = FALSE;
10126
10127       for (list = tree_view->priv->columns; list; list = list->next)
10128         if (list->data == focus_column)
10129           {
10130             column_in_tree = TRUE;
10131             break;
10132           }
10133       g_return_if_fail (column_in_tree);
10134       tree_view->priv->focus_column = focus_column;
10135       if (focus_cell)
10136         gtk_tree_view_column_focus_cell (focus_column, focus_cell);
10137       if (start_editing)
10138         gtk_tree_view_start_editing (tree_view, path);
10139     }
10140 }
10141
10142 /**
10143  * gtk_tree_view_get_bin_window:
10144  * @tree_view: A #GtkTreeView
10145  * 
10146  * Returns the window that @tree_view renders to.  This is used primarily to
10147  * compare to <literal>event->window</literal> to confirm that the event on
10148  * @tree_view is on the right window.
10149  * 
10150  * Return value: A #GdkWindow, or %NULL when @tree_view hasn't been realized yet
10151  **/
10152 GdkWindow *
10153 gtk_tree_view_get_bin_window (GtkTreeView *tree_view)
10154 {
10155   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
10156
10157   return tree_view->priv->bin_window;
10158 }
10159
10160 /**
10161  * gtk_tree_view_get_path_at_pos:
10162  * @tree_view: A #GtkTreeView.
10163  * @x: The x position to be identified.
10164  * @y: The y position to be identified.
10165  * @path: A pointer to a #GtkTreePath pointer to be filled in, or %NULL
10166  * @column: A pointer to a #GtkTreeViewColumn pointer to be filled in, or %NULL
10167  * @cell_x: A pointer where the X coordinate relative to the cell can be placed, or %NULL
10168  * @cell_y: A pointer where the Y coordinate relative to the cell can be placed, or %NULL
10169  *
10170  * Finds the path at the point (@x, @y), relative to widget coordinates.  That
10171  * is, @x and @y are relative to an events coordinates. @x and @y must come
10172  * from an event on the @tree_view only where event->window ==
10173  * gtk_tree_view_get_bin (). It is primarily for things like popup menus.
10174  * If @path is non-%NULL, then it will be filled with the #GtkTreePath at that
10175  * point.  This path should be freed with gtk_tree_path_free().  If @column
10176  * is non-%NULL, then it will be filled with the column at that point.
10177  * @cell_x and @cell_y return the coordinates relative to the cell background
10178  * (i.e. the @background_area passed to gtk_cell_renderer_render()).  This
10179  * function is only meaningful if @tree_view is realized.
10180  *
10181  * Return value: %TRUE if a row exists at that coordinate.
10182  **/
10183 gboolean
10184 gtk_tree_view_get_path_at_pos (GtkTreeView        *tree_view,
10185                                gint                x,
10186                                gint                y,
10187                                GtkTreePath       **path,
10188                                GtkTreeViewColumn **column,
10189                                gint               *cell_x,
10190                                gint               *cell_y)
10191 {
10192   GtkRBTree *tree;
10193   GtkRBNode *node;
10194   gint y_offset;
10195
10196   g_return_val_if_fail (tree_view != NULL, FALSE);
10197   g_return_val_if_fail (tree_view->priv->bin_window != NULL, FALSE);
10198
10199   if (path)
10200     *path = NULL;
10201   if (column)
10202     *column = NULL;
10203
10204   if (tree_view->priv->tree == NULL)
10205     return FALSE;
10206
10207   if (x > tree_view->priv->hadjustment->upper)
10208     return FALSE;
10209
10210   if (x < 0 || y < 0)
10211     return FALSE;
10212
10213   if (column || cell_x)
10214     {
10215       GtkTreeViewColumn *tmp_column;
10216       GtkTreeViewColumn *last_column = NULL;
10217       GList *list;
10218       gint remaining_x = x;
10219       gboolean found = FALSE;
10220
10221       for (list = tree_view->priv->columns; list; list = list->next)
10222         {
10223           tmp_column = list->data;
10224
10225           if (tmp_column->visible == FALSE)
10226             continue;
10227
10228           last_column = tmp_column;
10229           if (remaining_x <= tmp_column->width)
10230             {
10231               found = TRUE;
10232
10233               if (column)
10234                 *column = tmp_column;
10235
10236               if (cell_x)
10237                 *cell_x = remaining_x;
10238
10239               break;
10240             }
10241           remaining_x -= tmp_column->width;
10242         }
10243
10244       if (!found)
10245         {
10246           if (column)
10247             *column = last_column;
10248
10249           if (cell_x)
10250             *cell_x = last_column->width + remaining_x;
10251         }
10252     }
10253
10254   y_offset = _gtk_rbtree_find_offset (tree_view->priv->tree,
10255                                       TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y),
10256                                       &tree, &node);
10257
10258   if (tree == NULL)
10259     return FALSE;
10260
10261   if (cell_y)
10262     *cell_y = y_offset;
10263
10264   if (path)
10265     *path = _gtk_tree_view_find_path (tree_view, tree, node);
10266
10267   return TRUE;
10268 }
10269
10270
10271 /**
10272  * gtk_tree_view_get_cell_area:
10273  * @tree_view: a #GtkTreeView
10274  * @path: a #GtkTreePath for the row, or %NULL to get only horizontal coordinates
10275  * @column: a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordiantes
10276  * @rect: rectangle to fill with cell rect
10277  *
10278  * Fills the bounding rectangle in tree window coordinates for the cell at the
10279  * row specified by @path and the column specified by @column.  If @path is
10280  * %NULL, or points to a path not currently displayed, the @y and @height fields
10281  * of the rectangle will be filled with 0. If @column is %NULL, the @x and @width
10282  * fields will be filled with 0.  The sum of all cell rects does not cover the
10283  * entire tree; there are extra pixels in between rows, for example. The
10284  * returned rectangle is equivalent to the @cell_area passed to
10285  * gtk_cell_renderer_render().  This function is only valid if #tree_view is
10286  * realized.
10287  **/
10288 void
10289 gtk_tree_view_get_cell_area (GtkTreeView        *tree_view,
10290                              GtkTreePath        *path,
10291                              GtkTreeViewColumn  *column,
10292                              GdkRectangle       *rect)
10293 {
10294   GtkRBTree *tree = NULL;
10295   GtkRBNode *node = NULL;
10296   gint vertical_separator;
10297   gint horizontal_separator;
10298
10299   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10300   g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column));
10301   g_return_if_fail (rect != NULL);
10302   g_return_if_fail (!column || column->tree_view == (GtkWidget *) tree_view);
10303   g_return_if_fail (GTK_WIDGET_REALIZED (tree_view));
10304
10305   gtk_widget_style_get (GTK_WIDGET (tree_view),
10306                         "vertical_separator", &vertical_separator,
10307                         "horizontal_separator", &horizontal_separator,
10308                         NULL);
10309
10310   rect->x = 0;
10311   rect->y = 0;
10312   rect->width = 0;
10313   rect->height = 0;
10314
10315   if (column)
10316     {
10317       rect->x = column->button->allocation.x + horizontal_separator/2;
10318       rect->width = column->button->allocation.width - horizontal_separator;
10319     }
10320
10321   if (path)
10322     {
10323       gboolean ret = _gtk_tree_view_find_node (tree_view, path, &tree, &node);
10324
10325       /* Get vertical coords */
10326       if ((!ret && tree == NULL) || ret)
10327         return;
10328
10329       rect->y = CELL_FIRST_PIXEL (tree_view, tree, node, vertical_separator);
10330       rect->height = MAX (CELL_HEIGHT (node, vertical_separator), tree_view->priv->expander_size - vertical_separator);
10331
10332       if (gtk_tree_view_is_expander_column (tree_view, column) &&
10333           TREE_VIEW_DRAW_EXPANDERS (tree_view))
10334         {
10335           gint depth = gtk_tree_path_get_depth (path) - 1;
10336
10337           rect->x += depth * tree_view->priv->expander_size;
10338           rect->width -= depth * tree_view->priv->expander_size;
10339           rect->width = MAX (rect->width, 0);
10340         }
10341     }
10342 }
10343
10344 /**
10345  * gtk_tree_view_get_background_area:
10346  * @tree_view: a #GtkTreeView
10347  * @path: a #GtkTreePath for the row, or %NULL to get only horizontal coordinates
10348  * @column: a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordiantes
10349  * @rect: rectangle to fill with cell background rect
10350  *
10351  * Fills the bounding rectangle in tree window coordinates for the cell at the
10352  * row specified by @path and the column specified by @column.  If @path is
10353  * %NULL, or points to a node not found in the tree, the @y and @height fields of
10354  * the rectangle will be filled with 0. If @column is %NULL, the @x and @width
10355  * fields will be filled with 0.  The returned rectangle is equivalent to the
10356  * @background_area passed to gtk_cell_renderer_render().  These background
10357  * areas tile to cover the entire tree window (except for the area used for
10358  * header buttons). Contrast with the @cell_area, returned by
10359  * gtk_tree_view_get_cell_area(), which returns only the cell itself, excluding
10360  * surrounding borders and the tree expander area.
10361  *
10362  **/
10363 void
10364 gtk_tree_view_get_background_area (GtkTreeView        *tree_view,
10365                                    GtkTreePath        *path,
10366                                    GtkTreeViewColumn  *column,
10367                                    GdkRectangle       *rect)
10368 {
10369   GtkRBTree *tree = NULL;
10370   GtkRBNode *node = NULL;
10371
10372   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10373   g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column));
10374   g_return_if_fail (rect != NULL);
10375
10376   rect->x = 0;
10377   rect->y = 0;
10378   rect->width = 0;
10379   rect->height = 0;
10380
10381   if (path)
10382     {
10383       /* Get vertical coords */
10384
10385       if (!_gtk_tree_view_find_node (tree_view, path, &tree, &node) &&
10386           tree == NULL)
10387         return;
10388
10389       rect->y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
10390
10391       rect->height = MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size);
10392     }
10393
10394   if (column)
10395     {
10396       gint x2 = 0;
10397
10398       gtk_tree_view_get_background_xrange (tree_view, tree, column, &rect->x, &x2);
10399       rect->width = x2 - rect->x;
10400     }
10401 }
10402
10403 /**
10404  * gtk_tree_view_get_visible_rect:
10405  * @tree_view: a #GtkTreeView
10406  * @visible_rect: rectangle to fill
10407  *
10408  * Fills @visible_rect with the currently-visible region of the
10409  * buffer, in tree coordinates. Convert to widget coordinates with
10410  * gtk_tree_view_tree_to_widget_coords(). Tree coordinates start at
10411  * 0,0 for row 0 of the tree, and cover the entire scrollable area of
10412  * the tree.
10413  **/
10414 void
10415 gtk_tree_view_get_visible_rect (GtkTreeView  *tree_view,
10416                                 GdkRectangle *visible_rect)
10417 {
10418   GtkWidget *widget;
10419
10420   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10421
10422   widget = GTK_WIDGET (tree_view);
10423
10424   if (visible_rect)
10425     {
10426       visible_rect->x = tree_view->priv->hadjustment->value;
10427       visible_rect->y = tree_view->priv->vadjustment->value;
10428       visible_rect->width = widget->allocation.width;
10429       visible_rect->height = widget->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
10430     }
10431 }
10432
10433 /**
10434  * gtk_tree_view_widget_to_tree_coords:
10435  * @tree_view: a #GtkTreeView
10436  * @wx: widget X coordinate
10437  * @wy: widget Y coordinate
10438  * @tx: return location for tree X coordinate
10439  * @ty: return location for tree Y coordinate
10440  *
10441  * Converts widget coordinates to coordinates for the
10442  * tree window (the full scrollable area of the tree).
10443  *
10444  **/
10445 void
10446 gtk_tree_view_widget_to_tree_coords (GtkTreeView *tree_view,
10447                                      gint         wx,
10448                                      gint         wy,
10449                                      gint        *tx,
10450                                      gint        *ty)
10451 {
10452   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10453
10454   if (tx)
10455     *tx = wx + tree_view->priv->hadjustment->value;
10456   if (ty)
10457     *ty = wy + tree_view->priv->dy;
10458 }
10459
10460 /**
10461  * gtk_tree_view_tree_to_widget_coords:
10462  * @tree_view: a #GtkTreeView
10463  * @tx: tree X coordinate
10464  * @ty: tree Y coordinate
10465  * @wx: return location for widget X coordinate
10466  * @wy: return location for widget Y coordinate
10467  *
10468  * Converts tree coordinates (coordinates in full scrollable area of the tree)
10469  * to widget coordinates.
10470  *
10471  **/
10472 void
10473 gtk_tree_view_tree_to_widget_coords (GtkTreeView *tree_view,
10474                                      gint         tx,
10475                                      gint         ty,
10476                                      gint        *wx,
10477                                      gint        *wy)
10478 {
10479   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10480
10481   if (wx)
10482     *wx = tx - tree_view->priv->hadjustment->value;
10483   if (wy)
10484     *wy = ty - tree_view->priv->dy;
10485 }
10486
10487 static void
10488 unset_reorderable (GtkTreeView *tree_view)
10489 {
10490   if (tree_view->priv->reorderable)
10491     {
10492       tree_view->priv->reorderable = FALSE;
10493       g_object_notify (G_OBJECT (tree_view), "reorderable");
10494     }
10495 }
10496
10497 void
10498 gtk_tree_view_enable_model_drag_source (GtkTreeView              *tree_view,
10499                                         GdkModifierType           start_button_mask,
10500                                         const GtkTargetEntry     *targets,
10501                                         gint                      n_targets,
10502                                         GdkDragAction             actions)
10503 {
10504   TreeViewDragInfo *di;
10505
10506   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10507
10508   di = ensure_info (tree_view);
10509   clear_source_info (di);
10510
10511   di->start_button_mask = start_button_mask;
10512   di->source_target_list = gtk_target_list_new (targets, n_targets);
10513   di->source_actions = actions;
10514
10515   di->source_set = TRUE;
10516
10517   unset_reorderable (tree_view);
10518 }
10519
10520 void
10521 gtk_tree_view_enable_model_drag_dest (GtkTreeView              *tree_view,
10522                                       const GtkTargetEntry     *targets,
10523                                       gint                      n_targets,
10524                                       GdkDragAction             actions)
10525 {
10526   TreeViewDragInfo *di;
10527
10528   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10529
10530   gtk_drag_dest_set (GTK_WIDGET (tree_view),
10531                      0,
10532                      NULL,
10533                      0,
10534                      actions);
10535
10536   di = ensure_info (tree_view);
10537   clear_dest_info (di);
10538
10539   if (targets)
10540     di->dest_target_list = gtk_target_list_new (targets, n_targets);
10541
10542   di->dest_set = TRUE;
10543
10544   unset_reorderable (tree_view);
10545 }
10546
10547 void
10548 gtk_tree_view_unset_rows_drag_source (GtkTreeView *tree_view)
10549 {
10550   TreeViewDragInfo *di;
10551
10552   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10553
10554   di = get_info (tree_view);
10555
10556   if (di)
10557     {
10558       if (di->source_set)
10559         {
10560           clear_source_info (di);
10561           di->source_set = FALSE;
10562         }
10563
10564       if (!di->dest_set && !di->source_set)
10565         remove_info (tree_view);
10566     }
10567   
10568   unset_reorderable (tree_view);
10569 }
10570
10571 void
10572 gtk_tree_view_unset_rows_drag_dest (GtkTreeView *tree_view)
10573 {
10574   TreeViewDragInfo *di;
10575
10576   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10577
10578   di = get_info (tree_view);
10579
10580   if (di)
10581     {
10582       if (di->dest_set)
10583         {
10584           gtk_drag_dest_unset (GTK_WIDGET (tree_view));
10585           clear_dest_info (di);
10586           di->dest_set = FALSE;
10587         }
10588
10589       if (!di->dest_set && !di->source_set)
10590         remove_info (tree_view);
10591     }
10592
10593   unset_reorderable (tree_view);
10594 }
10595
10596 void
10597 gtk_tree_view_set_drag_dest_row (GtkTreeView            *tree_view,
10598                                  GtkTreePath            *path,
10599                                  GtkTreeViewDropPosition pos)
10600 {
10601   GtkTreePath *current_dest;
10602   /* Note; this function is exported to allow a custom DND
10603    * implementation, so it can't touch TreeViewDragInfo
10604    */
10605
10606   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10607
10608   current_dest = NULL;
10609
10610   if (tree_view->priv->drag_dest_row)
10611     current_dest = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
10612
10613   if (tree_view->priv->drag_dest_row)
10614     gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
10615
10616   tree_view->priv->drag_dest_pos = pos;
10617
10618   if (path)
10619     {
10620       tree_view->priv->drag_dest_row =
10621         gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
10622       gtk_tree_view_queue_draw_path (tree_view, path, NULL);
10623     }
10624   else
10625     tree_view->priv->drag_dest_row = NULL;
10626
10627   if (current_dest)
10628     {
10629       GtkRBTree *tree, *new_tree;
10630       GtkRBNode *node, *new_node;
10631
10632       _gtk_tree_view_find_node (tree_view, current_dest, &tree, &node);
10633       _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
10634
10635       if (tree && node)
10636         {
10637           _gtk_rbtree_next_full (tree, node, &new_tree, &new_node);
10638           if (new_tree && new_node)
10639             _gtk_tree_view_queue_draw_node (tree_view, new_tree, new_node, NULL);
10640
10641           _gtk_rbtree_prev_full (tree, node, &new_tree, &new_node);
10642           if (new_tree && new_node)
10643             _gtk_tree_view_queue_draw_node (tree_view, new_tree, new_node, NULL);
10644         }
10645       gtk_tree_path_free (current_dest);
10646     }
10647 }
10648
10649 void
10650 gtk_tree_view_get_drag_dest_row (GtkTreeView              *tree_view,
10651                                  GtkTreePath             **path,
10652                                  GtkTreeViewDropPosition  *pos)
10653 {
10654   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10655
10656   if (path)
10657     {
10658       if (tree_view->priv->drag_dest_row)
10659         *path = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
10660       else
10661         *path = NULL;
10662     }
10663
10664   if (pos)
10665     *pos = tree_view->priv->drag_dest_pos;
10666 }
10667
10668 gboolean
10669 gtk_tree_view_get_dest_row_at_pos (GtkTreeView             *tree_view,
10670                                    gint                     drag_x,
10671                                    gint                     drag_y,
10672                                    GtkTreePath            **path,
10673                                    GtkTreeViewDropPosition *pos)
10674 {
10675   gint cell_y;
10676   gdouble offset_into_row;
10677   gdouble third;
10678   GdkRectangle cell;
10679   GtkTreeViewColumn *column = NULL;
10680   GtkTreePath *tmp_path = NULL;
10681
10682   /* Note; this function is exported to allow a custom DND
10683    * implementation, so it can't touch TreeViewDragInfo
10684    */
10685
10686   g_return_val_if_fail (tree_view != NULL, FALSE);
10687   g_return_val_if_fail (drag_x >= 0, FALSE);
10688   g_return_val_if_fail (drag_y >= 0, FALSE);
10689   g_return_val_if_fail (tree_view->priv->bin_window != NULL, FALSE);
10690
10691
10692   if (path)
10693     *path = NULL;
10694
10695   if (tree_view->priv->tree == NULL)
10696     return FALSE;
10697
10698   /* If in the top third of a row, we drop before that row; if
10699    * in the bottom third, drop after that row; if in the middle,
10700    * and the row has children, drop into the row.
10701    */
10702
10703   if (!gtk_tree_view_get_path_at_pos (tree_view,
10704                                       drag_x,
10705                                       drag_y - TREE_VIEW_HEADER_HEIGHT (tree_view),
10706                                       &tmp_path,
10707                                       &column,
10708                                       NULL,
10709                                       &cell_y))
10710     return FALSE;
10711
10712   gtk_tree_view_get_background_area (tree_view, tmp_path, column,
10713                                      &cell);
10714
10715   offset_into_row = cell_y;
10716
10717   if (path)
10718     *path = tmp_path;
10719   else
10720     gtk_tree_path_free (tmp_path);
10721
10722   tmp_path = NULL;
10723
10724   third = cell.height / 3.0;
10725
10726   if (pos)
10727     {
10728       if (offset_into_row < third)
10729         {
10730           *pos = GTK_TREE_VIEW_DROP_BEFORE;
10731         }
10732       else if (offset_into_row < (cell.height / 2.0))
10733         {
10734           *pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE;
10735         }
10736       else if (offset_into_row < third * 2.0)
10737         {
10738           *pos = GTK_TREE_VIEW_DROP_INTO_OR_AFTER;
10739         }
10740       else
10741         {
10742           *pos = GTK_TREE_VIEW_DROP_AFTER;
10743         }
10744     }
10745
10746   return TRUE;
10747 }
10748
10749
10750
10751 /* KEEP IN SYNC WITH GTK_TREE_VIEW_BIN_EXPOSE */
10752 /**
10753  * gtk_tree_view_create_row_drag_icon:
10754  * @tree_view: a #GtkTreeView
10755  * @path: a #GtkTreePath in @tree_view
10756  *
10757  * Creates a #GdkPixmap representation of the row at @path.  This image is used
10758  * for a drag icon.
10759  *
10760  * Return value: a newly-allocated pixmap of the drag icon.
10761  **/
10762 GdkPixmap *
10763 gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
10764                                     GtkTreePath  *path)
10765 {
10766   GtkTreeIter   iter;
10767   GtkRBTree    *tree;
10768   GtkRBNode    *node;
10769   gint cell_offset;
10770   GList *list;
10771   GdkRectangle background_area;
10772   GdkRectangle expose_area;
10773   GtkWidget *widget;
10774   gint depth;
10775   /* start drawing inside the black outline */
10776   gint x = 1, y = 1;
10777   GdkDrawable *drawable;
10778   gint bin_window_width;
10779
10780   widget = GTK_WIDGET (tree_view);
10781
10782   depth = gtk_tree_path_get_depth (path);
10783
10784   _gtk_tree_view_find_node (tree_view,
10785                             path,
10786                             &tree,
10787                             &node);
10788
10789   if (tree == NULL)
10790     return NULL;
10791
10792   if (!gtk_tree_model_get_iter (tree_view->priv->model,
10793                                 &iter,
10794                                 path))
10795     return NULL;
10796
10797   cell_offset = x;
10798
10799   background_area.y = y;
10800   background_area.height = MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size);
10801
10802   gdk_drawable_get_size (tree_view->priv->bin_window,
10803                          &bin_window_width, NULL);
10804
10805   drawable = gdk_pixmap_new (tree_view->priv->bin_window,
10806                              bin_window_width + 2,
10807                              background_area.height + 2,
10808                              -1);
10809
10810   expose_area.x = 0;
10811   expose_area.y = 0;
10812   expose_area.width = bin_window_width + 2;
10813   expose_area.height = background_area.height + 2;
10814
10815   gdk_draw_rectangle (drawable,
10816                       widget->style->base_gc [GTK_WIDGET_STATE (widget)],
10817                       TRUE,
10818                       0, 0,
10819                       bin_window_width + 2,
10820                       background_area.height + 2);
10821
10822   for (list = tree_view->priv->columns; list; list = list->next)
10823     {
10824       GtkTreeViewColumn *column = list->data;
10825       GdkRectangle cell_area;
10826       gint vertical_separator;
10827
10828       if (!column->visible)
10829         continue;
10830
10831       gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, &iter,
10832                                                GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
10833                                                node->children?TRUE:FALSE);
10834
10835       background_area.x = cell_offset;
10836       background_area.width = column->width;
10837
10838       cell_area = background_area;
10839
10840       gtk_widget_style_get (widget, "vertical_separator", &vertical_separator, NULL);
10841       cell_area.y += vertical_separator / 2;
10842       cell_area.height -= vertical_separator;
10843
10844       if (gtk_tree_view_is_expander_column (tree_view, column) &&
10845           TREE_VIEW_DRAW_EXPANDERS(tree_view))
10846         {
10847           cell_area.x += depth * tree_view->priv->expander_size;
10848           cell_area.width -= depth * tree_view->priv->expander_size;
10849         }
10850
10851       if (gtk_tree_view_column_cell_is_visible (column))
10852         _gtk_tree_view_column_cell_render (column,
10853                                            drawable,
10854                                            &background_area,
10855                                            &cell_area,
10856                                            &expose_area,
10857                                            0);
10858       cell_offset += column->width;
10859     }
10860
10861   gdk_draw_rectangle (drawable,
10862                       widget->style->black_gc,
10863                       FALSE,
10864                       0, 0,
10865                       bin_window_width + 1,
10866                       background_area.height + 1);
10867
10868   return drawable;
10869 }
10870
10871
10872 /**
10873  * gtk_tree_view_set_destroy_count_func:
10874  * @tree_view: A #GtkTreeView
10875  * @func: Function to be called when a view row is destroyed, or %NULL
10876  * @data: User data to be passed to @func, or %NULL
10877  * @destroy: Destroy notifier for @data, or %NULL
10878  *
10879  * This function should almost never be used.  It is meant for private use by
10880  * ATK for determining the number of visible children that are removed when the
10881  * user collapses a row, or a row is deleted.
10882  **/
10883 void
10884 gtk_tree_view_set_destroy_count_func (GtkTreeView             *tree_view,
10885                                       GtkTreeDestroyCountFunc  func,
10886                                       gpointer                 data,
10887                                       GtkDestroyNotify         destroy)
10888 {
10889   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10890
10891   if (tree_view->priv->destroy_count_destroy)
10892     (* tree_view->priv->destroy_count_destroy) (tree_view->priv->destroy_count_data);
10893
10894   tree_view->priv->destroy_count_func = func;
10895   tree_view->priv->destroy_count_data = data;
10896   tree_view->priv->destroy_count_destroy = destroy;
10897 }
10898
10899
10900 /*
10901  * Interactive search
10902  */
10903
10904 /**
10905  * gtk_tree_view_set_enable_search:
10906  * @tree_view: A #GtkTreeView
10907  * @enable_search: %TRUE, if the user can search interactively
10908  *
10909  * If @enable_search is set, then the user can type in text to search through
10910  * the tree interactively.
10911  */
10912 void
10913 gtk_tree_view_set_enable_search (GtkTreeView *tree_view,
10914                                  gboolean     enable_search)
10915 {
10916   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10917
10918   enable_search = !!enable_search;
10919   
10920   if (tree_view->priv->enable_search != enable_search)
10921     {
10922        tree_view->priv->enable_search = enable_search;
10923        g_object_notify (G_OBJECT (tree_view), "enable_search");
10924     }
10925 }
10926
10927 /**
10928  * gtk_tree_view_get_enable_search:
10929  * @tree_view: A #GtkTreeView
10930  *
10931  * Returns whether or not the tree allows interactive searching.
10932  *
10933  * Return value: whether or not to let the user search interactively
10934  */
10935 gboolean
10936 gtk_tree_view_get_enable_search (GtkTreeView *tree_view)
10937 {
10938   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
10939
10940   return tree_view->priv->enable_search;
10941 }
10942
10943
10944 /**
10945  * gtk_tree_view_get_search_column:
10946  * @tree_view: A #GtkTreeView
10947  *
10948  * Gets the column searched on by the interactive search code.
10949  *
10950  * Return value: the column the interactive search code searches in.
10951  */
10952 gint
10953 gtk_tree_view_get_search_column (GtkTreeView *tree_view)
10954 {
10955   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), 0);
10956
10957   return (tree_view->priv->search_column);
10958 }
10959
10960 /**
10961  * gtk_tree_view_set_search_column:
10962  * @tree_view: A #GtkTreeView
10963  * @column: the column of the model to search in
10964  *
10965  * Sets @column as the column where the interactive search code should
10966  * search in.  Additionally, turns on interactive searching. Note that
10967  * @column refers to a column of the model.
10968  */
10969 void
10970 gtk_tree_view_set_search_column (GtkTreeView *tree_view,
10971                                  gint         column)
10972 {
10973   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10974   g_return_if_fail (column >= 0);
10975
10976   if (tree_view->priv->search_column == column)
10977     return;
10978
10979   tree_view->priv->search_column = column;
10980   g_object_notify (G_OBJECT (tree_view), "search_column");
10981 }
10982
10983 /**
10984  * gtk_tree_view_get_search_equal_func:
10985  * @tree_view: A #GtkTreeView
10986  *
10987  * Returns the compare function currently in use.
10988  *
10989  * Return value: the currently used compare function for the search code.
10990  */
10991
10992 GtkTreeViewSearchEqualFunc
10993 gtk_tree_view_get_search_equal_func (GtkTreeView *tree_view)
10994 {
10995   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
10996
10997   return tree_view->priv->search_equal_func;
10998 }
10999
11000 /**
11001  * gtk_tree_view_set_search_equal_func:
11002  * @tree_view: A #GtkTreeView
11003  * @search_equal_func: the compare function to use during the search
11004  * @search_user_data: user data to pass to @search_equal_func, or %NULL
11005  * @search_destroy: Destroy notifier for @search_user_data, or %NULL
11006  *
11007  * Sets the compare function for the interactive search capabilities.
11008  **/
11009 void
11010 gtk_tree_view_set_search_equal_func (GtkTreeView                *tree_view,
11011                                      GtkTreeViewSearchEqualFunc  search_equal_func,
11012                                      gpointer                    search_user_data,
11013                                      GtkDestroyNotify            search_destroy)
11014 {
11015   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
11016   g_return_if_fail (search_equal_func !=NULL);
11017
11018   if (tree_view->priv->search_destroy)
11019     (* tree_view->priv->search_destroy) (tree_view->priv->search_user_data);
11020
11021   tree_view->priv->search_equal_func = search_equal_func;
11022   tree_view->priv->search_user_data = search_user_data;
11023   tree_view->priv->search_destroy = search_destroy;
11024   if (tree_view->priv->search_equal_func == NULL)
11025     tree_view->priv->search_equal_func = gtk_tree_view_search_equal_func;
11026 }
11027
11028 static void
11029 gtk_tree_view_search_dialog_destroy (GtkWidget   *search_dialog,
11030                                      GtkTreeView *tree_view)
11031 {
11032   GtkEntry *entry = (GtkEntry *)(gtk_container_get_children (GTK_CONTAINER (search_dialog)))->data;
11033   gint *selected_iter;
11034
11035   if (tree_view->priv->disable_popdown)
11036     return;
11037
11038   if (entry)
11039     {
11040       /* send focus-in event */
11041       send_focus_change (GTK_WIDGET (entry), FALSE);
11042     }
11043
11044   /* remove data from tree_view */
11045   g_object_set_data (G_OBJECT (tree_view), GTK_TREE_VIEW_SEARCH_DIALOG_KEY,
11046                      NULL);
11047
11048   selected_iter = g_object_get_data (G_OBJECT (search_dialog),
11049                                      "gtk-tree-view-selected-iter");
11050   if (selected_iter)
11051     g_free (selected_iter);
11052   g_object_set_data (G_OBJECT (search_dialog), "gtk-tree-view-selected-iter",
11053                      NULL);
11054
11055   gtk_widget_destroy (search_dialog);
11056 }
11057
11058 static void
11059 gtk_tree_view_search_position_func (GtkTreeView *tree_view,
11060                                     GtkWidget   *search_dialog)
11061 {
11062   gint x, y;
11063   gint tree_x, tree_y;
11064   gint tree_width, tree_height;
11065   GdkWindow *tree_window = GTK_WIDGET (tree_view)->window;
11066   GdkScreen *screen = gdk_drawable_get_screen (tree_window);
11067   GtkRequisition requisition;
11068
11069   gtk_widget_realize (search_dialog);
11070
11071   gdk_window_get_origin (tree_window, &tree_x, &tree_y);
11072   gdk_drawable_get_size (tree_window,
11073                          &tree_width,
11074                          &tree_height);
11075   gtk_widget_size_request (search_dialog, &requisition);
11076
11077   if (tree_x + tree_width - requisition.width > gdk_screen_get_width (screen))
11078     x = gdk_screen_get_width (screen) - requisition.width;
11079   else if (tree_x + tree_width - requisition.width < 0)
11080     x = 0;
11081   else
11082     x = tree_x + tree_width - requisition.width;
11083
11084   if (tree_y + tree_height > gdk_screen_get_height (screen))
11085     y = gdk_screen_get_height (screen) - requisition.height;
11086   else if (tree_y + tree_height < 0) /* isn't really possible ... */
11087     y = 0;
11088   else
11089     y = tree_y + tree_height;
11090
11091   gtk_window_move (GTK_WINDOW (search_dialog), x, y);
11092 }
11093
11094 static void
11095 gtk_tree_view_search_disable_popdown (GtkEntry *entry,
11096                                       GtkMenu  *menu,
11097                                       gpointer  data)
11098 {
11099   GtkTreeView *tree_view = (GtkTreeView *)data;
11100
11101   tree_view->priv->disable_popdown = 1;
11102   g_signal_connect (menu, "hide",
11103                     G_CALLBACK (gtk_tree_view_search_enable_popdown), data);
11104 }
11105
11106 static gboolean
11107 gtk_tree_view_real_search_enable_popdown (gpointer data)
11108 {
11109   GtkTreeView *tree_view = (GtkTreeView *)data;
11110
11111   GDK_THREADS_ENTER ();
11112
11113   tree_view->priv->disable_popdown = 0;
11114
11115   GDK_THREADS_LEAVE ();
11116
11117   return FALSE;
11118 }
11119
11120 static void
11121 gtk_tree_view_search_enable_popdown (GtkWidget *widget,
11122                                      gpointer   data)
11123 {
11124   g_timeout_add (200, gtk_tree_view_real_search_enable_popdown, data);
11125 }
11126
11127 static gboolean
11128 gtk_tree_view_search_delete_event (GtkWidget *widget,
11129                                    GdkEventAny *event,
11130                                    GtkTreeView *tree_view)
11131 {
11132   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
11133
11134   gtk_tree_view_search_dialog_destroy (widget, tree_view);
11135
11136   return TRUE;
11137 }
11138
11139 static gboolean
11140 gtk_tree_view_search_button_press_event (GtkWidget *widget,
11141                                          GdkEventButton *event,
11142                                          GtkTreeView *tree_view)
11143 {
11144   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
11145
11146   gtk_tree_view_search_dialog_destroy (widget, tree_view);
11147
11148   return TRUE;
11149 }
11150
11151 static gboolean
11152 gtk_tree_view_search_key_press_event (GtkWidget *widget,
11153                                       GdkEventKey *event,
11154                                       GtkTreeView *tree_view)
11155 {
11156   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
11157   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
11158
11159   /* close window */
11160   if (event->keyval == GDK_Escape ||
11161       event->keyval == GDK_Return ||
11162       event->keyval == GDK_Tab)
11163     {
11164       gtk_tree_view_search_dialog_destroy (widget, tree_view);
11165       return TRUE;
11166     }
11167
11168   /* select previous matching iter */
11169   if (event->keyval == GDK_Up || event->keyval == GDK_KP_Up)
11170     {
11171       gtk_tree_view_search_move (widget, tree_view, TRUE);
11172       return TRUE;
11173     }
11174
11175   /* select next matching iter */
11176   if (event->keyval == GDK_Down || event->keyval == GDK_KP_Down)
11177     {
11178       gtk_tree_view_search_move (widget, tree_view, FALSE);
11179       return TRUE;
11180     }
11181
11182   return FALSE;
11183 }
11184
11185 static void
11186 gtk_tree_view_search_move (GtkWidget   *window,
11187                            GtkTreeView *tree_view,
11188                            gboolean     up)
11189 {
11190   gboolean ret;
11191   gint *selected_iter;
11192   gint len;
11193   gint count = 0;
11194   gchar *text;
11195   GtkTreeIter iter;
11196   GtkTreeModel *model;
11197   GtkTreeSelection *selection;
11198
11199   text = g_object_get_data (G_OBJECT (window), "gtk-tree-view-text");
11200   selected_iter = g_object_get_data (G_OBJECT (window), "gtk-tree-view-selected-iter");
11201
11202   g_return_if_fail (text != NULL);
11203
11204   if (!selected_iter || (up && *selected_iter == 1))
11205     return;
11206
11207   len = strlen (text);
11208
11209   if (len < 1)
11210     return;
11211
11212   model = gtk_tree_view_get_model (tree_view);
11213   selection = gtk_tree_view_get_selection (tree_view);
11214
11215   /* search */
11216   gtk_tree_selection_unselect_all (selection);
11217   gtk_tree_model_get_iter_first (model, &iter);
11218
11219   ret = gtk_tree_view_search_iter (model, selection, &iter, text,
11220                                    &count, up?((*selected_iter) - 1):((*selected_iter + 1)));
11221
11222   if (ret)
11223     {
11224       /* found */
11225       *selected_iter += up?(-1):(1);
11226     }
11227   else
11228     {
11229       /* return to old iter */
11230       count = 0;
11231       gtk_tree_model_get_iter_first (model, &iter);
11232       gtk_tree_view_search_iter (model, selection,
11233                                  &iter, text,
11234                                  &count, *selected_iter);
11235     }
11236 }
11237
11238 static gboolean
11239 gtk_tree_view_search_equal_func (GtkTreeModel *model,
11240                                  gint          column,
11241                                  const gchar  *key,
11242                                  GtkTreeIter  *iter,
11243                                  gpointer      search_data)
11244 {
11245   gboolean retval = TRUE;
11246   gchar *normalized_string;
11247   gchar *normalized_key;
11248   gchar *case_normalized_string;
11249   gchar *case_normalized_key;
11250   GValue value = {0,};
11251   GValue transformed = {0,};
11252   gint key_len;
11253
11254   gtk_tree_model_get_value (model, iter, column, &value);
11255
11256   g_value_init (&transformed, G_TYPE_STRING);
11257
11258   if (!g_value_transform (&value, &transformed))
11259     {
11260       g_value_unset (&value);
11261       return FALSE;
11262     }
11263
11264   g_value_unset (&value);
11265
11266   normalized_string = g_utf8_normalize (g_value_get_string (&transformed), -1, G_NORMALIZE_ALL);
11267   normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
11268   case_normalized_string = g_utf8_casefold (normalized_string, -1);
11269   case_normalized_key = g_utf8_casefold (normalized_key, -1);
11270
11271   key_len = strlen (case_normalized_key);
11272
11273   if (!strncmp (case_normalized_key, case_normalized_string, key_len))
11274     retval = FALSE;
11275
11276   g_value_unset (&transformed);
11277   g_free (normalized_key);
11278   g_free (normalized_string);
11279   g_free (case_normalized_key);
11280   g_free (case_normalized_string);
11281
11282   return retval;
11283 }
11284
11285 static gboolean
11286 gtk_tree_view_search_iter (GtkTreeModel     *model,
11287                            GtkTreeSelection *selection,
11288                            GtkTreeIter      *iter,
11289                            const gchar      *text,
11290                            gint             *count,
11291                            gint              n)
11292 {
11293   GtkRBTree *tree = NULL;
11294   GtkRBNode *node = NULL;
11295   GtkTreePath *path;
11296
11297   GtkTreeView *tree_view = gtk_tree_selection_get_tree_view (selection);
11298
11299   path = gtk_tree_model_get_path (model, iter);
11300   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
11301
11302   do
11303     {
11304       if (! tree_view->priv->search_equal_func (model, tree_view->priv->search_column, text, iter, tree_view->priv->search_user_data))
11305         {
11306           (*count)++;
11307           if (*count == n)
11308             {
11309               gtk_tree_view_scroll_to_cell (tree_view, path, NULL,
11310                                             TRUE, 0.5, 0.0);
11311               gtk_tree_selection_select_iter (selection, iter);
11312               gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
11313
11314               if (path)
11315                 gtk_tree_path_free (path);
11316
11317               return TRUE;
11318             }
11319         }
11320
11321       if (node->children)
11322         {
11323           gboolean has_child;
11324           GtkTreeIter tmp;
11325
11326           tree = node->children;
11327           node = tree->root;
11328
11329           while (node->left != tree->nil)
11330             node = node->left;
11331
11332           tmp = *iter;
11333           has_child = gtk_tree_model_iter_children (model, iter, &tmp);
11334           gtk_tree_path_down (path);
11335
11336           /* sanity check */
11337           TREE_VIEW_INTERNAL_ASSERT (has_child, FALSE);
11338         }
11339       else
11340         {
11341           gboolean done = FALSE;
11342
11343           do
11344             {
11345               node = _gtk_rbtree_next (tree, node);
11346
11347               if (node)
11348                 {
11349                   gboolean has_next;
11350
11351                   has_next = gtk_tree_model_iter_next (model, iter);
11352
11353                   done = TRUE;
11354                   gtk_tree_path_next (path);
11355
11356                   /* sanity check */
11357                   TREE_VIEW_INTERNAL_ASSERT (has_next, FALSE);
11358                 }
11359               else
11360                 {
11361                   gboolean has_parent;
11362                   GtkTreeIter tmp_iter = *iter;
11363
11364                   node = tree->parent_node;
11365                   tree = tree->parent_tree;
11366
11367                   if (!tree)
11368                     {
11369                       if (path)
11370                         gtk_tree_path_free (path);
11371
11372                       /* we've run out of tree, done with this func */
11373                       return FALSE;
11374                     }
11375
11376                   has_parent = gtk_tree_model_iter_parent (model,
11377                                                            iter,
11378                                                            &tmp_iter);
11379                   gtk_tree_path_up (path);
11380
11381                   /* sanity check */
11382                   TREE_VIEW_INTERNAL_ASSERT (has_parent, FALSE);
11383                 }
11384             }
11385           while (!done);
11386         }
11387     }
11388   while (1);
11389
11390   return FALSE;
11391 }
11392
11393 static void
11394 gtk_tree_view_search_init (GtkWidget   *entry,
11395                            GtkTreeView *tree_view)
11396 {
11397   gint ret;
11398   gint *selected_iter;
11399   gint len;
11400   gint count = 0;
11401   const gchar *text;
11402   GtkWidget *window;
11403   GtkTreeIter iter;
11404   GtkTreeModel *model;
11405   GtkTreeSelection *selection;
11406
11407   g_return_if_fail (GTK_IS_ENTRY (entry));
11408   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
11409
11410   window = gtk_widget_get_parent (entry);
11411   text = gtk_entry_get_text (GTK_ENTRY (entry));
11412   len = strlen (text);
11413   model = gtk_tree_view_get_model (tree_view);
11414   selection = gtk_tree_view_get_selection (tree_view);
11415
11416   /* search */
11417   gtk_tree_selection_unselect_all (selection);
11418   selected_iter = g_object_get_data (G_OBJECT (window), "gtk-tree-view-selected-iter");
11419   if (selected_iter)
11420     g_free (selected_iter);
11421   g_object_set_data (G_OBJECT (window), "gtk-tree-view-selected-iter", NULL);
11422
11423   if (len < 1)
11424     return;
11425
11426   gtk_tree_model_get_iter_first (model, &iter);
11427
11428   ret = gtk_tree_view_search_iter (model, selection,
11429                                    &iter, text,
11430                                    &count, 1);
11431
11432   if (ret)
11433     {
11434       selected_iter = g_malloc (sizeof (int));
11435       *selected_iter = 1;
11436       g_object_set_data (G_OBJECT (window), "gtk-tree-view-selected-iter",
11437                          selected_iter);
11438     }
11439 }
11440
11441 static void
11442 gtk_tree_view_remove_widget (GtkCellEditable *cell_editable,
11443                              GtkTreeView     *tree_view)
11444 {
11445   if (tree_view->priv->edited_column == NULL)
11446     return;
11447
11448   _gtk_tree_view_column_stop_editing (tree_view->priv->edited_column);
11449   tree_view->priv->edited_column = NULL;
11450
11451   if (GTK_WIDGET_HAS_FOCUS (cell_editable))
11452     gtk_widget_grab_focus (GTK_WIDGET (tree_view));
11453
11454   gtk_container_remove (GTK_CONTAINER (tree_view),
11455                         GTK_WIDGET (cell_editable));
11456 }
11457
11458 static gboolean
11459 gtk_tree_view_start_editing (GtkTreeView *tree_view,
11460                              GtkTreePath *cursor_path)
11461 {
11462   GtkTreeIter iter;
11463   GdkRectangle background_area;
11464   GdkRectangle cell_area;
11465   GtkCellEditable *editable_widget = NULL;
11466   gchar *path_string;
11467   guint flags = 0; /* can be 0, as the flags are primarily for rendering */
11468   gint retval = FALSE;
11469   GtkRBTree *cursor_tree;
11470   GtkRBNode *cursor_node;
11471
11472   g_assert (tree_view->priv->focus_column);
11473
11474   if (! GTK_WIDGET_REALIZED (tree_view))
11475     return FALSE;
11476
11477   if (_gtk_tree_view_find_node (tree_view, cursor_path, &cursor_tree, &cursor_node) ||
11478       cursor_node == NULL)
11479     return FALSE;
11480
11481   path_string = gtk_tree_path_to_string (cursor_path);
11482   gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path);
11483
11484   validate_row (tree_view, cursor_tree, cursor_node, &iter, cursor_path);
11485
11486   gtk_tree_view_column_cell_set_cell_data (tree_view->priv->focus_column,
11487                                            tree_view->priv->model,
11488                                            &iter,
11489                                            GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT),
11490                                            cursor_node->children?TRUE:FALSE);
11491   gtk_tree_view_get_background_area (tree_view,
11492                                      cursor_path,
11493                                      tree_view->priv->focus_column,
11494                                      &background_area);
11495   gtk_tree_view_get_cell_area (tree_view,
11496                                cursor_path,
11497                                tree_view->priv->focus_column,
11498                                &cell_area);
11499
11500   if (gtk_tree_view_is_expander_column (tree_view, tree_view->priv->focus_column) && TREE_VIEW_DRAW_EXPANDERS (tree_view))
11501     {
11502       cell_area.x += tree_view->priv->expander_size;
11503       cell_area.width -= tree_view->priv->expander_size;
11504     }
11505
11506   if (_gtk_tree_view_column_cell_event (tree_view->priv->focus_column,
11507                                         &editable_widget,
11508                                         NULL,
11509                                         path_string,
11510                                         &background_area,
11511                                         &cell_area,
11512                                         flags))
11513     {
11514       retval = TRUE;
11515       if (editable_widget != NULL)
11516         {
11517           gint left, right;
11518           GdkRectangle area;
11519           GtkCellRenderer *cell;
11520
11521           area = cell_area;
11522           cell = _gtk_tree_view_column_get_edited_cell (tree_view->priv->focus_column);
11523           _gtk_tree_view_column_get_neighbor_sizes (tree_view->priv->focus_column, cell, &left, &right);
11524
11525           area.x += left;
11526           area.width -= right + left;
11527
11528           gtk_tree_view_real_start_editing (tree_view,
11529                                             tree_view->priv->focus_column,
11530                                             cursor_path,
11531                                             editable_widget,
11532                                             &area,
11533                                             NULL,
11534                                             flags);
11535         }
11536
11537     }
11538   g_free (path_string);
11539   return retval;
11540 }
11541
11542 static void
11543 gtk_tree_view_real_start_editing (GtkTreeView       *tree_view,
11544                                   GtkTreeViewColumn *column,
11545                                   GtkTreePath       *path,
11546                                   GtkCellEditable   *cell_editable,
11547                                   GdkRectangle      *cell_area,
11548                                   GdkEvent          *event,
11549                                   guint              flags)
11550 {
11551   gint pre_val = tree_view->priv->vadjustment->value;
11552
11553   tree_view->priv->edited_column = column;
11554   _gtk_tree_view_column_start_editing (column, GTK_CELL_EDITABLE (cell_editable));
11555
11556   gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
11557
11558   cell_area->y += pre_val - tree_view->priv->vadjustment->value;
11559
11560   GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
11561   gtk_tree_view_put (tree_view,
11562                      GTK_WIDGET (cell_editable),
11563                      cell_area->x, cell_area->y, cell_area->width, cell_area->height);
11564   gtk_cell_editable_start_editing (GTK_CELL_EDITABLE (cell_editable),
11565                                    (GdkEvent *)event);
11566   gtk_widget_grab_focus (GTK_WIDGET (cell_editable));
11567   g_signal_connect (cell_editable, "remove_widget",
11568                     G_CALLBACK (gtk_tree_view_remove_widget), tree_view);
11569 }
11570
11571 static void
11572 gtk_tree_view_stop_editing (GtkTreeView *tree_view,
11573                             gboolean     cancel_editing)
11574 {
11575   GtkTreeViewColumn *column;
11576
11577   if (tree_view->priv->edited_column == NULL)
11578     return;
11579
11580   /*
11581    * This is very evil. We need to do this, because
11582    * gtk_cell_editable_editing_done may trigger gtk_tree_view_row_changed
11583    * later on. If gtk_tree_view_row_changed notices
11584    * tree_view->priv->edited_column != NULL, it'll call
11585    * gtk_tree_view_stop_editing again. Bad things will happen then.
11586    *
11587    * Please read that again if you intend to modify anything here.
11588    */
11589
11590   column = tree_view->priv->edited_column;
11591   tree_view->priv->edited_column = NULL;
11592
11593   if (! cancel_editing)
11594     gtk_cell_editable_editing_done (column->editable_widget);
11595
11596   tree_view->priv->edited_column = column;
11597
11598   gtk_cell_editable_remove_widget (column->editable_widget);
11599 }