]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeselection.c
remove unused enum
[~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  * The select function should return %TRUE if the state of the node may be toggled,
249  * and %FALSE if the state of the node should be left unchanged.
250  **/
251 void
252 gtk_tree_selection_set_select_function (GtkTreeSelection     *selection,
253                                         GtkTreeSelectionFunc  func,
254                                         gpointer              data,
255                                         GtkDestroyNotify      destroy)
256 {
257   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
258   g_return_if_fail (func != NULL);
259
260   selection->user_func = func;
261   selection->user_data = data;
262   selection->destroy = destroy;
263 }
264
265 /**
266  * gtk_tree_selection_get_user_data:
267  * @selection: A #GtkTreeSelection.
268  *
269  * Returns the user data for the selection function.
270  *
271  * Return value: The user data.
272  **/
273 gpointer
274 gtk_tree_selection_get_user_data (GtkTreeSelection *selection)
275 {
276   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
277
278   return selection->user_data;
279 }
280
281 /**
282  * gtk_tree_selection_get_tree_view:
283  * @selection: A #GtkTreeSelection
284  * 
285  * Returns the tree view associated with @selection.
286  * 
287  * Return value: A #GtkTreeView
288  **/
289 GtkTreeView *
290 gtk_tree_selection_get_tree_view (GtkTreeSelection *selection)
291 {
292   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
293
294   return selection->tree_view;
295 }
296
297 /**
298  * gtk_tree_selection_get_selected:
299  * @selection: A #GtkTreeSelection.
300  * @model: A pointer set to the #GtkTreeModel, or NULL.
301  * @iter: The #GtkTreeIter, or NULL.
302  *
303  * Sets @iter to the currently selected node if @selection is set to
304  * #GTK_SELECTION_SINGLE or #GTK_SELECTION_BROWSE.  @iter may be NULL if you
305  * just want to test if @selection has any selected nodes.  @model is filled
306  * with the current model as a convenience.  This function will not work if you
307  * use @selection is #GTK_SELECTION_MULTIPLE.
308  *
309  * Return value: TRUE, if there is a selected node.
310  **/
311 gboolean
312 gtk_tree_selection_get_selected (GtkTreeSelection  *selection,
313                                  GtkTreeModel     **model,
314                                  GtkTreeIter       *iter)
315 {
316   GtkRBTree *tree;
317   GtkRBNode *node;
318   GtkTreePath *anchor_path;
319   gboolean retval;
320
321   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
322   g_return_val_if_fail (selection->type != GTK_SELECTION_MULTIPLE, FALSE);
323   g_return_val_if_fail (selection->tree_view != NULL, FALSE);
324   g_return_val_if_fail (selection->tree_view->priv->model != NULL, FALSE);
325
326   if (model)
327     *model = selection->tree_view->priv->model;
328
329   if (selection->tree_view->priv->anchor == NULL)
330     return FALSE;
331
332   anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
333
334   if (anchor_path == NULL)
335     return FALSE;
336
337   if (iter == NULL)
338     {
339       gtk_tree_path_free (anchor_path);
340       return TRUE;
341     }
342
343   retval = FALSE;
344
345   if (!_gtk_tree_view_find_node (selection->tree_view,
346                                  anchor_path,
347                                  &tree,
348                                  &node) &&
349       ! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
350     {
351       /* We don't want to return the anchor if it isn't actually selected.
352        */
353       retval = FALSE;
354     }
355   else
356     {
357       retval = gtk_tree_model_get_iter (selection->tree_view->priv->model,
358                                         iter,
359                                         anchor_path);
360     }
361
362   gtk_tree_path_free (anchor_path);
363
364   return retval;
365 }
366
367 /**
368  * gtk_tree_selection_selected_foreach:
369  * @selection: A #GtkTreeSelection.
370  * @func: The function to call for each selected node.
371  * @data: user data to pass to the function.
372  *
373  * Calls a function for each selected node.
374  **/
375 void
376 gtk_tree_selection_selected_foreach (GtkTreeSelection            *selection,
377                                      GtkTreeSelectionForeachFunc  func,
378                                      gpointer                     data)
379 {
380   GtkTreePath *path;
381   GtkRBTree *tree;
382   GtkRBNode *node;
383   GtkTreeIter iter;
384
385   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
386   g_return_if_fail (selection->tree_view != NULL);
387   g_return_if_fail (selection->tree_view->priv->model != NULL);
388
389   if (func == NULL ||
390       selection->tree_view->priv->tree == NULL ||
391       selection->tree_view->priv->tree->root == NULL)
392     return;
393
394   if (selection->type == GTK_SELECTION_SINGLE ||
395       selection->type == GTK_SELECTION_BROWSE)
396     {
397       if (gtk_tree_row_reference_valid (selection->tree_view->priv->anchor))
398         {
399           path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
400           gtk_tree_model_get_iter (selection->tree_view->priv->model, &iter, path);
401           (* func) (selection->tree_view->priv->model, path, &iter, data);
402           gtk_tree_path_free (path);
403         }
404       return;
405     }
406
407   tree = selection->tree_view->priv->tree;
408   node = selection->tree_view->priv->tree->root;
409   
410   while (node->left != tree->nil)
411     node = node->left;
412
413   /* find the node internally */
414   path = gtk_tree_path_new_root ();
415   gtk_tree_model_get_iter (selection->tree_view->priv->model,
416                            &iter, path);
417
418   do
419     {
420       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
421         (* func) (selection->tree_view->priv->model, path, &iter, data);
422       if (node->children)
423         {
424           gboolean has_child;
425           GtkTreeIter tmp;
426
427           tree = node->children;
428           node = tree->root;
429           while (node->left != tree->nil)
430             node = node->left;
431           tmp = iter;
432           has_child = gtk_tree_model_iter_children (selection->tree_view->priv->model, &iter, &tmp);
433           gtk_tree_path_append_index (path, 0);
434           /* Sanity Check! */
435           TREE_VIEW_INTERNAL_ASSERT_VOID (has_child);
436         }
437       else
438         {
439           gboolean done = FALSE;
440           do
441             {
442               node = _gtk_rbtree_next (tree, node);
443               if (node != NULL)
444                 {
445                   gboolean has_next;
446
447                   has_next = gtk_tree_model_iter_next (selection->tree_view->priv->model, &iter);
448                   done = TRUE;
449                   gtk_tree_path_next (path);
450
451                   /* Sanity Check! */
452                   TREE_VIEW_INTERNAL_ASSERT_VOID (has_next);
453                 }
454               else
455                 {
456                   gboolean has_parent;
457                   GtkTreeIter tmp_iter = iter;
458
459                   node = tree->parent_node;
460                   tree = tree->parent_tree;
461                   if (tree == NULL)
462                     {
463                       gtk_tree_path_free (path);
464                       /* we've run out of tree */
465                       /* We're done with this function */
466                       return;
467                     }
468                   has_parent = gtk_tree_model_iter_parent (selection->tree_view->priv->model, &iter, &tmp_iter);
469                   gtk_tree_path_up (path);
470                   /* Sanity check */
471                   TREE_VIEW_INTERNAL_ASSERT_VOID (has_parent);
472                 }
473             }
474           while (!done);
475         }
476     }
477   while (TRUE);
478 }
479
480 /**
481  * gtk_tree_selection_select_path:
482  * @selection: A #GtkTreeSelection.
483  * @path: The #GtkTreePath to be selected.
484  *
485  * Select the row at @path.
486  **/
487 void
488 gtk_tree_selection_select_path (GtkTreeSelection *selection,
489                                 GtkTreePath      *path)
490 {
491   GtkRBNode *node;
492   GtkRBTree *tree;
493   GdkModifierType state = 0;
494
495   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
496   g_return_if_fail (selection->tree_view != NULL);
497   g_return_if_fail (path != NULL);
498
499   _gtk_tree_view_find_node (selection->tree_view,
500                             path,
501                             &tree,
502                             &node);
503
504   if (node == NULL || GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
505     return;
506
507   if (selection->type == GTK_SELECTION_MULTIPLE)
508     state = GDK_CONTROL_MASK;
509
510   _gtk_tree_selection_internal_select_node (selection,
511                                             node,
512                                             tree,
513                                             path,
514                                             state);
515 }
516
517 /**
518  * gtk_tree_selection_unselect_path:
519  * @selection: A #GtkTreeSelection.
520  * @path: The #GtkTreePath to be unselected.
521  *
522  * Unselects the row at @path.
523  **/
524 void
525 gtk_tree_selection_unselect_path (GtkTreeSelection *selection,
526                                   GtkTreePath      *path)
527 {
528   GtkRBNode *node;
529   GtkRBTree *tree;
530
531   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
532   g_return_if_fail (selection->tree_view != NULL);
533   g_return_if_fail (path != NULL);
534
535   _gtk_tree_view_find_node (selection->tree_view,
536                             path,
537                             &tree,
538                             &node);
539
540   if (node == NULL || !GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
541     return;
542
543   _gtk_tree_selection_internal_select_node (selection,
544                                             node,
545                                             tree,
546                                             path,
547                                             GDK_CONTROL_MASK);
548 }
549
550 /**
551  * gtk_tree_selection_select_iter:
552  * @selection: A #GtkTreeSelection.
553  * @iter: The #GtkTreeIter to be selected.
554  *
555  * Selects the specified iterator.
556  **/
557 void
558 gtk_tree_selection_select_iter (GtkTreeSelection *selection,
559                                 GtkTreeIter      *iter)
560 {
561   GtkTreePath *path;
562
563   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
564   g_return_if_fail (selection->tree_view != NULL);
565   g_return_if_fail (selection->tree_view->priv->model != NULL);
566   g_return_if_fail (iter != NULL);
567
568   path = gtk_tree_model_get_path (selection->tree_view->priv->model,
569                                   iter);
570
571   if (path == NULL)
572     return;
573
574   gtk_tree_selection_select_path (selection, path);
575   gtk_tree_path_free (path);
576 }
577
578
579 /**
580  * gtk_tree_selection_unselect_iter:
581  * @selection: A #GtkTreeSelection.
582  * @iter: The #GtkTreeIter to be unselected.
583  *
584  * Unselects the specified iterator.
585  **/
586 void
587 gtk_tree_selection_unselect_iter (GtkTreeSelection *selection,
588                                   GtkTreeIter      *iter)
589 {
590   GtkTreePath *path;
591
592   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
593   g_return_if_fail (selection->tree_view != NULL);
594   g_return_if_fail (selection->tree_view->priv->model != NULL);
595   g_return_if_fail (iter != NULL);
596
597   path = gtk_tree_model_get_path (selection->tree_view->priv->model,
598                                   iter);
599
600   if (path == NULL)
601     return;
602
603   gtk_tree_selection_select_path (selection, path);
604   gtk_tree_path_free (path);
605 }
606
607 /* Wish I was in python, right now... */
608 struct _TempTuple {
609   GtkTreeSelection *selection;
610   gint dirty;
611 };
612
613 static void
614 select_all_helper (GtkRBTree  *tree,
615                    GtkRBNode  *node,
616                    gpointer    data)
617 {
618   struct _TempTuple *tuple = data;
619
620   if (node->children)
621     _gtk_rbtree_traverse (node->children,
622                           node->children->root,
623                           G_PRE_ORDER,
624                           select_all_helper,
625                           data);
626   if (!GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
627     {
628       tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, TRUE) || tuple->dirty;
629     }
630 }
631
632
633 /* We have a real_{un,}select_all function that doesn't emit the signal, so we
634  * can use it in other places without fear of the signal being emitted.
635  */
636 static gint
637 gtk_tree_selection_real_select_all (GtkTreeSelection *selection)
638 {
639   struct _TempTuple *tuple;
640
641   if (selection->tree_view->priv->tree == NULL)
642     return FALSE;
643
644   /* Mark all nodes selected */
645   tuple = g_new (struct _TempTuple, 1);
646   tuple->selection = selection;
647   tuple->dirty = FALSE;
648
649   _gtk_rbtree_traverse (selection->tree_view->priv->tree,
650                         selection->tree_view->priv->tree->root,
651                         G_PRE_ORDER,
652                         select_all_helper,
653                         tuple);
654   if (tuple->dirty)
655     {
656       g_free (tuple);
657       return TRUE;
658     }
659   g_free (tuple);
660   return FALSE;
661 }
662
663 /**
664  * gtk_tree_selection_select_all:
665  * @selection: A #GtkTreeSelection.
666  *
667  * Selects all the nodes.  @selection is must be set to #GTK_SELECTION_MULTIPLE
668  * mode.
669  **/
670 void
671 gtk_tree_selection_select_all (GtkTreeSelection *selection)
672 {
673   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
674   g_return_if_fail (selection->tree_view != NULL);
675   if (selection->tree_view->priv->tree == NULL)
676     return;
677   g_return_if_fail (selection->type == GTK_SELECTION_MULTIPLE);
678
679   if (gtk_tree_selection_real_select_all (selection))
680     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
681 }
682
683 static void
684 unselect_all_helper (GtkRBTree  *tree,
685                      GtkRBNode  *node,
686                      gpointer    data)
687 {
688   struct _TempTuple *tuple = data;
689
690   if (node->children)
691     _gtk_rbtree_traverse (node->children,
692                           node->children->root,
693                           G_PRE_ORDER,
694                           unselect_all_helper,
695                           data);
696   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
697     {
698       tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, FALSE) || tuple->dirty;
699     }
700 }
701
702 static gint
703 gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection)
704 {
705   struct _TempTuple *tuple;
706
707   if (selection->type == GTK_SELECTION_SINGLE ||
708       selection->type == GTK_SELECTION_BROWSE)
709     {
710       GtkRBTree *tree = NULL;
711       GtkRBNode *node = NULL;
712       GtkTreePath *anchor_path;
713
714       if (selection->tree_view->priv->anchor == NULL)
715         return FALSE;
716
717       anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
718
719       if (anchor_path == NULL)
720         return FALSE;
721
722       _gtk_tree_view_find_node (selection->tree_view,
723                                 anchor_path,
724                                 &tree,
725                                 &node);
726
727       gtk_tree_path_free (anchor_path);
728
729       if (tree == NULL)
730         return FALSE;
731
732       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
733         {
734           if (gtk_tree_selection_real_select_node (selection, tree, node, FALSE))
735             {
736               gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
737               selection->tree_view->priv->anchor = NULL;
738               return TRUE;
739             }
740         }
741       return FALSE;
742     }
743   else
744     {
745       tuple = g_new (struct _TempTuple, 1);
746       tuple->selection = selection;
747       tuple->dirty = FALSE;
748
749       _gtk_rbtree_traverse (selection->tree_view->priv->tree,
750                             selection->tree_view->priv->tree->root,
751                             G_PRE_ORDER,
752                             unselect_all_helper,
753                             tuple);
754
755       if (tuple->dirty)
756         {
757           g_free (tuple);
758           return TRUE;
759         }
760       g_free (tuple);
761       return FALSE;
762     }
763 }
764
765 /**
766  * gtk_tree_selection_unselect_all:
767  * @selection: A #GtkTreeSelection.
768  *
769  * Unselects all the nodes.
770  **/
771 void
772 gtk_tree_selection_unselect_all (GtkTreeSelection *selection)
773 {
774   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
775   g_return_if_fail (selection->tree_view != NULL);
776   if (selection->tree_view->priv->tree == NULL)
777     return;
778   
779   if (selection->tree_view->priv->tree == NULL)
780     return;
781
782   if (gtk_tree_selection_real_unselect_all (selection))
783     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
784 }
785
786 static gint
787 gtk_tree_selection_real_select_range (GtkTreeSelection *selection,
788                                       GtkTreePath      *start_path,
789                                       GtkTreePath      *end_path)
790 {
791   GtkRBNode *start_node, *end_node;
792   GtkRBTree *start_tree, *end_tree;
793   gboolean dirty = FALSE;
794
795   switch (gtk_tree_path_compare (start_path, end_path))
796     {
797     case 1:
798       _gtk_tree_view_find_node (selection->tree_view,
799                                 end_path,
800                                 &start_tree,
801                                 &start_node);
802       _gtk_tree_view_find_node (selection->tree_view,
803                                 start_path,
804                                 &end_tree,
805                                 &end_node);
806       break;
807     case 0:
808       _gtk_tree_view_find_node (selection->tree_view,
809                                 start_path,
810                                 &start_tree,
811                                 &start_node);
812       end_tree = start_tree;
813       end_node = start_node;
814       break;
815     case -1:
816       _gtk_tree_view_find_node (selection->tree_view,
817                                 start_path,
818                                 &start_tree,
819                                 &start_node);
820       _gtk_tree_view_find_node (selection->tree_view,
821                                 end_path,
822                                 &end_tree,
823                                 &end_node);
824       break;
825     }
826
827   g_return_val_if_fail (start_node != NULL, FALSE);
828   g_return_val_if_fail (end_node != NULL, FALSE);
829
830   do
831     {
832       dirty |= gtk_tree_selection_real_select_node (selection, start_tree, start_node, TRUE);
833
834       if (start_node == end_node)
835         break;
836
837       if (start_node->children)
838         {
839           start_tree = start_node->children;
840           start_node = start_tree->root;
841           while (start_node->left != start_tree->nil)
842             start_node = start_node->left;
843         }
844       else
845         {
846           _gtk_rbtree_next_full (start_tree, start_node, &start_tree, &start_node);
847           if (start_tree == NULL)
848             {
849               /* we just ran out of tree.  That means someone passed in bogus values.
850                */
851               return dirty;
852             }
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_SELECTION_SINGLE ||
898       selection->type == GTK_SELECTION_BROWSE)
899     {
900       /* Did we try to select the same node again? */
901       if (selection->type == GTK_SELECTION_SINGLE &&
902           anchor_path && gtk_tree_path_compare (path, anchor_path) == 0)
903         {
904           if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
905             {
906               dirty = gtk_tree_selection_real_unselect_all (selection);
907             }
908         }
909       else
910         {
911           /* FIXME: We only want to select the new node if we can unselect the
912            * old one, and we can select the new one.  We are currently
913            * unselecting the old one first, then trying the new one. */
914           if (anchor_path)
915             {
916               dirty = gtk_tree_selection_real_unselect_all (selection);
917               if (dirty)
918                 {
919                   if (selection->tree_view->priv->anchor)
920                     gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
921                   if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE))
922                     {
923                       selection->tree_view->priv->anchor =
924                         gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
925                     }
926                 }
927             }
928           else
929             {
930               if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE))
931                 {
932                   dirty = TRUE;
933                   selection->tree_view->priv->anchor =
934                     gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
935                 }
936             }
937         }
938     }
939   else if (selection->type == GTK_SELECTION_MULTIPLE)
940     {
941       if (((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) && (anchor_path == NULL))
942         {
943           if (selection->tree_view->priv->anchor)
944             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
945
946           selection->tree_view->priv->anchor =
947             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
948           dirty = gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
949         }
950       else if ((state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) == (GDK_SHIFT_MASK|GDK_CONTROL_MASK))
951         {
952           gtk_tree_selection_select_range (selection,
953                                            anchor_path,
954                                            path);
955         }
956       else if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
957         {
958           flags = node->flags;
959           if (selection->tree_view->priv->anchor)
960             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
961
962           selection->tree_view->priv->anchor =
963             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
964
965           if ((flags & GTK_RBNODE_IS_SELECTED) == GTK_RBNODE_IS_SELECTED)
966             dirty |= gtk_tree_selection_real_select_node (selection, tree, node, FALSE);
967           else
968             dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
969         }
970       else if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
971         {
972           dirty = gtk_tree_selection_real_unselect_all (selection);
973           dirty |= gtk_tree_selection_real_select_range (selection,
974                                                          anchor_path,
975                                                          path);
976         }
977       else
978         {
979           dirty = gtk_tree_selection_real_unselect_all (selection);
980
981           if (selection->tree_view->priv->anchor)
982             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
983
984           selection->tree_view->priv->anchor =
985             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
986
987           dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
988         }
989     }
990
991   if (anchor_path)
992     gtk_tree_path_free (anchor_path);
993
994   if (dirty)
995     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
996 }
997
998 /* NOTE: Any {un,}selection ever done _MUST_ be done through this function!
999  */
1000
1001 static gint
1002 gtk_tree_selection_real_select_node (GtkTreeSelection *selection,
1003                                      GtkRBTree        *tree,
1004                                      GtkRBNode        *node,
1005                                      gboolean          select)
1006 {
1007   gboolean selected = FALSE;
1008   GtkTreePath *path = NULL;
1009
1010   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) != select)
1011     {
1012       path = _gtk_tree_view_find_path (selection->tree_view, tree, node);
1013       if (selection->user_func)
1014         {
1015           if ((*selection->user_func) (selection, selection->tree_view->priv->model, path,
1016                                        GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED),
1017                                        selection->user_data))
1018             selected = TRUE;
1019         }
1020       else
1021         selected = TRUE;
1022       gtk_tree_path_free (path);
1023     }
1024
1025   if (selected == TRUE)
1026     {
1027       node->flags ^= GTK_RBNODE_IS_SELECTED;
1028
1029       /* FIXME: just draw the one node*/
1030       gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
1031       return TRUE;
1032     }
1033
1034   return FALSE;
1035 }
1036