]> Pileus Git - ~andy/gtk/blob - gtk/gtkrbtree.c
treeview: Rename "parity" to "total_count"
[~andy/gtk] / gtk / gtkrbtree.c
1 /* gtkrbtree.c
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 "config.h"
21 #include "gtkrbtree.h"
22 #include "gtkdebug.h"
23
24 static GtkRBNode * _gtk_rbnode_new                (GtkRBTree  *tree,
25                                                    gint        height);
26 static void        _gtk_rbnode_free               (GtkRBNode  *node);
27 static void        _gtk_rbnode_rotate_left        (GtkRBTree  *tree,
28                                                    GtkRBNode  *node);
29 static void        _gtk_rbnode_rotate_right       (GtkRBTree  *tree,
30                                                    GtkRBNode  *node);
31 static void        _gtk_rbtree_insert_fixup       (GtkRBTree  *tree,
32                                                    GtkRBNode  *node);
33 static void        _gtk_rbtree_remove_node_fixup  (GtkRBTree  *tree,
34                                                    GtkRBNode  *node);
35 static inline void _fixup_validation              (GtkRBTree  *tree,
36                                                    GtkRBNode  *node);
37 static inline void _fixup_total_count             (GtkRBTree  *tree,
38                                                    GtkRBNode  *node);
39
40
41
42 static GtkRBNode *
43 _gtk_rbnode_new (GtkRBTree *tree,
44                  gint       height)
45 {
46   GtkRBNode *node = g_slice_new (GtkRBNode);
47
48   node->left = tree->nil;
49   node->right = tree->nil;
50   node->parent = tree->nil;
51   node->flags = GTK_RBNODE_RED;
52   node->total_count = 1;
53   node->count = 1;
54   node->children = NULL;
55   node->offset = height;
56   return node;
57 }
58
59 static void
60 _gtk_rbnode_free (GtkRBNode *node)
61 {
62   if (gtk_get_debug_flags () & GTK_DEBUG_TREE)
63     {
64       node->left = (gpointer) 0xdeadbeef;
65       node->right = (gpointer) 0xdeadbeef;
66       node->parent = (gpointer) 0xdeadbeef;
67       node->total_count = 56789;
68       node->offset = 56789;
69       node->count = 56789;
70       node->flags = 0;
71     }
72   g_slice_free (GtkRBNode, node);
73 }
74
75 static void
76 _gtk_rbnode_rotate_left (GtkRBTree *tree,
77                          GtkRBNode *node)
78 {
79   gint node_height, right_height;
80   GtkRBNode *right = node->right;
81
82   g_return_if_fail (node != tree->nil);
83
84   node_height = node->offset -
85     (node->left?node->left->offset:0) -
86     (node->right?node->right->offset:0) -
87     (node->children?node->children->root->offset:0);
88   right_height = right->offset -
89     (right->left?right->left->offset:0) -
90     (right->right?right->right->offset:0) -
91     (right->children?right->children->root->offset:0);
92   node->right = right->left;
93   if (right->left != tree->nil)
94     right->left->parent = node;
95
96   if (right != tree->nil)
97     right->parent = node->parent;
98   if (node->parent != tree->nil)
99     {
100       if (node == node->parent->left)
101         node->parent->left = right;
102       else
103         node->parent->right = right;
104     } else {
105       tree->root = right;
106     }
107
108   right->left = node;
109   if (node != tree->nil)
110     node->parent = right;
111
112   node->count = 1 + (node->left?node->left->count:0) +
113     (node->right?node->right->count:0);
114   right->count = 1 + (right->left?right->left->count:0) +
115     (right->right?right->right->count:0);
116
117   node->offset = node_height +
118     (node->left?node->left->offset:0) +
119     (node->right?node->right->offset:0) +
120     (node->children?node->children->root->offset:0);
121   right->offset = right_height +
122     (right->left?right->left->offset:0) +
123     (right->right?right->right->offset:0) +
124     (right->children?right->children->root->offset:0);
125
126   _fixup_validation (tree, node);
127   _fixup_validation (tree, right);
128   _fixup_total_count (tree, node);
129   _fixup_total_count (tree, right);
130 }
131
132 static void
133 _gtk_rbnode_rotate_right (GtkRBTree *tree,
134                           GtkRBNode *node)
135 {
136   gint node_height, left_height;
137   GtkRBNode *left = node->left;
138
139   g_return_if_fail (node != tree->nil);
140
141   node_height = node->offset -
142     (node->left?node->left->offset:0) -
143     (node->right?node->right->offset:0) -
144     (node->children?node->children->root->offset:0);
145   left_height = left->offset -
146     (left->left?left->left->offset:0) -
147     (left->right?left->right->offset:0) -
148     (left->children?left->children->root->offset:0);
149   
150   node->left = left->right;
151   if (left->right != tree->nil)
152     left->right->parent = node;
153
154   if (left != tree->nil)
155     left->parent = node->parent;
156   if (node->parent != tree->nil)
157     {
158       if (node == node->parent->right)
159         node->parent->right = left;
160       else
161         node->parent->left = left;
162     }
163   else
164     {
165       tree->root = left;
166     }
167
168   /* link node and left */
169   left->right = node;
170   if (node != tree->nil)
171     node->parent = left;
172
173   node->count = 1 + (node->left?node->left->count:0) +
174     (node->right?node->right->count:0);
175   left->count = 1 + (left->left?left->left->count:0) +
176     (left->right?left->right->count:0);
177
178   node->offset = node_height +
179     (node->left?node->left->offset:0) +
180     (node->right?node->right->offset:0) +
181     (node->children?node->children->root->offset:0);
182   left->offset = left_height +
183     (left->left?left->left->offset:0) +
184     (left->right?left->right->offset:0) +
185     (left->children?left->children->root->offset:0);
186
187   _fixup_validation (tree, node);
188   _fixup_validation (tree, left);
189   _fixup_total_count (tree, node);
190   _fixup_total_count (tree, left);
191 }
192
193 static void
194 _gtk_rbtree_insert_fixup (GtkRBTree *tree,
195                           GtkRBNode *node)
196 {
197
198   /* check Red-Black properties */
199   while (node != tree->root && GTK_RBNODE_GET_COLOR (node->parent) == GTK_RBNODE_RED)
200     {
201       /* we have a violation */
202       if (node->parent == node->parent->parent->left)
203         {
204           GtkRBNode *y = node->parent->parent->right;
205           if (GTK_RBNODE_GET_COLOR (y) == GTK_RBNODE_RED)
206             {
207                                 /* uncle is GTK_RBNODE_RED */
208               GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
209               GTK_RBNODE_SET_COLOR (y, GTK_RBNODE_BLACK);
210               GTK_RBNODE_SET_COLOR (node->parent->parent, GTK_RBNODE_RED);
211               node = node->parent->parent;
212             }
213           else
214             {
215                                 /* uncle is GTK_RBNODE_BLACK */
216               if (node == node->parent->right)
217                 {
218                   /* make node a left child */
219                   node = node->parent;
220                   _gtk_rbnode_rotate_left (tree, node);
221                 }
222
223                                 /* recolor and rotate */
224               GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
225               GTK_RBNODE_SET_COLOR (node->parent->parent, GTK_RBNODE_RED);
226               _gtk_rbnode_rotate_right(tree, node->parent->parent);
227             }
228         }
229       else
230         {
231           /* mirror image of above code */
232           GtkRBNode *y = node->parent->parent->left;
233           if (GTK_RBNODE_GET_COLOR (y) == GTK_RBNODE_RED)
234             {
235                                 /* uncle is GTK_RBNODE_RED */
236               GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
237               GTK_RBNODE_SET_COLOR (y, GTK_RBNODE_BLACK);
238               GTK_RBNODE_SET_COLOR (node->parent->parent, GTK_RBNODE_RED);
239               node = node->parent->parent;
240             }
241           else
242             {
243                                 /* uncle is GTK_RBNODE_BLACK */
244               if (node == node->parent->left)
245                 {
246                   node = node->parent;
247                   _gtk_rbnode_rotate_right (tree, node);
248                 }
249               GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
250               GTK_RBNODE_SET_COLOR (node->parent->parent, GTK_RBNODE_RED);
251               _gtk_rbnode_rotate_left (tree, node->parent->parent);
252             }
253         }
254     }
255   GTK_RBNODE_SET_COLOR (tree->root, GTK_RBNODE_BLACK);
256 }
257
258 static void
259 _gtk_rbtree_remove_node_fixup (GtkRBTree *tree,
260                                GtkRBNode *node)
261 {
262   while (node != tree->root && GTK_RBNODE_GET_COLOR (node) == GTK_RBNODE_BLACK)
263     {
264       if (node == node->parent->left)
265         {
266           GtkRBNode *w = node->parent->right;
267           if (GTK_RBNODE_GET_COLOR (w) == GTK_RBNODE_RED)
268             {
269               GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_BLACK);
270               GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_RED);
271               _gtk_rbnode_rotate_left (tree, node->parent);
272               w = node->parent->right;
273             }
274           if (GTK_RBNODE_GET_COLOR (w->left) == GTK_RBNODE_BLACK && GTK_RBNODE_GET_COLOR (w->right) == GTK_RBNODE_BLACK)
275             {
276               GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_RED);
277               node = node->parent;
278             }
279           else
280             {
281               if (GTK_RBNODE_GET_COLOR (w->right) == GTK_RBNODE_BLACK)
282                 {
283                   GTK_RBNODE_SET_COLOR (w->left, GTK_RBNODE_BLACK);
284                   GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_RED);
285                   _gtk_rbnode_rotate_right (tree, w);
286                   w = node->parent->right;
287                 }
288               GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_GET_COLOR (node->parent));
289               GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
290               GTK_RBNODE_SET_COLOR (w->right, GTK_RBNODE_BLACK);
291               _gtk_rbnode_rotate_left (tree, node->parent);
292               node = tree->root;
293             }
294         }
295       else
296         {
297           GtkRBNode *w = node->parent->left;
298           if (GTK_RBNODE_GET_COLOR (w) == GTK_RBNODE_RED)
299             {
300               GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_BLACK);
301               GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_RED);
302               _gtk_rbnode_rotate_right (tree, node->parent);
303               w = node->parent->left;
304             }
305           if (GTK_RBNODE_GET_COLOR (w->right) == GTK_RBNODE_BLACK && GTK_RBNODE_GET_COLOR (w->left) == GTK_RBNODE_BLACK)
306             {
307               GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_RED);
308               node = node->parent;
309             }
310           else
311             {
312               if (GTK_RBNODE_GET_COLOR (w->left) == GTK_RBNODE_BLACK)
313                 {
314                   GTK_RBNODE_SET_COLOR (w->right, GTK_RBNODE_BLACK);
315                   GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_RED);
316                   _gtk_rbnode_rotate_left (tree, w);
317                   w = node->parent->left;
318                 }
319               GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_GET_COLOR (node->parent));
320               GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
321               GTK_RBNODE_SET_COLOR (w->left, GTK_RBNODE_BLACK);
322               _gtk_rbnode_rotate_right (tree, node->parent);
323               node = tree->root;
324             }
325         }
326     }
327   GTK_RBNODE_SET_COLOR (node, GTK_RBNODE_BLACK);
328 }
329
330 GtkRBTree *
331 _gtk_rbtree_new (void)
332 {
333   GtkRBTree *retval;
334
335   retval = g_new (GtkRBTree, 1);
336   retval->parent_tree = NULL;
337   retval->parent_node = NULL;
338
339   retval->nil = g_slice_new (GtkRBNode);
340   retval->nil->left = NULL;
341   retval->nil->right = NULL;
342   retval->nil->parent = NULL;
343   retval->nil->flags = GTK_RBNODE_BLACK;
344   retval->nil->count = 0;
345   retval->nil->offset = 0;
346   retval->nil->total_count = 0;
347
348   retval->root = retval->nil;
349   return retval;
350 }
351
352 static void
353 _gtk_rbtree_free_helper (GtkRBTree  *tree,
354                          GtkRBNode  *node,
355                          gpointer    data)
356 {
357   if (node->children)
358     _gtk_rbtree_free (node->children);
359
360   _gtk_rbnode_free (node);
361 }
362
363 void
364 _gtk_rbtree_free (GtkRBTree *tree)
365 {
366   _gtk_rbtree_traverse (tree,
367                         tree->root,
368                         G_POST_ORDER,
369                         _gtk_rbtree_free_helper,
370                         NULL);
371
372   if (tree->parent_node &&
373       tree->parent_node->children == tree)
374     tree->parent_node->children = NULL;
375   _gtk_rbnode_free (tree->nil);
376   g_free (tree);
377 }
378
379 void
380 _gtk_rbtree_remove (GtkRBTree *tree)
381 {
382   GtkRBTree *tmp_tree;
383   GtkRBNode *tmp_node;
384
385   gint height = tree->root->offset;
386   guint total_count = tree->root->total_count;
387
388 #ifdef G_ENABLE_DEBUG  
389   if (gtk_get_debug_flags () & GTK_DEBUG_TREE)
390     _gtk_rbtree_test (G_STRLOC, tree);
391 #endif
392   
393   tmp_tree = tree->parent_tree;
394   tmp_node = tree->parent_node;
395
396   /* ugly hack to make _fixup_validation work in the first iteration of the
397    * loop below */
398   GTK_RBNODE_UNSET_FLAG (tree->root, GTK_RBNODE_DESCENDANTS_INVALID);
399   
400   while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil)
401     {
402       _fixup_validation (tmp_tree, tmp_node);
403       tmp_node->offset -= height;
404       tmp_node->total_count -= total_count;
405       
406       tmp_node = tmp_node->parent;
407       if (tmp_node == tmp_tree->nil)
408         {
409           tmp_node = tmp_tree->parent_node;
410           tmp_tree = tmp_tree->parent_tree;
411         }
412     }
413
414   tmp_tree = tree->parent_tree;
415   tmp_node = tree->parent_node;
416   _gtk_rbtree_free (tree);
417
418 #ifdef G_ENABLE_DEBUG  
419   if (gtk_get_debug_flags () & GTK_DEBUG_TREE)
420     _gtk_rbtree_test (G_STRLOC, tmp_tree);
421 #endif
422 }
423
424
425 GtkRBNode *
426 _gtk_rbtree_insert_after (GtkRBTree *tree,
427                           GtkRBNode *current,
428                           gint       height,
429                           gboolean   valid)
430 {
431   GtkRBNode *node;
432   gboolean right = TRUE;
433   GtkRBNode *tmp_node;
434   GtkRBTree *tmp_tree;  
435
436 #ifdef G_ENABLE_DEBUG  
437   if (gtk_get_debug_flags () & GTK_DEBUG_TREE)
438     {
439       g_print ("\n\n_gtk_rbtree_insert_after: %p\n", current);
440       _gtk_rbtree_debug_spew (tree);
441       _gtk_rbtree_test (G_STRLOC, tree);
442     }
443 #endif /* G_ENABLE_DEBUG */  
444
445   if (current != NULL && current->right != tree->nil)
446     {
447       current = current->right;
448       while (current->left != tree->nil)
449         current = current->left;
450       right = FALSE;
451     }
452   /* setup new node */
453   node = _gtk_rbnode_new (tree, height);
454   node->parent = (current?current:tree->nil);
455
456   /* insert node in tree */
457   if (current)
458     {
459       if (right)
460         current->right = node;
461       else
462         current->left = node;
463       tmp_node = node->parent;
464       tmp_tree = tree;
465     }
466   else
467     {
468       tree->root = node;
469       tmp_node = tree->parent_node;
470       tmp_tree = tree->parent_tree;
471     }
472
473   while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil)
474     {
475       /* We only want to propagate the count if we are in the tree we
476        * started in. */
477       if (tmp_tree == tree)
478         tmp_node->count++;
479
480       tmp_node->total_count += 1;
481       tmp_node->offset += height;
482       tmp_node = tmp_node->parent;
483       if (tmp_node == tmp_tree->nil)
484         {
485           tmp_node = tmp_tree->parent_node;
486           tmp_tree = tmp_tree->parent_tree;
487         }
488     }
489
490   if (valid)
491     _gtk_rbtree_node_mark_valid (tree, node);
492   else
493     _gtk_rbtree_node_mark_invalid (tree, node);
494
495   _gtk_rbtree_insert_fixup (tree, node);
496
497 #ifdef G_ENABLE_DEBUG  
498   if (gtk_get_debug_flags () & GTK_DEBUG_TREE)
499     {
500       g_print ("_gtk_rbtree_insert_after finished...\n");
501       _gtk_rbtree_debug_spew (tree);
502       g_print ("\n\n");
503       _gtk_rbtree_test (G_STRLOC, tree);
504     }
505 #endif /* G_ENABLE_DEBUG */  
506
507   return node;
508 }
509
510 GtkRBNode *
511 _gtk_rbtree_insert_before (GtkRBTree *tree,
512                            GtkRBNode *current,
513                            gint       height,
514                            gboolean   valid)
515 {
516   GtkRBNode *node;
517   gboolean left = TRUE;
518   GtkRBNode *tmp_node;
519   GtkRBTree *tmp_tree;
520
521 #ifdef G_ENABLE_DEBUG  
522   if (gtk_get_debug_flags () & GTK_DEBUG_TREE)
523     {
524       g_print ("\n\n_gtk_rbtree_insert_before: %p\n", current);
525       _gtk_rbtree_debug_spew (tree);
526       _gtk_rbtree_test (G_STRLOC, tree);
527     }
528 #endif /* G_ENABLE_DEBUG */
529   
530   if (current != NULL && current->left != tree->nil)
531     {
532       current = current->left;
533       while (current->right != tree->nil)
534         current = current->right;
535       left = FALSE;
536     }
537
538   /* setup new node */
539   node = _gtk_rbnode_new (tree, height);
540   node->parent = (current?current:tree->nil);
541
542   /* insert node in tree */
543   if (current)
544     {
545       if (left)
546         current->left = node;
547       else
548         current->right = node;
549       tmp_node = node->parent;
550       tmp_tree = tree;
551     }
552   else
553     {
554       tree->root = node;
555       tmp_node = tree->parent_node;
556       tmp_tree = tree->parent_tree;
557     }
558
559   while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil)
560     {
561       /* We only want to propagate the count if we are in the tree we
562        * started in. */
563       if (tmp_tree == tree)
564         tmp_node->count++;
565
566       tmp_node->total_count += 1;
567       tmp_node->offset += height;
568       tmp_node = tmp_node->parent;
569       if (tmp_node == tmp_tree->nil)
570         {
571           tmp_node = tmp_tree->parent_node;
572           tmp_tree = tmp_tree->parent_tree;
573         }
574     }
575
576   if (valid)
577     _gtk_rbtree_node_mark_valid (tree, node);
578   else
579     _gtk_rbtree_node_mark_invalid (tree, node);
580
581   _gtk_rbtree_insert_fixup (tree, node);
582
583 #ifdef G_ENABLE_DEBUG  
584   if (gtk_get_debug_flags () & GTK_DEBUG_TREE)
585     {
586       g_print ("_gtk_rbtree_insert_before finished...\n");
587       _gtk_rbtree_debug_spew (tree);
588       g_print ("\n\n");
589       _gtk_rbtree_test (G_STRLOC, tree);
590     }
591 #endif /* G_ENABLE_DEBUG */
592   
593   return node;
594 }
595
596 GtkRBNode *
597 _gtk_rbtree_find_count (GtkRBTree *tree,
598                         gint       count)
599 {
600   GtkRBNode *node;
601
602   node = tree->root;
603   while (node != tree->nil && (node->left->count + 1 != count))
604     {
605       if (node->left->count >= count)
606         node = node->left;
607       else
608         {
609           count -= (node->left->count + 1);
610           node = node->right;
611         }
612     }
613   if (node == tree->nil)
614     return NULL;
615   return node;
616 }
617
618 void
619 _gtk_rbtree_node_set_height (GtkRBTree *tree,
620                              GtkRBNode *node,
621                              gint       height)
622 {
623   gint diff = height - GTK_RBNODE_GET_HEIGHT (node);
624   GtkRBNode *tmp_node = node;
625   GtkRBTree *tmp_tree = tree;
626
627   if (diff == 0)
628     return;
629
630   while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil)
631     {
632       tmp_node->offset += diff;
633       tmp_node = tmp_node->parent;
634       if (tmp_node == tmp_tree->nil)
635         {
636           tmp_node = tmp_tree->parent_node;
637           tmp_tree = tmp_tree->parent_tree;
638         }
639     }
640 #ifdef G_ENABLE_DEBUG  
641   if (gtk_get_debug_flags () & GTK_DEBUG_TREE)
642     _gtk_rbtree_test (G_STRLOC, tree);
643 #endif
644 }
645
646 void
647 _gtk_rbtree_node_mark_invalid (GtkRBTree *tree,
648                                GtkRBNode *node)
649 {
650   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID))
651     return;
652
653   GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_INVALID);
654   do
655     {
656       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_DESCENDANTS_INVALID))
657         return;
658       GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID);
659       node = node->parent;
660       if (node == tree->nil)
661         {
662           node = tree->parent_node;
663           tree = tree->parent_tree;
664         }
665     }
666   while (node);
667 }
668
669 #if 0
670 /* Draconian version. */
671 void
672 _gtk_rbtree_node_mark_invalid (GtkRBTree *tree,
673                                GtkRBNode *node)
674 {
675   GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_INVALID);
676   do
677     {
678       _fixup_validation (tree, node);
679       node = node->parent;
680       if (node == tree->nil)
681         {
682           node = tree->parent_node;
683           tree = tree->parent_tree;
684         }
685     }
686   while (node);
687 }
688 #endif
689
690 void
691 _gtk_rbtree_node_mark_valid (GtkRBTree *tree,
692                              GtkRBNode *node)
693 {
694   if ((!GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID)) &&
695       (!GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID)))
696     return;
697
698   GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_INVALID);
699   GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_COLUMN_INVALID);
700
701   do
702     {
703       if ((GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID)) ||
704           (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID)) ||
705           (node->children && GTK_RBNODE_FLAG_SET (node->children->root, GTK_RBNODE_DESCENDANTS_INVALID)) ||
706           (node->left != tree->nil && GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID)) ||
707           (node->right != tree->nil && GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID)))
708         return;
709
710       GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID);
711       node = node->parent;
712       if (node == tree->nil)
713         {
714           node = tree->parent_node;
715           tree = tree->parent_tree;
716         }
717     }
718   while (node);
719 }
720
721 #if 0
722 /* Draconian version */
723 void
724 _gtk_rbtree_node_mark_valid (GtkRBTree *tree,
725                              GtkRBNode *node)
726 {
727   GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_INVALID);
728   GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_COLUMN_INVALID);
729
730   do
731     {
732       _fixup_validation (tree, node);
733       node = node->parent;
734       if (node == tree->nil)
735         {
736           node = tree->parent_node;
737           tree = tree->parent_tree;
738         }
739     }
740   while (node);
741 }
742 #endif
743 /* Assume tree is the root node as it doesn't set DESCENDANTS_INVALID above.
744  */
745 void
746 _gtk_rbtree_column_invalid (GtkRBTree *tree)
747 {
748   GtkRBNode *node;
749
750   if (tree == NULL)
751     return;
752   node = tree->root;
753   g_assert (node);
754
755   while (node->left != tree->nil)
756     node = node->left;
757
758   do
759     {
760       if (! (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID)))
761         GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_COLUMN_INVALID);
762       GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID);
763
764       if (node->children)
765         _gtk_rbtree_column_invalid (node->children);
766     }
767   while ((node = _gtk_rbtree_next (tree, node)) != NULL);
768 }
769
770 void
771 _gtk_rbtree_mark_invalid (GtkRBTree *tree)
772 {
773   GtkRBNode *node;
774
775   if (tree == NULL)
776     return;
777   node = tree->root;
778   g_assert (node);
779
780   while (node->left != tree->nil)
781     node = node->left;
782
783   do
784     {
785       GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_INVALID);
786       GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID);
787
788       if (node->children)
789         _gtk_rbtree_mark_invalid (node->children);
790     }
791   while ((node = _gtk_rbtree_next (tree, node)) != NULL);
792 }
793
794 void
795 _gtk_rbtree_set_fixed_height (GtkRBTree *tree,
796                               gint       height,
797                               gboolean   mark_valid)
798 {
799   GtkRBNode *node;
800
801   if (tree == NULL)
802     return;
803
804   node = tree->root;
805   g_assert (node);
806
807   while (node->left != tree->nil)
808     node = node->left;
809
810   do
811     {
812       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID))
813         {
814           _gtk_rbtree_node_set_height (tree, node, height);
815           if (mark_valid)
816             _gtk_rbtree_node_mark_valid (tree, node);
817         }
818
819       if (node->children)
820         _gtk_rbtree_set_fixed_height (node->children, height, mark_valid);
821     }
822   while ((node = _gtk_rbtree_next (tree, node)) != NULL);
823 }
824
825 typedef struct _GtkRBReorder
826 {
827   GtkRBTree *children;
828   gint height;
829   gint flags;
830   gint order;
831   gint invert_order;
832   guint total_count;
833 } GtkRBReorder;
834
835 static int
836 gtk_rbtree_reorder_sort_func (gconstpointer a,
837                               gconstpointer b)
838 {
839   return ((GtkRBReorder *) a)->order - ((GtkRBReorder *) b)->order;
840 }
841
842 static int
843 gtk_rbtree_reorder_invert_func (gconstpointer a,
844                                 gconstpointer b)
845 {
846   return ((GtkRBReorder *) a)->invert_order - ((GtkRBReorder *) b)->invert_order;
847 }
848
849 static void
850 gtk_rbtree_reorder_fixup (GtkRBTree *tree,
851                           GtkRBNode *node)
852 {
853   if (node == tree->nil)
854     return;
855
856   node->total_count = 1;
857
858   if (node->left != tree->nil)
859     {
860       gtk_rbtree_reorder_fixup (tree, node->left);
861       node->offset += node->left->offset;
862       node->total_count += node->left->total_count;
863     }
864   if (node->right != tree->nil)
865     {
866       gtk_rbtree_reorder_fixup (tree, node->right);
867       node->offset += node->right->offset;
868       node->total_count += node->right->total_count;
869     }
870       
871   if (node->children)
872     {
873       node->offset += node->children->root->offset;
874       node->total_count += node->children->root->total_count;
875     }
876   
877   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
878       (node->right != tree->nil && GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID)) ||
879       (node->left != tree->nil && GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID)) ||
880       (node->children && GTK_RBNODE_FLAG_SET (node->children->root, GTK_RBNODE_DESCENDANTS_INVALID)))
881     GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID);
882   else
883     GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID);
884 }
885
886 /* It basically pulls everything out of the tree, rearranges it, and puts it
887  * back together.  Our strategy is to keep the old RBTree intact, and just
888  * rearrange the contents.  When that is done, we go through and update the
889  * heights.  There is probably a more elegant way to write this function.  If
890  * anyone wants to spend the time writing it, patches will be accepted.
891  */
892 void
893 _gtk_rbtree_reorder (GtkRBTree *tree,
894                      gint      *new_order,
895                      gint       length)
896 {
897   GtkRBReorder reorder = { NULL };
898   GArray *array;
899   GtkRBNode *node;
900   gint i;
901   
902   g_return_if_fail (tree != NULL);
903   g_return_if_fail (length > 0);
904   g_return_if_fail (tree->root->count == length);
905   
906   /* Sort the trees values in the new tree. */
907   array = g_array_sized_new (FALSE, FALSE, sizeof (GtkRBReorder), length);
908   for (i = 0; i < length; i++)
909     {
910       reorder.order = new_order[i];
911       reorder.invert_order = i;
912       g_array_append_val (array, reorder);
913     }
914
915   g_array_sort(array, gtk_rbtree_reorder_sort_func);
916
917   /* rewind node*/
918   node = tree->root;
919   while (node && node->left != tree->nil)
920     node = node->left;
921
922   for (i = 0; i < length; i++)
923     {
924       g_assert (node != tree->nil);
925       g_array_index (array, GtkRBReorder, i).children = node->children;
926       g_array_index (array, GtkRBReorder, i).flags = GTK_RBNODE_NON_COLORS & node->flags;
927       g_array_index (array, GtkRBReorder, i).height = GTK_RBNODE_GET_HEIGHT (node);
928
929       node = _gtk_rbtree_next (tree, node);
930     }
931
932   g_array_sort (array, gtk_rbtree_reorder_invert_func);
933  
934   /* rewind node*/
935   node = tree->root;
936   while (node && node->left != tree->nil)
937     node = node->left;
938
939   /* Go through the tree and change the values to the new ones. */
940   for (i = 0; i < length; i++)
941     {
942       reorder = g_array_index (array, GtkRBReorder, i);
943       node->children = reorder.children;
944       if (node->children)
945         node->children->parent_node = node;
946       node->flags = GTK_RBNODE_GET_COLOR (node) | reorder.flags;
947       /* We temporarily set the height to this. */
948       node->offset = reorder.height;
949       node = _gtk_rbtree_next (tree, node);
950     }
951   gtk_rbtree_reorder_fixup (tree, tree->root);
952
953   g_array_free (array, TRUE);
954 }
955
956
957 gint
958 _gtk_rbtree_node_find_offset (GtkRBTree *tree,
959                               GtkRBNode *node)
960 {
961   GtkRBNode *last;
962   gint retval;
963
964   g_assert (node);
965   g_assert (node->left);
966   
967   retval = node->left->offset;
968
969   while (tree && node && node != tree->nil)
970     {
971       last = node;
972       node = node->parent;
973
974       /* Add left branch, plus children, iff we came from the right */
975       if (node->right == last)
976         retval += node->offset - node->right->offset;
977       
978       if (node == tree->nil)
979         {
980           node = tree->parent_node;
981           tree = tree->parent_tree;
982
983           /* Add the parent node, plus the left branch. */
984           if (node)
985             retval += node->left->offset + GTK_RBNODE_GET_HEIGHT (node);
986         }
987     }
988   return retval;
989 }
990
991 gint
992 _gtk_rbtree_node_find_parity (GtkRBTree *tree,
993                               GtkRBNode *node)
994 {
995   GtkRBNode *last;
996   gint retval;  
997   
998   g_assert (node);
999   g_assert (node->left);
1000   
1001   retval = node->left->total_count;
1002
1003   while (tree && node && node != tree->nil)
1004     {
1005       last = node;
1006       node = node->parent;
1007
1008       /* Add left branch, plus children, iff we came from the right */
1009       if (node->right == last)
1010         retval += node->total_count - node->right->total_count;
1011       
1012       if (node == tree->nil)
1013         {
1014           node = tree->parent_node;
1015           tree = tree->parent_tree;
1016
1017           /* Add the parent node, plus the left branch. */
1018           if (node)
1019             retval += node->left->total_count + 1; /* 1 == GTK_RBNODE_GET_PARITY() */
1020         }
1021     }
1022   
1023   return retval % 2;
1024 }
1025
1026 gint
1027 _gtk_rbtree_real_find_offset (GtkRBTree  *tree,
1028                               gint        height,
1029                               GtkRBTree **new_tree,
1030                               GtkRBNode **new_node)
1031 {
1032   GtkRBNode *tmp_node;
1033
1034   g_assert (tree);
1035
1036   if (height < 0)
1037     {
1038       *new_tree = NULL;
1039       *new_node = NULL;
1040
1041       return 0;
1042     }
1043   
1044     
1045   tmp_node = tree->root;
1046   while (tmp_node != tree->nil &&
1047          (tmp_node->left->offset > height ||
1048           (tmp_node->offset - tmp_node->right->offset) < height))
1049     {
1050       if (tmp_node->left->offset > height)
1051         tmp_node = tmp_node->left;
1052       else
1053         {
1054           height -= (tmp_node->offset - tmp_node->right->offset);
1055           tmp_node = tmp_node->right;
1056         }
1057     }
1058   if (tmp_node == tree->nil)
1059     {
1060       *new_tree = NULL;
1061       *new_node = NULL;
1062       return 0;
1063     }
1064   if (tmp_node->children)
1065     {
1066       if ((tmp_node->offset -
1067            tmp_node->right->offset -
1068            tmp_node->children->root->offset) > height)
1069         {
1070           *new_tree = tree;
1071           *new_node = tmp_node;
1072           return (height - tmp_node->left->offset);
1073         }
1074       return _gtk_rbtree_real_find_offset (tmp_node->children,
1075                                            height - tmp_node->left->offset -
1076                                            (tmp_node->offset -
1077                                             tmp_node->left->offset -
1078                                             tmp_node->right->offset -
1079                                             tmp_node->children->root->offset),
1080                                            new_tree,
1081                                            new_node);
1082     }
1083   *new_tree = tree;
1084   *new_node = tmp_node;
1085   return (height - tmp_node->left->offset);
1086 }
1087
1088 gint
1089 _gtk_rbtree_find_offset (GtkRBTree  *tree,
1090                               gint        height,
1091                               GtkRBTree **new_tree,
1092                               GtkRBNode **new_node)
1093 {
1094   g_assert (tree);
1095
1096   if ((height < 0) ||
1097       (height >= tree->root->offset))
1098     {
1099       *new_tree = NULL;
1100       *new_node = NULL;
1101
1102       return 0;
1103     }
1104   return _gtk_rbtree_real_find_offset (tree, height, new_tree, new_node);
1105 }
1106
1107 void
1108 _gtk_rbtree_remove_node (GtkRBTree *tree,
1109                          GtkRBNode *node)
1110 {
1111   GtkRBNode *x, *y;
1112   GtkRBTree *tmp_tree;
1113   GtkRBNode *tmp_node;
1114   gint y_height;
1115   
1116   g_return_if_fail (tree != NULL);
1117   g_return_if_fail (node != NULL);
1118
1119   
1120 #ifdef G_ENABLE_DEBUG
1121   if (gtk_get_debug_flags () & GTK_DEBUG_TREE)
1122     {
1123       g_print ("\n\n_gtk_rbtree_remove_node: %p\n", node);
1124       _gtk_rbtree_debug_spew (tree);
1125       _gtk_rbtree_test (G_STRLOC, tree);
1126     }
1127 #endif /* G_ENABLE_DEBUG */
1128   
1129   /* make sure we're deleting a node that's actually in the tree */
1130   for (x = node; x->parent != tree->nil; x = x->parent)
1131     ;
1132   g_return_if_fail (x == tree->root);
1133
1134 #ifdef G_ENABLE_DEBUG  
1135   if (gtk_get_debug_flags () & GTK_DEBUG_TREE)
1136     _gtk_rbtree_test (G_STRLOC, tree);
1137 #endif
1138   
1139   if (node->left == tree->nil || node->right == tree->nil)
1140     {
1141       y = node;
1142     }
1143   else
1144     {
1145       y = node->right;
1146
1147       while (y->left != tree->nil)
1148         y = y->left;
1149     }
1150
1151   /* adjust count only beneath tree */
1152   for (x = y; x != tree->nil; x = x->parent)
1153     {
1154       x->count--;
1155     }
1156
1157   /* offsets and total count adjust all the way up through parent trees */
1158   y_height = GTK_RBNODE_GET_HEIGHT (y);
1159
1160   tmp_tree = tree;
1161   tmp_node = y;
1162   while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil)
1163     {
1164       tmp_node->offset -= (y_height + (y->children?y->children->root->offset:0));
1165       _fixup_validation (tmp_tree, tmp_node);
1166       _fixup_total_count (tmp_tree, tmp_node);
1167       tmp_node = tmp_node->parent;
1168       if (tmp_node == tmp_tree->nil)
1169         {
1170           tmp_node = tmp_tree->parent_node;
1171           tmp_tree = tmp_tree->parent_tree;
1172         }
1173     }
1174
1175   /* x is y's only child, or nil */
1176   if (y->left != tree->nil)
1177     x = y->left;
1178   else
1179     x = y->right;
1180
1181   /* remove y from the parent chain */
1182   x->parent = y->parent;
1183   if (y->parent != tree->nil)
1184     {
1185       if (y == y->parent->left)
1186         y->parent->left = x;
1187       else
1188         y->parent->right = x;
1189     }
1190   else
1191     {
1192       tree->root = x;
1193     }
1194
1195   /* We need to clean up the validity of the tree.
1196    */
1197
1198   tmp_tree = tree;
1199   tmp_node = x;
1200   do
1201     {
1202       /* We skip the first time, iff x is nil */
1203       if (tmp_node != tmp_tree->nil)
1204         {
1205           _fixup_validation (tmp_tree, tmp_node);
1206           _fixup_total_count (tmp_tree, tmp_node);
1207         }
1208       tmp_node = tmp_node->parent;
1209       if (tmp_node == tmp_tree->nil)
1210         {
1211           tmp_node = tmp_tree->parent_node;
1212           tmp_tree = tmp_tree->parent_tree;
1213         }
1214     }
1215   while (tmp_tree != NULL);
1216
1217   if (y != node)
1218     {
1219       gint diff;
1220
1221       /* Copy the node over */
1222       if (GTK_RBNODE_GET_COLOR (node) == GTK_RBNODE_BLACK)
1223         node->flags = ((y->flags & (GTK_RBNODE_NON_COLORS)) | GTK_RBNODE_BLACK);
1224       else
1225         node->flags = ((y->flags & (GTK_RBNODE_NON_COLORS)) | GTK_RBNODE_RED);
1226       node->children = y->children;
1227       if (y->children)
1228         {
1229           node->children = y->children;
1230           node->children->parent_node = node;
1231         }
1232       else
1233         {
1234           node->children = NULL;
1235         }
1236       _fixup_validation (tree, node);
1237       _fixup_total_count (tree, node);
1238       /* We want to see how different our height is from the previous node.
1239        * To do this, we compare our current height with our supposed height.
1240        */
1241       diff = y_height - GTK_RBNODE_GET_HEIGHT (node);
1242       tmp_tree = tree;
1243       tmp_node = node;
1244
1245       while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil)
1246         {
1247           tmp_node->offset += diff;
1248           _fixup_validation (tmp_tree, tmp_node);
1249           _fixup_total_count (tmp_tree, tmp_node);
1250           tmp_node = tmp_node->parent;
1251           if (tmp_node == tmp_tree->nil)
1252             {
1253               tmp_node = tmp_tree->parent_node;
1254               tmp_tree = tmp_tree->parent_tree;
1255             }
1256         }
1257     }
1258
1259   if (GTK_RBNODE_GET_COLOR (y) == GTK_RBNODE_BLACK)
1260     _gtk_rbtree_remove_node_fixup (tree, x);
1261   _gtk_rbnode_free (y);
1262
1263 #ifdef G_ENABLE_DEBUG  
1264   if (gtk_get_debug_flags () & GTK_DEBUG_TREE)
1265     {
1266       g_print ("_gtk_rbtree_remove_node finished...\n");
1267       _gtk_rbtree_debug_spew (tree);
1268       g_print ("\n\n");
1269       _gtk_rbtree_test (G_STRLOC, tree);
1270     }
1271 #endif /* G_ENABLE_DEBUG */  
1272 }
1273
1274 GtkRBNode *
1275 _gtk_rbtree_next (GtkRBTree *tree,
1276                   GtkRBNode *node)
1277 {
1278   g_return_val_if_fail (tree != NULL, NULL);
1279   g_return_val_if_fail (node != NULL, NULL);
1280
1281   /* Case 1: the node's below us. */
1282   if (node->right != tree->nil)
1283     {
1284       node = node->right;
1285       while (node->left != tree->nil)
1286         node = node->left;
1287       return node;
1288     }
1289
1290   /* Case 2: it's an ancestor */
1291   while (node->parent != tree->nil)
1292     {
1293       if (node->parent->right == node)
1294         node = node->parent;
1295       else
1296         return (node->parent);
1297     }
1298
1299   /* Case 3: There is no next node */
1300   return NULL;
1301 }
1302
1303 GtkRBNode *
1304 _gtk_rbtree_prev (GtkRBTree *tree,
1305                   GtkRBNode *node)
1306 {
1307   g_return_val_if_fail (tree != NULL, NULL);
1308   g_return_val_if_fail (node != NULL, NULL);
1309
1310   /* Case 1: the node's below us. */
1311   if (node->left != tree->nil)
1312     {
1313       node = node->left;
1314       while (node->right != tree->nil)
1315         node = node->right;
1316       return node;
1317     }
1318
1319   /* Case 2: it's an ancestor */
1320   while (node->parent != tree->nil)
1321     {
1322       if (node->parent->left == node)
1323         node = node->parent;
1324       else
1325         return (node->parent);
1326     }
1327
1328   /* Case 3: There is no next node */
1329   return NULL;
1330 }
1331
1332 void
1333 _gtk_rbtree_next_full (GtkRBTree  *tree,
1334                        GtkRBNode  *node,
1335                        GtkRBTree **new_tree,
1336                        GtkRBNode **new_node)
1337 {
1338   g_return_if_fail (tree != NULL);
1339   g_return_if_fail (node != NULL);
1340   g_return_if_fail (new_tree != NULL);
1341   g_return_if_fail (new_node != NULL);
1342
1343   if (node->children)
1344     {
1345       *new_tree = node->children;
1346       *new_node = (*new_tree)->root;
1347       while ((*new_node)->left != (*new_tree)->nil)
1348         *new_node = (*new_node)->left;
1349       return;
1350     }
1351
1352   *new_tree = tree;
1353   *new_node = _gtk_rbtree_next (tree, node);
1354
1355   while ((*new_node == NULL) &&
1356          (*new_tree != NULL))
1357     {
1358       *new_node = (*new_tree)->parent_node;
1359       *new_tree = (*new_tree)->parent_tree;
1360       if (*new_tree)
1361         *new_node = _gtk_rbtree_next (*new_tree, *new_node);
1362     }
1363 }
1364
1365 void
1366 _gtk_rbtree_prev_full (GtkRBTree  *tree,
1367                        GtkRBNode  *node,
1368                        GtkRBTree **new_tree,
1369                        GtkRBNode **new_node)
1370 {
1371   g_return_if_fail (tree != NULL);
1372   g_return_if_fail (node != NULL);
1373   g_return_if_fail (new_tree != NULL);
1374   g_return_if_fail (new_node != NULL);
1375
1376   *new_tree = tree;
1377   *new_node = _gtk_rbtree_prev (tree, node);
1378
1379   if (*new_node == NULL)
1380     {
1381       *new_node = (*new_tree)->parent_node;
1382       *new_tree = (*new_tree)->parent_tree;
1383     }
1384   else
1385     {
1386       while ((*new_node)->children)
1387         {
1388           *new_tree = (*new_node)->children;
1389           *new_node = (*new_tree)->root;
1390           while ((*new_node)->right != (*new_tree)->nil)
1391             *new_node = (*new_node)->right;
1392         }
1393     }
1394 }
1395
1396 gint
1397 _gtk_rbtree_get_depth (GtkRBTree *tree)
1398 {
1399   GtkRBTree *tmp_tree;
1400   gint depth = 0;
1401
1402   tmp_tree = tree->parent_tree;
1403   while (tmp_tree)
1404     {
1405       ++depth;
1406       tmp_tree = tmp_tree->parent_tree;
1407     }
1408
1409   return depth;
1410 }
1411
1412 static void
1413 _gtk_rbtree_traverse_pre_order (GtkRBTree             *tree,
1414                                 GtkRBNode             *node,
1415                                 GtkRBTreeTraverseFunc  func,
1416                                 gpointer               data)
1417 {
1418   if (node == tree->nil)
1419     return;
1420
1421   (* func) (tree, node, data);
1422   _gtk_rbtree_traverse_pre_order (tree, node->left, func, data);
1423   _gtk_rbtree_traverse_pre_order (tree, node->right, func, data);
1424 }
1425
1426 static void
1427 _gtk_rbtree_traverse_post_order (GtkRBTree             *tree,
1428                                  GtkRBNode             *node,
1429                                  GtkRBTreeTraverseFunc  func,
1430                                  gpointer               data)
1431 {
1432   if (node == tree->nil)
1433     return;
1434
1435   _gtk_rbtree_traverse_post_order (tree, node->left, func, data);
1436   _gtk_rbtree_traverse_post_order (tree, node->right, func, data);
1437   (* func) (tree, node, data);
1438 }
1439
1440 void
1441 _gtk_rbtree_traverse (GtkRBTree             *tree,
1442                       GtkRBNode             *node,
1443                       GTraverseType          order,
1444                       GtkRBTreeTraverseFunc  func,
1445                       gpointer               data)
1446 {
1447   g_return_if_fail (tree != NULL);
1448   g_return_if_fail (node != NULL);
1449   g_return_if_fail (func != NULL);
1450   g_return_if_fail (order <= G_LEVEL_ORDER);
1451
1452   switch (order)
1453     {
1454     case G_PRE_ORDER:
1455       _gtk_rbtree_traverse_pre_order (tree, node, func, data);
1456       break;
1457     case G_POST_ORDER:
1458       _gtk_rbtree_traverse_post_order (tree, node, func, data);
1459       break;
1460     case G_IN_ORDER:
1461     case G_LEVEL_ORDER:
1462     default:
1463       g_warning ("unsupported traversal order.");
1464       break;
1465     }
1466 }
1467
1468 static inline
1469 void _fixup_validation (GtkRBTree *tree,
1470                         GtkRBNode *node)
1471 {
1472   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
1473       GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID) ||
1474       (node->left != tree->nil && GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID)) ||
1475       (node->right != tree->nil && GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID)) ||
1476       (node->children != NULL && GTK_RBNODE_FLAG_SET (node->children->root, GTK_RBNODE_DESCENDANTS_INVALID)))
1477     {
1478       GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID);
1479     }
1480   else
1481     {
1482       GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID);
1483     }
1484 }
1485
1486 static inline
1487 void _fixup_total_count (GtkRBTree *tree,
1488                     GtkRBNode *node)
1489 {
1490   node->total_count = 1 +
1491     (node->children != NULL ? node->children->root->total_count : 0) + 
1492     node->left->total_count + node->right->total_count;
1493 }
1494
1495 #ifdef G_ENABLE_DEBUG
1496 static guint
1497 get_total_count (GtkRBNode *node)
1498 {
1499   guint child_total = 0;
1500
1501   child_total += (guint) node->left->total_count;
1502   child_total += (guint) node->right->total_count;
1503
1504   if (node->children)
1505     child_total += (guint) node->children->root->total_count;
1506
1507   return child_total + 1;
1508 }
1509
1510 static guint
1511 count_total (GtkRBTree *tree,
1512              GtkRBNode *node)
1513 {
1514   guint res;
1515   
1516   if (node == tree->nil)
1517     return 0;
1518   
1519   res =
1520     count_total (tree, node->left) +
1521     count_total (tree, node->right) +
1522     (guint)1 +
1523     (node->children ? count_total (node->children, node->children->root) : 0);
1524
1525   if (res != node->total_count)
1526     g_print ("total count incorrect for node\n");
1527
1528   if (get_total_count (node) != node->total_count)
1529     g_error ("Node has incorrect total count %u, should be %u", node->total_count, get_total_count (node));
1530   
1531   return res;
1532 }
1533
1534 static gint
1535 _count_nodes (GtkRBTree *tree,
1536               GtkRBNode *node)
1537 {
1538   gint res;
1539   if (node == tree->nil)
1540     return 0;
1541
1542   g_assert (node->left);
1543   g_assert (node->right);
1544
1545   res = (_count_nodes (tree, node->left) +
1546          _count_nodes (tree, node->right) + 1);
1547
1548   if (res != node->count)
1549     g_print ("Tree failed\n");
1550   return res;
1551 }
1552
1553 static void
1554 _gtk_rbtree_test_height (GtkRBTree *tree,
1555                          GtkRBNode *node)
1556 {
1557   gint computed_offset = 0;
1558
1559   /* This whole test is sort of a useless truism. */
1560   
1561   if (node->left != tree->nil)
1562     computed_offset += node->left->offset;
1563
1564   if (node->right != tree->nil)
1565     computed_offset += node->right->offset;
1566
1567   if (node->children && node->children->root != node->children->nil)
1568     computed_offset += node->children->root->offset;
1569
1570   if (GTK_RBNODE_GET_HEIGHT (node) + computed_offset != node->offset)
1571     g_error ("node has broken offset\n");
1572
1573   if (node->left != tree->nil)
1574     _gtk_rbtree_test_height (tree, node->left);
1575
1576   if (node->right != tree->nil)
1577     _gtk_rbtree_test_height (tree, node->right);
1578
1579   if (node->children && node->children->root != node->children->nil)
1580     _gtk_rbtree_test_height (node->children, node->children->root);
1581 }
1582
1583 static void
1584 _gtk_rbtree_test_dirty (GtkRBTree *tree,
1585                         GtkRBNode *node,
1586                          gint      expected_dirtyness)
1587 {
1588
1589   if (expected_dirtyness)
1590     {
1591       g_assert (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID) ||
1592                 GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
1593                 (node->left != tree->nil && GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID)) ||
1594                 (node->right != tree->nil && GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID)) ||
1595                 (node->children && GTK_RBNODE_FLAG_SET (node->children->root, GTK_RBNODE_DESCENDANTS_INVALID)));
1596     }
1597   else
1598     {
1599       g_assert (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID) &&
1600                 ! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID));
1601       if (node->left != tree->nil)
1602         g_assert (! GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID));
1603       if (node->right != tree->nil)
1604         g_assert (! GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID));
1605       if (node->children != NULL)
1606         g_assert (! GTK_RBNODE_FLAG_SET (node->children->root, GTK_RBNODE_DESCENDANTS_INVALID));
1607     }
1608
1609   if (node->left != tree->nil)
1610     _gtk_rbtree_test_dirty (tree, node->left, GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID));
1611   if (node->right != tree->nil)
1612     _gtk_rbtree_test_dirty (tree, node->right, GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID));
1613   if (node->children != NULL && node->children->root != node->children->nil)
1614     _gtk_rbtree_test_dirty (node->children, node->children->root, GTK_RBNODE_FLAG_SET (node->children->root, GTK_RBNODE_DESCENDANTS_INVALID));
1615 }
1616
1617 static void _gtk_rbtree_test_structure (GtkRBTree *tree);
1618
1619 static void
1620 _gtk_rbtree_test_structure_helper (GtkRBTree *tree,
1621                                    GtkRBNode *node)
1622 {
1623   g_assert (node != tree->nil);
1624
1625   g_assert (node->left != NULL);
1626   g_assert (node->right != NULL);
1627   g_assert (node->parent != NULL);
1628
1629   if (node->left != tree->nil)
1630     {
1631       g_assert (node->left->parent == node);
1632       _gtk_rbtree_test_structure_helper (tree, node->left);
1633     }
1634   if (node->right != tree->nil)
1635     {
1636       g_assert (node->right->parent == node);
1637       _gtk_rbtree_test_structure_helper (tree, node->right);
1638     }
1639
1640   if (node->children != NULL)
1641     {
1642       g_assert (node->children->parent_tree == tree);
1643       g_assert (node->children->parent_node == node);
1644
1645       _gtk_rbtree_test_structure (node->children);
1646     }
1647 }
1648 static void
1649 _gtk_rbtree_test_structure (GtkRBTree *tree)
1650 {
1651   g_assert (tree->root);
1652   if (tree->root == tree->nil)
1653     return;
1654
1655   g_assert (tree->root->parent == tree->nil);
1656   _gtk_rbtree_test_structure_helper (tree, tree->root);
1657 }
1658
1659 void
1660 _gtk_rbtree_test (const gchar *where,
1661                   GtkRBTree   *tree)
1662 {
1663   GtkRBTree *tmp_tree;
1664
1665   if (tree == NULL)
1666     return;
1667
1668   /* Test the entire tree */
1669   tmp_tree = tree;
1670   while (tmp_tree->parent_tree)
1671     tmp_tree = tmp_tree->parent_tree;
1672   
1673   g_assert (tmp_tree->nil != NULL);
1674
1675   if (tmp_tree->root == tmp_tree->nil)
1676     return;
1677
1678   _gtk_rbtree_test_structure (tmp_tree);
1679
1680   g_assert ((_count_nodes (tmp_tree, tmp_tree->root->left) +
1681              _count_nodes (tmp_tree, tmp_tree->root->right) + 1) == tmp_tree->root->count);
1682       
1683       
1684   _gtk_rbtree_test_height (tmp_tree, tmp_tree->root);
1685   _gtk_rbtree_test_dirty (tmp_tree, tmp_tree->root, GTK_RBNODE_FLAG_SET (tmp_tree->root, GTK_RBNODE_DESCENDANTS_INVALID));
1686   g_assert (count_total (tmp_tree, tmp_tree->root) == tmp_tree->root->total_count);
1687 }
1688
1689 static void
1690 _gtk_rbtree_debug_spew_helper (GtkRBTree *tree,
1691                                GtkRBNode *node,
1692                                gint       depth)
1693 {
1694   gint i;
1695   for (i = 0; i < depth; i++)
1696     g_print ("\t");
1697
1698   g_print ("(%p - %s) (Offset %d) (Parity %d) (Validity %d%d%d)\n",
1699            node,
1700            (GTK_RBNODE_GET_COLOR (node) == GTK_RBNODE_BLACK)?"BLACK":" RED ",
1701            node->offset,
1702            node->total_count,
1703            (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_DESCENDANTS_INVALID))?1:0,
1704            (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID))?1:0,
1705            (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))?1:0);
1706   if (node->children != NULL)
1707     {
1708       g_print ("Looking at child.\n");
1709       _gtk_rbtree_debug_spew (node->children);
1710       g_print ("Done looking at child.\n");
1711     }
1712   if (node->left != tree->nil)
1713     {
1714       _gtk_rbtree_debug_spew_helper (tree, node->left, depth+1);
1715     }
1716   if (node->right != tree->nil)
1717     {
1718       _gtk_rbtree_debug_spew_helper (tree, node->right, depth+1);
1719     }
1720 }
1721
1722 void
1723 _gtk_rbtree_debug_spew (GtkRBTree *tree)
1724 {
1725   g_return_if_fail (tree != NULL);
1726
1727   if (tree->root == tree->nil)
1728     g_print ("Empty tree...\n");
1729   else
1730     _gtk_rbtree_debug_spew_helper (tree, tree->root, 0);
1731 }
1732 #endif /* G_ENABLE_DEBUG */