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