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