]> Pileus Git - ~andy/gtk/blob - gtk/gtktreemodel.c
Evil function to deal with very large (TM) amounts of text. May be moved
[~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.  It is expected that the flags supported
580  * do not change for an interface.
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.  If the model does not
642  * provide an implementation of this function, it is implemented in terms of
643  * @gtk_tree_model_iter_nth_child.
644  *
645  * Return value: TRUE, if @iter was set.
646  **/
647 gboolean
648 gtk_tree_model_get_iter (GtkTreeModel *tree_model,
649                          GtkTreeIter  *iter,
650                          GtkTreePath  *path)
651 {
652   GtkTreeIter parent;
653   gint *indices;
654   gint depth, i;
655
656   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
657   g_return_val_if_fail (iter != NULL, FALSE);
658   g_return_val_if_fail (path != NULL, FALSE);
659
660   if (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_iter != NULL)
661     return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_iter) (tree_model, iter, path);
662
663   indices = gtk_tree_path_get_indices (path);
664   depth = gtk_tree_path_get_depth (path);
665
666   g_return_val_if_fail (depth > 0, FALSE);
667
668   if (! gtk_tree_model_iter_nth_child (tree_model, iter, NULL, indices[0]))
669     return FALSE;
670
671   for (i = 1; i < depth; i++)
672     {
673       parent = *iter;
674       if (! gtk_tree_model_iter_nth_child (tree_model, iter, &parent, indices[i]))
675         return FALSE;
676     }
677
678   return TRUE;
679 }
680
681
682 /**
683  * gtk_tree_model_get_iter_root:
684  * @tree_model: A #GtkTreeModel.
685  * @iter: The uninitialized #GtkTreeIter.
686  * 
687  * Gets the root iter, if it exists.
688  * 
689  * Return value: TRUE, if @iter was set.
690  **/
691 gboolean
692 gtk_tree_model_get_iter_root (GtkTreeModel *tree_model,
693                               GtkTreeIter  *iter)
694 {
695   GtkTreePath *path;
696   gboolean retval;
697
698   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
699   g_return_val_if_fail (iter != NULL, FALSE);
700
701   path = gtk_tree_path_new_root ();
702   retval = gtk_tree_model_get_iter (tree_model, iter, path);
703   gtk_tree_path_free (path);
704
705   return retval;
706 }
707
708 /**
709  * gtk_tree_model_get_first:
710  * @tree_model: a #GtkTreeModel
711  * @iter: iterator to initialize
712  *
713  * Initialized @iter with the first iterator in the tree (the one at the
714  * root path) and returns %TRUE, or returns %FALSE if there are no
715  * iterable locations in the model (i.e. the tree is empty).
716  *
717  * Return value: %TRUE if @iter was initialized
718  **/
719 gboolean
720 gtk_tree_model_get_first (GtkTreeModel *tree_model,
721                           GtkTreeIter  *iter)
722 {
723   gboolean retval;
724   GtkTreePath *path;
725
726   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
727   g_return_val_if_fail (iter != NULL, FALSE);
728
729   path = gtk_tree_path_new_root ();
730
731   retval = gtk_tree_model_get_iter (tree_model, iter, path);
732
733   gtk_tree_path_free (path);
734
735   return retval;
736 }
737
738 /**
739  * gtk_tree_model_get_path:
740  * @tree_model: A #GtkTreeModel.
741  * @iter: The #GtkTreeIter.
742  *
743  * Returns a newly created #GtkTreePath referenced by @iter.  This path should
744  * be freed with #gtk_tree_path_free.
745  *
746  * Return value: a newly created #GtkTreePath.
747  **/
748 GtkTreePath *
749 gtk_tree_model_get_path (GtkTreeModel *tree_model,
750                          GtkTreeIter  *iter)
751 {
752   g_return_val_if_fail (tree_model != NULL, NULL);
753   g_return_val_if_fail (iter != NULL, NULL);
754   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), NULL);
755   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_path != NULL, NULL);
756
757   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_path) (tree_model, iter);
758 }
759
760 /**
761  * gtk_tree_model_get_value:
762  * @tree_model: A #GtkTreeModel.
763  * @iter: The #GtkTreeIter.
764  * @column: The column to lookup the value at.
765  * @value: An empty #GValue to set.
766  *
767  * Sets initializes and sets @value to that at @column.  When done with value,
768  * #g_value_unset needs to be called on it.
769  **/
770 void
771 gtk_tree_model_get_value (GtkTreeModel *tree_model,
772                           GtkTreeIter  *iter,
773                           gint          column,
774                           GValue       *value)
775 {
776   g_return_if_fail (tree_model != NULL);
777   g_return_if_fail (iter != NULL);
778   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
779   g_return_if_fail (value != NULL);
780   g_return_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_value != NULL);
781
782   (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_value) (tree_model, iter, column, value);
783 }
784
785 /**
786  * gtk_tree_model_iter_next:
787  * @tree_model: A #GtkTreeModel.
788  * @iter: The #GtkTreeIter.
789  *
790  * Sets @iter to point to the node following it at the current level.  If there
791  * is no next @iter, FALSE is returned and @iter is set to be invalid.
792  *
793  * Return value: TRUE if @iter has been changed to the next node.
794  **/
795 gboolean
796 gtk_tree_model_iter_next (GtkTreeModel  *tree_model,
797                           GtkTreeIter   *iter)
798 {
799   g_return_val_if_fail (tree_model != NULL, FALSE);
800   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
801   g_return_val_if_fail (iter != NULL, FALSE);
802   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_next != NULL, FALSE);
803
804   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_next) (tree_model, iter);
805 }
806
807 /**
808  * gtk_tree_model_iter_children:
809  * @tree_model: A #GtkTreeModel.
810  * @iter: The new #GtkTreeIter to be set to the child.
811  * @parent: The #GtkTreeIter.
812  *
813  * Sets @iter to point to the first child of @parent.  If @parent has no children,
814  * FALSE is returned and @iter is set to be invalid.  @parent will remain a valid
815  * node after this function has been called.
816  *
817  * Return value: TRUE, if @child has been set to the first child.
818  **/
819 gboolean
820 gtk_tree_model_iter_children (GtkTreeModel *tree_model,
821                               GtkTreeIter  *iter,
822                               GtkTreeIter  *parent)
823 {
824   g_return_val_if_fail (tree_model != NULL, FALSE);
825   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
826   g_return_val_if_fail (iter != NULL, FALSE);
827   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_children != NULL, FALSE);
828
829   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_children) (tree_model, iter, parent);
830 }
831
832 /**
833  * gtk_tree_model_iter_has_child:
834  * @tree_model: A #GtkTreeModel.
835  * @iter: The #GtkTreeIter to test for children.
836  *
837  * Returns TRUE if @iter has children, FALSE otherwise.
838  *
839  * Return value: TRUE if @iter has children.
840  **/
841 gboolean
842 gtk_tree_model_iter_has_child (GtkTreeModel *tree_model,
843                                GtkTreeIter  *iter)
844 {
845   g_return_val_if_fail (tree_model != NULL, FALSE);
846   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
847   g_return_val_if_fail (iter != NULL, FALSE);
848   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_has_child != NULL, FALSE);
849
850   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_has_child) (tree_model, iter);
851 }
852
853 /**
854  * gtk_tree_model_iter_n_children:
855  * @tree_model: A #GtkTreeModel.
856  * @iter: The #GtkTreeIter, or NULL.
857  *
858  * Returns the number of children that @iter has.  If @iter is NULL, then the
859  * number of toplevel nodes is returned.
860  *
861  * Return value: The number of children of @iter.
862  **/
863 gint
864 gtk_tree_model_iter_n_children (GtkTreeModel *tree_model,
865                                 GtkTreeIter  *iter)
866 {
867   g_return_val_if_fail (tree_model != NULL, 0);
868   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), 0);
869   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_n_children != NULL, 0);
870
871   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_n_children) (tree_model, iter);
872 }
873
874 /**
875  * gtk_tree_model_iter_nth_child:
876  * @tree_model: A #GtkTreeModel.
877  * @iter: The #GtkTreeIter to set to the nth child.
878  * @parent: The #GtkTreeIter to get the child from, or NULL.
879  * @n: Then index of the desired child.
880  *
881  * Sets @iter to be the child of @parent, using the given index.  The first
882  * index is 0.  If the index is too big, or @parent has no children, @iter is
883  * set to an invalid iterator and FALSE is returned.  @parent will remain a
884  * valid node after this function has been called.  If @parent is NULL, then the
885  * root node is assumed.
886  *
887  * Return value: TRUE, if @parent has an nth child.
888  **/
889 gboolean
890 gtk_tree_model_iter_nth_child (GtkTreeModel *tree_model,
891                                GtkTreeIter  *iter,
892                                GtkTreeIter  *parent,
893                                gint          n)
894 {
895   g_return_val_if_fail (tree_model != NULL, FALSE);
896   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
897   g_return_val_if_fail (iter != NULL, FALSE);
898   g_return_val_if_fail (n >= 0, FALSE);
899   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_nth_child != NULL, FALSE);
900
901   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_nth_child) (tree_model, iter, parent, n);
902 }
903
904 /**
905  * gtk_tree_model_iter_parent:
906  * @tree_model: A #GtkTreeModel
907  * @iter: The new #GtkTreeIter to set to the parent.
908  * @child: The #GtkTreeIter.
909  *
910  * Sets @iter to be the parent of @child.  If @child is at the toplevel, and
911  * doesn't have a parent, then @iter is set to an invalid iterator and FALSE
912  * is returned.  @child will remain a valid node after this function has been
913  * called.
914  *
915  * Return value: TRUE, if @iter is set to the parent of @child.
916  **/
917 gboolean
918 gtk_tree_model_iter_parent (GtkTreeModel *tree_model,
919                             GtkTreeIter  *iter,
920                             GtkTreeIter  *child)
921 {
922   g_return_val_if_fail (tree_model != NULL, FALSE);
923   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
924   g_return_val_if_fail (iter != NULL, FALSE);
925   g_return_val_if_fail (child != NULL, FALSE);
926   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_parent != NULL, FALSE);
927
928   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_parent) (tree_model, iter, child);
929 }
930
931 /**
932  * gtk_tree_model_ref_node:
933  * @tree_model: A #GtkTreeModel.
934  * @iter: The #GtkTreeIter.
935  *
936  * Lets the tree ref the node.  This is an optional method for models to
937  * implement.  To be more specific, models may ignore this call as it exists
938  * primarily for performance reasons.
939  * 
940  * This function is primarily meant as a way for views to let caching model know
941  * when nodes are being displayed (and hence, whether or not to cache that
942  * node.)  For example, a file-system based model would not want to keep the
943  * entire file-heirarchy in memory, just the sections that are currently being
944  * displayed by every current view.
945  **/
946 void
947 gtk_tree_model_ref_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)->ref_node)
954     (* GTK_TREE_MODEL_GET_IFACE (tree_model)->ref_node) (tree_model, iter);
955 }
956
957 /**
958  * gtk_tree_model_unref_node:
959  * @tree_model: A #GtkTreeModel.
960  * @iter: The #GtkTreeIter.
961  *
962  * Lets the tree unref the node.  This is an optional method for models to
963  * implement.  To be more specific, models may ignore this call as it exists
964  * primarily for performance reasons.
965  *
966  * For more information on what this means, please see #gtk_tree_model_ref_node.
967  * Please note that nodes that are deleted are not unreffed.
968  **/
969 void
970 gtk_tree_model_unref_node (GtkTreeModel *tree_model,
971                            GtkTreeIter  *iter)
972 {
973   g_return_if_fail (tree_model != NULL);
974   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
975
976   if (GTK_TREE_MODEL_GET_IFACE (tree_model)->unref_node)
977     (* GTK_TREE_MODEL_GET_IFACE (tree_model)->unref_node) (tree_model, iter);
978 }
979
980 /**
981  * gtk_tree_model_get:
982  * @tree_model: a #GtkTreeModel
983  * @iter: a row in @tree_model
984  * @Varargs: pairs of column number and value return locations, terminated by -1
985  *
986  * Gets the value of one or more cells in the row referenced by @iter.
987  * The variable argument list should contain integer column numbers,
988  * each column number followed by a place to store the value being
989  * retrieved.  The list is terminated by a -1. For example, to get a
990  * value from column 0 with type %G_TYPE_STRING, you would
991  * write: gtk_tree_model_set (model, iter, 0, &place_string_here, -1),
992  * where place_string_here is a gchar* to be filled with the string.
993  * If appropriate, the returned values have to be freed or unreferenced.
994  *
995  **/
996 void
997 gtk_tree_model_get (GtkTreeModel *tree_model,
998                     GtkTreeIter  *iter,
999                     ...)
1000 {
1001   va_list var_args;
1002
1003   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1004
1005   va_start (var_args, iter);
1006   gtk_tree_model_get_valist (tree_model, iter, var_args);
1007   va_end (var_args);
1008 }
1009
1010 /**
1011  * gtk_tree_model_get_valist:
1012  * @tree_model: a #GtkTreeModel
1013  * @iter: a row in @tree_model
1014  * @var_args: va_list of column/return location pairs
1015  *
1016  * See gtk_tree_model_get(), this version takes a va_list for
1017  * language bindings to use.
1018  *
1019  **/
1020 void
1021 gtk_tree_model_get_valist (GtkTreeModel *tree_model,
1022                            GtkTreeIter  *iter,
1023                            va_list      var_args)
1024 {
1025   gint column;
1026
1027   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1028
1029   column = va_arg (var_args, gint);
1030
1031   while (column != -1)
1032     {
1033       GValue value = { 0, };
1034       gchar *error = NULL;
1035
1036       if (column >= gtk_tree_model_get_n_columns (tree_model))
1037         {
1038           g_warning ("%s: Invalid column number %d accessed (remember to end your list of columns with a -1)", G_STRLOC, column);
1039           break;
1040         }
1041
1042       gtk_tree_model_get_value (GTK_TREE_MODEL (tree_model), iter, column, &value);
1043
1044       G_VALUE_LCOPY (&value, var_args, 0, &error);
1045       if (error)
1046         {
1047           g_warning ("%s: %s", G_STRLOC, error);
1048           g_free (error);
1049
1050           /* we purposely leak the value here, it might not be
1051            * in a sane state if an error condition occoured
1052            */
1053           break;
1054         }
1055
1056       g_value_unset (&value);
1057
1058       column = va_arg (var_args, gint);
1059     }
1060 }
1061
1062 void
1063 gtk_tree_model_range_changed (GtkTreeModel *tree_model,
1064                               GtkTreePath  *start_path,
1065                               GtkTreeIter  *start_iter,
1066                               GtkTreePath  *end_path,
1067                               GtkTreeIter  *end_iter)
1068 {
1069   g_return_if_fail (tree_model != NULL);
1070   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1071   g_return_if_fail (start_path != NULL);
1072   g_return_if_fail (start_iter != NULL);
1073   g_return_if_fail (end_path != NULL);
1074   g_return_if_fail (end_iter != NULL);
1075
1076   g_signal_emit_by_name (tree_model, "range_changed",
1077                          start_path, start_iter,
1078                          end_path, end_iter);
1079 }
1080
1081 void
1082 gtk_tree_model_inserted (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, "inserted", path, iter);
1092 }
1093
1094 void
1095 gtk_tree_model_has_child_toggled (GtkTreeModel *tree_model,
1096                                   GtkTreePath  *path,
1097                                   GtkTreeIter  *iter)
1098 {
1099   g_return_if_fail (tree_model != NULL);
1100   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1101   g_return_if_fail (path != NULL);
1102   g_return_if_fail (iter != NULL);
1103
1104   g_signal_emit_by_name (tree_model, "has_child_toggled", path, iter);
1105 }
1106
1107 void
1108 gtk_tree_model_deleted (GtkTreeModel *tree_model,
1109                         GtkTreePath  *path)
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 (path != NULL);
1114
1115   g_signal_emit_by_name (tree_model, "deleted", path);
1116 }
1117
1118 void
1119 gtk_tree_model_reordered (GtkTreeModel *tree_model,
1120                           GtkTreePath  *path,
1121                           GtkTreeIter  *iter,
1122                           gint         *new_order)
1123 {
1124   g_return_if_fail (tree_model != NULL);
1125   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1126   g_return_if_fail (new_order != NULL);
1127
1128   g_signal_emit_by_name (tree_model, "reordered", path, iter, new_order);
1129 }
1130
1131
1132 /*
1133  * GtkTreeRowReference
1134  */
1135
1136 #define ROW_REF_DATA_STRING "gtk-tree-row-refs"
1137
1138 struct _GtkTreeRowReference
1139 {
1140   GObject *proxy;
1141   GtkTreeModel *model;
1142   GtkTreePath *path;
1143 };
1144
1145 typedef struct
1146 {
1147   GSList *list;
1148 } RowRefList;
1149
1150
1151 static void
1152 release_row_references (gpointer data)
1153 {
1154   RowRefList *refs = data;
1155   GSList *tmp_list = NULL;
1156
1157   tmp_list = refs->list;
1158   while (tmp_list != NULL)
1159     {
1160       GtkTreeRowReference *reference = tmp_list->data;
1161
1162       if (reference->proxy == (GObject *)reference->model)
1163         reference->model = NULL;
1164       reference->proxy = NULL;
1165
1166       /* we don't free the reference, users are responsible for that. */
1167
1168       tmp_list = g_slist_next (tmp_list);
1169     }
1170
1171   g_slist_free (refs->list);
1172   g_free (refs);
1173 }
1174
1175 static void
1176 gtk_tree_row_ref_inserted_callback (GObject     *object,
1177                                     GtkTreePath *path,
1178                                     GtkTreeIter *iter,
1179                                     gpointer     data)
1180 {
1181   RowRefList *refs = g_object_get_data (data, ROW_REF_DATA_STRING);
1182
1183   GSList *tmp_list;
1184
1185   if (refs == NULL)
1186     return;
1187
1188   /* This function corrects the path stored in the reference to
1189    * account for an insertion. Note that it's called _after_ the insertion
1190    * with the path to the newly-inserted row. Which means that
1191    * the inserted path is in a different "coordinate system" than
1192    * the old path (e.g. if the inserted path was just before the old path,
1193    * then inserted path and old path will be the same, and old path must be
1194    * moved down one).
1195    */
1196
1197   tmp_list = refs->list;
1198
1199   while (tmp_list != NULL)
1200     {
1201       GtkTreeRowReference *reference = tmp_list->data;
1202
1203       if (reference->path)
1204         {
1205           gint depth = gtk_tree_path_get_depth (path);
1206           gint ref_depth = gtk_tree_path_get_depth (reference->path);
1207
1208           if (ref_depth >= depth)
1209             {
1210               gint *indices = gtk_tree_path_get_indices (path);
1211               gint *ref_indices = gtk_tree_path_get_indices (reference->path);
1212               gint i;
1213
1214               /* This is the depth that might affect us. */
1215               i = depth - 1;
1216
1217               if (indices[i] <= ref_indices[i])
1218                 ref_indices[i] += 1;
1219             }
1220         }
1221
1222       tmp_list = g_slist_next (tmp_list);
1223     }
1224 }
1225
1226 static void
1227 gtk_tree_row_ref_deleted_callback (GObject     *object,
1228                                    GtkTreePath *path,
1229                                    gpointer     data)
1230 {
1231   RowRefList *refs = g_object_get_data (data, ROW_REF_DATA_STRING);
1232   GSList *tmp_list;
1233
1234   if (refs == NULL)
1235     return;
1236
1237   /* This function corrects the path stored in the reference to
1238    * account for an deletion. Note that it's called _after_ the
1239    * deletion with the old path of the just-deleted row. Which means
1240    * that the deleted path is the same now-defunct "coordinate system"
1241    * as the path saved in the reference, which is what we want to fix.
1242    *
1243    * Note that this is different from the situation in "inserted," so
1244    * while you might think you can cut-and-paste between these
1245    * functions, it's not going to work. ;-)
1246    */
1247
1248   tmp_list = refs->list;
1249
1250   while (tmp_list != NULL)
1251     {
1252       GtkTreeRowReference *reference = tmp_list->data;
1253
1254       if (reference->path)
1255         {
1256           gint depth = gtk_tree_path_get_depth (path);
1257           gint ref_depth = gtk_tree_path_get_depth (reference->path);
1258
1259           if (ref_depth >= depth)
1260             {
1261               /* Need to adjust path upward */
1262               gint *indices = gtk_tree_path_get_indices (path);
1263               gint *ref_indices = gtk_tree_path_get_indices (reference->path);
1264               gint i;
1265
1266               i = depth - 1;
1267               if (indices[i] < ref_indices[i])
1268                 ref_indices[i] -= 1;
1269               else if (indices[i] == ref_indices[i])
1270                 {
1271                   /* the referenced node itself, or its parent, was
1272                    * deleted, mark invalid
1273                    */
1274
1275                   gtk_tree_path_free (reference->path);
1276                   reference->path = NULL;
1277                 }
1278             }
1279
1280         }
1281       tmp_list = g_slist_next (tmp_list);
1282     }
1283 }
1284
1285 static void
1286 gtk_tree_row_ref_reordered_callback (GObject     *object,
1287                                      GtkTreePath *path,
1288                                      GtkTreeIter *iter,
1289                                      gint        *new_order,
1290                                      gpointer     data)
1291 {
1292   RowRefList *refs = g_object_get_data (data, ROW_REF_DATA_STRING);
1293   GSList *tmp_list;
1294   gint length;
1295
1296   if (refs == NULL)
1297     return;
1298
1299   tmp_list = refs->list;
1300
1301   while (tmp_list != NULL)
1302     {
1303       GtkTreeRowReference *reference = tmp_list->data;
1304
1305       length = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (reference->model), iter);
1306
1307       if (length < 2)
1308         return;
1309
1310       if ((reference->path) &&
1311           (gtk_tree_path_is_ancestor (path, reference->path)))
1312         {
1313           gint ref_depth = gtk_tree_path_get_depth (reference->path);
1314           gint depth = gtk_tree_path_get_depth (path);
1315
1316           if (ref_depth > depth)
1317             {
1318               gint i;
1319               gint *indices = gtk_tree_path_get_indices (reference->path);
1320
1321               for (i = 0; i < length; i++)
1322                 {
1323                   if (new_order[i] == indices[depth])
1324                     {
1325                       indices[depth] = i;
1326                       return;
1327                     }
1328                 }
1329             }
1330         }
1331
1332       tmp_list = g_slist_next (tmp_list);
1333     }
1334   
1335 }
1336      
1337 static void
1338 connect_ref_callbacks (GtkTreeModel *model)
1339 {
1340   g_signal_connect_data (G_OBJECT (model),
1341                          "inserted",
1342                          (GCallback) gtk_tree_row_ref_inserted_callback,
1343                          model,
1344                          NULL,
1345                          FALSE,
1346                          FALSE);
1347
1348   g_signal_connect_data (G_OBJECT (model),
1349                          "deleted",
1350                          (GCallback) gtk_tree_row_ref_deleted_callback,
1351                          model,
1352                          NULL,
1353                          FALSE,
1354                          FALSE);
1355
1356   g_signal_connect_data (G_OBJECT (model),
1357                          "reordered",
1358                          (GCallback) gtk_tree_row_ref_reordered_callback,
1359                          model,
1360                          NULL,
1361                          FALSE,
1362                          FALSE);
1363 }
1364
1365 static void
1366 disconnect_ref_callbacks (GtkTreeModel *model)
1367 {
1368   g_signal_handlers_disconnect_matched (G_OBJECT (model),
1369                                         G_SIGNAL_MATCH_FUNC,
1370                                         0, 0, NULL,
1371                                         gtk_tree_row_ref_inserted_callback,
1372                                         NULL);
1373   g_signal_handlers_disconnect_matched (G_OBJECT (model),
1374                                         G_SIGNAL_MATCH_FUNC,
1375                                         0, 0, NULL,
1376                                         gtk_tree_row_ref_deleted_callback,
1377                                         NULL);
1378   g_signal_handlers_disconnect_matched (G_OBJECT (model),
1379                                         G_SIGNAL_MATCH_FUNC,
1380                                         0, 0, NULL,
1381                                         gtk_tree_row_ref_reordered_callback,
1382                                         NULL);
1383 }
1384
1385 GtkTreeRowReference *
1386 gtk_tree_row_reference_new (GtkTreeModel *model,
1387                             GtkTreePath  *path)
1388 {
1389   g_return_val_if_fail (model != NULL, NULL);
1390   g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
1391   g_return_val_if_fail (path != NULL, NULL);
1392
1393   return gtk_tree_row_reference_new_proxy (G_OBJECT (model), model, path);
1394 }
1395
1396 GtkTreeRowReference *
1397 gtk_tree_row_reference_new_proxy (GObject      *proxy,
1398                                   GtkTreeModel *model,
1399                                   GtkTreePath  *path)
1400 {
1401   GtkTreeRowReference *reference;
1402   RowRefList *refs;
1403
1404   g_return_val_if_fail (G_IS_OBJECT (proxy), NULL);
1405   g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
1406   g_return_val_if_fail (path != NULL, NULL);
1407
1408   reference = g_new (GtkTreeRowReference, 1);
1409
1410   reference->proxy = proxy;
1411   reference->model = model;
1412   reference->path = gtk_tree_path_copy (path);
1413
1414   refs = g_object_get_data (G_OBJECT (proxy), ROW_REF_DATA_STRING);
1415
1416   if (refs == NULL)
1417     {
1418       refs = g_new (RowRefList, 1);
1419       refs->list = NULL;
1420
1421       if (G_OBJECT (model) == proxy)
1422         connect_ref_callbacks (model);
1423
1424       g_object_set_data_full (G_OBJECT (proxy),
1425                               ROW_REF_DATA_STRING,
1426                               refs, release_row_references);
1427     }
1428
1429   refs->list = g_slist_prepend (refs->list, reference);
1430
1431   return reference;
1432 }
1433
1434 GtkTreePath *
1435 gtk_tree_row_reference_get_path (GtkTreeRowReference *reference)
1436 {
1437   g_return_val_if_fail (reference != NULL, NULL);
1438
1439   if (reference->proxy == NULL)
1440     return NULL;
1441
1442   if (reference->path == NULL)
1443     return NULL;
1444
1445   return gtk_tree_path_copy (reference->path);
1446 }
1447
1448 void
1449 gtk_tree_row_reference_free (GtkTreeRowReference *reference)
1450 {
1451   RowRefList *refs;
1452
1453   g_return_if_fail (reference != NULL);
1454
1455   if (reference->proxy)
1456     {
1457       refs = g_object_get_data (G_OBJECT (reference->proxy), ROW_REF_DATA_STRING);
1458
1459       if (refs == NULL)
1460         {
1461           g_warning (G_STRLOC": bad row reference, proxy has no outstanding row references");
1462           return;
1463         }
1464
1465       refs->list = g_slist_remove (refs->list, reference);
1466
1467       if (refs->list == NULL)
1468         {
1469           disconnect_ref_callbacks (reference->model);
1470           g_object_set_data (G_OBJECT (reference->proxy),
1471                              ROW_REF_DATA_STRING,
1472                              NULL);
1473         }
1474     }
1475
1476   if (reference->path)
1477     gtk_tree_path_free (reference->path);
1478
1479   g_free (reference);
1480 }
1481
1482 void
1483 gtk_tree_row_reference_inserted (GObject     *proxy,
1484                                  GtkTreePath *path)
1485 {
1486   g_return_if_fail (G_IS_OBJECT (proxy));
1487
1488   gtk_tree_row_ref_inserted_callback (NULL, path, NULL, proxy);
1489   
1490 }
1491
1492 void
1493 gtk_tree_row_reference_deleted (GObject     *proxy,
1494                                 GtkTreePath *path)
1495 {
1496   g_return_if_fail (G_IS_OBJECT (proxy));
1497
1498   gtk_tree_row_ref_deleted_callback (NULL, path, proxy);
1499 }
1500
1501 void
1502 gtk_tree_row_reference_reordered (GObject     *proxy,
1503                                   GtkTreePath *path,
1504                                   GtkTreeIter *iter,
1505                                   gint        *new_order)
1506 {
1507   g_return_if_fail (G_IS_OBJECT (proxy));
1508
1509   gtk_tree_row_ref_reordered_callback (NULL, path, iter, new_order, proxy);
1510 }
1511