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