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