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