]> Pileus Git - ~andy/gtk/blob - gtk/gtkliststore.c
Document 2.2 API additions.
[~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  * Since: 2.2
1378  **/
1379 gboolean
1380 gtk_list_store_iter_is_valid (GtkListStore *list_store,
1381                               GtkTreeIter  *iter)
1382 {
1383   GList *list;
1384
1385   g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), FALSE);
1386   g_return_val_if_fail (iter != NULL, FALSE);
1387
1388   if (!VALID_ITER (iter, list_store))
1389     return FALSE;
1390
1391   if (iter->user_data == list_store->root)
1392     return TRUE;
1393   if (iter->user_data == list_store->tail)
1394     return TRUE;
1395
1396   for (list = ((GList *)list_store->root)->next; list; list = list->next)
1397     if (list == iter->user_data)
1398       return TRUE;
1399
1400   return FALSE;
1401 }
1402
1403 static gboolean
1404 gtk_list_store_drag_data_delete (GtkTreeDragSource *drag_source,
1405                                  GtkTreePath       *path)
1406 {
1407   GtkTreeIter iter;
1408   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE);
1409
1410   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source),
1411                                &iter,
1412                                path))
1413     {
1414       gtk_list_store_remove (GTK_LIST_STORE (drag_source), &iter);
1415       return TRUE;
1416     }
1417   return FALSE;
1418 }
1419
1420 static gboolean
1421 gtk_list_store_drag_data_get (GtkTreeDragSource *drag_source,
1422                               GtkTreePath       *path,
1423                               GtkSelectionData  *selection_data)
1424 {
1425   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE);
1426
1427   /* Note that we don't need to handle the GTK_TREE_MODEL_ROW
1428    * target, because the default handler does it for us, but
1429    * we do anyway for the convenience of someone maybe overriding the
1430    * default handler.
1431    */
1432
1433   if (gtk_tree_set_row_drag_data (selection_data,
1434                                   GTK_TREE_MODEL (drag_source),
1435                                   path))
1436     {
1437       return TRUE;
1438     }
1439   else
1440     {
1441       /* FIXME handle text targets at least. */
1442     }
1443
1444   return FALSE;
1445 }
1446
1447 static gboolean
1448 gtk_list_store_drag_data_received (GtkTreeDragDest   *drag_dest,
1449                                    GtkTreePath       *dest,
1450                                    GtkSelectionData  *selection_data)
1451 {
1452   GtkTreeModel *tree_model;
1453   GtkListStore *list_store;
1454   GtkTreeModel *src_model = NULL;
1455   GtkTreePath *src_path = NULL;
1456   gboolean retval = FALSE;
1457
1458   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE);
1459
1460   tree_model = GTK_TREE_MODEL (drag_dest);
1461   list_store = GTK_LIST_STORE (drag_dest);
1462
1463   if (gtk_tree_get_row_drag_data (selection_data,
1464                                   &src_model,
1465                                   &src_path) &&
1466       src_model == tree_model)
1467     {
1468       /* Copy the given row to a new position */
1469       GtkTreeIter src_iter;
1470       GtkTreeIter dest_iter;
1471       GtkTreePath *prev;
1472
1473       if (!gtk_tree_model_get_iter (src_model,
1474                                     &src_iter,
1475                                     src_path))
1476         {
1477           goto out;
1478         }
1479
1480       /* Get the path to insert _after_ (dest is the path to insert _before_) */
1481       prev = gtk_tree_path_copy (dest);
1482
1483       if (!gtk_tree_path_prev (prev))
1484         {
1485           /* dest was the first spot in the list; which means we are supposed
1486            * to prepend.
1487            */
1488           gtk_list_store_prepend (GTK_LIST_STORE (tree_model),
1489                                   &dest_iter);
1490
1491           retval = TRUE;
1492         }
1493       else
1494         {
1495           if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model),
1496                                        &dest_iter,
1497                                        prev))
1498             {
1499               GtkTreeIter tmp_iter = dest_iter;
1500
1501               if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tree_model), "gtk-tree-model-drop-append")))
1502                 gtk_list_store_append (GTK_LIST_STORE (tree_model), &dest_iter);
1503               else
1504                 gtk_list_store_insert_after (GTK_LIST_STORE (tree_model),
1505                                              &dest_iter, &tmp_iter);
1506
1507               retval = TRUE;
1508             }
1509         }
1510
1511       g_object_set_data (G_OBJECT (tree_model), "gtk-tree-model-drop-append",
1512                          NULL);
1513
1514       gtk_tree_path_free (prev);
1515
1516       /* If we succeeded in creating dest_iter, copy data from src
1517        */
1518       if (retval)
1519         {
1520           GtkTreeDataList *dl = G_SLIST (src_iter.user_data)->data;
1521           GtkTreeDataList *copy_head = NULL;
1522           GtkTreeDataList *copy_prev = NULL;
1523           GtkTreeDataList *copy_iter = NULL;
1524           GtkTreePath *path;
1525           gint col;
1526
1527           col = 0;
1528           while (dl)
1529             {
1530               copy_iter = _gtk_tree_data_list_node_copy (dl,
1531                                                          list_store->column_headers[col]);
1532
1533               if (copy_head == NULL)
1534                 copy_head = copy_iter;
1535
1536               if (copy_prev)
1537                 copy_prev->next = copy_iter;
1538
1539               copy_prev = copy_iter;
1540
1541               dl = dl->next;
1542               ++col;
1543             }
1544
1545           dest_iter.stamp = GTK_LIST_STORE (tree_model)->stamp;
1546           G_SLIST (dest_iter.user_data)->data = copy_head;
1547
1548           path = gtk_list_store_get_path (GTK_TREE_MODEL (tree_model), &dest_iter);
1549           gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_model), path, &dest_iter);
1550           gtk_tree_path_free (path);
1551         }
1552     }
1553   else
1554     {
1555       /* FIXME maybe add some data targets eventually, or handle text
1556        * targets in the simple case.
1557        */
1558     }
1559
1560  out:
1561
1562   if (src_path)
1563     gtk_tree_path_free (src_path);
1564
1565   return retval;
1566 }
1567
1568 static gboolean
1569 gtk_list_store_row_drop_possible (GtkTreeDragDest  *drag_dest,
1570                                   GtkTreePath      *dest_path,
1571                                   GtkSelectionData *selection_data)
1572 {
1573   gint *indices;
1574   GtkTreeModel *src_model = NULL;
1575   GtkTreePath *src_path = NULL;
1576   gboolean retval = FALSE;
1577
1578   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE);
1579
1580   /* don't accept drops if the list has been sorted */
1581   if (GTK_LIST_STORE_IS_SORTED (drag_dest))
1582     return FALSE;
1583
1584   if (!gtk_tree_get_row_drag_data (selection_data,
1585                                    &src_model,
1586                                    &src_path))
1587     goto out;
1588     
1589   if (src_model != GTK_TREE_MODEL (drag_dest))
1590     goto out;
1591
1592   if (gtk_tree_path_get_depth (dest_path) != 1)
1593     goto out;
1594
1595   /* can drop before any existing node, or before one past any existing. */
1596
1597   indices = gtk_tree_path_get_indices (dest_path);
1598
1599   if (indices[0] <= GTK_LIST_STORE (drag_dest)->length)
1600     retval = TRUE;
1601
1602  out:
1603   gtk_tree_path_free (src_path);
1604   
1605   return retval;
1606 }
1607
1608 /* Sorting and reordering */
1609 typedef struct _SortTuple
1610 {
1611   gint offset;
1612   GSList *el;
1613 } SortTuple;
1614
1615 /* Reordering */
1616 static gint
1617 gtk_list_store_reorder_func (gconstpointer a,
1618                              gconstpointer b,
1619                              gpointer      user_data)
1620 {
1621   SortTuple *a_reorder;
1622   SortTuple *b_reorder;
1623
1624   a_reorder = (SortTuple *)a;
1625   b_reorder = (SortTuple *)b;
1626
1627   if (a_reorder->offset < b_reorder->offset)
1628     return -1;
1629   if (a_reorder->offset > b_reorder->offset)
1630     return 1;
1631
1632   return 0;
1633 }
1634
1635 /**
1636  * gtk_list_store_reorder:
1637  * @store: A #GtkTreeStore.
1638  * @new_order: An integer array indicating the new order for the list.
1639  *
1640  * Reorders @store to follow the order indicated by @new_order. Note that
1641  * this function only works with unsorted stores.
1642  *
1643  * Since: 2.2
1644  **/
1645 void
1646 gtk_list_store_reorder (GtkListStore *store,
1647                         gint         *new_order)
1648 {
1649   gint i;
1650   GSList *current_list;
1651   GtkTreePath *path;
1652   SortTuple *sort_array;
1653
1654   g_return_if_fail (GTK_IS_LIST_STORE (store));
1655   g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1656   g_return_if_fail (new_order != NULL);
1657
1658   sort_array = g_new (SortTuple, store->length);
1659
1660   current_list = store->root;
1661
1662   for (i = 0; i < store->length; i++)
1663     {
1664       sort_array[i].offset = new_order[i];
1665       sort_array[i].el = current_list;
1666
1667       current_list = current_list->next;
1668     }
1669
1670   g_qsort_with_data (sort_array,
1671                      store->length,
1672                      sizeof (SortTuple),
1673                      gtk_list_store_reorder_func,
1674                      NULL);
1675
1676   for (i = 0; i < store->length - 1; i++)
1677     G_SLIST (sort_array[i].el)->next = G_SLIST (sort_array[i+1].el);
1678
1679   store->root = G_SLIST (sort_array[0].el);
1680   store->tail = G_SLIST (sort_array[store->length-1].el);
1681   G_SLIST (store->tail)->next = NULL;
1682
1683   /* emit signal */
1684   path = gtk_tree_path_new ();
1685   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store),
1686                                  path, NULL, new_order);
1687   gtk_tree_path_free (path);
1688   g_free (sort_array);
1689 }
1690
1691 /**
1692  * gtk_list_store_swap:
1693  * @store: A #GtkListStore.
1694  * @a: A #GtkTreeIter.
1695  * @b: Another #GtkTreeIter.
1696  *
1697  * Swaps @a and @b in @store. Note that this function only works with
1698  * unsorted stores.
1699  *
1700  * Since: 2.2
1701  **/
1702 void
1703 gtk_list_store_swap (GtkListStore *store,
1704                      GtkTreeIter  *a,
1705                      GtkTreeIter  *b)
1706 {
1707   GSList *i, *prev_a = NULL, *prev_b = NULL;
1708   gint j, a_count = 0, b_count = 0, *order;
1709   GtkTreePath *path;
1710
1711   g_return_if_fail (GTK_IS_LIST_STORE (store));
1712   g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1713   g_return_if_fail (VALID_ITER (a, store));
1714   g_return_if_fail (VALID_ITER (b, store));
1715
1716   if (a->user_data == b->user_data)
1717     return;
1718
1719   if (a->user_data == store->root)
1720     prev_a = NULL;
1721   else
1722     {
1723       for (i = store->root; i; i = i->next, a_count++)
1724         if (i->next == a->user_data)
1725           {
1726             prev_a = i;
1727             break;
1728           }
1729
1730       a_count++;
1731     }
1732
1733   if (b->user_data == store->root)
1734     prev_b = NULL;
1735   else
1736     {
1737       for (i = store->root; i; i = i->next, b_count++)
1738         if (i->next == b->user_data)
1739           {
1740             prev_b = i;
1741             break;
1742           }
1743
1744       b_count++;
1745     }
1746
1747   if (!prev_a)
1748     store->root = b->user_data;
1749   else
1750     prev_a->next = b->user_data;
1751
1752   if (!prev_b)
1753     store->root = a->user_data;
1754   else
1755     prev_b->next = a->user_data;
1756
1757   /* think a_next inspead of a_prev here ... */
1758   prev_a = G_SLIST (a->user_data)->next;
1759   prev_b = G_SLIST (b->user_data)->next;
1760
1761   G_SLIST (a->user_data)->next = prev_b;
1762   G_SLIST (b->user_data)->next = prev_a;
1763
1764   /* emit signal */
1765   order = g_new (gint, store->length);
1766   for (j = 0; j < store->length; j++)
1767     if (j == a_count)
1768       order[j] = b_count;
1769     else if (j == b_count)
1770       order[j] = a_count;
1771     else
1772       order[j] = j;
1773
1774   path = gtk_tree_path_new ();
1775   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store),
1776                                  path, NULL, order);
1777   gtk_tree_path_free (path);
1778   g_free (order);
1779 }
1780
1781 static void
1782 gtk_list_store_move (GtkListStore *store,
1783                      GtkTreeIter  *iter,
1784                      GtkTreeIter  *position,
1785                      gboolean      before)
1786 {
1787   GtkTreeIter dst_a;
1788   GSList *i, *a, *prev = NULL, *tmp;
1789   gint new_pos = 0, old_pos = 0, j = 0, *order;
1790   GtkTreePath *path, *pos_path = NULL;
1791
1792   g_return_if_fail (GTK_IS_LIST_STORE (store));
1793   g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1794   g_return_if_fail (VALID_ITER (iter, store));
1795   if (position)
1796     g_return_if_fail (VALID_ITER (position, store));
1797
1798   /* lots of sanity checks */
1799   if (position)
1800     {
1801       path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), iter);
1802       pos_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), position);
1803
1804       if (gtk_tree_path_get_depth (pos_path) != 1)
1805         goto free_paths_and_out;
1806
1807       /* if before:
1808        *   moving the iter before path or "path + 1" doesn't make sense
1809        * else
1810        *   moving the iter before path or "path - 1" doesn't make sense
1811        */
1812       if (!gtk_tree_path_compare (path, pos_path))
1813         goto free_paths_and_out;
1814
1815       if (before)
1816         gtk_tree_path_next (path);
1817       else
1818         gtk_tree_path_prev (path);
1819
1820       if (!gtk_tree_path_compare (path, pos_path))
1821         goto free_paths_and_out;
1822
1823       gtk_tree_path_free (path);
1824     }
1825
1826   /* getting destination iters */
1827   if (before && position)
1828     {
1829       if (gtk_tree_path_get_indices (pos_path)[0] > 0)
1830         {
1831           gtk_tree_path_prev (pos_path);
1832           if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &dst_a, pos_path))
1833             a = G_SLIST (dst_a.user_data);
1834           else
1835             a = NULL;
1836           gtk_tree_path_next (pos_path);
1837         }
1838       else
1839         a = NULL;
1840     }
1841   else if (before && !position)
1842     a = NULL;
1843   else /* !before */
1844     {
1845       if (position)
1846         a = G_SLIST (position->user_data);
1847       else
1848         a = NULL;
1849     }
1850
1851   /* getting the old prev node */
1852   if (iter->user_data == store->root)
1853     prev = NULL;
1854   else
1855     {
1856       for (i = store->root; i; i = i->next, old_pos++)
1857         if (i->next == iter->user_data)
1858           {
1859             prev = i;
1860             break;
1861           }
1862
1863       old_pos++;
1864     }
1865
1866   /* remove node */
1867   if (!prev)
1868     store->root = G_SLIST (iter->user_data)->next;
1869   else
1870     prev->next = G_SLIST (iter->user_data)->next;
1871
1872   /* and reinsert it */
1873   if (a)
1874     {
1875       tmp = a->next;
1876
1877       a->next = G_SLIST (iter->user_data);
1878       a->next->next = tmp;
1879     }
1880   else if (!a && !before)
1881     {
1882       tmp = G_SLIST (store->root);
1883
1884       store->root = G_SLIST (iter->user_data);
1885       G_SLIST (store->root)->next = tmp;
1886     }
1887   else if (!a && before)
1888     {
1889       G_SLIST (store->tail)->next = G_SLIST (iter->user_data);
1890       G_SLIST (iter->user_data)->next = NULL;
1891       store->tail = iter->user_data;
1892     }
1893
1894   /* emit signal */
1895   if (position)
1896     new_pos = gtk_tree_path_get_indices (pos_path)[0];
1897   else if (before)
1898     new_pos = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL) - 1;
1899   else
1900     new_pos = 0;
1901
1902   if (new_pos > old_pos)
1903     {
1904       if (before)
1905         new_pos--;
1906     }
1907   else
1908     {
1909       if (!before)
1910         new_pos++;
1911     }
1912
1913   order = g_new (gint, store->length);
1914   if (new_pos > old_pos)
1915     {
1916       for (j = 0; j < store->length; j++)
1917         if (j < old_pos)
1918           order[j] = j;
1919         else if (j >= old_pos && j < new_pos)
1920           order[j] = j + 1;
1921         else if (j == new_pos)
1922           order[j] = old_pos;
1923         else
1924           order[j] = j;
1925     }
1926   else
1927     {
1928       for (j = 0; j < store->length; j++)
1929         if (j == new_pos)
1930           order[j] = old_pos;
1931         else if (j > new_pos && j <= old_pos)
1932           order[j] = j - 1;
1933         else
1934           order[j] = j;
1935     }
1936
1937   path = gtk_tree_path_new ();
1938   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store),
1939                                  path, NULL, order);
1940   gtk_tree_path_free (path);
1941   if (position)
1942     gtk_tree_path_free (pos_path);
1943   g_free (order);
1944
1945   return;
1946
1947 free_paths_and_out:
1948   gtk_tree_path_free (path);
1949   gtk_tree_path_free (pos_path);
1950 }
1951
1952 /**
1953  * gtk_list_store_move_before:
1954  * @store: A #GtkListStore.
1955  * @iter: A #GtkTreeIter.
1956  * @position: A #GtkTreeIter, or %NULL.
1957  *
1958  * Moves @iter in @store to the position before @position. Note that this
1959  * function only works with unsorted stores. If @position is %NULL, @iter
1960  * will be moved to the end of the list.
1961  *
1962  * Since: 2.2
1963  **/
1964 void
1965 gtk_list_store_move_before (GtkListStore *store,
1966                             GtkTreeIter  *iter,
1967                             GtkTreeIter  *position)
1968 {
1969   gtk_list_store_move (store, iter, position, TRUE);
1970 }
1971
1972 /**
1973  * gtk_list_store_move_after:
1974  * @store: A #GtkListStore.
1975  * @iter: A #GtkTreeIter.
1976  * @position: A #GtkTreeIter or %NULL.
1977  *
1978  * Moves @iter in @store to the position after @position. Note that this
1979  * function only works with unsorted stores. If @position is %NULL, @iter
1980  * will be moved to the start of the list.
1981  *
1982  * Since: 2.2
1983  **/
1984 void
1985 gtk_list_store_move_after (GtkListStore *store,
1986                            GtkTreeIter  *iter,
1987                            GtkTreeIter  *position)
1988 {
1989   gtk_list_store_move (store, iter, position, FALSE);
1990 }
1991
1992 /* Sorting */
1993 static gint
1994 gtk_list_store_compare_func (gconstpointer a,
1995                              gconstpointer b,
1996                              gpointer      user_data)
1997 {
1998   GtkListStore *list_store = user_data;
1999   GSList *el_a; /* Los Angeles? */
2000   GSList *el_b;
2001   GtkTreeIter iter_a;
2002   GtkTreeIter iter_b;
2003   gint retval;
2004   GtkTreeIterCompareFunc func;
2005   gpointer data;
2006
2007
2008   if (list_store->sort_column_id != -1)
2009     {
2010       GtkTreeDataSortHeader *header;
2011
2012       header = _gtk_tree_data_list_get_header (list_store->sort_list,
2013                                                list_store->sort_column_id);
2014       g_return_val_if_fail (header != NULL, 0);
2015       g_return_val_if_fail (header->func != NULL, 0);
2016
2017       func = header->func;
2018       data = header->data;
2019     }
2020   else
2021     {
2022       g_return_val_if_fail (list_store->default_sort_func != NULL, 0);
2023       func = list_store->default_sort_func;
2024       data = list_store->default_sort_data;
2025     }
2026
2027   el_a = ((SortTuple *) a)->el;
2028   el_b = ((SortTuple *) b)->el;
2029
2030   iter_a.stamp = list_store->stamp;
2031   iter_a.user_data = el_a;
2032   iter_b.stamp = list_store->stamp;
2033   iter_b.user_data = el_b;
2034
2035   retval = (* func) (GTK_TREE_MODEL (list_store), &iter_a, &iter_b, data);
2036
2037   if (list_store->order == GTK_SORT_DESCENDING)
2038     {
2039       if (retval > 0)
2040         retval = -1;
2041       else if (retval < 0)
2042         retval = 1;
2043     }
2044   return retval;
2045 }
2046
2047 static void
2048 gtk_list_store_sort (GtkListStore *list_store)
2049 {
2050   GArray *sort_array;
2051   gint i;
2052   gint *new_order;
2053   GSList *list;
2054   GtkTreePath *path;
2055
2056   if (list_store->length <= 1)
2057     return;
2058
2059   g_assert (GTK_LIST_STORE_IS_SORTED (list_store));
2060
2061   list = G_SLIST (list_store->root);
2062
2063   sort_array = g_array_sized_new (FALSE, FALSE,
2064                                   sizeof (SortTuple),
2065                                   list_store->length);
2066
2067   for (i = 0; i < list_store->length; i++)
2068     {
2069       SortTuple tuple;
2070
2071       /* If this fails, we are in an inconsistent state.  Bad */
2072       g_return_if_fail (list != NULL);
2073
2074       tuple.offset = i;
2075       tuple.el = list;
2076       g_array_append_val (sort_array, tuple);
2077
2078       list = list->next;
2079     }
2080
2081   g_array_sort_with_data (sort_array, gtk_list_store_compare_func, list_store);
2082
2083   for (i = 0; i < list_store->length - 1; i++)
2084       g_array_index (sort_array, SortTuple, i).el->next =
2085         g_array_index (sort_array, SortTuple, i + 1).el;
2086   g_array_index (sort_array, SortTuple, list_store->length - 1).el->next = NULL;
2087   list_store->root = g_array_index (sort_array, SortTuple, 0).el;
2088   list_store->tail = g_array_index (sort_array, SortTuple, list_store->length - 1).el;
2089
2090   /* Let the world know about our new order */
2091   new_order = g_new (gint, list_store->length);
2092   for (i = 0; i < list_store->length; i++)
2093     new_order[i] = g_array_index (sort_array, SortTuple, i).offset;
2094
2095   path = gtk_tree_path_new ();
2096   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (list_store),
2097                                  path, NULL, new_order);
2098   gtk_tree_path_free (path);
2099   g_free (new_order);
2100   g_array_free (sort_array, TRUE);
2101 }
2102
2103 static void
2104 gtk_list_store_sort_iter_changed (GtkListStore *list_store,
2105                                   GtkTreeIter  *iter,
2106                                   gint          column)
2107
2108 {
2109   GSList *prev = NULL;
2110   GSList *next = NULL;
2111   GSList *list = G_SLIST (list_store->root);
2112   GtkTreePath *tmp_path;
2113   GtkTreeIter tmp_iter;
2114   gint cmp_a = 0;
2115   gint cmp_b = 0;
2116   gint i;
2117   gint old_location;
2118   gint new_location;
2119   gint *new_order;
2120   GtkTreeIterCompareFunc func;
2121   gpointer data;
2122
2123   if (list_store->length < 2)
2124     return;
2125
2126   tmp_iter.stamp = list_store->stamp;
2127
2128   if (list_store->sort_column_id != -1)
2129     {
2130       GtkTreeDataSortHeader *header;
2131       header = _gtk_tree_data_list_get_header (list_store->sort_list,
2132                                                list_store->sort_column_id);
2133       g_return_if_fail (header != NULL);
2134       g_return_if_fail (header->func != NULL);
2135       func = header->func;
2136       data = header->data;
2137     }
2138   else
2139     {
2140       g_return_if_fail (list_store->default_sort_func != NULL);
2141       func = list_store->default_sort_func;
2142       data = list_store->default_sort_data;
2143     }
2144
2145   /* If it's the built in function, we don't sort. */
2146   if (func == gtk_tree_data_list_compare_func &&
2147       list_store->sort_column_id != column)
2148     return;
2149
2150   old_location = 0;
2151   /* First we find the iter, its prev, and its next */
2152   while (list)
2153     {
2154       if (list == G_SLIST (iter->user_data))
2155         break;
2156       prev = list;
2157       list = list->next;
2158       old_location++;
2159     }
2160   g_assert (list != NULL);
2161
2162   next = list->next;
2163
2164   /* Check the common case, where we don't need to sort it moved. */
2165   if (prev != NULL)
2166     {
2167       tmp_iter.user_data = prev;
2168       cmp_a = (* func) (GTK_TREE_MODEL (list_store), &tmp_iter, iter, data);
2169     }
2170
2171   if (next != NULL)
2172     {
2173       tmp_iter.user_data = next;
2174       cmp_b = (* func) (GTK_TREE_MODEL (list_store), iter, &tmp_iter, data);
2175     }
2176
2177   if (list_store->order == GTK_SORT_DESCENDING)
2178     {
2179       if (cmp_a < 0)
2180         cmp_a = 1;
2181       else if (cmp_a > 0)
2182         cmp_a = -1;
2183
2184       if (cmp_b < 0)
2185         cmp_b = 1;
2186       else if (cmp_b > 0)
2187         cmp_b = -1;
2188     }
2189
2190   if (prev == NULL && cmp_b <= 0)
2191     return;
2192   else if (next == NULL && cmp_a <= 0)
2193     return;
2194   else if (prev != NULL && next != NULL &&
2195            cmp_a <= 0 && cmp_b <= 0)
2196     return;
2197
2198   /* We actually need to sort it */
2199   /* First, remove the old link. */
2200
2201   if (prev == NULL)
2202     list_store->root = next;
2203   else
2204     prev->next = next;
2205   if (next == NULL)
2206     list_store->tail = prev;
2207   list->next = NULL;
2208   
2209   /* FIXME: as an optimization, we can potentially start at next */
2210   prev = NULL;
2211   list = G_SLIST (list_store->root);
2212   new_location = 0;
2213   tmp_iter.user_data = list;
2214   if (list_store->order == GTK_SORT_DESCENDING)
2215     cmp_a = (* func) (GTK_TREE_MODEL (list_store), &tmp_iter, iter, data);
2216   else
2217     cmp_a = (* func) (GTK_TREE_MODEL (list_store), iter, &tmp_iter, data);
2218
2219   while ((list->next) && (cmp_a > 0))
2220     {
2221       prev = list;
2222       list = list->next;
2223       new_location++;
2224       tmp_iter.user_data = list;
2225       if (list_store->order == GTK_SORT_DESCENDING)
2226         cmp_a = (* func) (GTK_TREE_MODEL (list_store), &tmp_iter, iter, data);
2227       else
2228         cmp_a = (* func) (GTK_TREE_MODEL (list_store), iter, &tmp_iter, data);
2229     }
2230
2231   if ((!list->next) && (cmp_a > 0))
2232     {
2233       new_location++;
2234       list->next = G_SLIST (iter->user_data);
2235       list_store->tail = list->next;
2236     }
2237   else if (prev)
2238     {
2239       prev->next = G_SLIST (iter->user_data);
2240       G_SLIST (iter->user_data)->next = list;
2241     }
2242   else
2243     {
2244       G_SLIST (iter->user_data)->next = G_SLIST (list_store->root);
2245       list_store->root = G_SLIST (iter->user_data);
2246     }
2247
2248   /* Emit the reordered signal. */
2249   new_order = g_new (int, list_store->length);
2250   if (old_location < new_location)
2251     for (i = 0; i < list_store->length; i++)
2252       {
2253         if (i < old_location ||
2254             i > new_location)
2255           new_order[i] = i;
2256         else if (i >= old_location &&
2257                  i < new_location)
2258           new_order[i] = i + 1;
2259         else if (i == new_location)
2260           new_order[i] = old_location;
2261       }
2262   else
2263     for (i = 0; i < list_store->length; i++)
2264       {
2265         if (i < new_location ||
2266             i > old_location)
2267           new_order[i] = i;
2268         else if (i > new_location &&
2269                  i <= old_location)
2270           new_order[i] = i - 1;
2271         else if (i == new_location)
2272           new_order[i] = old_location;
2273       }
2274
2275   tmp_path = gtk_tree_path_new ();
2276   tmp_iter.user_data = NULL;
2277
2278   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (list_store),
2279                                  tmp_path, NULL,
2280                                  new_order);
2281   gtk_tree_path_free (tmp_path);
2282   g_free (new_order);
2283 }
2284
2285 static gboolean
2286 gtk_list_store_get_sort_column_id (GtkTreeSortable  *sortable,
2287                                    gint             *sort_column_id,
2288                                    GtkSortType      *order)
2289 {
2290   GtkListStore *list_store = (GtkListStore *) sortable;
2291
2292   g_return_val_if_fail (GTK_IS_LIST_STORE (sortable), FALSE);
2293
2294   if (list_store->sort_column_id == -1)
2295     return FALSE;
2296
2297   if (sort_column_id)
2298     * sort_column_id = list_store->sort_column_id;
2299   if (order)
2300     * order = list_store->order;
2301   return TRUE;
2302 }
2303
2304 static void
2305 gtk_list_store_set_sort_column_id (GtkTreeSortable  *sortable,
2306                                    gint              sort_column_id,
2307                                    GtkSortType       order)
2308 {
2309   GtkListStore *list_store = (GtkListStore *) sortable;
2310
2311   g_return_if_fail (GTK_IS_LIST_STORE (sortable));
2312
2313   if ((list_store->sort_column_id == sort_column_id) &&
2314       (list_store->order == order))
2315     return;
2316
2317   if (sort_column_id != -1)
2318     {
2319       GtkTreeDataSortHeader *header = NULL;
2320
2321       header = _gtk_tree_data_list_get_header (list_store->sort_list, sort_column_id);
2322
2323       /* We want to make sure that we have a function */
2324       g_return_if_fail (header != NULL);
2325       g_return_if_fail (header->func != NULL);
2326     }
2327   else
2328     {
2329       g_return_if_fail (list_store->default_sort_func != NULL);
2330     }
2331
2332
2333   list_store->sort_column_id = sort_column_id;
2334   list_store->order = order;
2335
2336   gtk_list_store_sort (list_store);
2337
2338   gtk_tree_sortable_sort_column_changed (sortable);
2339 }
2340
2341 static void
2342 gtk_list_store_set_sort_func (GtkTreeSortable        *sortable,
2343                               gint                    sort_column_id,
2344                               GtkTreeIterCompareFunc  func,
2345                               gpointer                data,
2346                               GtkDestroyNotify        destroy)
2347 {
2348   GtkListStore *list_store = (GtkListStore *) sortable;
2349   GtkTreeDataSortHeader *header = NULL;
2350   GList *list;
2351
2352   g_return_if_fail (GTK_IS_LIST_STORE (sortable));
2353   g_return_if_fail (func != NULL);
2354
2355   for (list = list_store->sort_list; list; list = list->next)
2356     {
2357       GtkTreeDataSortHeader *list_header;
2358
2359       list_header = (GtkTreeDataSortHeader*) list->data;
2360       if (list_header->sort_column_id == sort_column_id)
2361         {
2362           header = list_header;
2363           break;
2364         }
2365     }
2366
2367   if (header == NULL)
2368     {
2369       header = g_new0 (GtkTreeDataSortHeader, 1);
2370       header->sort_column_id = sort_column_id;
2371       list_store->sort_list = g_list_append (list_store->sort_list, header);
2372     }
2373
2374   if (header->destroy)
2375     {
2376       GtkDestroyNotify d = header->destroy;
2377
2378       header->destroy = NULL;
2379       d (header->data);
2380     }
2381
2382   header->func = func;
2383   header->data = data;
2384   header->destroy = destroy;
2385 }
2386
2387
2388 static void
2389 gtk_list_store_set_default_sort_func (GtkTreeSortable        *sortable,
2390                                       GtkTreeIterCompareFunc  func,
2391                                       gpointer                data,
2392                                       GtkDestroyNotify        destroy)
2393 {
2394   GtkListStore *list_store = (GtkListStore *) sortable;
2395
2396   g_return_if_fail (GTK_IS_LIST_STORE (sortable));
2397
2398   if (list_store->default_sort_destroy)
2399     {
2400       GtkDestroyNotify d = list_store->default_sort_destroy;
2401
2402       list_store->default_sort_destroy = NULL;
2403       d (list_store->default_sort_data);
2404     }
2405
2406   list_store->default_sort_func = func;
2407   list_store->default_sort_data = data;
2408   list_store->default_sort_destroy = destroy;
2409 }
2410
2411 static gboolean
2412 gtk_list_store_has_default_sort_func (GtkTreeSortable *sortable)
2413 {
2414   GtkListStore *list_store = (GtkListStore *) sortable;
2415
2416   g_return_val_if_fail (GTK_IS_LIST_STORE (sortable), FALSE);
2417
2418   return (list_store->default_sort_func != NULL);
2419 }