]> Pileus Git - ~andy/gtk/blob - gtk/gtkliststore.c
538cbe67c283581a533a508817ff140ee7ca327a
[~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           return retval;
721         }
722
723       column--;
724       prev = list;
725       list = list->next;
726     }
727
728   if (G_SLIST (iter->user_data)->data == NULL)
729     {
730       G_SLIST (iter->user_data)->data = list = _gtk_tree_data_list_alloc ();
731       list->next = NULL;
732     }
733   else
734     {
735       list = prev->next = _gtk_tree_data_list_alloc ();
736       list->next = NULL;
737     }
738
739   while (column != 0)
740     {
741       list->next = _gtk_tree_data_list_alloc ();
742       list = list->next;
743       list->next = NULL;
744       column --;
745     }
746
747   if (converted)
748     _gtk_tree_data_list_value_to_node (list, &real_value);
749   else
750     _gtk_tree_data_list_value_to_node (list, value);
751
752   retval = TRUE;
753   if (converted)
754     g_value_unset (&real_value);
755
756   if (sort && GTK_LIST_STORE_IS_SORTED (list_store))
757     gtk_list_store_sort_iter_changed (list_store, iter, old_column);
758
759   return retval;
760 }
761
762
763 /**
764  * gtk_list_store_set_value:
765  * @list_store: A #GtkListStore
766  * @iter: A valid #GtkTreeIter for the row being modified
767  * @column: column number to modify
768  * @value: new value for the cell
769  *
770  * Sets the data in the cell specified by @iter and @column.
771  * The type of @value must be convertible to the type of the
772  * column.
773  *
774  **/
775 void
776 gtk_list_store_set_value (GtkListStore *list_store,
777                           GtkTreeIter  *iter,
778                           gint          column,
779                           GValue       *value)
780 {
781   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
782   g_return_if_fail (VALID_ITER (iter, list_store));
783   g_return_if_fail (column >= 0 && column < list_store->n_columns);
784   g_return_if_fail (G_IS_VALUE (value));
785
786   if (gtk_list_store_real_set_value (list_store, iter, column, value, TRUE))
787     {
788       GtkTreePath *path;
789
790       path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_store), iter);
791       gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
792       gtk_tree_path_free (path);
793     }
794 }
795
796 /**
797  * gtk_list_store_set_valist:
798  * @list_store: A #GtkListStore
799  * @iter: A valid #GtkTreeIter for the row being modified
800  * @var_args: va_list of column/value pairs
801  *
802  * See gtk_list_store_set(); this version takes a va_list for use by language
803  * bindings.
804  *
805  **/
806 void
807 gtk_list_store_set_valist (GtkListStore *list_store,
808                            GtkTreeIter  *iter,
809                            va_list       var_args)
810 {
811   gint column;
812   gboolean emit_signal = FALSE;
813   gboolean maybe_need_sort = FALSE;
814   GtkTreeIterCompareFunc func = NULL;
815
816   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
817   g_return_if_fail (VALID_ITER (iter, list_store));
818
819   column = va_arg (var_args, gint);
820
821   if (GTK_LIST_STORE_IS_SORTED (list_store))
822     {
823       if (list_store->sort_column_id != -1)
824         {
825           GtkTreeDataSortHeader *header;
826           header = _gtk_tree_data_list_get_header (list_store->sort_list,
827                                                    list_store->sort_column_id);
828           g_return_if_fail (header != NULL);
829           g_return_if_fail (header->func != NULL);
830           func = header->func;
831         }
832       else
833         {
834           func = list_store->default_sort_func;
835         }
836     }
837
838   if (func != gtk_tree_data_list_compare_func)
839     maybe_need_sort = TRUE;
840
841   while (column != -1)
842     {
843       GValue value = { 0, };
844       gchar *error = NULL;
845
846       if (column >= list_store->n_columns)
847         {
848           g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column);
849           break;
850         }
851       g_value_init (&value, list_store->column_headers[column]);
852
853       G_VALUE_COLLECT (&value, var_args, 0, &error);
854       if (error)
855         {
856           g_warning ("%s: %s", G_STRLOC, error);
857           g_free (error);
858
859           /* we purposely leak the value here, it might not be
860            * in a sane state if an error condition occoured
861            */
862           break;
863         }
864
865       /* FIXME: instead of calling this n times, refactor with above */
866       emit_signal = gtk_list_store_real_set_value (list_store,
867                                                    iter,
868                                                    column,
869                                                    &value,
870                                                    FALSE) || emit_signal;
871
872       if (func == gtk_tree_data_list_compare_func &&
873           column == list_store->sort_column_id)
874         maybe_need_sort = TRUE;
875
876       g_value_unset (&value);
877
878       column = va_arg (var_args, gint);
879     }
880
881   if (maybe_need_sort && GTK_LIST_STORE_IS_SORTED (list_store))
882     gtk_list_store_sort_iter_changed (list_store, iter, list_store->sort_column_id);
883
884   if (emit_signal)
885     {
886       GtkTreePath *path;
887
888       path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_store), iter);
889       gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
890       gtk_tree_path_free (path);
891     }
892 }
893
894 /**
895  * gtk_list_store_set:
896  * @list_store: a #GtkListStore
897  * @iter: row iterator
898  * @Varargs: pairs of column number and value, terminated with -1
899  *
900  * Sets the value of one or more cells in the row referenced by @iter.
901  * The variable argument list should contain integer column numbers,
902  * each column number followed by the value to be set.
903  * The list is terminated by a -1. For example, to set column 0 with type
904  * %G_TYPE_STRING to "Foo", you would write <literal>gtk_list_store_set (store, iter,
905  * 0, "Foo", -1)</literal>.
906  **/
907 void
908 gtk_list_store_set (GtkListStore *list_store,
909                     GtkTreeIter  *iter,
910                     ...)
911 {
912   va_list var_args;
913
914   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
915   g_return_if_fail (iter != NULL);
916   g_return_if_fail (iter->stamp == list_store->stamp);
917
918   va_start (var_args, iter);
919   gtk_list_store_set_valist (list_store, iter, var_args);
920   va_end (var_args);
921 }
922
923 static GSList*
924 remove_link_saving_prev (GSList  *list,
925                          GSList  *link,
926                          GSList **prevp)
927 {
928   GSList *tmp;
929   GSList *prev;
930
931   prev = NULL;
932   tmp = list;
933
934   while (tmp)
935     {
936       if (tmp == link)
937         {
938           if (prev)
939             prev->next = link->next;
940
941           if (list == link)
942             list = list->next;
943
944           link->next = NULL;
945           break;
946         }
947
948       prev = tmp;
949       tmp = tmp->next;
950     }
951
952   *prevp = prev;
953
954   return list;
955 }
956
957 static void
958 gtk_list_store_remove_silently (GtkListStore *list_store,
959                                 GtkTreeIter  *iter,
960                                 GtkTreePath  *path)
961 {
962   if (G_SLIST (iter->user_data)->data)
963     {
964       _gtk_tree_data_list_free ((GtkTreeDataList *) G_SLIST (iter->user_data)->data,
965                                 list_store->column_headers);
966       G_SLIST (iter->user_data)->data = NULL;
967     }
968
969   {
970     GSList *prev = NULL;
971
972     list_store->root = remove_link_saving_prev (G_SLIST (list_store->root),
973                                                 G_SLIST (iter->user_data),
974                                                 &prev);
975
976     list_store->length -= 1;
977
978     if (iter->user_data == list_store->tail)
979       list_store->tail = prev;
980
981     g_slist_free (G_SLIST (iter->user_data));
982   }
983 }
984
985 /**
986  * gtk_list_store_remove:
987  * @list_store: A #GtkListStore
988  * @iter: A valid #GtkTreeIter
989  *
990  * Removes the given row from the list store.  After being removed, 
991  * @iter is set to be the next valid row, or invalidated if it pointed 
992  * to the last row in @list_store.
993  *
994  * Return value: %TRUE if @iter is valid, %FALSE if not.
995  **/
996 gboolean
997 gtk_list_store_remove (GtkListStore *list_store,
998                        GtkTreeIter  *iter)
999 {
1000   GtkTreePath *path;
1001   GSList *next;
1002
1003   g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), FALSE);
1004   g_return_val_if_fail (VALID_ITER (iter, list_store), FALSE);
1005
1006   next = G_SLIST (iter->user_data)->next;
1007   path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
1008
1009   validate_list_store (list_store);
1010
1011   gtk_list_store_remove_silently (list_store, iter, path);
1012
1013   validate_list_store (list_store);
1014
1015   gtk_tree_model_row_deleted (GTK_TREE_MODEL (list_store), path);
1016   gtk_tree_path_free (path);
1017
1018   if (next)
1019     {
1020       iter->stamp = list_store->stamp;
1021       iter->user_data = next;
1022       return TRUE;
1023     }
1024   else
1025     {
1026       iter->stamp = 0;
1027     }
1028
1029   return FALSE;
1030 }
1031
1032 static void
1033 insert_after (GtkListStore *list_store,
1034               GSList       *sibling,
1035               GSList       *new_list)
1036 {
1037   g_return_if_fail (sibling != NULL);
1038   g_return_if_fail (new_list != NULL);
1039
1040   /* insert new node after list */
1041   new_list->next = sibling->next;
1042   sibling->next = new_list;
1043
1044   /* if list was the tail, the new node is the new tail */
1045   if (sibling == ((GSList *) list_store->tail))
1046     list_store->tail = new_list;
1047
1048   list_store->length += 1;
1049 }
1050
1051 /**
1052  * gtk_list_store_insert:
1053  * @list_store: A #GtkListStore
1054  * @iter: An unset #GtkTreeIter to set to the new row
1055  * @position: position to insert the new row
1056  *
1057  * Creates a new row at @position.  @iter will be changed to point to this new
1058  * row.  If @position is larger than the number of rows on the list, then the
1059  * new row will be appended to the list.  The row will be empty before this
1060  * function is called.  To fill in values, you need to call gtk_list_store_set()
1061  * or gtk_list_store_set_value().
1062  *
1063  **/
1064 void
1065 gtk_list_store_insert (GtkListStore *list_store,
1066                        GtkTreeIter  *iter,
1067                        gint          position)
1068 {
1069   GSList *list;
1070   GtkTreePath *path;
1071   GSList *new_list;
1072
1073   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1074   g_return_if_fail (iter != NULL);
1075   g_return_if_fail (position >= 0);
1076
1077   list_store->columns_dirty = TRUE;
1078
1079   if (position == 0 ||
1080       GTK_LIST_STORE_IS_SORTED (list_store))
1081     {
1082       gtk_list_store_prepend (list_store, iter);
1083       return;
1084     }
1085
1086   new_list = g_slist_alloc ();
1087
1088   list = g_slist_nth (G_SLIST (list_store->root), position - 1);
1089
1090   if (list == NULL)
1091     {
1092       /* position if off the end of the list, append it */
1093       gtk_list_store_append (list_store, iter);
1094
1095       return;
1096     }
1097
1098   insert_after (list_store, list, new_list);
1099
1100   iter->stamp = list_store->stamp;
1101   iter->user_data = new_list;
1102
1103   validate_list_store (list_store);
1104
1105   path = gtk_tree_path_new ();
1106   gtk_tree_path_append_index (path, position);
1107   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1108   gtk_tree_path_free (path);
1109 }
1110
1111 /**
1112  * gtk_list_store_insert_before:
1113  * @list_store: A #GtkListStore
1114  * @iter: An unset #GtkTreeIter to set to the new row
1115  * @sibling: A valid #GtkTreeIter, or %NULL
1116  *
1117  * Inserts a new row before @sibling. If @sibling is %NULL, then the row will be
1118  * appended to the end of the list. @iter will be changed to point to this new 
1119  * row. The row will be empty before this function is called. To fill in values,
1120  * you need to call gtk_list_store_set() or gtk_list_store_set_value().
1121  *
1122  **/
1123 void
1124 gtk_list_store_insert_before (GtkListStore *list_store,
1125                               GtkTreeIter  *iter,
1126                               GtkTreeIter  *sibling)
1127 {
1128   GtkTreePath *path;
1129   GSList *list, *prev, *new_list;
1130   gint i = 0;
1131
1132   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1133   g_return_if_fail (iter != NULL);
1134   if (sibling)
1135     g_return_if_fail (VALID_ITER (sibling, list_store));
1136
1137   list_store->columns_dirty = TRUE;
1138
1139   if (GTK_LIST_STORE_IS_SORTED (list_store))
1140     {
1141       gtk_list_store_prepend (list_store, iter);
1142       return;
1143     }
1144
1145   if (sibling == NULL)
1146     {
1147       gtk_list_store_append (list_store, iter);
1148       return;
1149     }
1150
1151   new_list = g_slist_alloc ();
1152
1153   prev = NULL;
1154   list = list_store->root;
1155   while (list && list != sibling->user_data)
1156     {
1157       prev = list;
1158       list = list->next;
1159       i++;
1160     }
1161
1162   if (list != sibling->user_data)
1163     {
1164       g_warning ("%s: sibling iterator invalid? not found in the list", G_STRLOC);
1165       return;
1166     }
1167
1168   /* if there are no nodes, we become the list tail, otherwise we
1169    * are inserting before any existing nodes so we can't change
1170    * the tail
1171    */
1172
1173   if (list_store->root == NULL)
1174     list_store->tail = new_list;
1175
1176   if (prev)
1177     {
1178       new_list->next = prev->next;
1179       prev->next = new_list;
1180     }
1181   else
1182     {
1183       new_list->next = list_store->root;
1184       list_store->root = new_list;
1185     }
1186
1187   iter->stamp = list_store->stamp;
1188   iter->user_data = new_list;
1189
1190   list_store->length += 1;
1191
1192   validate_list_store (list_store);
1193
1194   path = gtk_tree_path_new ();
1195   gtk_tree_path_append_index (path, i);
1196   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1197   gtk_tree_path_free (path);
1198 }
1199
1200 /**
1201  * gtk_list_store_insert_after:
1202  * @list_store: A #GtkListStore
1203  * @iter: An unset #GtkTreeIter to set to the new row
1204  * @sibling: A valid #GtkTreeIter, or %NULL
1205  *
1206  * Inserts a new row after @sibling. If @sibling is %NULL, then the row will be
1207  * prepended to the beginning of the list. @iter will be changed to point to
1208  * this new row. The row will be empty after this function is called. To fill
1209  * in values, you need to call gtk_list_store_set() or gtk_list_store_set_value().
1210  *
1211  **/
1212 void
1213 gtk_list_store_insert_after (GtkListStore *list_store,
1214                              GtkTreeIter  *iter,
1215                              GtkTreeIter  *sibling)
1216 {
1217   GtkTreePath *path;
1218   GSList *list, *new_list;
1219   gint i = 0;
1220
1221   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1222   g_return_if_fail (iter != NULL);
1223   if (sibling)
1224     g_return_if_fail (VALID_ITER (sibling, list_store));
1225
1226   list_store->columns_dirty = TRUE;
1227
1228   if (sibling == NULL ||
1229       GTK_LIST_STORE_IS_SORTED (list_store))
1230     {
1231       gtk_list_store_prepend (list_store, iter);
1232       return;
1233     }
1234
1235   for (list = list_store->root; list && list != sibling->user_data; list = list->next)
1236     i++;
1237
1238   g_return_if_fail (list == sibling->user_data);
1239
1240   new_list = g_slist_alloc ();
1241
1242   insert_after (list_store, list, new_list);
1243
1244   iter->stamp = list_store->stamp;
1245   iter->user_data = new_list;
1246
1247   validate_list_store (list_store);
1248
1249   path = gtk_tree_path_new ();
1250   gtk_tree_path_append_index (path, i + 1);
1251   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1252   gtk_tree_path_free (path);
1253 }
1254
1255 /**
1256  * gtk_list_store_prepend:
1257  * @list_store: A #GtkListStore
1258  * @iter: An unset #GtkTreeIter to set to the prepend row
1259  *
1260  * Prepends a new row to @list_store. @iter will be changed to point to this new
1261  * row. The row will be empty after this function is called. To fill in
1262  * values, you need to call gtk_list_store_set() or gtk_list_store_set_value().
1263  *
1264  **/
1265 void
1266 gtk_list_store_prepend (GtkListStore *list_store,
1267                         GtkTreeIter  *iter)
1268 {
1269   GtkTreePath *path;
1270
1271   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1272   g_return_if_fail (iter != NULL);
1273
1274   iter->stamp = list_store->stamp;
1275   iter->user_data = g_slist_alloc ();
1276
1277   list_store->columns_dirty = TRUE;
1278
1279   if (list_store->root == NULL)
1280     list_store->tail = iter->user_data;
1281
1282   G_SLIST (iter->user_data)->next = G_SLIST (list_store->root);
1283   list_store->root = iter->user_data;
1284
1285   list_store->length += 1;
1286
1287   validate_list_store (list_store);
1288
1289   path = gtk_tree_path_new ();
1290   gtk_tree_path_append_index (path, 0);
1291   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1292   gtk_tree_path_free (path);
1293 }
1294
1295 /**
1296  * gtk_list_store_append:
1297  * @list_store: A #GtkListStore
1298  * @iter: An unset #GtkTreeIter to set to the appended row
1299  *
1300  * Appends a new row to @list_store.  @iter will be changed to point to this new
1301  * row.  The row will be empty after this function is called.  To fill in
1302  * values, you need to call gtk_list_store_set() or gtk_list_store_set_value().
1303  *
1304  **/
1305 void
1306 gtk_list_store_append (GtkListStore *list_store,
1307                        GtkTreeIter  *iter)
1308 {
1309   GtkTreePath *path;
1310
1311   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1312   g_return_if_fail (iter != NULL);
1313
1314   list_store->columns_dirty = TRUE;
1315
1316   if (GTK_LIST_STORE_IS_SORTED (list_store))
1317     {
1318       gtk_list_store_prepend (list_store, iter);
1319       return;
1320     }
1321
1322   iter->stamp = list_store->stamp;
1323   iter->user_data = g_slist_alloc ();
1324
1325   if (list_store->tail)
1326     ((GSList *)list_store->tail)->next = iter->user_data;
1327   else
1328     list_store->root = iter->user_data;
1329
1330   list_store->tail = iter->user_data;
1331
1332   list_store->length += 1;
1333
1334   validate_list_store (list_store);
1335
1336   path = gtk_tree_path_new ();
1337   gtk_tree_path_append_index (path, list_store->length - 1);
1338   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1339   gtk_tree_path_free (path);
1340 }
1341
1342 /**
1343  * gtk_list_store_clear:
1344  * @list_store: a #GtkListStore.
1345  *
1346  * Removes all rows from the list store.  
1347  *
1348  **/
1349 void
1350 gtk_list_store_clear (GtkListStore *list_store)
1351 {
1352   GtkTreeIter iter;
1353   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1354
1355   while (list_store->root)
1356     {
1357       iter.stamp = list_store->stamp;
1358       iter.user_data = list_store->root;
1359       gtk_list_store_remove (list_store, &iter);
1360     }
1361 }
1362
1363 /**
1364  * gtk_list_store_iter_is_valid:
1365  * @list_store: A #GtkListStore.
1366  * @iter: A #GtkTreeIter.
1367  *
1368  * WARNING: This function is slow. Only use it for debugging and/or testing
1369  * purposes.
1370  *
1371  * Checks if the given iter is a valid iter for this #GtkListStore.
1372  *
1373  * Return value: %TRUE if the iter is valid, %FALSE if the iter is invalid.
1374  **/
1375 gboolean
1376 gtk_list_store_iter_is_valid (GtkListStore *list_store,
1377                               GtkTreeIter  *iter)
1378 {
1379   GList *list;
1380
1381   g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), FALSE);
1382   g_return_val_if_fail (iter != NULL, FALSE);
1383
1384   if (!VALID_ITER (iter, list_store))
1385     return FALSE;
1386
1387   if (iter->user_data == list_store->root)
1388     return TRUE;
1389   if (iter->user_data == list_store->tail)
1390     return TRUE;
1391
1392   for (list = ((GList *)list_store->root)->next; list; list = list->next)
1393     if (list == iter->user_data)
1394       return TRUE;
1395
1396   return FALSE;
1397 }
1398
1399 static gboolean
1400 gtk_list_store_drag_data_delete (GtkTreeDragSource *drag_source,
1401                                  GtkTreePath       *path)
1402 {
1403   GtkTreeIter iter;
1404   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE);
1405
1406   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source),
1407                                &iter,
1408                                path))
1409     {
1410       gtk_list_store_remove (GTK_LIST_STORE (drag_source), &iter);
1411       return TRUE;
1412     }
1413   return FALSE;
1414 }
1415
1416 static gboolean
1417 gtk_list_store_drag_data_get (GtkTreeDragSource *drag_source,
1418                               GtkTreePath       *path,
1419                               GtkSelectionData  *selection_data)
1420 {
1421   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE);
1422
1423   /* Note that we don't need to handle the GTK_TREE_MODEL_ROW
1424    * target, because the default handler does it for us, but
1425    * we do anyway for the convenience of someone maybe overriding the
1426    * default handler.
1427    */
1428
1429   if (gtk_tree_set_row_drag_data (selection_data,
1430                                   GTK_TREE_MODEL (drag_source),
1431                                   path))
1432     {
1433       return TRUE;
1434     }
1435   else
1436     {
1437       /* FIXME handle text targets at least. */
1438     }
1439
1440   return FALSE;
1441 }
1442
1443 static gboolean
1444 gtk_list_store_drag_data_received (GtkTreeDragDest   *drag_dest,
1445                                    GtkTreePath       *dest,
1446                                    GtkSelectionData  *selection_data)
1447 {
1448   GtkTreeModel *tree_model;
1449   GtkListStore *list_store;
1450   GtkTreeModel *src_model = NULL;
1451   GtkTreePath *src_path = NULL;
1452   gboolean retval = FALSE;
1453
1454   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE);
1455
1456   tree_model = GTK_TREE_MODEL (drag_dest);
1457   list_store = GTK_LIST_STORE (drag_dest);
1458
1459   if (gtk_tree_get_row_drag_data (selection_data,
1460                                   &src_model,
1461                                   &src_path) &&
1462       src_model == tree_model)
1463     {
1464       /* Copy the given row to a new position */
1465       GtkTreeIter src_iter;
1466       GtkTreeIter dest_iter;
1467       GtkTreePath *prev;
1468
1469       if (!gtk_tree_model_get_iter (src_model,
1470                                     &src_iter,
1471                                     src_path))
1472         {
1473           goto out;
1474         }
1475
1476       /* Get the path to insert _after_ (dest is the path to insert _before_) */
1477       prev = gtk_tree_path_copy (dest);
1478
1479       if (!gtk_tree_path_prev (prev))
1480         {
1481           /* dest was the first spot in the list; which means we are supposed
1482            * to prepend.
1483            */
1484           gtk_list_store_prepend (GTK_LIST_STORE (tree_model),
1485                                   &dest_iter);
1486
1487           retval = TRUE;
1488         }
1489       else
1490         {
1491           if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model),
1492                                        &dest_iter,
1493                                        prev))
1494             {
1495               GtkTreeIter tmp_iter = dest_iter;
1496
1497               if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tree_model), "gtk-tree-model-drop-append")))
1498                 gtk_list_store_append (GTK_LIST_STORE (tree_model), &dest_iter);
1499               else
1500                 gtk_list_store_insert_after (GTK_LIST_STORE (tree_model),
1501                                              &dest_iter, &tmp_iter);
1502
1503               retval = TRUE;
1504             }
1505         }
1506
1507       g_object_set_data (G_OBJECT (tree_model), "gtk-tree-model-drop-append",
1508                          NULL);
1509
1510       gtk_tree_path_free (prev);
1511
1512       /* If we succeeded in creating dest_iter, copy data from src
1513        */
1514       if (retval)
1515         {
1516           GtkTreeDataList *dl = G_SLIST (src_iter.user_data)->data;
1517           GtkTreeDataList *copy_head = NULL;
1518           GtkTreeDataList *copy_prev = NULL;
1519           GtkTreeDataList *copy_iter = NULL;
1520           GtkTreePath *path;
1521           gint col;
1522
1523           col = 0;
1524           while (dl)
1525             {
1526               copy_iter = _gtk_tree_data_list_node_copy (dl,
1527                                                          list_store->column_headers[col]);
1528
1529               if (copy_head == NULL)
1530                 copy_head = copy_iter;
1531
1532               if (copy_prev)
1533                 copy_prev->next = copy_iter;
1534
1535               copy_prev = copy_iter;
1536
1537               dl = dl->next;
1538               ++col;
1539             }
1540
1541           dest_iter.stamp = GTK_LIST_STORE (tree_model)->stamp;
1542           G_SLIST (dest_iter.user_data)->data = copy_head;
1543
1544           path = gtk_list_store_get_path (GTK_TREE_MODEL (tree_model), &dest_iter);
1545           gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_model), path, &dest_iter);
1546           gtk_tree_path_free (path);
1547         }
1548     }
1549   else
1550     {
1551       /* FIXME maybe add some data targets eventually, or handle text
1552        * targets in the simple case.
1553        */
1554     }
1555
1556  out:
1557
1558   if (src_path)
1559     gtk_tree_path_free (src_path);
1560
1561   return retval;
1562 }
1563
1564 static gboolean
1565 gtk_list_store_row_drop_possible (GtkTreeDragDest  *drag_dest,
1566                                   GtkTreePath      *dest_path,
1567                                   GtkSelectionData *selection_data)
1568 {
1569   gint *indices;
1570   GtkTreeModel *src_model = NULL;
1571   GtkTreePath *src_path = NULL;
1572   gboolean retval = FALSE;
1573
1574   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE);
1575
1576   /* don't accept drops if the list has been sorted */
1577   if (GTK_LIST_STORE_IS_SORTED (drag_dest))
1578     return FALSE;
1579
1580   if (!gtk_tree_get_row_drag_data (selection_data,
1581                                    &src_model,
1582                                    &src_path))
1583     goto out;
1584     
1585   if (src_model != GTK_TREE_MODEL (drag_dest))
1586     goto out;
1587
1588   if (gtk_tree_path_get_depth (dest_path) != 1)
1589     goto out;
1590
1591   /* can drop before any existing node, or before one past any existing. */
1592
1593   indices = gtk_tree_path_get_indices (dest_path);
1594
1595   if (indices[0] <= GTK_LIST_STORE (drag_dest)->length)
1596     retval = TRUE;
1597
1598  out:
1599   gtk_tree_path_free (src_path);
1600   
1601   return retval;
1602 }
1603
1604 /* Sorting and reordering */
1605 typedef struct _SortTuple
1606 {
1607   gint offset;
1608   GSList *el;
1609 } SortTuple;
1610
1611 /* Reordering */
1612 static gint
1613 gtk_list_store_reorder_func (gconstpointer a,
1614                              gconstpointer b,
1615                              gpointer      user_data)
1616 {
1617   SortTuple *a_reorder;
1618   SortTuple *b_reorder;
1619
1620   a_reorder = (SortTuple *)a;
1621   b_reorder = (SortTuple *)b;
1622
1623   if (a_reorder->offset < b_reorder->offset)
1624     return -1;
1625   if (a_reorder->offset > b_reorder->offset)
1626     return 1;
1627
1628   return 0;
1629 }
1630
1631 /**
1632  * gtk_list_store_reorder:
1633  * @store: A #GtkTreeStore.
1634  * @new_order: An integer array indicating the new order for the list.
1635  *
1636  * Reorders @store to follow the order indicated by @new_order. Note that
1637  * this function only works with unsorted stores.
1638  **/
1639 void
1640 gtk_list_store_reorder (GtkListStore *store,
1641                         gint         *new_order)
1642 {
1643   gint i;
1644   GSList *current_list;
1645   GtkTreePath *path;
1646   SortTuple *sort_array;
1647
1648   g_return_if_fail (GTK_IS_LIST_STORE (store));
1649   g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1650   g_return_if_fail (new_order != NULL);
1651
1652   sort_array = g_new (SortTuple, store->length);
1653
1654   current_list = store->root;
1655
1656   for (i = 0; i < store->length; i++)
1657     {
1658       sort_array[i].offset = new_order[i];
1659       sort_array[i].el = current_list;
1660
1661       current_list = current_list->next;
1662     }
1663
1664   g_qsort_with_data (sort_array,
1665                      store->length,
1666                      sizeof (SortTuple),
1667                      gtk_list_store_reorder_func,
1668                      NULL);
1669
1670   for (i = 0; i < store->length - 1; i++)
1671     G_SLIST (sort_array[i].el)->next = G_SLIST (sort_array[i+1].el);
1672
1673   store->root = G_SLIST (sort_array[0].el);
1674   store->tail = G_SLIST (sort_array[store->length-1].el);
1675   G_SLIST (store->tail)->next = NULL;
1676
1677   /* emit signal */
1678   path = gtk_tree_path_new ();
1679   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store),
1680                                  path, NULL, new_order);
1681   gtk_tree_path_free (path);
1682   g_free (sort_array);
1683 }
1684
1685 /**
1686  * gtk_list_store_swap:
1687  * @store: A #GtkListStore.
1688  * @a: A #GtkTreeIter.
1689  * @b: Another #GtkTreeIter.
1690  *
1691  * Swaps @a and @b in @store. Note that this function only works with
1692  * unsorted stores.
1693  **/
1694 void
1695 gtk_list_store_swap (GtkListStore *store,
1696                      GtkTreeIter  *a,
1697                      GtkTreeIter  *b)
1698 {
1699   GSList *i, *prev_a = NULL, *prev_b = NULL;
1700   gint j, a_count = 0, b_count = 0, *order;
1701   GtkTreePath *path;
1702
1703   g_return_if_fail (GTK_IS_LIST_STORE (store));
1704   g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1705   g_return_if_fail (VALID_ITER (a, store));
1706   g_return_if_fail (VALID_ITER (b, store));
1707
1708   if (a->user_data == b->user_data)
1709     return;
1710
1711   if (a->user_data == store->root)
1712     prev_a = NULL;
1713   else
1714     {
1715       for (i = store->root; i; i = i->next, a_count++)
1716         if (i->next == a->user_data)
1717           {
1718             prev_a = i;
1719             break;
1720           }
1721
1722       a_count++;
1723     }
1724
1725   if (b->user_data == store->root)
1726     prev_b = NULL;
1727   else
1728     {
1729       for (i = store->root; i; i = i->next, b_count++)
1730         if (i->next == b->user_data)
1731           {
1732             prev_b = i;
1733             break;
1734           }
1735
1736       b_count++;
1737     }
1738
1739   if (!prev_a)
1740     store->root = b->user_data;
1741   else
1742     prev_a->next = b->user_data;
1743
1744   if (!prev_b)
1745     store->root = a->user_data;
1746   else
1747     prev_b->next = a->user_data;
1748
1749   /* think a_next inspead of a_prev here ... */
1750   prev_a = G_SLIST (a->user_data)->next;
1751   prev_b = G_SLIST (b->user_data)->next;
1752
1753   G_SLIST (a->user_data)->next = prev_b;
1754   G_SLIST (b->user_data)->next = prev_a;
1755
1756   /* emit signal */
1757   order = g_new (gint, store->length);
1758   for (j = 0; j < store->length; j++)
1759     if (j == a_count)
1760       order[j] = b_count;
1761     else if (j == b_count)
1762       order[j] = a_count;
1763     else
1764       order[j] = j;
1765
1766   path = gtk_tree_path_new ();
1767   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store),
1768                                  path, NULL, order);
1769   gtk_tree_path_free (path);
1770   g_free (order);
1771 }
1772
1773 static void
1774 gtk_list_store_move (GtkListStore *store,
1775                      GtkTreeIter  *iter,
1776                      GtkTreeIter  *position,
1777                      gboolean      before)
1778 {
1779   GtkTreeIter dst_a;
1780   GSList *i, *a, *prev = NULL, *tmp;
1781   gint new_pos = 0, old_pos = 0, j = 0, *order;
1782   GtkTreePath *path, *pos_path = NULL;
1783
1784   g_return_if_fail (GTK_IS_LIST_STORE (store));
1785   g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1786   g_return_if_fail (VALID_ITER (iter, store));
1787   if (position)
1788     g_return_if_fail (VALID_ITER (position, store));
1789
1790   /* lots of sanity checks */
1791   if (position)
1792     {
1793       path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), iter);
1794       pos_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), position);
1795
1796       if (gtk_tree_path_get_depth (pos_path) != 1)
1797         goto free_paths_and_out;
1798
1799       /* if before:
1800        *   moving the iter before path or "path + 1" doesn't make sense
1801        * else
1802        *   moving the iter before path or "path - 1" doesn't make sense
1803        */
1804       if (!gtk_tree_path_compare (path, pos_path))
1805         goto free_paths_and_out;
1806
1807       if (before)
1808         gtk_tree_path_next (path);
1809       else
1810         gtk_tree_path_prev (path);
1811
1812       if (!gtk_tree_path_compare (path, pos_path))
1813         goto free_paths_and_out;
1814
1815       gtk_tree_path_free (path);
1816     }
1817
1818   /* getting destination iters */
1819   if (before && position)
1820     {
1821       if (gtk_tree_path_get_indices (pos_path)[0] > 0)
1822         {
1823           gtk_tree_path_prev (pos_path);
1824           if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &dst_a, pos_path))
1825             a = G_SLIST (dst_a.user_data);
1826           else
1827             a = NULL;
1828           gtk_tree_path_next (pos_path);
1829         }
1830       else
1831         a = NULL;
1832     }
1833   else if (before && !position)
1834     a = NULL;
1835   else /* !before */
1836     {
1837       if (position)
1838         a = G_SLIST (position->user_data);
1839       else
1840         a = NULL;
1841     }
1842
1843   /* getting the old prev node */
1844   if (iter->user_data == store->root)
1845     prev = NULL;
1846   else
1847     {
1848       for (i = store->root; i; i = i->next, old_pos++)
1849         if (i->next == iter->user_data)
1850           {
1851             prev = i;
1852             break;
1853           }
1854
1855       old_pos++;
1856     }
1857
1858   /* remove node */
1859   if (!prev)
1860     store->root = G_SLIST (iter->user_data)->next;
1861   else
1862     prev->next = G_SLIST (iter->user_data)->next;
1863
1864   /* and reinsert it */
1865   if (a)
1866     {
1867       tmp = a->next;
1868
1869       a->next = G_SLIST (iter->user_data);
1870       a->next->next = tmp;
1871     }
1872   else if (!a && !before)
1873     {
1874       tmp = G_SLIST (store->root);
1875
1876       store->root = G_SLIST (iter->user_data);
1877       G_SLIST (store->root)->next = tmp;
1878     }
1879   else if (!a && before)
1880     {
1881       G_SLIST (store->tail)->next = G_SLIST (iter->user_data);
1882       G_SLIST (iter->user_data)->next = NULL;
1883       store->tail = iter->user_data;
1884     }
1885
1886   /* emit signal */
1887   if (position)
1888     new_pos = gtk_tree_path_get_indices (pos_path)[0];
1889   else if (before)
1890     new_pos = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL) - 1;
1891   else
1892     new_pos = 0;
1893
1894   if (new_pos > old_pos)
1895     {
1896       if (before)
1897         new_pos--;
1898     }
1899   else
1900     {
1901       if (!before)
1902         new_pos++;
1903     }
1904
1905   order = g_new (gint, store->length);
1906   if (new_pos > old_pos)
1907     {
1908       for (j = 0; j < store->length; j++)
1909         if (j < old_pos)
1910           order[j] = j;
1911         else if (j >= old_pos && j < new_pos)
1912           order[j] = j + 1;
1913         else if (j == new_pos)
1914           order[j] = old_pos;
1915         else
1916           order[j] = j;
1917     }
1918   else
1919     {
1920       for (j = 0; j < store->length; j++)
1921         if (j == new_pos)
1922           order[j] = old_pos;
1923         else if (j > new_pos && j <= old_pos)
1924           order[j] = j - 1;
1925         else
1926           order[j] = j;
1927     }
1928
1929   path = gtk_tree_path_new ();
1930   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store),
1931                                  path, NULL, order);
1932   gtk_tree_path_free (path);
1933   if (position)
1934     gtk_tree_path_free (pos_path);
1935   g_free (order);
1936
1937   return;
1938
1939 free_paths_and_out:
1940   gtk_tree_path_free (path);
1941   gtk_tree_path_free (pos_path);
1942 }
1943
1944 /**
1945  * gtk_list_store_move_before:
1946  * @store: A #GtkListStore.
1947  * @iter: A #GtkTreeIter.
1948  * @position: A #GtkTreeIter, or %NULL.
1949  *
1950  * Moves @iter in @store to the position before @position. Note that this
1951  * function only works with unsorted stores. If @position is %NULL, @iter
1952  * will be moved to the end of the list.
1953  **/
1954 void
1955 gtk_list_store_move_before (GtkListStore *store,
1956                             GtkTreeIter  *iter,
1957                             GtkTreeIter  *position)
1958 {
1959   gtk_list_store_move (store, iter, position, TRUE);
1960 }
1961
1962 /**
1963  * gtk_list_store_move_after:
1964  * @store: A #GtkListStore.
1965  * @iter: A #GtkTreeIter.
1966  * @position: A #GtkTreeIter, or %NULL.
1967  *
1968  * Moves @iter in @store to the position after @position. Note that this
1969  * function only works with unsorted stores. If @position is %NULL, @iter
1970  * will be moved to the start of the list.
1971  **/
1972 void
1973 gtk_list_store_move_after (GtkListStore *store,
1974                            GtkTreeIter  *iter,
1975                            GtkTreeIter  *position)
1976 {
1977   gtk_list_store_move (store, iter, position, FALSE);
1978 }
1979
1980 /* Sorting */
1981 static gint
1982 gtk_list_store_compare_func (gconstpointer a,
1983                              gconstpointer b,
1984                              gpointer      user_data)
1985 {
1986   GtkListStore *list_store = user_data;
1987   GSList *el_a; /* Los Angeles? */
1988   GSList *el_b;
1989   GtkTreeIter iter_a;
1990   GtkTreeIter iter_b;
1991   gint retval;
1992   GtkTreeIterCompareFunc func;
1993   gpointer data;
1994
1995
1996   if (list_store->sort_column_id != -1)
1997     {
1998       GtkTreeDataSortHeader *header;
1999
2000       header = _gtk_tree_data_list_get_header (list_store->sort_list,
2001                                                list_store->sort_column_id);
2002       g_return_val_if_fail (header != NULL, 0);
2003       g_return_val_if_fail (header->func != NULL, 0);
2004
2005       func = header->func;
2006       data = header->data;
2007     }
2008   else
2009     {
2010       g_return_val_if_fail (list_store->default_sort_func != NULL, 0);
2011       func = list_store->default_sort_func;
2012       data = list_store->default_sort_data;
2013     }
2014
2015   el_a = ((SortTuple *) a)->el;
2016   el_b = ((SortTuple *) b)->el;
2017
2018   iter_a.stamp = list_store->stamp;
2019   iter_a.user_data = el_a;
2020   iter_b.stamp = list_store->stamp;
2021   iter_b.user_data = el_b;
2022
2023   retval = (* func) (GTK_TREE_MODEL (list_store), &iter_a, &iter_b, data);
2024
2025   if (list_store->order == GTK_SORT_DESCENDING)
2026     {
2027       if (retval > 0)
2028         retval = -1;
2029       else if (retval < 0)
2030         retval = 1;
2031     }
2032   return retval;
2033 }
2034
2035 static void
2036 gtk_list_store_sort (GtkListStore *list_store)
2037 {
2038   GArray *sort_array;
2039   gint i;
2040   gint *new_order;
2041   GSList *list;
2042   GtkTreePath *path;
2043
2044   if (list_store->length <= 1)
2045     return;
2046
2047   g_assert (GTK_LIST_STORE_IS_SORTED (list_store));
2048
2049   list = G_SLIST (list_store->root);
2050
2051   sort_array = g_array_sized_new (FALSE, FALSE,
2052                                   sizeof (SortTuple),
2053                                   list_store->length);
2054
2055   for (i = 0; i < list_store->length; i++)
2056     {
2057       SortTuple tuple;
2058
2059       /* If this fails, we are in an inconsistent state.  Bad */
2060       g_return_if_fail (list != NULL);
2061
2062       tuple.offset = i;
2063       tuple.el = list;
2064       g_array_append_val (sort_array, tuple);
2065
2066       list = list->next;
2067     }
2068
2069   g_array_sort_with_data (sort_array, gtk_list_store_compare_func, list_store);
2070
2071   for (i = 0; i < list_store->length - 1; i++)
2072       g_array_index (sort_array, SortTuple, i).el->next =
2073         g_array_index (sort_array, SortTuple, i + 1).el;
2074   g_array_index (sort_array, SortTuple, list_store->length - 1).el->next = NULL;
2075   list_store->root = g_array_index (sort_array, SortTuple, 0).el;
2076   list_store->tail = g_array_index (sort_array, SortTuple, list_store->length - 1).el;
2077
2078   /* Let the world know about our new order */
2079   new_order = g_new (gint, list_store->length);
2080   for (i = 0; i < list_store->length; i++)
2081     new_order[i] = g_array_index (sort_array, SortTuple, i).offset;
2082
2083   path = gtk_tree_path_new ();
2084   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (list_store),
2085                                  path, NULL, new_order);
2086   gtk_tree_path_free (path);
2087   g_free (new_order);
2088   g_array_free (sort_array, TRUE);
2089 }
2090
2091 static void
2092 gtk_list_store_sort_iter_changed (GtkListStore *list_store,
2093                                   GtkTreeIter  *iter,
2094                                   gint          column)
2095
2096 {
2097   GSList *prev = NULL;
2098   GSList *next = NULL;
2099   GSList *list = G_SLIST (list_store->root);
2100   GtkTreePath *tmp_path;
2101   GtkTreeIter tmp_iter;
2102   gint cmp_a = 0;
2103   gint cmp_b = 0;
2104   gint i;
2105   gint old_location;
2106   gint new_location;
2107   gint *new_order;
2108   GtkTreeIterCompareFunc func;
2109   gpointer data;
2110
2111   if (list_store->length < 2)
2112     return;
2113
2114   tmp_iter.stamp = list_store->stamp;
2115
2116   if (list_store->sort_column_id != -1)
2117     {
2118       GtkTreeDataSortHeader *header;
2119       header = _gtk_tree_data_list_get_header (list_store->sort_list,
2120                                                list_store->sort_column_id);
2121       g_return_if_fail (header != NULL);
2122       g_return_if_fail (header->func != NULL);
2123       func = header->func;
2124       data = header->data;
2125     }
2126   else
2127     {
2128       g_return_if_fail (list_store->default_sort_func != NULL);
2129       func = list_store->default_sort_func;
2130       data = list_store->default_sort_data;
2131     }
2132
2133   /* If it's the built in function, we don't sort. */
2134   if (func == gtk_tree_data_list_compare_func &&
2135       list_store->sort_column_id != column)
2136     return;
2137
2138   old_location = 0;
2139   /* First we find the iter, its prev, and its next */
2140   while (list)
2141     {
2142       if (list == G_SLIST (iter->user_data))
2143         break;
2144       prev = list;
2145       list = list->next;
2146       old_location++;
2147     }
2148   g_assert (list != NULL);
2149
2150   next = list->next;
2151
2152   /* Check the common case, where we don't need to sort it moved. */
2153   if (prev != NULL)
2154     {
2155       tmp_iter.user_data = prev;
2156       cmp_a = (* func) (GTK_TREE_MODEL (list_store), &tmp_iter, iter, data);
2157     }
2158
2159   if (next != NULL)
2160     {
2161       tmp_iter.user_data = next;
2162       cmp_b = (* func) (GTK_TREE_MODEL (list_store), iter, &tmp_iter, data);
2163     }
2164
2165   if (list_store->order == GTK_SORT_DESCENDING)
2166     {
2167       if (cmp_a < 0)
2168         cmp_a = 1;
2169       else if (cmp_a > 0)
2170         cmp_a = -1;
2171
2172       if (cmp_b < 0)
2173         cmp_b = 1;
2174       else if (cmp_b > 0)
2175         cmp_b = -1;
2176     }
2177
2178   if (prev == NULL && cmp_b <= 0)
2179     return;
2180   else if (next == NULL && cmp_a <= 0)
2181     return;
2182   else if (prev != NULL && next != NULL &&
2183            cmp_a <= 0 && cmp_b <= 0)
2184     return;
2185
2186   /* We actually need to sort it */
2187   /* First, remove the old link. */
2188
2189   if (prev == NULL)
2190     list_store->root = next;
2191   else
2192     prev->next = next;
2193   if (next == NULL)
2194     list_store->tail = prev;
2195   list->next = NULL;
2196   
2197   /* FIXME: as an optimization, we can potentially start at next */
2198   prev = NULL;
2199   list = G_SLIST (list_store->root);
2200   new_location = 0;
2201   tmp_iter.user_data = list;
2202   if (list_store->order == GTK_SORT_DESCENDING)
2203     cmp_a = (* func) (GTK_TREE_MODEL (list_store), &tmp_iter, iter, data);
2204   else
2205     cmp_a = (* func) (GTK_TREE_MODEL (list_store), iter, &tmp_iter, data);
2206
2207   while ((list->next) && (cmp_a > 0))
2208     {
2209       prev = list;
2210       list = list->next;
2211       new_location++;
2212       tmp_iter.user_data = list;
2213       if (list_store->order == GTK_SORT_DESCENDING)
2214         cmp_a = (* func) (GTK_TREE_MODEL (list_store), &tmp_iter, iter, data);
2215       else
2216         cmp_a = (* func) (GTK_TREE_MODEL (list_store), iter, &tmp_iter, data);
2217     }
2218
2219   if ((!list->next) && (cmp_a > 0))
2220     {
2221       new_location++;
2222       list->next = G_SLIST (iter->user_data);
2223       list_store->tail = list->next;
2224     }
2225   else if (prev)
2226     {
2227       prev->next = G_SLIST (iter->user_data);
2228       G_SLIST (iter->user_data)->next = list;
2229     }
2230   else
2231     {
2232       G_SLIST (iter->user_data)->next = G_SLIST (list_store->root);
2233       list_store->root = G_SLIST (iter->user_data);
2234     }
2235
2236   /* Emit the reordered signal. */
2237   new_order = g_new (int, list_store->length);
2238   if (old_location < new_location)
2239     for (i = 0; i < list_store->length; i++)
2240       {
2241         if (i < old_location ||
2242             i > new_location)
2243           new_order[i] = i;
2244         else if (i >= old_location &&
2245                  i < new_location)
2246           new_order[i] = i + 1;
2247         else if (i == new_location)
2248           new_order[i] = old_location;
2249       }
2250   else
2251     for (i = 0; i < list_store->length; i++)
2252       {
2253         if (i < new_location ||
2254             i > old_location)
2255           new_order[i] = i;
2256         else if (i > new_location &&
2257                  i <= old_location)
2258           new_order[i] = i - 1;
2259         else if (i == new_location)
2260           new_order[i] = old_location;
2261       }
2262
2263   tmp_path = gtk_tree_path_new ();
2264   tmp_iter.user_data = NULL;
2265
2266   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (list_store),
2267                                  tmp_path, NULL,
2268                                  new_order);
2269
2270   gtk_tree_path_free (tmp_path);
2271   g_free (new_order);
2272 }
2273
2274 static gboolean
2275 gtk_list_store_get_sort_column_id (GtkTreeSortable  *sortable,
2276                                    gint             *sort_column_id,
2277                                    GtkSortType      *order)
2278 {
2279   GtkListStore *list_store = (GtkListStore *) sortable;
2280
2281   g_return_val_if_fail (GTK_IS_LIST_STORE (sortable), FALSE);
2282
2283   if (list_store->sort_column_id == -1)
2284     return FALSE;
2285
2286   if (sort_column_id)
2287     * sort_column_id = list_store->sort_column_id;
2288   if (order)
2289     * order = list_store->order;
2290   return TRUE;
2291 }
2292
2293 static void
2294 gtk_list_store_set_sort_column_id (GtkTreeSortable  *sortable,
2295                                    gint              sort_column_id,
2296                                    GtkSortType       order)
2297 {
2298   GtkListStore *list_store = (GtkListStore *) sortable;
2299
2300   g_return_if_fail (GTK_IS_LIST_STORE (sortable));
2301
2302   if ((list_store->sort_column_id == sort_column_id) &&
2303       (list_store->order == order))
2304     return;
2305
2306   if (sort_column_id != -1)
2307     {
2308       GtkTreeDataSortHeader *header = NULL;
2309
2310       header = _gtk_tree_data_list_get_header (list_store->sort_list, sort_column_id);
2311
2312       /* We want to make sure that we have a function */
2313       g_return_if_fail (header != NULL);
2314       g_return_if_fail (header->func != NULL);
2315     }
2316   else
2317     {
2318       g_return_if_fail (list_store->default_sort_func != NULL);
2319     }
2320
2321
2322   list_store->sort_column_id = sort_column_id;
2323   list_store->order = order;
2324
2325   gtk_list_store_sort (list_store);
2326
2327   gtk_tree_sortable_sort_column_changed (sortable);
2328 }
2329
2330 static void
2331 gtk_list_store_set_sort_func (GtkTreeSortable        *sortable,
2332                               gint                    sort_column_id,
2333                               GtkTreeIterCompareFunc  func,
2334                               gpointer                data,
2335                               GtkDestroyNotify        destroy)
2336 {
2337   GtkListStore *list_store = (GtkListStore *) sortable;
2338   GtkTreeDataSortHeader *header = NULL;
2339   GList *list;
2340
2341   g_return_if_fail (GTK_IS_LIST_STORE (sortable));
2342   g_return_if_fail (func != NULL);
2343
2344   for (list = list_store->sort_list; list; list = list->next)
2345     {
2346       GtkTreeDataSortHeader *list_header;
2347
2348       list_header = (GtkTreeDataSortHeader*) list->data;
2349       if (list_header->sort_column_id == sort_column_id)
2350         {
2351           header = list_header;
2352           break;
2353         }
2354     }
2355
2356   if (header == NULL)
2357     {
2358       header = g_new0 (GtkTreeDataSortHeader, 1);
2359       header->sort_column_id = sort_column_id;
2360       list_store->sort_list = g_list_append (list_store->sort_list, header);
2361     }
2362
2363   if (header->destroy)
2364     {
2365       GtkDestroyNotify d = header->destroy;
2366
2367       header->destroy = NULL;
2368       d (header->data);
2369     }
2370
2371   header->func = func;
2372   header->data = data;
2373   header->destroy = destroy;
2374 }
2375
2376
2377 static void
2378 gtk_list_store_set_default_sort_func (GtkTreeSortable        *sortable,
2379                                       GtkTreeIterCompareFunc  func,
2380                                       gpointer                data,
2381                                       GtkDestroyNotify        destroy)
2382 {
2383   GtkListStore *list_store = (GtkListStore *) sortable;
2384
2385   g_return_if_fail (GTK_IS_LIST_STORE (sortable));
2386
2387   if (list_store->default_sort_destroy)
2388     {
2389       GtkDestroyNotify d = list_store->default_sort_destroy;
2390
2391       list_store->default_sort_destroy = NULL;
2392       d (list_store->default_sort_data);
2393     }
2394
2395   list_store->default_sort_func = func;
2396   list_store->default_sort_data = data;
2397   list_store->default_sort_destroy = destroy;
2398 }
2399
2400 static gboolean
2401 gtk_list_store_has_default_sort_func (GtkTreeSortable *sortable)
2402 {
2403   GtkListStore *list_store = (GtkListStore *) sortable;
2404
2405   g_return_val_if_fail (GTK_IS_LIST_STORE (sortable), FALSE);
2406
2407   return (list_store->default_sort_func != NULL);
2408 }