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