]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeselection.c
Patch from Matthias Clasen to remove remove all instances of
[~andy/gtk] / gtk / gtktreeselection.c
1 /* gtktreeselection.h
2  * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "gtktreeselection.h"
21 #include "gtktreeprivate.h"
22 #include "gtkrbtree.h"
23 #include "gtksignal.h"
24
25 static void gtk_tree_selection_init              (GtkTreeSelection      *selection);
26 static void gtk_tree_selection_class_init        (GtkTreeSelectionClass *class);
27
28 static void gtk_tree_selection_finalize          (GObject               *object);
29 static gint gtk_tree_selection_real_select_all   (GtkTreeSelection      *selection);
30 static gint gtk_tree_selection_real_unselect_all (GtkTreeSelection      *selection);
31 static gint gtk_tree_selection_real_select_node  (GtkTreeSelection      *selection,
32                                                   GtkRBTree             *tree,
33                                                   GtkRBNode             *node,
34                                                   gboolean               select);
35
36 enum
37 {
38   CHANGED,
39   LAST_SIGNAL
40 };
41
42 static GObjectClass *parent_class = NULL;
43 static guint tree_selection_signals[LAST_SIGNAL] = { 0 };
44
45 GtkType
46 gtk_tree_selection_get_type (void)
47 {
48   static GtkType selection_type = 0;
49
50   if (!selection_type)
51     {
52       static const GTypeInfo selection_info =
53       {
54         sizeof (GtkTreeSelectionClass),
55         NULL,           /* base_init */
56         NULL,           /* base_finalize */
57         (GClassInitFunc) gtk_tree_selection_class_init,
58         NULL,           /* class_finalize */
59         NULL,           /* class_data */
60         sizeof (GtkTreeSelection),
61         0,              /* n_preallocs */
62         (GInstanceInitFunc) gtk_tree_selection_init
63       };
64
65       selection_type = g_type_register_static (G_TYPE_OBJECT, "GtkTreeSelection", &selection_info, 0);
66     }
67
68   return selection_type;
69 }
70
71 static void
72 gtk_tree_selection_class_init (GtkTreeSelectionClass *class)
73 {
74   GObjectClass *object_class;
75
76   object_class = (GObjectClass*) class;
77   parent_class = g_type_class_peek_parent (class);
78
79   object_class->finalize = gtk_tree_selection_finalize;
80   class->changed = NULL;
81
82   tree_selection_signals[CHANGED] =
83     gtk_signal_new ("changed",
84                     GTK_RUN_FIRST,
85                     GTK_CLASS_TYPE (object_class),
86                     GTK_SIGNAL_OFFSET (GtkTreeSelectionClass, changed),
87                     gtk_marshal_VOID__VOID,
88                     GTK_TYPE_NONE, 0);
89 }
90
91 static void
92 gtk_tree_selection_init (GtkTreeSelection *selection)
93 {
94   selection->type = GTK_TREE_SELECTION_SINGLE;
95 }
96
97 static void
98 gtk_tree_selection_finalize (GObject *object)
99 {
100   if (GTK_TREE_SELECTION (object)->destroy)
101     (* GTK_TREE_SELECTION (object)->destroy) (GTK_TREE_SELECTION (object)->user_data);
102 }
103
104 /**
105  * _gtk_tree_selection_new:
106  *
107  * Creates a new #GtkTreeSelection object.  This function should not be invoked,
108  * as each #GtkTreeView will create it's own #GtkTreeSelection.
109  *
110  * Return value: A newly created #GtkTreeSelection object.
111  **/
112 GtkTreeSelection*
113 _gtk_tree_selection_new (void)
114 {
115   GtkTreeSelection *selection;
116
117   selection = GTK_TREE_SELECTION (g_object_new (GTK_TYPE_TREE_SELECTION, NULL));
118
119   return selection;
120 }
121
122 /**
123  * _gtk_tree_selection_new_with_tree_view:
124  * @tree_view: The #GtkTreeView.
125  *
126  * Creates a new #GtkTreeSelection object.  This function should not be invoked,
127  * as each #GtkTreeView will create it's own #GtkTreeSelection.
128  *
129  * Return value: A newly created #GtkTreeSelection object.
130  **/
131 GtkTreeSelection*
132 _gtk_tree_selection_new_with_tree_view (GtkTreeView *tree_view)
133 {
134   GtkTreeSelection *selection;
135
136   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
137
138   selection = _gtk_tree_selection_new ();
139   _gtk_tree_selection_set_tree_view (selection, tree_view);
140
141   return selection;
142 }
143
144 /**
145  * _gtk_tree_selection_set_tree_view:
146  * @selection: A #GtkTreeSelection.
147  * @tree_view: The #GtkTreeView.
148  *
149  * Sets the #GtkTreeView of @selection.  This function should not be invoked, as
150  * it is used internally by #GtkTreeView.
151  **/
152 void
153 _gtk_tree_selection_set_tree_view (GtkTreeSelection *selection,
154                                    GtkTreeView      *tree_view)
155 {
156   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
157   if (tree_view != NULL)
158     g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
159
160   selection->tree_view = tree_view;
161 }
162
163 /**
164  * gtk_tree_selection_set_mode:
165  * @selection: A #GtkTreeSelection.
166  * @type: The selection mode
167  *
168  * Sets the selection mode of the @selection.  If the previous type was
169  * #GTK_TREE_SELECTION_MULTI and @type is #GTK_TREE_SELECTION_SINGLE, then
170  * the anchor is kept selected, if it was previously selected.
171  **/
172 void
173 gtk_tree_selection_set_mode (GtkTreeSelection     *selection,
174                              GtkTreeSelectionMode  type)
175 {
176   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
177
178   if (selection->type == type)
179     return;
180
181   if (type == GTK_TREE_SELECTION_SINGLE)
182     {
183       GtkRBTree *tree = NULL;
184       GtkRBNode *node = NULL;
185       gint selected = FALSE;
186
187       if (selection->tree_view->priv->anchor)
188         {
189           GtkTreePath *anchor_path;
190
191           anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
192
193           if (anchor_path)
194             {
195               _gtk_tree_view_find_node (selection->tree_view,
196                                         anchor_path,
197                                         &tree,
198                                         &node);
199
200               if (node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
201                 selected = TRUE;
202
203               gtk_tree_path_free (anchor_path);
204             }
205         }
206       /* FIXME: if user_func is set, then it needs to unconditionally unselect
207        * all.
208        */
209       gtk_tree_selection_unselect_all (selection);
210
211       /* FIXME are we properly emitting the selection_changed signal here? */
212       if (node && selected)
213         GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SELECTED);
214     }
215   selection->type = type;
216 }
217
218 /**
219  * gtk_tree_selection_get_mode:
220  * @selection: a #GtkTreeSelection
221  *
222  * Gets the selection mode for @selection. See
223  * gtk_tree_selection_set_mode().
224  *
225  * Return value: the current selection mode
226  **/
227 GtkTreeSelectionMode
228 gtk_tree_selection_get_mode (GtkTreeSelection *selection)
229 {
230   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), GTK_TREE_SELECTION_SINGLE);
231
232   return selection->type;
233 }
234
235 /**
236  * gtk_tree_selection_set_select_function:
237  * @selection: A #GtkTreeSelection.
238  * @func: The selection function.
239  * @data: The selection function's data.
240  * @destroy: The destroy function for user data.  May be NULL.
241  *
242  * Sets the selection function.  If set, this function is called before any node
243  * is selected or unselected, giving some control over which nodes are selected.
244  **/
245 void
246 gtk_tree_selection_set_select_function (GtkTreeSelection     *selection,
247                                         GtkTreeSelectionFunc  func,
248                                         gpointer              data,
249                                         GtkDestroyNotify      destroy)
250 {
251   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
252   g_return_if_fail (func != NULL);
253
254   selection->user_func = func;
255   selection->user_data = data;
256   selection->destroy = destroy;
257 }
258
259 /**
260  * gtk_tree_selection_get_user_data:
261  * @selection: A #GtkTreeSelection.
262  *
263  * Returns the user data for the selection function.
264  *
265  * Return value: The user data.
266  **/
267 gpointer
268 gtk_tree_selection_get_user_data (GtkTreeSelection *selection)
269 {
270   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
271
272   return selection->user_data;
273 }
274
275 GtkTreeView*
276 gtk_tree_selection_get_tree_view (GtkTreeSelection *selection)
277 {
278   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
279
280   return selection->tree_view;
281 }
282
283 /**
284  * gtk_tree_selection_get_selected:
285  * @selection: A #GtkTreeSelection.
286  * @model: A pointer set to the #GtkTreeModel, or NULL.
287  * @iter: The #GtkTreeIter, or NULL.
288  *
289  * Sets @iter to the currently selected node if @selection is set to
290  * #GTK_TREE_SELECTION_SINGLE.  @iter may be NULL if you just want to test if
291  * @selection has any selected nodes.  @model is filled with the current model
292  * as a convenience.  This function will not work if you use @selection is
293  * #GTK_TREE_SELECTION_MULTI.
294  *
295  * Return value: TRUE, if there is a selected node.
296  **/
297 gboolean
298 gtk_tree_selection_get_selected (GtkTreeSelection  *selection,
299                                  GtkTreeModel     **model,
300                                  GtkTreeIter       *iter)
301 {
302   GtkRBTree *tree;
303   GtkRBNode *node;
304   GtkTreePath *anchor_path;
305   gboolean retval;
306
307   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
308   g_return_val_if_fail (selection->type == GTK_TREE_SELECTION_SINGLE, FALSE);
309   g_return_val_if_fail (selection->tree_view != NULL, FALSE);
310   g_return_val_if_fail (selection->tree_view->priv->model != NULL, FALSE);
311
312   if (model)
313     *model = selection->tree_view->priv->model;
314
315   if (selection->tree_view->priv->anchor == NULL)
316     return FALSE;
317
318   anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
319
320   if (anchor_path == NULL)
321     return FALSE;
322
323   if (iter == NULL)
324     {
325       gtk_tree_path_free (anchor_path);
326       return TRUE;
327     }
328
329   retval = FALSE;
330
331   if (!_gtk_tree_view_find_node (selection->tree_view,
332                                  anchor_path,
333                                  &tree,
334                                  &node) &&
335       ! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
336     {
337       /* We don't want to return the anchor if it isn't actually selected.
338        */
339       retval = FALSE;
340     }
341   else
342     {
343       retval = gtk_tree_model_get_iter (selection->tree_view->priv->model,
344                                         iter,
345                                         anchor_path);
346     }
347
348   gtk_tree_path_free (anchor_path);
349
350   return retval;
351 }
352
353 /**
354  * gtk_tree_selection_selected_foreach:
355  * @selection: A #GtkTreeSelection.
356  * @func: The function to call for each selected node.
357  * @data: user data to pass to the function.
358  *
359  * Calls a function for each selected node.
360  **/
361 void
362 gtk_tree_selection_selected_foreach (GtkTreeSelection            *selection,
363                                      GtkTreeSelectionForeachFunc  func,
364                                      gpointer                     data)
365 {
366   GtkTreePath *path;
367   GtkRBTree *tree;
368   GtkRBNode *node;
369   GtkTreeIter iter;
370
371   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
372   g_return_if_fail (selection->tree_view != NULL);
373   g_return_if_fail (selection->tree_view->priv->model != NULL);
374
375   if (func == NULL ||
376       selection->tree_view->priv->tree == NULL ||
377       selection->tree_view->priv->tree->root == NULL)
378     return;
379
380   if (selection->type == GTK_TREE_SELECTION_SINGLE)
381     {
382       if (gtk_tree_row_reference_valid (selection->tree_view->priv->anchor))
383         {
384           path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
385           gtk_tree_model_get_iter (selection->tree_view->priv->model, &iter, path);
386           (* func) (selection->tree_view->priv->model, path, &iter, data);
387           gtk_tree_path_free (path);
388         }
389       return;
390     }
391
392   tree = selection->tree_view->priv->tree;
393   node = selection->tree_view->priv->tree->root;
394   
395   while (node->left != tree->nil)
396     node = node->left;
397
398   /* find the node internally */
399   path = gtk_tree_path_new_root ();
400   gtk_tree_model_get_iter (selection->tree_view->priv->model,
401                            &iter, path);
402
403   do
404     {
405       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
406         (* func) (selection->tree_view->priv->model, path, &iter, data);
407       if (node->children)
408         {
409           gboolean has_child;
410           GtkTreeIter tmp;
411
412           tree = node->children;
413           node = tree->root;
414           while (node->left != tree->nil)
415             node = node->left;
416           tmp = iter;
417           has_child = gtk_tree_model_iter_children (selection->tree_view->priv->model, &iter, &tmp);
418           gtk_tree_path_append_index (path, 0);
419           /* Sanity Check! */
420           TREE_VIEW_INTERNAL_ASSERT_VOID (has_child);
421         }
422       else
423         {
424           gboolean done = FALSE;
425           do
426             {
427               node = _gtk_rbtree_next (tree, node);
428               if (node != NULL)
429                 {
430                   gboolean has_next;
431
432                   has_next = gtk_tree_model_iter_next (selection->tree_view->priv->model, &iter);
433                   done = TRUE;
434                   gtk_tree_path_next (path);
435
436                   /* Sanity Check! */
437                   TREE_VIEW_INTERNAL_ASSERT_VOID (has_next);
438                 }
439               else
440                 {
441                   gboolean has_parent;
442                   GtkTreeIter tmp_iter = iter;
443
444                   node = tree->parent_node;
445                   tree = tree->parent_tree;
446                   if (tree == NULL)
447                     {
448                       gtk_tree_path_free (path);
449                       /* we've run out of tree */
450                       /* We're done with this function */
451                       return;
452                     }
453                   has_parent = gtk_tree_model_iter_parent (selection->tree_view->priv->model, &iter, &tmp_iter);
454                   gtk_tree_path_up (path);
455                   /* Sanity check */
456                   TREE_VIEW_INTERNAL_ASSERT_VOID (has_parent);
457                 }
458             }
459           while (!done);
460         }
461     }
462   while (TRUE);
463 }
464
465 /**
466  * gtk_tree_selection_select_path:
467  * @selection: A #GtkTreeSelection.
468  * @path: The #GtkTreePath to be selected.
469  *
470  * Select the row at @path.
471  **/
472 void
473 gtk_tree_selection_select_path (GtkTreeSelection *selection,
474                                 GtkTreePath      *path)
475 {
476   GtkRBNode *node;
477   GtkRBTree *tree;
478   GdkModifierType state = 0;
479
480   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
481   g_return_if_fail (selection->tree_view != NULL);
482   g_return_if_fail (path != NULL);
483
484   _gtk_tree_view_find_node (selection->tree_view,
485                             path,
486                             &tree,
487                             &node);
488
489   if (node == NULL || GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
490     return;
491
492   if (selection->type == GTK_TREE_SELECTION_MULTI)
493     state = GDK_CONTROL_MASK;
494
495   _gtk_tree_selection_internal_select_node (selection,
496                                             node,
497                                             tree,
498                                             path,
499                                             state);
500 }
501
502 /**
503  * gtk_tree_selection_unselect_path:
504  * @selection: A #GtkTreeSelection.
505  * @path: The #GtkTreePath to be unselected.
506  *
507  * Unselects the row at @path.
508  **/
509 void
510 gtk_tree_selection_unselect_path (GtkTreeSelection *selection,
511                                   GtkTreePath      *path)
512 {
513   GtkRBNode *node;
514   GtkRBTree *tree;
515
516   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
517   g_return_if_fail (selection->tree_view != NULL);
518   g_return_if_fail (path != NULL);
519
520   _gtk_tree_view_find_node (selection->tree_view,
521                             path,
522                             &tree,
523                             &node);
524
525   if (node == NULL || !GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
526     return;
527
528   _gtk_tree_selection_internal_select_node (selection,
529                                             node,
530                                             tree,
531                                             path,
532                                             GDK_CONTROL_MASK);
533 }
534
535 /**
536  * gtk_tree_selection_select_iter:
537  * @selection: A #GtkTreeSelection.
538  * @iter: The #GtkTreeIter to be selected.
539  *
540  * Selects the specified iterator.
541  **/
542 void
543 gtk_tree_selection_select_iter (GtkTreeSelection *selection,
544                                 GtkTreeIter      *iter)
545 {
546   GtkTreePath *path;
547
548   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
549   g_return_if_fail (selection->tree_view != NULL);
550   g_return_if_fail (selection->tree_view->priv->model != NULL);
551   g_return_if_fail (iter != NULL);
552
553   path = gtk_tree_model_get_path (selection->tree_view->priv->model,
554                                   iter);
555
556   if (path == NULL)
557     return;
558
559   gtk_tree_selection_select_path (selection, path);
560   gtk_tree_path_free (path);
561 }
562
563
564 /**
565  * gtk_tree_selection_unselect_iter:
566  * @selection: A #GtkTreeSelection.
567  * @iter: The #GtkTreeIter to be unselected.
568  *
569  * Unselects the specified iterator.
570  **/
571 void
572 gtk_tree_selection_unselect_iter (GtkTreeSelection *selection,
573                                   GtkTreeIter      *iter)
574 {
575   GtkTreePath *path;
576
577   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
578   g_return_if_fail (selection->tree_view != NULL);
579   g_return_if_fail (selection->tree_view->priv->model != NULL);
580   g_return_if_fail (iter != NULL);
581
582   path = gtk_tree_model_get_path (selection->tree_view->priv->model,
583                                   iter);
584
585   if (path == NULL)
586     return;
587
588   gtk_tree_selection_select_path (selection, path);
589   gtk_tree_path_free (path);
590 }
591
592 /* Wish I was in python, right now... */
593 struct _TempTuple {
594   GtkTreeSelection *selection;
595   gint dirty;
596 };
597
598 static void
599 select_all_helper (GtkRBTree  *tree,
600                    GtkRBNode  *node,
601                    gpointer    data)
602 {
603   struct _TempTuple *tuple = data;
604
605   if (node->children)
606     _gtk_rbtree_traverse (node->children,
607                           node->children->root,
608                           G_PRE_ORDER,
609                           select_all_helper,
610                           data);
611   if (!GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
612     {
613       tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, TRUE) || tuple->dirty;
614     }
615 }
616
617
618 /* We have a real_{un,}select_all function that doesn't emit the signal, so we
619  * can use it in other places without fear of the signal being emitted.
620  */
621 static gint
622 gtk_tree_selection_real_select_all (GtkTreeSelection *selection)
623 {
624   struct _TempTuple *tuple;
625
626   if (selection->tree_view->priv->tree == NULL)
627     return FALSE;
628
629   /* Mark all nodes selected */
630   tuple = g_new (struct _TempTuple, 1);
631   tuple->selection = selection;
632   tuple->dirty = FALSE;
633
634   _gtk_rbtree_traverse (selection->tree_view->priv->tree,
635                         selection->tree_view->priv->tree->root,
636                         G_PRE_ORDER,
637                         select_all_helper,
638                         tuple);
639   if (tuple->dirty)
640     {
641       g_free (tuple);
642       return TRUE;
643     }
644   g_free (tuple);
645   return FALSE;
646 }
647
648 /**
649  * gtk_tree_selection_select_all:
650  * @selection: A #GtkTreeSelection.
651  *
652  * Selects all the nodes.  @selection is must be set to
653  * #GTK_TREE_SELECTION_MULTI mode.
654  **/
655 void
656 gtk_tree_selection_select_all (GtkTreeSelection *selection)
657 {
658   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
659   g_return_if_fail (selection->tree_view != NULL);
660   g_return_if_fail (selection->tree_view->priv->tree != NULL);
661   g_return_if_fail (selection->type != GTK_TREE_SELECTION_MULTI);
662
663   if (gtk_tree_selection_real_select_all (selection))
664     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
665 }
666
667 static void
668 unselect_all_helper (GtkRBTree  *tree,
669                      GtkRBNode  *node,
670                      gpointer    data)
671 {
672   struct _TempTuple *tuple = data;
673
674   if (node->children)
675     _gtk_rbtree_traverse (node->children,
676                           node->children->root,
677                           G_PRE_ORDER,
678                           unselect_all_helper,
679                           data);
680   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
681     {
682       tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, FALSE) || tuple->dirty;
683     }
684 }
685
686 static gint
687 gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection)
688 {
689   struct _TempTuple *tuple;
690
691   if (selection->type == GTK_TREE_SELECTION_SINGLE)
692     {
693       GtkRBTree *tree = NULL;
694       GtkRBNode *node = NULL;
695       GtkTreePath *anchor_path;
696
697       if (selection->tree_view->priv->anchor == NULL)
698         return FALSE;
699
700       anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
701
702       if (anchor_path == NULL)
703         return FALSE;
704
705       _gtk_tree_view_find_node (selection->tree_view,
706                                 anchor_path,
707                                 &tree,
708                                 &node);
709
710       gtk_tree_path_free (anchor_path);
711
712       if (tree == NULL)
713         return FALSE;
714
715       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
716         {
717           if (gtk_tree_selection_real_select_node (selection, tree, node, FALSE))
718             {
719               gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
720               selection->tree_view->priv->anchor = NULL;
721               return TRUE;
722             }
723         }
724       return FALSE;
725     }
726   else
727     {
728       tuple = g_new (struct _TempTuple, 1);
729       tuple->selection = selection;
730       tuple->dirty = FALSE;
731
732       _gtk_rbtree_traverse (selection->tree_view->priv->tree,
733                             selection->tree_view->priv->tree->root,
734                             G_PRE_ORDER,
735                             unselect_all_helper,
736                             tuple);
737
738       if (tuple->dirty)
739         {
740           g_free (tuple);
741           return TRUE;
742         }
743       g_free (tuple);
744       return FALSE;
745     }
746 }
747
748 /**
749  * gtk_tree_selection_unselect_all:
750  * @selection: A #GtkTreeSelection.
751  *
752  * Unselects all the nodes.
753  **/
754 void
755 gtk_tree_selection_unselect_all (GtkTreeSelection *selection)
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 (selection->tree_view->priv->tree != NULL);
760   if (selection->tree_view->priv->tree == NULL)
761     return;
762
763   if (gtk_tree_selection_real_unselect_all (selection))
764     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
765 }
766
767 static gint
768 gtk_tree_selection_real_select_range (GtkTreeSelection *selection,
769                                       GtkTreePath      *start_path,
770                                       GtkTreePath      *end_path)
771 {
772   GtkRBNode *start_node, *end_node;
773   GtkRBTree *start_tree, *end_tree;
774   gboolean dirty = FALSE;
775
776   switch (gtk_tree_path_compare (start_path, end_path))
777     {
778     case 1:
779       _gtk_tree_view_find_node (selection->tree_view,
780                                 end_path,
781                                 &start_tree,
782                                 &start_node);
783       _gtk_tree_view_find_node (selection->tree_view,
784                                 start_path,
785                                 &end_tree,
786                                 &end_node);
787       break;
788     case 0:
789       _gtk_tree_view_find_node (selection->tree_view,
790                                 start_path,
791                                 &start_tree,
792                                 &start_node);
793       end_tree = start_tree;
794       end_node = start_node;
795       break;
796     case -1:
797       _gtk_tree_view_find_node (selection->tree_view,
798                                 start_path,
799                                 &start_tree,
800                                 &start_node);
801       _gtk_tree_view_find_node (selection->tree_view,
802                                 end_path,
803                                 &end_tree,
804                                 &end_node);
805       break;
806     }
807
808   g_return_val_if_fail (start_node != NULL, FALSE);
809   g_return_val_if_fail (end_node != NULL, FALSE);
810
811   do
812     {
813       if (GTK_RBNODE_FLAG_SET (start_node, GTK_RBNODE_IS_SELECTED))
814         {
815           dirty = gtk_tree_selection_real_select_node (selection, start_tree, start_node, FALSE);
816         }
817
818       if (start_node == end_node)
819         break;
820
821       if (start_node->children)
822         {
823           start_tree = start_node->children;
824           start_node = start_tree->root;
825           while (start_node->left != start_tree->nil)
826             start_node = start_node->left;
827         }
828       else
829         {
830           gboolean done = FALSE;
831           do
832             {
833               start_node = _gtk_rbtree_next (start_tree, start_node);
834               if (start_node != NULL)
835                 {
836                   done = TRUE;
837                 }
838               else
839                 {
840                   start_node = start_tree->parent_node;
841                   start_tree = start_tree->parent_tree;
842                   if (start_tree == NULL)
843                     /* FIXME should this really be silent, or should it g_warning? */
844                     /* we've run out of tree */
845                     /* This means we never found end node!! */
846                     break;
847                 }
848             }
849           while (!done);
850         }
851     }
852   while (TRUE);
853
854   return dirty;
855 }
856
857 /**
858  * gtk_tree_selection_select_range:
859  * @selection: A #GtkTreeSelection.
860  * @start_path: The initial node of the range.
861  * @end_path: The final node of the range.
862  *
863  * Selects a range of nodes, determined by @start_path and @end_path inclusive.
864  **/
865 void
866 gtk_tree_selection_select_range (GtkTreeSelection *selection,
867                                  GtkTreePath      *start_path,
868                                  GtkTreePath      *end_path)
869 {
870   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
871   g_return_if_fail (selection->tree_view != NULL);
872
873   if (gtk_tree_selection_real_select_range (selection, start_path, end_path))
874     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
875 }
876
877 /* Called internally by gtktreeview.c It handles actually selecting the tree.
878  */
879 void
880 _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection,
881                                           GtkRBNode        *node,
882                                           GtkRBTree        *tree,
883                                           GtkTreePath      *path,
884                                           GdkModifierType   state)
885 {
886   gint flags;
887   gint dirty = FALSE;
888   GtkTreePath *anchor_path = NULL;
889
890
891   if (selection->tree_view->priv->anchor)
892     anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
893
894   if (selection->type == GTK_TREE_SELECTION_SINGLE)
895     {
896       /* Did we try to select the same node again? */
897       if (anchor_path && gtk_tree_path_compare (path, anchor_path) == 0)
898         {
899           if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
900             {
901               dirty = gtk_tree_selection_real_unselect_all (selection);
902             }
903         }
904       else
905         {
906           /* FIXME: We only want to select the new node if we can unselect the
907            * old one, and we can select the new one.  We are currently
908            * unselecting the old one first, then trying the new one. */
909           if (anchor_path)
910             {
911               dirty = gtk_tree_selection_real_unselect_all (selection);
912               if (dirty)
913                 {
914                   if (selection->tree_view->priv->anchor)
915                     gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
916                   if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE))
917                     {
918                       selection->tree_view->priv->anchor =
919                         gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
920                     }
921                 }
922             }
923           else
924             {
925               if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE))
926                 {
927                   dirty = TRUE;
928                   selection->tree_view->priv->anchor =
929                     gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
930                 }
931             }
932         }
933     }
934   else if (selection->type == GTK_TREE_SELECTION_MULTI)
935     {
936       if (((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) && (anchor_path == NULL))
937         {
938           if (selection->tree_view->priv->anchor)
939             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
940
941           selection->tree_view->priv->anchor =
942             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
943           dirty = gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
944         }
945       else if ((state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) == (GDK_SHIFT_MASK|GDK_CONTROL_MASK))
946         {
947           gtk_tree_selection_select_range (selection,
948                                            anchor_path,
949                                            path);
950         }
951       else if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
952         {
953           flags = node->flags;
954           if (selection->tree_view->priv->anchor)
955             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
956
957           selection->tree_view->priv->anchor =
958             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
959
960           if ((flags & GTK_RBNODE_IS_SELECTED) == GTK_RBNODE_IS_SELECTED)
961             dirty |= gtk_tree_selection_real_select_node (selection, tree, node, FALSE);
962           else
963             dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
964         }
965       else if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
966         {
967           dirty = gtk_tree_selection_real_unselect_all (selection);
968           dirty |= gtk_tree_selection_real_select_range (selection,
969                                                          anchor_path,
970                                                          path);
971         }
972       else
973         {
974           dirty = gtk_tree_selection_real_unselect_all (selection);
975
976           if (selection->tree_view->priv->anchor)
977             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
978
979           selection->tree_view->priv->anchor =
980             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
981
982           dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
983         }
984     }
985
986   if (anchor_path)
987     gtk_tree_path_free (anchor_path);
988
989   if (dirty)
990     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
991 }
992
993 /* NOTE: Any {un,}selection ever done _MUST_ be done through this function!
994  */
995
996 /* FIXME: user_func can screw up GTK_TREE_SELECTION_SINGLE.  If it prevents
997  * unselection of a node, it can keep more then one node selected.
998  */
999 /* Perhaps the correct solution is to prevent selecting the new node, if
1000  * we fail to unselect the old node.
1001  */
1002 static gint
1003 gtk_tree_selection_real_select_node (GtkTreeSelection *selection,
1004                                      GtkRBTree        *tree,
1005                                      GtkRBNode        *node,
1006                                      gboolean          select)
1007 {
1008   gboolean selected = FALSE;
1009   GtkTreePath *path = NULL;
1010
1011   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) != select)
1012     {
1013       path = _gtk_tree_view_find_path (selection->tree_view, tree, node);
1014       if (selection->user_func)
1015         {
1016           if ((*selection->user_func) (selection, selection->tree_view->priv->model, path, selection->user_data))
1017             selected = TRUE;
1018         }
1019       else
1020         selected = TRUE;
1021       gtk_tree_path_free (path);
1022     }
1023
1024   if (selected == TRUE)
1025     {
1026       node->flags ^= GTK_RBNODE_IS_SELECTED;
1027
1028       /* FIXME: just draw the one node*/
1029       gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
1030       return TRUE;
1031     }
1032
1033   return FALSE;
1034 }
1035