]> Pileus Git - ~andy/gtk/blob - gtk/gtktreemodel.c
Deprecation cleanup
[~andy/gtk] / gtk / gtktreemodel.c
1 /* gtktreemodel.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 <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <glib.h>
24 #include <gobject/gvaluecollector.h>
25 #include "gtktreemodel.h"
26 #include "gtktreeview.h"
27 #include "gtktreeprivate.h"
28 #include "gtkmarshalers.h"
29
30
31 #define INITIALIZE_TREE_ITER(Iter) \
32     G_STMT_START{ \
33       (Iter)->stamp = 0; \
34       (Iter)->user_data  = NULL; \
35       (Iter)->user_data2 = NULL; \
36       (Iter)->user_data3 = NULL; \
37     }G_STMT_END
38
39
40 struct _GtkTreePath
41 {
42   gint depth;
43   gint *indices;
44 };
45
46 static void gtk_tree_model_base_init (gpointer g_class);
47
48
49 GType
50 gtk_tree_model_get_type (void)
51 {
52   static GType tree_model_type = 0;
53
54   if (! tree_model_type)
55     {
56       static const GTypeInfo tree_model_info =
57       {
58         sizeof (GtkTreeModelIface), /* class_size */
59         gtk_tree_model_base_init,   /* base_init */
60         NULL,           /* base_finalize */
61         NULL,
62         NULL,           /* class_finalize */
63         NULL,           /* class_data */
64         0,
65         0,              /* n_preallocs */
66         NULL
67       };
68
69       tree_model_type =
70         g_type_register_static (G_TYPE_INTERFACE, "GtkTreeModel",
71                                 &tree_model_info, 0);
72
73       g_type_interface_add_prerequisite (tree_model_type, G_TYPE_OBJECT);
74     }
75
76   return tree_model_type;
77 }
78
79 static void
80 gtk_tree_model_base_init (gpointer g_class)
81 {
82   static gboolean initialized = FALSE;
83
84   if (! initialized)
85     {
86       g_signal_new ("row_changed",
87                     GTK_TYPE_TREE_MODEL,
88                     G_SIGNAL_RUN_LAST,
89                     G_STRUCT_OFFSET (GtkTreeModelIface, row_changed),
90                     NULL, NULL,
91                     _gtk_marshal_VOID__BOXED_BOXED,
92                     G_TYPE_NONE, 2,
93                     GTK_TYPE_TREE_PATH,
94                     GTK_TYPE_TREE_ITER);
95       g_signal_new ("row_inserted",
96                     GTK_TYPE_TREE_MODEL,
97                     G_SIGNAL_RUN_LAST,
98                     G_STRUCT_OFFSET (GtkTreeModelIface, row_inserted),
99                     NULL, NULL,
100                     _gtk_marshal_VOID__BOXED_BOXED,
101                     G_TYPE_NONE, 2,
102                     GTK_TYPE_TREE_PATH,
103                     GTK_TYPE_TREE_ITER);
104       g_signal_new ("row_has_child_toggled",
105                     GTK_TYPE_TREE_MODEL,
106                     G_SIGNAL_RUN_LAST,
107                     G_STRUCT_OFFSET (GtkTreeModelIface, row_has_child_toggled),
108                     NULL, NULL,
109                     _gtk_marshal_VOID__BOXED_BOXED,
110                     G_TYPE_NONE, 2,
111                     GTK_TYPE_TREE_PATH,
112                     GTK_TYPE_TREE_ITER);
113       g_signal_new ("row_deleted",
114                     GTK_TYPE_TREE_MODEL,
115                     G_SIGNAL_RUN_LAST,
116                     G_STRUCT_OFFSET (GtkTreeModelIface, row_deleted),
117                     NULL, NULL,
118                     _gtk_marshal_VOID__BOXED,
119                     G_TYPE_NONE, 1,
120                     GTK_TYPE_TREE_PATH);
121       g_signal_new ("rows_reordered",
122                     GTK_TYPE_TREE_MODEL,
123                     G_SIGNAL_RUN_LAST,
124                     G_STRUCT_OFFSET (GtkTreeModelIface, rows_reordered),
125                     NULL, NULL,
126                     _gtk_marshal_VOID__BOXED_BOXED_POINTER,
127                     G_TYPE_NONE, 3,
128                     GTK_TYPE_TREE_PATH,
129                     GTK_TYPE_TREE_ITER,
130                     G_TYPE_POINTER);
131       initialized = TRUE;
132     }
133 }
134
135 /**
136  * gtk_tree_path_new:
137  *
138  * Creates a new #GtkTreePath.  This structure refers to a row.
139  *
140  * Return value: A newly created #GtkTreePath.
141  **/
142 /* GtkTreePath Operations */
143 GtkTreePath *
144 gtk_tree_path_new (void)
145 {
146   GtkTreePath *retval;
147   retval = (GtkTreePath *) g_new (GtkTreePath, 1);
148   retval->depth = 0;
149   retval->indices = NULL;
150
151   return retval;
152 }
153
154 /**
155  * gtk_tree_path_new_from_string:
156  * @path: The string representation of a path.
157  *
158  * Creates a new #GtkTreePath initialized to @path.  @path is expected to be a
159  * colon separated list of numbers.  For example, the string "10:4:0" would
160  * create a path of depth 3 pointing to the 11th child of the root node, the 5th
161  * child of that 11th child, and the 1st child of that 5th child.  If an invalid
162  * path string is passed in, %NULL is returned.
163  *
164  * Return value: A newly-created #GtkTreePath, or %NULL
165  **/
166 GtkTreePath *
167 gtk_tree_path_new_from_string (const gchar *path)
168 {
169   GtkTreePath *retval;
170   const gchar *orig_path = path;
171   gchar *ptr;
172   gint i;
173
174   g_return_val_if_fail (path != NULL, NULL);
175   g_return_val_if_fail (*path != '\000', NULL);
176
177   retval = gtk_tree_path_new ();
178
179   while (1)
180     {
181       i = strtol (path, &ptr, 10);
182       gtk_tree_path_append_index (retval, i);
183
184       if (i < 0)
185         {
186           g_warning (G_STRLOC ": Negative numbers in path %s passed to gtk_tree_path_new_from_string", orig_path);
187           gtk_tree_path_free (retval);
188           return NULL;
189         }
190       if (*ptr == '\000')
191         break;
192       if (ptr == path || *ptr != ':')
193         {
194           g_warning (G_STRLOC ": Invalid path %s passed to gtk_tree_path_new_from_string", orig_path);
195           gtk_tree_path_free (retval);
196           return NULL;
197         }
198       path = ptr + 1;
199     }
200
201   return retval;
202 }
203
204 /**
205  * gtk_tree_path_new_from_indices:
206  * @first_index: first integer
207  * @varargs: list of integers terminated by -1
208  *
209  * Creates a new path with @first_index and @varargs as indices.
210  *
211  * Return value: A newly created GtkTreePath.
212  **/
213 GtkTreePath *
214 gtk_tree_path_new_from_indices (gint first_index,
215                                 ...)
216 {
217   int arg;
218   va_list args;
219   GtkTreePath *path;
220
221   path = gtk_tree_path_new ();
222
223   va_start (args, first_index);
224   arg = first_index;
225
226   while (arg != -1)
227     {
228       gtk_tree_path_append_index (path, arg);
229       arg = va_arg (args, gint);
230     }
231
232   va_end (args);
233
234   return path;
235 }
236
237 /**
238  * gtk_tree_path_to_string:
239  * @path: A #GtkTreePath
240  *
241  * Generates a string representation of the path.  This string is a ':'
242  * separated list of numbers.  For example, "4:10:0:3" would be an acceptable return value for this string.
243  *
244  * Return value: A newly-allocated string.  Must be freed with g_free().
245  **/
246 gchar *
247 gtk_tree_path_to_string (GtkTreePath *path)
248 {
249   gchar *retval, *ptr;
250   gint i;
251
252   g_return_val_if_fail (path != NULL, NULL);
253
254   if (path->depth == 0)
255     return NULL;
256
257   ptr = retval = (gchar *) g_new0 (char *, path->depth*8);
258   sprintf (retval, "%d", path->indices[0]);
259   while (*ptr != '\000')
260     ptr++;
261
262   for (i = 1; i < path->depth; i++)
263     {
264       sprintf (ptr, ":%d", path->indices[i]);
265       while (*ptr != '\000')
266         ptr++;
267     }
268
269   return retval;
270 }
271
272 /**
273  * gtk_tree_path_new_first:
274  *
275  * Creates a new #GtkTreePath.  The string representation of this path is "0"
276  *
277  * Return value: A new #GtkTreePath.
278  **/
279 GtkTreePath *
280 gtk_tree_path_new_first (void)
281 {
282   GtkTreePath *retval;
283
284   retval = gtk_tree_path_new ();
285   gtk_tree_path_append_index (retval, 0);
286
287   return retval;
288 }
289
290 /**
291  * gtk_tree_path_append_index:
292  * @path: A #GtkTreePath.
293  * @index: The index.
294  *
295  * Appends a new index to a path.  As a result, the depth of the path is
296  * increased.
297  **/
298 void
299 gtk_tree_path_append_index (GtkTreePath *path,
300                             gint         index)
301 {
302   g_return_if_fail (path != NULL);
303   g_return_if_fail (index >= 0);
304
305   path->depth += 1;
306   path->indices = g_realloc (path->indices, path->depth * sizeof(gint));
307   path->indices[path->depth - 1] = index;
308 }
309
310 /**
311  * gtk_tree_path_prepend_index:
312  * @path: A #GtkTreePath.
313  * @index: The index.
314  *
315  * Prepends a new index to a path.  As a result, the depth of the path is
316  * increased.
317  **/
318 void
319 gtk_tree_path_prepend_index (GtkTreePath *path,
320                              gint       index)
321 {
322   gint *new_indices;
323
324   (path->depth)++;
325   new_indices = g_new (gint, path->depth);
326
327   if (path->indices == NULL)
328     {
329       path->indices = new_indices;
330       path->indices[0] = index;
331       return;
332     }
333   memcpy (new_indices + 1, path->indices, (path->depth - 1)*sizeof (gint));
334   g_free (path->indices);
335   path->indices = new_indices;
336   path->indices[0] = index;
337 }
338
339 /**
340  * gtk_tree_path_get_depth:
341  * @path: A #GtkTreePath.
342  *
343  * Returns the current depth of @path.
344  *
345  * Return value: The depth of @path
346  **/
347 gint
348 gtk_tree_path_get_depth (GtkTreePath *path)
349 {
350   g_return_val_if_fail (path != NULL, 0);
351
352   return path->depth;
353 }
354
355 /**
356  * gtk_tree_path_get_indices:
357  * @path: A #GtkTreePath.
358  *
359  * Returns the current indices of @path.  This is an array of integers, each
360  * representing a node in a tree.  This value should not be freed.
361  *
362  * Return value: The current indices, or %NULL.
363  **/
364 gint *
365 gtk_tree_path_get_indices (GtkTreePath *path)
366 {
367   g_return_val_if_fail (path != NULL, NULL);
368
369   return path->indices;
370 }
371
372 /**
373  * gtk_tree_path_free:
374  * @path: A #GtkTreePath.
375  *
376  * Frees @path.
377  **/
378 void
379 gtk_tree_path_free (GtkTreePath *path)
380 {
381   g_return_if_fail (path != NULL);
382
383   g_free (path->indices);
384   g_free (path);
385 }
386
387 /**
388  * gtk_tree_path_copy:
389  * @path: A #GtkTreePath.
390  *
391  * Creates a new #GtkTreePath as a copy of @path.
392  *
393  * Return value: A new #GtkTreePath.
394  **/
395 GtkTreePath *
396 gtk_tree_path_copy (const GtkTreePath *path)
397 {
398   GtkTreePath *retval;
399
400   g_return_val_if_fail (path != NULL, NULL);
401
402   retval = g_new (GtkTreePath, 1);
403   retval->depth = path->depth;
404   retval->indices = g_new (gint, path->depth);
405   memcpy (retval->indices, path->indices, path->depth * sizeof (gint));
406   return retval;
407 }
408
409 GType
410 gtk_tree_path_get_type (void)
411 {
412   static GType our_type = 0;
413   
414   if (our_type == 0)
415     our_type = g_boxed_type_register_static ("GtkTreePath",
416                                              (GBoxedCopyFunc) gtk_tree_path_copy,
417                                              (GBoxedFreeFunc) gtk_tree_path_free);
418
419   return our_type;
420 }
421
422 /**
423  * gtk_tree_path_compare:
424  * @a: A #GtkTreePath.
425  * @b: A #GtkTreePath to compare with.
426  *
427  * Compares two paths.  If @a appears before @b in a tree, then -1 is returned.
428  * If @b appears before @a, then 1 is returned.  If the two nodes are equal,
429  * then 0 is returned.
430  *
431  * Return value: The relative positions of @a and @b
432  **/
433 gint
434 gtk_tree_path_compare (const GtkTreePath *a,
435                        const GtkTreePath *b)
436 {
437   gint p = 0, q = 0;
438
439   g_return_val_if_fail (a != NULL, 0);
440   g_return_val_if_fail (b != NULL, 0);
441   g_return_val_if_fail (a->depth > 0, 0);
442   g_return_val_if_fail (b->depth > 0, 0);
443
444   do
445     {
446       if (a->indices[p] == b->indices[q])
447         continue;
448       return (a->indices[p] < b->indices[q]?-1:1);
449     }
450   while (++p < a->depth && ++q < b->depth);
451   if (a->depth == b->depth)
452     return 0;
453   return (a->depth < b->depth?-1:1);
454 }
455
456 /**
457  * gtk_tree_path_is_ancestor:
458  * @path: a #GtkTreePath
459  * @descendant: another #GtkTreePath
460  *
461  * Returns %TRUE if @descendant is a descendant of @path.
462  *
463  * Return value: %TRUE if @descendant is contained inside @path
464  **/
465 gboolean
466 gtk_tree_path_is_ancestor (GtkTreePath *path,
467                            GtkTreePath *descendant)
468 {
469   gint i;
470
471   g_return_val_if_fail (path != NULL, FALSE);
472   g_return_val_if_fail (descendant != NULL, FALSE);
473
474   /* can't be an ancestor if we're deeper */
475   if (path->depth >= descendant->depth)
476     return FALSE;
477
478   i = 0;
479   while (i < path->depth)
480     {
481       if (path->indices[i] != descendant->indices[i])
482         return FALSE;
483       ++i;
484     }
485
486   return TRUE;
487 }
488
489 /**
490  * gtk_tree_path_is_descendant:
491  * @path: a #GtkTreePath
492  * @ancestor: another #GtkTreePath
493  *
494  * Returns %TRUE if @path is a descendant of @ancestor.
495  *
496  * Return value: %TRUE if @ancestor contains @path somewhere below it
497  **/
498 gboolean
499 gtk_tree_path_is_descendant (GtkTreePath *path,
500                              GtkTreePath *ancestor)
501 {
502   gint i;
503
504   g_return_val_if_fail (path != NULL, FALSE);
505   g_return_val_if_fail (ancestor != NULL, FALSE);
506
507   /* can't be a descendant if we're shallower in the tree */
508   if (path->depth <= ancestor->depth)
509     return FALSE;
510
511   i = 0;
512   while (i < ancestor->depth)
513     {
514       if (path->indices[i] != ancestor->indices[i])
515         return FALSE;
516       ++i;
517     }
518
519   return TRUE;
520 }
521
522
523 /**
524  * gtk_tree_path_next:
525  * @path: A #GtkTreePath.
526  *
527  * Moves the @path to point to the next node at the current depth.
528  **/
529 void
530 gtk_tree_path_next (GtkTreePath *path)
531 {
532   g_return_if_fail (path != NULL);
533   g_return_if_fail (path->depth > 0);
534
535   path->indices[path->depth - 1] ++;
536 }
537
538 /**
539  * gtk_tree_path_prev:
540  * @path: A #GtkTreePath.
541  *
542  * Moves the @path to point to the previous node at the current depth, if it exists.
543  *
544  * Return value: %TRUE if @path has a previous node, and the move was made.
545  **/
546 gboolean
547 gtk_tree_path_prev (GtkTreePath *path)
548 {
549   g_return_val_if_fail (path != NULL, FALSE);
550
551   if (path->indices[path->depth - 1] == 0)
552     return FALSE;
553
554   path->indices[path->depth - 1] -= 1;
555
556   return TRUE;
557 }
558
559 /**
560  * gtk_tree_path_up:
561  * @path: A #GtkTreePath.
562  *
563  * Moves the @path to point to it's parent node, if it has a parent.
564  *
565  * Return value: %TRUE if @path has a parent, and the move was made.
566  **/
567 gboolean
568 gtk_tree_path_up (GtkTreePath *path)
569 {
570   g_return_val_if_fail (path != NULL, FALSE);
571
572   if (path->depth == 0)
573     return FALSE;
574
575   path->depth--;
576
577   return TRUE;
578 }
579
580 /**
581  * gtk_tree_path_down:
582  * @path: A #GtkTreePath.
583  *
584  * Moves @path to point to the first child of the current path.
585  **/
586 void
587 gtk_tree_path_down (GtkTreePath *path)
588 {
589   g_return_if_fail (path != NULL);
590
591   gtk_tree_path_append_index (path, 0);
592 }
593
594 /**
595  * gtk_tree_iter_copy:
596  * @iter: A #GtkTreeIter.
597  *
598  * Creates a dynamically allocated tree iterator as a copy of @iter.  This
599  * function is not intended for use in applications, because you can just copy
600  * the structs by value (<literal>GtkTreeIter new_iter = iter;</literal>).  You
601  * must free this iter with gtk_tree_iter_free ().
602  *
603  * Return value: a newly-allocated copy of @iter.
604  **/
605 GtkTreeIter *
606 gtk_tree_iter_copy (GtkTreeIter *iter)
607 {
608   GtkTreeIter *retval;
609
610   g_return_val_if_fail (iter != NULL, NULL);
611
612   retval = g_new (GtkTreeIter, 1);
613   *retval = *iter;
614
615   return retval;
616 }
617
618 /**
619  * gtk_tree_iter_free:
620  * @iter: A dynamically allocated tree iterator.
621  *
622  * Frees an iterator that has been allocated on the heap.  This function is
623  * mainly used for language bindings.
624  **/
625 void
626 gtk_tree_iter_free (GtkTreeIter *iter)
627 {
628   g_return_if_fail (iter != NULL);
629
630   g_free (iter);
631 }
632
633 GType
634 gtk_tree_iter_get_type (void)
635 {
636   static GType our_type = 0;
637   
638   if (our_type == 0)
639     our_type = g_boxed_type_register_static ("GtkTreeIter",
640                                              (GBoxedCopyFunc) gtk_tree_iter_copy,
641                                              (GBoxedFreeFunc) gtk_tree_iter_free);
642
643   return our_type;
644 }
645
646 /**
647  * gtk_tree_model_get_flags:
648  * @tree_model: A #GtkTreeModel.
649  *
650  * Returns a set of flags supported by this interface.  The flags are a bitwise
651  * combination of #GtkTreeModelFlags.  The flags supported should not change
652  * during the lifecycle of the tree_model.
653  *
654  * Return value: The flags supported by this interface.
655  **/
656 GtkTreeModelFlags
657 gtk_tree_model_get_flags (GtkTreeModel *tree_model)
658 {
659   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), 0);
660
661   if (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_flags)
662     return (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_flags) (tree_model);
663
664   return 0;
665 }
666
667 /**
668  * gtk_tree_model_get_n_columns:
669  * @tree_model: A #GtkTreeModel.
670  *
671  * Returns the number of columns supported by @tree_model.
672  *
673  * Return value: The number of columns.
674  **/
675 gint
676 gtk_tree_model_get_n_columns (GtkTreeModel *tree_model)
677 {
678   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), 0);
679   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_n_columns != NULL, 0);
680
681   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_n_columns) (tree_model);
682 }
683
684 /**
685  * gtk_tree_model_get_column_type:
686  * @tree_model: A #GtkTreeModel.
687  * @index: The column index.
688  *
689  * Returns the type of the column.
690  *
691  * Return value: The type of the column.
692  **/
693 GType
694 gtk_tree_model_get_column_type (GtkTreeModel *tree_model,
695                                 gint          index)
696 {
697   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), G_TYPE_INVALID);
698   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_column_type != NULL, G_TYPE_INVALID);
699   g_return_val_if_fail (index >= 0, G_TYPE_INVALID);
700
701   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_column_type) (tree_model, index);
702 }
703
704 /**
705  * gtk_tree_model_get_iter:
706  * @tree_model: A #GtkTreeModel.
707  * @iter: The uninitialized #GtkTreeIter.
708  * @path: The #GtkTreePath.
709  *
710  * Sets @iter to a valid iterator pointing to @path.
711  *
712  * Return value: %TRUE, if @iter was set.
713  **/
714 gboolean
715 gtk_tree_model_get_iter (GtkTreeModel *tree_model,
716                          GtkTreeIter  *iter,
717                          GtkTreePath  *path)
718 {
719   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
720   g_return_val_if_fail (iter != NULL, FALSE);
721   g_return_val_if_fail (path != NULL, FALSE);
722   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_iter != NULL, FALSE);
723   g_return_val_if_fail (path->depth > 0, FALSE);
724
725   INITIALIZE_TREE_ITER (iter);
726
727   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_iter) (tree_model, iter, path);
728 }
729
730 /**
731  * gtk_tree_model_get_iter_from_string:
732  * @tree_model: A #GtkTreeModel.
733  * @iter: An uninitialized #GtkTreeIter.
734  * @path_string: A string representation of a #GtkTreePath.
735  *
736  * Sets @iter to a valid iterator pointing to @path_string, if it
737  * exists. Otherwise, @iter is left invalid and %FALSE is returned.
738  *
739  * Return value: %TRUE, if @iter was set.
740  **/
741 gboolean
742 gtk_tree_model_get_iter_from_string (GtkTreeModel *tree_model,
743                                      GtkTreeIter  *iter,
744                                      const gchar  *path_string)
745 {
746   gboolean retval;
747   GtkTreePath *path;
748
749   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
750   g_return_val_if_fail (iter != NULL, FALSE);
751   g_return_val_if_fail (path_string != NULL, FALSE);
752   
753   path = gtk_tree_path_new_from_string (path_string);
754   
755   g_return_val_if_fail (path != NULL, FALSE);
756
757   retval = gtk_tree_model_get_iter (tree_model, iter, path);
758   gtk_tree_path_free (path);
759   
760   return retval;
761 }
762
763 /**
764  * gtk_tree_model_get_string_from_iter:
765  * @tree_model: A #GtkTreeModel.
766  * @iter: An #GtkTreeIter.
767  *
768  * Generates a string representation of the iter. This string is a ':'
769  * separated list of numbers. For example, "4:10:0:3" would be an
770  * acceptable return value for this string.
771  *
772  * Return value: A newly-allocated string. Must be freed with g_free().
773  **/
774 gchar *
775 gtk_tree_model_get_string_from_iter (GtkTreeModel *tree_model,
776                                      GtkTreeIter  *iter)
777 {
778   GtkTreePath *path;
779   gchar *ret;
780
781   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), NULL);
782   g_return_val_if_fail (iter != NULL, NULL);
783
784   path = gtk_tree_model_get_path (tree_model, iter);
785
786   g_return_val_if_fail (path != NULL, NULL);
787
788   ret = gtk_tree_path_to_string (path);
789   gtk_tree_path_free (path);
790
791   return ret;
792 }
793
794 /**
795  * gtk_tree_model_get_iter_first:
796  * @tree_model: A #GtkTreeModel.
797  * @iter: The uninitialized #GtkTreeIter.
798  * 
799  * Initializes @iter with the first iterator in the tree (the one at the path
800  * "0") and returns %TRUE.  Returns %FALSE if the tree is empty.
801  * 
802  * Return value: %TRUE, if @iter was set.
803  **/
804 gboolean
805 gtk_tree_model_get_iter_first (GtkTreeModel *tree_model,
806                                GtkTreeIter  *iter)
807 {
808   GtkTreePath *path;
809   gboolean retval;
810
811   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
812   g_return_val_if_fail (iter != NULL, FALSE);
813
814   path = gtk_tree_path_new_first ();
815   retval = gtk_tree_model_get_iter (tree_model, iter, path);
816   gtk_tree_path_free (path);
817
818   return retval;
819 }
820
821 /**
822  * gtk_tree_model_get_path:
823  * @tree_model: A #GtkTreeModel.
824  * @iter: The #GtkTreeIter.
825  *
826  * Returns a newly-created #GtkTreePath referenced by @iter.  This path should
827  * be freed with gtk_tree_path_free().
828  *
829  * Return value: a newly-created #GtkTreePath.
830  **/
831 GtkTreePath *
832 gtk_tree_model_get_path (GtkTreeModel *tree_model,
833                          GtkTreeIter  *iter)
834 {
835   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), NULL);
836   g_return_val_if_fail (iter != NULL, NULL);
837   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_path != NULL, NULL);
838
839   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_path) (tree_model, iter);
840 }
841
842 /**
843  * gtk_tree_model_get_value:
844  * @tree_model: A #GtkTreeModel.
845  * @iter: The #GtkTreeIter.
846  * @column: The column to lookup the value at.
847  * @value: An empty #GValue to set.
848  *
849  * Sets initializes and sets @value to that at @column.  When done with @value,
850  * g_value_unset() needs to be called to free any allocated memory.
851  **/
852 void
853 gtk_tree_model_get_value (GtkTreeModel *tree_model,
854                           GtkTreeIter  *iter,
855                           gint          column,
856                           GValue       *value)
857 {
858   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
859   g_return_if_fail (iter != NULL);
860   g_return_if_fail (value != NULL);
861   g_return_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_value != NULL);
862
863   (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_value) (tree_model, iter, column, value);
864 }
865
866 /**
867  * gtk_tree_model_iter_next:
868  * @tree_model: A #GtkTreeModel.
869  * @iter: The #GtkTreeIter.
870  *
871  * Sets @iter to point to the node following it at the current level.  If there
872  * is no next @iter, %FALSE is returned and @iter is set to be invalid.
873  *
874  * Return value: %TRUE if @iter has been changed to the next node.
875  **/
876 gboolean
877 gtk_tree_model_iter_next (GtkTreeModel  *tree_model,
878                           GtkTreeIter   *iter)
879 {
880   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
881   g_return_val_if_fail (iter != NULL, FALSE);
882   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_next != NULL, FALSE);
883
884   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_next) (tree_model, iter);
885 }
886
887 /**
888  * gtk_tree_model_iter_children:
889  * @tree_model: A #GtkTreeModel.
890  * @iter: The new #GtkTreeIter to be set to the child.
891  * @parent: The #GtkTreeIter, or %NULL
892  *
893  * Sets @iter to point to the first child of @parent.  If @parent has no children,
894  * %FALSE is returned and @iter is set to be invalid.  @parent will remain a valid
895  * node after this function has been called.
896  *
897  * If @parent is %NULL returns the first node, equivalent to
898  * <literal>gtk_tree_model_get_iter_first (tree_model, iter);</literal>
899  *
900  * Return value: %TRUE, if @child has been set to the first child.
901  **/
902 gboolean
903 gtk_tree_model_iter_children (GtkTreeModel *tree_model,
904                               GtkTreeIter  *iter,
905                               GtkTreeIter  *parent)
906 {
907   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
908   g_return_val_if_fail (iter != NULL, FALSE);
909   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_children != NULL, FALSE);
910
911   INITIALIZE_TREE_ITER (iter);
912
913   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_children) (tree_model, iter, parent);
914 }
915
916 /**
917  * gtk_tree_model_iter_has_child:
918  * @tree_model: A #GtkTreeModel.
919  * @iter: The #GtkTreeIter to test for children.
920  *
921  * Returns %TRUE if @iter has children, %FALSE otherwise.
922  *
923  * Return value: %TRUE if @iter has children.
924  **/
925 gboolean
926 gtk_tree_model_iter_has_child (GtkTreeModel *tree_model,
927                                GtkTreeIter  *iter)
928 {
929   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
930   g_return_val_if_fail (iter != NULL, FALSE);
931   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_has_child != NULL, FALSE);
932
933   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_has_child) (tree_model, iter);
934 }
935
936 /**
937  * gtk_tree_model_iter_n_children:
938  * @tree_model: A #GtkTreeModel.
939  * @iter: The #GtkTreeIter, or %NULL.
940  *
941  * Returns the number of children that @iter has.  As a special case, if @iter
942  * is %NULL, then the number of toplevel nodes is returned.
943  *
944  * Return value: The number of children of @iter.
945  **/
946 gint
947 gtk_tree_model_iter_n_children (GtkTreeModel *tree_model,
948                                 GtkTreeIter  *iter)
949 {
950   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), 0);
951   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_n_children != NULL, 0);
952
953   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_n_children) (tree_model, iter);
954 }
955
956 /**
957  * gtk_tree_model_iter_nth_child:
958  * @tree_model: A #GtkTreeModel.
959  * @iter: The #GtkTreeIter to set to the nth child.
960  * @parent: The #GtkTreeIter to get the child from, or %NULL.
961  * @n: Then index of the desired child.
962  *
963  * Sets @iter to be the child of @parent, using the given index.  The first
964  * index is 0.  If @index is too big, or @parent has no children, @iter is set
965  * to an invalid iterator and %FALSE is returned.  @parent will remain a valid
966  * node after this function has been called.  As a special case, if @parent is
967  * %NULL, then the @n<!-- -->th root node is set.
968  *
969  * Return value: %TRUE, if @parent has an @n<!-- -->th child.
970  **/
971 gboolean
972 gtk_tree_model_iter_nth_child (GtkTreeModel *tree_model,
973                                GtkTreeIter  *iter,
974                                GtkTreeIter  *parent,
975                                gint          n)
976 {
977   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
978   g_return_val_if_fail (iter != NULL, FALSE);
979   g_return_val_if_fail (n >= 0, FALSE);
980   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_nth_child != NULL, FALSE);
981
982   INITIALIZE_TREE_ITER (iter);
983
984   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_nth_child) (tree_model, iter, parent, n);
985 }
986
987 /**
988  * gtk_tree_model_iter_parent:
989  * @tree_model: A #GtkTreeModel
990  * @iter: The new #GtkTreeIter to set to the parent.
991  * @child: The #GtkTreeIter.
992  *
993  * Sets @iter to be the parent of @child.  If @child is at the toplevel, and
994  * doesn't have a parent, then @iter is set to an invalid iterator and %FALSE
995  * is returned.  @child will remain a valid node after this function has been
996  * called.
997  *
998  * Return value: %TRUE, if @iter is set to the parent of @child.
999  **/
1000 gboolean
1001 gtk_tree_model_iter_parent (GtkTreeModel *tree_model,
1002                             GtkTreeIter  *iter,
1003                             GtkTreeIter  *child)
1004 {
1005   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1006   g_return_val_if_fail (iter != NULL, FALSE);
1007   g_return_val_if_fail (child != NULL, FALSE);
1008   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_parent != NULL, FALSE);
1009
1010   INITIALIZE_TREE_ITER (iter);
1011
1012   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_parent) (tree_model, iter, child);
1013 }
1014
1015 /**
1016  * gtk_tree_model_ref_node:
1017  * @tree_model: A #GtkTreeModel.
1018  * @iter: The #GtkTreeIter.
1019  *
1020  * Lets the tree ref the node.  This is an optional method for models to
1021  * implement.  To be more specific, models may ignore this call as it exists
1022  * primarily for performance reasons.
1023  * 
1024  * This function is primarily meant as a way for views to let caching model know
1025  * when nodes are being displayed (and hence, whether or not to cache that
1026  * node.)  For example, a file-system based model would not want to keep the
1027  * entire file-hierarchy in memory, just the sections that are currently being
1028  * displayed by every current view.
1029  *
1030  * A model should be expected to be able to get an iter independent of it's
1031  * reffed state.
1032  **/
1033 void
1034 gtk_tree_model_ref_node (GtkTreeModel *tree_model,
1035                          GtkTreeIter  *iter)
1036 {
1037   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1038
1039   if (GTK_TREE_MODEL_GET_IFACE (tree_model)->ref_node)
1040     (* GTK_TREE_MODEL_GET_IFACE (tree_model)->ref_node) (tree_model, iter);
1041 }
1042
1043 /**
1044  * gtk_tree_model_unref_node:
1045  * @tree_model: A #GtkTreeModel.
1046  * @iter: The #GtkTreeIter.
1047  *
1048  * Lets the tree unref the node.  This is an optional method for models to
1049  * implement.  To be more specific, models may ignore this call as it exists
1050  * primarily for performance reasons.
1051  *
1052  * For more information on what this means, see gtk_tree_model_ref_node().
1053  * Please note that nodes that are deleted are not unreffed.
1054  **/
1055 void
1056 gtk_tree_model_unref_node (GtkTreeModel *tree_model,
1057                            GtkTreeIter  *iter)
1058 {
1059   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1060   g_return_if_fail (iter != NULL);
1061
1062   if (GTK_TREE_MODEL_GET_IFACE (tree_model)->unref_node)
1063     (* GTK_TREE_MODEL_GET_IFACE (tree_model)->unref_node) (tree_model, iter);
1064 }
1065
1066 /**
1067  * gtk_tree_model_get:
1068  * @tree_model: a #GtkTreeModel
1069  * @iter: a row in @tree_model
1070  * @Varargs: pairs of column number and value return locations, terminated by -1
1071  *
1072  * Gets the value of one or more cells in the row referenced by @iter.
1073  * The variable argument list should contain integer column numbers,
1074  * each column number followed by a place to store the value being
1075  * retrieved.  The list is terminated by a -1. For example, to get a
1076  * value from column 0 with type %G_TYPE_STRING, you would
1077  * write: <literal>gtk_tree_model_get (model, iter, 0, &amp;place_string_here, -1)</literal>,
1078  * where <literal>place_string_here</literal> is a <type>gchar*</type> to be 
1079  * filled with the string.
1080  * If appropriate, the returned values have to be freed or unreferenced.
1081  *
1082  **/
1083 void
1084 gtk_tree_model_get (GtkTreeModel *tree_model,
1085                     GtkTreeIter  *iter,
1086                     ...)
1087 {
1088   va_list var_args;
1089
1090   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1091   g_return_if_fail (iter != NULL);
1092
1093   va_start (var_args, iter);
1094   gtk_tree_model_get_valist (tree_model, iter, var_args);
1095   va_end (var_args);
1096 }
1097
1098 /**
1099  * gtk_tree_model_get_valist:
1100  * @tree_model: a #GtkTreeModel
1101  * @iter: a row in @tree_model
1102  * @var_args: <type>va_list</type> of column/return location pairs
1103  *
1104  * See gtk_tree_model_get(), this version takes a <type>va_list</type> 
1105  * for language bindings to use.
1106  **/
1107 void
1108 gtk_tree_model_get_valist (GtkTreeModel *tree_model,
1109                            GtkTreeIter  *iter,
1110                            va_list      var_args)
1111 {
1112   gint column;
1113
1114   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1115   g_return_if_fail (iter != NULL);
1116
1117   column = va_arg (var_args, gint);
1118
1119   while (column != -1)
1120     {
1121       GValue value = { 0, };
1122       gchar *error = NULL;
1123
1124       if (column >= gtk_tree_model_get_n_columns (tree_model))
1125         {
1126           g_warning ("%s: Invalid column number %d accessed (remember to end your list of columns with a -1)", G_STRLOC, column);
1127           break;
1128         }
1129
1130       gtk_tree_model_get_value (GTK_TREE_MODEL (tree_model), iter, column, &value);
1131
1132       G_VALUE_LCOPY (&value, var_args, 0, &error);
1133       if (error)
1134         {
1135           g_warning ("%s: %s", G_STRLOC, error);
1136           g_free (error);
1137
1138           /* we purposely leak the value here, it might not be
1139            * in a sane state if an error condition occoured
1140            */
1141           break;
1142         }
1143
1144       g_value_unset (&value);
1145
1146       column = va_arg (var_args, gint);
1147     }
1148 }
1149
1150 /**
1151  * gtk_tree_model_row_changed:
1152  * @tree_model: A #GtkTreeModel
1153  * @path: A #GtkTreePath pointing to the changed row
1154  * @iter: A valid #GtkTreeIter pointing to the changed row
1155  * 
1156  * Emits the "row_changed" signal on @tree_model.
1157  **/
1158 void
1159 gtk_tree_model_row_changed (GtkTreeModel *tree_model,
1160                             GtkTreePath  *path,
1161                             GtkTreeIter  *iter)
1162 {
1163   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1164   g_return_if_fail (path != NULL);
1165   g_return_if_fail (iter != NULL);
1166
1167   g_signal_emit_by_name (tree_model, "row_changed", path, iter);
1168 }
1169
1170 /**
1171  * gtk_tree_model_row_inserted:
1172  * @tree_model: A #GtkTreeModel
1173  * @path: A #GtkTreePath pointing to the inserted row
1174  * @iter: A valid #GtkTreeIter pointing to the inserted row
1175  * 
1176  * Emits the "row_inserted" signal on @tree_model
1177  **/
1178 void
1179 gtk_tree_model_row_inserted (GtkTreeModel *tree_model,
1180                              GtkTreePath  *path,
1181                              GtkTreeIter  *iter)
1182 {
1183   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1184   g_return_if_fail (path != NULL);
1185   g_return_if_fail (iter != NULL);
1186
1187   g_signal_emit_by_name (tree_model, "row_inserted", path, iter);
1188 }
1189
1190 /**
1191  * gtk_tree_model_row_has_child_toggled:
1192  * @tree_model: A #GtkTreeModel
1193  * @path: A #GtkTreePath pointing to the changed row
1194  * @iter: A valid #GtkTreeIter pointing to the changed row
1195  * 
1196  * Emits the "row_has_child_toggled" signal on @tree_model.  This should be
1197  * called by models after the child state of a node changes.
1198  **/
1199 void
1200 gtk_tree_model_row_has_child_toggled (GtkTreeModel *tree_model,
1201                                       GtkTreePath  *path,
1202                                       GtkTreeIter  *iter)
1203 {
1204   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1205   g_return_if_fail (path != NULL);
1206   g_return_if_fail (iter != NULL);
1207
1208   g_signal_emit_by_name (tree_model, "row_has_child_toggled", path, iter);
1209 }
1210
1211 /**
1212  * gtk_tree_model_row_deleted:
1213  * @tree_model: A #GtkTreeModel
1214  * @path: A #GtkTreePath pointing to the previous location of the deleted row.
1215  * 
1216  * Emits the "row_deleted" signal on @tree_model.  This should be called by
1217  * models after a row has been removed.  The location pointed to by @path should
1218  * be the location that the row previously was at.  It may not be a valid
1219  * location anymore.
1220  **/
1221 void
1222 gtk_tree_model_row_deleted (GtkTreeModel *tree_model,
1223                             GtkTreePath  *path)
1224 {
1225   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1226   g_return_if_fail (path != NULL);
1227
1228   g_signal_emit_by_name (tree_model, "row_deleted", path);
1229 }
1230
1231 /**
1232  * gtk_tree_model_rows_reordered:
1233  * @tree_model: A #GtkTreeModel
1234  * @path: A #GtkTreePath pointing to the tree node whose children have been reordered
1235  * @iter: A valid #GtkTreeIter pointing to the node whose children have been reordered
1236  * @new_order: an array of integers containing the new indices of the children,
1237  *      i.e. the former child <literal>n</literal> is now at position
1238  *      @new_order<literal>[n]</literal>. 
1239  * 
1240  * Emits the "rows_reordered" signal on @tree_model.  This should be called by
1241  * models when their rows have been reordered.  
1242  **/
1243 void
1244 gtk_tree_model_rows_reordered (GtkTreeModel *tree_model,
1245                                GtkTreePath  *path,
1246                                GtkTreeIter  *iter,
1247                                gint         *new_order)
1248 {
1249   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1250   g_return_if_fail (new_order != NULL);
1251
1252   g_signal_emit_by_name (tree_model, "rows_reordered", path, iter, new_order);
1253 }
1254
1255
1256 static gboolean
1257 gtk_tree_model_foreach_helper (GtkTreeModel            *model,
1258                                GtkTreeIter             *iter,
1259                                GtkTreePath             *path,
1260                                GtkTreeModelForeachFunc  func,
1261                                gpointer                 user_data)
1262 {
1263   do
1264     {
1265       GtkTreeIter child;
1266
1267       if ((* func) (model, path, iter, user_data))
1268         return TRUE;
1269
1270       if (gtk_tree_model_iter_children (model, &child, iter))
1271         {
1272           gtk_tree_path_down (path);
1273           if (gtk_tree_model_foreach_helper (model, &child, path, func, user_data))
1274             return TRUE;
1275           gtk_tree_path_up (path);
1276         }
1277
1278       gtk_tree_path_next (path);
1279     }
1280   while (gtk_tree_model_iter_next (model, iter));
1281
1282   return FALSE;
1283 }
1284
1285 /**
1286  * gtk_tree_model_foreach:
1287  * @model: A #GtkTreeModel
1288  * @func: A function to be called on each row
1289  * @user_data: User data to passed to func.
1290  * 
1291  * Calls func on each node in model in a depth-first fashion.  If func returns
1292  * %TRUE, then the tree ceases to be walked, and gtk_tree_model_foreach() returns.
1293  **/
1294
1295 void
1296 gtk_tree_model_foreach (GtkTreeModel            *model,
1297                         GtkTreeModelForeachFunc  func,
1298                         gpointer                 user_data)
1299 {
1300   GtkTreePath *path;
1301   GtkTreeIter iter;
1302
1303   g_return_if_fail (GTK_IS_TREE_MODEL (model));
1304   g_return_if_fail (func != NULL);
1305
1306   path = gtk_tree_path_new_first ();
1307   if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
1308     {
1309       gtk_tree_path_free (path);
1310       return;
1311     }
1312
1313   gtk_tree_model_foreach_helper (model, &iter, path, func, user_data);
1314   gtk_tree_path_free (path);
1315 }
1316
1317
1318 /*
1319  * GtkTreeRowReference
1320  */
1321
1322 static void gtk_tree_row_reference_unref_path (GtkTreePath  *path,
1323                                                GtkTreeModel *model,
1324                                                gint          depth);
1325
1326
1327 GType
1328 gtk_tree_row_reference_get_type (void)
1329 {
1330   static GType our_type = 0;
1331   
1332   if (our_type == 0)
1333     our_type = g_boxed_type_register_static ("GtkTreeRowReference",
1334                                              (GBoxedCopyFunc) gtk_tree_row_reference_copy,
1335                                              (GBoxedFreeFunc) gtk_tree_row_reference_free);
1336
1337   return our_type;
1338 }
1339
1340
1341 #define ROW_REF_DATA_STRING "gtk-tree-row-refs"
1342
1343 struct _GtkTreeRowReference
1344 {
1345   GObject *proxy;
1346   GtkTreeModel *model;
1347   GtkTreePath *path;
1348 };
1349
1350 typedef struct
1351 {
1352   GSList *list;
1353 } RowRefList;
1354
1355
1356 static void
1357 release_row_references (gpointer data)
1358 {
1359   RowRefList *refs = data;
1360   GSList *tmp_list = NULL;
1361
1362   tmp_list = refs->list;
1363   while (tmp_list != NULL)
1364     {
1365       GtkTreeRowReference *reference = tmp_list->data;
1366
1367       if (reference->proxy == (GObject *)reference->model)
1368         reference->model = NULL;
1369       reference->proxy = NULL;
1370
1371       /* we don't free the reference, users are responsible for that. */
1372
1373       tmp_list = g_slist_next (tmp_list);
1374     }
1375
1376   g_slist_free (refs->list);
1377   g_free (refs);
1378 }
1379
1380 static void
1381 gtk_tree_row_ref_inserted_callback (GObject     *object,
1382                                     GtkTreePath *path,
1383                                     GtkTreeIter *iter,
1384                                     gpointer     data)
1385 {
1386   RowRefList *refs = g_object_get_data (data, ROW_REF_DATA_STRING);
1387
1388   GSList *tmp_list;
1389
1390   if (refs == NULL)
1391     return;
1392
1393   /* This function corrects the path stored in the reference to
1394    * account for an insertion. Note that it's called _after_ the insertion
1395    * with the path to the newly-inserted row. Which means that
1396    * the inserted path is in a different "coordinate system" than
1397    * the old path (e.g. if the inserted path was just before the old path,
1398    * then inserted path and old path will be the same, and old path must be
1399    * moved down one).
1400    */
1401
1402   tmp_list = refs->list;
1403
1404   while (tmp_list != NULL)
1405     {
1406       GtkTreeRowReference *reference = tmp_list->data;
1407
1408       if (reference->path == NULL)
1409         goto done;
1410
1411       if (reference->path->depth >= path->depth)
1412         {
1413           gint i;
1414           gboolean ancestor = TRUE;
1415
1416           for (i = 0; i < path->depth - 1; i ++)
1417             {
1418               if (path->indices[i] != reference->path->indices[i])
1419                 {
1420                   ancestor = FALSE;
1421                   break;
1422                 }
1423             }
1424           if (ancestor == FALSE)
1425             goto done;
1426
1427           if (path->indices[path->depth-1] <= reference->path->indices[path->depth-1])
1428             reference->path->indices[path->depth-1] += 1;
1429         }
1430     done:
1431       tmp_list = g_slist_next (tmp_list);
1432     }
1433 }
1434
1435 static void
1436 gtk_tree_row_ref_deleted_callback (GObject     *object,
1437                                    GtkTreePath *path,
1438                                    gpointer     data)
1439 {
1440   RowRefList *refs = g_object_get_data (data, ROW_REF_DATA_STRING);
1441   GSList *tmp_list;
1442
1443   if (refs == NULL)
1444     return;
1445
1446   /* This function corrects the path stored in the reference to
1447    * account for an deletion. Note that it's called _after_ the
1448    * deletion with the old path of the just-deleted row. Which means
1449    * that the deleted path is the same now-defunct "coordinate system"
1450    * as the path saved in the reference, which is what we want to fix.
1451    */
1452
1453   tmp_list = refs->list;
1454
1455   while (tmp_list != NULL)
1456     {
1457       GtkTreeRowReference *reference = tmp_list->data;
1458
1459       if (reference->path)
1460         {
1461           gint i;
1462
1463           if (path->depth > reference->path->depth)
1464             goto next;
1465           for (i = 0; i < path->depth - 1; i++)
1466             {
1467               if (path->indices[i] != reference->path->indices[i])
1468                 goto next;
1469             }
1470
1471           /* We know it affects us. */
1472           if (path->indices[i] == reference->path->indices[i])
1473             {
1474               if (reference->path->depth > path->depth)
1475                 /* some parent was deleted, trying to unref any node
1476                  * between the deleted parent and the node the reference
1477                  * is pointing to is bad, as those nodes are already gone.
1478                  */
1479                 gtk_tree_row_reference_unref_path (reference->path, reference->model, path->depth - 1);
1480               else
1481                 gtk_tree_row_reference_unref_path (reference->path, reference->model, reference->path->depth - 1);
1482               gtk_tree_path_free (reference->path);
1483               reference->path = NULL;
1484             }
1485           else if (path->indices[i] < reference->path->indices[i])
1486             {
1487               reference->path->indices[path->depth-1]-=1;
1488             }
1489         }
1490
1491 next:
1492       tmp_list = g_slist_next (tmp_list);
1493     }
1494 }
1495
1496 static void
1497 gtk_tree_row_ref_reordered_callback (GObject     *object,
1498                                      GtkTreePath *path,
1499                                      GtkTreeIter *iter,
1500                                      gint        *new_order,
1501                                      gpointer     data)
1502 {
1503   RowRefList *refs = g_object_get_data (data, ROW_REF_DATA_STRING);
1504   GSList *tmp_list;
1505   gint length;
1506
1507   if (refs == NULL)
1508     return;
1509
1510   tmp_list = refs->list;
1511
1512   while (tmp_list != NULL)
1513     {
1514       GtkTreeRowReference *reference = tmp_list->data;
1515
1516       length = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (reference->model), iter);
1517
1518       if (length < 2)
1519         return;
1520
1521       if ((reference->path) &&
1522           (gtk_tree_path_is_ancestor (path, reference->path)))
1523         {
1524           gint ref_depth = gtk_tree_path_get_depth (reference->path);
1525           gint depth = gtk_tree_path_get_depth (path);
1526
1527           if (ref_depth > depth)
1528             {
1529               gint i;
1530               gint *indices = gtk_tree_path_get_indices (reference->path);
1531
1532               for (i = 0; i < length; i++)
1533                 {
1534                   if (new_order[i] == indices[depth])
1535                     {
1536                       indices[depth] = i;
1537                       break;
1538                     }
1539                 }
1540             }
1541         }
1542
1543       tmp_list = g_slist_next (tmp_list);
1544     }
1545   
1546 }
1547      
1548 static void
1549 connect_ref_callbacks (GtkTreeModel *model)
1550 {
1551   g_signal_connect (model,
1552                     "row_inserted",
1553                     G_CALLBACK (gtk_tree_row_ref_inserted_callback),
1554                     model);
1555   g_signal_connect (model,
1556                     "row_deleted",
1557                     G_CALLBACK (gtk_tree_row_ref_deleted_callback),
1558                     model);
1559   g_signal_connect (model,
1560                     "rows_reordered",
1561                     G_CALLBACK (gtk_tree_row_ref_reordered_callback),
1562                     model);
1563 }
1564
1565
1566 /* We do this recursively so that we can unref children nodes before their parent */
1567 static void
1568 gtk_tree_row_reference_unref_path_helper (GtkTreePath  *path,
1569                                           GtkTreeModel *model,
1570                                           GtkTreeIter  *parent_iter,
1571                                           gint          depth,
1572                                           gint          current_depth)
1573 {
1574   GtkTreeIter iter;
1575
1576   if (depth == current_depth)
1577     return;
1578
1579   gtk_tree_model_iter_nth_child (model, &iter, parent_iter, path->indices[current_depth]);
1580   gtk_tree_row_reference_unref_path_helper (path, model, &iter, depth, current_depth + 1);
1581   gtk_tree_model_unref_node (model, &iter);
1582 }
1583
1584 static void
1585 gtk_tree_row_reference_unref_path (GtkTreePath  *path,
1586                                    GtkTreeModel *model,
1587                                    gint          depth)
1588 {
1589   GtkTreeIter iter;
1590
1591   if (depth <= 0)
1592     return;
1593   
1594   gtk_tree_model_iter_nth_child (model, &iter, NULL, path->indices[0]);
1595   gtk_tree_row_reference_unref_path_helper (path, model, &iter, depth, 1);
1596   gtk_tree_model_unref_node (model, &iter);
1597 }
1598
1599 static void
1600 disconnect_ref_callbacks (GtkTreeModel *model)
1601 {
1602   g_signal_handlers_disconnect_matched (model,
1603                                         G_SIGNAL_MATCH_FUNC,
1604                                         0, 0, NULL,
1605                                         gtk_tree_row_ref_inserted_callback,
1606                                         NULL);
1607   g_signal_handlers_disconnect_matched (model,
1608                                         G_SIGNAL_MATCH_FUNC,
1609                                         0, 0, NULL,
1610                                         gtk_tree_row_ref_deleted_callback,
1611                                         NULL);
1612   g_signal_handlers_disconnect_matched (model,
1613                                         G_SIGNAL_MATCH_FUNC,
1614                                         0, 0, NULL,
1615                                         gtk_tree_row_ref_reordered_callback,
1616                                         NULL);
1617 }
1618
1619 /**
1620  * gtk_tree_row_reference_new:
1621  * @model: A #GtkTreeModel
1622  * @path: A valid #GtkTreePath to monitor
1623  * 
1624  * Creates a row reference based on @path.  This reference will keep pointing to
1625  * the node pointed to by @path, so long as it exists.  It listens to all
1626  * signals emitted by @model, and updates it's path appropriately.  If @path
1627  * isn't a valid path in @model, then %NULL is returned.
1628  * 
1629  * Return value: A newly allocated #GtkTreeRowReference, or %NULL
1630  **/
1631 GtkTreeRowReference *
1632 gtk_tree_row_reference_new (GtkTreeModel *model,
1633                             GtkTreePath  *path)
1634 {
1635   g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
1636   g_return_val_if_fail (path != NULL, NULL);
1637
1638   return gtk_tree_row_reference_new_proxy (G_OBJECT (model), model, path);
1639 }
1640
1641 /**
1642  * gtk_tree_row_reference_new_proxy:
1643  * @proxy: A proxy #GObject
1644  * @model: A #GtkTreeModel
1645  * @path: A valid #GtkTreePath to monitor
1646  * 
1647  * You do not need to use this function.  Creates a row reference based on
1648  * @path.  This reference will keep pointing to the node pointed to by @path, so
1649  * long as it exists.  If @path isn't a valid path in @model, then %NULL is
1650  * returned.  However, unlike references created with
1651  * gtk_tree_row_reference_new(), it does not listen to the model for changes.
1652  * The creator of the row reference must do this explicitly using
1653  * gtk_tree_row_reference_inserted(), gtk_tree_row_reference_deleted(),
1654  * gtk_tree_row_reference_reordered().  This must be called once per signal per
1655  * proxy.
1656  *
1657  * This type of row reference is primarily meant by structures that need to
1658  * carefully monitor exactly when a row_reference updates itself, and is not
1659  * generally needed by most applications.
1660  *
1661  * Return value: A newly allocated #GtkTreeRowReference, or %NULL
1662  **/
1663 GtkTreeRowReference *
1664 gtk_tree_row_reference_new_proxy (GObject      *proxy,
1665                                   GtkTreeModel *model,
1666                                   GtkTreePath  *path)
1667 {
1668   GtkTreeRowReference *reference;
1669   RowRefList *refs;
1670   GtkTreeIter parent_iter;
1671   gint i;
1672
1673   g_return_val_if_fail (G_IS_OBJECT (proxy), NULL);
1674   g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
1675   g_return_val_if_fail (path != NULL, NULL);
1676   g_return_val_if_fail (path->depth > 0, NULL);
1677
1678   /* check that the path is valid */
1679   if (gtk_tree_model_get_iter (model, &parent_iter, path) == FALSE)
1680     return NULL;
1681
1682   /* Now we want to ref every node */
1683   gtk_tree_model_iter_nth_child (model, &parent_iter, NULL, path->indices[0]);
1684   gtk_tree_model_ref_node (model, &parent_iter);
1685
1686   for (i = 1; i < path->depth; i++)
1687     {
1688       GtkTreeIter iter;
1689       gtk_tree_model_iter_nth_child (model, &iter, &parent_iter, path->indices[i]);
1690       gtk_tree_model_ref_node (model, &iter);
1691       parent_iter = iter;
1692     }
1693
1694   /* Make ther row reference */
1695   reference = g_new (GtkTreeRowReference, 1);
1696
1697   g_object_ref (proxy);
1698   g_object_ref (model);
1699   reference->proxy = proxy;
1700   reference->model = model;
1701   reference->path = gtk_tree_path_copy (path);
1702
1703   refs = g_object_get_data (G_OBJECT (proxy), ROW_REF_DATA_STRING);
1704
1705   if (refs == NULL)
1706     {
1707       refs = g_new (RowRefList, 1);
1708       refs->list = NULL;
1709
1710       if (G_OBJECT (model) == proxy)
1711         connect_ref_callbacks (model);
1712
1713       g_object_set_data_full (G_OBJECT (proxy),
1714                               ROW_REF_DATA_STRING,
1715                               refs, release_row_references);
1716     }
1717
1718   refs->list = g_slist_prepend (refs->list, reference);
1719
1720   return reference;
1721 }
1722
1723 /**
1724  * gtk_tree_row_reference_get_path:
1725  * @reference: A #GtkTreeRowReference
1726  * 
1727  * Returns a path that the row reference currently points to, or %NULL if the
1728  * path pointed to is no longer valid.
1729  * 
1730  * Return value: A current path, or %NULL.
1731  **/
1732 GtkTreePath *
1733 gtk_tree_row_reference_get_path (GtkTreeRowReference *reference)
1734 {
1735   g_return_val_if_fail (reference != NULL, NULL);
1736
1737   if (reference->proxy == NULL)
1738     return NULL;
1739
1740   if (reference->path == NULL)
1741     return NULL;
1742
1743   return gtk_tree_path_copy (reference->path);
1744 }
1745
1746 /**
1747  * gtk_tree_row_reference_valid:
1748  * @reference: A #GtkTreeRowReference, or NULL
1749  * 
1750  * Returns TRUE if the %reference is non-NULL and refers to a current valid
1751  * path.
1752  * 
1753  * Return value: TRUE if %reference points to a valid path.
1754  **/
1755 gboolean
1756 gtk_tree_row_reference_valid (GtkTreeRowReference *reference)
1757 {
1758   if (reference == NULL || reference->path == NULL)
1759     return FALSE;
1760
1761   return TRUE;
1762 }
1763
1764
1765 GtkTreeRowReference *
1766 gtk_tree_row_reference_copy (GtkTreeRowReference *reference)
1767 {
1768   return gtk_tree_row_reference_new_proxy (reference->proxy,
1769                                            reference->model,
1770                                            reference->path);
1771 }
1772
1773 /**
1774  * gtk_tree_row_reference_free:
1775  * @reference: A #GtkTreeRowReference, or NULL
1776  * 
1777  * Free's %reference.  %reference may be NULL.
1778  **/
1779 void
1780 gtk_tree_row_reference_free (GtkTreeRowReference *reference)
1781 {
1782   RowRefList *refs;
1783
1784   if (reference == NULL)
1785     return;
1786
1787   refs = g_object_get_data (G_OBJECT (reference->proxy), ROW_REF_DATA_STRING);
1788
1789   if (refs == NULL)
1790     {
1791       g_warning (G_STRLOC": bad row reference, proxy has no outstanding row references");
1792       return;
1793     }
1794
1795   refs->list = g_slist_remove (refs->list, reference);
1796
1797   if (refs->list == NULL)
1798     {
1799       if (G_OBJECT (reference->model) == reference->proxy)
1800         disconnect_ref_callbacks (reference->model);
1801
1802       g_object_set_data (G_OBJECT (reference->proxy),
1803                          ROW_REF_DATA_STRING,
1804                          NULL);
1805     }
1806
1807   if (reference->path)
1808     {
1809       gtk_tree_row_reference_unref_path (reference->path, reference->model, reference->path->depth);
1810       gtk_tree_path_free (reference->path);
1811     }
1812
1813   g_object_unref (reference->proxy);
1814   g_object_unref (reference->model);
1815   g_free (reference);
1816 }
1817
1818 /**
1819  * gtk_tree_row_reference_inserted:
1820  * @proxy: A #GObject
1821  * @path: The row position that was inserted
1822  * 
1823  * Lets a set of row reference created by gtk_tree_row_reference_new_proxy()
1824  * know that the model emitted the "row_inserted" signal.
1825  **/
1826 void
1827 gtk_tree_row_reference_inserted (GObject     *proxy,
1828                                  GtkTreePath *path)
1829 {
1830   g_return_if_fail (G_IS_OBJECT (proxy));
1831
1832   gtk_tree_row_ref_inserted_callback (NULL, path, NULL, proxy);
1833   
1834 }
1835
1836 /**
1837  * gtk_tree_row_reference_deleted:
1838  * @proxy: A #GObject
1839  * @path: The path position that was deleted
1840  * 
1841  * Lets a set of row reference created by gtk_tree_row_reference_new_proxy()
1842  * know that the model emitted the "row_deleted" signal.
1843  **/
1844 void
1845 gtk_tree_row_reference_deleted (GObject     *proxy,
1846                                 GtkTreePath *path)
1847 {
1848   g_return_if_fail (G_IS_OBJECT (proxy));
1849
1850   gtk_tree_row_ref_deleted_callback (NULL, path, proxy);
1851 }
1852
1853 /**
1854  * gtk_tree_row_reference_reordered:
1855  * @proxy: A #GObject
1856  * @path: The parent path of the reordered signal
1857  * @iter: The iter pointing to the parent of the reordered
1858  * @new_order: The new order of rows
1859  * 
1860  * Lets a set of row reference created by gtk_tree_row_reference_new_proxy()
1861  * know that the model emitted the "rows_reordered" signal.
1862  **/
1863 void
1864 gtk_tree_row_reference_reordered (GObject     *proxy,
1865                                   GtkTreePath *path,
1866                                   GtkTreeIter *iter,
1867                                   gint        *new_order)
1868 {
1869   g_return_if_fail (G_IS_OBJECT (proxy));
1870
1871   gtk_tree_row_ref_reordered_callback (NULL, path, iter, new_order, proxy);
1872 }
1873   
1874