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