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