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