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