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