]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeselection.c
Support separators in combo boxes and more generally in tree views
[~andy/gtk] / gtk / gtktreeselection.c
1 /* gtktreeselection.h
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 #include <config.h>
21 #include "gtktreeselection.h"
22 #include "gtktreeprivate.h"
23 #include "gtkrbtree.h"
24 #include "gtkmarshalers.h"
25
26 static void gtk_tree_selection_init              (GtkTreeSelection      *selection);
27 static void gtk_tree_selection_class_init        (GtkTreeSelectionClass *class);
28
29 static void gtk_tree_selection_finalize          (GObject               *object);
30 static gint gtk_tree_selection_real_select_all   (GtkTreeSelection      *selection);
31 static gint gtk_tree_selection_real_unselect_all (GtkTreeSelection      *selection);
32 static gint gtk_tree_selection_real_select_node  (GtkTreeSelection      *selection,
33                                                   GtkRBTree             *tree,
34                                                   GtkRBNode             *node,
35                                                   gboolean               select);
36
37 enum
38 {
39   CHANGED,
40   LAST_SIGNAL
41 };
42
43 static GObjectClass *parent_class = NULL;
44 static guint tree_selection_signals [LAST_SIGNAL] = { 0 };
45
46 GType
47 gtk_tree_selection_get_type (void)
48 {
49   static GType selection_type = 0;
50
51   if (!selection_type)
52     {
53       static const GTypeInfo selection_info =
54       {
55         sizeof (GtkTreeSelectionClass),
56         NULL,           /* base_init */
57         NULL,           /* base_finalize */
58         (GClassInitFunc) gtk_tree_selection_class_init,
59         NULL,           /* class_finalize */
60         NULL,           /* class_data */
61         sizeof (GtkTreeSelection),
62         0,              /* n_preallocs */
63         (GInstanceInitFunc) gtk_tree_selection_init
64       };
65
66       selection_type =
67         g_type_register_static (G_TYPE_OBJECT, "GtkTreeSelection",
68                                 &selection_info, 0);
69     }
70
71   return selection_type;
72 }
73
74 static void
75 gtk_tree_selection_class_init (GtkTreeSelectionClass *class)
76 {
77   GObjectClass *object_class;
78
79   object_class = (GObjectClass*) class;
80   parent_class = g_type_class_peek_parent (class);
81
82   object_class->finalize = gtk_tree_selection_finalize;
83   class->changed = NULL;
84
85   tree_selection_signals[CHANGED] =
86     g_signal_new ("changed",
87                   G_OBJECT_CLASS_TYPE (object_class),
88                   G_SIGNAL_RUN_FIRST,
89                   G_STRUCT_OFFSET (GtkTreeSelectionClass, changed),
90                   NULL, NULL,
91                   _gtk_marshal_VOID__VOID,
92                   G_TYPE_NONE, 0);
93 }
94
95 static void
96 gtk_tree_selection_init (GtkTreeSelection *selection)
97 {
98   selection->type = GTK_SELECTION_SINGLE;
99 }
100
101 static void
102 gtk_tree_selection_finalize (GObject *object)
103 {
104   GtkTreeSelection *selection = GTK_TREE_SELECTION (object);
105
106   if (selection->destroy)
107     {
108       GtkDestroyNotify d = selection->destroy;
109
110       selection->destroy = NULL;
111       d (selection->user_data);
112     }
113
114   /* chain parent_class' handler */
115   G_OBJECT_CLASS (parent_class)->finalize (object);
116 }
117
118 /**
119  * _gtk_tree_selection_new:
120  *
121  * Creates a new #GtkTreeSelection object.  This function should not be invoked,
122  * as each #GtkTreeView will create its own #GtkTreeSelection.
123  *
124  * Return value: A newly created #GtkTreeSelection object.
125  **/
126 GtkTreeSelection*
127 _gtk_tree_selection_new (void)
128 {
129   GtkTreeSelection *selection;
130
131   selection = g_object_new (GTK_TYPE_TREE_SELECTION, NULL);
132
133   return selection;
134 }
135
136 /**
137  * _gtk_tree_selection_new_with_tree_view:
138  * @tree_view: The #GtkTreeView.
139  *
140  * Creates a new #GtkTreeSelection object.  This function should not be invoked,
141  * as each #GtkTreeView will create its own #GtkTreeSelection.
142  *
143  * Return value: A newly created #GtkTreeSelection object.
144  **/
145 GtkTreeSelection*
146 _gtk_tree_selection_new_with_tree_view (GtkTreeView *tree_view)
147 {
148   GtkTreeSelection *selection;
149
150   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
151
152   selection = _gtk_tree_selection_new ();
153   _gtk_tree_selection_set_tree_view (selection, tree_view);
154
155   return selection;
156 }
157
158 /**
159  * _gtk_tree_selection_set_tree_view:
160  * @selection: A #GtkTreeSelection.
161  * @tree_view: The #GtkTreeView.
162  *
163  * Sets the #GtkTreeView of @selection.  This function should not be invoked, as
164  * it is used internally by #GtkTreeView.
165  **/
166 void
167 _gtk_tree_selection_set_tree_view (GtkTreeSelection *selection,
168                                    GtkTreeView      *tree_view)
169 {
170   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
171   if (tree_view != NULL)
172     g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
173
174   selection->tree_view = tree_view;
175 }
176
177 /**
178  * gtk_tree_selection_set_mode:
179  * @selection: A #GtkTreeSelection.
180  * @type: The selection mode
181  *
182  * Sets the selection mode of the @selection.  If the previous type was
183  * #GTK_SELECTION_MULTIPLE, then the anchor is kept selected, if it was
184  * previously selected.
185  **/
186 void
187 gtk_tree_selection_set_mode (GtkTreeSelection *selection,
188                              GtkSelectionMode  type)
189 {
190   GtkTreeSelectionFunc tmp_func;
191   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
192
193   if (selection->type == type)
194     return;
195
196   
197   if (type == GTK_SELECTION_NONE)
198     {
199       /* We do this so that we unconditionally unset all rows
200        */
201       tmp_func = selection->user_func;
202       selection->user_func = NULL;
203       gtk_tree_selection_unselect_all (selection);
204       selection->user_func = tmp_func;
205
206       gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
207       selection->tree_view->priv->anchor = NULL;
208     }
209   else if (type == GTK_SELECTION_SINGLE ||
210            type == GTK_SELECTION_BROWSE)
211     {
212       GtkRBTree *tree = NULL;
213       GtkRBNode *node = NULL;
214       gint selected = FALSE;
215       GtkTreePath *anchor_path = NULL;
216
217       if (selection->tree_view->priv->anchor)
218         {
219           anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
220
221           if (anchor_path)
222             {
223               _gtk_tree_view_find_node (selection->tree_view,
224                                         anchor_path,
225                                         &tree,
226                                         &node);
227
228               if (node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
229                 selected = TRUE;
230             }
231         }
232
233       /* We do this so that we unconditionally unset all rows
234        */
235       tmp_func = selection->user_func;
236       selection->user_func = NULL;
237       gtk_tree_selection_unselect_all (selection);
238       selection->user_func = tmp_func;
239
240       if (node && selected)
241         _gtk_tree_selection_internal_select_node (selection,
242                                                   node,
243                                                   tree,
244                                                   anchor_path,
245                                                   0,
246                                                   FALSE);
247       if (anchor_path)
248         gtk_tree_path_free (anchor_path);
249     }
250
251   selection->type = type;
252 }
253
254 /**
255  * gtk_tree_selection_get_mode:
256  * @selection: a #GtkTreeSelection
257  *
258  * Gets the selection mode for @selection. See
259  * gtk_tree_selection_set_mode().
260  *
261  * Return value: the current selection mode
262  **/
263 GtkSelectionMode
264 gtk_tree_selection_get_mode (GtkTreeSelection *selection)
265 {
266   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), GTK_SELECTION_SINGLE);
267
268   return selection->type;
269 }
270
271 /**
272  * gtk_tree_selection_set_select_function:
273  * @selection: A #GtkTreeSelection.
274  * @func: The selection function.
275  * @data: The selection function's data.
276  * @destroy: The destroy function for user data.  May be NULL.
277  *
278  * Sets the selection function.  If set, this function is called before any node
279  * is selected or unselected, giving some control over which nodes are selected.
280  * The select function should return %TRUE if the state of the node may be toggled,
281  * and %FALSE if the state of the node should be left unchanged.
282  **/
283 void
284 gtk_tree_selection_set_select_function (GtkTreeSelection     *selection,
285                                         GtkTreeSelectionFunc  func,
286                                         gpointer              data,
287                                         GtkDestroyNotify      destroy)
288 {
289   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
290   g_return_if_fail (func != NULL);
291
292   if (selection->destroy)
293     {
294       GtkDestroyNotify d = selection->destroy;
295
296       selection->destroy = NULL;
297       d (selection->user_data);
298     }
299
300   selection->user_func = func;
301   selection->user_data = data;
302   selection->destroy = destroy;
303 }
304
305 /**
306  * gtk_tree_selection_get_user_data:
307  * @selection: A #GtkTreeSelection.
308  *
309  * Returns the user data for the selection function.
310  *
311  * Return value: The user data.
312  **/
313 gpointer
314 gtk_tree_selection_get_user_data (GtkTreeSelection *selection)
315 {
316   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
317
318   return selection->user_data;
319 }
320
321 /**
322  * gtk_tree_selection_get_tree_view:
323  * @selection: A #GtkTreeSelection
324  * 
325  * Returns the tree view associated with @selection.
326  * 
327  * Return value: A #GtkTreeView
328  **/
329 GtkTreeView *
330 gtk_tree_selection_get_tree_view (GtkTreeSelection *selection)
331 {
332   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
333
334   return selection->tree_view;
335 }
336
337 /**
338  * gtk_tree_selection_get_selected:
339  * @selection: A #GtkTreeSelection.
340  * @model: A pointer to set to the #GtkTreeModel, or NULL.
341  * @iter: The #GtkTreeIter, or NULL.
342  *
343  * Sets @iter to the currently selected node if @selection is set to
344  * #GTK_SELECTION_SINGLE or #GTK_SELECTION_BROWSE.  @iter may be NULL if you
345  * just want to test if @selection has any selected nodes.  @model is filled
346  * with the current model as a convenience.  This function will not work if you
347  * use @selection is #GTK_SELECTION_MULTIPLE.
348  *
349  * Return value: TRUE, if there is a selected node.
350  **/
351 gboolean
352 gtk_tree_selection_get_selected (GtkTreeSelection  *selection,
353                                  GtkTreeModel     **model,
354                                  GtkTreeIter       *iter)
355 {
356   GtkRBTree *tree;
357   GtkRBNode *node;
358   GtkTreePath *anchor_path;
359   gboolean retval;
360   gboolean found_node;
361
362   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
363   g_return_val_if_fail (selection->type != GTK_SELECTION_MULTIPLE, FALSE);
364   g_return_val_if_fail (selection->tree_view != NULL, FALSE);
365   g_return_val_if_fail (selection->tree_view->priv->model != NULL, FALSE);
366
367   if (model)
368     *model = selection->tree_view->priv->model;
369
370   if (selection->tree_view->priv->anchor == NULL)
371     return FALSE;
372
373   anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
374
375   if (anchor_path == NULL)
376     return FALSE;
377
378   retval = FALSE;
379
380   found_node = !_gtk_tree_view_find_node (selection->tree_view,
381                                           anchor_path,
382                                           &tree,
383                                           &node);
384
385   if (found_node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
386     {
387       /* we only want to return the anchor if it exists in the rbtree and
388        * is selected.
389        */
390       if (iter == NULL)
391         retval = TRUE;
392       else
393         retval = gtk_tree_model_get_iter (selection->tree_view->priv->model,
394                                           iter,
395                                           anchor_path);
396     }
397   else
398     {
399       /* We don't want to return the anchor if it isn't actually selected.
400        */
401       retval = FALSE;
402     }
403
404   gtk_tree_path_free (anchor_path);
405
406   return retval;
407 }
408
409 /**
410  * gtk_tree_selection_get_selected_rows:
411  * @selection: A #GtkTreeSelection.
412  * @model: A pointer to set to the #GtkTreeModel, or NULL.
413  *
414  * Creates a list of path of all selected rows. Additionally, if you are
415  * planning on modifying the model after calling this function, you may
416  * want to convert the returned list into a list of #GtkTreeRowReference<!-- -->s.
417  * To do this, you can use gtk_tree_row_reference_new().
418  *
419  * To free the return value, use:
420  * <informalexample><programlisting>
421  * g_list_foreach (list, gtk_tree_path_free, NULL);
422  * g_list_free (list);
423  * </programlisting></informalexample>
424  *
425  * Return value: A #GList containing a #GtkTreePath for each selected row.
426  *
427  * Since: 2.2
428  **/
429 GList *
430 gtk_tree_selection_get_selected_rows (GtkTreeSelection   *selection,
431                                       GtkTreeModel      **model)
432 {
433   GList *list = NULL;
434   GtkRBTree *tree = NULL;
435   GtkRBNode *node = NULL;
436   GtkTreePath *path;
437
438   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
439   g_return_val_if_fail (selection->tree_view != NULL, NULL);
440   g_return_val_if_fail (selection->tree_view->priv->model != NULL, NULL);
441
442   if (selection->tree_view->priv->tree == NULL ||
443       selection->tree_view->priv->tree->root == NULL)
444     return NULL;
445
446   if (model)
447     *model = selection->tree_view->priv->model;
448
449   if (selection->type == GTK_SELECTION_NONE)
450     return NULL;
451   else if (selection->type != GTK_SELECTION_MULTIPLE)
452     {
453       GtkTreeIter iter;
454
455       if (gtk_tree_selection_get_selected (selection, NULL, &iter))
456         {
457           GtkTreePath *path;
458
459           path = gtk_tree_model_get_path (selection->tree_view->priv->model, &iter);
460           list = g_list_append (list, path);
461
462           return list;
463         }
464
465       return NULL;
466     }
467
468   tree = selection->tree_view->priv->tree;
469   node = selection->tree_view->priv->tree->root;
470
471   while (node->left != tree->nil)
472     node = node->left;
473   path = gtk_tree_path_new_first ();
474
475   do
476     {
477       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
478         list = g_list_prepend (list, gtk_tree_path_copy (path));
479
480       if (node->children)
481         {
482           tree = node->children;
483           node = tree->root;
484
485           while (node->left != tree->nil)
486             node = node->left;
487
488           gtk_tree_path_append_index (path, 0);
489         }
490       else
491         {
492           gboolean done = FALSE;
493
494           do
495             {
496               node = _gtk_rbtree_next (tree, node);
497               if (node != NULL)
498                 {
499                   done = TRUE;
500                   gtk_tree_path_next (path);
501                 }
502               else
503                 {
504                   node = tree->parent_node;
505                   tree = tree->parent_tree;
506
507                   if (!tree)
508                     {
509                       gtk_tree_path_free (path);
510
511                       goto done; 
512                     }
513
514                   gtk_tree_path_up (path);
515                 }
516             }
517           while (!done);
518         }
519     }
520   while (TRUE);
521
522   gtk_tree_path_free (path);
523
524  done:
525   return g_list_reverse (list);
526 }
527
528 static void
529 gtk_tree_selection_count_selected_rows_helper (GtkRBTree *tree,
530                                                GtkRBNode *node,
531                                                gpointer   data)
532 {
533   gint *count = (gint *)data;
534
535   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
536     (*count)++;
537
538   if (node->children)
539     _gtk_rbtree_traverse (node->children, node->children->root,
540                           G_PRE_ORDER,
541                           gtk_tree_selection_count_selected_rows_helper, data);
542 }
543
544 /**
545  * gtk_tree_selection_count_selected_rows:
546  * @selection: A #GtkTreeSelection.
547  *
548  * Returns the number of rows that have been selected in @tree.
549  *
550  * Return value: The number of rows selected.
551  * 
552  * Since: 2.2
553  **/
554 gint
555 gtk_tree_selection_count_selected_rows (GtkTreeSelection *selection)
556 {
557   gint count = 0;
558   GtkRBTree *tree;
559   GtkRBNode *node;
560
561   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), 0);
562   g_return_val_if_fail (selection->tree_view != NULL, 0);
563   g_return_val_if_fail (selection->tree_view->priv->model != NULL, 0);
564
565   if (selection->tree_view->priv->tree == NULL ||
566       selection->tree_view->priv->tree->root == NULL)
567     return 0;
568
569   if (selection->type == GTK_SELECTION_SINGLE ||
570       selection->type == GTK_SELECTION_BROWSE)
571     {
572       if (gtk_tree_selection_get_selected (selection, NULL, NULL))
573         return 1;
574       else
575         return 0;
576     }
577
578   tree = selection->tree_view->priv->tree;
579   node = selection->tree_view->priv->tree->root;
580
581   _gtk_rbtree_traverse (selection->tree_view->priv->tree,
582                         selection->tree_view->priv->tree->root,
583                         G_PRE_ORDER,
584                         gtk_tree_selection_count_selected_rows_helper,
585                         &count);
586
587   return count;
588 }
589
590 /* gtk_tree_selection_selected_foreach helper */
591 static void
592 model_changed (gpointer data)
593 {
594   gboolean *stop = (gboolean *)data;
595
596   *stop = TRUE;
597 }
598
599 /**
600  * gtk_tree_selection_selected_foreach:
601  * @selection: A #GtkTreeSelection.
602  * @func: The function to call for each selected node.
603  * @data: user data to pass to the function.
604  *
605  * Calls a function for each selected node. Note that you cannot modify
606  * the tree or selection from within this function. As a result,
607  * gtk_tree_selection_get_selected_rows() might be more useful.
608  **/
609 void
610 gtk_tree_selection_selected_foreach (GtkTreeSelection            *selection,
611                                      GtkTreeSelectionForeachFunc  func,
612                                      gpointer                     data)
613 {
614   GtkTreePath *path;
615   GtkRBTree *tree;
616   GtkRBNode *node;
617   GtkTreeIter iter;
618
619   guint inserted_id, deleted_id, reordered_id;
620   gboolean stop = FALSE, has_next = TRUE, has_parent = TRUE;
621
622   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
623   g_return_if_fail (selection->tree_view != NULL);
624   g_return_if_fail (selection->tree_view->priv->model != NULL);
625
626   if (func == NULL ||
627       selection->tree_view->priv->tree == NULL ||
628       selection->tree_view->priv->tree->root == NULL)
629     return;
630
631   if (selection->type == GTK_SELECTION_SINGLE ||
632       selection->type == GTK_SELECTION_BROWSE)
633     {
634       if (gtk_tree_row_reference_valid (selection->tree_view->priv->anchor))
635         {
636           path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
637           gtk_tree_model_get_iter (selection->tree_view->priv->model, &iter, path);
638           (* func) (selection->tree_view->priv->model, path, &iter, data);
639           gtk_tree_path_free (path);
640         }
641       return;
642     }
643
644   tree = selection->tree_view->priv->tree;
645   node = selection->tree_view->priv->tree->root;
646   
647   while (node->left != tree->nil)
648     node = node->left;
649
650   /* connect to signals to monitor changes in treemodel */
651   inserted_id = g_signal_connect_swapped (selection->tree_view->priv->model,
652                                           "row_inserted",
653                                           G_CALLBACK (model_changed),
654                                           &stop);
655   deleted_id = g_signal_connect_swapped (selection->tree_view->priv->model,
656                                          "row_deleted",
657                                          G_CALLBACK (model_changed),
658                                          &stop);
659   reordered_id = g_signal_connect_swapped (selection->tree_view->priv->model,
660                                            "rows_reordered",
661                                            G_CALLBACK (model_changed),
662                                            &stop);
663
664   /* find the node internally */
665   path = gtk_tree_path_new_first ();
666   gtk_tree_model_get_iter (selection->tree_view->priv->model,
667                            &iter, path);
668
669   do
670     {
671       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
672         (* func) (selection->tree_view->priv->model, path, &iter, data);
673
674       if (stop)
675         goto out;
676
677       if (node->children)
678         {
679           gboolean has_child;
680           GtkTreeIter tmp;
681
682           tree = node->children;
683           node = tree->root;
684           while (node->left != tree->nil)
685             node = node->left;
686           tmp = iter;
687           has_child = gtk_tree_model_iter_children (selection->tree_view->priv->model, &iter, &tmp);
688           gtk_tree_path_append_index (path, 0);
689
690           /* we do the sanity check at the bottom of this function */
691           if (!has_child)
692             goto out;
693         }
694       else
695         {
696           gboolean done = FALSE;
697           do
698             {
699               node = _gtk_rbtree_next (tree, node);
700               if (node != NULL)
701                 {
702                   gboolean has_next;
703
704                   has_next = gtk_tree_model_iter_next (selection->tree_view->priv->model, &iter);
705                   done = TRUE;
706                   gtk_tree_path_next (path);
707
708                   /* we do the sanity check at the bottom of this function */
709                   if (!has_next)
710                     goto out;
711                 }
712               else
713                 {
714                   gboolean has_parent;
715                   GtkTreeIter tmp_iter = iter;
716
717                   node = tree->parent_node;
718                   tree = tree->parent_tree;
719                   if (tree == NULL)
720                     {
721                       /* we've run out of tree */
722                       /* We're done with this function */
723
724                       goto out;
725                     }
726
727                   has_parent = gtk_tree_model_iter_parent (selection->tree_view->priv->model, &iter, &tmp_iter);
728                   gtk_tree_path_up (path);
729
730                   /* we do the sanity check at the bottom of this function */
731                   if (!has_parent)
732                     goto out;
733                 }
734             }
735           while (!done);
736         }
737     }
738   while (TRUE);
739
740 out:
741   if (path)
742     gtk_tree_path_free (path);
743
744   g_signal_handler_disconnect (selection->tree_view->priv->model,
745                                inserted_id);
746   g_signal_handler_disconnect (selection->tree_view->priv->model,
747                                deleted_id);
748   g_signal_handler_disconnect (selection->tree_view->priv->model,
749                                reordered_id);
750
751   /* check if we have to spew a scary message */
752   if (!has_next)
753     TREE_VIEW_INTERNAL_ASSERT_VOID (has_next);
754   if (!has_parent)
755     TREE_VIEW_INTERNAL_ASSERT_VOID (has_parent);
756   if (stop)
757     g_warning
758       ("The model has been modified from within gtk_tree_selection_selected_foreach.\n"
759        "This function is for observing the selections of the tree only.  If\n"
760        "you are trying to get all selected items from the tree, try using\n"
761        "gtk_tree_selection_get_selected_rows instead.\n");
762 }
763
764 /**
765  * gtk_tree_selection_select_path:
766  * @selection: A #GtkTreeSelection.
767  * @path: The #GtkTreePath to be selected.
768  *
769  * Select the row at @path.
770  **/
771 void
772 gtk_tree_selection_select_path (GtkTreeSelection *selection,
773                                 GtkTreePath      *path)
774 {
775   GtkRBNode *node;
776   GtkRBTree *tree;
777   gboolean ret;
778   GtkTreeSelectMode mode = 0;
779
780   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
781   g_return_if_fail (selection->tree_view != NULL);
782   g_return_if_fail (path != NULL);
783
784   ret = _gtk_tree_view_find_node (selection->tree_view,
785                                   path,
786                                   &tree,
787                                   &node);
788
789   if (node == NULL || GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) ||
790       ret == TRUE)
791     return;
792
793   if (selection->type == GTK_SELECTION_MULTIPLE)
794     mode = GTK_TREE_SELECT_MODE_TOGGLE;
795
796   _gtk_tree_selection_internal_select_node (selection,
797                                             node,
798                                             tree,
799                                             path,
800                                             mode,
801                                             FALSE);
802 }
803
804 /**
805  * gtk_tree_selection_unselect_path:
806  * @selection: A #GtkTreeSelection.
807  * @path: The #GtkTreePath to be unselected.
808  *
809  * Unselects the row at @path.
810  **/
811 void
812 gtk_tree_selection_unselect_path (GtkTreeSelection *selection,
813                                   GtkTreePath      *path)
814 {
815   GtkRBNode *node;
816   GtkRBTree *tree;
817   gboolean ret;
818
819   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
820   g_return_if_fail (selection->tree_view != NULL);
821   g_return_if_fail (path != NULL);
822
823   ret = _gtk_tree_view_find_node (selection->tree_view,
824                                   path,
825                                   &tree,
826                                   &node);
827
828   if (node == NULL || !GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) ||
829       ret == TRUE)
830     return;
831
832   _gtk_tree_selection_internal_select_node (selection,
833                                             node,
834                                             tree,
835                                             path,
836                                             GTK_TREE_SELECT_MODE_TOGGLE,
837                                             TRUE);
838 }
839
840 /**
841  * gtk_tree_selection_select_iter:
842  * @selection: A #GtkTreeSelection.
843  * @iter: The #GtkTreeIter to be selected.
844  *
845  * Selects the specified iterator.
846  **/
847 void
848 gtk_tree_selection_select_iter (GtkTreeSelection *selection,
849                                 GtkTreeIter      *iter)
850 {
851   GtkTreePath *path;
852
853   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
854   g_return_if_fail (selection->tree_view != NULL);
855   g_return_if_fail (selection->tree_view->priv->model != NULL);
856   g_return_if_fail (iter != NULL);
857
858   path = gtk_tree_model_get_path (selection->tree_view->priv->model,
859                                   iter);
860
861   if (path == NULL)
862     return;
863
864   gtk_tree_selection_select_path (selection, path);
865   gtk_tree_path_free (path);
866 }
867
868
869 /**
870  * gtk_tree_selection_unselect_iter:
871  * @selection: A #GtkTreeSelection.
872  * @iter: The #GtkTreeIter to be unselected.
873  *
874  * Unselects the specified iterator.
875  **/
876 void
877 gtk_tree_selection_unselect_iter (GtkTreeSelection *selection,
878                                   GtkTreeIter      *iter)
879 {
880   GtkTreePath *path;
881
882   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
883   g_return_if_fail (selection->tree_view != NULL);
884   g_return_if_fail (selection->tree_view->priv->model != NULL);
885   g_return_if_fail (iter != NULL);
886
887   path = gtk_tree_model_get_path (selection->tree_view->priv->model,
888                                   iter);
889
890   if (path == NULL)
891     return;
892
893   gtk_tree_selection_unselect_path (selection, path);
894   gtk_tree_path_free (path);
895 }
896
897 /**
898  * gtk_tree_selection_path_is_selected:
899  * @selection: A #GtkTreeSelection.
900  * @path: A #GtkTreePath to check selection on.
901  * 
902  * Returns %TRUE if the row pointed to by @path is currently selected.  If @path
903  * does not point to a valid location, %FALSE is returned
904  * 
905  * Return value: %TRUE if @path is selected.
906  **/
907 gboolean
908 gtk_tree_selection_path_is_selected (GtkTreeSelection *selection,
909                                      GtkTreePath      *path)
910 {
911   GtkRBNode *node;
912   GtkRBTree *tree;
913   gboolean ret;
914
915   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
916   g_return_val_if_fail (path != NULL, FALSE);
917   g_return_val_if_fail (selection->tree_view != NULL, FALSE);
918   g_return_val_if_fail (selection->tree_view->priv->model != NULL, FALSE);
919
920   ret = _gtk_tree_view_find_node (selection->tree_view,
921                                   path,
922                                   &tree,
923                                   &node);
924
925   if ((node == NULL) || !GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) ||
926       ret == TRUE)
927     return FALSE;
928
929   return TRUE;
930 }
931
932 /**
933  * gtk_tree_selection_iter_is_selected:
934  * @selection: A #GtkTreeSelection
935  * @iter: A valid #GtkTreeIter
936  * 
937  * Returns %TRUE if the row at @iter is currently selected.
938  * 
939  * Return value: %TRUE, if @iter is selected
940  **/
941 gboolean
942 gtk_tree_selection_iter_is_selected (GtkTreeSelection *selection,
943                                      GtkTreeIter      *iter)
944 {
945   GtkTreePath *path;
946   gboolean retval;
947
948   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
949   g_return_val_if_fail (iter != NULL, FALSE);
950   g_return_val_if_fail (selection->tree_view != NULL, FALSE);
951   g_return_val_if_fail (selection->tree_view->priv->model != NULL, FALSE);
952
953   path = gtk_tree_model_get_path (selection->tree_view->priv->model, iter);
954   if (path == NULL)
955     return FALSE;
956
957   retval = gtk_tree_selection_path_is_selected (selection, path);
958   gtk_tree_path_free (path);
959
960   return retval;
961 }
962
963
964 /* Wish I was in python, right now... */
965 struct _TempTuple {
966   GtkTreeSelection *selection;
967   gint dirty;
968 };
969
970 static void
971 select_all_helper (GtkRBTree  *tree,
972                    GtkRBNode  *node,
973                    gpointer    data)
974 {
975   struct _TempTuple *tuple = data;
976
977   if (node->children)
978     _gtk_rbtree_traverse (node->children,
979                           node->children->root,
980                           G_PRE_ORDER,
981                           select_all_helper,
982                           data);
983   if (!GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
984     {
985       tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, TRUE) || tuple->dirty;
986     }
987 }
988
989
990 /* We have a real_{un,}select_all function that doesn't emit the signal, so we
991  * can use it in other places without fear of the signal being emitted.
992  */
993 static gint
994 gtk_tree_selection_real_select_all (GtkTreeSelection *selection)
995 {
996   struct _TempTuple *tuple;
997
998   if (selection->tree_view->priv->tree == NULL)
999     return FALSE;
1000
1001   /* Mark all nodes selected */
1002   tuple = g_new (struct _TempTuple, 1);
1003   tuple->selection = selection;
1004   tuple->dirty = FALSE;
1005
1006   _gtk_rbtree_traverse (selection->tree_view->priv->tree,
1007                         selection->tree_view->priv->tree->root,
1008                         G_PRE_ORDER,
1009                         select_all_helper,
1010                         tuple);
1011   if (tuple->dirty)
1012     {
1013       g_free (tuple);
1014       return TRUE;
1015     }
1016   g_free (tuple);
1017   return FALSE;
1018 }
1019
1020 /**
1021  * gtk_tree_selection_select_all:
1022  * @selection: A #GtkTreeSelection.
1023  *
1024  * Selects all the nodes. @selection must be set to #GTK_SELECTION_MULTIPLE
1025  * mode.
1026  **/
1027 void
1028 gtk_tree_selection_select_all (GtkTreeSelection *selection)
1029 {
1030   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
1031   g_return_if_fail (selection->tree_view != NULL);
1032   if (selection->tree_view->priv->tree == NULL)
1033     return;
1034   g_return_if_fail (selection->type == GTK_SELECTION_MULTIPLE);
1035
1036   if (gtk_tree_selection_real_select_all (selection))
1037     g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
1038 }
1039
1040 static void
1041 unselect_all_helper (GtkRBTree  *tree,
1042                      GtkRBNode  *node,
1043                      gpointer    data)
1044 {
1045   struct _TempTuple *tuple = data;
1046
1047   if (node->children)
1048     _gtk_rbtree_traverse (node->children,
1049                           node->children->root,
1050                           G_PRE_ORDER,
1051                           unselect_all_helper,
1052                           data);
1053   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
1054     {
1055       tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, FALSE) || tuple->dirty;
1056     }
1057 }
1058
1059 static gint
1060 gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection)
1061 {
1062   struct _TempTuple *tuple;
1063
1064   if (selection->type == GTK_SELECTION_SINGLE ||
1065       selection->type == GTK_SELECTION_BROWSE)
1066     {
1067       GtkRBTree *tree = NULL;
1068       GtkRBNode *node = NULL;
1069       GtkTreePath *anchor_path;
1070
1071       if (selection->tree_view->priv->anchor == NULL)
1072         return FALSE;
1073
1074       anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
1075
1076       if (anchor_path == NULL)
1077         return FALSE;
1078
1079       _gtk_tree_view_find_node (selection->tree_view,
1080                                 anchor_path,
1081                                 &tree,
1082                                 &node);
1083
1084       gtk_tree_path_free (anchor_path);
1085
1086       if (tree == NULL)
1087         return FALSE;
1088
1089       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
1090         {
1091           if (gtk_tree_selection_real_select_node (selection, tree, node, FALSE))
1092             {
1093               gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1094               selection->tree_view->priv->anchor = NULL;
1095               return TRUE;
1096             }
1097         }
1098       return FALSE;
1099     }
1100   else
1101     {
1102       tuple = g_new (struct _TempTuple, 1);
1103       tuple->selection = selection;
1104       tuple->dirty = FALSE;
1105
1106       _gtk_rbtree_traverse (selection->tree_view->priv->tree,
1107                             selection->tree_view->priv->tree->root,
1108                             G_PRE_ORDER,
1109                             unselect_all_helper,
1110                             tuple);
1111
1112       if (tuple->dirty)
1113         {
1114           g_free (tuple);
1115           return TRUE;
1116         }
1117       g_free (tuple);
1118       return FALSE;
1119     }
1120 }
1121
1122 /**
1123  * gtk_tree_selection_unselect_all:
1124  * @selection: A #GtkTreeSelection.
1125  *
1126  * Unselects all the nodes.
1127  **/
1128 void
1129 gtk_tree_selection_unselect_all (GtkTreeSelection *selection)
1130 {
1131   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
1132   g_return_if_fail (selection->tree_view != NULL);
1133   if (selection->tree_view->priv->tree == NULL)
1134     return;
1135   
1136   if (selection->tree_view->priv->tree == NULL)
1137     return;
1138
1139   if (gtk_tree_selection_real_unselect_all (selection))
1140     g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
1141 }
1142
1143 enum
1144 {
1145   RANGE_SELECT,
1146   RANGE_UNSELECT
1147 };
1148
1149 static gint
1150 gtk_tree_selection_real_modify_range (GtkTreeSelection *selection,
1151                                       gint              mode,
1152                                       GtkTreePath      *start_path,
1153                                       GtkTreePath      *end_path)
1154 {
1155   GtkRBNode *start_node, *end_node;
1156   GtkRBTree *start_tree, *end_tree;
1157   GtkTreePath *anchor_path = NULL;
1158   gboolean dirty = FALSE;
1159
1160   switch (gtk_tree_path_compare (start_path, end_path))
1161     {
1162     case 1:
1163       _gtk_tree_view_find_node (selection->tree_view,
1164                                 end_path,
1165                                 &start_tree,
1166                                 &start_node);
1167       _gtk_tree_view_find_node (selection->tree_view,
1168                                 start_path,
1169                                 &end_tree,
1170                                 &end_node);
1171       anchor_path = start_path;
1172       break;
1173     case 0:
1174       _gtk_tree_view_find_node (selection->tree_view,
1175                                 start_path,
1176                                 &start_tree,
1177                                 &start_node);
1178       end_tree = start_tree;
1179       end_node = start_node;
1180       anchor_path = start_path;
1181       break;
1182     case -1:
1183       _gtk_tree_view_find_node (selection->tree_view,
1184                                 start_path,
1185                                 &start_tree,
1186                                 &start_node);
1187       _gtk_tree_view_find_node (selection->tree_view,
1188                                 end_path,
1189                                 &end_tree,
1190                                 &end_node);
1191       anchor_path = start_path;
1192       break;
1193     }
1194
1195   g_return_val_if_fail (start_node != NULL, FALSE);
1196   g_return_val_if_fail (end_node != NULL, FALSE);
1197
1198   if (anchor_path)
1199     {
1200       if (selection->tree_view->priv->anchor)
1201         gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1202
1203       selection->tree_view->priv->anchor =
1204         gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view),
1205                                           selection->tree_view->priv->model,
1206                                           anchor_path);
1207     }
1208
1209   do
1210     {
1211       dirty |= gtk_tree_selection_real_select_node (selection, start_tree, start_node, (mode == RANGE_SELECT)?TRUE:FALSE);
1212
1213       if (start_node == end_node)
1214         break;
1215
1216       if (start_node->children)
1217         {
1218           start_tree = start_node->children;
1219           start_node = start_tree->root;
1220           while (start_node->left != start_tree->nil)
1221             start_node = start_node->left;
1222         }
1223       else
1224         {
1225           _gtk_rbtree_next_full (start_tree, start_node, &start_tree, &start_node);
1226           if (start_tree == NULL)
1227             {
1228               /* we just ran out of tree.  That means someone passed in bogus values.
1229                */
1230               return dirty;
1231             }
1232         }
1233     }
1234   while (TRUE);
1235
1236   return dirty;
1237 }
1238
1239 /**
1240  * gtk_tree_selection_select_range:
1241  * @selection: A #GtkTreeSelection.
1242  * @start_path: The initial node of the range.
1243  * @end_path: The final node of the range.
1244  *
1245  * Selects a range of nodes, determined by @start_path and @end_path inclusive.
1246  * @selection must be set to #GTK_SELECTION_MULTIPLE mode. 
1247  **/
1248 void
1249 gtk_tree_selection_select_range (GtkTreeSelection *selection,
1250                                  GtkTreePath      *start_path,
1251                                  GtkTreePath      *end_path)
1252 {
1253   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
1254   g_return_if_fail (selection->tree_view != NULL);
1255   g_return_if_fail (selection->type == GTK_SELECTION_MULTIPLE);
1256
1257   if (gtk_tree_selection_real_modify_range (selection, RANGE_SELECT, start_path, end_path))
1258     g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
1259 }
1260
1261 /**
1262  * gtk_tree_selection_unselect_range:
1263  * @selection: A #GtkTreeSelection.
1264  * @start_path: The initial node of the range.
1265  * @end_path: The initial node of the range.
1266  *
1267  * Unselects a range of nodes, determined by @start_path and @end_path
1268  * inclusive.
1269  *
1270  * Since: 2.2
1271  **/
1272 void
1273 gtk_tree_selection_unselect_range (GtkTreeSelection *selection,
1274                                    GtkTreePath      *start_path,
1275                                    GtkTreePath      *end_path)
1276 {
1277   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
1278   g_return_if_fail (selection->tree_view != NULL);
1279
1280   if (gtk_tree_selection_real_modify_range (selection, RANGE_UNSELECT, start_path, end_path))
1281     g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
1282 }
1283
1284 static gboolean
1285 tree_column_is_sensitive (GtkTreeViewColumn *column,
1286                           GtkTreeModel      *model,
1287                           GtkTreeIter       *iter)
1288 {
1289   GList *cells, *list;
1290   gboolean sensitive;
1291   gboolean visible;
1292
1293   gtk_tree_view_column_cell_set_cell_data (column, model,
1294                                            iter, FALSE, FALSE);
1295
1296   cells = gtk_tree_view_column_get_cell_renderers (column);
1297
1298   list = cells;
1299   while (list)
1300     {
1301       g_object_get (G_OBJECT (list->data), 
1302                     "sensitive", &sensitive, 
1303                     "visible", &visible,
1304                     NULL);
1305       
1306       if (visible && sensitive)
1307         break;
1308
1309       list = list->next;
1310     }
1311   g_list_free (cells);
1312
1313   return sensitive;
1314 }
1315
1316 static gboolean
1317 row_is_selectable (GtkTreeSelection *selection,
1318                    GtkRBNode        *node,
1319                    GtkTreePath      *path)
1320 {
1321   GList *list;
1322   GtkTreeIter iter;
1323   gboolean sensitive = FALSE;
1324
1325   if (!gtk_tree_model_get_iter (selection->tree_view->priv->model, &iter, path))
1326     sensitive = TRUE;
1327
1328   if (!sensitive && selection->tree_view->priv->row_separator_func)
1329     {
1330       /* never allow separators to be selected */
1331       if ((* selection->tree_view->priv->row_separator_func) (selection->tree_view->priv->model,
1332                                                               &iter,
1333                                                               selection->tree_view->priv->row_separator_data))
1334         return FALSE;
1335     }
1336
1337   for (list = selection->tree_view->priv->columns; list && !sensitive; list = list->next)
1338     {
1339       GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (list->data);
1340
1341       if (!column->visible)
1342         continue;
1343
1344       sensitive = tree_column_is_sensitive (column, selection->tree_view->priv->model, &iter);
1345     }
1346
1347   if (!sensitive)
1348     return FALSE;
1349
1350   if (selection->user_func)
1351     return (*selection->user_func) (selection, selection->tree_view->priv->model, path,
1352                                     GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED),
1353                                     selection->user_data);
1354   else
1355     return TRUE;
1356 }
1357
1358
1359 /* Called internally by gtktreeview.c It handles actually selecting the tree.
1360  */
1361
1362 /*
1363  * docs about the 'override_browse_mode', we set this flag when we want to
1364  * unset select the node and override the select browse mode behaviour (that is
1365  * 'one node should *always* be selected').
1366  */
1367 void
1368 _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection,
1369                                           GtkRBNode        *node,
1370                                           GtkRBTree        *tree,
1371                                           GtkTreePath      *path,
1372                                           GtkTreeSelectMode mode,
1373                                           gboolean          override_browse_mode)
1374 {
1375   gint flags;
1376   gint dirty = FALSE;
1377   GtkTreePath *anchor_path = NULL;
1378
1379   if (selection->type == GTK_SELECTION_NONE)
1380     return;
1381
1382   if (selection->tree_view->priv->anchor)
1383     anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
1384
1385   if (selection->type == GTK_SELECTION_SINGLE ||
1386       selection->type == GTK_SELECTION_BROWSE)
1387     {
1388       /* just unselect */
1389       if (selection->type == GTK_SELECTION_BROWSE && override_browse_mode)
1390         {
1391           dirty = gtk_tree_selection_real_unselect_all (selection);
1392         }
1393       /* Did we try to select the same node again? */
1394       else if (selection->type == GTK_SELECTION_SINGLE &&
1395                anchor_path && gtk_tree_path_compare (path, anchor_path) == 0)
1396         {
1397           if ((mode & GTK_TREE_SELECT_MODE_TOGGLE) == GTK_TREE_SELECT_MODE_TOGGLE)
1398             {
1399               dirty = gtk_tree_selection_real_unselect_all (selection);
1400             }
1401         }
1402       else
1403         {
1404           if (anchor_path)
1405             {
1406               /* We only want to select the new node if we can unselect the old one,
1407                * and we can select the new one. */
1408               dirty = row_is_selectable (selection, node, path);
1409
1410               /* if dirty is FALSE, we weren't able to select the new one, otherwise, we try to
1411                * unselect the new one
1412                */
1413               if (dirty)
1414                 dirty = gtk_tree_selection_real_unselect_all (selection);
1415
1416               /* if dirty is TRUE at this point, we successfully unselected the
1417                * old one, and can then select the new one */
1418               if (dirty)
1419                 {
1420                   if (selection->tree_view->priv->anchor)
1421                     {
1422                       gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1423                       selection->tree_view->priv->anchor = NULL;
1424                     }
1425
1426                   if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE))
1427                     {
1428                       selection->tree_view->priv->anchor =
1429                         gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1430                     }
1431                 }
1432             }
1433           else
1434             {
1435               if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE))
1436                 {
1437                   dirty = TRUE;
1438                   if (selection->tree_view->priv->anchor)
1439                     gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1440
1441                   selection->tree_view->priv->anchor =
1442                     gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1443                 }
1444             }
1445         }
1446     }
1447   else if (selection->type == GTK_SELECTION_MULTIPLE)
1448     {
1449       if ((mode & GTK_TREE_SELECT_MODE_EXTEND) == GTK_TREE_SELECT_MODE_EXTEND
1450           && (anchor_path == NULL))
1451         {
1452           if (selection->tree_view->priv->anchor)
1453             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1454
1455           selection->tree_view->priv->anchor =
1456             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1457           dirty = gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
1458         }
1459       else if ((mode & (GTK_TREE_SELECT_MODE_EXTEND | GTK_TREE_SELECT_MODE_TOGGLE)) == (GTK_TREE_SELECT_MODE_EXTEND | GTK_TREE_SELECT_MODE_TOGGLE))
1460         {
1461           gtk_tree_selection_select_range (selection,
1462                                            anchor_path,
1463                                            path);
1464         }
1465       else if ((mode & GTK_TREE_SELECT_MODE_TOGGLE) == GTK_TREE_SELECT_MODE_TOGGLE)
1466         {
1467           flags = node->flags;
1468           if (selection->tree_view->priv->anchor)
1469             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1470
1471           selection->tree_view->priv->anchor =
1472             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1473
1474           if ((flags & GTK_RBNODE_IS_SELECTED) == GTK_RBNODE_IS_SELECTED)
1475             dirty |= gtk_tree_selection_real_select_node (selection, tree, node, FALSE);
1476           else
1477             dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
1478         }
1479       else if ((mode & GTK_TREE_SELECT_MODE_EXTEND) == GTK_TREE_SELECT_MODE_EXTEND)
1480         {
1481           dirty = gtk_tree_selection_real_unselect_all (selection);
1482           dirty |= gtk_tree_selection_real_modify_range (selection,
1483                                                          RANGE_SELECT,
1484                                                          anchor_path,
1485                                                          path);
1486         }
1487       else
1488         {
1489           dirty = gtk_tree_selection_real_unselect_all (selection);
1490
1491           if (selection->tree_view->priv->anchor)
1492             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1493
1494           selection->tree_view->priv->anchor =
1495             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1496
1497           dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
1498         }
1499     }
1500
1501   if (anchor_path)
1502     gtk_tree_path_free (anchor_path);
1503
1504   if (dirty)
1505     g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
1506 }
1507
1508 /* NOTE: Any {un,}selection ever done _MUST_ be done through this function!
1509  */
1510
1511 static gint
1512 gtk_tree_selection_real_select_node (GtkTreeSelection *selection,
1513                                      GtkRBTree        *tree,
1514                                      GtkRBNode        *node,
1515                                      gboolean          select)
1516 {
1517   gboolean selected = FALSE;
1518   GtkTreePath *path = NULL;
1519
1520   select = !! select;
1521
1522   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) != select)
1523     {
1524       path = _gtk_tree_view_find_path (selection->tree_view, tree, node);
1525       selected = row_is_selectable (selection, node, path);
1526       gtk_tree_path_free (path);
1527     }
1528
1529   if (selected == TRUE)
1530     {
1531       node->flags ^= GTK_RBNODE_IS_SELECTED;
1532
1533       _gtk_tree_view_queue_draw_node (selection->tree_view, tree, node, NULL);
1534       
1535       return TRUE;
1536     }
1537
1538   return FALSE;
1539 }
1540