]> Pileus Git - ~andy/gtk/blob - gtk/gtktreemodel.c
clean up (gtk_tree_view_move_cursor_page_up_down): implement.
[~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_newc ("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_newc ("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_newc ("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_newc ("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_newc ("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 /*
1120  * GtkTreeRowReference
1121  */
1122
1123 #define ROW_REF_DATA_STRING "gtk-tree-row-refs"
1124
1125 struct _GtkTreeRowReference
1126 {
1127   GObject *proxy;
1128   GtkTreeModel *model;
1129   GtkTreePath *path;
1130 };
1131
1132 typedef struct
1133 {
1134   GSList *list;
1135 } RowRefList;
1136
1137
1138 static void
1139 release_row_references (gpointer data)
1140 {
1141   RowRefList *refs = data;
1142   GSList *tmp_list = NULL;
1143
1144   tmp_list = refs->list;
1145   while (tmp_list != NULL)
1146     {
1147       GtkTreeRowReference *reference = tmp_list->data;
1148
1149       if (reference->proxy == (GObject *)reference->model)
1150         reference->model = NULL;
1151       reference->proxy = NULL;
1152
1153       /* we don't free the reference, users are responsible for that. */
1154
1155       tmp_list = g_slist_next (tmp_list);
1156     }
1157
1158   g_slist_free (refs->list);
1159   g_free (refs);
1160 }
1161
1162 static void
1163 gtk_tree_row_ref_inserted_callback (GObject     *object,
1164                                     GtkTreePath *path,
1165                                     GtkTreeIter *iter,
1166                                     gpointer     data)
1167 {
1168   RowRefList *refs = g_object_get_data (data, ROW_REF_DATA_STRING);
1169
1170   GSList *tmp_list;
1171
1172   if (refs == NULL)
1173     return;
1174
1175   /* This function corrects the path stored in the reference to
1176    * account for an insertion. Note that it's called _after_ the insertion
1177    * with the path to the newly-inserted row. Which means that
1178    * the inserted path is in a different "coordinate system" than
1179    * the old path (e.g. if the inserted path was just before the old path,
1180    * then inserted path and old path will be the same, and old path must be
1181    * moved down one).
1182    */
1183
1184   tmp_list = refs->list;
1185
1186   while (tmp_list != NULL)
1187     {
1188       GtkTreeRowReference *reference = tmp_list->data;
1189
1190       if (reference->path)
1191         {
1192           gint depth = gtk_tree_path_get_depth (path);
1193           gint ref_depth = gtk_tree_path_get_depth (reference->path);
1194
1195           if (ref_depth >= depth)
1196             {
1197               gint *indices = gtk_tree_path_get_indices (path);
1198               gint *ref_indices = gtk_tree_path_get_indices (reference->path);
1199               gint i;
1200
1201               /* This is the depth that might affect us. */
1202               i = depth - 1;
1203
1204               if (indices[i] <= ref_indices[i])
1205                 ref_indices[i] += 1;
1206             }
1207         }
1208
1209       tmp_list = g_slist_next (tmp_list);
1210     }
1211 }
1212
1213 static void
1214 gtk_tree_row_ref_deleted_callback (GObject     *object,
1215                                    GtkTreePath *path,
1216                                    gpointer     data)
1217 {
1218   RowRefList *refs = g_object_get_data (data, ROW_REF_DATA_STRING);
1219   GSList *tmp_list;
1220
1221   if (refs == NULL)
1222     return;
1223
1224   /* This function corrects the path stored in the reference to
1225    * account for an deletion. Note that it's called _after_ the
1226    * deletion with the old path of the just-deleted row. Which means
1227    * that the deleted path is the same now-defunct "coordinate system"
1228    * as the path saved in the reference, which is what we want to fix.
1229    *
1230    * Note that this is different from the situation in "inserted," so
1231    * while you might think you can cut-and-paste between these
1232    * functions, it's not going to work. ;-)
1233    */
1234
1235   tmp_list = refs->list;
1236
1237   while (tmp_list != NULL)
1238     {
1239       GtkTreeRowReference *reference = tmp_list->data;
1240
1241       if (reference->path)
1242         {
1243           gint depth = gtk_tree_path_get_depth (path);
1244           gint ref_depth = gtk_tree_path_get_depth (reference->path);
1245
1246           if (ref_depth >= depth)
1247             {
1248               /* Need to adjust path upward */
1249               gint *indices = gtk_tree_path_get_indices (path);
1250               gint *ref_indices = gtk_tree_path_get_indices (reference->path);
1251               gint i;
1252
1253               i = depth - 1;
1254               if (indices[i] < ref_indices[i])
1255                 ref_indices[i] -= 1;
1256               else if (indices[i] == ref_indices[i])
1257                 {
1258                   /* the referenced node itself, or its parent, was
1259                    * deleted, mark invalid
1260                    */
1261
1262                   gtk_tree_path_free (reference->path);
1263                   reference->path = NULL;
1264                 }
1265             }
1266
1267         }
1268       tmp_list = g_slist_next (tmp_list);
1269     }
1270 }
1271
1272 static void
1273 gtk_tree_row_ref_reordered_callback (GObject     *object,
1274                                      GtkTreePath *path,
1275                                      GtkTreeIter *iter,
1276                                      gint        *new_order,
1277                                      gpointer     data)
1278 {
1279   RowRefList *refs = g_object_get_data (data, ROW_REF_DATA_STRING);
1280   GSList *tmp_list;
1281   gint length;
1282
1283   if (refs == NULL)
1284     return;
1285
1286   tmp_list = refs->list;
1287
1288   while (tmp_list != NULL)
1289     {
1290       GtkTreeRowReference *reference = tmp_list->data;
1291
1292       length = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (reference->model), iter);
1293
1294       if (length < 2)
1295         return;
1296
1297       if ((reference->path) &&
1298           (gtk_tree_path_is_ancestor (path, reference->path)))
1299         {
1300           gint ref_depth = gtk_tree_path_get_depth (reference->path);
1301           gint depth = gtk_tree_path_get_depth (path);
1302
1303           if (ref_depth > depth)
1304             {
1305               gint i;
1306               gint *indices = gtk_tree_path_get_indices (reference->path);
1307
1308               for (i = 0; i < length; i++)
1309                 {
1310                   if (new_order[i] == indices[depth])
1311                     {
1312                       indices[depth] = i;
1313                       return;
1314                     }
1315                 }
1316             }
1317         }
1318
1319       tmp_list = g_slist_next (tmp_list);
1320     }
1321   
1322 }
1323      
1324 static void
1325 connect_ref_callbacks (GtkTreeModel *model)
1326 {
1327   g_signal_connect_data (G_OBJECT (model),
1328                          "inserted",
1329                          (GCallback) gtk_tree_row_ref_inserted_callback,
1330                          model,
1331                          NULL,
1332                          FALSE,
1333                          FALSE);
1334
1335   g_signal_connect_data (G_OBJECT (model),
1336                          "deleted",
1337                          (GCallback) gtk_tree_row_ref_deleted_callback,
1338                          model,
1339                          NULL,
1340                          FALSE,
1341                          FALSE);
1342
1343   g_signal_connect_data (G_OBJECT (model),
1344                          "reordered",
1345                          (GCallback) gtk_tree_row_ref_reordered_callback,
1346                          model,
1347                          NULL,
1348                          FALSE,
1349                          FALSE);
1350 }
1351
1352 static void
1353 disconnect_ref_callbacks (GtkTreeModel *model)
1354 {
1355   g_signal_handlers_disconnect_matched (G_OBJECT (model),
1356                                         G_SIGNAL_MATCH_FUNC,
1357                                         0, 0, NULL,
1358                                         gtk_tree_row_ref_inserted_callback,
1359                                         NULL);
1360   g_signal_handlers_disconnect_matched (G_OBJECT (model),
1361                                         G_SIGNAL_MATCH_FUNC,
1362                                         0, 0, NULL,
1363                                         gtk_tree_row_ref_deleted_callback,
1364                                         NULL);
1365   g_signal_handlers_disconnect_matched (G_OBJECT (model),
1366                                         G_SIGNAL_MATCH_FUNC,
1367                                         0, 0, NULL,
1368                                         gtk_tree_row_ref_reordered_callback,
1369                                         NULL);
1370 }
1371
1372 GtkTreeRowReference *
1373 gtk_tree_row_reference_new (GtkTreeModel *model,
1374                             GtkTreePath  *path)
1375 {
1376   g_return_val_if_fail (model != NULL, NULL);
1377   g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
1378   g_return_val_if_fail (path != NULL, NULL);
1379
1380   return gtk_tree_row_reference_new_proxy (G_OBJECT (model), model, path);
1381 }
1382
1383 GtkTreeRowReference *
1384 gtk_tree_row_reference_new_proxy (GObject      *proxy,
1385                                   GtkTreeModel *model,
1386                                   GtkTreePath  *path)
1387 {
1388   GtkTreeRowReference *reference;
1389   RowRefList *refs;
1390
1391   g_return_val_if_fail (G_IS_OBJECT (proxy), NULL);
1392   g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
1393   g_return_val_if_fail (path != NULL, NULL);
1394
1395   reference = g_new (GtkTreeRowReference, 1);
1396
1397   g_object_ref (proxy);
1398   g_object_ref (model);
1399   reference->proxy = proxy;
1400   reference->model = model;
1401   reference->path = gtk_tree_path_copy (path);
1402
1403   refs = g_object_get_data (G_OBJECT (proxy), ROW_REF_DATA_STRING);
1404
1405   if (refs == NULL)
1406     {
1407       refs = g_new (RowRefList, 1);
1408       refs->list = NULL;
1409
1410       if (G_OBJECT (model) == proxy)
1411         connect_ref_callbacks (model);
1412
1413       g_object_set_data_full (G_OBJECT (proxy),
1414                               ROW_REF_DATA_STRING,
1415                               refs, release_row_references);
1416     }
1417
1418   refs->list = g_slist_prepend (refs->list, reference);
1419
1420   return reference;
1421 }
1422
1423 /**
1424  * gtk_tree_row_reference_get_path:
1425  * @reference: A #GtkTreeRowReference
1426  * 
1427  * Returns a path that the row reference currently points to, or NULL if the
1428  * path pointed to is no longer valid.
1429  * 
1430  * Return value: A current path, or NULL.
1431  **/
1432 GtkTreePath *
1433 gtk_tree_row_reference_get_path (GtkTreeRowReference *reference)
1434 {
1435   g_return_val_if_fail (reference != NULL, NULL);
1436
1437   if (reference->proxy == NULL)
1438     return NULL;
1439
1440   if (reference->path == NULL)
1441     return NULL;
1442
1443   return gtk_tree_path_copy (reference->path);
1444 }
1445
1446 /**
1447  * gtk_tree_row_reference_valid:
1448  * @reference: A #GtkTreeRowReference, or NULL
1449  * 
1450  * Returns TRUE if the %reference is non-NULL and refers to a current valid
1451  * path.
1452  * 
1453  * Return value: TRUE if %reference points to a valid path.
1454  **/
1455 gboolean
1456 gtk_tree_row_reference_valid (GtkTreeRowReference *reference)
1457 {
1458   if (reference == NULL || reference->path == NULL)
1459     return FALSE;
1460
1461   return TRUE;
1462 }
1463
1464 /**
1465  * gtk_tree_row_reference_free:
1466  * @reference: A #GtkTreeRowReference, or NULL
1467  * 
1468  * Free's %reference.  %reference may be NULL.
1469  **/
1470 void
1471 gtk_tree_row_reference_free (GtkTreeRowReference *reference)
1472 {
1473   RowRefList *refs;
1474
1475   if (reference == NULL)
1476     return;
1477
1478   refs = g_object_get_data (G_OBJECT (reference->proxy), ROW_REF_DATA_STRING);
1479
1480   if (refs == NULL)
1481     {
1482       g_warning (G_STRLOC": bad row reference, proxy has no outstanding row references");
1483       return;
1484     }
1485
1486   refs->list = g_slist_remove (refs->list, reference);
1487
1488   if (refs->list == NULL)
1489     {
1490       disconnect_ref_callbacks (reference->model);
1491       g_object_set_data (G_OBJECT (reference->proxy),
1492                          ROW_REF_DATA_STRING,
1493                          NULL);
1494     }
1495   g_object_unref (reference->proxy);
1496   g_object_unref (reference->model);
1497
1498   if (reference->path)
1499     gtk_tree_path_free (reference->path);
1500
1501   g_free (reference);
1502 }
1503
1504 void
1505 gtk_tree_row_reference_inserted (GObject     *proxy,
1506                                  GtkTreePath *path)
1507 {
1508   g_return_if_fail (G_IS_OBJECT (proxy));
1509
1510   gtk_tree_row_ref_inserted_callback (NULL, path, NULL, proxy);
1511   
1512 }
1513
1514 void
1515 gtk_tree_row_reference_deleted (GObject     *proxy,
1516                                 GtkTreePath *path)
1517 {
1518   g_return_if_fail (G_IS_OBJECT (proxy));
1519
1520   gtk_tree_row_ref_deleted_callback (NULL, path, proxy);
1521 }
1522
1523 void
1524 gtk_tree_row_reference_reordered (GObject     *proxy,
1525                                   GtkTreePath *path,
1526                                   GtkTreeIter *iter,
1527                                   gint        *new_order)
1528 {
1529   g_return_if_fail (G_IS_OBJECT (proxy));
1530
1531   gtk_tree_row_ref_reordered_callback (NULL, path, iter, new_order, proxy);
1532 }
1533