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