]> Pileus Git - ~andy/gtk/blob - gtk/gtktreestore.c
Bug fix to make trees work again when not sorted.
[~andy/gtk] / gtk / gtktreestore.c
1 /* gtktreestore.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 "gtktreemodel.h"
21 #include "gtktreestore.h"
22 #include "gtktreedatalist.h"
23 #include "gtktreednd.h"
24 #include <string.h>
25 #include <gobject/gvaluecollector.h>
26
27 #define G_NODE(node) ((GNode *)node)
28 #define GTK_TREE_STORE_IS_SORTED(tree) (GTK_TREE_STORE (tree)->sort_column_id != -1)
29
30 static void         gtk_tree_store_init            (GtkTreeStore      *tree_store);
31 static void         gtk_tree_store_class_init      (GtkTreeStoreClass *tree_store_class);
32 static void         gtk_tree_store_tree_model_init (GtkTreeModelIface *iface);
33 static void         gtk_tree_store_drag_source_init(GtkTreeDragSourceIface *iface);
34 static void         gtk_tree_store_drag_dest_init  (GtkTreeDragDestIface   *iface);
35 static void         gtk_tree_store_sortable_init   (GtkTreeSortableIface   *iface);
36 static guint        gtk_tree_store_get_flags       (GtkTreeModel      *tree_model);
37 static gint         gtk_tree_store_get_n_columns   (GtkTreeModel      *tree_model);
38 static GType        gtk_tree_store_get_column_type (GtkTreeModel      *tree_model,
39                                                     gint               index);
40 static GtkTreePath *gtk_tree_store_get_path        (GtkTreeModel      *tree_model,
41                                                     GtkTreeIter       *iter);
42 static void         gtk_tree_store_get_value       (GtkTreeModel      *tree_model,
43                                                     GtkTreeIter       *iter,
44                                                     gint               column,
45                                                     GValue            *value);
46 static gboolean     gtk_tree_store_iter_next       (GtkTreeModel      *tree_model,
47                                                     GtkTreeIter       *iter);
48 static gboolean     gtk_tree_store_iter_children   (GtkTreeModel      *tree_model,
49                                                     GtkTreeIter       *iter,
50                                                     GtkTreeIter       *parent);
51 static gboolean     gtk_tree_store_iter_has_child  (GtkTreeModel      *tree_model,
52                                                     GtkTreeIter       *iter);
53 static gint         gtk_tree_store_iter_n_children (GtkTreeModel      *tree_model,
54                                                     GtkTreeIter       *iter);
55 static gboolean     gtk_tree_store_iter_nth_child  (GtkTreeModel      *tree_model,
56                                                     GtkTreeIter       *iter,
57                                                     GtkTreeIter       *parent,
58                                                     gint               n);
59 static gboolean     gtk_tree_store_iter_parent     (GtkTreeModel      *tree_model,
60                                                     GtkTreeIter       *iter,
61                                                     GtkTreeIter       *child);
62
63
64 /* DND interfaces */
65 static gboolean gtk_tree_store_drag_data_delete   (GtkTreeDragSource *drag_source,
66                                                    GtkTreePath       *path);
67 static gboolean gtk_tree_store_drag_data_get      (GtkTreeDragSource *drag_source,
68                                                    GtkTreePath       *path,
69                                                    GtkSelectionData  *selection_data);
70 static gboolean gtk_tree_store_drag_data_received (GtkTreeDragDest   *drag_dest,
71                                                    GtkTreePath       *dest,
72                                                    GtkSelectionData  *selection_data);
73 static gboolean gtk_tree_store_row_drop_possible  (GtkTreeDragDest   *drag_dest,
74                                                    GtkTreeModel      *src_model,
75                                                    GtkTreePath       *src_path,
76                                                    GtkTreePath       *dest_path);
77
78 /* Sortable Interfaces */
79
80 static void     gtk_tree_store_sort                    (GtkTreeStore           *tree_store);
81 static void     gtk_tree_store_sort_iter_changed       (GtkTreeStore           *tree_store,
82                                                         GtkTreeIter            *iter,
83                                                         gint                    column);
84 static gboolean gtk_tree_store_get_sort_column_id      (GtkTreeSortable        *sortable,
85                                                         gint                   *sort_column_id,
86                                                         GtkTreeSortOrder       *order);
87 static void     gtk_tree_store_set_sort_column_id      (GtkTreeSortable        *sortable,
88                                                         gint                    sort_column_id,
89                                                         GtkTreeSortOrder        order);
90 static void     gtk_tree_store_sort_column_id_set_func (GtkTreeSortable        *sortable,
91                                                         gint                    sort_column_id,
92                                                         GtkTreeIterCompareFunc  func,
93                                                         gpointer                data,
94                                                         GtkDestroyNotify        destroy);
95
96
97 static void     validate_gnode                    (GNode *node);
98
99 static inline void
100 validate_tree (GtkTreeStore *tree_store)
101 {
102   if (gtk_debug_flags & GTK_DEBUG_TREE)
103     {
104       g_assert (G_NODE (tree_store->root)->parent == NULL);
105
106       validate_gnode (G_NODE (tree_store->root));
107     }
108 }
109
110 GtkType
111 gtk_tree_store_get_type (void)
112 {
113   static GType tree_store_type = 0;
114
115   if (!tree_store_type)
116     {
117       static const GTypeInfo tree_store_info =
118       {
119         sizeof (GtkTreeStoreClass),
120         NULL,           /* base_init */
121         NULL,           /* base_finalize */
122         (GClassInitFunc) gtk_tree_store_class_init,
123         NULL,           /* class_finalize */
124         NULL,           /* class_data */
125         sizeof (GtkTreeStore),
126         0,              /* n_preallocs */
127         (GInstanceInitFunc) gtk_tree_store_init
128       };
129
130       static const GInterfaceInfo tree_model_info =
131       {
132         (GInterfaceInitFunc) gtk_tree_store_tree_model_init,
133         NULL,
134         NULL
135       };
136
137       static const GInterfaceInfo drag_source_info =
138       {
139         (GInterfaceInitFunc) gtk_tree_store_drag_source_init,
140         NULL,
141         NULL
142       };
143
144       static const GInterfaceInfo drag_dest_info =
145       {
146         (GInterfaceInitFunc) gtk_tree_store_drag_dest_init,
147         NULL,
148         NULL
149       };
150
151       static const GInterfaceInfo sortable_info =
152       {
153         (GInterfaceInitFunc) gtk_tree_store_sortable_init,
154         NULL,
155         NULL
156       };
157
158       tree_store_type = g_type_register_static (G_TYPE_OBJECT, "GtkTreeStore", &tree_store_info, 0);
159
160       g_type_add_interface_static (tree_store_type,
161                                    GTK_TYPE_TREE_MODEL,
162                                    &tree_model_info);
163       g_type_add_interface_static (tree_store_type,
164                                    GTK_TYPE_TREE_DRAG_SOURCE,
165                                    &drag_source_info);
166       g_type_add_interface_static (tree_store_type,
167                                    GTK_TYPE_TREE_DRAG_DEST,
168                                    &drag_dest_info);
169       g_type_add_interface_static (tree_store_type,
170                                    GTK_TYPE_TREE_SORTABLE,
171                                    &sortable_info);
172
173     }
174
175   return tree_store_type;
176 }
177
178 static void
179 gtk_tree_store_class_init (GtkTreeStoreClass *tree_store_class)
180 {
181   GObjectClass *object_class;
182
183   object_class = (GObjectClass *) tree_store_class;
184
185 }
186
187 static void
188 gtk_tree_store_tree_model_init (GtkTreeModelIface *iface)
189 {
190   iface->get_flags = gtk_tree_store_get_flags;
191   iface->get_n_columns = gtk_tree_store_get_n_columns;
192   iface->get_column_type = gtk_tree_store_get_column_type;
193   iface->get_path = gtk_tree_store_get_path;
194   iface->get_value = gtk_tree_store_get_value;
195   iface->iter_next = gtk_tree_store_iter_next;
196   iface->iter_children = gtk_tree_store_iter_children;
197   iface->iter_has_child = gtk_tree_store_iter_has_child;
198   iface->iter_n_children = gtk_tree_store_iter_n_children;
199   iface->iter_nth_child = gtk_tree_store_iter_nth_child;
200   iface->iter_parent = gtk_tree_store_iter_parent;
201 }
202
203 static void
204 gtk_tree_store_drag_source_init (GtkTreeDragSourceIface *iface)
205 {
206   iface->drag_data_delete = gtk_tree_store_drag_data_delete;
207   iface->drag_data_get = gtk_tree_store_drag_data_get;
208 }
209
210 static void
211 gtk_tree_store_drag_dest_init (GtkTreeDragDestIface *iface)
212 {
213   iface->drag_data_received = gtk_tree_store_drag_data_received;
214   iface->row_drop_possible = gtk_tree_store_row_drop_possible;
215 }
216
217 static void
218 gtk_tree_store_sortable_init (GtkTreeSortableIface *iface)
219 {
220   iface->get_sort_column_id = gtk_tree_store_get_sort_column_id;
221   iface->set_sort_column_id = gtk_tree_store_set_sort_column_id;
222   iface->sort_column_id_set_func = gtk_tree_store_sort_column_id_set_func;
223 }
224
225 static void
226 gtk_tree_store_init (GtkTreeStore *tree_store)
227 {
228   tree_store->root = g_node_new (NULL);
229   tree_store->stamp = g_random_int ();
230   tree_store->sort_list = NULL;
231   tree_store->sort_column_id = -1;
232 }
233
234 GtkTreeStore *
235 gtk_tree_store_new (void)
236 {
237   return GTK_TREE_STORE (g_object_new (gtk_tree_store_get_type (), NULL));
238 }
239
240 GtkTreeStore *
241 gtk_tree_store_new_with_types (gint n_columns,
242                                ...)
243 {
244   GtkTreeStore *retval;
245   va_list args;
246   gint i;
247
248   g_return_val_if_fail (n_columns > 0, NULL);
249
250   retval = gtk_tree_store_new ();
251   gtk_tree_store_set_n_columns (retval, n_columns);
252
253   va_start (args, n_columns);
254
255   for (i = 0; i < n_columns; i++)
256     {
257       GType type = va_arg (args, GType);
258       if (! _gtk_tree_data_list_check_type (type))
259         {
260           g_warning ("%s: Invalid type %s passed to gtk_tree_store_new_with_types\n", G_STRLOC, g_type_name (type));
261           g_object_unref (G_OBJECT (retval));
262           return NULL;
263         }
264       gtk_tree_store_set_column_type (retval, i, type);
265     }
266   va_end (args);
267
268   return retval;
269 }
270
271 /**
272  * gtk_tree_store_set_n_columns:
273  * @tree_store: 
274  * @n_columns: 
275  * 
276  * As a side effect of calling this function, all sort columns that overlap with
277  * the current number of columns will be removed.
278  **/
279 void
280 gtk_tree_store_set_n_columns (GtkTreeStore *tree_store,
281                               gint          n_columns)
282 {
283   GType *new_columns;
284
285   g_return_if_fail (tree_store != NULL);
286   g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
287
288   if (tree_store->n_columns == n_columns)
289     return;
290
291   new_columns = g_new0 (GType, n_columns);
292   if (tree_store->column_headers)
293     {
294       /* copy the old header orders over */
295       if (n_columns >= tree_store->n_columns)
296         memcpy (new_columns, tree_store->column_headers, tree_store->n_columns * sizeof (gchar *));
297       else
298         memcpy (new_columns, tree_store->column_headers, n_columns * sizeof (GType));
299
300       g_free (tree_store->column_headers);
301     }
302
303   if (tree_store->sort_list)
304     _gtk_tree_data_list_header_free (tree_store->sort_list);
305
306   tree_store->sort_list = _gtk_tree_data_list_header_new (n_columns, tree_store->column_headers);
307
308   tree_store->column_headers = new_columns;
309   tree_store->n_columns = n_columns;
310 }
311
312 /**
313  * gtk_tree_store_set_column_type:
314  * @tree_store: a #GtkTreeStore
315  * @column: column number
316  * @type: type of the data to be stored in @column
317  *
318  * Supported types include: %G_TYPE_UINT, %G_TYPE_INT, %G_TYPE_UCHAR,
319  * %G_TYPE_CHAR, %G_TYPE_BOOLEAN, %G_TYPE_POINTER, %G_TYPE_FLOAT,
320  * %G_TYPE_DOUBLE, %G_TYPE_STRING, %G_TYPE_OBJECT, and %G_TYPE_BOXED, along with
321  * subclasses of those types such as %GDK_TYPE_PIXBUF.
322  *
323  **/
324 void
325 gtk_tree_store_set_column_type (GtkTreeStore *tree_store,
326                                 gint          column,
327                                 GType         type)
328 {
329   g_return_if_fail (tree_store != NULL);
330   g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
331   g_return_if_fail (column >=0 && column < tree_store->n_columns);
332   if (!_gtk_tree_data_list_check_type (type))
333     {
334       g_warning ("%s: Invalid type %s passed to gtk_tree_store_new_with_types\n", G_STRLOC, g_type_name (type));
335       return;
336     }
337   tree_store->column_headers[column] = type;
338 }
339
340 /* fulfill the GtkTreeModel requirements */
341 /* NOTE: GtkTreeStore::root is a GNode, that acts as the parent node.  However,
342  * it is not visible to the tree or to the user., and the path "0" refers to the
343  * first child of GtkTreeStore::root.
344  */
345
346
347 static guint
348 gtk_tree_store_get_flags (GtkTreeModel *tree_model)
349 {
350   g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), 0);
351
352   return GTK_TREE_MODEL_ITERS_PERSIST;
353 }
354
355 static gint
356 gtk_tree_store_get_n_columns (GtkTreeModel *tree_model)
357 {
358   g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), 0);
359
360   return GTK_TREE_STORE (tree_model)->n_columns;
361 }
362
363 static GType
364 gtk_tree_store_get_column_type (GtkTreeModel *tree_model,
365                                 gint          index)
366 {
367   g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), G_TYPE_INVALID);
368   g_return_val_if_fail (index < GTK_TREE_STORE (tree_model)->n_columns &&
369                         index >= 0, G_TYPE_INVALID);
370
371   return GTK_TREE_STORE (tree_model)->column_headers[index];
372 }
373
374 static GtkTreePath *
375 gtk_tree_store_get_path (GtkTreeModel *tree_model,
376                          GtkTreeIter  *iter)
377 {
378   GtkTreePath *retval;
379   GNode *tmp_node;
380   gint i = 0;
381
382   g_return_val_if_fail (tree_model != NULL, NULL);
383   g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), NULL);
384   g_return_val_if_fail (iter != NULL, NULL);
385   g_return_val_if_fail (iter->user_data != NULL, NULL);
386
387   validate_tree ((GtkTreeStore*)tree_model);
388
389   g_assert (G_NODE (iter->user_data)->parent != NULL);
390
391   if (G_NODE (iter->user_data)->parent == G_NODE (GTK_TREE_STORE (tree_model)->root))
392     {
393       retval = gtk_tree_path_new ();
394       tmp_node = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
395     }
396   else
397     {
398       GtkTreeIter tmp_iter = *iter;
399
400       tmp_iter.user_data = G_NODE (iter->user_data)->parent;
401
402       retval = gtk_tree_store_get_path (tree_model,
403                                         &tmp_iter);
404       tmp_node = G_NODE (iter->user_data)->parent->children;
405     }
406
407   if (retval == NULL)
408     return NULL;
409
410   if (tmp_node == NULL)
411     {
412       gtk_tree_path_free (retval);
413       return NULL;
414     }
415
416   for (; tmp_node; tmp_node = tmp_node->next)
417     {
418       if (tmp_node == G_NODE (iter->user_data))
419         break;
420       i++;
421     }
422
423   if (tmp_node == NULL)
424     {
425       /* We couldn't find node, meaning it's prolly not ours */
426       /* Perhaps I should do a g_return_if_fail here. */
427       gtk_tree_path_free (retval);
428       return NULL;
429     }
430
431   gtk_tree_path_append_index (retval, i);
432
433   return retval;
434 }
435
436
437 static void
438 gtk_tree_store_get_value (GtkTreeModel *tree_model,
439                           GtkTreeIter  *iter,
440                           gint          column,
441                           GValue       *value)
442 {
443   GtkTreeDataList *list;
444   gint tmp_column = column;
445
446   g_return_if_fail (tree_model != NULL);
447   g_return_if_fail (GTK_IS_TREE_STORE (tree_model));
448   g_return_if_fail (iter != NULL);
449   g_return_if_fail (column < GTK_TREE_STORE (tree_model)->n_columns);
450
451   list = G_NODE (iter->user_data)->data;
452
453   while (tmp_column-- > 0 && list)
454     list = list->next;
455
456   if (list)
457     {
458       _gtk_tree_data_list_node_to_value (list,
459                                          GTK_TREE_STORE (tree_model)->column_headers[column],
460                                          value);
461     }
462   else
463     {
464       /* We want to return an initialized but empty (default) value */
465       g_value_init (value, GTK_TREE_STORE (tree_model)->column_headers[column]);
466     }
467 }
468
469 static gboolean
470 gtk_tree_store_iter_next (GtkTreeModel  *tree_model,
471                           GtkTreeIter   *iter)
472 {
473   g_return_val_if_fail (iter->user_data != NULL, FALSE);
474
475   if (G_NODE (iter->user_data)->next)
476     {
477       iter->user_data = G_NODE (iter->user_data)->next;
478       return TRUE;
479     }
480   else
481     return FALSE;
482 }
483
484 static gboolean
485 gtk_tree_store_iter_children (GtkTreeModel *tree_model,
486                               GtkTreeIter  *iter,
487                               GtkTreeIter  *parent)
488 {
489   GNode *children;
490
491   g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE);
492
493   if (parent)
494     children = G_NODE (parent->user_data)->children;
495   else
496     children = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
497
498   if (children)
499     {
500       iter->stamp = GTK_TREE_STORE (tree_model)->stamp;
501       iter->user_data = children;
502       return TRUE;
503     }
504   else
505     return FALSE;
506 }
507
508 static gboolean
509 gtk_tree_store_iter_has_child (GtkTreeModel *tree_model,
510                                GtkTreeIter  *iter)
511 {
512   g_return_val_if_fail (tree_model != NULL, FALSE);
513   g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), FALSE);
514   g_return_val_if_fail (iter != NULL, FALSE);
515   g_return_val_if_fail (iter->user_data != NULL, FALSE);
516
517   return G_NODE (iter->user_data)->children != NULL;
518 }
519
520 static gint
521 gtk_tree_store_iter_n_children (GtkTreeModel *tree_model,
522                                 GtkTreeIter  *iter)
523 {
524   GNode *node;
525   gint i = 0;
526
527   g_return_val_if_fail (tree_model != NULL, 0);
528   g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), 0);
529   g_return_val_if_fail (iter != NULL, FALSE);
530   g_return_val_if_fail (iter->user_data != NULL, FALSE);
531
532   if (iter == NULL)
533     node = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
534   else
535     node = G_NODE (iter->user_data)->children;
536
537   while (node)
538     {
539       i++;
540       node = node->next;
541     }
542
543   return i;
544 }
545
546 static gboolean
547 gtk_tree_store_iter_nth_child (GtkTreeModel *tree_model,
548                                GtkTreeIter  *iter,
549                                GtkTreeIter  *parent,
550                                gint          n)
551 {
552   GNode *parent_node;
553   GNode *child;
554
555   g_return_val_if_fail (tree_model != NULL, FALSE);
556   g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), FALSE);
557   g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE);
558
559   if (parent == NULL)
560     parent_node = GTK_TREE_STORE (tree_model)->root;
561   else
562     parent_node = parent->user_data;
563
564   child = g_node_nth_child (parent_node, n);
565
566   if (child)
567     {
568       iter->user_data = child;
569       iter->stamp = GTK_TREE_STORE (tree_model)->stamp;
570       return TRUE;
571     }
572   else
573     return FALSE;
574 }
575
576 static gboolean
577 gtk_tree_store_iter_parent (GtkTreeModel *tree_model,
578                             GtkTreeIter  *iter,
579                             GtkTreeIter  *child)
580 {
581   GNode *parent;
582
583   g_return_val_if_fail (iter != NULL, FALSE);
584   g_return_val_if_fail (iter->user_data != NULL, FALSE);
585
586   parent = G_NODE (child->user_data)->parent;
587
588   g_assert (parent != NULL);
589
590   if (parent != GTK_TREE_STORE (tree_model)->root)
591     {
592       iter->user_data = parent;
593       iter->stamp = GTK_TREE_STORE (tree_model)->stamp;
594       return TRUE;
595     }
596   else
597     return FALSE;
598 }
599
600 /*
601  * This is a somewhat inelegant function that does a lot of list
602  * manipulations on it's own.
603  */
604 void
605 gtk_tree_store_set_value (GtkTreeStore *tree_store,
606                           GtkTreeIter  *iter,
607                           gint          column,
608                           GValue       *value)
609 {
610   GtkTreeDataList *list;
611   GtkTreeDataList *prev;
612   GtkTreePath *path = NULL;
613   GValue real_value = {0, };
614   gboolean converted = FALSE;
615
616   g_return_if_fail (tree_store != NULL);
617   g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
618   g_return_if_fail (column >= 0 && column < tree_store->n_columns);
619   g_return_if_fail (G_IS_VALUE (value));
620
621   if (! g_type_is_a (G_VALUE_TYPE (value), tree_store->column_headers[column]))
622     {
623       if (! (g_value_type_compatible (G_VALUE_TYPE (value), tree_store->column_headers[column]) &&
624              g_value_type_compatible (tree_store->column_headers[column], G_VALUE_TYPE (value))))
625         {
626           g_warning ("%s: Unable to convert from %s to %s\n",
627                      G_STRLOC,
628                      g_type_name (G_VALUE_TYPE (value)),
629                      g_type_name (tree_store->column_headers[column]));
630           return;
631         }
632       if (!g_value_transform (value, &real_value))
633         {
634           g_warning ("%s: Unable to make conversion from %s to %s\n",
635                      G_STRLOC,
636                      g_type_name (G_VALUE_TYPE (value)),
637                      g_type_name (tree_store->column_headers[column]));
638           g_value_unset (&real_value);
639           return;
640         }
641       converted = TRUE;
642     }
643
644   prev = list = G_NODE (iter->user_data)->data;
645
646   path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
647
648   while (list != NULL)
649     {
650       if (column == 0)
651         {
652           if (converted)
653             _gtk_tree_data_list_value_to_node (list, &real_value);
654           else
655             _gtk_tree_data_list_value_to_node (list, value);
656           gtk_tree_model_range_changed (GTK_TREE_MODEL (tree_store), path, iter, path, iter);
657           gtk_tree_path_free (path);
658           if (converted)
659             g_value_unset (&real_value);
660           return;
661         }
662
663       column--;
664       prev = list;
665       list = list->next;
666     }
667
668   if (G_NODE (iter->user_data)->data == NULL)
669     {
670       G_NODE (iter->user_data)->data = list = _gtk_tree_data_list_alloc ();
671       list->next = NULL;
672     }
673   else
674     {
675       list = prev->next = _gtk_tree_data_list_alloc ();
676       list->next = NULL;
677     }
678
679   while (column != 0)
680     {
681       list->next = _gtk_tree_data_list_alloc ();
682       list = list->next;
683       list->next = NULL;
684       column --;
685     }
686   if (converted)
687     _gtk_tree_data_list_value_to_node (list, &real_value);
688   else
689     _gtk_tree_data_list_value_to_node (list, value);
690   gtk_tree_model_range_changed (GTK_TREE_MODEL (tree_store), path, iter, path, iter);
691   gtk_tree_path_free (path);
692   if (converted)
693     g_value_unset (&real_value);
694
695   if (GTK_TREE_STORE_IS_SORTED (tree_store))
696     gtk_tree_store_sort_iter_changed (tree_store, iter, column);
697 }
698
699 /**
700  * gtk_tree_store_set_valist:
701  * @tree_store: a #GtkTreeStore
702  * @iter: row to set data for
703  * @var_args: va_list of column/value pairs
704  *
705  * See gtk_tree_store_set(); this version takes a va_list for
706  * use by language bindings.
707  *
708  **/
709 void
710 gtk_tree_store_set_valist (GtkTreeStore *tree_store,
711                            GtkTreeIter  *iter,
712                            va_list      var_args)
713 {
714   gint column;
715
716   g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
717
718   column = va_arg (var_args, gint);
719
720   while (column != -1)
721     {
722       GValue value = { 0, };
723       gchar *error = NULL;
724
725       if (column >= tree_store->n_columns)
726         {
727           g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column);
728           break;
729         }
730       g_value_init (&value, tree_store->column_headers[column]);
731
732       G_VALUE_COLLECT (&value, var_args, 0, &error);
733       if (error)
734         {
735           g_warning ("%s: %s", G_STRLOC, error);
736           g_free (error);
737
738           /* we purposely leak the value here, it might not be
739            * in a sane state if an error condition occoured
740            */
741           break;
742         }
743
744       gtk_tree_store_set_value (tree_store,
745                                 iter,
746                                 column,
747                                 &value);
748
749       g_value_unset (&value);
750
751       column = va_arg (var_args, gint);
752     }
753 }
754
755 /**
756  * gtk_tree_store_set:
757  * @tree_store: a #GtkTreeStore
758  * @iter: row iterator
759  * @Varargs: pairs of column number and value, terminated with -1
760  *
761  * Sets the value of one or more cells in the row referenced by @iter.
762  * The variable argument list should contain integer column numbers,
763  * each column number followed by the value to be set. For example,
764  * The list is terminated by a -1. For example, to set column 0 with type
765  * %G_TYPE_STRING to "Foo", you would write gtk_tree_store_set (store, iter,
766  * 0, "Foo", -1).
767  **/
768 void
769 gtk_tree_store_set (GtkTreeStore *tree_store,
770                     GtkTreeIter  *iter,
771                     ...)
772 {
773   va_list var_args;
774
775   g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
776
777   va_start (var_args, iter);
778   gtk_tree_store_set_valist (tree_store, iter, var_args);
779   va_end (var_args);
780 }
781
782 void
783 gtk_tree_store_remove (GtkTreeStore *model,
784                        GtkTreeIter  *iter)
785 {
786   GtkTreePath *path;
787   GtkTreeIter new_iter = {0,};
788   GNode *parent;
789
790   g_return_if_fail (model != NULL);
791   g_return_if_fail (GTK_IS_TREE_STORE (model));
792
793   parent = G_NODE (iter->user_data)->parent;
794
795   g_assert (parent != NULL);
796
797   if (G_NODE (iter->user_data)->data)
798     _gtk_tree_data_list_free ((GtkTreeDataList *) G_NODE (iter->user_data)->data,
799                               model->column_headers);
800
801   path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
802   g_node_destroy (G_NODE (iter->user_data));
803
804   model->stamp++;
805   gtk_tree_model_deleted (GTK_TREE_MODEL (model), path);
806
807   if (parent != G_NODE (model->root) && parent->children == NULL)
808     {
809       gtk_tree_path_up (path);
810
811       new_iter.stamp = model->stamp;
812       new_iter.user_data = parent;
813       gtk_tree_model_has_child_toggled (GTK_TREE_MODEL (model), path, &new_iter);
814     }
815   gtk_tree_path_free (path);
816 }
817
818 void
819 gtk_tree_store_insert (GtkTreeStore *model,
820                        GtkTreeIter  *iter,
821                        GtkTreeIter  *parent,
822                        gint          position)
823 {
824   GtkTreePath *path;
825   GNode *parent_node;
826
827   g_return_if_fail (model != NULL);
828   g_return_if_fail (GTK_IS_TREE_STORE (model));
829
830   if (parent)
831     parent_node = parent->user_data;
832   else
833     parent_node = model->root;
834
835   iter->stamp = model->stamp;
836   iter->user_data = g_node_new (NULL);
837   g_node_insert (parent_node, position, G_NODE (iter->user_data));
838
839   path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
840   gtk_tree_model_inserted (GTK_TREE_MODEL (model), path, iter);
841
842   gtk_tree_path_free (path);
843
844   validate_tree ((GtkTreeStore*)model);
845 }
846
847 void
848 gtk_tree_store_insert_before (GtkTreeStore *model,
849                               GtkTreeIter  *iter,
850                               GtkTreeIter  *parent,
851                               GtkTreeIter  *sibling)
852 {
853   GtkTreePath *path;
854   GNode *parent_node = NULL;
855   GNode *new_node;
856
857   g_return_if_fail (model != NULL);
858   g_return_if_fail (GTK_IS_TREE_STORE (model));
859   g_return_if_fail (iter != NULL);
860
861   new_node = g_node_new (NULL);
862
863   if (parent == NULL && sibling == NULL)
864     parent_node = model->root;
865   else if (parent == NULL)
866     parent_node = G_NODE (sibling->user_data)->parent;
867   else if (sibling == NULL)
868     parent_node = G_NODE (parent->user_data);
869   else
870     {
871       g_return_if_fail (G_NODE (sibling->user_data)->parent ==
872                         G_NODE (parent->user_data));
873       parent_node = G_NODE (parent->user_data);
874     }
875
876   g_node_insert_before (parent_node,
877                         sibling ? G_NODE (sibling->user_data) : NULL,
878                         new_node);
879
880   iter->stamp = model->stamp;
881   iter->user_data = new_node;
882
883   path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
884   gtk_tree_model_inserted (GTK_TREE_MODEL (model), path, iter);
885
886   gtk_tree_path_free (path);
887
888   validate_tree ((GtkTreeStore*)model);
889 }
890
891 void
892 gtk_tree_store_insert_after (GtkTreeStore *model,
893                              GtkTreeIter  *iter,
894                              GtkTreeIter  *parent,
895                              GtkTreeIter  *sibling)
896 {
897   GtkTreePath *path;
898   GNode *parent_node;
899   GNode *new_node;
900
901   g_return_if_fail (model != NULL);
902   g_return_if_fail (GTK_IS_TREE_STORE (model));
903   g_return_if_fail (iter != NULL);
904
905   new_node = g_node_new (NULL);
906
907   if (parent == NULL && sibling == NULL)
908     parent_node = model->root;
909   else if (parent == NULL)
910     parent_node = G_NODE (sibling->user_data)->parent;
911   else if (sibling == NULL)
912     parent_node = G_NODE (parent->user_data);
913   else
914     {
915       g_return_if_fail (G_NODE (sibling->user_data)->parent ==
916                         G_NODE (parent->user_data));
917       parent_node = G_NODE (parent->user_data);
918     }
919
920
921   g_node_insert_after (parent_node,
922                        sibling ? G_NODE (sibling->user_data) : NULL,
923                        new_node);
924
925   iter->stamp = model->stamp;
926   iter->user_data = new_node;
927
928   path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
929   gtk_tree_model_inserted (GTK_TREE_MODEL (model), path, iter);
930
931   gtk_tree_path_free (path);
932
933   validate_tree ((GtkTreeStore*)model);
934 }
935
936 void
937 gtk_tree_store_prepend (GtkTreeStore *model,
938                         GtkTreeIter  *iter,
939                         GtkTreeIter  *parent)
940 {
941   GNode *parent_node;
942
943   g_return_if_fail (model != NULL);
944   g_return_if_fail (GTK_IS_TREE_STORE (model));
945   g_return_if_fail (iter != NULL);
946
947   if (parent == NULL)
948     parent_node = model->root;
949   else
950     parent_node = parent->user_data;
951
952   if (parent_node->children == NULL)
953     {
954       GtkTreePath *path;
955
956       iter->stamp = model->stamp;
957       iter->user_data = g_node_new (NULL);
958
959       g_node_prepend (parent_node, iter->user_data);
960
961       if (parent_node != model->root)
962         {
963           path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), parent);
964           gtk_tree_model_has_child_toggled (GTK_TREE_MODEL (model), path, parent);
965           gtk_tree_path_append_index (path, 0);
966         }
967       else
968         {
969           path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
970         }
971       gtk_tree_model_inserted (GTK_TREE_MODEL (model), path, iter);
972       gtk_tree_path_free (path);
973     }
974   else
975     {
976       gtk_tree_store_insert_after (model, iter, parent, NULL);
977     }
978
979   validate_tree ((GtkTreeStore*)model);
980 }
981
982 void
983 gtk_tree_store_append (GtkTreeStore *model,
984                        GtkTreeIter  *iter,
985                        GtkTreeIter  *parent)
986 {
987   GNode *parent_node;
988
989   g_return_if_fail (model != NULL);
990   g_return_if_fail (GTK_IS_TREE_STORE (model));
991   g_return_if_fail (iter != NULL);
992
993   if (parent == NULL)
994     parent_node = model->root;
995   else
996     parent_node = parent->user_data;
997
998   if (parent_node->children == NULL)
999     {
1000       GtkTreePath *path;
1001
1002       iter->stamp = model->stamp;
1003       iter->user_data = g_node_new (NULL);
1004
1005       g_node_append (parent_node, G_NODE (iter->user_data));
1006
1007       if (parent_node != model->root)
1008         {
1009           path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), parent);
1010           gtk_tree_model_has_child_toggled (GTK_TREE_MODEL (model), path, parent);
1011           gtk_tree_path_append_index (path, 0);
1012         }
1013       else
1014         {
1015           path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
1016         }
1017
1018       gtk_tree_model_inserted (GTK_TREE_MODEL (model), path, iter);
1019       gtk_tree_path_free (path);
1020     }
1021   else
1022     {
1023       gtk_tree_store_insert_before (model, iter, parent, NULL);
1024     }
1025
1026   validate_tree ((GtkTreeStore*)model);
1027 }
1028
1029 gboolean
1030 gtk_tree_store_is_ancestor (GtkTreeStore *model,
1031                             GtkTreeIter  *iter,
1032                             GtkTreeIter  *descendant)
1033 {
1034   g_return_val_if_fail (model != NULL, FALSE);
1035   g_return_val_if_fail (GTK_IS_TREE_STORE (model), FALSE);
1036   g_return_val_if_fail (iter != NULL, FALSE);
1037   g_return_val_if_fail (descendant != NULL, FALSE);
1038
1039   return g_node_is_ancestor (G_NODE (iter->user_data),
1040                              G_NODE (descendant->user_data));
1041 }
1042
1043
1044 gint
1045 gtk_tree_store_iter_depth (GtkTreeStore *model,
1046                            GtkTreeIter  *iter)
1047 {
1048   g_return_val_if_fail (model != NULL, 0);
1049   g_return_val_if_fail (GTK_IS_TREE_STORE (model), 0);
1050   g_return_val_if_fail (iter != NULL, 0);
1051
1052   return g_node_depth (G_NODE (iter->user_data)) - 1;
1053 }
1054
1055 /* DND */
1056
1057
1058
1059 static gboolean
1060 gtk_tree_store_drag_data_delete (GtkTreeDragSource *drag_source,
1061                                  GtkTreePath       *path)
1062 {
1063   GtkTreeIter iter;
1064
1065   g_return_val_if_fail (GTK_IS_TREE_STORE (drag_source), FALSE);
1066
1067   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source),
1068                                &iter,
1069                                path))
1070     {
1071       gtk_tree_store_remove (GTK_TREE_STORE (drag_source),
1072                              &iter);
1073       return TRUE;
1074     }
1075   else
1076     {
1077       return FALSE;
1078     }
1079 }
1080
1081 static gboolean
1082 gtk_tree_store_drag_data_get (GtkTreeDragSource *drag_source,
1083                               GtkTreePath       *path,
1084                               GtkSelectionData  *selection_data)
1085 {
1086   g_return_val_if_fail (GTK_IS_TREE_STORE (drag_source), FALSE);
1087
1088   /* Note that we don't need to handle the GTK_TREE_MODEL_ROW
1089    * target, because the default handler does it for us, but
1090    * we do anyway for the convenience of someone maybe overriding the
1091    * default handler.
1092    */
1093
1094   if (gtk_selection_data_set_tree_row (selection_data,
1095                                        GTK_TREE_MODEL (drag_source),
1096                                        path))
1097     {
1098       return TRUE;
1099     }
1100   else
1101     {
1102       /* FIXME handle text targets at least. */
1103     }
1104
1105   return FALSE;
1106 }
1107
1108 static void
1109 copy_node_data (GtkTreeStore *tree_store,
1110                 GtkTreeIter  *src_iter,
1111                 GtkTreeIter  *dest_iter)
1112 {
1113   GtkTreeDataList *dl = G_NODE (src_iter->user_data)->data;
1114   GtkTreeDataList *copy_head = NULL;
1115   GtkTreeDataList *copy_prev = NULL;
1116   GtkTreeDataList *copy_iter = NULL;
1117   GtkTreePath *path;
1118   gint col;
1119
1120   col = 0;
1121   while (dl)
1122     {
1123       copy_iter = _gtk_tree_data_list_node_copy (dl, tree_store->column_headers[col]);
1124
1125       if (copy_head == NULL)
1126         copy_head = copy_iter;
1127
1128       if (copy_prev)
1129         copy_prev->next = copy_iter;
1130
1131       copy_prev = copy_iter;
1132
1133       dl = dl->next;
1134       ++col;
1135     }
1136
1137   G_NODE (dest_iter->user_data)->data = copy_head;
1138
1139   path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), dest_iter);
1140   gtk_tree_model_range_changed (GTK_TREE_MODEL (tree_store), path, dest_iter, path, dest_iter);
1141   gtk_tree_path_free (path);
1142 }
1143
1144 static void
1145 recursive_node_copy (GtkTreeStore *tree_store,
1146                      GtkTreeIter  *src_iter,
1147                      GtkTreeIter  *dest_iter)
1148 {
1149   GtkTreeIter child;
1150   GtkTreeModel *model;
1151
1152   model = GTK_TREE_MODEL (tree_store);
1153
1154   copy_node_data (tree_store, src_iter, dest_iter);
1155
1156   if (gtk_tree_model_iter_children (model,
1157                                     &child,
1158                                     src_iter))
1159     {
1160       /* Need to create children and recurse. Note our
1161        * dependence on persistent iterators here.
1162        */
1163       do
1164         {
1165           GtkTreeIter copy;
1166
1167           /* Gee, a really slow algorithm... ;-) FIXME */
1168           gtk_tree_store_append (tree_store,
1169                                  &copy,
1170                                  dest_iter);
1171
1172           recursive_node_copy (tree_store, &child, &copy);
1173         }
1174       while (gtk_tree_model_iter_next (model, &child));
1175     }
1176 }
1177
1178 static gboolean
1179 gtk_tree_store_drag_data_received (GtkTreeDragDest   *drag_dest,
1180                                    GtkTreePath       *dest,
1181                                    GtkSelectionData  *selection_data)
1182 {
1183   GtkTreeModel *tree_model;
1184   GtkTreeStore *tree_store;
1185   GtkTreeModel *src_model = NULL;
1186   GtkTreePath *src_path = NULL;
1187   gboolean retval = FALSE;
1188
1189   g_return_val_if_fail (GTK_IS_TREE_STORE (drag_dest), FALSE);
1190
1191   tree_model = GTK_TREE_MODEL (drag_dest);
1192   tree_store = GTK_TREE_STORE (drag_dest);
1193
1194   validate_tree (tree_store);
1195
1196   if (gtk_selection_data_get_tree_row (selection_data,
1197                                        &src_model,
1198                                        &src_path) &&
1199       src_model == tree_model)
1200     {
1201       /* Copy the given row to a new position */
1202       GtkTreeIter src_iter;
1203       GtkTreeIter dest_iter;
1204       GtkTreePath *prev;
1205
1206       if (!gtk_tree_model_get_iter (src_model,
1207                                     &src_iter,
1208                                     src_path))
1209         {
1210           goto out;
1211         }
1212
1213       /* Get the path to insert _after_ (dest is the path to insert _before_) */
1214       prev = gtk_tree_path_copy (dest);
1215
1216       if (!gtk_tree_path_prev (prev))
1217         {
1218           GtkTreeIter dest_parent;
1219           GtkTreePath *parent;
1220           GtkTreeIter *dest_parent_p;
1221
1222           /* dest was the first spot at the current depth; which means
1223            * we are supposed to prepend.
1224            */
1225
1226           /* Get the parent, NULL if parent is the root */
1227           dest_parent_p = NULL;
1228           parent = gtk_tree_path_copy (dest);
1229           if (gtk_tree_path_up (parent))
1230             {
1231               gtk_tree_model_get_iter (tree_model,
1232                                        &dest_parent,
1233                                        parent);
1234               dest_parent_p = &dest_parent;
1235             }
1236           gtk_tree_path_free (parent);
1237           parent = NULL;
1238
1239           gtk_tree_store_prepend (GTK_TREE_STORE (tree_model),
1240                                   &dest_iter,
1241                                   dest_parent_p);
1242
1243           retval = TRUE;
1244         }
1245       else
1246         {
1247           if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model),
1248                                        &dest_iter,
1249                                        prev))
1250             {
1251               GtkTreeIter tmp_iter = dest_iter;
1252               gtk_tree_store_insert_after (GTK_TREE_STORE (tree_model),
1253                                            &dest_iter,
1254                                            NULL,
1255                                            &tmp_iter);
1256               retval = TRUE;
1257
1258             }
1259         }
1260
1261       gtk_tree_path_free (prev);
1262
1263       /* If we succeeded in creating dest_iter, walk src_iter tree branch,
1264        * duplicating it below dest_iter.
1265        */
1266
1267       if (retval)
1268         {
1269           recursive_node_copy (tree_store,
1270                                &src_iter,
1271                                &dest_iter);
1272         }
1273     }
1274   else
1275     {
1276       /* FIXME maybe add some data targets eventually, or handle text
1277        * targets in the simple case.
1278        */
1279
1280     }
1281
1282  out:
1283
1284   if (src_path)
1285     gtk_tree_path_free (src_path);
1286
1287   return retval;
1288 }
1289
1290 static gboolean
1291 gtk_tree_store_row_drop_possible (GtkTreeDragDest *drag_dest,
1292                                   GtkTreeModel    *src_model,
1293                                   GtkTreePath     *src_path,
1294                                   GtkTreePath     *dest_path)
1295 {
1296   /* can only drag to ourselves */
1297   if (src_model != GTK_TREE_MODEL (drag_dest))
1298     return FALSE;
1299
1300   /* Can't drop into ourself. */
1301   if (gtk_tree_path_is_ancestor (src_path,
1302                                  dest_path))
1303     return FALSE;
1304
1305   /* Can't drop if dest_path's parent doesn't exist */
1306   {
1307     GtkTreeIter iter;
1308     GtkTreePath *tmp = gtk_tree_path_copy (dest_path);
1309
1310     /* if we can't go up, we know the parent exists, the root
1311      * always exists.
1312      */
1313     if (gtk_tree_path_up (tmp))
1314       {
1315         if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_dest),
1316                                       &iter, tmp))
1317           {
1318             if (tmp)
1319               gtk_tree_path_free (tmp);
1320             return FALSE;
1321           }
1322       }
1323
1324     if (tmp)
1325       gtk_tree_path_free (tmp);
1326   }
1327
1328   /* Can otherwise drop anywhere. */
1329   return TRUE;
1330 }
1331
1332
1333 static void
1334 gtk_tree_store_sort (GtkTreeStore *tree_store)
1335 {
1336
1337 }
1338
1339 static void
1340 gtk_tree_store_sort_iter_changed (GtkTreeStore *tree_store,
1341                                   GtkTreeIter  *iter,
1342                                   gint          column)
1343 {
1344   GtkTreeDataSortHeader *header;
1345   GNode *prev = NULL;
1346   GNode *next = NULL;
1347   GNode *node;
1348   GtkTreePath *tmp_path;
1349   GtkTreeIter tmp_iter;
1350   gint cmp_a = 0;
1351   gint cmp_b = 0;
1352   gint i;
1353   gint old_location;
1354   gint new_location;
1355   gint *new_order;
1356   gint length;
1357
1358   /* FIX*/
1359   if (G_NODE (iter->user_data)->parent)
1360     node = G_NODE (iter->user_data)->parent->children;
1361   else
1362     node = G_NODE (tree_store->root);
1363
1364   tmp_iter.stamp = tree_store->stamp;
1365   header = _gtk_tree_data_list_get_header (tree_store->sort_list,
1366                                            tree_store->sort_column_id);
1367   g_return_if_fail (header != NULL);
1368   g_return_if_fail (header->func != NULL);
1369
1370   /* If it's the built in function, we don't sort. */
1371   if (header->func == gtk_tree_data_list_compare_func &&
1372       tree_store->sort_column_id != column)
1373     return;
1374
1375   old_location = 0;
1376   /* First we find the iter, its prev, and its next */
1377   while (node)
1378     {
1379       if (node == G_NODE (iter->user_data))
1380         break;
1381       prev = node;
1382       node = node->next;
1383       old_location++;
1384     }
1385   g_assert (node != NULL);
1386
1387   next = node->next;
1388
1389   /* Check the common case, where we don't need to sort it moved. */
1390   if (prev != NULL)
1391     {
1392       tmp_iter.user_data = prev;
1393       cmp_a = (* header->func) (GTK_TREE_MODEL (tree_store),
1394                                 &tmp_iter, iter,
1395                                 header->data);
1396     }
1397
1398   if (next != NULL)
1399     {
1400       tmp_iter.user_data = next;
1401       cmp_b = (* header->func) (GTK_TREE_MODEL (tree_store),
1402                                 iter, &tmp_iter,
1403                                 header->data);
1404     }
1405
1406
1407   if (tree_store->order == GTK_TREE_SORT_DESCENDING)
1408     {
1409       if (cmp_a < 0)
1410         cmp_a = 1;
1411       else if (cmp_a > 0)
1412         cmp_a = -1;
1413
1414       if (cmp_b < 0)
1415         cmp_b = 1;
1416       else if (cmp_b > 0)
1417         cmp_b = -1;
1418     }
1419
1420   if (prev == NULL && cmp_b <= 0)
1421     return;
1422   else if (next == NULL && cmp_a <= 0)
1423     return;
1424   else if (prev != NULL && next != NULL &&
1425            cmp_a <= 0 && cmp_b <= 0)
1426     return;
1427
1428   /* We actually need to sort it */
1429   /* First, remove the old link. */
1430
1431   if (prev == NULL)
1432     tree_store->root = next;
1433   else
1434     prev->next = next;
1435   node->next = NULL;
1436   
1437   /* FIXME: as an optimization, we can potentially start at next */
1438   prev = NULL;
1439   node = G_NODE (tree_store->root);
1440   new_location = 0;
1441   tmp_iter.user_data = node;
1442   if (tree_store->order == GTK_TREE_SORT_DESCENDING)
1443     cmp_a = (* header->func) (GTK_TREE_MODEL (tree_store),
1444                               &tmp_iter, iter, header->data);
1445   else
1446     cmp_a = (* header->func) (GTK_TREE_MODEL (tree_store),
1447                               iter, &tmp_iter, header->data);
1448
1449   while ((node->next) && (cmp_a > 0))
1450     {
1451       prev = node;
1452       node = node->next;
1453       new_location++;
1454       tmp_iter.user_data = node;
1455       if (tree_store->order == GTK_TREE_SORT_DESCENDING)
1456         cmp_a = (* header->func) (GTK_TREE_MODEL (tree_store),
1457                                   &tmp_iter, iter, header->data);
1458       else
1459         cmp_a = (* header->func) (GTK_TREE_MODEL (tree_store),
1460                                   iter, &tmp_iter, header->data);
1461     }
1462
1463   if ((!node->next) && (cmp_a > 0))
1464     {
1465       node->next = G_NODE (iter->user_data);
1466     }
1467   else if (prev)
1468     {
1469       prev->next = G_NODE (iter->user_data);
1470       G_NODE (iter->user_data)->next = node;
1471     }
1472   else
1473     {
1474       G_NODE (iter->user_data)->next = G_NODE (tree_store->root);
1475       tree_store->root = G_NODE (iter->user_data);
1476     }
1477
1478   /* Emit the reordered signal. */
1479   length = g_node_n_children (node->parent);
1480   new_order = g_new (int, length);
1481   if (old_location < new_location)
1482     for (i = 0; i < length; i++)
1483       {
1484         if (i < old_location ||
1485             i > new_location)
1486           new_order[i] = i;
1487         else if (i >= old_location &&
1488                  i < new_location)
1489           new_order[i] = i + 1;
1490         else if (i == new_location)
1491           new_order[i] = old_location;
1492       }
1493   else
1494     for (i = 0; i < length; i++)
1495       {
1496         if (i < new_location ||
1497             i > old_location)
1498           new_order[i] = i;
1499         else if (i > new_location &&
1500                  i <= old_location)
1501           new_order[i] = i - 1;
1502         else if (i == new_location)
1503           new_order[i] = old_location;
1504       }
1505
1506
1507   tmp_path = gtk_tree_path_new ();
1508   tmp_iter.user_data = NULL;
1509
1510   gtk_tree_model_reordered (GTK_TREE_MODEL (tree_store),
1511                             tmp_path, &tmp_iter,
1512                             new_order);
1513
1514   gtk_tree_path_free (tmp_path);
1515   g_free (new_order);
1516 }
1517
1518
1519 static gboolean
1520 gtk_tree_store_get_sort_column_id (GtkTreeSortable  *sortable,
1521                                    gint             *sort_column_id,
1522                                    GtkTreeSortOrder *order)
1523 {
1524   GtkTreeStore *tree_store = (GtkTreeStore *) sortable;
1525
1526   g_return_val_if_fail (sortable != NULL, FALSE);
1527   g_return_val_if_fail (GTK_IS_TREE_STORE (sortable), FALSE);
1528
1529   if (tree_store->sort_column_id == -1)
1530     return FALSE;
1531
1532   if (sort_column_id)
1533     * sort_column_id = tree_store->sort_column_id;
1534   if (order)
1535     * order = tree_store->order;
1536   return TRUE;
1537
1538 }
1539
1540 static void
1541 gtk_tree_store_set_sort_column_id (GtkTreeSortable  *sortable,
1542                                    gint              sort_column_id,
1543                                    GtkTreeSortOrder  order)
1544 {
1545   GtkTreeStore *tree_store = (GtkTreeStore *) sortable;
1546   GList *list;
1547
1548   g_return_if_fail (sortable != NULL);
1549   g_return_if_fail (GTK_IS_TREE_STORE (sortable));
1550
1551   for (list = tree_store->sort_list; list; list = list->next)
1552     {
1553       GtkTreeDataSortHeader *header = (GtkTreeDataSortHeader*) list->data;
1554       if (header->sort_column_id == sort_column_id)
1555         break;
1556     }
1557   g_return_if_fail (list != NULL);
1558
1559   if ((tree_store->sort_column_id == sort_column_id) &&
1560       (tree_store->order == order))
1561     return;
1562
1563   tree_store->sort_column_id = sort_column_id;
1564   tree_store->order = order;
1565
1566   if (tree_store->sort_column_id >= 0)
1567     gtk_tree_store_sort (tree_store);
1568
1569   gtk_tree_sortable_sort_column_changed (sortable);
1570 }
1571
1572 static void
1573 gtk_tree_store_sort_column_id_set_func (GtkTreeSortable        *sortable,
1574                                         gint                    sort_column_id,
1575                                         GtkTreeIterCompareFunc  func,
1576                                         gpointer                data,
1577                                         GtkDestroyNotify        destroy)
1578 {
1579   GtkTreeStore *tree_store = (GtkTreeStore *) sortable;
1580   GtkTreeDataSortHeader *header = NULL;
1581   GList *list;
1582
1583   g_return_if_fail (sortable != NULL);
1584   g_return_if_fail (GTK_IS_TREE_STORE (sortable));
1585   g_return_if_fail (func != NULL);
1586
1587   for (list = tree_store->sort_list; list; list = list->next)
1588     {
1589       header = (GtkTreeDataSortHeader*) list->data;
1590       if (header->sort_column_id == sort_column_id)
1591         break;
1592     }
1593
1594   if (header == NULL)
1595     {
1596       header = g_new0 (GtkTreeDataSortHeader, 1);
1597       header->sort_column_id = sort_column_id;
1598       tree_store->sort_list = g_list_append (tree_store->sort_list, header);
1599     }
1600
1601   if (header->destroy)
1602     (* header->destroy) (header->data);
1603
1604   header->func = func;
1605   header->data = data;
1606   header->destroy = destroy;
1607
1608 }
1609
1610 static void
1611 validate_gnode (GNode* node)
1612 {
1613   GNode *iter;
1614
1615   iter = node->children;
1616   while (iter != NULL)
1617     {
1618       g_assert (iter->parent == node);
1619       if (iter->prev)
1620         g_assert (iter->prev->next == iter);
1621       validate_gnode (iter);
1622       iter = iter->next;
1623     }
1624 }
1625
1626