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