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