]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeselection.c
90a0dac1745200e0d6ba76f38a58e7e9632f8718
[~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   GtkTreeModel *model;
618
619   gulong inserted_id, deleted_id, reordered_id, changed_id;
620   gboolean stop = FALSE;
621
622   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
623   g_return_if_fail (selection->tree_view != NULL);
624
625   if (func == NULL ||
626       selection->tree_view->priv->tree == NULL ||
627       selection->tree_view->priv->tree->root == NULL)
628     return;
629
630   if (selection->type == GTK_SELECTION_SINGLE ||
631       selection->type == GTK_SELECTION_BROWSE)
632     {
633       if (gtk_tree_row_reference_valid (selection->tree_view->priv->anchor))
634         {
635           path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
636           gtk_tree_model_get_iter (selection->tree_view->priv->model, &iter, path);
637           (* func) (selection->tree_view->priv->model, path, &iter, data);
638           gtk_tree_path_free (path);
639         }
640       return;
641     }
642
643   tree = selection->tree_view->priv->tree;
644   node = selection->tree_view->priv->tree->root;
645   
646   while (node->left != tree->nil)
647     node = node->left;
648
649   model = selection->tree_view->priv->model;
650   g_object_ref (model);
651
652   /* connect to signals to monitor changes in treemodel */
653   inserted_id = g_signal_connect_swapped (model, "row_inserted",
654                                           G_CALLBACK (model_changed),
655                                           &stop);
656   deleted_id = g_signal_connect_swapped (model, "row_deleted",
657                                          G_CALLBACK (model_changed),
658                                          &stop);
659   reordered_id = g_signal_connect_swapped (model, "rows_reordered",
660                                            G_CALLBACK (model_changed),
661                                            &stop);
662   changed_id = g_signal_connect_swapped (selection->tree_view, "notify::model",
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 (model, &iter, path);
674           (* func) (model, path, &iter, data);
675         }
676
677       if (stop)
678         goto out;
679
680       if (node->children)
681         {
682           tree = node->children;
683           node = tree->root;
684
685           while (node->left != tree->nil)
686             node = node->left;
687
688           gtk_tree_path_append_index (path, 0);
689         }
690       else
691         {
692           gboolean done = FALSE;
693
694           do
695             {
696               node = _gtk_rbtree_next (tree, node);
697               if (node != NULL)
698                 {
699                   done = TRUE;
700                   gtk_tree_path_next (path);
701                 }
702               else
703                 {
704                   node = tree->parent_node;
705                   tree = tree->parent_tree;
706
707                   if (tree == NULL)
708                     {
709                       /* we've run out of tree */
710                       /* We're done with this function */
711
712                       goto out;
713                     }
714
715                   gtk_tree_path_up (path);
716                 }
717             }
718           while (!done);
719         }
720     }
721   while (TRUE);
722
723 out:
724   if (path)
725     gtk_tree_path_free (path);
726
727   g_signal_handler_disconnect (model, inserted_id);
728   g_signal_handler_disconnect (model, deleted_id);
729   g_signal_handler_disconnect (model, reordered_id);
730   g_signal_handler_disconnect (selection->tree_view, changed_id);
731   g_object_unref (model);
732
733   /* check if we have to spew a scary message */
734   if (stop)
735     g_warning ("The model has been modified from within gtk_tree_selection_selected_foreach.\n"
736                "This function is for observing the selections of the tree only.  If\n"
737                "you are trying to get all selected items from the tree, try using\n"
738                "gtk_tree_selection_get_selected_rows instead.\n");
739 }
740
741 /**
742  * gtk_tree_selection_select_path:
743  * @selection: A #GtkTreeSelection.
744  * @path: The #GtkTreePath to be selected.
745  *
746  * Select the row at @path.
747  **/
748 void
749 gtk_tree_selection_select_path (GtkTreeSelection *selection,
750                                 GtkTreePath      *path)
751 {
752   GtkRBNode *node;
753   GtkRBTree *tree;
754   gboolean ret;
755   GtkTreeSelectMode mode = 0;
756
757   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
758   g_return_if_fail (selection->tree_view != NULL);
759   g_return_if_fail (path != NULL);
760
761   ret = _gtk_tree_view_find_node (selection->tree_view,
762                                   path,
763                                   &tree,
764                                   &node);
765
766   if (node == NULL || GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) ||
767       ret == TRUE)
768     return;
769
770   if (selection->type == GTK_SELECTION_MULTIPLE)
771     mode = GTK_TREE_SELECT_MODE_TOGGLE;
772
773   _gtk_tree_selection_internal_select_node (selection,
774                                             node,
775                                             tree,
776                                             path,
777                                             mode,
778                                             FALSE);
779 }
780
781 /**
782  * gtk_tree_selection_unselect_path:
783  * @selection: A #GtkTreeSelection.
784  * @path: The #GtkTreePath to be unselected.
785  *
786  * Unselects the row at @path.
787  **/
788 void
789 gtk_tree_selection_unselect_path (GtkTreeSelection *selection,
790                                   GtkTreePath      *path)
791 {
792   GtkRBNode *node;
793   GtkRBTree *tree;
794   gboolean ret;
795
796   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
797   g_return_if_fail (selection->tree_view != NULL);
798   g_return_if_fail (path != NULL);
799
800   ret = _gtk_tree_view_find_node (selection->tree_view,
801                                   path,
802                                   &tree,
803                                   &node);
804
805   if (node == NULL || !GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) ||
806       ret == TRUE)
807     return;
808
809   _gtk_tree_selection_internal_select_node (selection,
810                                             node,
811                                             tree,
812                                             path,
813                                             GTK_TREE_SELECT_MODE_TOGGLE,
814                                             TRUE);
815 }
816
817 /**
818  * gtk_tree_selection_select_iter:
819  * @selection: A #GtkTreeSelection.
820  * @iter: The #GtkTreeIter to be selected.
821  *
822  * Selects the specified iterator.
823  **/
824 void
825 gtk_tree_selection_select_iter (GtkTreeSelection *selection,
826                                 GtkTreeIter      *iter)
827 {
828   GtkTreePath *path;
829
830   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
831   g_return_if_fail (selection->tree_view != NULL);
832   g_return_if_fail (selection->tree_view->priv->model != NULL);
833   g_return_if_fail (iter != NULL);
834
835   path = gtk_tree_model_get_path (selection->tree_view->priv->model,
836                                   iter);
837
838   if (path == NULL)
839     return;
840
841   gtk_tree_selection_select_path (selection, path);
842   gtk_tree_path_free (path);
843 }
844
845
846 /**
847  * gtk_tree_selection_unselect_iter:
848  * @selection: A #GtkTreeSelection.
849  * @iter: The #GtkTreeIter to be unselected.
850  *
851  * Unselects the specified iterator.
852  **/
853 void
854 gtk_tree_selection_unselect_iter (GtkTreeSelection *selection,
855                                   GtkTreeIter      *iter)
856 {
857   GtkTreePath *path;
858
859   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
860   g_return_if_fail (selection->tree_view != NULL);
861   g_return_if_fail (selection->tree_view->priv->model != NULL);
862   g_return_if_fail (iter != NULL);
863
864   path = gtk_tree_model_get_path (selection->tree_view->priv->model,
865                                   iter);
866
867   if (path == NULL)
868     return;
869
870   gtk_tree_selection_unselect_path (selection, path);
871   gtk_tree_path_free (path);
872 }
873
874 /**
875  * gtk_tree_selection_path_is_selected:
876  * @selection: A #GtkTreeSelection.
877  * @path: A #GtkTreePath to check selection on.
878  * 
879  * Returns %TRUE if the row pointed to by @path is currently selected.  If @path
880  * does not point to a valid location, %FALSE is returned
881  * 
882  * Return value: %TRUE if @path is selected.
883  **/
884 gboolean
885 gtk_tree_selection_path_is_selected (GtkTreeSelection *selection,
886                                      GtkTreePath      *path)
887 {
888   GtkRBNode *node;
889   GtkRBTree *tree;
890   gboolean ret;
891
892   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
893   g_return_val_if_fail (path != NULL, FALSE);
894   g_return_val_if_fail (selection->tree_view != NULL, FALSE);
895
896   if (selection->tree_view->priv->model == NULL)
897     return FALSE;
898
899   ret = _gtk_tree_view_find_node (selection->tree_view,
900                                   path,
901                                   &tree,
902                                   &node);
903
904   if ((node == NULL) || !GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) ||
905       ret == TRUE)
906     return FALSE;
907
908   return TRUE;
909 }
910
911 /**
912  * gtk_tree_selection_iter_is_selected:
913  * @selection: A #GtkTreeSelection
914  * @iter: A valid #GtkTreeIter
915  * 
916  * Returns %TRUE if the row at @iter is currently selected.
917  * 
918  * Return value: %TRUE, if @iter is selected
919  **/
920 gboolean
921 gtk_tree_selection_iter_is_selected (GtkTreeSelection *selection,
922                                      GtkTreeIter      *iter)
923 {
924   GtkTreePath *path;
925   gboolean retval;
926
927   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
928   g_return_val_if_fail (iter != NULL, FALSE);
929   g_return_val_if_fail (selection->tree_view != NULL, FALSE);
930   g_return_val_if_fail (selection->tree_view->priv->model != NULL, FALSE);
931
932   path = gtk_tree_model_get_path (selection->tree_view->priv->model, iter);
933   if (path == NULL)
934     return FALSE;
935
936   retval = gtk_tree_selection_path_is_selected (selection, path);
937   gtk_tree_path_free (path);
938
939   return retval;
940 }
941
942
943 /* Wish I was in python, right now... */
944 struct _TempTuple {
945   GtkTreeSelection *selection;
946   gint dirty;
947 };
948
949 static void
950 select_all_helper (GtkRBTree  *tree,
951                    GtkRBNode  *node,
952                    gpointer    data)
953 {
954   struct _TempTuple *tuple = data;
955
956   if (node->children)
957     _gtk_rbtree_traverse (node->children,
958                           node->children->root,
959                           G_PRE_ORDER,
960                           select_all_helper,
961                           data);
962   if (!GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
963     {
964       tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, TRUE) || tuple->dirty;
965     }
966 }
967
968
969 /* We have a real_{un,}select_all function that doesn't emit the signal, so we
970  * can use it in other places without fear of the signal being emitted.
971  */
972 static gint
973 gtk_tree_selection_real_select_all (GtkTreeSelection *selection)
974 {
975   struct _TempTuple *tuple;
976
977   if (selection->tree_view->priv->tree == NULL)
978     return FALSE;
979
980   /* Mark all nodes selected */
981   tuple = g_new (struct _TempTuple, 1);
982   tuple->selection = selection;
983   tuple->dirty = FALSE;
984
985   _gtk_rbtree_traverse (selection->tree_view->priv->tree,
986                         selection->tree_view->priv->tree->root,
987                         G_PRE_ORDER,
988                         select_all_helper,
989                         tuple);
990   if (tuple->dirty)
991     {
992       g_free (tuple);
993       return TRUE;
994     }
995   g_free (tuple);
996   return FALSE;
997 }
998
999 /**
1000  * gtk_tree_selection_select_all:
1001  * @selection: A #GtkTreeSelection.
1002  *
1003  * Selects all the nodes. @selection must be set to #GTK_SELECTION_MULTIPLE
1004  * mode.
1005  **/
1006 void
1007 gtk_tree_selection_select_all (GtkTreeSelection *selection)
1008 {
1009   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
1010   g_return_if_fail (selection->tree_view != NULL);
1011
1012   if (selection->tree_view->priv->tree == NULL || selection->tree_view->priv->model == NULL)
1013     return;
1014
1015   g_return_if_fail (selection->type == GTK_SELECTION_MULTIPLE);
1016
1017   if (gtk_tree_selection_real_select_all (selection))
1018     g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
1019 }
1020
1021 static void
1022 unselect_all_helper (GtkRBTree  *tree,
1023                      GtkRBNode  *node,
1024                      gpointer    data)
1025 {
1026   struct _TempTuple *tuple = data;
1027
1028   if (node->children)
1029     _gtk_rbtree_traverse (node->children,
1030                           node->children->root,
1031                           G_PRE_ORDER,
1032                           unselect_all_helper,
1033                           data);
1034   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
1035     {
1036       tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, FALSE) || tuple->dirty;
1037     }
1038 }
1039
1040 static gint
1041 gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection)
1042 {
1043   struct _TempTuple *tuple;
1044
1045   if (selection->type == GTK_SELECTION_SINGLE ||
1046       selection->type == GTK_SELECTION_BROWSE)
1047     {
1048       GtkRBTree *tree = NULL;
1049       GtkRBNode *node = NULL;
1050       GtkTreePath *anchor_path;
1051
1052       if (selection->tree_view->priv->anchor == NULL)
1053         return FALSE;
1054
1055       anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
1056
1057       if (anchor_path == NULL)
1058         return FALSE;
1059
1060       _gtk_tree_view_find_node (selection->tree_view,
1061                                 anchor_path,
1062                                 &tree,
1063                                 &node);
1064
1065       gtk_tree_path_free (anchor_path);
1066
1067       if (tree == NULL)
1068         return FALSE;
1069
1070       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
1071         {
1072           if (gtk_tree_selection_real_select_node (selection, tree, node, FALSE))
1073             {
1074               gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1075               selection->tree_view->priv->anchor = NULL;
1076               return TRUE;
1077             }
1078         }
1079       return FALSE;
1080     }
1081   else
1082     {
1083       tuple = g_new (struct _TempTuple, 1);
1084       tuple->selection = selection;
1085       tuple->dirty = FALSE;
1086
1087       _gtk_rbtree_traverse (selection->tree_view->priv->tree,
1088                             selection->tree_view->priv->tree->root,
1089                             G_PRE_ORDER,
1090                             unselect_all_helper,
1091                             tuple);
1092
1093       if (tuple->dirty)
1094         {
1095           g_free (tuple);
1096           return TRUE;
1097         }
1098       g_free (tuple);
1099       return FALSE;
1100     }
1101 }
1102
1103 /**
1104  * gtk_tree_selection_unselect_all:
1105  * @selection: A #GtkTreeSelection.
1106  *
1107  * Unselects all the nodes.
1108  **/
1109 void
1110 gtk_tree_selection_unselect_all (GtkTreeSelection *selection)
1111 {
1112   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
1113   g_return_if_fail (selection->tree_view != NULL);
1114
1115   if (selection->tree_view->priv->tree == NULL || selection->tree_view->priv->model == NULL)
1116     return;
1117   
1118   if (gtk_tree_selection_real_unselect_all (selection))
1119     g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
1120 }
1121
1122 enum
1123 {
1124   RANGE_SELECT,
1125   RANGE_UNSELECT
1126 };
1127
1128 static gint
1129 gtk_tree_selection_real_modify_range (GtkTreeSelection *selection,
1130                                       gint              mode,
1131                                       GtkTreePath      *start_path,
1132                                       GtkTreePath      *end_path)
1133 {
1134   GtkRBNode *start_node, *end_node;
1135   GtkRBTree *start_tree, *end_tree;
1136   GtkTreePath *anchor_path = NULL;
1137   gboolean dirty = FALSE;
1138
1139   switch (gtk_tree_path_compare (start_path, end_path))
1140     {
1141     case 1:
1142       _gtk_tree_view_find_node (selection->tree_view,
1143                                 end_path,
1144                                 &start_tree,
1145                                 &start_node);
1146       _gtk_tree_view_find_node (selection->tree_view,
1147                                 start_path,
1148                                 &end_tree,
1149                                 &end_node);
1150       anchor_path = start_path;
1151       break;
1152     case 0:
1153       _gtk_tree_view_find_node (selection->tree_view,
1154                                 start_path,
1155                                 &start_tree,
1156                                 &start_node);
1157       end_tree = start_tree;
1158       end_node = start_node;
1159       anchor_path = start_path;
1160       break;
1161     case -1:
1162       _gtk_tree_view_find_node (selection->tree_view,
1163                                 start_path,
1164                                 &start_tree,
1165                                 &start_node);
1166       _gtk_tree_view_find_node (selection->tree_view,
1167                                 end_path,
1168                                 &end_tree,
1169                                 &end_node);
1170       anchor_path = start_path;
1171       break;
1172     }
1173
1174   g_return_val_if_fail (start_node != NULL, FALSE);
1175   g_return_val_if_fail (end_node != NULL, FALSE);
1176
1177   if (anchor_path)
1178     {
1179       if (selection->tree_view->priv->anchor)
1180         gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1181
1182       selection->tree_view->priv->anchor =
1183         gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view),
1184                                           selection->tree_view->priv->model,
1185                                           anchor_path);
1186     }
1187
1188   do
1189     {
1190       dirty |= gtk_tree_selection_real_select_node (selection, start_tree, start_node, (mode == RANGE_SELECT)?TRUE:FALSE);
1191
1192       if (start_node == end_node)
1193         break;
1194
1195       if (start_node->children)
1196         {
1197           start_tree = start_node->children;
1198           start_node = start_tree->root;
1199           while (start_node->left != start_tree->nil)
1200             start_node = start_node->left;
1201         }
1202       else
1203         {
1204           _gtk_rbtree_next_full (start_tree, start_node, &start_tree, &start_node);
1205           if (start_tree == NULL)
1206             {
1207               /* we just ran out of tree.  That means someone passed in bogus values.
1208                */
1209               return dirty;
1210             }
1211         }
1212     }
1213   while (TRUE);
1214
1215   return dirty;
1216 }
1217
1218 /**
1219  * gtk_tree_selection_select_range:
1220  * @selection: A #GtkTreeSelection.
1221  * @start_path: The initial node of the range.
1222  * @end_path: The final node of the range.
1223  *
1224  * Selects a range of nodes, determined by @start_path and @end_path inclusive.
1225  * @selection must be set to #GTK_SELECTION_MULTIPLE mode. 
1226  **/
1227 void
1228 gtk_tree_selection_select_range (GtkTreeSelection *selection,
1229                                  GtkTreePath      *start_path,
1230                                  GtkTreePath      *end_path)
1231 {
1232   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
1233   g_return_if_fail (selection->tree_view != NULL);
1234   g_return_if_fail (selection->type == GTK_SELECTION_MULTIPLE);
1235   g_return_if_fail (selection->tree_view->priv->model != NULL);
1236
1237   if (gtk_tree_selection_real_modify_range (selection, RANGE_SELECT, start_path, end_path))
1238     g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
1239 }
1240
1241 /**
1242  * gtk_tree_selection_unselect_range:
1243  * @selection: A #GtkTreeSelection.
1244  * @start_path: The initial node of the range.
1245  * @end_path: The initial node of the range.
1246  *
1247  * Unselects a range of nodes, determined by @start_path and @end_path
1248  * inclusive.
1249  *
1250  * Since: 2.2
1251  **/
1252 void
1253 gtk_tree_selection_unselect_range (GtkTreeSelection *selection,
1254                                    GtkTreePath      *start_path,
1255                                    GtkTreePath      *end_path)
1256 {
1257   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
1258   g_return_if_fail (selection->tree_view != NULL);
1259   g_return_if_fail (selection->tree_view->priv->model != NULL);
1260
1261   if (gtk_tree_selection_real_modify_range (selection, RANGE_UNSELECT, start_path, end_path))
1262     g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
1263 }
1264
1265 static gboolean
1266 tree_column_is_sensitive (GtkTreeViewColumn *column,
1267                           GtkTreeModel      *model,
1268                           GtkTreeIter       *iter)
1269 {
1270   GList *cells, *list;
1271   gboolean sensitive;
1272   gboolean visible;
1273
1274   gtk_tree_view_column_cell_set_cell_data (column, model,
1275                                            iter, FALSE, FALSE);
1276
1277   cells = gtk_tree_view_column_get_cell_renderers (column);
1278
1279   list = cells;
1280   while (list)
1281     {
1282       g_object_get (list->data,
1283                     "sensitive", &sensitive,
1284                     "visible", &visible,
1285                     NULL);
1286       
1287       if (visible && sensitive)
1288         break;
1289
1290       list = list->next;
1291     }
1292   g_list_free (cells);
1293
1294   return sensitive;
1295 }
1296
1297 static gboolean
1298 row_is_selectable (GtkTreeSelection *selection,
1299                    GtkRBNode        *node,
1300                    GtkTreePath      *path)
1301 {
1302   GList *list;
1303   GtkTreeIter iter;
1304   gboolean sensitive = FALSE;
1305
1306   if (!gtk_tree_model_get_iter (selection->tree_view->priv->model, &iter, path))
1307     sensitive = TRUE;
1308
1309   if (!sensitive && selection->tree_view->priv->row_separator_func)
1310     {
1311       /* never allow separators to be selected */
1312       if ((* selection->tree_view->priv->row_separator_func) (selection->tree_view->priv->model,
1313                                                               &iter,
1314                                                               selection->tree_view->priv->row_separator_data))
1315         return FALSE;
1316     }
1317
1318   for (list = selection->tree_view->priv->columns; list && !sensitive; list = list->next)
1319     {
1320       GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (list->data);
1321
1322       if (!column->visible)
1323         continue;
1324
1325       sensitive = tree_column_is_sensitive (column, selection->tree_view->priv->model, &iter);
1326     }
1327
1328   if (!sensitive)
1329     return FALSE;
1330
1331   if (selection->user_func)
1332     return (*selection->user_func) (selection, selection->tree_view->priv->model, path,
1333                                     GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED),
1334                                     selection->user_data);
1335   else
1336     return TRUE;
1337 }
1338
1339
1340 /* Called internally by gtktreeview.c It handles actually selecting the tree.
1341  */
1342
1343 /*
1344  * docs about the 'override_browse_mode', we set this flag when we want to
1345  * unset select the node and override the select browse mode behaviour (that is
1346  * 'one node should *always* be selected').
1347  */
1348 void
1349 _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection,
1350                                           GtkRBNode        *node,
1351                                           GtkRBTree        *tree,
1352                                           GtkTreePath      *path,
1353                                           GtkTreeSelectMode mode,
1354                                           gboolean          override_browse_mode)
1355 {
1356   gint flags;
1357   gint dirty = FALSE;
1358   GtkTreePath *anchor_path = NULL;
1359
1360   if (selection->type == GTK_SELECTION_NONE)
1361     return;
1362
1363   if (selection->tree_view->priv->anchor)
1364     anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
1365
1366   if (selection->type == GTK_SELECTION_SINGLE ||
1367       selection->type == GTK_SELECTION_BROWSE)
1368     {
1369       /* just unselect */
1370       if (selection->type == GTK_SELECTION_BROWSE && override_browse_mode)
1371         {
1372           dirty = gtk_tree_selection_real_unselect_all (selection);
1373         }
1374       /* Did we try to select the same node again? */
1375       else if (selection->type == GTK_SELECTION_SINGLE &&
1376                anchor_path && gtk_tree_path_compare (path, anchor_path) == 0)
1377         {
1378           if ((mode & GTK_TREE_SELECT_MODE_TOGGLE) == GTK_TREE_SELECT_MODE_TOGGLE)
1379             {
1380               dirty = gtk_tree_selection_real_unselect_all (selection);
1381             }
1382         }
1383       else
1384         {
1385           if (anchor_path)
1386             {
1387               /* We only want to select the new node if we can unselect the old one,
1388                * and we can select the new one. */
1389               dirty = row_is_selectable (selection, node, path);
1390
1391               /* if dirty is FALSE, we weren't able to select the new one, otherwise, we try to
1392                * unselect the new one
1393                */
1394               if (dirty)
1395                 dirty = gtk_tree_selection_real_unselect_all (selection);
1396
1397               /* if dirty is TRUE at this point, we successfully unselected the
1398                * old one, and can then select the new one */
1399               if (dirty)
1400                 {
1401                   if (selection->tree_view->priv->anchor)
1402                     {
1403                       gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1404                       selection->tree_view->priv->anchor = NULL;
1405                     }
1406
1407                   if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE))
1408                     {
1409                       selection->tree_view->priv->anchor =
1410                         gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1411                     }
1412                 }
1413             }
1414           else
1415             {
1416               if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE))
1417                 {
1418                   dirty = TRUE;
1419                   if (selection->tree_view->priv->anchor)
1420                     gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1421
1422                   selection->tree_view->priv->anchor =
1423                     gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1424                 }
1425             }
1426         }
1427     }
1428   else if (selection->type == GTK_SELECTION_MULTIPLE)
1429     {
1430       if ((mode & GTK_TREE_SELECT_MODE_EXTEND) == GTK_TREE_SELECT_MODE_EXTEND
1431           && (anchor_path == NULL))
1432         {
1433           if (selection->tree_view->priv->anchor)
1434             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1435
1436           selection->tree_view->priv->anchor =
1437             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1438           dirty = gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
1439         }
1440       else if ((mode & (GTK_TREE_SELECT_MODE_EXTEND | GTK_TREE_SELECT_MODE_TOGGLE)) == (GTK_TREE_SELECT_MODE_EXTEND | GTK_TREE_SELECT_MODE_TOGGLE))
1441         {
1442           gtk_tree_selection_select_range (selection,
1443                                            anchor_path,
1444                                            path);
1445         }
1446       else if ((mode & GTK_TREE_SELECT_MODE_TOGGLE) == GTK_TREE_SELECT_MODE_TOGGLE)
1447         {
1448           flags = node->flags;
1449           if (selection->tree_view->priv->anchor)
1450             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1451
1452           selection->tree_view->priv->anchor =
1453             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1454
1455           if ((flags & GTK_RBNODE_IS_SELECTED) == GTK_RBNODE_IS_SELECTED)
1456             dirty |= gtk_tree_selection_real_select_node (selection, tree, node, FALSE);
1457           else
1458             dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
1459         }
1460       else if ((mode & GTK_TREE_SELECT_MODE_EXTEND) == GTK_TREE_SELECT_MODE_EXTEND)
1461         {
1462           dirty = gtk_tree_selection_real_unselect_all (selection);
1463           dirty |= gtk_tree_selection_real_modify_range (selection,
1464                                                          RANGE_SELECT,
1465                                                          anchor_path,
1466                                                          path);
1467         }
1468       else
1469         {
1470           dirty = gtk_tree_selection_real_unselect_all (selection);
1471
1472           if (selection->tree_view->priv->anchor)
1473             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1474
1475           selection->tree_view->priv->anchor =
1476             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1477
1478           dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
1479         }
1480     }
1481
1482   if (anchor_path)
1483     gtk_tree_path_free (anchor_path);
1484
1485   if (dirty)
1486     g_signal_emit (selection, tree_selection_signals[CHANGED], 0);  
1487 }
1488
1489
1490 void 
1491 _gtk_tree_selection_emit_changed (GtkTreeSelection *selection)
1492 {
1493   g_signal_emit (selection, tree_selection_signals[CHANGED], 0);  
1494 }
1495
1496 /* NOTE: Any {un,}selection ever done _MUST_ be done through this function!
1497  */
1498
1499 static gint
1500 gtk_tree_selection_real_select_node (GtkTreeSelection *selection,
1501                                      GtkRBTree        *tree,
1502                                      GtkRBNode        *node,
1503                                      gboolean          select)
1504 {
1505   gboolean selected = FALSE;
1506   GtkTreePath *path = NULL;
1507
1508   select = !! select;
1509
1510   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) != select)
1511     {
1512       path = _gtk_tree_view_find_path (selection->tree_view, tree, node);
1513       selected = row_is_selectable (selection, node, path);
1514       gtk_tree_path_free (path);
1515     }
1516
1517   if (selected == TRUE)
1518     {
1519       node->flags ^= GTK_RBNODE_IS_SELECTED;
1520
1521       _gtk_tree_view_queue_draw_node (selection->tree_view, tree, node, NULL);
1522       
1523       return TRUE;
1524     }
1525
1526   return FALSE;
1527 }
1528
1529 #define __GTK_TREE_SELECTION_C__
1530 #include "gtkaliasdef.c"