]> Pileus Git - ~andy/gtk/blob - gtk/gtkliststore.c
API additions: _move, _reorder and _swap for stores, path constructor.
[~andy/gtk] / gtk / gtkliststore.c
1 /* gtkliststore.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 <string.h>
21 #include "gtktreemodel.h"
22 #include "gtkliststore.h"
23 #include "gtktreedatalist.h"
24 #include "gtksignal.h"
25 #include "gtktreednd.h"
26 #include <gobject/gvaluecollector.h>
27
28 #define G_SLIST(x) ((GSList *) x)
29 #define GTK_LIST_STORE_IS_SORTED(list) (GTK_LIST_STORE (list)->sort_column_id != -2)
30 #define VALID_ITER(iter, list_store) (iter!= NULL && iter->user_data != NULL && list_store->stamp == iter->stamp)
31
32 static void         gtk_list_store_init            (GtkListStore      *list_store);
33 static void         gtk_list_store_class_init      (GtkListStoreClass *class);
34 static void         gtk_list_store_tree_model_init (GtkTreeModelIface *iface);
35 static void         gtk_list_store_drag_source_init(GtkTreeDragSourceIface *iface);
36 static void         gtk_list_store_drag_dest_init  (GtkTreeDragDestIface   *iface);
37 static void         gtk_list_store_sortable_init   (GtkTreeSortableIface   *iface);
38 static void         gtk_list_store_finalize        (GObject           *object);
39 static guint        gtk_list_store_get_flags       (GtkTreeModel      *tree_model);
40 static gint         gtk_list_store_get_n_columns   (GtkTreeModel      *tree_model);
41 static GType        gtk_list_store_get_column_type (GtkTreeModel      *tree_model,
42                                                     gint               index);
43 static gboolean     gtk_list_store_get_iter        (GtkTreeModel      *tree_model,
44                                                     GtkTreeIter       *iter,
45                                                     GtkTreePath       *path);
46 static GtkTreePath *gtk_list_store_get_path        (GtkTreeModel      *tree_model,
47                                                     GtkTreeIter       *iter);
48 static void         gtk_list_store_get_value       (GtkTreeModel      *tree_model,
49                                                     GtkTreeIter       *iter,
50                                                     gint               column,
51                                                     GValue            *value);
52 static gboolean     gtk_list_store_iter_next       (GtkTreeModel      *tree_model,
53                                                     GtkTreeIter       *iter);
54 static gboolean     gtk_list_store_iter_children   (GtkTreeModel      *tree_model,
55                                                     GtkTreeIter       *iter,
56                                                     GtkTreeIter       *parent);
57 static gboolean     gtk_list_store_iter_has_child  (GtkTreeModel      *tree_model,
58                                                     GtkTreeIter       *iter);
59 static gint         gtk_list_store_iter_n_children (GtkTreeModel      *tree_model,
60                                                     GtkTreeIter       *iter);
61 static gboolean     gtk_list_store_iter_nth_child  (GtkTreeModel      *tree_model,
62                                                     GtkTreeIter       *iter,
63                                                     GtkTreeIter       *parent,
64                                                     gint               n);
65 static gboolean     gtk_list_store_iter_parent     (GtkTreeModel      *tree_model,
66                                                     GtkTreeIter       *iter,
67                                                     GtkTreeIter       *child);
68
69
70 static void gtk_list_store_set_n_columns   (GtkListStore *list_store,
71                                             gint          n_columns);
72 static void gtk_list_store_set_column_type (GtkListStore *list_store,
73                                             gint          column,
74                                             GType         type);
75
76
77 /* Drag and Drop */
78 static gboolean gtk_list_store_drag_data_delete   (GtkTreeDragSource *drag_source,
79                                                    GtkTreePath       *path);
80 static gboolean gtk_list_store_drag_data_get      (GtkTreeDragSource *drag_source,
81                                                    GtkTreePath       *path,
82                                                    GtkSelectionData  *selection_data);
83 static gboolean gtk_list_store_drag_data_received (GtkTreeDragDest   *drag_dest,
84                                                    GtkTreePath       *dest,
85                                                    GtkSelectionData  *selection_data);
86 static gboolean gtk_list_store_row_drop_possible  (GtkTreeDragDest   *drag_dest,
87                                                    GtkTreePath       *dest_path,
88                                                    GtkSelectionData  *selection_data);
89
90
91 /* sortable */
92 static void     gtk_list_store_sort                  (GtkListStore           *list_store);
93 static void     gtk_list_store_sort_iter_changed     (GtkListStore           *list_store,
94                                                       GtkTreeIter            *iter,
95                                                       gint                    column);
96 static gboolean gtk_list_store_get_sort_column_id    (GtkTreeSortable        *sortable,
97                                                       gint                   *sort_column_id,
98                                                       GtkSortType            *order);
99 static void     gtk_list_store_set_sort_column_id    (GtkTreeSortable        *sortable,
100                                                       gint                    sort_column_id,
101                                                       GtkSortType             order);
102 static void     gtk_list_store_set_sort_func         (GtkTreeSortable        *sortable,
103                                                       gint                    sort_column_id,
104                                                       GtkTreeIterCompareFunc  func,
105                                                       gpointer                data,
106                                                       GtkDestroyNotify        destroy);
107 static void     gtk_list_store_set_default_sort_func (GtkTreeSortable        *sortable,
108                                                       GtkTreeIterCompareFunc  func,
109                                                       gpointer                data,
110                                                       GtkDestroyNotify        destroy);
111 static gboolean gtk_list_store_has_default_sort_func (GtkTreeSortable        *sortable);
112
113
114 static GObjectClass *parent_class = NULL;
115
116
117 static void
118 validate_list_store (GtkListStore *list_store)
119 {
120   if (gtk_debug_flags & GTK_DEBUG_TREE)
121     {
122       g_assert (g_slist_length (list_store->root) == list_store->length);
123
124       g_assert (g_slist_last (list_store->root) == list_store->tail);
125     }
126 }
127
128 GtkType
129 gtk_list_store_get_type (void)
130 {
131   static GType list_store_type = 0;
132
133   if (!list_store_type)
134     {
135       static const GTypeInfo list_store_info =
136       {
137         sizeof (GtkListStoreClass),
138         NULL,           /* base_init */
139         NULL,           /* base_finalize */
140         (GClassInitFunc) gtk_list_store_class_init,
141         NULL,           /* class_finalize */
142         NULL,           /* class_data */
143         sizeof (GtkListStore),
144         0,
145         (GInstanceInitFunc) gtk_list_store_init,
146       };
147
148       static const GInterfaceInfo tree_model_info =
149       {
150         (GInterfaceInitFunc) gtk_list_store_tree_model_init,
151         NULL,
152         NULL
153       };
154
155       static const GInterfaceInfo drag_source_info =
156       {
157         (GInterfaceInitFunc) gtk_list_store_drag_source_init,
158         NULL,
159         NULL
160       };
161
162       static const GInterfaceInfo drag_dest_info =
163       {
164         (GInterfaceInitFunc) gtk_list_store_drag_dest_init,
165         NULL,
166         NULL
167       };
168
169       static const GInterfaceInfo sortable_info =
170       {
171         (GInterfaceInitFunc) gtk_list_store_sortable_init,
172         NULL,
173         NULL
174       };
175
176       list_store_type = g_type_register_static (G_TYPE_OBJECT, "GtkListStore", &list_store_info, 0);
177       g_type_add_interface_static (list_store_type,
178                                    GTK_TYPE_TREE_MODEL,
179                                    &tree_model_info);
180       g_type_add_interface_static (list_store_type,
181                                    GTK_TYPE_TREE_DRAG_SOURCE,
182                                    &drag_source_info);
183       g_type_add_interface_static (list_store_type,
184                                    GTK_TYPE_TREE_DRAG_DEST,
185                                    &drag_dest_info);
186       g_type_add_interface_static (list_store_type,
187                                    GTK_TYPE_TREE_SORTABLE,
188                                    &sortable_info);
189     }
190
191   return list_store_type;
192 }
193
194 static void
195 gtk_list_store_class_init (GtkListStoreClass *class)
196 {
197   GObjectClass *object_class;
198
199   parent_class = g_type_class_peek_parent (class);
200   object_class = (GObjectClass*) class;
201
202   object_class->finalize = gtk_list_store_finalize;
203 }
204
205 static void
206 gtk_list_store_tree_model_init (GtkTreeModelIface *iface)
207 {
208   iface->get_flags = gtk_list_store_get_flags;
209   iface->get_n_columns = gtk_list_store_get_n_columns;
210   iface->get_column_type = gtk_list_store_get_column_type;
211   iface->get_iter = gtk_list_store_get_iter;
212   iface->get_path = gtk_list_store_get_path;
213   iface->get_value = gtk_list_store_get_value;
214   iface->iter_next = gtk_list_store_iter_next;
215   iface->iter_children = gtk_list_store_iter_children;
216   iface->iter_has_child = gtk_list_store_iter_has_child;
217   iface->iter_n_children = gtk_list_store_iter_n_children;
218   iface->iter_nth_child = gtk_list_store_iter_nth_child;
219   iface->iter_parent = gtk_list_store_iter_parent;
220 }
221
222 static void
223 gtk_list_store_drag_source_init (GtkTreeDragSourceIface *iface)
224 {
225   iface->drag_data_delete = gtk_list_store_drag_data_delete;
226   iface->drag_data_get = gtk_list_store_drag_data_get;
227 }
228
229 static void
230 gtk_list_store_drag_dest_init (GtkTreeDragDestIface *iface)
231 {
232   iface->drag_data_received = gtk_list_store_drag_data_received;
233   iface->row_drop_possible = gtk_list_store_row_drop_possible;
234 }
235
236 static void
237 gtk_list_store_sortable_init (GtkTreeSortableIface *iface)
238 {
239   iface->get_sort_column_id = gtk_list_store_get_sort_column_id;
240   iface->set_sort_column_id = gtk_list_store_set_sort_column_id;
241   iface->set_sort_func = gtk_list_store_set_sort_func;
242   iface->set_default_sort_func = gtk_list_store_set_default_sort_func;
243   iface->has_default_sort_func = gtk_list_store_has_default_sort_func;
244 }
245
246 static void
247 gtk_list_store_init (GtkListStore *list_store)
248 {
249   list_store->root = NULL;
250   list_store->tail = NULL;
251   list_store->sort_list = NULL;
252   list_store->stamp = g_random_int ();
253   list_store->length = 0;
254   list_store->sort_column_id = -2;
255   list_store->columns_dirty = FALSE;
256 }
257
258 /**
259  * gtk_list_store_new:
260  * @n_columns: number of columns in the list store
261  * @Varargs: all #GType types for the columns, from first to last
262  *
263  * Creates a new list store as with @n_columns columns each of the types passed
264  * in.  As an example, <literal>gtk_tree_store_new (3, G_TYPE_INT, G_TYPE_STRING,
265  * GDK_TYPE_PIXBUF);</literal> will create a new #GtkListStore with three columns, of type
266  * int, string and #GdkPixbuf respectively.
267  *
268  * Return value: a new #GtkListStore
269  **/
270 GtkListStore *
271 gtk_list_store_new (gint n_columns,
272                                ...)
273 {
274   GtkListStore *retval;
275   va_list args;
276   gint i;
277
278   g_return_val_if_fail (n_columns > 0, NULL);
279
280   retval = GTK_LIST_STORE (g_object_new (gtk_list_store_get_type (), NULL));
281   gtk_list_store_set_n_columns (retval, n_columns);
282
283   va_start (args, n_columns);
284
285   for (i = 0; i < n_columns; i++)
286     {
287       GType type = va_arg (args, GType);
288       if (! _gtk_tree_data_list_check_type (type))
289         {
290           g_warning ("%s: Invalid type %s passed to gtk_list_store_new\n", G_STRLOC, g_type_name (type));
291           g_object_unref (G_OBJECT (retval));
292           return NULL;
293         }
294
295       gtk_list_store_set_column_type (retval, i, type);
296     }
297
298   va_end (args);
299
300   return retval;
301 }
302
303
304 /**
305  * gtk_list_store_newv:
306  * @n_columns: number of columns in the list store
307  * @types: an array of #GType types for the columns, from first to last
308  *
309  * Non-vararg creation function.  Used primarily by language bindings.
310  *
311  * Return value: a new #GtkListStore
312  **/
313 GtkListStore *
314 gtk_list_store_newv (gint   n_columns,
315                      GType *types)
316 {
317   GtkListStore *retval;
318   gint i;
319
320   g_return_val_if_fail (n_columns > 0, NULL);
321
322   retval = GTK_LIST_STORE (g_object_new (gtk_list_store_get_type (), NULL));
323   gtk_list_store_set_n_columns (retval, n_columns);
324
325   for (i = 0; i < n_columns; i++)
326     {
327       if (! _gtk_tree_data_list_check_type (types[i]))
328         {
329           g_warning ("%s: Invalid type %s passed to gtk_list_store_newv\n", G_STRLOC, g_type_name (types[i]));
330           g_object_unref (G_OBJECT (retval));
331           return NULL;
332         }
333
334       gtk_list_store_set_column_type (retval, i, types[i]);
335     }
336
337   return retval;
338 }
339
340 /**
341  * gtk_list_store_set_column_types:
342  * @list_store: A #GtkListStore
343  * @n_columns: Number of columns for the list store
344  * @types: An array length n of #GTypes
345  * 
346  * This function is meant primarily for #GObjects that inherit from #GtkListStore,
347  * and should only be used when constructing a new #GtkListStore.  It will not
348  * function after a row has been added, or a method on the #GtkTreeModel
349  * interface is called.
350  **/
351 void
352 gtk_list_store_set_column_types (GtkListStore *list_store,
353                                  gint          n_columns,
354                                  GType        *types)
355 {
356   gint i;
357
358   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
359   g_return_if_fail (list_store->columns_dirty == 0);
360
361   gtk_list_store_set_n_columns (list_store, n_columns);
362    for (i = 0; i < n_columns; i++)
363     {
364       if (! _gtk_tree_data_list_check_type (types[i]))
365         {
366           g_warning ("%s: Invalid type %s passed to gtk_list_store_set_column_types\n", G_STRLOC, g_type_name (types[i]));
367           continue;
368         }
369       gtk_list_store_set_column_type (list_store, i, types[i]);
370     }
371 }
372
373 static void
374 gtk_list_store_set_n_columns (GtkListStore *list_store,
375                               gint          n_columns)
376 {
377   GType *new_columns;
378
379   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
380   g_return_if_fail (n_columns > 0);
381
382   if (list_store->n_columns == n_columns)
383     return;
384
385   new_columns = g_new0 (GType, n_columns);
386   if (list_store->column_headers)
387     {
388       /* copy the old header orders over */
389       if (n_columns >= list_store->n_columns)
390         memcpy (new_columns, list_store->column_headers, list_store->n_columns * sizeof (gchar *));
391       else
392         memcpy (new_columns, list_store->column_headers, n_columns * sizeof (GType));
393
394       g_free (list_store->column_headers);
395     }
396
397   if (list_store->sort_list)
398     _gtk_tree_data_list_header_free (list_store->sort_list);
399
400   list_store->sort_list = _gtk_tree_data_list_header_new (n_columns, list_store->column_headers);
401
402   list_store->column_headers = new_columns;
403   list_store->n_columns = n_columns;
404 }
405
406 static void
407 gtk_list_store_set_column_type (GtkListStore *list_store,
408                                 gint          column,
409                                 GType         type)
410 {
411   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
412   g_return_if_fail (column >=0 && column < list_store->n_columns);
413   if (!_gtk_tree_data_list_check_type (type))
414     {
415       g_warning ("%s: Invalid type %s passed to gtk_list_store_set_column_type\n", G_STRLOC, g_type_name (type));
416       return;
417     }
418
419   list_store->column_headers[column] = type;
420 }
421
422 static void
423 gtk_list_store_finalize (GObject *object)
424 {
425   GtkListStore *list_store = GTK_LIST_STORE (object);
426
427   g_list_foreach (list_store->root, (GFunc) _gtk_tree_data_list_free, list_store->column_headers);
428   _gtk_tree_data_list_header_free (list_store->sort_list);
429   g_free (list_store->column_headers);
430   
431   if (list_store->default_sort_destroy)
432     {
433       GtkDestroyNotify d = list_store->default_sort_destroy;
434
435       list_store->default_sort_destroy = NULL;
436       d (list_store->default_sort_data);
437       list_store->default_sort_data = NULL;
438     }
439
440   (* parent_class->finalize) (object);
441 }
442
443 /* Fulfill the GtkTreeModel requirements */
444 static guint
445 gtk_list_store_get_flags (GtkTreeModel *tree_model)
446 {
447   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), 0);
448
449   return GTK_TREE_MODEL_ITERS_PERSIST | GTK_TREE_MODEL_LIST_ONLY;
450 }
451
452 static gint
453 gtk_list_store_get_n_columns (GtkTreeModel *tree_model)
454 {
455   GtkListStore *list_store = (GtkListStore *) tree_model;
456
457   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), 0);
458
459   list_store->columns_dirty = TRUE;
460
461   return list_store->n_columns;
462 }
463
464 static GType
465 gtk_list_store_get_column_type (GtkTreeModel *tree_model,
466                                 gint          index)
467 {
468   GtkListStore *list_store = (GtkListStore *) tree_model;
469
470   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), G_TYPE_INVALID);
471   g_return_val_if_fail (index < GTK_LIST_STORE (tree_model)->n_columns &&
472                         index >= 0, G_TYPE_INVALID);
473
474   list_store->columns_dirty = TRUE;
475
476   return list_store->column_headers[index];
477 }
478
479 static gboolean
480 gtk_list_store_get_iter (GtkTreeModel *tree_model,
481                          GtkTreeIter  *iter,
482                          GtkTreePath  *path)
483 {
484   GtkListStore *list_store = (GtkListStore *) tree_model;
485   GSList *list;
486   gint i;
487
488   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
489   g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
490
491   list_store->columns_dirty = TRUE;
492
493   i = gtk_tree_path_get_indices (path)[0];
494
495   if (i >= list_store->length)
496     return FALSE;
497
498   list = g_slist_nth (G_SLIST (list_store->root), i);
499
500   /* If this fails, list_store->length has gotten mangled. */
501   g_assert (list);
502
503   iter->stamp = list_store->stamp;
504   iter->user_data = list;
505
506   return TRUE;
507 }
508
509 static GtkTreePath *
510 gtk_list_store_get_path (GtkTreeModel *tree_model,
511                          GtkTreeIter  *iter)
512 {
513   GtkTreePath *retval;
514   GSList *list;
515   gint i = 0;
516
517   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), NULL);
518   g_return_val_if_fail (iter->stamp == GTK_LIST_STORE (tree_model)->stamp, NULL);
519   if (G_SLIST (iter->user_data) == G_SLIST (GTK_LIST_STORE (tree_model)->tail))
520     {
521       retval = gtk_tree_path_new ();
522       gtk_tree_path_append_index (retval, GTK_LIST_STORE (tree_model)->length - 1);
523       return retval;
524     }
525
526   for (list = G_SLIST (GTK_LIST_STORE (tree_model)->root); list; list = list->next)
527     {
528       if (list == G_SLIST (iter->user_data))
529         break;
530       i++;
531     }
532   if (list == NULL)
533     return NULL;
534
535   retval = gtk_tree_path_new ();
536   gtk_tree_path_append_index (retval, i);
537   return retval;
538 }
539
540 static void
541 gtk_list_store_get_value (GtkTreeModel *tree_model,
542                           GtkTreeIter  *iter,
543                           gint          column,
544                           GValue       *value)
545 {
546   GtkTreeDataList *list;
547   gint tmp_column = column;
548
549   g_return_if_fail (GTK_IS_LIST_STORE (tree_model));
550   g_return_if_fail (column < GTK_LIST_STORE (tree_model)->n_columns);
551   g_return_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp);
552
553   list = G_SLIST (iter->user_data)->data;
554
555   while (tmp_column-- > 0 && list)
556     list = list->next;
557
558   if (list == NULL)
559     g_value_init (value, GTK_LIST_STORE (tree_model)->column_headers[column]);
560   else
561     _gtk_tree_data_list_node_to_value (list,
562                                        GTK_LIST_STORE (tree_model)->column_headers[column],
563                                        value);
564 }
565
566 static gboolean
567 gtk_list_store_iter_next (GtkTreeModel  *tree_model,
568                           GtkTreeIter   *iter)
569 {
570   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
571   g_return_val_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp, FALSE);
572
573   iter->user_data = G_SLIST (iter->user_data)->next;
574
575   return (iter->user_data != NULL);
576 }
577
578 static gboolean
579 gtk_list_store_iter_children (GtkTreeModel *tree_model,
580                               GtkTreeIter  *iter,
581                               GtkTreeIter  *parent)
582 {
583   /* this is a list, nodes have no children */
584   if (parent)
585     return FALSE;
586
587   /* but if parent == NULL we return the list itself as children of the
588    * "root"
589    */
590
591   if (GTK_LIST_STORE (tree_model)->root)
592     {
593       iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
594       iter->user_data = GTK_LIST_STORE (tree_model)->root;
595       return TRUE;
596     }
597   else
598     return FALSE;
599 }
600
601 static gboolean
602 gtk_list_store_iter_has_child (GtkTreeModel *tree_model,
603                                GtkTreeIter  *iter)
604 {
605   return FALSE;
606 }
607
608 static gint
609 gtk_list_store_iter_n_children (GtkTreeModel *tree_model,
610                                 GtkTreeIter  *iter)
611 {
612   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), -1);
613   if (iter == NULL)
614     return GTK_LIST_STORE (tree_model)->length;
615
616   g_return_val_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp, -1);
617   return 0;
618 }
619
620 static gboolean
621 gtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
622                                GtkTreeIter  *iter,
623                                GtkTreeIter  *parent,
624                                gint          n)
625 {
626   GSList *child;
627
628   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
629
630   if (parent)
631     return FALSE;
632
633   child = g_slist_nth (G_SLIST (GTK_LIST_STORE (tree_model)->root), n);
634
635   if (child)
636     {
637       iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
638       iter->user_data = child;
639       return TRUE;
640     }
641   else
642     return FALSE;
643 }
644
645 static gboolean
646 gtk_list_store_iter_parent (GtkTreeModel *tree_model,
647                             GtkTreeIter  *iter,
648                             GtkTreeIter  *child)
649 {
650   return FALSE;
651 }
652
653 static gboolean
654 gtk_list_store_real_set_value (GtkListStore *list_store,
655                                GtkTreeIter  *iter,
656                                gint          column,
657                                GValue       *value,
658                                gboolean      sort)
659 {
660   GtkTreeDataList *list;
661   GtkTreeDataList *prev;
662   gint old_column = column;
663   GValue real_value = {0, };
664   gboolean converted = FALSE;
665   gboolean retval = FALSE;
666
667   g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), FALSE);
668   g_return_val_if_fail (VALID_ITER (iter, list_store), FALSE);
669   g_return_val_if_fail (column >= 0 && column < list_store->n_columns, FALSE);
670   g_return_val_if_fail (G_IS_VALUE (value), FALSE);
671
672   if (! g_type_is_a (G_VALUE_TYPE (value), list_store->column_headers[column]))
673     {
674       if (! (g_value_type_compatible (G_VALUE_TYPE (value), list_store->column_headers[column]) &&
675              g_value_type_compatible (list_store->column_headers[column], G_VALUE_TYPE (value))))
676         {
677           g_warning ("%s: Unable to convert from %s to %s\n",
678                      G_STRLOC,
679                      g_type_name (G_VALUE_TYPE (value)),
680                      g_type_name (list_store->column_headers[column]));
681           return retval;
682         }
683       if (!g_value_transform (value, &real_value))
684         {
685           g_warning ("%s: Unable to make conversion from %s to %s\n",
686                      G_STRLOC,
687                      g_type_name (G_VALUE_TYPE (value)),
688                      g_type_name (list_store->column_headers[column]));
689           g_value_unset (&real_value);
690           return retval;
691         }
692       converted = TRUE;
693     }
694
695   prev = list = G_SLIST (iter->user_data)->data;
696
697   while (list != NULL)
698     {
699       if (column == 0)
700         {
701           if (converted)
702             _gtk_tree_data_list_value_to_node (list, &real_value);
703           else
704             _gtk_tree_data_list_value_to_node (list, value);
705           retval = TRUE;
706           if (converted)
707             g_value_unset (&real_value);
708           return retval;
709         }
710
711       column--;
712       prev = list;
713       list = list->next;
714     }
715
716   if (G_SLIST (iter->user_data)->data == NULL)
717     {
718       G_SLIST (iter->user_data)->data = list = _gtk_tree_data_list_alloc ();
719       list->next = NULL;
720     }
721   else
722     {
723       list = prev->next = _gtk_tree_data_list_alloc ();
724       list->next = NULL;
725     }
726
727   while (column != 0)
728     {
729       list->next = _gtk_tree_data_list_alloc ();
730       list = list->next;
731       list->next = NULL;
732       column --;
733     }
734
735   if (converted)
736     _gtk_tree_data_list_value_to_node (list, &real_value);
737   else
738     _gtk_tree_data_list_value_to_node (list, value);
739
740   retval = TRUE;
741   if (converted)
742     g_value_unset (&real_value);
743
744   if (sort && GTK_LIST_STORE_IS_SORTED (list_store))
745     gtk_list_store_sort_iter_changed (list_store, iter, old_column);
746
747   return retval;
748 }
749
750
751 /**
752  * gtk_list_store_set_value:
753  * @list_store: A #GtkListStore
754  * @iter: A valid #GtkTreeIter for the row being modified
755  * @column: column number to modify
756  * @value: new value for the cell
757  *
758  * Sets the data in the cell specified by @iter and @column.
759  * The type of @value must be convertible to the type of the
760  * column.
761  *
762  **/
763 void
764 gtk_list_store_set_value (GtkListStore *list_store,
765                           GtkTreeIter  *iter,
766                           gint          column,
767                           GValue       *value)
768 {
769   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
770   g_return_if_fail (VALID_ITER (iter, list_store));
771   g_return_if_fail (column >= 0 && column < list_store->n_columns);
772   g_return_if_fail (G_IS_VALUE (value));
773
774   if (gtk_list_store_real_set_value (list_store, iter, column, value, TRUE))
775     {
776       GtkTreePath *path;
777
778       path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_store), iter);
779       gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
780       gtk_tree_path_free (path);
781     }
782 }
783
784 /**
785  * gtk_list_store_set_valist:
786  * @list_store: A #GtkListStore
787  * @iter: A valid #GtkTreeIter for the row being modified
788  * @var_args: va_list of column/value pairs
789  *
790  * See gtk_list_store_set(); this version takes a va_list for use by language
791  * bindings.
792  *
793  **/
794 void
795 gtk_list_store_set_valist (GtkListStore *list_store,
796                            GtkTreeIter  *iter,
797                            va_list       var_args)
798 {
799   gint column;
800   gboolean emit_signal = FALSE;
801   gboolean maybe_need_sort = FALSE;
802   GtkTreeIterCompareFunc func = NULL;
803
804   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
805   g_return_if_fail (VALID_ITER (iter, list_store));
806
807   column = va_arg (var_args, gint);
808
809   if (GTK_LIST_STORE_IS_SORTED (list_store))
810     {
811       if (list_store->sort_column_id != -1)
812         {
813           GtkTreeDataSortHeader *header;
814           header = _gtk_tree_data_list_get_header (list_store->sort_list,
815                                                    list_store->sort_column_id);
816           g_return_if_fail (header != NULL);
817           g_return_if_fail (header->func != NULL);
818           func = header->func;
819         }
820       else
821         {
822           func = list_store->default_sort_func;
823         }
824     }
825
826   if (func != gtk_tree_data_list_compare_func)
827     maybe_need_sort = TRUE;
828
829   while (column != -1)
830     {
831       GValue value = { 0, };
832       gchar *error = NULL;
833
834       if (column >= list_store->n_columns)
835         {
836           g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column);
837           break;
838         }
839       g_value_init (&value, list_store->column_headers[column]);
840
841       G_VALUE_COLLECT (&value, var_args, 0, &error);
842       if (error)
843         {
844           g_warning ("%s: %s", G_STRLOC, error);
845           g_free (error);
846
847           /* we purposely leak the value here, it might not be
848            * in a sane state if an error condition occoured
849            */
850           break;
851         }
852
853       /* FIXME: instead of calling this n times, refactor with above */
854       emit_signal = gtk_list_store_real_set_value (list_store,
855                                                    iter,
856                                                    column,
857                                                    &value,
858                                                    FALSE) || emit_signal;
859
860       if (func == gtk_tree_data_list_compare_func &&
861           column == list_store->sort_column_id)
862         maybe_need_sort = TRUE;
863
864       g_value_unset (&value);
865
866       column = va_arg (var_args, gint);
867     }
868
869   if (maybe_need_sort && GTK_LIST_STORE_IS_SORTED (list_store))
870     gtk_list_store_sort_iter_changed (list_store, iter, list_store->sort_column_id);
871
872   if (emit_signal)
873     {
874       GtkTreePath *path;
875
876       path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_store), iter);
877       gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
878       gtk_tree_path_free (path);
879     }
880 }
881
882 /**
883  * gtk_list_store_set:
884  * @list_store: a #GtkListStore
885  * @iter: row iterator
886  * @Varargs: pairs of column number and value, terminated with -1
887  *
888  * Sets the value of one or more cells in the row referenced by @iter.
889  * The variable argument list should contain integer column numbers,
890  * each column number followed by the value to be set.
891  * The list is terminated by a -1. For example, to set column 0 with type
892  * %G_TYPE_STRING to "Foo", you would write <literal>gtk_list_store_set (store, iter,
893  * 0, "Foo", -1)</literal>.
894  **/
895 void
896 gtk_list_store_set (GtkListStore *list_store,
897                     GtkTreeIter  *iter,
898                     ...)
899 {
900   va_list var_args;
901
902   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
903   g_return_if_fail (iter != NULL);
904   g_return_if_fail (iter->stamp == list_store->stamp);
905
906   va_start (var_args, iter);
907   gtk_list_store_set_valist (list_store, iter, var_args);
908   va_end (var_args);
909 }
910
911 static GSList*
912 remove_link_saving_prev (GSList  *list,
913                          GSList  *link,
914                          GSList **prevp)
915 {
916   GSList *tmp;
917   GSList *prev;
918
919   prev = NULL;
920   tmp = list;
921
922   while (tmp)
923     {
924       if (tmp == link)
925         {
926           if (prev)
927             prev->next = link->next;
928
929           if (list == link)
930             list = list->next;
931
932           link->next = NULL;
933           break;
934         }
935
936       prev = tmp;
937       tmp = tmp->next;
938     }
939
940   *prevp = prev;
941
942   return list;
943 }
944
945 static void
946 gtk_list_store_remove_silently (GtkListStore *list_store,
947                                 GtkTreeIter  *iter,
948                                 GtkTreePath  *path)
949 {
950   if (G_SLIST (iter->user_data)->data)
951     {
952       _gtk_tree_data_list_free ((GtkTreeDataList *) G_SLIST (iter->user_data)->data,
953                                 list_store->column_headers);
954       G_SLIST (iter->user_data)->data = NULL;
955     }
956
957   {
958     GSList *prev = NULL;
959
960     list_store->root = remove_link_saving_prev (G_SLIST (list_store->root),
961                                                 G_SLIST (iter->user_data),
962                                                 &prev);
963
964     list_store->length -= 1;
965
966     if (iter->user_data == list_store->tail)
967       list_store->tail = prev;
968   }
969 }
970
971 /**
972  * gtk_list_store_remove:
973  * @list_store: A #GtkListStore
974  * @iter: A valid #GtkTreeIter
975  *
976  * Removes the given row from the list store.  After being removed, 
977  * @iter is set to be the next valid row, or invalidated if it pointed 
978  * to the last row in @list_store.
979  *
980  * Return value: %TRUE if @iter is valid, %FALSE if not.
981  **/
982 gboolean
983 gtk_list_store_remove (GtkListStore *list_store,
984                        GtkTreeIter  *iter)
985 {
986   GtkTreePath *path;
987   GSList *next;
988
989   g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), FALSE);
990   g_return_val_if_fail (VALID_ITER (iter, list_store), FALSE);
991
992   next = G_SLIST (iter->user_data)->next;
993   path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
994
995   validate_list_store (list_store);
996
997   gtk_list_store_remove_silently (list_store, iter, path);
998
999   validate_list_store (list_store);
1000
1001   gtk_tree_model_row_deleted (GTK_TREE_MODEL (list_store), path);
1002   gtk_tree_path_free (path);
1003
1004   if (next)
1005     {
1006       iter->stamp = list_store->stamp;
1007       iter->user_data = next;
1008       return TRUE;
1009     }
1010   else
1011     {
1012       iter->stamp = 0;
1013     }
1014
1015   return FALSE;
1016 }
1017
1018 static void
1019 insert_after (GtkListStore *list_store,
1020               GSList       *sibling,
1021               GSList       *new_list)
1022 {
1023   g_return_if_fail (sibling != NULL);
1024   g_return_if_fail (new_list != NULL);
1025
1026   /* insert new node after list */
1027   new_list->next = sibling->next;
1028   sibling->next = new_list;
1029
1030   /* if list was the tail, the new node is the new tail */
1031   if (sibling == ((GSList *) list_store->tail))
1032     list_store->tail = new_list;
1033
1034   list_store->length += 1;
1035 }
1036
1037 /**
1038  * gtk_list_store_insert:
1039  * @list_store: A #GtkListStore
1040  * @iter: An unset #GtkTreeIter to set to the new row
1041  * @position: position to insert the new row
1042  *
1043  * Creates a new row at @position.  @iter will be changed to point to this new
1044  * row.  If @position is larger than the number of rows on the list, then the
1045  * new row will be appended to the list.  The row will be empty before this
1046  * function is called.  To fill in values, you need to call gtk_list_store_set()
1047  * or gtk_list_store_set_value().
1048  *
1049  **/
1050 void
1051 gtk_list_store_insert (GtkListStore *list_store,
1052                        GtkTreeIter  *iter,
1053                        gint          position)
1054 {
1055   GSList *list;
1056   GtkTreePath *path;
1057   GSList *new_list;
1058
1059   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1060   g_return_if_fail (iter != NULL);
1061   g_return_if_fail (position >= 0);
1062
1063   list_store->columns_dirty = TRUE;
1064
1065   if (position == 0 ||
1066       GTK_LIST_STORE_IS_SORTED (list_store))
1067     {
1068       gtk_list_store_prepend (list_store, iter);
1069       return;
1070     }
1071
1072   new_list = g_slist_alloc ();
1073
1074   list = g_slist_nth (G_SLIST (list_store->root), position - 1);
1075
1076   if (list == NULL)
1077     {
1078       /* position if off the end of the list, append it */
1079       gtk_list_store_append (list_store, iter);
1080
1081       return;
1082     }
1083
1084   insert_after (list_store, list, new_list);
1085
1086   iter->stamp = list_store->stamp;
1087   iter->user_data = new_list;
1088
1089   validate_list_store (list_store);
1090
1091   path = gtk_tree_path_new ();
1092   gtk_tree_path_append_index (path, position);
1093   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1094   gtk_tree_path_free (path);
1095 }
1096
1097 /**
1098  * gtk_list_store_insert_before:
1099  * @list_store: A #GtkListStore
1100  * @iter: An unset #GtkTreeIter to set to the new row
1101  * @sibling: A valid #GtkTreeIter, or %NULL
1102  *
1103  * Inserts a new row before @sibling. If @sibling is %NULL, then the row will be
1104  * appended to the end of the list. @iter will be changed to point to this new 
1105  * row. The row will be empty before this function is called. To fill in values,
1106  * you need to call gtk_list_store_set() or gtk_list_store_set_value().
1107  *
1108  **/
1109 void
1110 gtk_list_store_insert_before (GtkListStore *list_store,
1111                               GtkTreeIter  *iter,
1112                               GtkTreeIter  *sibling)
1113 {
1114   GtkTreePath *path;
1115   GSList *list, *prev, *new_list;
1116   gint i = 0;
1117
1118   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1119   g_return_if_fail (iter != NULL);
1120   if (sibling)
1121     g_return_if_fail (VALID_ITER (sibling, list_store));
1122
1123   list_store->columns_dirty = TRUE;
1124
1125   if (GTK_LIST_STORE_IS_SORTED (list_store))
1126     {
1127       gtk_list_store_prepend (list_store, iter);
1128       return;
1129     }
1130
1131   if (sibling == NULL)
1132     {
1133       gtk_list_store_append (list_store, iter);
1134       return;
1135     }
1136
1137   new_list = g_slist_alloc ();
1138
1139   prev = NULL;
1140   list = list_store->root;
1141   while (list && list != sibling->user_data)
1142     {
1143       prev = list;
1144       list = list->next;
1145       i++;
1146     }
1147
1148   if (list != sibling->user_data)
1149     {
1150       g_warning ("%s: sibling iterator invalid? not found in the list", G_STRLOC);
1151       return;
1152     }
1153
1154   /* if there are no nodes, we become the list tail, otherwise we
1155    * are inserting before any existing nodes so we can't change
1156    * the tail
1157    */
1158
1159   if (list_store->root == NULL)
1160     list_store->tail = new_list;
1161
1162   if (prev)
1163     {
1164       new_list->next = prev->next;
1165       prev->next = new_list;
1166     }
1167   else
1168     {
1169       new_list->next = list_store->root;
1170       list_store->root = new_list;
1171     }
1172
1173   iter->stamp = list_store->stamp;
1174   iter->user_data = new_list;
1175
1176   list_store->length += 1;
1177
1178   validate_list_store (list_store);
1179
1180   path = gtk_tree_path_new ();
1181   gtk_tree_path_append_index (path, i);
1182   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1183   gtk_tree_path_free (path);
1184 }
1185
1186 /**
1187  * gtk_list_store_insert_after:
1188  * @list_store: A #GtkListStore
1189  * @iter: An unset #GtkTreeIter to set to the new row
1190  * @sibling: A valid #GtkTreeIter, or %NULL
1191  *
1192  * Inserts a new row after @sibling. If @sibling is %NULL, then the row will be
1193  * prepended to the beginning of the list. @iter will be changed to point to
1194  * this new row. The row will be empty after this function is called. To fill
1195  * in values, you need to call gtk_list_store_set() or gtk_list_store_set_value().
1196  *
1197  **/
1198 void
1199 gtk_list_store_insert_after (GtkListStore *list_store,
1200                              GtkTreeIter  *iter,
1201                              GtkTreeIter  *sibling)
1202 {
1203   GtkTreePath *path;
1204   GSList *list, *new_list;
1205   gint i = 0;
1206
1207   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1208   g_return_if_fail (iter != NULL);
1209   if (sibling)
1210     g_return_if_fail (VALID_ITER (sibling, list_store));
1211
1212   list_store->columns_dirty = TRUE;
1213
1214   if (sibling == NULL ||
1215       GTK_LIST_STORE_IS_SORTED (list_store))
1216     {
1217       gtk_list_store_prepend (list_store, iter);
1218       return;
1219     }
1220
1221   for (list = list_store->root; list && list != sibling->user_data; list = list->next)
1222     i++;
1223
1224   g_return_if_fail (list == sibling->user_data);
1225
1226   new_list = g_slist_alloc ();
1227
1228   insert_after (list_store, list, new_list);
1229
1230   iter->stamp = list_store->stamp;
1231   iter->user_data = new_list;
1232
1233   validate_list_store (list_store);
1234
1235   path = gtk_tree_path_new ();
1236   gtk_tree_path_append_index (path, i + 1);
1237   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1238   gtk_tree_path_free (path);
1239 }
1240
1241 /**
1242  * gtk_list_store_prepend:
1243  * @list_store: A #GtkListStore
1244  * @iter: An unset #GtkTreeIter to set to the prepend row
1245  *
1246  * Prepends a new row to @list_store. @iter will be changed to point to this new
1247  * row. The row will be empty after this function is called. To fill in
1248  * values, you need to call gtk_list_store_set() or gtk_list_store_set_value().
1249  *
1250  **/
1251 void
1252 gtk_list_store_prepend (GtkListStore *list_store,
1253                         GtkTreeIter  *iter)
1254 {
1255   GtkTreePath *path;
1256
1257   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1258   g_return_if_fail (iter != NULL);
1259
1260   iter->stamp = list_store->stamp;
1261   iter->user_data = g_slist_alloc ();
1262
1263   list_store->columns_dirty = TRUE;
1264
1265   if (list_store->root == NULL)
1266     list_store->tail = iter->user_data;
1267
1268   G_SLIST (iter->user_data)->next = G_SLIST (list_store->root);
1269   list_store->root = iter->user_data;
1270
1271   list_store->length += 1;
1272
1273   validate_list_store (list_store);
1274
1275   path = gtk_tree_path_new ();
1276   gtk_tree_path_append_index (path, 0);
1277   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1278   gtk_tree_path_free (path);
1279 }
1280
1281 /**
1282  * gtk_list_store_append:
1283  * @list_store: A #GtkListStore
1284  * @iter: An unset #GtkTreeIter to set to the appended row
1285  *
1286  * Appends a new row to @list_store.  @iter will be changed to point to this new
1287  * row.  The row will be empty after this function is called.  To fill in
1288  * values, you need to call gtk_list_store_set() or gtk_list_store_set_value().
1289  *
1290  **/
1291 void
1292 gtk_list_store_append (GtkListStore *list_store,
1293                        GtkTreeIter  *iter)
1294 {
1295   GtkTreePath *path;
1296
1297   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1298   g_return_if_fail (iter != NULL);
1299
1300   list_store->columns_dirty = TRUE;
1301
1302   if (GTK_LIST_STORE_IS_SORTED (list_store))
1303     {
1304       gtk_list_store_prepend (list_store, iter);
1305       return;
1306     }
1307
1308   iter->stamp = list_store->stamp;
1309   iter->user_data = g_slist_alloc ();
1310
1311   if (list_store->tail)
1312     ((GSList *)list_store->tail)->next = iter->user_data;
1313   else
1314     list_store->root = iter->user_data;
1315
1316   list_store->tail = iter->user_data;
1317
1318   list_store->length += 1;
1319
1320   validate_list_store (list_store);
1321
1322   path = gtk_tree_path_new ();
1323   gtk_tree_path_append_index (path, list_store->length - 1);
1324   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1325   gtk_tree_path_free (path);
1326 }
1327
1328 /**
1329  * gtk_list_store_clear:
1330  * @list_store: a #GtkListStore.
1331  *
1332  * Removes all rows from the list store.  
1333  *
1334  **/
1335 void
1336 gtk_list_store_clear (GtkListStore *list_store)
1337 {
1338   GtkTreeIter iter;
1339   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1340
1341   while (list_store->root)
1342     {
1343       iter.stamp = list_store->stamp;
1344       iter.user_data = list_store->root;
1345       gtk_list_store_remove (list_store, &iter);
1346     }
1347 }
1348
1349 /**
1350  * gtk_list_store_iter_is_valid:
1351  * @list_store: A #GtkListStore.
1352  * @iter: A #GtkTreeIter.
1353  *
1354  * WARNING: This function is slow. Only use it for debugging and/or testing
1355  * purposes.
1356  *
1357  * Checks if the given iter is a valid iter for this #GtkListStore.
1358  *
1359  * Return value: %TRUE if the iter is valid, %FALSE if the iter is invalid.
1360  **/
1361 gboolean
1362 gtk_list_store_iter_is_valid (GtkListStore *list_store,
1363                               GtkTreeIter  *iter)
1364 {
1365   GList *list;
1366
1367   g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), FALSE);
1368   g_return_val_if_fail (iter != NULL, FALSE);
1369
1370   if (!VALID_ITER (iter, list_store))
1371     return FALSE;
1372
1373   if (iter->user_data == list_store->root)
1374     return TRUE;
1375   if (iter->user_data == list_store->tail)
1376     return TRUE;
1377
1378   for (list = ((GList *)list_store->root)->next; list; list = list->next)
1379     if (list == iter->user_data)
1380       return TRUE;
1381
1382   return FALSE;
1383 }
1384
1385 static gboolean
1386 gtk_list_store_drag_data_delete (GtkTreeDragSource *drag_source,
1387                                  GtkTreePath       *path)
1388 {
1389   GtkTreeIter iter;
1390   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE);
1391
1392   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source),
1393                                &iter,
1394                                path))
1395     {
1396       gtk_list_store_remove (GTK_LIST_STORE (drag_source), &iter);
1397       return TRUE;
1398     }
1399   return FALSE;
1400 }
1401
1402 static gboolean
1403 gtk_list_store_drag_data_get (GtkTreeDragSource *drag_source,
1404                               GtkTreePath       *path,
1405                               GtkSelectionData  *selection_data)
1406 {
1407   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE);
1408
1409   /* Note that we don't need to handle the GTK_TREE_MODEL_ROW
1410    * target, because the default handler does it for us, but
1411    * we do anyway for the convenience of someone maybe overriding the
1412    * default handler.
1413    */
1414
1415   if (gtk_tree_set_row_drag_data (selection_data,
1416                                   GTK_TREE_MODEL (drag_source),
1417                                   path))
1418     {
1419       return TRUE;
1420     }
1421   else
1422     {
1423       /* FIXME handle text targets at least. */
1424     }
1425
1426   return FALSE;
1427 }
1428
1429 static gboolean
1430 gtk_list_store_drag_data_received (GtkTreeDragDest   *drag_dest,
1431                                    GtkTreePath       *dest,
1432                                    GtkSelectionData  *selection_data)
1433 {
1434   GtkTreeModel *tree_model;
1435   GtkListStore *list_store;
1436   GtkTreeModel *src_model = NULL;
1437   GtkTreePath *src_path = NULL;
1438   gboolean retval = FALSE;
1439
1440   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE);
1441
1442   tree_model = GTK_TREE_MODEL (drag_dest);
1443   list_store = GTK_LIST_STORE (drag_dest);
1444
1445   if (gtk_tree_get_row_drag_data (selection_data,
1446                                   &src_model,
1447                                   &src_path) &&
1448       src_model == tree_model)
1449     {
1450       /* Copy the given row to a new position */
1451       GtkTreeIter src_iter;
1452       GtkTreeIter dest_iter;
1453       GtkTreePath *prev;
1454
1455       if (!gtk_tree_model_get_iter (src_model,
1456                                     &src_iter,
1457                                     src_path))
1458         {
1459           goto out;
1460         }
1461
1462       /* Get the path to insert _after_ (dest is the path to insert _before_) */
1463       prev = gtk_tree_path_copy (dest);
1464
1465       if (!gtk_tree_path_prev (prev))
1466         {
1467           /* dest was the first spot in the list; which means we are supposed
1468            * to prepend.
1469            */
1470           gtk_list_store_prepend (GTK_LIST_STORE (tree_model),
1471                                   &dest_iter);
1472
1473           retval = TRUE;
1474         }
1475       else
1476         {
1477           if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model),
1478                                        &dest_iter,
1479                                        prev))
1480             {
1481               GtkTreeIter tmp_iter = dest_iter;
1482
1483               if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tree_model), "gtk-tree-model-drop-append")))
1484                 gtk_list_store_append (GTK_LIST_STORE (tree_model), &dest_iter);
1485               else
1486                 gtk_list_store_insert_after (GTK_LIST_STORE (tree_model),
1487                                              &dest_iter, &tmp_iter);
1488
1489               retval = TRUE;
1490             }
1491         }
1492
1493       g_object_set_data (G_OBJECT (tree_model), "gtk-tree-model-drop-append",
1494                          NULL);
1495
1496       gtk_tree_path_free (prev);
1497
1498       /* If we succeeded in creating dest_iter, copy data from src
1499        */
1500       if (retval)
1501         {
1502           GtkTreeDataList *dl = G_SLIST (src_iter.user_data)->data;
1503           GtkTreeDataList *copy_head = NULL;
1504           GtkTreeDataList *copy_prev = NULL;
1505           GtkTreeDataList *copy_iter = NULL;
1506           GtkTreePath *path;
1507           gint col;
1508
1509           col = 0;
1510           while (dl)
1511             {
1512               copy_iter = _gtk_tree_data_list_node_copy (dl,
1513                                                          list_store->column_headers[col]);
1514
1515               if (copy_head == NULL)
1516                 copy_head = copy_iter;
1517
1518               if (copy_prev)
1519                 copy_prev->next = copy_iter;
1520
1521               copy_prev = copy_iter;
1522
1523               dl = dl->next;
1524               ++col;
1525             }
1526
1527           dest_iter.stamp = GTK_LIST_STORE (tree_model)->stamp;
1528           G_SLIST (dest_iter.user_data)->data = copy_head;
1529
1530           path = gtk_list_store_get_path (GTK_TREE_MODEL (tree_model), &dest_iter);
1531           gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_model), path, &dest_iter);
1532           gtk_tree_path_free (path);
1533         }
1534     }
1535   else
1536     {
1537       /* FIXME maybe add some data targets eventually, or handle text
1538        * targets in the simple case.
1539        */
1540     }
1541
1542  out:
1543
1544   if (src_path)
1545     gtk_tree_path_free (src_path);
1546
1547   return retval;
1548 }
1549
1550 static gboolean
1551 gtk_list_store_row_drop_possible (GtkTreeDragDest  *drag_dest,
1552                                   GtkTreePath      *dest_path,
1553                                   GtkSelectionData *selection_data)
1554 {
1555   gint *indices;
1556   GtkTreeModel *src_model = NULL;
1557   GtkTreePath *src_path = NULL;
1558   gboolean retval = FALSE;
1559
1560   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE);
1561
1562   if (!gtk_tree_get_row_drag_data (selection_data,
1563                                    &src_model,
1564                                    &src_path))
1565     goto out;
1566     
1567   if (src_model != GTK_TREE_MODEL (drag_dest))
1568     goto out;
1569
1570   if (gtk_tree_path_get_depth (dest_path) != 1)
1571     goto out;
1572
1573   /* can drop before any existing node, or before one past any existing. */
1574
1575   indices = gtk_tree_path_get_indices (dest_path);
1576
1577   if (indices[0] <= GTK_LIST_STORE (drag_dest)->length)
1578     retval = TRUE;
1579
1580  out:
1581   gtk_tree_path_free (src_path);
1582   
1583   return retval;
1584 }
1585
1586 /* Sorting and reordering */
1587 typedef struct _SortTuple
1588 {
1589   gint offset;
1590   GSList *el;
1591 } SortTuple;
1592
1593 /* Reordering */
1594 static gint
1595 gtk_list_store_reorder_func (gconstpointer a,
1596                              gconstpointer b,
1597                              gpointer      user_data)
1598 {
1599   SortTuple *a_reorder;
1600   SortTuple *b_reorder;
1601
1602   a_reorder = (SortTuple *)a;
1603   b_reorder = (SortTuple *)b;
1604
1605   if (a_reorder->offset < b_reorder->offset)
1606     return -1;
1607   if (a_reorder->offset > b_reorder->offset)
1608     return 1;
1609
1610   return 0;
1611 }
1612
1613 /**
1614  * gtk_list_store_reorder:
1615  * @store: A #GtkTreeStore.
1616  * @new_order: An integer array indicating the new order for the list.
1617  *
1618  * Reorders @store to follow the order indicated by @new_order. Note that
1619  * this function only works with unsorted stores.
1620  **/
1621 void
1622 gtk_list_store_reorder (GtkListStore *store,
1623                         gint         *new_order)
1624 {
1625   gint i;
1626   GSList *current_list;
1627   GtkTreePath *path;
1628   SortTuple *sort_array;
1629
1630   g_return_if_fail (GTK_IS_LIST_STORE (store));
1631   g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1632   g_return_if_fail (new_order != NULL);
1633
1634   sort_array = g_new (SortTuple, store->length);
1635
1636   current_list = store->root;
1637
1638   for (i = 0; i < store->length; i++)
1639     {
1640       sort_array[i].offset = new_order[i];
1641       sort_array[i].el = current_list;
1642
1643       current_list = current_list->next;
1644     }
1645
1646   g_qsort_with_data (sort_array,
1647                      store->length,
1648                      sizeof (SortTuple),
1649                      gtk_list_store_reorder_func,
1650                      NULL);
1651
1652   for (i = 0; i < store->length - 1; i++)
1653     G_SLIST (sort_array[i].el)->next = G_SLIST (sort_array[i+1].el);
1654
1655   store->root = G_SLIST (sort_array[0].el);
1656   store->tail = G_SLIST (sort_array[store->length-1].el);
1657   G_SLIST (store->tail)->next = NULL;
1658
1659   /* emit signal */
1660   path = gtk_tree_path_new ();
1661   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store),
1662                                  path, NULL, new_order);
1663   gtk_tree_path_free (path);
1664   g_free (sort_array);
1665 }
1666
1667 /**
1668  * gtk_list_store_swap:
1669  * @store: A #GtkListStore.
1670  * @a: A #GtkTreeIter.
1671  * @b: Another #GtkTreeIter.
1672  *
1673  * Swaps @a and @b in @store. Note that this function only works with
1674  * unsorted stores.
1675  **/
1676 void
1677 gtk_list_store_swap (GtkListStore *store,
1678                      GtkTreeIter  *a,
1679                      GtkTreeIter  *b)
1680 {
1681   GSList *i, *prev_a = NULL, *prev_b = NULL;
1682   gint j, a_count = 0, b_count = 0, *order;
1683   GtkTreePath *path;
1684
1685   g_return_if_fail (GTK_IS_LIST_STORE (store));
1686   g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1687   g_return_if_fail (VALID_ITER (a, store));
1688   g_return_if_fail (VALID_ITER (b, store));
1689
1690   if (a->user_data == b->user_data)
1691     return;
1692
1693   if (a->user_data == store->root)
1694     prev_a = NULL;
1695   else
1696     {
1697       for (i = store->root; i; i = i->next, a_count++)
1698         if (i->next == a->user_data)
1699           {
1700             prev_a = i;
1701             break;
1702           }
1703
1704       a_count++;
1705     }
1706
1707   if (a->user_data == store->root)
1708     prev_b = NULL;
1709   else
1710     {
1711       for (i = store->root; i; i = i->next, b_count++)
1712         if (i->next == b->user_data)
1713           {
1714             prev_b = i;
1715             break;
1716           }
1717
1718       b_count++;
1719     }
1720
1721   if (!prev_a)
1722     store->root = b->user_data;
1723   else
1724     prev_a->next = b->user_data;
1725
1726   if (!prev_b)
1727     store->root = a->user_data;
1728   else
1729     prev_b->next = a->user_data;
1730
1731   /* think a_next inspead of a_prev here ... */
1732   prev_a = G_SLIST (a->user_data)->next;
1733   prev_b = G_SLIST (b->user_data)->next;
1734
1735   G_SLIST (a->user_data)->next = prev_b;
1736   G_SLIST (b->user_data)->next = prev_a;
1737
1738   /* emit signal */
1739   order = g_new (gint, store->length);
1740   for (j = 0; j < store->length; j++)
1741     if (j == a_count)
1742       order[j] = b_count;
1743     else if (j == b_count)
1744       order[j] = a_count;
1745     else
1746       order[j] = j;
1747
1748   path = gtk_tree_path_new ();
1749   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store),
1750                                  path, NULL, order);
1751   gtk_tree_path_free (path);
1752   g_free (order);
1753 }
1754
1755 /**
1756  * gtk_list_store_move:
1757  * @store: A #GtkTreeStore.
1758  * @iter: A #GtkTreeIter.
1759  * @position: A #GtkTreePath.
1760  *
1761  * Moves @iter in @store to the position before @position. Note that this
1762  * function only works with unsorted stores.
1763  **/
1764 void
1765 gtk_list_store_move (GtkListStore *store,
1766                      GtkTreeIter  *iter,
1767                      GtkTreePath  *position)
1768 {
1769   GSList *i, *prev = NULL, *new_prev = NULL;
1770   gint old_pos = 0, j = 0, *order;
1771   GtkTreePath *path;
1772
1773   g_return_if_fail (GTK_IS_LIST_STORE (store));
1774   g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1775   g_return_if_fail (VALID_ITER (iter, store));
1776   g_return_if_fail (position != NULL);
1777
1778   if (gtk_tree_path_get_depth (position) != 1)
1779     return;
1780
1781   if (iter->user_data == store->root)
1782     prev = NULL;
1783   else
1784     {
1785       for (i = store->root; i; i = i->next, old_pos++)
1786         if (i->next == iter->user_data)
1787           {
1788             prev = i;
1789             break;
1790           }
1791
1792       old_pos++;
1793     }
1794
1795   if (old_pos == gtk_tree_path_get_indices (position)[0])
1796     return;
1797
1798   if (gtk_tree_path_get_indices (position)[0] == 0)
1799     new_prev = NULL;
1800   else
1801     {
1802       for (i = store->root; i; i = i->next, j++)
1803         if (j == gtk_tree_path_get_indices (position)[0] - 1)
1804           {
1805             new_prev = i;
1806             break;
1807           }
1808     }
1809
1810   if (!prev)
1811     store->root = G_SLIST (iter->user_data)->next;
1812   else
1813     prev->next = G_SLIST (iter->user_data)->next;
1814
1815   if (!new_prev)
1816     {
1817       G_SLIST (iter->user_data)->next = store->root;
1818       store->root = G_SLIST (iter->user_data);
1819     }
1820   else
1821     {
1822       G_SLIST (iter->user_data)->next = new_prev->next;
1823       new_prev->next = G_SLIST (iter->user_data);
1824     }
1825
1826   /* emit signal */
1827   order = g_new (gint, store->length);
1828   for (j = 0; j < store->length; j++)
1829     if (j < old_pos)
1830       order[j] = j;
1831     else if (j >= old_pos && j < gtk_tree_path_get_indices (position)[0])
1832       order[j] = j + 1;
1833     else if (j == gtk_tree_path_get_indices (position)[0])
1834       order[j] = old_pos;
1835     else
1836       order[j] = j;
1837
1838   path = gtk_tree_path_new ();
1839   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store),
1840                                  path, NULL, order);
1841   gtk_tree_path_free (path);
1842   g_free (order);
1843 }
1844
1845 /* Sorting */
1846 static gint
1847 gtk_list_store_compare_func (gconstpointer a,
1848                              gconstpointer b,
1849                              gpointer      user_data)
1850 {
1851   GtkListStore *list_store = user_data;
1852   GSList *el_a; /* Los Angeles? */
1853   GSList *el_b;
1854   GtkTreeIter iter_a;
1855   GtkTreeIter iter_b;
1856   gint retval;
1857   GtkTreeIterCompareFunc func;
1858   gpointer data;
1859
1860
1861   if (list_store->sort_column_id != -1)
1862     {
1863       GtkTreeDataSortHeader *header;
1864
1865       header = _gtk_tree_data_list_get_header (list_store->sort_list,
1866                                                list_store->sort_column_id);
1867       g_return_val_if_fail (header != NULL, 0);
1868       g_return_val_if_fail (header->func != NULL, 0);
1869
1870       func = header->func;
1871       data = header->data;
1872     }
1873   else
1874     {
1875       g_return_val_if_fail (list_store->default_sort_func != NULL, 0);
1876       func = list_store->default_sort_func;
1877       data = list_store->default_sort_data;
1878     }
1879
1880   el_a = ((SortTuple *) a)->el;
1881   el_b = ((SortTuple *) b)->el;
1882
1883   iter_a.stamp = list_store->stamp;
1884   iter_a.user_data = el_a;
1885   iter_b.stamp = list_store->stamp;
1886   iter_b.user_data = el_b;
1887
1888   retval = (* func) (GTK_TREE_MODEL (list_store), &iter_a, &iter_b, data);
1889
1890   if (list_store->order == GTK_SORT_DESCENDING)
1891     {
1892       if (retval > 0)
1893         retval = -1;
1894       else if (retval < 0)
1895         retval = 1;
1896     }
1897   return retval;
1898 }
1899
1900 static void
1901 gtk_list_store_sort (GtkListStore *list_store)
1902 {
1903   GArray *sort_array;
1904   gint i;
1905   gint *new_order;
1906   GSList *list;
1907   GtkTreePath *path;
1908
1909   if (list_store->length <= 1)
1910     return;
1911
1912   g_assert (GTK_LIST_STORE_IS_SORTED (list_store));
1913
1914   list = G_SLIST (list_store->root);
1915
1916   sort_array = g_array_sized_new (FALSE, FALSE,
1917                                   sizeof (SortTuple),
1918                                   list_store->length);
1919
1920   for (i = 0; i < list_store->length; i++)
1921     {
1922       SortTuple tuple;
1923
1924       /* If this fails, we are in an inconsistent state.  Bad */
1925       g_return_if_fail (list != NULL);
1926
1927       tuple.offset = i;
1928       tuple.el = list;
1929       g_array_append_val (sort_array, tuple);
1930
1931       list = list->next;
1932     }
1933
1934   g_array_sort_with_data (sort_array, gtk_list_store_compare_func, list_store);
1935
1936   for (i = 0; i < list_store->length - 1; i++)
1937       g_array_index (sort_array, SortTuple, i).el->next =
1938         g_array_index (sort_array, SortTuple, i + 1).el;
1939   g_array_index (sort_array, SortTuple, list_store->length - 1).el->next = NULL;
1940   list_store->root = g_array_index (sort_array, SortTuple, 0).el;
1941   list_store->tail = g_array_index (sort_array, SortTuple, list_store->length - 1).el;
1942
1943   /* Let the world know about our new order */
1944   new_order = g_new (gint, list_store->length);
1945   for (i = 0; i < list_store->length; i++)
1946     new_order[i] = g_array_index (sort_array, SortTuple, i).offset;
1947
1948   path = gtk_tree_path_new ();
1949   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (list_store),
1950                                  path, NULL, new_order);
1951   gtk_tree_path_free (path);
1952   g_free (new_order);
1953   g_array_free (sort_array, TRUE);
1954 }
1955
1956 static void
1957 gtk_list_store_sort_iter_changed (GtkListStore *list_store,
1958                                   GtkTreeIter  *iter,
1959                                   gint          column)
1960
1961 {
1962   GSList *prev = NULL;
1963   GSList *next = NULL;
1964   GSList *list = G_SLIST (list_store->root);
1965   GtkTreePath *tmp_path;
1966   GtkTreeIter tmp_iter;
1967   gint cmp_a = 0;
1968   gint cmp_b = 0;
1969   gint i;
1970   gint old_location;
1971   gint new_location;
1972   gint *new_order;
1973   GtkTreeIterCompareFunc func;
1974   gpointer data;
1975
1976   if (list_store->length < 2)
1977     return;
1978
1979   tmp_iter.stamp = list_store->stamp;
1980
1981   if (list_store->sort_column_id != -1)
1982     {
1983       GtkTreeDataSortHeader *header;
1984       header = _gtk_tree_data_list_get_header (list_store->sort_list,
1985                                                list_store->sort_column_id);
1986       g_return_if_fail (header != NULL);
1987       g_return_if_fail (header->func != NULL);
1988       func = header->func;
1989       data = header->data;
1990     }
1991   else
1992     {
1993       g_return_if_fail (list_store->default_sort_func != NULL);
1994       func = list_store->default_sort_func;
1995       data = list_store->default_sort_data;
1996     }
1997
1998   /* If it's the built in function, we don't sort. */
1999   if (func == gtk_tree_data_list_compare_func &&
2000       list_store->sort_column_id != column)
2001     return;
2002
2003   old_location = 0;
2004   /* First we find the iter, its prev, and its next */
2005   while (list)
2006     {
2007       if (list == G_SLIST (iter->user_data))
2008         break;
2009       prev = list;
2010       list = list->next;
2011       old_location++;
2012     }
2013   g_assert (list != NULL);
2014
2015   next = list->next;
2016
2017   /* Check the common case, where we don't need to sort it moved. */
2018   if (prev != NULL)
2019     {
2020       tmp_iter.user_data = prev;
2021       cmp_a = (* func) (GTK_TREE_MODEL (list_store), &tmp_iter, iter, data);
2022     }
2023
2024   if (next != NULL)
2025     {
2026       tmp_iter.user_data = next;
2027       cmp_b = (* func) (GTK_TREE_MODEL (list_store), iter, &tmp_iter, data);
2028     }
2029
2030   if (list_store->order == GTK_SORT_DESCENDING)
2031     {
2032       if (cmp_a < 0)
2033         cmp_a = 1;
2034       else if (cmp_a > 0)
2035         cmp_a = -1;
2036
2037       if (cmp_b < 0)
2038         cmp_b = 1;
2039       else if (cmp_b > 0)
2040         cmp_b = -1;
2041     }
2042
2043   if (prev == NULL && cmp_b <= 0)
2044     return;
2045   else if (next == NULL && cmp_a <= 0)
2046     return;
2047   else if (prev != NULL && next != NULL &&
2048            cmp_a <= 0 && cmp_b <= 0)
2049     return;
2050
2051   /* We actually need to sort it */
2052   /* First, remove the old link. */
2053
2054   if (prev == NULL)
2055     list_store->root = next;
2056   else
2057     prev->next = next;
2058   if (next == NULL)
2059     list_store->tail = prev;
2060   list->next = NULL;
2061   
2062   /* FIXME: as an optimization, we can potentially start at next */
2063   prev = NULL;
2064   list = G_SLIST (list_store->root);
2065   new_location = 0;
2066   tmp_iter.user_data = list;
2067   if (list_store->order == GTK_SORT_DESCENDING)
2068     cmp_a = (* func) (GTK_TREE_MODEL (list_store), &tmp_iter, iter, data);
2069   else
2070     cmp_a = (* func) (GTK_TREE_MODEL (list_store), iter, &tmp_iter, data);
2071
2072   while ((list->next) && (cmp_a > 0))
2073     {
2074       prev = list;
2075       list = list->next;
2076       new_location++;
2077       tmp_iter.user_data = list;
2078       if (list_store->order == GTK_SORT_DESCENDING)
2079         cmp_a = (* func) (GTK_TREE_MODEL (list_store), &tmp_iter, iter, data);
2080       else
2081         cmp_a = (* func) (GTK_TREE_MODEL (list_store), iter, &tmp_iter, data);
2082     }
2083
2084   if ((!list->next) && (cmp_a > 0))
2085     {
2086       new_location++;
2087       list->next = G_SLIST (iter->user_data);
2088       list_store->tail = list->next;
2089     }
2090   else if (prev)
2091     {
2092       prev->next = G_SLIST (iter->user_data);
2093       G_SLIST (iter->user_data)->next = list;
2094     }
2095   else
2096     {
2097       G_SLIST (iter->user_data)->next = G_SLIST (list_store->root);
2098       list_store->root = G_SLIST (iter->user_data);
2099     }
2100
2101   /* Emit the reordered signal. */
2102   new_order = g_new (int, list_store->length);
2103   if (old_location < new_location)
2104     for (i = 0; i < list_store->length; i++)
2105       {
2106         if (i < old_location ||
2107             i > new_location)
2108           new_order[i] = i;
2109         else if (i >= old_location &&
2110                  i < new_location)
2111           new_order[i] = i + 1;
2112         else if (i == new_location)
2113           new_order[i] = old_location;
2114       }
2115   else
2116     for (i = 0; i < list_store->length; i++)
2117       {
2118         if (i < new_location ||
2119             i > old_location)
2120           new_order[i] = i;
2121         else if (i > new_location &&
2122                  i <= old_location)
2123           new_order[i] = i - 1;
2124         else if (i == new_location)
2125           new_order[i] = old_location;
2126       }
2127
2128   tmp_path = gtk_tree_path_new ();
2129   tmp_iter.user_data = NULL;
2130
2131   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (list_store),
2132                                  tmp_path, NULL,
2133                                  new_order);
2134
2135   gtk_tree_path_free (tmp_path);
2136   g_free (new_order);
2137 }
2138
2139 static gboolean
2140 gtk_list_store_get_sort_column_id (GtkTreeSortable  *sortable,
2141                                    gint             *sort_column_id,
2142                                    GtkSortType      *order)
2143 {
2144   GtkListStore *list_store = (GtkListStore *) sortable;
2145
2146   g_return_val_if_fail (GTK_IS_LIST_STORE (sortable), FALSE);
2147
2148   if (list_store->sort_column_id == -1)
2149     return FALSE;
2150
2151   if (sort_column_id)
2152     * sort_column_id = list_store->sort_column_id;
2153   if (order)
2154     * order = list_store->order;
2155   return TRUE;
2156 }
2157
2158 static void
2159 gtk_list_store_set_sort_column_id (GtkTreeSortable  *sortable,
2160                                    gint              sort_column_id,
2161                                    GtkSortType       order)
2162 {
2163   GtkListStore *list_store = (GtkListStore *) sortable;
2164
2165   g_return_if_fail (GTK_IS_LIST_STORE (sortable));
2166
2167   if ((list_store->sort_column_id == sort_column_id) &&
2168       (list_store->order == order))
2169     return;
2170
2171   if (sort_column_id != -1)
2172     {
2173       GtkTreeDataSortHeader *header = NULL;
2174
2175       header = _gtk_tree_data_list_get_header (list_store->sort_list, sort_column_id);
2176
2177       /* We want to make sure that we have a function */
2178       g_return_if_fail (header != NULL);
2179       g_return_if_fail (header->func != NULL);
2180     }
2181   else
2182     {
2183       g_return_if_fail (list_store->default_sort_func != NULL);
2184     }
2185
2186
2187   list_store->sort_column_id = sort_column_id;
2188   list_store->order = order;
2189
2190   gtk_list_store_sort (list_store);
2191
2192   gtk_tree_sortable_sort_column_changed (sortable);
2193 }
2194
2195 static void
2196 gtk_list_store_set_sort_func (GtkTreeSortable        *sortable,
2197                               gint                    sort_column_id,
2198                               GtkTreeIterCompareFunc  func,
2199                               gpointer                data,
2200                               GtkDestroyNotify        destroy)
2201 {
2202   GtkListStore *list_store = (GtkListStore *) sortable;
2203   GtkTreeDataSortHeader *header = NULL;
2204   GList *list;
2205
2206   g_return_if_fail (GTK_IS_LIST_STORE (sortable));
2207   g_return_if_fail (func != NULL);
2208
2209   for (list = list_store->sort_list; list; list = list->next)
2210     {
2211       GtkTreeDataSortHeader *list_header;
2212
2213       list_header = (GtkTreeDataSortHeader*) list->data;
2214       if (list_header->sort_column_id == sort_column_id)
2215         {
2216           header = list_header;
2217           break;
2218         }
2219     }
2220
2221   if (header == NULL)
2222     {
2223       header = g_new0 (GtkTreeDataSortHeader, 1);
2224       header->sort_column_id = sort_column_id;
2225       list_store->sort_list = g_list_append (list_store->sort_list, header);
2226     }
2227
2228   if (header->destroy)
2229     {
2230       GtkDestroyNotify d = header->destroy;
2231
2232       header->destroy = NULL;
2233       d (header->data);
2234     }
2235
2236   header->func = func;
2237   header->data = data;
2238   header->destroy = destroy;
2239 }
2240
2241
2242 static void
2243 gtk_list_store_set_default_sort_func (GtkTreeSortable        *sortable,
2244                                       GtkTreeIterCompareFunc  func,
2245                                       gpointer                data,
2246                                       GtkDestroyNotify        destroy)
2247 {
2248   GtkListStore *list_store = (GtkListStore *) sortable;
2249
2250   g_return_if_fail (GTK_IS_LIST_STORE (sortable));
2251
2252   if (list_store->default_sort_destroy)
2253     {
2254       GtkDestroyNotify d = list_store->default_sort_destroy;
2255
2256       list_store->default_sort_destroy = NULL;
2257       d (list_store->default_sort_data);
2258     }
2259
2260   list_store->default_sort_func = func;
2261   list_store->default_sort_data = data;
2262   list_store->default_sort_destroy = destroy;
2263 }
2264
2265 static gboolean
2266 gtk_list_store_has_default_sort_func (GtkTreeSortable *sortable)
2267 {
2268   GtkListStore *list_store = (GtkListStore *) sortable;
2269
2270   g_return_val_if_fail (GTK_IS_LIST_STORE (sortable), FALSE);
2271
2272   return (list_store->default_sort_func != NULL);
2273 }