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