]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeview.c
move grab_focus to after handling the button presses in the TreeView to
[~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                                                         _("TreeView Model"),
528                                                         _("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                                                         _("Horizontal Adjustment"),
536                                                         _("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                                                         _("Vertical Adjustment"),
544                                                         _("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                                                          _("Visible"),
552                                                          _("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                                                          _("Headers Clickable"),
560                                                          _("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                                                         _("Expander Column"),
568                                                         _("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                                                          _("Reorderable"),
576                                                          _("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                                                          _("Rules Hint"),
584                                                          _("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                                                            _("Enable Search"),
592                                                            _("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                                                        _("Search Column"),
600                                                        _("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                                                            _("Fixed Height Mode"),
610                                                            _("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                                                              _("Expander Size"),
622                                                              _("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                                                              _("Vertical Separator Width"),
631                                                              _("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                                                              _("Horizontal Separator Width"),
640                                                              _("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                                                                  _("Allow Rules"),
649                                                                  _("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                                                                  _("Indent Expanders"),
656                                                                  _("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                                                                _("Even Row Color"),
663                                                                _("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                                                                _("Odd Row Color"),
670                                                                _("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     while (do_expand_collapse (tree_view));
6895   tree_view->priv->expand_collapse_timeout = 0;
6896 }
6897
6898 static void
6899 gtk_tree_view_rows_reordered (GtkTreeModel *model,
6900                               GtkTreePath  *parent,
6901                               GtkTreeIter  *iter,
6902                               gint         *new_order,
6903                               gpointer      data)
6904 {
6905   GtkTreeView *tree_view = GTK_TREE_VIEW (data);
6906   GtkRBTree *tree;
6907   GtkRBNode *node;
6908   gint len;
6909
6910   len = gtk_tree_model_iter_n_children (model, iter);
6911
6912   if (len < 2)
6913     return;
6914
6915   gtk_tree_row_reference_reordered (G_OBJECT (data),
6916                                     parent,
6917                                     iter,
6918                                     new_order);
6919
6920   if (_gtk_tree_view_find_node (tree_view,
6921                                 parent,
6922                                 &tree,
6923                                 &node))
6924     return;
6925
6926   /* We need to special case the parent path */
6927   if (tree == NULL)
6928     tree = tree_view->priv->tree;
6929   else
6930     tree = node->children;
6931
6932   if (tree == NULL)
6933     return;
6934
6935   if (tree_view->priv->edited_column)
6936     gtk_tree_view_stop_editing (tree_view, TRUE);
6937
6938   /* we need to be unprelighted */
6939   ensure_unprelighted (tree_view);
6940
6941   /* clear the timeout */
6942   cancel_arrow_animation (tree_view);
6943   
6944   _gtk_rbtree_reorder (tree, new_order, len);
6945
6946   gtk_widget_queue_draw (GTK_WIDGET (tree_view));
6947
6948   gtk_tree_view_dy_to_top_row (tree_view);
6949 }
6950
6951
6952 /* Internal tree functions
6953  */
6954
6955
6956 static void
6957 gtk_tree_view_get_background_xrange (GtkTreeView       *tree_view,
6958                                      GtkRBTree         *tree,
6959                                      GtkTreeViewColumn *column,
6960                                      gint              *x1,
6961                                      gint              *x2)
6962 {
6963   GtkTreeViewColumn *tmp_column = NULL;
6964   gint total_width;
6965   GList *list;
6966   gboolean rtl;
6967
6968   if (x1)
6969     *x1 = 0;
6970
6971   if (x2)
6972     *x2 = 0;
6973
6974   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
6975
6976   total_width = 0;
6977   for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
6978        list;
6979        list = (rtl ? list->prev : list->next))
6980     {
6981       tmp_column = list->data;
6982
6983       if (tmp_column == column)
6984         break;
6985
6986       if (tmp_column->visible)
6987         total_width += tmp_column->width;
6988     }
6989
6990   if (tmp_column != column)
6991     {
6992       g_warning (G_STRLOC": passed-in column isn't in the tree");
6993       return;
6994     }
6995
6996   if (x1)
6997     *x1 = total_width;
6998
6999   if (x2)
7000     {
7001       if (column->visible)
7002         *x2 = total_width + column->width;
7003       else
7004         *x2 = total_width; /* width of 0 */
7005     }
7006 }
7007 static void
7008 gtk_tree_view_get_arrow_xrange (GtkTreeView *tree_view,
7009                                 GtkRBTree   *tree,
7010                                 gint        *x1,
7011                                 gint        *x2)
7012 {
7013   gint x_offset = 0;
7014   GList *list;
7015   GtkTreeViewColumn *tmp_column = NULL;
7016   gint total_width;
7017   gboolean indent_expanders;
7018   gboolean rtl;
7019
7020   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
7021
7022   total_width = 0;
7023   for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
7024        list;
7025        list = (rtl ? list->prev : list->next))
7026     {
7027       tmp_column = list->data;
7028
7029       if (gtk_tree_view_is_expander_column (tree_view, tmp_column))
7030         {
7031           if (rtl)
7032             x_offset = total_width + tmp_column->width - tree_view->priv->expander_size;
7033           else
7034             x_offset = total_width;
7035           break;
7036         }
7037
7038       if (tmp_column->visible)
7039         total_width += tmp_column->width;
7040     }
7041
7042   gtk_widget_style_get (GTK_WIDGET (tree_view),
7043                         "indent_expanders", &indent_expanders,
7044                         NULL);
7045
7046   if (indent_expanders)
7047     {
7048       if (rtl)
7049         x_offset -= tree_view->priv->expander_size * _gtk_rbtree_get_depth (tree);
7050       else
7051         x_offset += tree_view->priv->expander_size * _gtk_rbtree_get_depth (tree);
7052     }
7053   if (x1)
7054     {
7055       *x1 = x_offset;
7056     }
7057
7058   if (tmp_column && tmp_column->visible)
7059     {
7060       /* +1 because x2 isn't included in the range. */
7061       if (x2)
7062         *x2 = *x1 + tree_view->priv->expander_size + 1;
7063     }
7064   else
7065     {
7066       /* return an empty range, the expander column is hidden */
7067       if (x2)
7068         *x2 = *x1;
7069     }
7070 }
7071
7072 static void
7073 gtk_tree_view_build_tree (GtkTreeView *tree_view,
7074                           GtkRBTree   *tree,
7075                           GtkTreeIter *iter,
7076                           gint         depth,
7077                           gboolean     recurse)
7078 {
7079   GtkRBNode *temp = NULL;
7080   gboolean is_list = GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IS_LIST);
7081
7082   do
7083     {
7084       gtk_tree_model_ref_node (tree_view->priv->model, iter);
7085       temp = _gtk_rbtree_insert_after (tree, temp, 0, FALSE);
7086
7087       if (is_list)
7088         continue;
7089
7090       if (recurse)
7091         {
7092           GtkTreeIter child;
7093
7094           if (gtk_tree_model_iter_children (tree_view->priv->model, &child, iter))
7095             {
7096               temp->children = _gtk_rbtree_new ();
7097               temp->children->parent_tree = tree;
7098               temp->children->parent_node = temp;
7099               gtk_tree_view_build_tree (tree_view, temp->children, &child, depth + 1, recurse);
7100             }
7101         }
7102       if (gtk_tree_model_iter_has_child (tree_view->priv->model, iter))
7103         {
7104           if ((temp->flags&GTK_RBNODE_IS_PARENT) != GTK_RBNODE_IS_PARENT)
7105             temp->flags ^= GTK_RBNODE_IS_PARENT;
7106         }
7107     }
7108   while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
7109 }
7110
7111 /* If height is non-NULL, then we set it to be the new height.  if it's all
7112  * dirty, then height is -1.  We know we'll remeasure dirty rows, anyways.
7113  */
7114 static gboolean
7115 gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view,
7116                                    GtkTreeIter *iter,
7117                                    gint         depth,
7118                                    gint        *height,
7119                                    GtkRBNode   *node)
7120 {
7121   GtkTreeViewColumn *column;
7122   GList *list;
7123   gboolean retval = FALSE;
7124   gint tmpheight;
7125   gint horizontal_separator;
7126
7127   gtk_widget_style_get (GTK_WIDGET (tree_view),
7128                         "horizontal_separator", &horizontal_separator,
7129                         NULL);
7130
7131   if (height)
7132     *height = -1;
7133
7134   for (list = tree_view->priv->columns; list; list = list->next)
7135     {
7136       gint width;
7137       column = list->data;
7138       if (column->dirty == TRUE)
7139         continue;
7140       if (height == NULL && column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
7141         continue;
7142       if (!column->visible)
7143         continue;
7144
7145       gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, iter,
7146                                                GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
7147                                                node->children?TRUE:FALSE);
7148
7149       if (height)
7150         {
7151           gtk_tree_view_column_cell_get_size (column,
7152                                               NULL, NULL, NULL,
7153                                               &width, &tmpheight);
7154           *height = MAX (*height, tmpheight);
7155         }
7156       else
7157         {
7158           gtk_tree_view_column_cell_get_size (column,
7159                                               NULL, NULL, NULL,
7160                                               &width, NULL);
7161         }
7162
7163       if (gtk_tree_view_is_expander_column (tree_view, column) &&
7164           TREE_VIEW_DRAW_EXPANDERS (tree_view))
7165         {
7166           if (depth * tree_view->priv->expander_size + horizontal_separator + width > column->requested_width)
7167             {
7168               _gtk_tree_view_column_cell_set_dirty (column, TRUE);
7169               retval = TRUE;
7170             }
7171         }
7172       else
7173         {
7174           if (horizontal_separator + width > column->requested_width)
7175             {
7176               _gtk_tree_view_column_cell_set_dirty (column, TRUE);
7177               retval = TRUE;
7178             }
7179         }
7180     }
7181
7182   return retval;
7183 }
7184
7185 static void
7186 gtk_tree_view_discover_dirty (GtkTreeView *tree_view,
7187                               GtkRBTree   *tree,
7188                               GtkTreeIter *iter,
7189                               gint         depth)
7190 {
7191   GtkRBNode *temp = tree->root;
7192   GtkTreeViewColumn *column;
7193   GList *list;
7194   GtkTreeIter child;
7195   gboolean is_all_dirty;
7196
7197   TREE_VIEW_INTERNAL_ASSERT_VOID (tree != NULL);
7198
7199   while (temp->left != tree->nil)
7200     temp = temp->left;
7201
7202   do
7203     {
7204       TREE_VIEW_INTERNAL_ASSERT_VOID (temp != NULL);
7205       is_all_dirty = TRUE;
7206       for (list = tree_view->priv->columns; list; list = list->next)
7207         {
7208           column = list->data;
7209           if (column->dirty == FALSE)
7210             {
7211               is_all_dirty = FALSE;
7212               break;
7213             }
7214         }
7215
7216       if (is_all_dirty)
7217         return;
7218
7219       gtk_tree_view_discover_dirty_iter (tree_view,
7220                                          iter,
7221                                          depth,
7222                                          NULL,
7223                                          temp);
7224       if (gtk_tree_model_iter_children (tree_view->priv->model, &child, iter) &&
7225           temp->children != NULL)
7226         gtk_tree_view_discover_dirty (tree_view, temp->children, &child, depth + 1);
7227       temp = _gtk_rbtree_next (tree, temp);
7228     }
7229   while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
7230 }
7231
7232
7233 /* Make sure the node is visible vertically */
7234 static void
7235 gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view,
7236                                   GtkRBTree   *tree,
7237                                   GtkRBNode   *node)
7238 {
7239   GtkTreePath *path = NULL;
7240
7241   if (!GTK_WIDGET_REALIZED (tree_view))
7242     return;
7243
7244   path = _gtk_tree_view_find_path (tree_view, tree, node);
7245
7246   if (path)
7247     {
7248       /* We process updates because we want to clear old selected items when we scroll.
7249        * if this is removed, we get a "selection streak" at the bottom. */
7250       gdk_window_process_updates (tree_view->priv->bin_window, TRUE);
7251       gtk_tree_view_scroll_to_cell (tree_view, path, NULL, FALSE, 0.0, 0.0);
7252       gtk_tree_path_free (path);
7253     }
7254 }
7255
7256 static void
7257 gtk_tree_view_clamp_column_visible (GtkTreeView       *tree_view,
7258                                     GtkTreeViewColumn *column)
7259 {
7260   if (column == NULL)
7261     return;
7262   if ((tree_view->priv->hadjustment->value + tree_view->priv->hadjustment->page_size) <
7263       (column->button->allocation.x + column->button->allocation.width))
7264     gtk_adjustment_set_value (tree_view->priv->hadjustment,
7265                               column->button->allocation.x + column->button->allocation.width -
7266                               tree_view->priv->hadjustment->page_size);
7267   else if (tree_view->priv->hadjustment->value > column->button->allocation.x)
7268     gtk_adjustment_set_value (tree_view->priv->hadjustment,
7269                               column->button->allocation.x);
7270 }
7271
7272 /* This function could be more efficient.  I'll optimize it if profiling seems
7273  * to imply that it is important */
7274 GtkTreePath *
7275 _gtk_tree_view_find_path (GtkTreeView *tree_view,
7276                           GtkRBTree   *tree,
7277                           GtkRBNode   *node)
7278 {
7279   GtkTreePath *path;
7280   GtkRBTree *tmp_tree;
7281   GtkRBNode *tmp_node, *last;
7282   gint count;
7283
7284   path = gtk_tree_path_new ();
7285
7286   g_return_val_if_fail (node != NULL, path);
7287   g_return_val_if_fail (node != tree->nil, path);
7288
7289   count = 1 + node->left->count;
7290
7291   last = node;
7292   tmp_node = node->parent;
7293   tmp_tree = tree;
7294   while (tmp_tree)
7295     {
7296       while (tmp_node != tmp_tree->nil)
7297         {
7298           if (tmp_node->right == last)
7299             count += 1 + tmp_node->left->count;
7300           last = tmp_node;
7301           tmp_node = tmp_node->parent;
7302         }
7303       gtk_tree_path_prepend_index (path, count - 1);
7304       last = tmp_tree->parent_node;
7305       tmp_tree = tmp_tree->parent_tree;
7306       if (last)
7307         {
7308           count = 1 + last->left->count;
7309           tmp_node = last->parent;
7310         }
7311     }
7312   return path;
7313 }
7314
7315 /* Returns TRUE if we ran out of tree before finding the path.  If the path is
7316  * invalid (ie. points to a node that's not in the tree), *tree and *node are
7317  * both set to NULL.
7318  */
7319 gboolean
7320 _gtk_tree_view_find_node (GtkTreeView  *tree_view,
7321                           GtkTreePath  *path,
7322                           GtkRBTree   **tree,
7323                           GtkRBNode   **node)
7324 {
7325   GtkRBNode *tmpnode = NULL;
7326   GtkRBTree *tmptree = tree_view->priv->tree;
7327   gint *indices = gtk_tree_path_get_indices (path);
7328   gint depth = gtk_tree_path_get_depth (path);
7329   gint i = 0;
7330
7331   *node = NULL;
7332   *tree = NULL;
7333
7334   if (depth == 0 || tmptree == NULL)
7335     return FALSE;
7336   do
7337     {
7338       tmpnode = _gtk_rbtree_find_count (tmptree, indices[i] + 1);
7339       ++i;
7340       if (tmpnode == NULL)
7341         {
7342           *tree = NULL;
7343           *node = NULL;
7344           return FALSE;
7345         }
7346       if (i >= depth)
7347         {
7348           *tree = tmptree;
7349           *node = tmpnode;
7350           return FALSE;
7351         }
7352       *tree = tmptree;
7353       *node = tmpnode;
7354       tmptree = tmpnode->children;
7355       if (tmptree == NULL)
7356         return TRUE;
7357     }
7358   while (1);
7359 }
7360
7361 static gboolean
7362 gtk_tree_view_is_expander_column (GtkTreeView       *tree_view,
7363                                   GtkTreeViewColumn *column)
7364 {
7365   GList *list;
7366
7367   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IS_LIST))
7368     return FALSE;
7369
7370   if (tree_view->priv->expander_column != NULL)
7371     {
7372       if (tree_view->priv->expander_column == column)
7373         return TRUE;
7374       return FALSE;
7375     }
7376   else
7377     {
7378       for (list = tree_view->priv->columns;
7379            list;
7380            list = list->next)
7381         if (((GtkTreeViewColumn *)list->data)->visible)
7382           break;
7383       if (list && list->data == column)
7384         return TRUE;
7385     }
7386   return FALSE;
7387 }
7388
7389 static void
7390 gtk_tree_view_add_move_binding (GtkBindingSet  *binding_set,
7391                                 guint           keyval,
7392                                 guint           modmask,
7393                                 GtkMovementStep step,
7394                                 gint            count)
7395 {
7396   
7397   gtk_binding_entry_add_signal (binding_set, keyval, modmask,
7398                                 "move_cursor", 2,
7399                                 G_TYPE_ENUM, step,
7400                                 G_TYPE_INT, count);
7401
7402   gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
7403                                 "move_cursor", 2,
7404                                 G_TYPE_ENUM, step,
7405                                 G_TYPE_INT, count);
7406
7407   if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
7408    return;
7409
7410   gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
7411                                 "move_cursor", 2,
7412                                 G_TYPE_ENUM, step,
7413                                 G_TYPE_INT, count);
7414
7415   gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK,
7416                                 "move_cursor", 2,
7417                                 G_TYPE_ENUM, step,
7418                                 G_TYPE_INT, count);
7419 }
7420
7421 static gint
7422 gtk_tree_view_unref_tree_helper (GtkTreeModel *model,
7423                                  GtkTreeIter  *iter,
7424                                  GtkRBTree    *tree,
7425                                  GtkRBNode    *node)
7426 {
7427   gint retval = FALSE;
7428   do
7429     {
7430       g_return_val_if_fail (node != NULL, FALSE);
7431
7432       if (node->children)
7433         {
7434           GtkTreeIter child;
7435           GtkRBTree *new_tree;
7436           GtkRBNode *new_node;
7437
7438           new_tree = node->children;
7439           new_node = new_tree->root;
7440
7441           while (new_node && new_node->left != new_tree->nil)
7442             new_node = new_node->left;
7443
7444           if (!gtk_tree_model_iter_children (model, &child, iter))
7445             return FALSE;
7446
7447           retval = retval || gtk_tree_view_unref_tree_helper (model, &child, new_tree, new_node);
7448         }
7449
7450       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
7451         retval = TRUE;
7452       gtk_tree_model_unref_node (model, iter);
7453       node = _gtk_rbtree_next (tree, node);
7454     }
7455   while (gtk_tree_model_iter_next (model, iter));
7456
7457   return retval;
7458 }
7459
7460 static gint
7461 gtk_tree_view_unref_and_check_selection_tree (GtkTreeView *tree_view,
7462                                               GtkRBTree   *tree)
7463 {
7464   GtkTreeIter iter;
7465   GtkTreePath *path;
7466   GtkRBNode *node;
7467   gint retval;
7468
7469   if (!tree)
7470     return FALSE;
7471
7472   node = tree->root;
7473   while (node && node->left != tree->nil)
7474     node = node->left;
7475
7476   g_return_val_if_fail (node != NULL, FALSE);
7477   path = _gtk_tree_view_find_path (tree_view, tree, node);
7478   gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_view->priv->model),
7479                            &iter, path);
7480   retval = gtk_tree_view_unref_tree_helper (GTK_TREE_MODEL (tree_view->priv->model), &iter, tree, node);
7481   gtk_tree_path_free (path);
7482
7483   return retval;
7484 }
7485
7486 static void
7487 gtk_tree_view_set_column_drag_info (GtkTreeView       *tree_view,
7488                                     GtkTreeViewColumn *column)
7489 {
7490   GtkTreeViewColumn *left_column;
7491   GtkTreeViewColumn *cur_column = NULL;
7492   GtkTreeViewColumnReorder *reorder;
7493   gboolean rtl;
7494   GList *tmp_list;
7495   gint left;
7496
7497   /* We want to precalculate the motion list such that we know what column slots
7498    * are available.
7499    */
7500   left_column = NULL;
7501   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
7502
7503   /* First, identify all possible drop spots */
7504   if (rtl)
7505     tmp_list = g_list_last (tree_view->priv->columns);
7506   else
7507     tmp_list = g_list_first (tree_view->priv->columns);
7508
7509   while (tmp_list)
7510     {
7511       cur_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
7512       tmp_list = rtl?g_list_previous (tmp_list):g_list_next (tmp_list);
7513
7514       if (cur_column->visible == FALSE)
7515         continue;
7516
7517       /* If it's not the column moving and func tells us to skip over the column, we continue. */
7518       if (left_column != column && cur_column != column &&
7519           tree_view->priv->column_drop_func &&
7520           ! (* tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
7521         {
7522           left_column = cur_column;
7523           continue;
7524         }
7525       reorder = g_new (GtkTreeViewColumnReorder, 1);
7526       reorder->left_column = left_column;
7527       left_column = reorder->right_column = cur_column;
7528
7529       tree_view->priv->column_drag_info = g_list_append (tree_view->priv->column_drag_info, reorder);
7530     }
7531
7532   /* Add the last one */
7533   if (tree_view->priv->column_drop_func == NULL ||
7534       ((left_column != column) &&
7535        (* tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data)))
7536     {
7537       reorder = g_new (GtkTreeViewColumnReorder, 1);
7538       reorder->left_column = left_column;
7539       reorder->right_column = NULL;
7540       tree_view->priv->column_drag_info = g_list_append (tree_view->priv->column_drag_info, reorder);
7541     }
7542
7543   /* We quickly check to see if it even makes sense to reorder columns. */
7544   /* If there is nothing that can be moved, then we return */
7545
7546   if (tree_view->priv->column_drag_info == NULL)
7547     return;
7548
7549   /* We know there are always 2 slots possbile, as you can always return column. */
7550   /* If that's all there is, return */
7551   if (tree_view->priv->column_drag_info->next->next == NULL &&
7552       ((GtkTreeViewColumnReorder *)tree_view->priv->column_drag_info->data)->right_column == column &&
7553       ((GtkTreeViewColumnReorder *)tree_view->priv->column_drag_info->next->data)->left_column == column)
7554     {
7555       for (tmp_list = tree_view->priv->column_drag_info; tmp_list; tmp_list = tmp_list->next)
7556         g_free (tmp_list->data);
7557       g_list_free (tree_view->priv->column_drag_info);
7558       tree_view->priv->column_drag_info = NULL;
7559       return;
7560     }
7561   /* We fill in the ranges for the columns, now that we've isolated them */
7562   left = - TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER (tree_view);
7563
7564   for (tmp_list = tree_view->priv->column_drag_info; tmp_list; tmp_list = tmp_list->next)
7565     {
7566       reorder = (GtkTreeViewColumnReorder *) tmp_list->data;
7567
7568       reorder->left_align = left;
7569       if (tmp_list->next != NULL)
7570         {
7571           g_assert (tmp_list->next->data);
7572           left = reorder->right_align = (reorder->right_column->button->allocation.x +
7573                                          reorder->right_column->button->allocation.width +
7574                                          ((GtkTreeViewColumnReorder *)tmp_list->next->data)->left_column->button->allocation.x)/2;
7575         }
7576       else
7577         {
7578           gint width;
7579
7580           gdk_drawable_get_size (tree_view->priv->header_window, &width, NULL);
7581           reorder->right_align = width + TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER (tree_view);
7582         }
7583     }
7584 }
7585
7586 void
7587 _gtk_tree_view_column_start_drag (GtkTreeView       *tree_view,
7588                                   GtkTreeViewColumn *column)
7589 {
7590   GdkEvent *send_event;
7591   GtkAllocation allocation;
7592   gint x, y, width, height;
7593   GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (tree_view));
7594   GdkDisplay *display = gdk_screen_get_display (screen);
7595
7596   g_return_if_fail (tree_view->priv->column_drag_info == NULL);
7597
7598   gtk_tree_view_set_column_drag_info (tree_view, column);
7599
7600   if (tree_view->priv->column_drag_info == NULL)
7601     return;
7602
7603   if (tree_view->priv->drag_window == NULL)
7604     {
7605       GdkWindowAttr attributes;
7606       guint attributes_mask;
7607
7608       attributes.window_type = GDK_WINDOW_CHILD;
7609       attributes.wclass = GDK_INPUT_OUTPUT;
7610       attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
7611       attributes.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
7612       attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
7613       attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
7614
7615       tree_view->priv->drag_window = gdk_window_new (tree_view->priv->bin_window,
7616                                                      &attributes,
7617                                                      attributes_mask);
7618       gdk_window_set_user_data (tree_view->priv->drag_window, GTK_WIDGET (tree_view));
7619     }
7620
7621   gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
7622   gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
7623
7624   gtk_grab_remove (column->button);
7625
7626   send_event = gdk_event_new (GDK_LEAVE_NOTIFY);
7627   send_event->crossing.send_event = TRUE;
7628   send_event->crossing.window = g_object_ref (column->button->window);
7629   send_event->crossing.subwindow = NULL;
7630   send_event->crossing.detail = GDK_NOTIFY_ANCESTOR;
7631   send_event->crossing.time = GDK_CURRENT_TIME;
7632
7633   gtk_propagate_event (column->button, send_event);
7634   gdk_event_free (send_event);
7635
7636   send_event = gdk_event_new (GDK_BUTTON_RELEASE);
7637   send_event->button.window = g_object_ref (gdk_screen_get_root_window (screen));
7638   send_event->button.send_event = TRUE;
7639   send_event->button.time = GDK_CURRENT_TIME;
7640   send_event->button.x = -1;
7641   send_event->button.y = -1;
7642   send_event->button.axes = NULL;
7643   send_event->button.state = 0;
7644   send_event->button.button = 1;
7645   send_event->button.device = gdk_display_get_core_pointer (display);
7646   send_event->button.x_root = 0;
7647   send_event->button.y_root = 0;
7648
7649   gtk_propagate_event (column->button, send_event);
7650   gdk_event_free (send_event);
7651
7652   gdk_window_move_resize (tree_view->priv->drag_window,
7653                           column->button->allocation.x,
7654                           0,
7655                           column->button->allocation.width,
7656                           column->button->allocation.height);
7657
7658   /* Kids, don't try this at home */
7659   g_object_ref (column->button);
7660   gtk_container_remove (GTK_CONTAINER (tree_view), column->button);
7661   gtk_widget_set_parent_window (column->button, tree_view->priv->drag_window);
7662   gtk_widget_set_parent (column->button, GTK_WIDGET (tree_view));
7663   g_object_unref (column->button);
7664
7665   tree_view->priv->drag_column_x = column->button->allocation.x;
7666   allocation = column->button->allocation;
7667   allocation.x = 0;
7668   gtk_widget_size_allocate (column->button, &allocation);
7669   gtk_widget_set_parent_window (column->button, tree_view->priv->drag_window);
7670
7671   tree_view->priv->drag_column = column;
7672   gdk_window_show (tree_view->priv->drag_window);
7673
7674   gdk_window_get_origin (tree_view->priv->header_window, &x, &y);
7675   gdk_drawable_get_size (tree_view->priv->header_window, &width, &height);
7676
7677   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
7678   while (gtk_events_pending ())
7679     gtk_main_iteration ();
7680
7681   GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG);
7682   gdk_pointer_grab (tree_view->priv->drag_window,
7683                     FALSE,
7684                     GDK_POINTER_MOTION_MASK|GDK_BUTTON_RELEASE_MASK,
7685                     NULL, NULL, GDK_CURRENT_TIME);
7686   gdk_keyboard_grab (tree_view->priv->drag_window,
7687                      FALSE,
7688                      GDK_CURRENT_TIME);
7689
7690 }
7691
7692 static void
7693 gtk_tree_view_queue_draw_arrow (GtkTreeView      *tree_view,
7694                                 GtkRBTree        *tree,
7695                                 GtkRBNode        *node,
7696                                 GdkRectangle     *clip_rect)
7697 {
7698   GdkRectangle rect;
7699
7700   if (!GTK_WIDGET_REALIZED (tree_view))
7701     return;
7702
7703   rect.x = 0;
7704   rect.width = MAX (tree_view->priv->expander_size, GTK_WIDGET (tree_view)->allocation.width);
7705
7706   rect.y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
7707   rect.height = MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size);
7708
7709   if (clip_rect)
7710     {
7711       GdkRectangle new_rect;
7712
7713       gdk_rectangle_intersect (clip_rect, &rect, &new_rect);
7714
7715       gdk_window_invalidate_rect (tree_view->priv->bin_window, &new_rect, TRUE);
7716     }
7717   else
7718     {
7719       gdk_window_invalidate_rect (tree_view->priv->bin_window, &rect, TRUE);
7720     }
7721 }
7722
7723 void
7724 _gtk_tree_view_queue_draw_node (GtkTreeView  *tree_view,
7725                                 GtkRBTree    *tree,
7726                                 GtkRBNode    *node,
7727                                 GdkRectangle *clip_rect)
7728 {
7729   GdkRectangle rect;
7730
7731   if (!GTK_WIDGET_REALIZED (tree_view))
7732     return;
7733
7734   rect.x = 0;
7735   rect.width = MAX (tree_view->priv->width, GTK_WIDGET (tree_view)->allocation.width);
7736
7737   rect.y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
7738   rect.height = MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size);
7739
7740   if (clip_rect)
7741     {
7742       GdkRectangle new_rect;
7743
7744       gdk_rectangle_intersect (clip_rect, &rect, &new_rect);
7745
7746       gdk_window_invalidate_rect (tree_view->priv->bin_window, &new_rect, TRUE);
7747     }
7748   else
7749     {
7750       gdk_window_invalidate_rect (tree_view->priv->bin_window, &rect, TRUE);
7751     }
7752 }
7753
7754 static void
7755 gtk_tree_view_queue_draw_path (GtkTreeView      *tree_view,
7756                                GtkTreePath      *path,
7757                                GdkRectangle     *clip_rect)
7758 {
7759   GtkRBTree *tree = NULL;
7760   GtkRBNode *node = NULL;
7761
7762   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
7763
7764   if (tree)
7765     _gtk_tree_view_queue_draw_node (tree_view, tree, node, clip_rect);
7766 }
7767
7768 /* x and y are the mouse position
7769  */
7770 static void
7771 gtk_tree_view_draw_arrow (GtkTreeView *tree_view,
7772                           GtkRBTree   *tree,
7773                           GtkRBNode   *node,
7774                           gint         x,
7775                           gint         y)
7776 {
7777   GdkRectangle area;
7778   GtkStateType state;
7779   GtkWidget *widget;
7780   gint x_offset = 0;
7781   gint vertical_separator;
7782   gint expander_size;
7783   GtkExpanderStyle expander_style;
7784
7785   gtk_widget_style_get (GTK_WIDGET (tree_view),
7786                         "vertical_separator", &vertical_separator,
7787                         NULL);
7788   expander_size = tree_view->priv->expander_size - EXPANDER_EXTRA_PADDING;
7789
7790   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
7791     return;
7792
7793   widget = GTK_WIDGET (tree_view);
7794
7795   gtk_tree_view_get_arrow_xrange (tree_view, tree, &x_offset, NULL);
7796
7797   area.x = x_offset;
7798   area.y = CELL_FIRST_PIXEL (tree_view, tree, node, vertical_separator);
7799   area.width = expander_size + 2;
7800   area.height = MAX (CELL_HEIGHT (node, vertical_separator), (expander_size - vertical_separator));
7801
7802   if (node == tree_view->priv->button_pressed_node)
7803     {
7804       if (x >= area.x && x <= (area.x + area.width) &&
7805           y >= area.y && y <= (area.y + area.height))
7806         state = GTK_STATE_ACTIVE;
7807       else
7808         state = GTK_STATE_NORMAL;
7809     }
7810   else
7811     {
7812       if (node == tree_view->priv->prelight_node &&
7813           GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
7814         state = GTK_STATE_PRELIGHT;
7815       else
7816         state = GTK_STATE_NORMAL;
7817     }
7818
7819   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SEMI_EXPANDED))
7820     expander_style = GTK_EXPANDER_SEMI_EXPANDED;
7821   else if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SEMI_COLLAPSED))
7822     expander_style = GTK_EXPANDER_SEMI_COLLAPSED;
7823   else if (node->children != NULL)
7824     expander_style = GTK_EXPANDER_EXPANDED;
7825   else
7826     expander_style = GTK_EXPANDER_COLLAPSED;
7827
7828   gtk_paint_expander (widget->style,
7829                       tree_view->priv->bin_window,
7830                       state,
7831                       &area,
7832                       widget,
7833                       "treeview",
7834                       area.x + area.width / 2,
7835                       area.y + area.height / 2,
7836                       expander_style);
7837 }
7838
7839 static void
7840 gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view)
7841
7842 {
7843   GtkTreePath *cursor_path;
7844
7845   if ((tree_view->priv->tree == NULL) ||
7846       (! GTK_WIDGET_REALIZED (tree_view)))
7847     return;
7848
7849   GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
7850
7851   cursor_path = NULL;
7852   if (tree_view->priv->cursor)
7853     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
7854
7855   if (cursor_path == NULL)
7856     {
7857       cursor_path = gtk_tree_path_new_first ();
7858       gtk_tree_row_reference_free (tree_view->priv->cursor);
7859       tree_view->priv->cursor = NULL;
7860
7861       if (tree_view->priv->selection->type == GTK_SELECTION_MULTIPLE)
7862         gtk_tree_view_real_set_cursor (tree_view, cursor_path, FALSE, FALSE);
7863       else
7864         gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE);
7865     }
7866   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
7867   gtk_tree_path_free (cursor_path);
7868
7869   if (tree_view->priv->focus_column == NULL)
7870     {
7871       GList *list;
7872       for (list = tree_view->priv->columns; list; list = list->next)
7873         {
7874           if (GTK_TREE_VIEW_COLUMN (list->data)->visible)
7875             {
7876               tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (list->data);
7877               break;
7878             }
7879         }
7880     }
7881 }
7882
7883 static void
7884 gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
7885                                    gint         count)
7886 {
7887   GtkRBTree *cursor_tree = NULL;
7888   GtkRBNode *cursor_node = NULL;
7889   GtkRBTree *new_cursor_tree = NULL;
7890   GtkRBNode *new_cursor_node = NULL;
7891   GtkTreePath *cursor_path = NULL;
7892
7893   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
7894     return;
7895
7896   cursor_path = NULL;
7897   if (!gtk_tree_row_reference_valid (tree_view->priv->cursor))
7898     /* FIXME: we lost the cursor; should we get the first? */
7899     return;
7900
7901   cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
7902   _gtk_tree_view_find_node (tree_view, cursor_path,
7903                             &cursor_tree, &cursor_node);
7904   gtk_tree_path_free (cursor_path);
7905
7906   if (cursor_tree == NULL)
7907     /* FIXME: we lost the cursor; should we get the first? */
7908     return;
7909   if (count == -1)
7910     _gtk_rbtree_prev_full (cursor_tree, cursor_node,
7911                            &new_cursor_tree, &new_cursor_node);
7912   else
7913     _gtk_rbtree_next_full (cursor_tree, cursor_node,
7914                            &new_cursor_tree, &new_cursor_node);
7915
7916   if (new_cursor_node)
7917     {
7918       cursor_path = _gtk_tree_view_find_path (tree_view, new_cursor_tree, new_cursor_node);
7919       gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE);
7920       gtk_tree_path_free (cursor_path);
7921     }
7922   else
7923     {
7924       gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
7925     }
7926
7927   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
7928 }
7929
7930 static void
7931 gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
7932                                         gint         count)
7933 {
7934   GtkRBTree *cursor_tree = NULL;
7935   GtkRBNode *cursor_node = NULL;
7936   GtkTreePath *cursor_path = NULL;
7937   gint y;
7938   gint vertical_separator;
7939
7940   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
7941     return;
7942
7943   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
7944     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
7945   else
7946     /* This is sorta weird.  Focus in should give us a cursor */
7947     return;
7948
7949   gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical_separator", &vertical_separator, NULL);
7950   _gtk_tree_view_find_node (tree_view, cursor_path,
7951                             &cursor_tree, &cursor_node);
7952
7953   gtk_tree_path_free (cursor_path);
7954
7955   if (cursor_tree == NULL)
7956     /* FIXME: we lost the cursor.  Should we try to get one? */
7957     return;
7958   g_return_if_fail (cursor_node != NULL);
7959
7960   y = _gtk_rbtree_node_find_offset (cursor_tree, cursor_node);
7961   y += count * tree_view->priv->vadjustment->page_size;
7962   if (count > 0)
7963     y -= MAX (GTK_RBNODE_GET_HEIGHT (cursor_node),
7964               tree_view->priv->expander_size);
7965   else if (count < 0)
7966     y += MAX (GTK_RBNODE_GET_HEIGHT (cursor_node),
7967               tree_view->priv->expander_size);
7968   y = CLAMP (y, (gint)tree_view->priv->vadjustment->lower,  (gint)tree_view->priv->vadjustment->upper - vertical_separator);
7969
7970   if (y > tree_view->priv->height)
7971     y = tree_view->priv->height - 1;
7972
7973   _gtk_rbtree_find_offset (tree_view->priv->tree, y, &cursor_tree, &cursor_node);
7974   cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
7975   g_return_if_fail (cursor_path != NULL);
7976   gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE);
7977   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
7978   gtk_tree_path_free (cursor_path);
7979 }
7980
7981 static void
7982 gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
7983                                       gint         count)
7984 {
7985   GtkRBTree *cursor_tree = NULL;
7986   GtkRBNode *cursor_node = NULL;
7987   GtkTreePath *cursor_path = NULL;
7988   GtkTreeViewColumn *column;
7989   GtkTreeIter iter;
7990   GList *list;
7991   gboolean found_column = FALSE;
7992   gboolean rtl;
7993
7994   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
7995
7996   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
7997     return;
7998
7999   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
8000     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
8001   else
8002     return;
8003
8004   _gtk_tree_view_find_node (tree_view, cursor_path, &cursor_tree, &cursor_node);
8005   if (cursor_tree == NULL)
8006     return;
8007   if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path) == FALSE)
8008     {
8009       gtk_tree_path_free (cursor_path);
8010       return;
8011     }
8012   gtk_tree_path_free (cursor_path);
8013
8014   list = tree_view->priv->columns;
8015   if (tree_view->priv->focus_column)
8016     {
8017       for (list = tree_view->priv->columns; list; list = list->next)
8018         {
8019           if (list->data == tree_view->priv->focus_column)
8020             break;
8021         }
8022     }
8023
8024   while (list)
8025     {
8026       column = list->data;
8027       if (column->visible == FALSE)
8028         goto loop_end;
8029
8030       gtk_tree_view_column_cell_set_cell_data (column,
8031                                                tree_view->priv->model,
8032                                                &iter,
8033                                                GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT),
8034                                                cursor_node->children?TRUE:FALSE);
8035       if (_gtk_tree_view_column_cell_focus (column, count,
8036                                             list->prev?TRUE:FALSE,
8037                                             list->next?TRUE:FALSE))
8038         {
8039           tree_view->priv->focus_column = column;
8040           found_column = TRUE;
8041           break;
8042         }
8043     loop_end:
8044       if (count == 1)
8045         list = rtl ? list->prev : list->next;
8046       else
8047         list = rtl ? list->next : list->prev;
8048     }
8049
8050   if (found_column)
8051     {
8052       if (!gtk_tree_view_has_special_cell (tree_view))
8053         _gtk_tree_view_queue_draw_node (tree_view,
8054                                         cursor_tree,
8055                                         cursor_node,
8056                                         NULL);
8057       g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
8058     }
8059   gtk_tree_view_clamp_column_visible (tree_view, tree_view->priv->focus_column);
8060 }
8061
8062 static void
8063 gtk_tree_view_move_cursor_start_end (GtkTreeView *tree_view,
8064                                      gint         count)
8065 {
8066   GtkRBTree *cursor_tree;
8067   GtkRBNode *cursor_node;
8068   GtkTreePath *path;
8069
8070   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
8071     return;
8072
8073   g_return_if_fail (tree_view->priv->tree != NULL);
8074
8075   if (count == -1)
8076     {
8077       cursor_tree = tree_view->priv->tree;
8078       cursor_node = cursor_tree->root;
8079       while (cursor_node && cursor_node->left != cursor_tree->nil)
8080         cursor_node = cursor_node->left;
8081     }
8082   else
8083     {
8084       cursor_tree = tree_view->priv->tree;
8085       cursor_node = cursor_tree->root;
8086       do
8087         {
8088           while (cursor_node && cursor_node->right != cursor_tree->nil)
8089             cursor_node = cursor_node->right;
8090           if (cursor_node->children == NULL)
8091             break;
8092
8093           cursor_tree = cursor_node->children;
8094           cursor_node = cursor_tree->root;
8095         }
8096       while (1);
8097     }
8098
8099   path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
8100   gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
8101   gtk_tree_path_free (path);
8102 }
8103
8104 static gboolean
8105 gtk_tree_view_real_select_all (GtkTreeView *tree_view)
8106 {
8107   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
8108     return FALSE;
8109
8110   if (tree_view->priv->selection->type != GTK_SELECTION_MULTIPLE)
8111     return FALSE;
8112
8113   gtk_tree_selection_select_all (tree_view->priv->selection);
8114
8115   return TRUE;
8116 }
8117
8118 static gboolean
8119 gtk_tree_view_real_unselect_all (GtkTreeView *tree_view)
8120 {
8121   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
8122     return FALSE;
8123
8124   if (tree_view->priv->selection->type != GTK_SELECTION_MULTIPLE)
8125     return FALSE;
8126
8127   gtk_tree_selection_unselect_all (tree_view->priv->selection);
8128
8129   return TRUE;
8130 }
8131
8132 static gboolean
8133 gtk_tree_view_real_select_cursor_row (GtkTreeView *tree_view,
8134                                       gboolean     start_editing)
8135 {
8136   GtkRBTree *cursor_tree = NULL;
8137   GtkRBNode *cursor_node = NULL;
8138   GtkTreePath *cursor_path = NULL;
8139   GtkTreeSelectMode mode = 0;
8140
8141   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
8142     return FALSE;
8143
8144   if (tree_view->priv->cursor)
8145     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
8146
8147   if (cursor_path == NULL)
8148     return FALSE;
8149
8150   _gtk_tree_view_find_node (tree_view, cursor_path,
8151                             &cursor_tree, &cursor_node);
8152
8153   if (cursor_tree == NULL)
8154     {
8155       gtk_tree_path_free (cursor_path);
8156       return FALSE;
8157     }
8158
8159   if (!tree_view->priv->shift_pressed && start_editing &&
8160       tree_view->priv->focus_column)
8161     {
8162       if (gtk_tree_view_start_editing (tree_view, cursor_path))
8163         {
8164           gtk_tree_path_free (cursor_path);
8165           return TRUE;
8166         }
8167     }
8168
8169   if (tree_view->priv->ctrl_pressed)
8170     mode |= GTK_TREE_SELECT_MODE_TOGGLE;
8171   if (tree_view->priv->shift_pressed)
8172     mode |= GTK_TREE_SELECT_MODE_EXTEND;
8173
8174   _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
8175                                             cursor_node,
8176                                             cursor_tree,
8177                                             cursor_path,
8178                                             mode,
8179                                             FALSE);
8180
8181   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
8182
8183   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
8184   _gtk_tree_view_queue_draw_node (tree_view, cursor_tree, cursor_node, NULL);
8185
8186   if (!tree_view->priv->shift_pressed)
8187     gtk_tree_view_row_activated (tree_view, cursor_path,
8188                                  tree_view->priv->focus_column);
8189     
8190   gtk_tree_path_free (cursor_path);
8191
8192   return TRUE;
8193 }
8194
8195 static gboolean
8196 gtk_tree_view_real_toggle_cursor_row (GtkTreeView *tree_view)
8197 {
8198   GtkRBTree *cursor_tree = NULL;
8199   GtkRBNode *cursor_node = NULL;
8200   GtkTreePath *cursor_path = NULL;
8201
8202   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
8203     return FALSE;
8204
8205   cursor_path = NULL;
8206   if (tree_view->priv->cursor)
8207     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
8208
8209   if (cursor_path == NULL)
8210     return FALSE;
8211
8212   _gtk_tree_view_find_node (tree_view, cursor_path,
8213                             &cursor_tree, &cursor_node);
8214   if (cursor_tree == NULL)
8215     {
8216       gtk_tree_path_free (cursor_path);
8217       return FALSE;
8218     }
8219
8220   _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
8221                                             cursor_node,
8222                                             cursor_tree,
8223                                             cursor_path,
8224                                             GTK_TREE_SELECT_MODE_TOGGLE,
8225                                             FALSE);
8226
8227   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
8228
8229   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
8230   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
8231   gtk_tree_path_free (cursor_path);
8232
8233   return TRUE;
8234 }
8235
8236 static gboolean
8237 gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView *tree_view,
8238                                                gboolean     logical,
8239                                                gboolean     expand,
8240                                                gboolean     open_all)
8241 {
8242   GtkTreePath *cursor_path = NULL;
8243   GtkRBTree *tree;
8244   GtkRBNode *node;
8245
8246   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
8247     return FALSE;
8248
8249   cursor_path = NULL;
8250   if (tree_view->priv->cursor)
8251     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
8252
8253   if (cursor_path == NULL)
8254     return FALSE;
8255
8256   if (_gtk_tree_view_find_node (tree_view, cursor_path, &tree, &node))
8257     return FALSE;
8258   
8259   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
8260   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
8261
8262   if (!logical
8263       && gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL)
8264     expand = !expand;
8265
8266   if (expand)
8267     gtk_tree_view_real_expand_row (tree_view, cursor_path, tree, node, open_all, TRUE);
8268   else
8269     gtk_tree_view_real_collapse_row (tree_view, cursor_path, tree, node, TRUE);
8270
8271   gtk_tree_path_free (cursor_path);
8272
8273   return TRUE;
8274 }
8275
8276 static gboolean
8277 gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
8278 {
8279   GtkRBTree *cursor_tree = NULL;
8280   GtkRBNode *cursor_node = NULL;
8281   GtkTreePath *cursor_path = NULL;
8282
8283   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
8284     return FALSE;
8285
8286   cursor_path = NULL;
8287   if (tree_view->priv->cursor)
8288     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
8289
8290   if (cursor_path == NULL)
8291     return FALSE;
8292
8293   _gtk_tree_view_find_node (tree_view, cursor_path,
8294                             &cursor_tree, &cursor_node);
8295   if (cursor_tree == NULL)
8296     {
8297       gtk_tree_path_free (cursor_path);
8298       return FALSE;
8299     }
8300
8301   if (cursor_tree->parent_node)
8302     {
8303       gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
8304       cursor_node = cursor_tree->parent_node;
8305       cursor_tree = cursor_tree->parent_tree;
8306
8307       gtk_tree_path_up (cursor_path);
8308       gtk_tree_row_reference_free (tree_view->priv->cursor);
8309       tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, cursor_path);
8310       _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
8311                                                 cursor_node,
8312                                                 cursor_tree,
8313                                                 cursor_path,
8314                                                 0,
8315                                                 FALSE);
8316     }
8317
8318   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
8319
8320   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
8321   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
8322   gtk_tree_path_free (cursor_path);
8323
8324   return TRUE;
8325 }
8326
8327 /* Cut and paste from gtkwindow.c */
8328 static void
8329 send_focus_change (GtkWidget *widget,
8330                    gboolean   in)
8331 {
8332   GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
8333
8334   g_object_ref (widget);
8335    
8336  if (in)
8337     GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
8338   else
8339     GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
8340
8341   fevent->focus_change.type = GDK_FOCUS_CHANGE;
8342   fevent->focus_change.window = g_object_ref (widget->window);
8343   fevent->focus_change.in = in;
8344   
8345   gtk_widget_event (widget, fevent);
8346   
8347   g_object_notify (G_OBJECT (widget), "has_focus");
8348
8349   g_object_unref (widget);
8350   gdk_event_free (fevent);
8351 }
8352
8353 static gboolean
8354 gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view)
8355 {
8356   GtkWidget *window;
8357   GtkWidget *entry;
8358   GtkWidget *search_dialog;
8359
8360   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
8361     return FALSE;
8362
8363   if (tree_view->priv->enable_search == FALSE ||
8364       tree_view->priv->search_column < 0)
8365     return FALSE;
8366
8367   search_dialog = g_object_get_data (G_OBJECT (tree_view),
8368                                      GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
8369   if (search_dialog)
8370     return FALSE;
8371
8372   /* set up window */
8373   window = gtk_window_new (GTK_WINDOW_POPUP);
8374   gtk_window_set_title (GTK_WINDOW (window), "search dialog");
8375   gtk_container_set_border_width (GTK_CONTAINER (window), 3);
8376   gtk_window_set_modal (GTK_WINDOW (window), TRUE);
8377   g_signal_connect (window, "delete_event",
8378                     G_CALLBACK (gtk_tree_view_search_delete_event),
8379                     tree_view);
8380   g_signal_connect (window, "key_press_event",
8381                     G_CALLBACK (gtk_tree_view_search_key_press_event),
8382                     tree_view);
8383   g_signal_connect (window, "button_press_event",
8384                     G_CALLBACK (gtk_tree_view_search_button_press_event),
8385                     tree_view);
8386
8387   /* add entry */
8388   entry = gtk_entry_new ();
8389   gtk_widget_show (entry);
8390   g_signal_connect (entry, "changed",
8391                     G_CALLBACK (gtk_tree_view_search_init),
8392                     tree_view);
8393   g_signal_connect (entry, "populate_popup",
8394                     G_CALLBACK (gtk_tree_view_search_disable_popdown),
8395                     tree_view);
8396   gtk_container_add (GTK_CONTAINER (window), entry);
8397
8398   /* done, show it */
8399   tree_view->priv->search_dialog_position_func (tree_view, window);
8400   gtk_widget_show_all (window);
8401   gtk_widget_grab_focus (entry);
8402
8403   /* send focus-in event */
8404   send_focus_change (entry, TRUE);
8405
8406   /* position window */
8407
8408   /* yes, we point to the entry's private text thing here, a bit evil */
8409   g_object_set_data (G_OBJECT (window), "gtk-tree-view-text",
8410                      (gchar *) gtk_entry_get_text (GTK_ENTRY (entry)));
8411   g_object_set_data (G_OBJECT (tree_view),
8412                      GTK_TREE_VIEW_SEARCH_DIALOG_KEY, window);
8413
8414   /* search first matching iter */
8415   gtk_tree_view_search_init (entry, tree_view);
8416
8417   return TRUE;
8418 }
8419
8420 /* this function returns the new width of the column being resized given
8421  * the column and x position of the cursor; the x cursor position is passed
8422  * in as a pointer and automagicly corrected if it's beyond min/max limits
8423  */
8424 static gint
8425 gtk_tree_view_new_column_width (GtkTreeView *tree_view,
8426                                 gint       i,
8427                                 gint      *x)
8428 {
8429   GtkTreeViewColumn *column;
8430   gint width;
8431   gboolean rtl;
8432
8433   /* first translate the x position from widget->window
8434    * to clist->clist_window
8435    */
8436   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
8437   column = g_list_nth (tree_view->priv->columns, i)->data;
8438   width = rtl ? (column->button->allocation.x + column->button->allocation.width - *x) : (*x - column->button->allocation.x);
8439  
8440   /* Clamp down the value */
8441   if (column->min_width == -1)
8442     width = MAX (column->button->requisition.width,
8443                  width);
8444   else
8445     width = MAX (column->min_width,
8446                  width);
8447   if (column->max_width != -1)
8448     width = MIN (width, column->max_width != -1);
8449
8450   *x = rtl ? (column->button->allocation.x + column->button->allocation.width - width) : (column->button->allocation.x + width);
8451  
8452   return width;
8453 }
8454
8455
8456 /* Callbacks */
8457 static void
8458 gtk_tree_view_adjustment_changed (GtkAdjustment *adjustment,
8459                                   GtkTreeView   *tree_view)
8460 {
8461   if (GTK_WIDGET_REALIZED (tree_view))
8462     {
8463       gint dy;
8464         
8465       gdk_window_move (tree_view->priv->bin_window,
8466                        - tree_view->priv->hadjustment->value,
8467                        TREE_VIEW_HEADER_HEIGHT (tree_view));
8468       gdk_window_move (tree_view->priv->header_window,
8469                        - tree_view->priv->hadjustment->value,
8470                        0);
8471       dy = tree_view->priv->dy - (int) tree_view->priv->vadjustment->value;
8472       if (dy && tree_view->priv->edited_column)
8473         gtk_tree_view_stop_editing (tree_view, TRUE);
8474       gdk_window_scroll (tree_view->priv->bin_window, 0, dy);
8475
8476       /* update our dy and top_row */
8477       tree_view->priv->dy = (int) tree_view->priv->vadjustment->value;
8478       gtk_tree_view_dy_to_top_row (tree_view);
8479     }
8480 }
8481
8482 \f
8483
8484 /* Public methods
8485  */
8486
8487 /**
8488  * gtk_tree_view_new:
8489  *
8490  * Creates a new #GtkTreeView widget.
8491  *
8492  * Return value: A newly created #GtkTreeView widget.
8493  **/
8494 GtkWidget *
8495 gtk_tree_view_new (void)
8496 {
8497   return g_object_new (GTK_TYPE_TREE_VIEW, NULL);
8498 }
8499
8500 /**
8501  * gtk_tree_view_new_with_model:
8502  * @model: the model.
8503  *
8504  * Creates a new #GtkTreeView widget with the model initialized to @model.
8505  *
8506  * Return value: A newly created #GtkTreeView widget.
8507  **/
8508 GtkWidget *
8509 gtk_tree_view_new_with_model (GtkTreeModel *model)
8510 {
8511   return g_object_new (GTK_TYPE_TREE_VIEW, "model", model, NULL);
8512 }
8513
8514 /* Public Accessors
8515  */
8516
8517 /**
8518  * gtk_tree_view_get_model:
8519  * @tree_view: a #GtkTreeView
8520  *
8521  * Returns the model the the #GtkTreeView is based on.  Returns %NULL if the
8522  * model is unset.
8523  *
8524  * Return value: A #GtkTreeModel, or %NULL if none is currently being used.
8525  **/
8526 GtkTreeModel *
8527 gtk_tree_view_get_model (GtkTreeView *tree_view)
8528 {
8529   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
8530
8531   return tree_view->priv->model;
8532 }
8533
8534 /**
8535  * gtk_tree_view_set_model:
8536  * @tree_view: A #GtkTreeNode.
8537  * @model: The model.
8538  *
8539  * Sets the model for a #GtkTreeView.  If the @tree_view already has a model
8540  * set, it will remove it before setting the new model.  If @model is %NULL, then
8541  * it will unset the old model.
8542  **/
8543 void
8544 gtk_tree_view_set_model (GtkTreeView  *tree_view,
8545                          GtkTreeModel *model)
8546 {
8547   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8548
8549   if (model == tree_view->priv->model)
8550     return;
8551
8552   if (tree_view->priv->model)
8553     {
8554       GList *tmplist = tree_view->priv->columns;
8555
8556       gtk_tree_view_unref_and_check_selection_tree (tree_view, tree_view->priv->tree);
8557
8558       g_signal_handlers_disconnect_by_func (tree_view->priv->model,
8559                                             gtk_tree_view_row_changed,
8560                                             tree_view);
8561       g_signal_handlers_disconnect_by_func (tree_view->priv->model,
8562                                             gtk_tree_view_row_inserted,
8563                                             tree_view);
8564       g_signal_handlers_disconnect_by_func (tree_view->priv->model,
8565                                             gtk_tree_view_row_has_child_toggled,
8566                                             tree_view);
8567       g_signal_handlers_disconnect_by_func (tree_view->priv->model,
8568                                             gtk_tree_view_row_deleted,
8569                                             tree_view);
8570       g_signal_handlers_disconnect_by_func (tree_view->priv->model,
8571                                             gtk_tree_view_rows_reordered,
8572                                             tree_view);
8573
8574       for (; tmplist; tmplist = tmplist->next)
8575         _gtk_tree_view_column_unset_model (tmplist->data,
8576                                            tree_view->priv->model);
8577
8578       if (tree_view->priv->tree)
8579         {
8580           _gtk_rbtree_free (tree_view->priv->tree);
8581           tree_view->priv->tree = NULL;
8582         }
8583
8584       tree_view->priv->prelight_node = NULL;
8585       tree_view->priv->prelight_tree = NULL;
8586       tree_view->priv->button_pressed_node = NULL;
8587       tree_view->priv->button_pressed_tree = NULL;
8588
8589       gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
8590       tree_view->priv->drag_dest_row = NULL;
8591       gtk_tree_row_reference_free (tree_view->priv->cursor);
8592       tree_view->priv->cursor = NULL;
8593       gtk_tree_row_reference_free (tree_view->priv->anchor);
8594       tree_view->priv->anchor = NULL;
8595       gtk_tree_row_reference_free (tree_view->priv->top_row);
8596       tree_view->priv->top_row = NULL;
8597       gtk_tree_row_reference_free (tree_view->priv->last_button_press);
8598       tree_view->priv->last_button_press = NULL;
8599       gtk_tree_row_reference_free (tree_view->priv->last_button_press_2);
8600       tree_view->priv->last_button_press_2 = NULL;
8601       gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
8602       tree_view->priv->scroll_to_path = NULL;
8603
8604       tree_view->priv->scroll_to_column = NULL;
8605
8606       g_object_unref (tree_view->priv->model);
8607
8608       tree_view->priv->search_column = -1;
8609       tree_view->priv->fixed_height_check = 0;
8610       tree_view->priv->fixed_height = -1;
8611       tree_view->priv->dy = tree_view->priv->top_row_dy = 0;
8612     }
8613
8614   tree_view->priv->model = model;
8615
8616
8617   if (tree_view->priv->model)
8618     {
8619       gint i;
8620       GtkTreePath *path;
8621       GtkTreeIter iter;
8622       GtkTreeModelFlags flags;
8623
8624       if (tree_view->priv->search_column == -1)
8625         {
8626           for (i = 0; i < gtk_tree_model_get_n_columns (model); i++)
8627             {
8628               GType type = gtk_tree_model_get_column_type (model, i);
8629
8630               if (g_value_type_transformable (type, G_TYPE_STRING))
8631                 {
8632                   tree_view->priv->search_column = i;
8633                   break;
8634                 }
8635             }
8636         }
8637
8638       g_object_ref (tree_view->priv->model);
8639       g_signal_connect (tree_view->priv->model,
8640                         "row_changed",
8641                         G_CALLBACK (gtk_tree_view_row_changed),
8642                         tree_view);
8643       g_signal_connect (tree_view->priv->model,
8644                         "row_inserted",
8645                         G_CALLBACK (gtk_tree_view_row_inserted),
8646                         tree_view);
8647       g_signal_connect (tree_view->priv->model,
8648                         "row_has_child_toggled",
8649                         G_CALLBACK (gtk_tree_view_row_has_child_toggled),
8650                         tree_view);
8651       g_signal_connect (tree_view->priv->model,
8652                         "row_deleted",
8653                         G_CALLBACK (gtk_tree_view_row_deleted),
8654                         tree_view);
8655       g_signal_connect (tree_view->priv->model,
8656                         "rows_reordered",
8657                         G_CALLBACK (gtk_tree_view_rows_reordered),
8658                         tree_view);
8659
8660       flags = gtk_tree_model_get_flags (tree_view->priv->model);
8661       if ((flags & GTK_TREE_MODEL_LIST_ONLY) == GTK_TREE_MODEL_LIST_ONLY)
8662         GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_IS_LIST);
8663       else
8664         GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IS_LIST);
8665
8666       path = gtk_tree_path_new_first ();
8667       if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, path))
8668         {
8669           tree_view->priv->tree = _gtk_rbtree_new ();
8670           gtk_tree_view_build_tree (tree_view, tree_view->priv->tree, &iter, 1, FALSE);
8671         }
8672       gtk_tree_path_free (path);
8673
8674       /*  FIXME: do I need to do this? gtk_tree_view_create_buttons (tree_view); */
8675       install_presize_handler (tree_view);
8676     }
8677
8678   g_object_notify (G_OBJECT (tree_view), "model");
8679
8680   if (GTK_WIDGET_REALIZED (tree_view))
8681     gtk_widget_queue_resize (GTK_WIDGET (tree_view));
8682 }
8683
8684 /**
8685  * gtk_tree_view_get_selection:
8686  * @tree_view: A #GtkTreeView.
8687  *
8688  * Gets the #GtkTreeSelection associated with @tree_view.
8689  *
8690  * Return value: A #GtkTreeSelection object.
8691  **/
8692 GtkTreeSelection *
8693 gtk_tree_view_get_selection (GtkTreeView *tree_view)
8694 {
8695   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
8696
8697   return tree_view->priv->selection;
8698 }
8699
8700 /**
8701  * gtk_tree_view_get_hadjustment:
8702  * @tree_view: A #GtkTreeView
8703  *
8704  * Gets the #GtkAdjustment currently being used for the horizontal aspect.
8705  *
8706  * Return value: A #GtkAdjustment object, or %NULL if none is currently being
8707  * used.
8708  **/
8709 GtkAdjustment *
8710 gtk_tree_view_get_hadjustment (GtkTreeView *tree_view)
8711 {
8712   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
8713
8714   if (tree_view->priv->hadjustment == NULL)
8715     gtk_tree_view_set_hadjustment (tree_view, NULL);
8716
8717   return tree_view->priv->hadjustment;
8718 }
8719
8720 /**
8721  * gtk_tree_view_set_hadjustment:
8722  * @tree_view: A #GtkTreeView
8723  * @adjustment: The #GtkAdjustment to set, or %NULL
8724  *
8725  * Sets the #GtkAdjustment for the current horizontal aspect.
8726  **/
8727 void
8728 gtk_tree_view_set_hadjustment (GtkTreeView   *tree_view,
8729                                GtkAdjustment *adjustment)
8730 {
8731   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8732
8733   gtk_tree_view_set_adjustments (tree_view,
8734                                  adjustment,
8735                                  tree_view->priv->vadjustment);
8736
8737   g_object_notify (G_OBJECT (tree_view), "hadjustment");
8738 }
8739
8740 /**
8741  * gtk_tree_view_get_vadjustment:
8742  * @tree_view: A #GtkTreeView
8743  *
8744  * Gets the #GtkAdjustment currently being used for the vertical aspect.
8745  *
8746  * Return value: A #GtkAdjustment object, or %NULL if none is currently being
8747  * used.
8748  **/
8749 GtkAdjustment *
8750 gtk_tree_view_get_vadjustment (GtkTreeView *tree_view)
8751 {
8752   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
8753
8754   if (tree_view->priv->vadjustment == NULL)
8755     gtk_tree_view_set_vadjustment (tree_view, NULL);
8756
8757   return tree_view->priv->vadjustment;
8758 }
8759
8760 /**
8761  * gtk_tree_view_set_vadjustment:
8762  * @tree_view: A #GtkTreeView
8763  * @adjustment: The #GtkAdjustment to set, or %NULL
8764  *
8765  * Sets the #GtkAdjustment for the current vertical aspect.
8766  **/
8767 void
8768 gtk_tree_view_set_vadjustment (GtkTreeView   *tree_view,
8769                                GtkAdjustment *adjustment)
8770 {
8771   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8772
8773   gtk_tree_view_set_adjustments (tree_view,
8774                                  tree_view->priv->hadjustment,
8775                                  adjustment);
8776
8777   g_object_notify (G_OBJECT (tree_view), "vadjustment");
8778 }
8779
8780 /* Column and header operations */
8781
8782 /**
8783  * gtk_tree_view_get_headers_visible:
8784  * @tree_view: A #GtkTreeView.
8785  *
8786  * Returns %TRUE if the headers on the @tree_view are visible.
8787  *
8788  * Return value: Whether the headers are visible or not.
8789  **/
8790 gboolean
8791 gtk_tree_view_get_headers_visible (GtkTreeView *tree_view)
8792 {
8793   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
8794
8795   return GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE);
8796 }
8797
8798 /**
8799  * gtk_tree_view_set_headers_visible:
8800  * @tree_view: A #GtkTreeView.
8801  * @headers_visible: %TRUE if the headers are visible
8802  *
8803  * Sets the the visibility state of the headers.
8804  **/
8805 void
8806 gtk_tree_view_set_headers_visible (GtkTreeView *tree_view,
8807                                    gboolean     headers_visible)
8808 {
8809   gint x, y;
8810   GList *list;
8811   GtkTreeViewColumn *column;
8812
8813   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8814
8815   headers_visible = !! headers_visible;
8816
8817   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE) == headers_visible)
8818     return;
8819
8820   if (headers_visible)
8821     GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE);
8822   else
8823     GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE);
8824
8825   if (GTK_WIDGET_REALIZED (tree_view))
8826     {
8827       gdk_window_get_position (tree_view->priv->bin_window, &x, &y);
8828       if (headers_visible)
8829         {
8830           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));
8831
8832           if (GTK_WIDGET_MAPPED (tree_view))
8833             gtk_tree_view_map_buttons (tree_view);
8834         }
8835       else
8836         {
8837           gdk_window_move_resize (tree_view->priv->bin_window, x, y, tree_view->priv->width, tree_view->priv->height);
8838
8839           for (list = tree_view->priv->columns; list; list = list->next)
8840             {
8841               column = list->data;
8842               gtk_widget_unmap (column->button);
8843             }
8844           gdk_window_hide (tree_view->priv->header_window);
8845         }
8846     }
8847
8848   tree_view->priv->vadjustment->page_size = GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
8849   tree_view->priv->vadjustment->page_increment = (GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view)) / 2;
8850   tree_view->priv->vadjustment->lower = 0;
8851   tree_view->priv->vadjustment->upper = tree_view->priv->height;
8852   gtk_adjustment_changed (tree_view->priv->vadjustment);
8853
8854   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
8855
8856   g_object_notify (G_OBJECT (tree_view), "headers_visible");
8857 }
8858
8859 /**
8860  * gtk_tree_view_columns_autosize:
8861  * @tree_view: A #GtkTreeView.
8862  *
8863  * Resizes all columns to their optimal width. Only works after the
8864  * treeview has been realized.
8865  **/
8866 void
8867 gtk_tree_view_columns_autosize (GtkTreeView *tree_view)
8868 {
8869   gboolean dirty = FALSE;
8870   GList *list;
8871   GtkTreeViewColumn *column;
8872
8873   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8874
8875   for (list = tree_view->priv->columns; list; list = list->next)
8876     {
8877       column = list->data;
8878       if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
8879         continue;
8880       _gtk_tree_view_column_cell_set_dirty (column, TRUE);
8881       dirty = TRUE;
8882     }
8883
8884   if (dirty)
8885     gtk_widget_queue_resize (GTK_WIDGET (tree_view));
8886 }
8887
8888 /**
8889  * gtk_tree_view_set_headers_clickable:
8890  * @tree_view: A #GtkTreeView.
8891  * @setting: %TRUE if the columns are clickable.
8892  *
8893  * Allow the column title buttons to be clicked.
8894  **/
8895 void
8896 gtk_tree_view_set_headers_clickable (GtkTreeView *tree_view,
8897                                      gboolean   setting)
8898 {
8899   GList *list;
8900
8901   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8902   g_return_if_fail (tree_view->priv->model != NULL);
8903
8904   for (list = tree_view->priv->columns; list; list = list->next)
8905     gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (list->data), setting);
8906
8907   g_object_notify (G_OBJECT (tree_view), "headers_clickable");
8908 }
8909
8910
8911 /**
8912  * gtk_tree_view_set_rules_hint
8913  * @tree_view: a #GtkTreeView
8914  * @setting: %TRUE if the tree requires reading across rows
8915  *
8916  * This function tells GTK+ that the user interface for your
8917  * application requires users to read across tree rows and associate
8918  * cells with one another. By default, GTK+ will then render the tree
8919  * with alternating row colors. Do <emphasis>not</emphasis> use it
8920  * just because you prefer the appearance of the ruled tree; that's a
8921  * question for the theme. Some themes will draw tree rows in
8922  * alternating colors even when rules are turned off, and users who
8923  * prefer that appearance all the time can choose those themes. You
8924  * should call this function only as a <emphasis>semantic</emphasis>
8925  * hint to the theme engine that your tree makes alternating colors
8926  * useful from a functional standpoint (since it has lots of columns,
8927  * generally).
8928  *
8929  **/
8930 void
8931 gtk_tree_view_set_rules_hint (GtkTreeView  *tree_view,
8932                               gboolean      setting)
8933 {
8934   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8935
8936   setting = setting != FALSE;
8937
8938   if (tree_view->priv->has_rules != setting)
8939     {
8940       tree_view->priv->has_rules = setting;
8941       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
8942     }
8943
8944   g_object_notify (G_OBJECT (tree_view), "rules_hint");
8945 }
8946
8947 /**
8948  * gtk_tree_view_get_rules_hint
8949  * @tree_view: a #GtkTreeView
8950  *
8951  * Gets the setting set by gtk_tree_view_set_rules_hint().
8952  *
8953  * Return value: %TRUE if rules are useful for the user of this tree
8954  **/
8955 gboolean
8956 gtk_tree_view_get_rules_hint (GtkTreeView  *tree_view)
8957 {
8958   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
8959
8960   return tree_view->priv->has_rules;
8961 }
8962
8963 /* Public Column functions
8964  */
8965
8966 /**
8967  * gtk_tree_view_append_column:
8968  * @tree_view: A #GtkTreeView.
8969  * @column: The #GtkTreeViewColumn to add.
8970  *
8971  * Appends @column to the list of columns. If @tree_view has "fixed_height"
8972  * mode enbabled, then @column must have its "sizing" property set to be
8973  * GTK_TREE_VIEW_COLUMN_FIXED.
8974  *
8975  * Return value: The number of columns in @tree_view after appending.
8976  **/
8977 gint
8978 gtk_tree_view_append_column (GtkTreeView       *tree_view,
8979                              GtkTreeViewColumn *column)
8980 {
8981   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
8982   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
8983   g_return_val_if_fail (column->tree_view == NULL, -1);
8984
8985   return gtk_tree_view_insert_column (tree_view, column, -1);
8986 }
8987
8988
8989 /**
8990  * gtk_tree_view_remove_column:
8991  * @tree_view: A #GtkTreeView.
8992  * @column: The #GtkTreeViewColumn to remove.
8993  *
8994  * Removes @column from @tree_view.
8995  *
8996  * Return value: The number of columns in @tree_view after removing.
8997  **/
8998 gint
8999 gtk_tree_view_remove_column (GtkTreeView       *tree_view,
9000                              GtkTreeViewColumn *column)
9001 {
9002   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
9003   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
9004   g_return_val_if_fail (column->tree_view == GTK_WIDGET (tree_view), -1);
9005
9006   if (tree_view->priv->focus_column == column)
9007     tree_view->priv->focus_column = NULL;
9008
9009   if (tree_view->priv->edited_column == column)
9010     {
9011       gtk_tree_view_stop_editing (tree_view, TRUE);
9012
9013       /* no need to, but just to be sure ... */
9014       tree_view->priv->edited_column = NULL;
9015     }
9016
9017   g_signal_handlers_disconnect_by_func (column,
9018                                         G_CALLBACK (column_sizing_notify),
9019                                         tree_view);
9020
9021   _gtk_tree_view_column_unset_tree_view (column);
9022
9023   tree_view->priv->columns = g_list_remove (tree_view->priv->columns, column);
9024   tree_view->priv->n_columns--;
9025
9026   if (GTK_WIDGET_REALIZED (tree_view))
9027     {
9028       GList *list;
9029
9030       _gtk_tree_view_column_unrealize_button (column);
9031       for (list = tree_view->priv->columns; list; list = list->next)
9032         {
9033           GtkTreeViewColumn *tmp_column;
9034
9035           tmp_column = GTK_TREE_VIEW_COLUMN (list->data);
9036           if (tmp_column->visible)
9037             _gtk_tree_view_column_cell_set_dirty (tmp_column, TRUE);
9038         }
9039
9040       if (tree_view->priv->n_columns == 0 &&
9041           gtk_tree_view_get_headers_visible (tree_view))
9042         gdk_window_hide (tree_view->priv->header_window);
9043
9044       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
9045     }
9046
9047   g_object_unref (column);
9048   g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
9049
9050   return tree_view->priv->n_columns;
9051 }
9052
9053 /**
9054  * gtk_tree_view_insert_column:
9055  * @tree_view: A #GtkTreeView.
9056  * @column: The #GtkTreeViewColumn to be inserted.
9057  * @position: The position to insert @column in.
9058  *
9059  * This inserts the @column into the @tree_view at @position.  If @position is
9060  * -1, then the column is inserted at the end. If @tree_view has
9061  * "fixed_height" mode enabled, then @column must have its "sizing" property
9062  * set to be GTK_TREE_VIEW_COLUMN_FIXED.
9063  *
9064  * Return value: The number of columns in @tree_view after insertion.
9065  **/
9066 gint
9067 gtk_tree_view_insert_column (GtkTreeView       *tree_view,
9068                              GtkTreeViewColumn *column,
9069                              gint               position)
9070 {
9071   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
9072   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
9073   g_return_val_if_fail (column->tree_view == NULL, -1);
9074
9075   if (tree_view->priv->fixed_height_mode)
9076     g_return_val_if_fail (gtk_tree_view_column_get_sizing (column)
9077                           == GTK_TREE_VIEW_COLUMN_FIXED, -1);
9078
9079   g_object_ref (column);
9080   gtk_object_sink (GTK_OBJECT (column));
9081
9082   if (tree_view->priv->n_columns == 0 &&
9083       GTK_WIDGET_REALIZED (tree_view) &&
9084       gtk_tree_view_get_headers_visible (tree_view))
9085     {
9086       gdk_window_show (tree_view->priv->header_window);
9087     }
9088
9089   g_signal_connect (column, "notify::sizing",
9090                     G_CALLBACK (column_sizing_notify), tree_view);
9091
9092   tree_view->priv->columns = g_list_insert (tree_view->priv->columns,
9093                                             column, position);
9094   tree_view->priv->n_columns++;
9095
9096   _gtk_tree_view_column_set_tree_view (column, tree_view);
9097
9098   if (GTK_WIDGET_REALIZED (tree_view))
9099     {
9100       GList *list;
9101
9102       _gtk_tree_view_column_realize_button (column);
9103
9104       for (list = tree_view->priv->columns; list; list = list->next)
9105         {
9106           column = GTK_TREE_VIEW_COLUMN (list->data);
9107           if (column->visible)
9108             _gtk_tree_view_column_cell_set_dirty (column, TRUE);
9109         }
9110       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
9111     }
9112
9113   g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
9114
9115   return tree_view->priv->n_columns;
9116 }
9117
9118 /**
9119  * gtk_tree_view_insert_column_with_attributes:
9120  * @tree_view: A #GtkTreeView
9121  * @position: The position to insert the new column in.
9122  * @title: The title to set the header to.
9123  * @cell: The #GtkCellRenderer.
9124  * @Varargs: A %NULL-terminated list of attributes.
9125  *
9126  * Creates a new #GtkTreeViewColumn and inserts it into the @tree_view at
9127  * @position.  If @position is -1, then the newly created column is inserted at
9128  * the end.  The column is initialized with the attributes given. If @tree_view
9129  * has "fixed_height" mode enabled, then @column must have its sizing
9130  * property set to be GTK_TREE_VIEW_COLUMN_FIXED.
9131  *
9132  * Return value: The number of columns in @tree_view after insertion.
9133  **/
9134 gint
9135 gtk_tree_view_insert_column_with_attributes (GtkTreeView     *tree_view,
9136                                              gint             position,
9137                                              const gchar     *title,
9138                                              GtkCellRenderer *cell,
9139                                              ...)
9140 {
9141   GtkTreeViewColumn *column;
9142   gchar *attribute;
9143   va_list args;
9144   gint column_id;
9145
9146   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
9147
9148   column = gtk_tree_view_column_new ();
9149
9150   gtk_tree_view_column_set_title (column, title);
9151   gtk_tree_view_column_pack_start (column, cell, TRUE);
9152
9153   va_start (args, cell);
9154
9155   attribute = va_arg (args, gchar *);
9156
9157   while (attribute != NULL)
9158     {
9159       column_id = va_arg (args, gint);
9160       gtk_tree_view_column_add_attribute (column, cell, attribute, column_id);
9161       attribute = va_arg (args, gchar *);
9162     }
9163
9164   va_end (args);
9165
9166   gtk_tree_view_insert_column (tree_view, column, position);
9167
9168   return tree_view->priv->n_columns;
9169 }
9170
9171 /**
9172  * gtk_tree_view_insert_column_with_data_func:
9173  * @tree_view: a #GtkTreeView
9174  * @position: Position to insert, -1 for append
9175  * @title: column title
9176  * @cell: cell renderer for column
9177  * @func: function to set attributes of cell renderer
9178  * @data: data for @func
9179  * @dnotify: destroy notifier for @data
9180  *
9181  * Convenience function that inserts a new column into the #GtkTreeView
9182  * with the given cell renderer and a #GtkCellDataFunc to set cell renderer
9183  * attributes (normally using data from the model). See also
9184  * gtk_tree_view_column_set_cell_data_func(), gtk_tree_view_column_pack_start().
9185  * If @tree_view has "fixed_height" mode enabled, then @column must have its
9186  * "sizing" property set to be GTK_TREE_VIEW_COLUMN_FIXED.
9187  *
9188  * Return value: number of columns in the tree view post-insert
9189  **/
9190 gint
9191 gtk_tree_view_insert_column_with_data_func  (GtkTreeView               *tree_view,
9192                                              gint                       position,
9193                                              const gchar               *title,
9194                                              GtkCellRenderer           *cell,
9195                                              GtkTreeCellDataFunc        func,
9196                                              gpointer                   data,
9197                                              GDestroyNotify             dnotify)
9198 {
9199   GtkTreeViewColumn *column;
9200
9201   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
9202
9203   column = gtk_tree_view_column_new ();
9204
9205   gtk_tree_view_column_set_title (column, title);
9206   gtk_tree_view_column_pack_start (column, cell, TRUE);
9207   gtk_tree_view_column_set_cell_data_func (column, cell, func, data, dnotify);
9208
9209   gtk_tree_view_insert_column (tree_view, column, position);
9210
9211   return tree_view->priv->n_columns;
9212 }
9213
9214 /**
9215  * gtk_tree_view_get_column:
9216  * @tree_view: A #GtkTreeView.
9217  * @n: The position of the column, counting from 0.
9218  *
9219  * Gets the #GtkTreeViewColumn at the given position in the #tree_view.
9220  *
9221  * Return value: The #GtkTreeViewColumn, or %NULL if the position is outside the
9222  * range of columns.
9223  **/
9224 GtkTreeViewColumn *
9225 gtk_tree_view_get_column (GtkTreeView *tree_view,
9226                           gint         n)
9227 {
9228   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
9229
9230   if (n < 0 || n >= tree_view->priv->n_columns)
9231     return NULL;
9232
9233   if (tree_view->priv->columns == NULL)
9234     return NULL;
9235
9236   return GTK_TREE_VIEW_COLUMN (g_list_nth (tree_view->priv->columns, n)->data);
9237 }
9238
9239 /**
9240  * gtk_tree_view_get_columns:
9241  * @tree_view: A #GtkTreeView
9242  *
9243  * Returns a #GList of all the #GtkTreeViewColumn s currently in @tree_view.
9244  * The returned list must be freed with g_list_free ().
9245  *
9246  * Return value: A list of #GtkTreeViewColumn s
9247  **/
9248 GList *
9249 gtk_tree_view_get_columns (GtkTreeView *tree_view)
9250 {
9251   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
9252
9253   return g_list_copy (tree_view->priv->columns);
9254 }
9255
9256 /**
9257  * gtk_tree_view_move_column_after:
9258  * @tree_view: A #GtkTreeView
9259  * @column: The #GtkTreeViewColumn to be moved.
9260  * @base_column: The #GtkTreeViewColumn to be moved relative to, or %NULL.
9261  *
9262  * Moves @column to be after to @base_column.  If @base_column is %NULL, then
9263  * @column is placed in the first position.
9264  **/
9265 void
9266 gtk_tree_view_move_column_after (GtkTreeView       *tree_view,
9267                                  GtkTreeViewColumn *column,
9268                                  GtkTreeViewColumn *base_column)
9269 {
9270   GList *column_list_el, *base_el = NULL;
9271
9272   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
9273
9274   column_list_el = g_list_find (tree_view->priv->columns, column);
9275   g_return_if_fail (column_list_el != NULL);
9276
9277   if (base_column)
9278     {
9279       base_el = g_list_find (tree_view->priv->columns, base_column);
9280       g_return_if_fail (base_el != NULL);
9281     }
9282
9283   if (column_list_el->prev == base_el)
9284     return;
9285
9286   tree_view->priv->columns = g_list_remove_link (tree_view->priv->columns, column_list_el);
9287   if (base_el == NULL)
9288     {
9289       column_list_el->prev = NULL;
9290       column_list_el->next = tree_view->priv->columns;
9291       if (column_list_el->next)
9292         column_list_el->next->prev = column_list_el;
9293       tree_view->priv->columns = column_list_el;
9294     }
9295   else
9296     {
9297       column_list_el->prev = base_el;
9298       column_list_el->next = base_el->next;
9299       if (column_list_el->next)
9300         column_list_el->next->prev = column_list_el;
9301       base_el->next = column_list_el;
9302     }
9303
9304   if (GTK_WIDGET_REALIZED (tree_view))
9305     {
9306       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
9307       gtk_tree_view_size_allocate_columns (GTK_WIDGET (tree_view));
9308     }
9309
9310   g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
9311 }
9312
9313 /**
9314  * gtk_tree_view_set_expander_column:
9315  * @tree_view: A #GtkTreeView
9316  * @column: %NULL, or the column to draw the expander arrow at.
9317  *
9318  * Sets the column to draw the expander arrow at. It must be in @tree_view.  If
9319  * @column is %NULL, then the expander arrow is always at the first visible
9320  * column.
9321  **/
9322 void
9323 gtk_tree_view_set_expander_column (GtkTreeView       *tree_view,
9324                                    GtkTreeViewColumn *column)
9325 {
9326   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
9327   if (column != NULL)
9328     g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (column));
9329
9330   if (tree_view->priv->expander_column != column)
9331     {
9332       GList *list;
9333
9334       if (column)
9335         {
9336           /* Confirm that column is in tree_view */
9337           for (list = tree_view->priv->columns; list; list = list->next)
9338             if (list->data == column)
9339               break;
9340           g_return_if_fail (list != NULL);
9341         }
9342
9343       tree_view->priv->expander_column = column;
9344       g_object_notify (G_OBJECT (tree_view), "expander_column");
9345     }
9346 }
9347
9348 /**
9349  * gtk_tree_view_get_expander_column:
9350  * @tree_view: A #GtkTreeView
9351  *
9352  * Returns the column that is the current expander column.  This
9353  * column has the expander arrow drawn next to it.
9354  *
9355  * Return value: The expander column.
9356  **/
9357 GtkTreeViewColumn *
9358 gtk_tree_view_get_expander_column (GtkTreeView *tree_view)
9359 {
9360   GList *list;
9361
9362   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
9363
9364   for (list = tree_view->priv->columns; list; list = list->next)
9365     if (gtk_tree_view_is_expander_column (tree_view, GTK_TREE_VIEW_COLUMN (list->data)))
9366       return (GtkTreeViewColumn *) list->data;
9367   return NULL;
9368 }
9369
9370
9371 /**
9372  * gtk_tree_view_set_column_drag_function:
9373  * @tree_view: A #GtkTreeView.
9374  * @func: A function to determine which columns are reorderable, or %NULL.
9375  * @user_data: User data to be passed to @func, or %NULL
9376  * @destroy: Destroy notifier for @user_data, or %NULL
9377  *
9378  * Sets a user function for determining where a column may be dropped when
9379  * dragged.  This function is called on every column pair in turn at the
9380  * beginning of a column drag to determine where a drop can take place.  The
9381  * arguments passed to @func are: the @tree_view, the #GtkTreeViewColumn being
9382  * dragged, the two #GtkTreeViewColumn s determining the drop spot, and
9383  * @user_data.  If either of the #GtkTreeViewColumn arguments for the drop spot
9384  * are %NULL, then they indicate an edge.  If @func is set to be %NULL, then
9385  * @tree_view reverts to the default behavior of allowing all columns to be
9386  * dropped everywhere.
9387  **/
9388 void
9389 gtk_tree_view_set_column_drag_function (GtkTreeView               *tree_view,
9390                                         GtkTreeViewColumnDropFunc  func,
9391                                         gpointer                   user_data,
9392                                         GtkDestroyNotify           destroy)
9393 {
9394   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
9395
9396   if (tree_view->priv->column_drop_func_data_destroy)
9397     (* tree_view->priv->column_drop_func_data_destroy) (tree_view->priv->column_drop_func_data);
9398
9399   tree_view->priv->column_drop_func = func;
9400   tree_view->priv->column_drop_func_data = user_data;
9401   tree_view->priv->column_drop_func_data_destroy = destroy;
9402 }
9403
9404 /**
9405  * gtk_tree_view_scroll_to_point:
9406  * @tree_view: a #GtkTreeView
9407  * @tree_x: X coordinate of new top-left pixel of visible area, or -1
9408  * @tree_y: Y coordinate of new top-left pixel of visible area, or -1
9409  *
9410  * Scrolls the tree view such that the top-left corner of the visible
9411  * area is @tree_x, @tree_y, where @tree_x and @tree_y are specified
9412  * in tree window coordinates.  The @tree_view must be realized before
9413  * this function is called.  If it isn't, you probably want to be
9414  * using gtk_tree_view_scroll_to_cell().
9415  *
9416  * If either @tree_x or @tree_y are -1, then that direction isn't scrolled.
9417  **/
9418 void
9419 gtk_tree_view_scroll_to_point (GtkTreeView *tree_view,
9420                                gint         tree_x,
9421                                gint         tree_y)
9422 {
9423   GtkAdjustment *hadj;
9424   GtkAdjustment *vadj;
9425
9426   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
9427   g_return_if_fail (GTK_WIDGET_REALIZED (tree_view));
9428
9429   hadj = tree_view->priv->hadjustment;
9430   vadj = tree_view->priv->vadjustment;
9431
9432   if (tree_x != -1)
9433     gtk_adjustment_set_value (hadj, CLAMP (tree_x, hadj->lower, hadj->upper - hadj->page_size));
9434   if (tree_y != -1)
9435     gtk_adjustment_set_value (vadj, CLAMP (tree_y, vadj->lower, vadj->upper - vadj->page_size));
9436 }
9437
9438 /**
9439  * gtk_tree_view_scroll_to_cell
9440  * @tree_view: A #GtkTreeView.
9441  * @path: The path of the row to move to, or %NULL.
9442  * @column: The #GtkTreeViewColumn to move horizontally to, or %NULL.
9443  * @use_align: whether to use alignment arguments, or %FALSE.
9444  * @row_align: The vertical alignment of the row specified by @path.
9445  * @col_align: The horizontal alignment of the column specified by @column.
9446  *
9447  * Moves the alignments of @tree_view to the position specified by @column and
9448  * @path.  If @column is %NULL, then no horizontal scrolling occurs.  Likewise,
9449  * if @path is %NULL no vertical scrolling occurs.  At a minimum, one of @column
9450  * or @path need to be non-%NULL.  @row_align determines where the row is
9451  * placed, and @col_align determines where @column is placed.  Both are expected
9452  * to be between 0.0 and 1.0. 0.0 means left/top alignment, 1.0 means
9453  * right/bottom alignment, 0.5 means center.
9454  *
9455  * If @use_align is %FALSE, then the alignment arguments are ignored, and the
9456  * tree does the minimum amount of work to scroll the cell onto the screen.
9457  * This means that the cell will be scrolled to the edge closest to its current
9458  * position.  If the cell is currently visible on the screen, nothing is done.
9459  *
9460  * This function only works if the model is set, and @path is a valid row on the
9461  * model.  If the model changes before the @tree_view is realized, the centered
9462  * path will be modified to reflect this change.
9463  **/
9464 void
9465 gtk_tree_view_scroll_to_cell (GtkTreeView       *tree_view,
9466                               GtkTreePath       *path,
9467                               GtkTreeViewColumn *column,
9468                               gboolean           use_align,
9469                               gfloat             row_align,
9470                               gfloat             col_align)
9471 {
9472   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
9473   g_return_if_fail (tree_view->priv->model != NULL);
9474   g_return_if_fail (tree_view->priv->tree != NULL);
9475   g_return_if_fail (row_align >= 0.0 && row_align <= 1.0);
9476   g_return_if_fail (col_align >= 0.0 && col_align <= 1.0);
9477   g_return_if_fail (path != NULL || column != NULL);
9478
9479 #if 0
9480   g_print ("gtk_tree_view_scroll_to_cell:\npath: %s\ncolumn: %s\nuse_align: %d\nrow_align: %f\ncol_align: %f\n",
9481            gtk_tree_path_to_string (path), column?"non-null":"null", use_align, row_align, col_align);
9482 #endif
9483   row_align = CLAMP (row_align, 0.0, 1.0);
9484   col_align = CLAMP (col_align, 0.0, 1.0);
9485
9486
9487   /* Note: Despite the benefits that come from having one code path for the
9488    * scrolling code, we short-circuit validate_visible_area's immplementation as
9489    * it is much slower than just going to the point.
9490    */
9491   if (! GTK_WIDGET_REALIZED (tree_view) ||
9492       GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
9493     {
9494       if (tree_view->priv->scroll_to_path)
9495         gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
9496
9497       tree_view->priv->scroll_to_path = NULL;
9498       tree_view->priv->scroll_to_column = NULL;
9499
9500       if (path)
9501         tree_view->priv->scroll_to_path = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
9502       if (column)
9503         tree_view->priv->scroll_to_column = column;
9504       tree_view->priv->scroll_to_use_align = use_align;
9505       tree_view->priv->scroll_to_row_align = row_align;
9506       tree_view->priv->scroll_to_col_align = col_align;
9507
9508       install_presize_handler (tree_view);
9509     }
9510   else
9511     {
9512       GdkRectangle cell_rect;
9513       GdkRectangle vis_rect;
9514       gint dest_x, dest_y;
9515
9516       gtk_tree_view_get_cell_area (tree_view, path, column, &cell_rect);
9517       gtk_tree_view_widget_to_tree_coords (tree_view, cell_rect.x, cell_rect.y, &(cell_rect.x), &(cell_rect.y));
9518       gtk_tree_view_get_visible_rect (tree_view, &vis_rect);
9519
9520       dest_x = vis_rect.x;
9521       dest_y = vis_rect.y;
9522
9523       if (column)
9524         {
9525           if (use_align)
9526             {
9527               dest_x = cell_rect.x - ((vis_rect.width - cell_rect.width) * col_align);
9528             }
9529           else
9530             {
9531               if (cell_rect.x < vis_rect.x)
9532                 dest_x = cell_rect.x;
9533               if (cell_rect.x + cell_rect.width > vis_rect.x + vis_rect.width)
9534                 dest_x = cell_rect.x + cell_rect.width - vis_rect.width;
9535             }
9536         }
9537
9538       if (path)
9539         {
9540           if (use_align)
9541             {
9542               dest_y = cell_rect.y - ((vis_rect.height - cell_rect.height) * row_align);
9543               dest_y = MAX (dest_y, 0);
9544             }
9545           else
9546             {
9547               if (cell_rect.y < vis_rect.y)
9548                 dest_y = cell_rect.y;
9549               if (cell_rect.y + cell_rect.height > vis_rect.y + vis_rect.height)
9550                 dest_y = cell_rect.y + cell_rect.height - vis_rect.height;
9551             }
9552         }
9553
9554       gtk_tree_view_scroll_to_point (tree_view, dest_x, dest_y);
9555     }
9556 }
9557
9558 /**
9559  * gtk_tree_view_row_activated:
9560  * @tree_view: A #GtkTreeView
9561  * @path: The #GtkTreePath to be activated.
9562  * @column: The #GtkTreeViewColumn to be activated.
9563  *
9564  * Activates the cell determined by @path and @column.
9565  **/
9566 void
9567 gtk_tree_view_row_activated (GtkTreeView       *tree_view,
9568                              GtkTreePath       *path,
9569                              GtkTreeViewColumn *column)
9570 {
9571   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
9572
9573   g_signal_emit (tree_view, tree_view_signals[ROW_ACTIVATED], 0, path, column);
9574 }
9575
9576
9577 static void
9578 gtk_tree_view_expand_all_emission_helper (GtkRBTree *tree,
9579                                           GtkRBNode *node,
9580                                           gpointer   data)
9581 {
9582   GtkTreeView *tree_view = data;
9583
9584   if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT &&
9585       node->children)
9586     {
9587       GtkTreePath *path;
9588       GtkTreeIter iter;
9589
9590       path = _gtk_tree_view_find_path (tree_view, tree, node);
9591       gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
9592
9593       g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
9594
9595       gtk_tree_path_free (path);
9596     }
9597
9598   if (node->children)
9599     _gtk_rbtree_traverse (node->children,
9600                           node->children->root,
9601                           G_PRE_ORDER,
9602                           gtk_tree_view_expand_all_emission_helper,
9603                           tree_view);
9604 }
9605
9606 static void
9607 gtk_tree_view_expand_all_helper (GtkRBTree  *tree,
9608                                  GtkRBNode  *node,
9609                                  gpointer  data)
9610 {
9611   GtkTreeView *tree_view = data;
9612
9613   if (node->children)
9614     _gtk_rbtree_traverse (node->children,
9615                           node->children->root,
9616                           G_PRE_ORDER,
9617                           gtk_tree_view_expand_all_helper,
9618                           data);
9619   else if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT && node->children == NULL)
9620     {
9621       GtkTreePath *path;
9622       GtkTreeIter iter;
9623       GtkTreeIter child;
9624
9625       node->children = _gtk_rbtree_new ();
9626       node->children->parent_tree = tree;
9627       node->children->parent_node = node;
9628       path = _gtk_tree_view_find_path (tree_view, tree, node);
9629       gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
9630       gtk_tree_model_iter_children (tree_view->priv->model, &child, &iter);
9631       gtk_tree_view_build_tree (tree_view,
9632                                 node->children,
9633                                 &child,
9634                                 gtk_tree_path_get_depth (path) + 1,
9635                                 TRUE);
9636
9637       g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
9638       _gtk_rbtree_traverse (node->children,
9639                             node->children->root,
9640                             G_PRE_ORDER,
9641                             gtk_tree_view_expand_all_emission_helper,
9642                             tree_view);
9643       gtk_tree_path_free (path);
9644     }
9645 }
9646
9647 /**
9648  * gtk_tree_view_expand_all:
9649  * @tree_view: A #GtkTreeView.
9650  *
9651  * Recursively expands all nodes in the @tree_view.
9652  **/
9653 void
9654 gtk_tree_view_expand_all (GtkTreeView *tree_view)
9655 {
9656   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
9657
9658   if (tree_view->priv->tree == NULL)
9659     return;
9660
9661   _gtk_rbtree_traverse (tree_view->priv->tree,
9662                         tree_view->priv->tree->root,
9663                         G_PRE_ORDER,
9664                         gtk_tree_view_expand_all_helper,
9665                         tree_view);
9666 }
9667
9668 /* Timeout to animate the expander during expands and collapses */
9669 static gboolean
9670 expand_collapse_timeout (gpointer data)
9671 {
9672   gboolean retval;
9673
9674   GDK_THREADS_ENTER ();
9675
9676   retval = do_expand_collapse (data);
9677
9678   GDK_THREADS_LEAVE ();
9679
9680   return retval;
9681 }
9682
9683 static gboolean
9684 do_expand_collapse (GtkTreeView *tree_view)
9685 {
9686   GtkRBNode *node;
9687   GtkRBTree *tree;
9688   gboolean expanding;
9689   gboolean redraw;
9690
9691   redraw = FALSE;
9692   expanding = TRUE;
9693
9694   node = tree_view->priv->expanded_collapsed_node;
9695   tree = tree_view->priv->expanded_collapsed_tree;
9696
9697   if (node->children == NULL)
9698     expanding = FALSE;
9699
9700   if (expanding)
9701     {
9702       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SEMI_COLLAPSED))
9703         {
9704           GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_IS_SEMI_COLLAPSED);
9705           GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_EXPANDED);
9706
9707           redraw = TRUE;
9708
9709         }
9710       else if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SEMI_EXPANDED))
9711         {
9712           GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_IS_SEMI_EXPANDED);
9713
9714           redraw = TRUE;
9715         }
9716     }
9717   else
9718     {
9719       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SEMI_EXPANDED))
9720         {
9721           GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_IS_SEMI_EXPANDED);
9722           GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_COLLAPSED);
9723
9724           redraw = TRUE;
9725         }
9726       else if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SEMI_COLLAPSED))
9727         {
9728           GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_IS_SEMI_COLLAPSED);
9729
9730           redraw = TRUE;
9731
9732         }
9733     }
9734
9735   if (redraw)
9736     {
9737       gtk_tree_view_queue_draw_arrow (tree_view, tree, node, NULL);
9738
9739       return TRUE;
9740     }
9741
9742   return FALSE;
9743 }
9744
9745 /**
9746  * gtk_tree_view_collapse_all:
9747  * @tree_view: A #GtkTreeView.
9748  *
9749  * Recursively collapses all visible, expanded nodes in @tree_view.
9750  **/
9751 void
9752 gtk_tree_view_collapse_all (GtkTreeView *tree_view)
9753 {
9754   GtkRBTree *tree;
9755   GtkRBNode *node;
9756   GtkTreePath *path;
9757   gint *indices;
9758
9759   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
9760
9761   if (tree_view->priv->tree == NULL)
9762     return;
9763
9764   path = gtk_tree_path_new ();
9765   gtk_tree_path_down (path);
9766   indices = gtk_tree_path_get_indices (path);
9767
9768   tree = tree_view->priv->tree;
9769   node = tree->root;
9770   while (node && node->left != tree->nil)
9771     node = node->left;
9772
9773   while (node)
9774     {
9775       if (node->children)
9776         gtk_tree_view_real_collapse_row (tree_view, path, tree, node, FALSE);
9777       indices[0]++;
9778       node = _gtk_rbtree_next (tree, node);
9779     }
9780
9781   gtk_tree_path_free (path);
9782 }
9783
9784 /**
9785  * gtk_tree_view_expand_to_path:
9786  * @tree_view: A #GtkTreeView.
9787  * @path: path to a row.
9788  *
9789  * Expands the row at @path. This will also expand all parent rows of
9790  * @path as necessary.
9791  *
9792  * Since: 2.2
9793  **/
9794 void
9795 gtk_tree_view_expand_to_path (GtkTreeView *tree_view,
9796                               GtkTreePath *path)
9797 {
9798   gint i, depth;
9799   gint *indices;
9800   GtkTreePath *tmp;
9801
9802   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
9803   g_return_if_fail (path != NULL);
9804
9805   depth = gtk_tree_path_get_depth (path);
9806   indices = gtk_tree_path_get_indices (path);
9807
9808   tmp = gtk_tree_path_new ();
9809   g_return_if_fail (tmp != NULL);
9810
9811   for (i = 0; i < depth; i++)
9812     {
9813       gtk_tree_path_append_index (tmp, indices[i]);
9814       gtk_tree_view_expand_row (tree_view, tmp, FALSE);
9815     }
9816
9817   gtk_tree_path_free (tmp);
9818 }
9819
9820 /* FIXME the bool return values for expand_row and collapse_row are
9821  * not analagous; they should be TRUE if the row had children and
9822  * was not already in the requested state.
9823  */
9824
9825
9826 static gboolean
9827 gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
9828                                GtkTreePath *path,
9829                                GtkRBTree   *tree,
9830                                GtkRBNode   *node,
9831                                gboolean     open_all,
9832                                gboolean     animate)
9833 {
9834   GtkTreeIter iter;
9835   GtkTreeIter temp;
9836   gboolean expand;
9837
9838   if (node->children && !open_all)
9839     return FALSE;
9840
9841   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
9842     return FALSE;
9843
9844   gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
9845   if (! gtk_tree_model_iter_has_child (tree_view->priv->model, &iter))
9846     return FALSE;
9847
9848
9849    if (node->children && open_all)
9850     {
9851       gboolean retval = FALSE;
9852       GtkTreePath *tmp_path = gtk_tree_path_copy (path);
9853
9854       gtk_tree_path_append_index (tmp_path, 0);
9855       tree = node->children;
9856       node = tree->root;
9857       while (node->left != tree->nil)
9858         node = node->left;
9859       /* try to expand the children */
9860       do
9861         {
9862          gboolean t;
9863          t = gtk_tree_view_real_expand_row (tree_view, tmp_path, tree, node,
9864                                             TRUE, animate);
9865          if (t)
9866            retval = TRUE;
9867
9868          gtk_tree_path_next (tmp_path);
9869          node = _gtk_rbtree_next (tree, node);
9870        }
9871       while (node != NULL);
9872
9873       gtk_tree_path_free (tmp_path);
9874
9875       return retval;
9876     }
9877
9878   g_signal_emit (tree_view, tree_view_signals[TEST_EXPAND_ROW], 0, &iter, path, &expand);
9879
9880   if (expand)
9881     return FALSE;
9882
9883   node->children = _gtk_rbtree_new ();
9884   node->children->parent_tree = tree;
9885   node->children->parent_node = node;
9886
9887   gtk_tree_model_iter_children (tree_view->priv->model, &temp, &iter);
9888
9889   gtk_tree_view_build_tree (tree_view,
9890                             node->children,
9891                             &temp,
9892                             gtk_tree_path_get_depth (path) + 1,
9893                             open_all);
9894
9895   if (tree_view->priv->expand_collapse_timeout)
9896     {
9897       g_source_remove (tree_view->priv->expand_collapse_timeout);
9898       tree_view->priv->expand_collapse_timeout = 0;
9899     }
9900
9901   if (tree_view->priv->expanded_collapsed_node != NULL)
9902     {
9903       GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_EXPANDED);
9904       GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_COLLAPSED);
9905
9906       tree_view->priv->expanded_collapsed_node = NULL;
9907     }
9908
9909   if (animate)
9910     {
9911       tree_view->priv->expand_collapse_timeout = g_timeout_add (50, expand_collapse_timeout, tree_view);
9912       tree_view->priv->expanded_collapsed_node = node;
9913       tree_view->priv->expanded_collapsed_tree = tree;
9914
9915       GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_COLLAPSED);
9916     }
9917
9918   install_presize_handler (tree_view);
9919
9920   g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
9921   return TRUE;
9922 }
9923
9924
9925 /**
9926  * gtk_tree_view_expand_row:
9927  * @tree_view: a #GtkTreeView
9928  * @path: path to a row
9929  * @open_all: whether to recursively expand, or just expand immediate children
9930  *
9931  * Opens the row so its children are visible.
9932  *
9933  * Return value: %TRUE if the row existed and had children
9934  **/
9935 gboolean
9936 gtk_tree_view_expand_row (GtkTreeView *tree_view,
9937                           GtkTreePath *path,
9938                           gboolean     open_all)
9939 {
9940   GtkRBTree *tree;
9941   GtkRBNode *node;
9942
9943   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
9944   g_return_val_if_fail (tree_view->priv->model != NULL, FALSE);
9945   g_return_val_if_fail (path != NULL, FALSE);
9946
9947   if (_gtk_tree_view_find_node (tree_view,
9948                                 path,
9949                                 &tree,
9950                                 &node))
9951     return FALSE;
9952
9953   if (tree != NULL)
9954     return gtk_tree_view_real_expand_row (tree_view, path, tree, node, open_all, FALSE);
9955   else
9956     return FALSE;
9957 }
9958
9959 static gboolean
9960 gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
9961                                  GtkTreePath *path,
9962                                  GtkRBTree   *tree,
9963                                  GtkRBNode   *node,
9964                                  gboolean     animate)
9965 {
9966   GtkTreeIter iter;
9967   GtkTreeIter children;
9968   gboolean collapse;
9969   gint x, y;
9970   GList *list;
9971   GdkDisplay *display;
9972   GdkWindow *child, *parent;
9973
9974   if (node->children == NULL)
9975     return FALSE;
9976
9977   gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
9978
9979   g_signal_emit (tree_view, tree_view_signals[TEST_COLLAPSE_ROW], 0, &iter, path, &collapse);
9980
9981   if (collapse)
9982     return FALSE;
9983
9984   /* if the prelighted node is a child of us, we want to unprelight it.  We have
9985    * a chance to prelight the correct node below */
9986
9987   if (tree_view->priv->prelight_tree)
9988     {
9989       GtkRBTree *parent_tree;
9990       GtkRBNode *parent_node;
9991
9992       parent_tree = tree_view->priv->prelight_tree->parent_tree;
9993       parent_node = tree_view->priv->prelight_tree->parent_node;
9994       while (parent_tree)
9995         {
9996           if (parent_tree == tree && parent_node == node)
9997             {
9998               ensure_unprelighted (tree_view);
9999               break;
10000             }
10001           parent_node = parent_tree->parent_node;
10002           parent_tree = parent_tree->parent_tree;
10003         }
10004     }
10005
10006   TREE_VIEW_INTERNAL_ASSERT (gtk_tree_model_iter_children (tree_view->priv->model, &children, &iter), FALSE);
10007
10008   for (list = tree_view->priv->columns; list; list = list->next)
10009     {
10010       GtkTreeViewColumn *column = list->data;
10011
10012       if (column->visible == FALSE)
10013         continue;
10014       if (gtk_tree_view_column_get_sizing (column) == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
10015         _gtk_tree_view_column_cell_set_dirty (column, TRUE);
10016     }
10017
10018   if (tree_view->priv->destroy_count_func)
10019     {
10020       GtkTreePath *child_path;
10021       gint child_count = 0;
10022       child_path = gtk_tree_path_copy (path);
10023       gtk_tree_path_down (child_path);
10024       if (node->children)
10025         _gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, count_children_helper, &child_count);
10026       (* tree_view->priv->destroy_count_func) (tree_view, child_path, child_count, tree_view->priv->destroy_count_data);
10027       gtk_tree_path_free (child_path);
10028     }
10029
10030   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
10031     {
10032       GtkTreePath *cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
10033
10034       if (gtk_tree_path_is_ancestor (path, cursor_path))
10035         {
10036           gtk_tree_row_reference_free (tree_view->priv->cursor);
10037           tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
10038                                                                       tree_view->priv->model,
10039                                                                       path);
10040         }
10041       gtk_tree_path_free (cursor_path);
10042     }
10043
10044   if (gtk_tree_row_reference_valid (tree_view->priv->anchor))
10045     {
10046       GtkTreePath *anchor_path = gtk_tree_row_reference_get_path (tree_view->priv->anchor);
10047       if (gtk_tree_path_is_ancestor (path, anchor_path))
10048         {
10049           gtk_tree_row_reference_free (tree_view->priv->anchor);
10050           tree_view->priv->anchor = NULL;
10051         }
10052       gtk_tree_path_free (anchor_path);
10053     }
10054
10055   if (gtk_tree_row_reference_valid (tree_view->priv->last_button_press))
10056     {
10057       GtkTreePath *lsc = gtk_tree_row_reference_get_path (tree_view->priv->last_button_press);
10058       if (gtk_tree_path_is_ancestor (path, lsc))
10059         {
10060           gtk_tree_row_reference_free (tree_view->priv->last_button_press);
10061           tree_view->priv->last_button_press = NULL;
10062         }
10063       gtk_tree_path_free (lsc);
10064     }
10065
10066   if (gtk_tree_row_reference_valid (tree_view->priv->last_button_press_2))
10067     {
10068       GtkTreePath *lsc = gtk_tree_row_reference_get_path (tree_view->priv->last_button_press_2);
10069       if (gtk_tree_path_is_ancestor (path, lsc))
10070         {
10071           gtk_tree_row_reference_free (tree_view->priv->last_button_press_2);
10072           tree_view->priv->last_button_press_2 = NULL;
10073         }
10074       gtk_tree_path_free (lsc);
10075     }
10076
10077   if (gtk_tree_view_unref_and_check_selection_tree (tree_view, node->children))
10078     {
10079       _gtk_rbtree_remove (node->children);
10080       g_signal_emit_by_name (tree_view->priv->selection, "changed");
10081     }
10082   else
10083     _gtk_rbtree_remove (node->children);
10084
10085   if (tree_view->priv->expand_collapse_timeout)
10086     {
10087       g_source_remove (tree_view->priv->expand_collapse_timeout);
10088       tree_view->priv->expand_collapse_timeout = 0;
10089     }
10090   
10091   if (tree_view->priv->expanded_collapsed_node != NULL)
10092     {
10093       GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_EXPANDED);
10094       GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_COLLAPSED);
10095       
10096       tree_view->priv->expanded_collapsed_node = NULL;
10097     }
10098
10099   if (animate)
10100     {
10101       tree_view->priv->expand_collapse_timeout = g_timeout_add (50, expand_collapse_timeout, tree_view);
10102       tree_view->priv->expanded_collapsed_node = node;
10103       tree_view->priv->expanded_collapsed_tree = tree;
10104
10105       GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_EXPANDED);
10106     }
10107   
10108   if (GTK_WIDGET_MAPPED (tree_view))
10109     {
10110       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
10111     }
10112
10113   g_signal_emit (tree_view, tree_view_signals[ROW_COLLAPSED], 0, &iter, path);
10114
10115   if (GTK_WIDGET_MAPPED (tree_view))
10116     {
10117       /* now that we've collapsed all rows, we want to try to set the prelight
10118        * again. To do this, we fake a motion event and send it to ourselves. */
10119
10120       display = gdk_drawable_get_display (tree_view->priv->bin_window);
10121       child = tree_view->priv->bin_window;
10122       parent = gdk_window_get_parent (child);
10123
10124       if (gdk_window_get_pointer (parent, &x, &y, NULL) == child)
10125         {
10126           GdkEventMotion event;
10127           gint child_x, child_y;
10128
10129           gdk_window_get_position (child, &child_x, &child_y);
10130
10131           event.window = tree_view->priv->bin_window;
10132           event.x = x - child_x;
10133           event.y = y - child_y;
10134
10135           /* despite the fact this isn't a real event, I'm almost positive it will
10136            * never trigger a drag event.  maybe_drag is the only function that uses
10137            * more than just event.x and event.y. */
10138           gtk_tree_view_motion_bin_window (GTK_WIDGET (tree_view), &event);
10139         }
10140     }
10141
10142   return TRUE;
10143 }
10144
10145 /**
10146  * gtk_tree_view_collapse_row:
10147  * @tree_view: a #GtkTreeView
10148  * @path: path to a row in the @tree_view
10149  *
10150  * Collapses a row (hides its child rows, if they exist).
10151  *
10152  * Return value: %TRUE if the row was collapsed.
10153  **/
10154 gboolean
10155 gtk_tree_view_collapse_row (GtkTreeView *tree_view,
10156                             GtkTreePath *path)
10157 {
10158   GtkRBTree *tree;
10159   GtkRBNode *node;
10160
10161   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
10162   g_return_val_if_fail (tree_view->priv->tree != NULL, FALSE);
10163   g_return_val_if_fail (path != NULL, FALSE);
10164
10165   if (_gtk_tree_view_find_node (tree_view,
10166                                 path,
10167                                 &tree,
10168                                 &node))
10169     return FALSE;
10170
10171   if (tree == NULL || node->children == NULL)
10172     return FALSE;
10173
10174   return gtk_tree_view_real_collapse_row (tree_view, path, tree, node, FALSE);
10175 }
10176
10177 static void
10178 gtk_tree_view_map_expanded_rows_helper (GtkTreeView            *tree_view,
10179                                         GtkRBTree              *tree,
10180                                         GtkTreePath            *path,
10181                                         GtkTreeViewMappingFunc  func,
10182                                         gpointer                user_data)
10183 {
10184   GtkRBNode *node;
10185
10186   if (tree == NULL || tree->root == NULL)
10187     return;
10188
10189   node = tree->root;
10190
10191   while (node && node->left != tree->nil)
10192     node = node->left;
10193
10194   while (node)
10195     {
10196       if (node->children)
10197         {
10198           (* func) (tree_view, path, user_data);
10199           gtk_tree_path_down (path);
10200           gtk_tree_view_map_expanded_rows_helper (tree_view, node->children, path, func, user_data);
10201           gtk_tree_path_up (path);
10202         }
10203       gtk_tree_path_next (path);
10204       node = _gtk_rbtree_next (tree, node);
10205     }
10206 }
10207
10208 /**
10209  * gtk_tree_view_map_expanded_rows:
10210  * @tree_view: A #GtkTreeView
10211  * @func: A function to be called
10212  * @data: User data to be passed to the function.
10213  *
10214  * Calls @func on all expanded rows.
10215  **/
10216 void
10217 gtk_tree_view_map_expanded_rows (GtkTreeView            *tree_view,
10218                                  GtkTreeViewMappingFunc  func,
10219                                  gpointer                user_data)
10220 {
10221   GtkTreePath *path;
10222
10223   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10224   g_return_if_fail (func != NULL);
10225
10226   path = gtk_tree_path_new_first ();
10227
10228   gtk_tree_view_map_expanded_rows_helper (tree_view,
10229                                           tree_view->priv->tree,
10230                                           path, func, user_data);
10231
10232   gtk_tree_path_free (path);
10233 }
10234
10235 /**
10236  * gtk_tree_view_row_expanded:
10237  * @tree_view: A #GtkTreeView.
10238  * @path: A #GtkTreePath to test expansion state.
10239  *
10240  * Returns %TRUE if the node pointed to by @path is expanded in @tree_view.
10241  *
10242  * Return value: %TRUE if #path is expanded.
10243  **/
10244 gboolean
10245 gtk_tree_view_row_expanded (GtkTreeView *tree_view,
10246                             GtkTreePath *path)
10247 {
10248   GtkRBTree *tree;
10249   GtkRBNode *node;
10250
10251   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
10252   g_return_val_if_fail (path != NULL, FALSE);
10253
10254   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
10255
10256   if (node == NULL)
10257     return FALSE;
10258
10259   return (node->children != NULL);
10260 }
10261
10262 static const GtkTargetEntry row_targets[] = {
10263   { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, 0 }
10264 };
10265
10266
10267 /**
10268  * gtk_tree_view_get_reorderable:
10269  * @tree_view: a #GtkTreeView
10270  *
10271  * Retrieves whether the user can reorder the tree via drag-and-drop. See
10272  * gtk_tree_view_set_reorderable().
10273  *
10274  * Return value: %TRUE if the tree can be reordered.
10275  **/
10276 gboolean
10277 gtk_tree_view_get_reorderable (GtkTreeView *tree_view)
10278 {
10279   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
10280
10281   return tree_view->priv->reorderable;
10282 }
10283
10284 /**
10285  * gtk_tree_view_set_reorderable:
10286  * @tree_view: A #GtkTreeView.
10287  * @reorderable: %TRUE, if the tree can be reordered.
10288  *
10289  * This function is a convenience function to allow you to reorder models that
10290  * support the #GtkDragSourceIface and the #GtkDragDestIface.  Both
10291  * #GtkTreeStore and #GtkListStore support these.  If @reorderable is %TRUE, then
10292  * the user can reorder the model by dragging and dropping rows.  The
10293  * developer can listen to these changes by connecting to the model's
10294  * signals.
10295  *
10296  * This function does not give you any degree of control over the order -- any
10297  * reorderering is allowed.  If more control is needed, you should probably
10298  * handle drag and drop manually.
10299  **/
10300 void
10301 gtk_tree_view_set_reorderable (GtkTreeView *tree_view,
10302                                gboolean     reorderable)
10303 {
10304   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10305
10306   reorderable = reorderable != FALSE;
10307
10308   if (tree_view->priv->reorderable == reorderable)
10309     return;
10310
10311   if (reorderable)
10312     {
10313       gtk_tree_view_enable_model_drag_source (tree_view,
10314                                               GDK_BUTTON1_MASK,
10315                                               row_targets,
10316                                               G_N_ELEMENTS (row_targets),
10317                                               GDK_ACTION_MOVE);
10318       gtk_tree_view_enable_model_drag_dest (tree_view,
10319                                             row_targets,
10320                                             G_N_ELEMENTS (row_targets),
10321                                             GDK_ACTION_MOVE);
10322     }
10323   else
10324     {
10325       gtk_tree_view_unset_rows_drag_source (tree_view);
10326       gtk_tree_view_unset_rows_drag_dest (tree_view);
10327     }
10328
10329   tree_view->priv->reorderable = reorderable;
10330
10331   g_object_notify (G_OBJECT (tree_view), "reorderable");
10332 }
10333
10334 static void
10335 gtk_tree_view_real_set_cursor (GtkTreeView     *tree_view,
10336                                GtkTreePath     *path,
10337                                gboolean         clear_and_select,
10338                                gboolean         clamp_node)
10339 {
10340   GtkRBTree *tree = NULL;
10341   GtkRBNode *node = NULL;
10342
10343   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
10344     {
10345       GtkTreePath *cursor_path;
10346       cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
10347       gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
10348       gtk_tree_path_free (cursor_path);
10349     }
10350
10351   gtk_tree_row_reference_free (tree_view->priv->cursor);
10352
10353   tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
10354                                                               tree_view->priv->model,
10355                                                               path);
10356   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
10357   if (tree != NULL)
10358     {
10359       GtkRBTree *new_tree = NULL;
10360       GtkRBNode *new_node = NULL;
10361
10362       if (clear_and_select && !tree_view->priv->ctrl_pressed)
10363         {
10364           GtkTreeSelectMode mode = 0;
10365
10366           if (tree_view->priv->ctrl_pressed)
10367             mode |= GTK_TREE_SELECT_MODE_TOGGLE;
10368           if (tree_view->priv->shift_pressed)
10369             mode |= GTK_TREE_SELECT_MODE_EXTEND;
10370
10371           _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
10372                                                     node, tree, path, mode,
10373                                                     FALSE);
10374         }
10375
10376       /* We have to re-find tree and node here again, somebody might have
10377        * cleared the node or the whole tree in the GtkTreeSelection::changed
10378        * callback. If the nodes differ we bail out here.
10379        */
10380       _gtk_tree_view_find_node (tree_view, path, &new_tree, &new_node);
10381
10382       if (tree != new_tree || node != new_node)
10383         return;
10384
10385       if (clamp_node)
10386         {
10387           gtk_tree_view_clamp_node_visible (tree_view, tree, node);
10388           _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
10389         }
10390     }
10391
10392   g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
10393 }
10394
10395 /**
10396  * gtk_tree_view_get_cursor:
10397  * @tree_view: A #GtkTreeView
10398  * @path: A pointer to be filled with the current cursor path, or %NULL
10399  * @focus_column: A pointer to be filled with the current focus column, or %NULL
10400  *
10401  * Fills in @path and @focus_column with the current path and focus column.  If
10402  * the cursor isn't currently set, then *@path will be %NULL.  If no column
10403  * currently has focus, then *@focus_column will be %NULL.
10404  *
10405  * The returned #GtkTreePath must be freed with gtk_tree_path_free() when
10406  * you are done with it.
10407  **/
10408 void
10409 gtk_tree_view_get_cursor (GtkTreeView        *tree_view,
10410                           GtkTreePath       **path,
10411                           GtkTreeViewColumn **focus_column)
10412 {
10413   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10414
10415   if (path)
10416     {
10417       if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
10418         *path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
10419       else
10420         *path = NULL;
10421     }
10422
10423   if (focus_column)
10424     {
10425       *focus_column = tree_view->priv->focus_column;
10426     }
10427 }
10428
10429 /**
10430  * gtk_tree_view_set_cursor:
10431  * @tree_view: A #GtkTreeView
10432  * @path: A #GtkTreePath
10433  * @focus_column: A #GtkTreeViewColumn, or %NULL
10434  * @start_editing: %TRUE if the specified cell should start being edited.
10435  *
10436  * Sets the current keyboard focus to be at @path, and selects it.  This is
10437  * useful when you want to focus the user's attention on a particular row.  If
10438  * @focus_column is not %NULL, then focus is given to the column specified by 
10439  * it. Additionally, if @focus_column is specified, and @start_editing is 
10440  * %TRUE, then editing should be started in the specified cell.  
10441  * This function is often followed by @gtk_widget_grab_focus (@tree_view) 
10442  * in order to give keyboard focus to the widget.  Please note that editing 
10443  * can only happen when the widget is realized.
10444  **/
10445 void
10446 gtk_tree_view_set_cursor (GtkTreeView       *tree_view,
10447                           GtkTreePath       *path,
10448                           GtkTreeViewColumn *focus_column,
10449                           gboolean           start_editing)
10450 {
10451   gtk_tree_view_set_cursor_on_cell (tree_view, path, focus_column,
10452                                     NULL, start_editing);
10453 }
10454
10455 /**
10456  * gtk_tree_view_set_cursor_on_cell:
10457  * @tree_view: A #GtkTreeView
10458  * @path: A #GtkTreePath
10459  * @focus_column: A #GtkTreeViewColumn, or %NULL
10460  * @focus_cell: A #GtkCellRenderer, or %NULL
10461  * @start_editing: %TRUE if the specified cell should start being edited.
10462  *
10463  * Sets the current keyboard focus to be at @path, and selects it.  This is
10464  * useful when you want to focus the user's attention on a particular row.  If
10465  * @focus_column is not %NULL, then focus is given to the column specified by
10466  * it. If @focus_column and @focus_cell are not %NULL, and @focus_column
10467  * contains 2 or more editable or activatable cells, then focus is given to
10468  * the cell specified by @focus_cell. Additionally, if @focus_column is
10469  * specified, and @start_editing is %TRUE, then editing should be started in
10470  * the specified cell.  This function is often followed by
10471  * @gtk_widget_grab_focus (@tree_view) in order to give keyboard focus to the
10472  * widget.  Please note that editing can only happen when the widget is
10473  * realized.
10474  *
10475  * Since: 2.2
10476  **/
10477 void
10478 gtk_tree_view_set_cursor_on_cell (GtkTreeView       *tree_view,
10479                                   GtkTreePath       *path,
10480                                   GtkTreeViewColumn *focus_column,
10481                                   GtkCellRenderer   *focus_cell,
10482                                   gboolean           start_editing)
10483 {
10484   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10485   g_return_if_fail (path != NULL);
10486   if (focus_column)
10487     g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (focus_column));
10488   if (focus_cell)
10489     {
10490       g_return_if_fail (focus_column);
10491       g_return_if_fail (GTK_IS_CELL_RENDERER (focus_cell));
10492     }
10493
10494   /* cancel the current editing, if it exists */
10495   if (tree_view->priv->edited_column &&
10496       tree_view->priv->edited_column->editable_widget)
10497     gtk_tree_view_stop_editing (tree_view, TRUE);
10498
10499   gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
10500
10501   if (focus_column && focus_column->visible)
10502     {
10503       GList *list;
10504       gboolean column_in_tree = FALSE;
10505
10506       for (list = tree_view->priv->columns; list; list = list->next)
10507         if (list->data == focus_column)
10508           {
10509             column_in_tree = TRUE;
10510             break;
10511           }
10512       g_return_if_fail (column_in_tree);
10513       tree_view->priv->focus_column = focus_column;
10514       if (focus_cell)
10515         gtk_tree_view_column_focus_cell (focus_column, focus_cell);
10516       if (start_editing)
10517         gtk_tree_view_start_editing (tree_view, path);
10518     }
10519 }
10520
10521 /**
10522  * gtk_tree_view_get_bin_window:
10523  * @tree_view: A #GtkTreeView
10524  * 
10525  * Returns the window that @tree_view renders to.  This is used primarily to
10526  * compare to <literal>event->window</literal> to confirm that the event on
10527  * @tree_view is on the right window.
10528  * 
10529  * Return value: A #GdkWindow, or %NULL when @tree_view hasn't been realized yet
10530  **/
10531 GdkWindow *
10532 gtk_tree_view_get_bin_window (GtkTreeView *tree_view)
10533 {
10534   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
10535
10536   return tree_view->priv->bin_window;
10537 }
10538
10539 /**
10540  * gtk_tree_view_get_path_at_pos:
10541  * @tree_view: A #GtkTreeView.
10542  * @x: The x position to be identified.
10543  * @y: The y position to be identified.
10544  * @path: A pointer to a #GtkTreePath pointer to be filled in, or %NULL
10545  * @column: A pointer to a #GtkTreeViewColumn pointer to be filled in, or %NULL
10546  * @cell_x: A pointer where the X coordinate relative to the cell can be placed, or %NULL
10547  * @cell_y: A pointer where the Y coordinate relative to the cell can be placed, or %NULL
10548  *
10549  * Finds the path at the point (@x, @y), relative to widget coordinates.  That
10550  * is, @x and @y are relative to an events coordinates. @x and @y must come
10551  * from an event on the @tree_view only where event->window ==
10552  * gtk_tree_view_get_bin (). It is primarily for things like popup menus.
10553  * If @path is non-%NULL, then it will be filled with the #GtkTreePath at that
10554  * point.  This path should be freed with gtk_tree_path_free().  If @column
10555  * is non-%NULL, then it will be filled with the column at that point.
10556  * @cell_x and @cell_y return the coordinates relative to the cell background
10557  * (i.e. the @background_area passed to gtk_cell_renderer_render()).  This
10558  * function is only meaningful if @tree_view is realized.
10559  *
10560  * Return value: %TRUE if a row exists at that coordinate.
10561  **/
10562 gboolean
10563 gtk_tree_view_get_path_at_pos (GtkTreeView        *tree_view,
10564                                gint                x,
10565                                gint                y,
10566                                GtkTreePath       **path,
10567                                GtkTreeViewColumn **column,
10568                                gint               *cell_x,
10569                                gint               *cell_y)
10570 {
10571   GtkRBTree *tree;
10572   GtkRBNode *node;
10573   gint y_offset;
10574
10575   g_return_val_if_fail (tree_view != NULL, FALSE);
10576   g_return_val_if_fail (tree_view->priv->bin_window != NULL, FALSE);
10577
10578   if (path)
10579     *path = NULL;
10580   if (column)
10581     *column = NULL;
10582
10583   if (tree_view->priv->tree == NULL)
10584     return FALSE;
10585
10586   if (x > tree_view->priv->hadjustment->upper)
10587     return FALSE;
10588
10589   if (x < 0 || y < 0)
10590     return FALSE;
10591
10592   if (column || cell_x)
10593     {
10594       GtkTreeViewColumn *tmp_column;
10595       GtkTreeViewColumn *last_column = NULL;
10596       GList *list;
10597       gint remaining_x = x;
10598       gboolean found = FALSE;
10599
10600       for (list = tree_view->priv->columns; list; list = list->next)
10601         {
10602           tmp_column = list->data;
10603
10604           if (tmp_column->visible == FALSE)
10605             continue;
10606
10607           last_column = tmp_column;
10608           if (remaining_x <= tmp_column->width)
10609             {
10610               found = TRUE;
10611
10612               if (column)
10613                 *column = tmp_column;
10614
10615               if (cell_x)
10616                 *cell_x = remaining_x;
10617
10618               break;
10619             }
10620           remaining_x -= tmp_column->width;
10621         }
10622
10623       if (!found)
10624         {
10625           if (column)
10626             *column = last_column;
10627
10628           if (cell_x)
10629             *cell_x = last_column->width + remaining_x;
10630         }
10631     }
10632
10633   y_offset = _gtk_rbtree_find_offset (tree_view->priv->tree,
10634                                       TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y),
10635                                       &tree, &node);
10636
10637   if (tree == NULL)
10638     return FALSE;
10639
10640   if (cell_y)
10641     *cell_y = y_offset;
10642
10643   if (path)
10644     *path = _gtk_tree_view_find_path (tree_view, tree, node);
10645
10646   return TRUE;
10647 }
10648
10649
10650 /**
10651  * gtk_tree_view_get_cell_area:
10652  * @tree_view: a #GtkTreeView
10653  * @path: a #GtkTreePath for the row, or %NULL to get only horizontal coordinates
10654  * @column: a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordiantes
10655  * @rect: rectangle to fill with cell rect
10656  *
10657  * Fills the bounding rectangle in tree window coordinates for the cell at the
10658  * row specified by @path and the column specified by @column.  If @path is
10659  * %NULL, or points to a path not currently displayed, the @y and @height fields
10660  * of the rectangle will be filled with 0. If @column is %NULL, the @x and @width
10661  * fields will be filled with 0.  The sum of all cell rects does not cover the
10662  * entire tree; there are extra pixels in between rows, for example. The
10663  * returned rectangle is equivalent to the @cell_area passed to
10664  * gtk_cell_renderer_render().  This function is only valid if #tree_view is
10665  * realized.
10666  **/
10667 void
10668 gtk_tree_view_get_cell_area (GtkTreeView        *tree_view,
10669                              GtkTreePath        *path,
10670                              GtkTreeViewColumn  *column,
10671                              GdkRectangle       *rect)
10672 {
10673   GtkRBTree *tree = NULL;
10674   GtkRBNode *node = NULL;
10675   gint vertical_separator;
10676   gint horizontal_separator;
10677
10678   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10679   g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column));
10680   g_return_if_fail (rect != NULL);
10681   g_return_if_fail (!column || column->tree_view == (GtkWidget *) tree_view);
10682   g_return_if_fail (GTK_WIDGET_REALIZED (tree_view));
10683
10684   gtk_widget_style_get (GTK_WIDGET (tree_view),
10685                         "vertical_separator", &vertical_separator,
10686                         "horizontal_separator", &horizontal_separator,
10687                         NULL);
10688
10689   rect->x = 0;
10690   rect->y = 0;
10691   rect->width = 0;
10692   rect->height = 0;
10693
10694   if (column)
10695     {
10696       rect->x = column->button->allocation.x + horizontal_separator/2;
10697       rect->width = column->button->allocation.width - horizontal_separator;
10698     }
10699
10700   if (path)
10701     {
10702       gboolean ret = _gtk_tree_view_find_node (tree_view, path, &tree, &node);
10703
10704       /* Get vertical coords */
10705       if ((!ret && tree == NULL) || ret)
10706         return;
10707
10708       rect->y = CELL_FIRST_PIXEL (tree_view, tree, node, vertical_separator);
10709       rect->height = MAX (CELL_HEIGHT (node, vertical_separator), tree_view->priv->expander_size - vertical_separator);
10710
10711       if (gtk_tree_view_is_expander_column (tree_view, column) &&
10712           TREE_VIEW_DRAW_EXPANDERS (tree_view))
10713         {
10714           gint depth = gtk_tree_path_get_depth (path) - 1;
10715
10716           rect->x += depth * tree_view->priv->expander_size;
10717           rect->width -= depth * tree_view->priv->expander_size;
10718           rect->width = MAX (rect->width, 0);
10719         }
10720     }
10721 }
10722
10723 /**
10724  * gtk_tree_view_get_background_area:
10725  * @tree_view: a #GtkTreeView
10726  * @path: a #GtkTreePath for the row, or %NULL to get only horizontal coordinates
10727  * @column: a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordiantes
10728  * @rect: rectangle to fill with cell background rect
10729  *
10730  * Fills the bounding rectangle in tree window coordinates for the cell at the
10731  * row specified by @path and the column specified by @column.  If @path is
10732  * %NULL, or points to a node not found in the tree, the @y and @height fields of
10733  * the rectangle will be filled with 0. If @column is %NULL, the @x and @width
10734  * fields will be filled with 0.  The returned rectangle is equivalent to the
10735  * @background_area passed to gtk_cell_renderer_render().  These background
10736  * areas tile to cover the entire tree window (except for the area used for
10737  * header buttons). Contrast with the @cell_area, returned by
10738  * gtk_tree_view_get_cell_area(), which returns only the cell itself, excluding
10739  * surrounding borders and the tree expander area.
10740  *
10741  **/
10742 void
10743 gtk_tree_view_get_background_area (GtkTreeView        *tree_view,
10744                                    GtkTreePath        *path,
10745                                    GtkTreeViewColumn  *column,
10746                                    GdkRectangle       *rect)
10747 {
10748   GtkRBTree *tree = NULL;
10749   GtkRBNode *node = NULL;
10750
10751   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10752   g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column));
10753   g_return_if_fail (rect != NULL);
10754
10755   rect->x = 0;
10756   rect->y = 0;
10757   rect->width = 0;
10758   rect->height = 0;
10759
10760   if (path)
10761     {
10762       /* Get vertical coords */
10763
10764       if (!_gtk_tree_view_find_node (tree_view, path, &tree, &node) &&
10765           tree == NULL)
10766         return;
10767
10768       rect->y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
10769
10770       rect->height = MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size);
10771     }
10772
10773   if (column)
10774     {
10775       gint x2 = 0;
10776
10777       gtk_tree_view_get_background_xrange (tree_view, tree, column, &rect->x, &x2);
10778       rect->width = x2 - rect->x;
10779     }
10780 }
10781
10782 /**
10783  * gtk_tree_view_get_visible_rect:
10784  * @tree_view: a #GtkTreeView
10785  * @visible_rect: rectangle to fill
10786  *
10787  * Fills @visible_rect with the currently-visible region of the
10788  * buffer, in tree coordinates. Convert to widget coordinates with
10789  * gtk_tree_view_tree_to_widget_coords(). Tree coordinates start at
10790  * 0,0 for row 0 of the tree, and cover the entire scrollable area of
10791  * the tree.
10792  **/
10793 void
10794 gtk_tree_view_get_visible_rect (GtkTreeView  *tree_view,
10795                                 GdkRectangle *visible_rect)
10796 {
10797   GtkWidget *widget;
10798
10799   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10800
10801   widget = GTK_WIDGET (tree_view);
10802
10803   if (visible_rect)
10804     {
10805       visible_rect->x = tree_view->priv->hadjustment->value;
10806       visible_rect->y = tree_view->priv->vadjustment->value;
10807       visible_rect->width = widget->allocation.width;
10808       visible_rect->height = widget->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
10809     }
10810 }
10811
10812 /**
10813  * gtk_tree_view_widget_to_tree_coords:
10814  * @tree_view: a #GtkTreeView
10815  * @wx: widget X coordinate
10816  * @wy: widget Y coordinate
10817  * @tx: return location for tree X coordinate
10818  * @ty: return location for tree Y coordinate
10819  *
10820  * Converts widget coordinates to coordinates for the
10821  * tree window (the full scrollable area of the tree).
10822  *
10823  **/
10824 void
10825 gtk_tree_view_widget_to_tree_coords (GtkTreeView *tree_view,
10826                                      gint         wx,
10827                                      gint         wy,
10828                                      gint        *tx,
10829                                      gint        *ty)
10830 {
10831   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10832
10833   if (tx)
10834     *tx = wx + tree_view->priv->hadjustment->value;
10835   if (ty)
10836     *ty = wy + tree_view->priv->dy;
10837 }
10838
10839 /**
10840  * gtk_tree_view_tree_to_widget_coords:
10841  * @tree_view: a #GtkTreeView
10842  * @tx: tree X coordinate
10843  * @ty: tree Y coordinate
10844  * @wx: return location for widget X coordinate
10845  * @wy: return location for widget Y coordinate
10846  *
10847  * Converts tree coordinates (coordinates in full scrollable area of the tree)
10848  * to widget coordinates.
10849  *
10850  **/
10851 void
10852 gtk_tree_view_tree_to_widget_coords (GtkTreeView *tree_view,
10853                                      gint         tx,
10854                                      gint         ty,
10855                                      gint        *wx,
10856                                      gint        *wy)
10857 {
10858   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10859
10860   if (wx)
10861     *wx = tx - tree_view->priv->hadjustment->value;
10862   if (wy)
10863     *wy = ty - tree_view->priv->dy;
10864 }
10865
10866 static void
10867 unset_reorderable (GtkTreeView *tree_view)
10868 {
10869   if (tree_view->priv->reorderable)
10870     {
10871       tree_view->priv->reorderable = FALSE;
10872       g_object_notify (G_OBJECT (tree_view), "reorderable");
10873     }
10874 }
10875
10876 void
10877 gtk_tree_view_enable_model_drag_source (GtkTreeView              *tree_view,
10878                                         GdkModifierType           start_button_mask,
10879                                         const GtkTargetEntry     *targets,
10880                                         gint                      n_targets,
10881                                         GdkDragAction             actions)
10882 {
10883   TreeViewDragInfo *di;
10884
10885   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10886
10887   di = ensure_info (tree_view);
10888   clear_source_info (di);
10889
10890   di->start_button_mask = start_button_mask;
10891   di->source_target_list = gtk_target_list_new (targets, n_targets);
10892   di->source_actions = actions;
10893
10894   di->source_set = TRUE;
10895
10896   unset_reorderable (tree_view);
10897 }
10898
10899 void
10900 gtk_tree_view_enable_model_drag_dest (GtkTreeView              *tree_view,
10901                                       const GtkTargetEntry     *targets,
10902                                       gint                      n_targets,
10903                                       GdkDragAction             actions)
10904 {
10905   TreeViewDragInfo *di;
10906
10907   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10908
10909   gtk_drag_dest_set (GTK_WIDGET (tree_view),
10910                      0,
10911                      NULL,
10912                      0,
10913                      actions);
10914
10915   di = ensure_info (tree_view);
10916   clear_dest_info (di);
10917
10918   if (targets)
10919     di->dest_target_list = gtk_target_list_new (targets, n_targets);
10920
10921   di->dest_set = TRUE;
10922
10923   unset_reorderable (tree_view);
10924 }
10925
10926 void
10927 gtk_tree_view_unset_rows_drag_source (GtkTreeView *tree_view)
10928 {
10929   TreeViewDragInfo *di;
10930
10931   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10932
10933   di = get_info (tree_view);
10934
10935   if (di)
10936     {
10937       if (di->source_set)
10938         {
10939           clear_source_info (di);
10940           di->source_set = FALSE;
10941         }
10942
10943       if (!di->dest_set && !di->source_set)
10944         remove_info (tree_view);
10945     }
10946   
10947   unset_reorderable (tree_view);
10948 }
10949
10950 void
10951 gtk_tree_view_unset_rows_drag_dest (GtkTreeView *tree_view)
10952 {
10953   TreeViewDragInfo *di;
10954
10955   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10956
10957   di = get_info (tree_view);
10958
10959   if (di)
10960     {
10961       if (di->dest_set)
10962         {
10963           gtk_drag_dest_unset (GTK_WIDGET (tree_view));
10964           clear_dest_info (di);
10965           di->dest_set = FALSE;
10966         }
10967
10968       if (!di->dest_set && !di->source_set)
10969         remove_info (tree_view);
10970     }
10971
10972   unset_reorderable (tree_view);
10973 }
10974
10975 void
10976 gtk_tree_view_set_drag_dest_row (GtkTreeView            *tree_view,
10977                                  GtkTreePath            *path,
10978                                  GtkTreeViewDropPosition pos)
10979 {
10980   GtkTreePath *current_dest;
10981
10982   /* Note; this function is exported to allow a custom DND
10983    * implementation, so it can't touch TreeViewDragInfo
10984    */
10985
10986   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
10987
10988   current_dest = NULL;
10989
10990   if (tree_view->priv->drag_dest_row)
10991     {
10992       current_dest = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
10993       gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
10994     }
10995
10996   /* special case a drop on an empty model */
10997   tree_view->priv->empty_view_drop = 0;
10998
10999   if (pos == GTK_TREE_VIEW_DROP_BEFORE && path
11000       && gtk_tree_path_get_depth (path) == 1
11001       && gtk_tree_path_get_indices (path)[0] == 0)
11002     {
11003       gint n_children;
11004
11005       n_children = gtk_tree_model_iter_n_children (tree_view->priv->model,
11006                                                    NULL);
11007
11008       if (!n_children)
11009         tree_view->priv->empty_view_drop = 1;
11010     }
11011
11012   tree_view->priv->drag_dest_pos = pos;
11013
11014   if (path)
11015     {
11016       tree_view->priv->drag_dest_row =
11017         gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
11018       gtk_tree_view_queue_draw_path (tree_view, path, NULL);
11019     }
11020   else
11021     tree_view->priv->drag_dest_row = NULL;
11022
11023   if (current_dest)
11024     {
11025       GtkRBTree *tree, *new_tree;
11026       GtkRBNode *node, *new_node;
11027
11028       _gtk_tree_view_find_node (tree_view, current_dest, &tree, &node);
11029       _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
11030
11031       if (tree && node)
11032         {
11033           _gtk_rbtree_next_full (tree, node, &new_tree, &new_node);
11034           if (new_tree && new_node)
11035             _gtk_tree_view_queue_draw_node (tree_view, new_tree, new_node, NULL);
11036
11037           _gtk_rbtree_prev_full (tree, node, &new_tree, &new_node);
11038           if (new_tree && new_node)
11039             _gtk_tree_view_queue_draw_node (tree_view, new_tree, new_node, NULL);
11040         }
11041       gtk_tree_path_free (current_dest);
11042     }
11043 }
11044
11045 void
11046 gtk_tree_view_get_drag_dest_row (GtkTreeView              *tree_view,
11047                                  GtkTreePath             **path,
11048                                  GtkTreeViewDropPosition  *pos)
11049 {
11050   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
11051
11052   if (path)
11053     {
11054       if (tree_view->priv->drag_dest_row)
11055         *path = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
11056       else
11057         {
11058           if (tree_view->priv->empty_view_drop)
11059             *path = gtk_tree_path_new_from_indices (0, -1);
11060           else
11061             *path = NULL;
11062         }
11063     }
11064
11065   if (pos)
11066     *pos = tree_view->priv->drag_dest_pos;
11067 }
11068
11069 gboolean
11070 gtk_tree_view_get_dest_row_at_pos (GtkTreeView             *tree_view,
11071                                    gint                     drag_x,
11072                                    gint                     drag_y,
11073                                    GtkTreePath            **path,
11074                                    GtkTreeViewDropPosition *pos)
11075 {
11076   gint cell_y;
11077   gdouble offset_into_row;
11078   gdouble third;
11079   GdkRectangle cell;
11080   GtkTreeViewColumn *column = NULL;
11081   GtkTreePath *tmp_path = NULL;
11082
11083   /* Note; this function is exported to allow a custom DND
11084    * implementation, so it can't touch TreeViewDragInfo
11085    */
11086
11087   g_return_val_if_fail (tree_view != NULL, FALSE);
11088   g_return_val_if_fail (drag_x >= 0, FALSE);
11089   g_return_val_if_fail (drag_y >= 0, FALSE);
11090   g_return_val_if_fail (tree_view->priv->bin_window != NULL, FALSE);
11091
11092
11093   if (path)
11094     *path = NULL;
11095
11096   if (tree_view->priv->tree == NULL)
11097     return FALSE;
11098
11099   /* If in the top third of a row, we drop before that row; if
11100    * in the bottom third, drop after that row; if in the middle,
11101    * and the row has children, drop into the row.
11102    */
11103
11104   if (!gtk_tree_view_get_path_at_pos (tree_view,
11105                                       drag_x,
11106                                       drag_y - TREE_VIEW_HEADER_HEIGHT (tree_view),
11107                                       &tmp_path,
11108                                       &column,
11109                                       NULL,
11110                                       &cell_y))
11111     return FALSE;
11112
11113   gtk_tree_view_get_background_area (tree_view, tmp_path, column,
11114                                      &cell);
11115
11116   offset_into_row = cell_y;
11117
11118   if (path)
11119     *path = tmp_path;
11120   else
11121     gtk_tree_path_free (tmp_path);
11122
11123   tmp_path = NULL;
11124
11125   third = cell.height / 3.0;
11126
11127   if (pos)
11128     {
11129       if (offset_into_row < third)
11130         {
11131           *pos = GTK_TREE_VIEW_DROP_BEFORE;
11132         }
11133       else if (offset_into_row < (cell.height / 2.0))
11134         {
11135           *pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE;
11136         }
11137       else if (offset_into_row < third * 2.0)
11138         {
11139           *pos = GTK_TREE_VIEW_DROP_INTO_OR_AFTER;
11140         }
11141       else
11142         {
11143           *pos = GTK_TREE_VIEW_DROP_AFTER;
11144         }
11145     }
11146
11147   return TRUE;
11148 }
11149
11150
11151
11152 /* KEEP IN SYNC WITH GTK_TREE_VIEW_BIN_EXPOSE */
11153 /**
11154  * gtk_tree_view_create_row_drag_icon:
11155  * @tree_view: a #GtkTreeView
11156  * @path: a #GtkTreePath in @tree_view
11157  *
11158  * Creates a #GdkPixmap representation of the row at @path.  This image is used
11159  * for a drag icon.
11160  *
11161  * Return value: a newly-allocated pixmap of the drag icon.
11162  **/
11163 GdkPixmap *
11164 gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
11165                                     GtkTreePath  *path)
11166 {
11167   GtkTreeIter   iter;
11168   GtkRBTree    *tree;
11169   GtkRBNode    *node;
11170   gint cell_offset;
11171   GList *list;
11172   GdkRectangle background_area;
11173   GdkRectangle expose_area;
11174   GtkWidget *widget;
11175   gint depth;
11176   /* start drawing inside the black outline */
11177   gint x = 1, y = 1;
11178   GdkDrawable *drawable;
11179   gint bin_window_width;
11180
11181   widget = GTK_WIDGET (tree_view);
11182
11183   depth = gtk_tree_path_get_depth (path);
11184
11185   _gtk_tree_view_find_node (tree_view,
11186                             path,
11187                             &tree,
11188                             &node);
11189
11190   if (tree == NULL)
11191     return NULL;
11192
11193   if (!gtk_tree_model_get_iter (tree_view->priv->model,
11194                                 &iter,
11195                                 path))
11196     return NULL;
11197
11198   cell_offset = x;
11199
11200   background_area.y = y;
11201   background_area.height = MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size);
11202
11203   gdk_drawable_get_size (tree_view->priv->bin_window,
11204                          &bin_window_width, NULL);
11205
11206   drawable = gdk_pixmap_new (tree_view->priv->bin_window,
11207                              bin_window_width + 2,
11208                              background_area.height + 2,
11209                              -1);
11210
11211   expose_area.x = 0;
11212   expose_area.y = 0;
11213   expose_area.width = bin_window_width + 2;
11214   expose_area.height = background_area.height + 2;
11215
11216   gdk_draw_rectangle (drawable,
11217                       widget->style->base_gc [GTK_WIDGET_STATE (widget)],
11218                       TRUE,
11219                       0, 0,
11220                       bin_window_width + 2,
11221                       background_area.height + 2);
11222
11223   for (list = tree_view->priv->columns; list; list = list->next)
11224     {
11225       GtkTreeViewColumn *column = list->data;
11226       GdkRectangle cell_area;
11227       gint vertical_separator;
11228
11229       if (!column->visible)
11230         continue;
11231
11232       gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, &iter,
11233                                                GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
11234                                                node->children?TRUE:FALSE);
11235
11236       background_area.x = cell_offset;
11237       background_area.width = column->width;
11238
11239       cell_area = background_area;
11240
11241       gtk_widget_style_get (widget, "vertical_separator", &vertical_separator, NULL);
11242       cell_area.y += vertical_separator / 2;
11243       cell_area.height -= vertical_separator;
11244
11245       if (gtk_tree_view_is_expander_column (tree_view, column) &&
11246           TREE_VIEW_DRAW_EXPANDERS(tree_view))
11247         {
11248           cell_area.x += depth * tree_view->priv->expander_size;
11249           cell_area.width -= depth * tree_view->priv->expander_size;
11250         }
11251
11252       if (gtk_tree_view_column_cell_is_visible (column))
11253         _gtk_tree_view_column_cell_render (column,
11254                                            drawable,
11255                                            &background_area,
11256                                            &cell_area,
11257                                            &expose_area,
11258                                            0);
11259       cell_offset += column->width;
11260     }
11261
11262   gdk_draw_rectangle (drawable,
11263                       widget->style->black_gc,
11264                       FALSE,
11265                       0, 0,
11266                       bin_window_width + 1,
11267                       background_area.height + 1);
11268
11269   return drawable;
11270 }
11271
11272
11273 /**
11274  * gtk_tree_view_set_destroy_count_func:
11275  * @tree_view: A #GtkTreeView
11276  * @func: Function to be called when a view row is destroyed, or %NULL
11277  * @data: User data to be passed to @func, or %NULL
11278  * @destroy: Destroy notifier for @data, or %NULL
11279  *
11280  * This function should almost never be used.  It is meant for private use by
11281  * ATK for determining the number of visible children that are removed when the
11282  * user collapses a row, or a row is deleted.
11283  **/
11284 void
11285 gtk_tree_view_set_destroy_count_func (GtkTreeView             *tree_view,
11286                                       GtkTreeDestroyCountFunc  func,
11287                                       gpointer                 data,
11288                                       GtkDestroyNotify         destroy)
11289 {
11290   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
11291
11292   if (tree_view->priv->destroy_count_destroy)
11293     (* tree_view->priv->destroy_count_destroy) (tree_view->priv->destroy_count_data);
11294
11295   tree_view->priv->destroy_count_func = func;
11296   tree_view->priv->destroy_count_data = data;
11297   tree_view->priv->destroy_count_destroy = destroy;
11298 }
11299
11300
11301 /*
11302  * Interactive search
11303  */
11304
11305 /**
11306  * gtk_tree_view_set_enable_search:
11307  * @tree_view: A #GtkTreeView
11308  * @enable_search: %TRUE, if the user can search interactively
11309  *
11310  * If @enable_search is set, then the user can type in text to search through
11311  * the tree interactively.
11312  */
11313 void
11314 gtk_tree_view_set_enable_search (GtkTreeView *tree_view,
11315                                  gboolean     enable_search)
11316 {
11317   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
11318
11319   enable_search = !!enable_search;
11320   
11321   if (tree_view->priv->enable_search != enable_search)
11322     {
11323        tree_view->priv->enable_search = enable_search;
11324        g_object_notify (G_OBJECT (tree_view), "enable_search");
11325     }
11326 }
11327
11328 /**
11329  * gtk_tree_view_get_enable_search:
11330  * @tree_view: A #GtkTreeView
11331  *
11332  * Returns whether or not the tree allows interactive searching.
11333  *
11334  * Return value: whether or not to let the user search interactively
11335  */
11336 gboolean
11337 gtk_tree_view_get_enable_search (GtkTreeView *tree_view)
11338 {
11339   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
11340
11341   return tree_view->priv->enable_search;
11342 }
11343
11344
11345 /**
11346  * gtk_tree_view_get_search_column:
11347  * @tree_view: A #GtkTreeView
11348  *
11349  * Gets the column searched on by the interactive search code.
11350  *
11351  * Return value: the column the interactive search code searches in.
11352  */
11353 gint
11354 gtk_tree_view_get_search_column (GtkTreeView *tree_view)
11355 {
11356   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), 0);
11357
11358   return (tree_view->priv->search_column);
11359 }
11360
11361 /**
11362  * gtk_tree_view_set_search_column:
11363  * @tree_view: A #GtkTreeView
11364  * @column: the column of the model to search in
11365  *
11366  * Sets @column as the column where the interactive search code should
11367  * search in.  Additionally, turns on interactive searching. Note that
11368  * @column refers to a column of the model.
11369  */
11370 void
11371 gtk_tree_view_set_search_column (GtkTreeView *tree_view,
11372                                  gint         column)
11373 {
11374   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
11375   g_return_if_fail (column >= 0);
11376
11377   if (tree_view->priv->search_column == column)
11378     return;
11379
11380   tree_view->priv->search_column = column;
11381   g_object_notify (G_OBJECT (tree_view), "search_column");
11382 }
11383
11384 /**
11385  * gtk_tree_view_get_search_equal_func:
11386  * @tree_view: A #GtkTreeView
11387  *
11388  * Returns the compare function currently in use.
11389  *
11390  * Return value: the currently used compare function for the search code.
11391  */
11392
11393 GtkTreeViewSearchEqualFunc
11394 gtk_tree_view_get_search_equal_func (GtkTreeView *tree_view)
11395 {
11396   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
11397
11398   return tree_view->priv->search_equal_func;
11399 }
11400
11401 /**
11402  * gtk_tree_view_set_search_equal_func:
11403  * @tree_view: A #GtkTreeView
11404  * @search_equal_func: the compare function to use during the search
11405  * @search_user_data: user data to pass to @search_equal_func, or %NULL
11406  * @search_destroy: Destroy notifier for @search_user_data, or %NULL
11407  *
11408  * Sets the compare function for the interactive search capabilities.
11409  **/
11410 void
11411 gtk_tree_view_set_search_equal_func (GtkTreeView                *tree_view,
11412                                      GtkTreeViewSearchEqualFunc  search_equal_func,
11413                                      gpointer                    search_user_data,
11414                                      GtkDestroyNotify            search_destroy)
11415 {
11416   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
11417   g_return_if_fail (search_equal_func !=NULL);
11418
11419   if (tree_view->priv->search_destroy)
11420     (* tree_view->priv->search_destroy) (tree_view->priv->search_user_data);
11421
11422   tree_view->priv->search_equal_func = search_equal_func;
11423   tree_view->priv->search_user_data = search_user_data;
11424   tree_view->priv->search_destroy = search_destroy;
11425   if (tree_view->priv->search_equal_func == NULL)
11426     tree_view->priv->search_equal_func = gtk_tree_view_search_equal_func;
11427 }
11428
11429 static void
11430 gtk_tree_view_search_dialog_destroy (GtkWidget   *search_dialog,
11431                                      GtkTreeView *tree_view)
11432 {
11433   GList *list;
11434   GtkEntry *entry;
11435   gint *selected_iter;
11436
11437   list = gtk_container_get_children (GTK_CONTAINER (search_dialog));
11438   entry = (GtkEntry *)list->data;
11439   g_list_free (list);
11440
11441   if (tree_view->priv->disable_popdown)
11442     return;
11443
11444   if (entry)
11445     {
11446       /* send focus-in event */
11447       send_focus_change (GTK_WIDGET (entry), FALSE);
11448     }
11449
11450   /* remove data from tree_view */
11451   g_object_set_data (G_OBJECT (tree_view), GTK_TREE_VIEW_SEARCH_DIALOG_KEY,
11452                      NULL);
11453
11454   selected_iter = g_object_get_data (G_OBJECT (search_dialog),
11455                                      "gtk-tree-view-selected-iter");
11456   if (selected_iter)
11457     g_free (selected_iter);
11458   g_object_set_data (G_OBJECT (search_dialog), "gtk-tree-view-selected-iter",
11459                      NULL);
11460
11461   gtk_widget_destroy (search_dialog);
11462 }
11463
11464 static void
11465 gtk_tree_view_search_position_func (GtkTreeView *tree_view,
11466                                     GtkWidget   *search_dialog)
11467 {
11468   gint x, y;
11469   gint tree_x, tree_y;
11470   gint tree_width, tree_height;
11471   GdkWindow *tree_window = GTK_WIDGET (tree_view)->window;
11472   GdkScreen *screen = gdk_drawable_get_screen (tree_window);
11473   GtkRequisition requisition;
11474
11475   gtk_widget_realize (search_dialog);
11476
11477   gdk_window_get_origin (tree_window, &tree_x, &tree_y);
11478   gdk_drawable_get_size (tree_window,
11479                          &tree_width,
11480                          &tree_height);
11481   gtk_widget_size_request (search_dialog, &requisition);
11482
11483   if (tree_x + tree_width - requisition.width > gdk_screen_get_width (screen))
11484     x = gdk_screen_get_width (screen) - requisition.width;
11485   else if (tree_x + tree_width - requisition.width < 0)
11486     x = 0;
11487   else
11488     x = tree_x + tree_width - requisition.width;
11489
11490   if (tree_y + tree_height > gdk_screen_get_height (screen))
11491     y = gdk_screen_get_height (screen) - requisition.height;
11492   else if (tree_y + tree_height < 0) /* isn't really possible ... */
11493     y = 0;
11494   else
11495     y = tree_y + tree_height;
11496
11497   gtk_window_move (GTK_WINDOW (search_dialog), x, y);
11498 }
11499
11500 static void
11501 gtk_tree_view_search_disable_popdown (GtkEntry *entry,
11502                                       GtkMenu  *menu,
11503                                       gpointer  data)
11504 {
11505   GtkTreeView *tree_view = (GtkTreeView *)data;
11506
11507   tree_view->priv->disable_popdown = 1;
11508   g_signal_connect (menu, "hide",
11509                     G_CALLBACK (gtk_tree_view_search_enable_popdown), data);
11510 }
11511
11512 static gboolean
11513 gtk_tree_view_real_search_enable_popdown (gpointer data)
11514 {
11515   GtkTreeView *tree_view = (GtkTreeView *)data;
11516
11517   GDK_THREADS_ENTER ();
11518
11519   tree_view->priv->disable_popdown = 0;
11520
11521   GDK_THREADS_LEAVE ();
11522
11523   return FALSE;
11524 }
11525
11526 static void
11527 gtk_tree_view_search_enable_popdown (GtkWidget *widget,
11528                                      gpointer   data)
11529 {
11530   g_timeout_add (200, gtk_tree_view_real_search_enable_popdown, data);
11531 }
11532
11533 static gboolean
11534 gtk_tree_view_search_delete_event (GtkWidget *widget,
11535                                    GdkEventAny *event,
11536                                    GtkTreeView *tree_view)
11537 {
11538   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
11539
11540   gtk_tree_view_search_dialog_destroy (widget, tree_view);
11541
11542   return TRUE;
11543 }
11544
11545 static gboolean
11546 gtk_tree_view_search_button_press_event (GtkWidget *widget,
11547                                          GdkEventButton *event,
11548                                          GtkTreeView *tree_view)
11549 {
11550   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
11551
11552   gtk_tree_view_search_dialog_destroy (widget, tree_view);
11553
11554   return TRUE;
11555 }
11556
11557 static gboolean
11558 gtk_tree_view_search_key_press_event (GtkWidget *widget,
11559                                       GdkEventKey *event,
11560                                       GtkTreeView *tree_view)
11561 {
11562   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
11563   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
11564
11565   /* close window */
11566   if (event->keyval == GDK_Escape ||
11567       event->keyval == GDK_Return ||
11568       event->keyval == GDK_Tab)
11569     {
11570       gtk_tree_view_search_dialog_destroy (widget, tree_view);
11571       return TRUE;
11572     }
11573
11574   /* select previous matching iter */
11575   if (event->keyval == GDK_Up || event->keyval == GDK_KP_Up)
11576     {
11577       gtk_tree_view_search_move (widget, tree_view, TRUE);
11578       return TRUE;
11579     }
11580
11581   /* select next matching iter */
11582   if (event->keyval == GDK_Down || event->keyval == GDK_KP_Down)
11583     {
11584       gtk_tree_view_search_move (widget, tree_view, FALSE);
11585       return TRUE;
11586     }
11587
11588   return FALSE;
11589 }
11590
11591 static void
11592 gtk_tree_view_search_move (GtkWidget   *window,
11593                            GtkTreeView *tree_view,
11594                            gboolean     up)
11595 {
11596   gboolean ret;
11597   gint *selected_iter;
11598   gint len;
11599   gint count = 0;
11600   gchar *text;
11601   GtkTreeIter iter;
11602   GtkTreeModel *model;
11603   GtkTreeSelection *selection;
11604
11605   text = g_object_get_data (G_OBJECT (window), "gtk-tree-view-text");
11606   selected_iter = g_object_get_data (G_OBJECT (window), "gtk-tree-view-selected-iter");
11607
11608   g_return_if_fail (text != NULL);
11609
11610   if (!selected_iter || (up && *selected_iter == 1))
11611     return;
11612
11613   len = strlen (text);
11614
11615   if (len < 1)
11616     return;
11617
11618   model = gtk_tree_view_get_model (tree_view);
11619   selection = gtk_tree_view_get_selection (tree_view);
11620
11621   /* search */
11622   gtk_tree_selection_unselect_all (selection);
11623   gtk_tree_model_get_iter_first (model, &iter);
11624
11625   ret = gtk_tree_view_search_iter (model, selection, &iter, text,
11626                                    &count, up?((*selected_iter) - 1):((*selected_iter + 1)));
11627
11628   if (ret)
11629     {
11630       /* found */
11631       *selected_iter += up?(-1):(1);
11632     }
11633   else
11634     {
11635       /* return to old iter */
11636       count = 0;
11637       gtk_tree_model_get_iter_first (model, &iter);
11638       gtk_tree_view_search_iter (model, selection,
11639                                  &iter, text,
11640                                  &count, *selected_iter);
11641     }
11642 }
11643
11644 static gboolean
11645 gtk_tree_view_search_equal_func (GtkTreeModel *model,
11646                                  gint          column,
11647                                  const gchar  *key,
11648                                  GtkTreeIter  *iter,
11649                                  gpointer      search_data)
11650 {
11651   gboolean retval = TRUE;
11652   gchar *normalized_string;
11653   gchar *normalized_key;
11654   gchar *case_normalized_string = NULL;
11655   gchar *case_normalized_key = NULL;
11656   GValue value = {0,};
11657   GValue transformed = {0,};
11658   gint key_len;
11659
11660   gtk_tree_model_get_value (model, iter, column, &value);
11661
11662   g_value_init (&transformed, G_TYPE_STRING);
11663
11664   if (!g_value_transform (&value, &transformed))
11665     {
11666       g_value_unset (&value);
11667       return FALSE;
11668     }
11669
11670   g_value_unset (&value);
11671
11672   normalized_string = g_utf8_normalize (g_value_get_string (&transformed), -1, G_NORMALIZE_ALL);
11673   normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
11674
11675   if (normalized_string && normalized_key)
11676     {
11677       case_normalized_string = g_utf8_casefold (normalized_string, -1);
11678       case_normalized_key = g_utf8_casefold (normalized_key, -1);
11679
11680       key_len = strlen (case_normalized_key);
11681
11682       if (strstr (case_normalized_string, case_normalized_key))
11683         retval = FALSE;
11684     }
11685   else
11686     retval = FALSE;
11687
11688   g_value_unset (&transformed);
11689   g_free (normalized_key);
11690   g_free (normalized_string);
11691   g_free (case_normalized_key);
11692   g_free (case_normalized_string);
11693
11694   return retval;
11695 }
11696
11697 static gboolean
11698 gtk_tree_view_search_iter (GtkTreeModel     *model,
11699                            GtkTreeSelection *selection,
11700                            GtkTreeIter      *iter,
11701                            const gchar      *text,
11702                            gint             *count,
11703                            gint              n)
11704 {
11705   GtkRBTree *tree = NULL;
11706   GtkRBNode *node = NULL;
11707   GtkTreePath *path;
11708
11709   GtkTreeView *tree_view = gtk_tree_selection_get_tree_view (selection);
11710
11711   path = gtk_tree_model_get_path (model, iter);
11712   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
11713
11714   do
11715     {
11716       if (! tree_view->priv->search_equal_func (model, tree_view->priv->search_column, text, iter, tree_view->priv->search_user_data))
11717         {
11718           (*count)++;
11719           if (*count == n)
11720             {
11721               gtk_tree_view_scroll_to_cell (tree_view, path, NULL,
11722                                             TRUE, 0.5, 0.0);
11723               gtk_tree_selection_select_iter (selection, iter);
11724               gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
11725
11726               if (path)
11727                 gtk_tree_path_free (path);
11728
11729               return TRUE;
11730             }
11731         }
11732
11733       if (node->children)
11734         {
11735           gboolean has_child;
11736           GtkTreeIter tmp;
11737
11738           tree = node->children;
11739           node = tree->root;
11740
11741           while (node->left != tree->nil)
11742             node = node->left;
11743
11744           tmp = *iter;
11745           has_child = gtk_tree_model_iter_children (model, iter, &tmp);
11746           gtk_tree_path_down (path);
11747
11748           /* sanity check */
11749           TREE_VIEW_INTERNAL_ASSERT (has_child, FALSE);
11750         }
11751       else
11752         {
11753           gboolean done = FALSE;
11754
11755           do
11756             {
11757               node = _gtk_rbtree_next (tree, node);
11758
11759               if (node)
11760                 {
11761                   gboolean has_next;
11762
11763                   has_next = gtk_tree_model_iter_next (model, iter);
11764
11765                   done = TRUE;
11766                   gtk_tree_path_next (path);
11767
11768                   /* sanity check */
11769                   TREE_VIEW_INTERNAL_ASSERT (has_next, FALSE);
11770                 }
11771               else
11772                 {
11773                   gboolean has_parent;
11774                   GtkTreeIter tmp_iter = *iter;
11775
11776                   node = tree->parent_node;
11777                   tree = tree->parent_tree;
11778
11779                   if (!tree)
11780                     {
11781                       if (path)
11782                         gtk_tree_path_free (path);
11783
11784                       /* we've run out of tree, done with this func */
11785                       return FALSE;
11786                     }
11787
11788                   has_parent = gtk_tree_model_iter_parent (model,
11789                                                            iter,
11790                                                            &tmp_iter);
11791                   gtk_tree_path_up (path);
11792
11793                   /* sanity check */
11794                   TREE_VIEW_INTERNAL_ASSERT (has_parent, FALSE);
11795                 }
11796             }
11797           while (!done);
11798         }
11799     }
11800   while (1);
11801
11802   return FALSE;
11803 }
11804
11805 static void
11806 gtk_tree_view_search_init (GtkWidget   *entry,
11807                            GtkTreeView *tree_view)
11808 {
11809   gint ret;
11810   gint *selected_iter;
11811   gint len;
11812   gint count = 0;
11813   const gchar *text;
11814   GtkWidget *window;
11815   GtkTreeIter iter;
11816   GtkTreeModel *model;
11817   GtkTreeSelection *selection;
11818
11819   g_return_if_fail (GTK_IS_ENTRY (entry));
11820   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
11821
11822   window = gtk_widget_get_parent (entry);
11823   text = gtk_entry_get_text (GTK_ENTRY (entry));
11824   len = strlen (text);
11825   model = gtk_tree_view_get_model (tree_view);
11826   selection = gtk_tree_view_get_selection (tree_view);
11827
11828   /* search */
11829   gtk_tree_selection_unselect_all (selection);
11830   selected_iter = g_object_get_data (G_OBJECT (window), "gtk-tree-view-selected-iter");
11831   if (selected_iter)
11832     g_free (selected_iter);
11833   g_object_set_data (G_OBJECT (window), "gtk-tree-view-selected-iter", NULL);
11834
11835   if (len < 1)
11836     return;
11837
11838   gtk_tree_model_get_iter_first (model, &iter);
11839
11840   ret = gtk_tree_view_search_iter (model, selection,
11841                                    &iter, text,
11842                                    &count, 1);
11843
11844   if (ret)
11845     {
11846       selected_iter = g_malloc (sizeof (int));
11847       *selected_iter = 1;
11848       g_object_set_data (G_OBJECT (window), "gtk-tree-view-selected-iter",
11849                          selected_iter);
11850     }
11851 }
11852
11853 static void
11854 gtk_tree_view_remove_widget (GtkCellEditable *cell_editable,
11855                              GtkTreeView     *tree_view)
11856 {
11857   if (tree_view->priv->edited_column == NULL)
11858     return;
11859
11860   _gtk_tree_view_column_stop_editing (tree_view->priv->edited_column);
11861   tree_view->priv->edited_column = NULL;
11862
11863   if (GTK_WIDGET_HAS_FOCUS (cell_editable))
11864     gtk_widget_grab_focus (GTK_WIDGET (tree_view));
11865
11866   gtk_container_remove (GTK_CONTAINER (tree_view),
11867                         GTK_WIDGET (cell_editable));
11868 }
11869
11870 static gboolean
11871 gtk_tree_view_start_editing (GtkTreeView *tree_view,
11872                              GtkTreePath *cursor_path)
11873 {
11874   GtkTreeIter iter;
11875   GdkRectangle background_area;
11876   GdkRectangle cell_area;
11877   GtkCellEditable *editable_widget = NULL;
11878   gchar *path_string;
11879   guint flags = 0; /* can be 0, as the flags are primarily for rendering */
11880   gint retval = FALSE;
11881   GtkRBTree *cursor_tree;
11882   GtkRBNode *cursor_node;
11883
11884   g_assert (tree_view->priv->focus_column);
11885
11886   if (! GTK_WIDGET_REALIZED (tree_view))
11887     return FALSE;
11888
11889   if (_gtk_tree_view_find_node (tree_view, cursor_path, &cursor_tree, &cursor_node) ||
11890       cursor_node == NULL)
11891     return FALSE;
11892
11893   path_string = gtk_tree_path_to_string (cursor_path);
11894   gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path);
11895
11896   validate_row (tree_view, cursor_tree, cursor_node, &iter, cursor_path);
11897
11898   gtk_tree_view_column_cell_set_cell_data (tree_view->priv->focus_column,
11899                                            tree_view->priv->model,
11900                                            &iter,
11901                                            GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT),
11902                                            cursor_node->children?TRUE:FALSE);
11903   gtk_tree_view_get_background_area (tree_view,
11904                                      cursor_path,
11905                                      tree_view->priv->focus_column,
11906                                      &background_area);
11907   gtk_tree_view_get_cell_area (tree_view,
11908                                cursor_path,
11909                                tree_view->priv->focus_column,
11910                                &cell_area);
11911
11912   if (gtk_tree_view_is_expander_column (tree_view, tree_view->priv->focus_column) && TREE_VIEW_DRAW_EXPANDERS (tree_view))
11913     {
11914       cell_area.x += tree_view->priv->expander_size;
11915       cell_area.width -= tree_view->priv->expander_size;
11916     }
11917
11918   if (_gtk_tree_view_column_cell_event (tree_view->priv->focus_column,
11919                                         &editable_widget,
11920                                         NULL,
11921                                         path_string,
11922                                         &background_area,
11923                                         &cell_area,
11924                                         flags))
11925     {
11926       retval = TRUE;
11927       if (editable_widget != NULL)
11928         {
11929           gint left, right;
11930           GdkRectangle area;
11931           GtkCellRenderer *cell;
11932
11933           area = cell_area;
11934           cell = _gtk_tree_view_column_get_edited_cell (tree_view->priv->focus_column);
11935           _gtk_tree_view_column_get_neighbor_sizes (tree_view->priv->focus_column, cell, &left, &right);
11936
11937           area.x += left;
11938           area.width -= right + left;
11939
11940           gtk_tree_view_real_start_editing (tree_view,
11941                                             tree_view->priv->focus_column,
11942                                             cursor_path,
11943                                             editable_widget,
11944                                             &area,
11945                                             NULL,
11946                                             flags);
11947         }
11948
11949     }
11950   g_free (path_string);
11951   return retval;
11952 }
11953
11954 static void
11955 gtk_tree_view_real_start_editing (GtkTreeView       *tree_view,
11956                                   GtkTreeViewColumn *column,
11957                                   GtkTreePath       *path,
11958                                   GtkCellEditable   *cell_editable,
11959                                   GdkRectangle      *cell_area,
11960                                   GdkEvent          *event,
11961                                   guint              flags)
11962 {
11963   gint pre_val = tree_view->priv->vadjustment->value;
11964
11965   tree_view->priv->edited_column = column;
11966   _gtk_tree_view_column_start_editing (column, GTK_CELL_EDITABLE (cell_editable));
11967
11968   gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
11969
11970   cell_area->y += pre_val - tree_view->priv->vadjustment->value;
11971
11972   GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
11973   gtk_tree_view_put (tree_view,
11974                      GTK_WIDGET (cell_editable),
11975                      cell_area->x, cell_area->y, cell_area->width, cell_area->height);
11976   gtk_cell_editable_start_editing (GTK_CELL_EDITABLE (cell_editable),
11977                                    (GdkEvent *)event);
11978   gtk_widget_grab_focus (GTK_WIDGET (cell_editable));
11979   g_signal_connect (cell_editable, "remove_widget",
11980                     G_CALLBACK (gtk_tree_view_remove_widget), tree_view);
11981 }
11982
11983 static void
11984 gtk_tree_view_stop_editing (GtkTreeView *tree_view,
11985                             gboolean     cancel_editing)
11986 {
11987   GtkTreeViewColumn *column;
11988
11989   if (tree_view->priv->edited_column == NULL)
11990     return;
11991
11992   /*
11993    * This is very evil. We need to do this, because
11994    * gtk_cell_editable_editing_done may trigger gtk_tree_view_row_changed
11995    * later on. If gtk_tree_view_row_changed notices
11996    * tree_view->priv->edited_column != NULL, it'll call
11997    * gtk_tree_view_stop_editing again. Bad things will happen then.
11998    *
11999    * Please read that again if you intend to modify anything here.
12000    */
12001
12002   column = tree_view->priv->edited_column;
12003   tree_view->priv->edited_column = NULL;
12004
12005   if (! cancel_editing)
12006     gtk_cell_editable_editing_done (column->editable_widget);
12007
12008   tree_view->priv->edited_column = column;
12009
12010   gtk_cell_editable_remove_widget (column->editable_widget);
12011 }