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