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