]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeselection.c
Remove strict checking for rows.
[~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   if (selection->tree_view->priv->tree == NULL)
661     return;
662   g_return_if_fail (selection->type != GTK_TREE_SELECTION_MULTI);
663
664   if (gtk_tree_selection_real_select_all (selection))
665     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
666 }
667
668 static void
669 unselect_all_helper (GtkRBTree  *tree,
670                      GtkRBNode  *node,
671                      gpointer    data)
672 {
673   struct _TempTuple *tuple = data;
674
675   if (node->children)
676     _gtk_rbtree_traverse (node->children,
677                           node->children->root,
678                           G_PRE_ORDER,
679                           unselect_all_helper,
680                           data);
681   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
682     {
683       tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, FALSE) || tuple->dirty;
684     }
685 }
686
687 static gint
688 gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection)
689 {
690   struct _TempTuple *tuple;
691
692   if (selection->type == GTK_TREE_SELECTION_SINGLE)
693     {
694       GtkRBTree *tree = NULL;
695       GtkRBNode *node = NULL;
696       GtkTreePath *anchor_path;
697
698       if (selection->tree_view->priv->anchor == NULL)
699         return FALSE;
700
701       anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
702
703       if (anchor_path == NULL)
704         return FALSE;
705
706       _gtk_tree_view_find_node (selection->tree_view,
707                                 anchor_path,
708                                 &tree,
709                                 &node);
710
711       gtk_tree_path_free (anchor_path);
712
713       if (tree == NULL)
714         return FALSE;
715
716       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
717         {
718           if (gtk_tree_selection_real_select_node (selection, tree, node, FALSE))
719             {
720               gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
721               selection->tree_view->priv->anchor = NULL;
722               return TRUE;
723             }
724         }
725       return FALSE;
726     }
727   else
728     {
729       tuple = g_new (struct _TempTuple, 1);
730       tuple->selection = selection;
731       tuple->dirty = FALSE;
732
733       _gtk_rbtree_traverse (selection->tree_view->priv->tree,
734                             selection->tree_view->priv->tree->root,
735                             G_PRE_ORDER,
736                             unselect_all_helper,
737                             tuple);
738
739       if (tuple->dirty)
740         {
741           g_free (tuple);
742           return TRUE;
743         }
744       g_free (tuple);
745       return FALSE;
746     }
747 }
748
749 /**
750  * gtk_tree_selection_unselect_all:
751  * @selection: A #GtkTreeSelection.
752  *
753  * Unselects all the nodes.
754  **/
755 void
756 gtk_tree_selection_unselect_all (GtkTreeSelection *selection)
757 {
758   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
759   g_return_if_fail (selection->tree_view != NULL);
760   if (selection->tree_view->priv->tree == NULL)
761     return;
762   
763   if (selection->tree_view->priv->tree == NULL)
764     return;
765
766   if (gtk_tree_selection_real_unselect_all (selection))
767     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
768 }
769
770 static gint
771 gtk_tree_selection_real_select_range (GtkTreeSelection *selection,
772                                       GtkTreePath      *start_path,
773                                       GtkTreePath      *end_path)
774 {
775   GtkRBNode *start_node, *end_node;
776   GtkRBTree *start_tree, *end_tree;
777   gboolean dirty = FALSE;
778
779   switch (gtk_tree_path_compare (start_path, end_path))
780     {
781     case 1:
782       _gtk_tree_view_find_node (selection->tree_view,
783                                 end_path,
784                                 &start_tree,
785                                 &start_node);
786       _gtk_tree_view_find_node (selection->tree_view,
787                                 start_path,
788                                 &end_tree,
789                                 &end_node);
790       break;
791     case 0:
792       _gtk_tree_view_find_node (selection->tree_view,
793                                 start_path,
794                                 &start_tree,
795                                 &start_node);
796       end_tree = start_tree;
797       end_node = start_node;
798       break;
799     case -1:
800       _gtk_tree_view_find_node (selection->tree_view,
801                                 start_path,
802                                 &start_tree,
803                                 &start_node);
804       _gtk_tree_view_find_node (selection->tree_view,
805                                 end_path,
806                                 &end_tree,
807                                 &end_node);
808       break;
809     }
810
811   g_return_val_if_fail (start_node != NULL, FALSE);
812   g_return_val_if_fail (end_node != NULL, FALSE);
813
814   do
815     {
816       if (GTK_RBNODE_FLAG_SET (start_node, GTK_RBNODE_IS_SELECTED))
817         {
818           dirty = gtk_tree_selection_real_select_node (selection, start_tree, start_node, FALSE);
819         }
820
821       if (start_node == end_node)
822         break;
823
824       if (start_node->children)
825         {
826           start_tree = start_node->children;
827           start_node = start_tree->root;
828           while (start_node->left != start_tree->nil)
829             start_node = start_node->left;
830         }
831       else
832         {
833           gboolean done = FALSE;
834           do
835             {
836               start_node = _gtk_rbtree_next (start_tree, start_node);
837               if (start_node != NULL)
838                 {
839                   done = TRUE;
840                 }
841               else
842                 {
843                   start_node = start_tree->parent_node;
844                   start_tree = start_tree->parent_tree;
845                   if (start_tree == NULL)
846                     /* FIXME should this really be silent, or should it g_warning? */
847                     /* we've run out of tree */
848                     /* This means we never found end node!! */
849                     break;
850                 }
851             }
852           while (!done);
853         }
854     }
855   while (TRUE);
856
857   return dirty;
858 }
859
860 /**
861  * gtk_tree_selection_select_range:
862  * @selection: A #GtkTreeSelection.
863  * @start_path: The initial node of the range.
864  * @end_path: The final node of the range.
865  *
866  * Selects a range of nodes, determined by @start_path and @end_path inclusive.
867  **/
868 void
869 gtk_tree_selection_select_range (GtkTreeSelection *selection,
870                                  GtkTreePath      *start_path,
871                                  GtkTreePath      *end_path)
872 {
873   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
874   g_return_if_fail (selection->tree_view != NULL);
875
876   if (gtk_tree_selection_real_select_range (selection, start_path, end_path))
877     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
878 }
879
880 /* Called internally by gtktreeview.c It handles actually selecting the tree.
881  */
882 void
883 _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection,
884                                           GtkRBNode        *node,
885                                           GtkRBTree        *tree,
886                                           GtkTreePath      *path,
887                                           GdkModifierType   state)
888 {
889   gint flags;
890   gint dirty = FALSE;
891   GtkTreePath *anchor_path = NULL;
892
893
894   if (selection->tree_view->priv->anchor)
895     anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
896
897   if (selection->type == GTK_TREE_SELECTION_SINGLE)
898     {
899       /* Did we try to select the same node again? */
900       if (anchor_path && gtk_tree_path_compare (path, anchor_path) == 0)
901         {
902           if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
903             {
904               dirty = gtk_tree_selection_real_unselect_all (selection);
905             }
906         }
907       else
908         {
909           /* FIXME: We only want to select the new node if we can unselect the
910            * old one, and we can select the new one.  We are currently
911            * unselecting the old one first, then trying the new one. */
912           if (anchor_path)
913             {
914               dirty = gtk_tree_selection_real_unselect_all (selection);
915               if (dirty)
916                 {
917                   if (selection->tree_view->priv->anchor)
918                     gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
919                   if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE))
920                     {
921                       selection->tree_view->priv->anchor =
922                         gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
923                     }
924                 }
925             }
926           else
927             {
928               if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE))
929                 {
930                   dirty = TRUE;
931                   selection->tree_view->priv->anchor =
932                     gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
933                 }
934             }
935         }
936     }
937   else if (selection->type == GTK_TREE_SELECTION_MULTI)
938     {
939       if (((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) && (anchor_path == NULL))
940         {
941           if (selection->tree_view->priv->anchor)
942             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
943
944           selection->tree_view->priv->anchor =
945             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
946           dirty = gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
947         }
948       else if ((state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) == (GDK_SHIFT_MASK|GDK_CONTROL_MASK))
949         {
950           gtk_tree_selection_select_range (selection,
951                                            anchor_path,
952                                            path);
953         }
954       else if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
955         {
956           flags = node->flags;
957           if (selection->tree_view->priv->anchor)
958             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
959
960           selection->tree_view->priv->anchor =
961             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
962
963           if ((flags & GTK_RBNODE_IS_SELECTED) == GTK_RBNODE_IS_SELECTED)
964             dirty |= gtk_tree_selection_real_select_node (selection, tree, node, FALSE);
965           else
966             dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
967         }
968       else if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
969         {
970           dirty = gtk_tree_selection_real_unselect_all (selection);
971           dirty |= gtk_tree_selection_real_select_range (selection,
972                                                          anchor_path,
973                                                          path);
974         }
975       else
976         {
977           dirty = gtk_tree_selection_real_unselect_all (selection);
978
979           if (selection->tree_view->priv->anchor)
980             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
981
982           selection->tree_view->priv->anchor =
983             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
984
985           dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
986         }
987     }
988
989   if (anchor_path)
990     gtk_tree_path_free (anchor_path);
991
992   if (dirty)
993     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
994 }
995
996 /* NOTE: Any {un,}selection ever done _MUST_ be done through this function!
997  */
998
999 /* FIXME: user_func can screw up GTK_TREE_SELECTION_SINGLE.  If it prevents
1000  * unselection of a node, it can keep more then one node selected.
1001  */
1002 /* Perhaps the correct solution is to prevent selecting the new node, if
1003  * we fail to unselect the old node.
1004  */
1005 static gint
1006 gtk_tree_selection_real_select_node (GtkTreeSelection *selection,
1007                                      GtkRBTree        *tree,
1008                                      GtkRBNode        *node,
1009                                      gboolean          select)
1010 {
1011   gboolean selected = FALSE;
1012   GtkTreePath *path = NULL;
1013
1014   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) != select)
1015     {
1016       path = _gtk_tree_view_find_path (selection->tree_view, tree, node);
1017       if (selection->user_func)
1018         {
1019           if ((*selection->user_func) (selection, selection->tree_view->priv->model, path, selection->user_data))
1020             selected = TRUE;
1021         }
1022       else
1023         selected = TRUE;
1024       gtk_tree_path_free (path);
1025     }
1026
1027   if (selected == TRUE)
1028     {
1029       node->flags ^= GTK_RBNODE_IS_SELECTED;
1030
1031       /* FIXME: just draw the one node*/
1032       gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
1033       return TRUE;
1034     }
1035
1036   return FALSE;
1037 }
1038