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