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