]> Pileus Git - ~andy/gtk/blob - gtk/gtkliststore.c
Stop being stupid and emitting the signal every time.
[~andy/gtk] / gtk / gtkliststore.c
1 /* gtkliststore.c
2  * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <string.h>
21 #include "gtktreemodel.h"
22 #include "gtkliststore.h"
23 #include "gtktreedatalist.h"
24 #include "gtksignal.h"
25 #include "gtktreednd.h"
26 #include <gobject/gvaluecollector.h>
27
28 #define G_SLIST(x) ((GSList *) x)
29 #define GTK_LIST_STORE_IS_SORTED(list) (GTK_LIST_STORE (list)->sort_column_id != -2)
30 #define VALID_ITER(iter, list_store) (iter!= NULL && iter->user_data != NULL && list_store->stamp == iter->stamp)
31
32 static void         gtk_list_store_init            (GtkListStore      *list_store);
33 static void         gtk_list_store_class_init      (GtkListStoreClass *class);
34 static void         gtk_list_store_tree_model_init (GtkTreeModelIface *iface);
35 static void         gtk_list_store_drag_source_init(GtkTreeDragSourceIface *iface);
36 static void         gtk_list_store_drag_dest_init  (GtkTreeDragDestIface   *iface);
37 static void         gtk_list_store_sortable_init   (GtkTreeSortableIface   *iface);
38 static guint        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                                                    GtkTreeModel      *src_model,
87                                                    GtkTreePath       *src_path,
88                                                    GtkTreePath       *dest_path);
89
90
91 /* sortable */
92 static void     gtk_list_store_sort                  (GtkListStore           *list_store);
93 static void     gtk_list_store_sort_iter_changed     (GtkListStore           *list_store,
94                                                       GtkTreeIter            *iter,
95                                                       gint                    column);
96 static gboolean gtk_list_store_get_sort_column_id    (GtkTreeSortable        *sortable,
97                                                       gint                   *sort_column_id,
98                                                       GtkSortType            *order);
99 static void     gtk_list_store_set_sort_column_id    (GtkTreeSortable        *sortable,
100                                                       gint                    sort_column_id,
101                                                       GtkSortType             order);
102 static void     gtk_list_store_set_sort_func         (GtkTreeSortable        *sortable,
103                                                       gint                    sort_column_id,
104                                                       GtkTreeIterCompareFunc  func,
105                                                       gpointer                data,
106                                                       GtkDestroyNotify        destroy);
107 static void     gtk_list_store_set_default_sort_func (GtkTreeSortable        *sortable,
108                                                       GtkTreeIterCompareFunc  func,
109                                                       gpointer                data,
110                                                       GtkDestroyNotify        destroy);
111 static gboolean gtk_list_store_has_default_sort_func (GtkTreeSortable        *sortable);
112
113
114
115 static void
116 validate_list_store (GtkListStore *list_store)
117 {
118   if (gtk_debug_flags & GTK_DEBUG_TREE)
119     {
120       g_assert (g_slist_length (list_store->root) == list_store->length);
121
122       g_assert (g_slist_last (list_store->root) == list_store->tail);
123     }
124 }
125
126 GtkType
127 gtk_list_store_get_type (void)
128 {
129   static GType list_store_type = 0;
130
131   if (!list_store_type)
132     {
133       static const GTypeInfo list_store_info =
134       {
135         sizeof (GtkListStoreClass),
136         NULL,           /* base_init */
137         NULL,           /* base_finalize */
138         (GClassInitFunc) gtk_list_store_class_init,
139         NULL,           /* class_finalize */
140         NULL,           /* class_data */
141         sizeof (GtkListStore),
142         0,
143         (GInstanceInitFunc) gtk_list_store_init,
144       };
145
146       static const GInterfaceInfo tree_model_info =
147       {
148         (GInterfaceInitFunc) gtk_list_store_tree_model_init,
149         NULL,
150         NULL
151       };
152
153       static const GInterfaceInfo drag_source_info =
154       {
155         (GInterfaceInitFunc) gtk_list_store_drag_source_init,
156         NULL,
157         NULL
158       };
159
160       static const GInterfaceInfo drag_dest_info =
161       {
162         (GInterfaceInitFunc) gtk_list_store_drag_dest_init,
163         NULL,
164         NULL
165       };
166
167       static const GInterfaceInfo sortable_info =
168       {
169         (GInterfaceInitFunc) gtk_list_store_sortable_init,
170         NULL,
171         NULL
172       };
173
174       list_store_type = g_type_register_static (G_TYPE_OBJECT, "GtkListStore", &list_store_info, 0);
175       g_type_add_interface_static (list_store_type,
176                                    GTK_TYPE_TREE_MODEL,
177                                    &tree_model_info);
178       g_type_add_interface_static (list_store_type,
179                                    GTK_TYPE_TREE_DRAG_SOURCE,
180                                    &drag_source_info);
181       g_type_add_interface_static (list_store_type,
182                                    GTK_TYPE_TREE_DRAG_DEST,
183                                    &drag_dest_info);
184       g_type_add_interface_static (list_store_type,
185                                    GTK_TYPE_TREE_SORTABLE,
186                                    &sortable_info);
187     }
188
189   return list_store_type;
190 }
191
192 static void
193 gtk_list_store_class_init (GtkListStoreClass *class)
194 {
195   GObjectClass *object_class;
196
197   object_class = (GObjectClass*) class;
198 }
199
200 static void
201 gtk_list_store_tree_model_init (GtkTreeModelIface *iface)
202 {
203   iface->get_flags = gtk_list_store_get_flags;
204   iface->get_n_columns = gtk_list_store_get_n_columns;
205   iface->get_column_type = gtk_list_store_get_column_type;
206   iface->get_iter = gtk_list_store_get_iter;
207   iface->get_path = gtk_list_store_get_path;
208   iface->get_value = gtk_list_store_get_value;
209   iface->iter_next = gtk_list_store_iter_next;
210   iface->iter_children = gtk_list_store_iter_children;
211   iface->iter_has_child = gtk_list_store_iter_has_child;
212   iface->iter_n_children = gtk_list_store_iter_n_children;
213   iface->iter_nth_child = gtk_list_store_iter_nth_child;
214   iface->iter_parent = gtk_list_store_iter_parent;
215 }
216
217 static void
218 gtk_list_store_drag_source_init (GtkTreeDragSourceIface *iface)
219 {
220   iface->drag_data_delete = gtk_list_store_drag_data_delete;
221   iface->drag_data_get = gtk_list_store_drag_data_get;
222 }
223
224 static void
225 gtk_list_store_drag_dest_init (GtkTreeDragDestIface *iface)
226 {
227   iface->drag_data_received = gtk_list_store_drag_data_received;
228   iface->row_drop_possible = gtk_list_store_row_drop_possible;
229 }
230
231 static void
232 gtk_list_store_sortable_init (GtkTreeSortableIface *iface)
233 {
234   iface->get_sort_column_id = gtk_list_store_get_sort_column_id;
235   iface->set_sort_column_id = gtk_list_store_set_sort_column_id;
236   iface->set_sort_func = gtk_list_store_set_sort_func;
237   iface->set_default_sort_func = gtk_list_store_set_default_sort_func;
238   iface->has_default_sort_func = gtk_list_store_has_default_sort_func;
239 }
240
241 static void
242 gtk_list_store_init (GtkListStore *list_store)
243 {
244   list_store->root = NULL;
245   list_store->tail = NULL;
246   list_store->sort_list = NULL;
247   list_store->stamp = g_random_int ();
248   list_store->length = 0;
249   list_store->sort_column_id = -2;
250 }
251
252 /**
253  * gtk_list_store_new:
254  * @n_columns: number of columns in the list store
255  * @Varargs: all #GType types for the columns, from first to last
256  *
257  * Creates a new list store as with @n_columns columns each of the types passed
258  * in.  As an example, gtk_tree_store_new (3, G_TYPE_INT, G_TYPE_STRING,
259  * GDK_TYPE_PIXBUF); will create a new GtkListStore with three columns, of type
260  * int, string and GDkPixbuf respectively.
261  *
262  * Return value: a new #GtkListStore
263  **/
264 GtkListStore *
265 gtk_list_store_new (gint n_columns,
266                                ...)
267 {
268   GtkListStore *retval;
269   va_list args;
270   gint i;
271
272   g_return_val_if_fail (n_columns > 0, NULL);
273
274   retval = GTK_LIST_STORE (g_object_new (gtk_list_store_get_type (), NULL));
275   gtk_list_store_set_n_columns (retval, n_columns);
276
277   va_start (args, n_columns);
278
279   for (i = 0; i < n_columns; i++)
280     {
281       GType type = va_arg (args, GType);
282       if (! _gtk_tree_data_list_check_type (type))
283         {
284           g_warning ("%s: Invalid type %s passed to gtk_list_store_new\n", G_STRLOC, g_type_name (type));
285           g_object_unref (G_OBJECT (retval));
286           return NULL;
287         }
288
289       gtk_list_store_set_column_type (retval, i, type);
290     }
291
292   va_end (args);
293
294   return retval;
295 }
296
297
298 /**
299  * gtk_list_store_newv:
300  * @n_columns: number of columns in the list store
301  * @types: an array of #GType types for the columns, from first to last
302  *
303  * Non vararg creation function.  Used primarily by language bindings.
304  *
305  * Return value: a new #GtkListStore
306  **/
307 GtkListStore *
308 gtk_list_store_newv (gint   n_columns,
309                      GType *types)
310 {
311   GtkListStore *retval;
312   gint i;
313
314   g_return_val_if_fail (n_columns > 0, NULL);
315
316   retval = GTK_LIST_STORE (g_object_new (gtk_list_store_get_type (), NULL));
317   gtk_list_store_set_n_columns (retval, n_columns);
318
319   for (i = 0; i < n_columns; i++)
320     {
321       if (! _gtk_tree_data_list_check_type (types[i]))
322         {
323           g_warning ("%s: Invalid type %s passed to gtk_list_store_newv\n", G_STRLOC, g_type_name (types[i]));
324           g_object_unref (G_OBJECT (retval));
325           return NULL;
326         }
327
328       gtk_list_store_set_column_type (retval, i, types[i]);
329     }
330
331   return retval;
332 }
333
334 static void
335 gtk_list_store_set_n_columns (GtkListStore *list_store,
336                               gint          n_columns)
337 {
338   GType *new_columns;
339
340   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
341   g_return_if_fail (n_columns > 0);
342
343   if (list_store->n_columns == n_columns)
344     return;
345
346   new_columns = g_new0 (GType, n_columns);
347   if (list_store->column_headers)
348     {
349       /* copy the old header orders over */
350       if (n_columns >= list_store->n_columns)
351         memcpy (new_columns, list_store->column_headers, list_store->n_columns * sizeof (gchar *));
352       else
353         memcpy (new_columns, list_store->column_headers, n_columns * sizeof (GType));
354
355       g_free (list_store->column_headers);
356     }
357
358   if (list_store->sort_list)
359     _gtk_tree_data_list_header_free (list_store->sort_list);
360
361   list_store->sort_list = _gtk_tree_data_list_header_new (n_columns, list_store->column_headers);
362
363   list_store->column_headers = new_columns;
364   list_store->n_columns = n_columns;
365 }
366
367 static void
368 gtk_list_store_set_column_type (GtkListStore *list_store,
369                                 gint          column,
370                                 GType         type)
371 {
372   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
373   g_return_if_fail (column >=0 && column < list_store->n_columns);
374   if (!_gtk_tree_data_list_check_type (type))
375     {
376       g_warning ("%s: Invalid type %s passed to gtk_list_store_set_column_type\n", G_STRLOC, g_type_name (type));
377       return;
378     }
379
380   list_store->column_headers[column] = type;
381 }
382
383 /* Fulfill the GtkTreeModel requirements */
384 static guint
385 gtk_list_store_get_flags (GtkTreeModel *tree_model)
386 {
387   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), 0);
388
389   return GTK_TREE_MODEL_ITERS_PERSIST | GTK_TREE_MODEL_LIST_ONLY;
390 }
391
392 static gint
393 gtk_list_store_get_n_columns (GtkTreeModel *tree_model)
394 {
395   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), 0);
396
397   return GTK_LIST_STORE (tree_model)->n_columns;
398 }
399
400 static GType
401 gtk_list_store_get_column_type (GtkTreeModel *tree_model,
402                                 gint          index)
403 {
404   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), G_TYPE_INVALID);
405   g_return_val_if_fail (index < GTK_LIST_STORE (tree_model)->n_columns &&
406                         index >= 0, G_TYPE_INVALID);
407
408   return GTK_LIST_STORE (tree_model)->column_headers[index];
409 }
410
411 static gboolean
412 gtk_list_store_get_iter (GtkTreeModel *tree_model,
413                          GtkTreeIter  *iter,
414                          GtkTreePath  *path)
415 {
416   GSList *list;
417   gint i;
418
419   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
420   g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
421
422   i = gtk_tree_path_get_indices (path)[0];
423
424   if (i >= GTK_LIST_STORE (tree_model)->length)
425     return FALSE;
426
427   list = g_slist_nth (G_SLIST (GTK_LIST_STORE (tree_model)->root), i);
428
429   /* If this fails, list_store->length has gotten mangled. */
430   g_assert (list);
431
432   iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
433   iter->user_data = list;
434   return TRUE;
435 }
436
437 static GtkTreePath *
438 gtk_list_store_get_path (GtkTreeModel *tree_model,
439                          GtkTreeIter  *iter)
440 {
441   GtkTreePath *retval;
442   GSList *list;
443   gint i = 0;
444
445   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), NULL);
446   g_return_val_if_fail (iter->stamp == GTK_LIST_STORE (tree_model)->stamp, NULL);
447
448   for (list = G_SLIST (GTK_LIST_STORE (tree_model)->root); list; list = list->next)
449     {
450       if (list == G_SLIST (iter->user_data))
451         break;
452       i++;
453     }
454   if (list == NULL)
455     return NULL;
456
457   retval = gtk_tree_path_new ();
458   gtk_tree_path_append_index (retval, i);
459   return retval;
460 }
461
462 static void
463 gtk_list_store_get_value (GtkTreeModel *tree_model,
464                           GtkTreeIter  *iter,
465                           gint          column,
466                           GValue       *value)
467 {
468   GtkTreeDataList *list;
469   gint tmp_column = column;
470
471   g_return_if_fail (GTK_IS_LIST_STORE (tree_model));
472   g_return_if_fail (column < GTK_LIST_STORE (tree_model)->n_columns);
473   g_return_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp);
474
475   list = G_SLIST (iter->user_data)->data;
476
477   while (tmp_column-- > 0 && list)
478     list = list->next;
479
480   if (list == NULL)
481     g_value_init (value, GTK_LIST_STORE (tree_model)->column_headers[column]);
482   else
483     _gtk_tree_data_list_node_to_value (list,
484                                        GTK_LIST_STORE (tree_model)->column_headers[column],
485                                        value);
486 }
487
488 static gboolean
489 gtk_list_store_iter_next (GtkTreeModel  *tree_model,
490                           GtkTreeIter   *iter)
491 {
492   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
493   g_return_val_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp, FALSE);
494
495   iter->user_data = G_SLIST (iter->user_data)->next;
496
497   return (iter->user_data != NULL);
498 }
499
500 static gboolean
501 gtk_list_store_iter_children (GtkTreeModel *tree_model,
502                               GtkTreeIter  *iter,
503                               GtkTreeIter  *parent)
504 {
505   /* this is a list, nodes have no children */
506   if (parent)
507     return FALSE;
508
509   /* but if parent == NULL we return the list itself as children of the
510    * "root"
511    */
512
513   if (GTK_LIST_STORE (tree_model)->root)
514     {
515       iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
516       iter->user_data = GTK_LIST_STORE (tree_model)->root;
517       return TRUE;
518     }
519   else
520     return FALSE;
521 }
522
523 static gboolean
524 gtk_list_store_iter_has_child (GtkTreeModel *tree_model,
525                                GtkTreeIter  *iter)
526 {
527   return FALSE;
528 }
529
530 static gint
531 gtk_list_store_iter_n_children (GtkTreeModel *tree_model,
532                                 GtkTreeIter  *iter)
533 {
534   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), -1);
535   if (iter == NULL)
536     return GTK_LIST_STORE (tree_model)->length;
537
538   g_return_val_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp, -1);
539   return 0;
540 }
541
542 static gboolean
543 gtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
544                                GtkTreeIter  *iter,
545                                GtkTreeIter  *parent,
546                                gint          n)
547 {
548   GSList *child;
549
550   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
551
552   if (parent)
553     return FALSE;
554
555   child = g_slist_nth (G_SLIST (GTK_LIST_STORE (tree_model)->root), n);
556
557   if (child)
558     {
559       iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
560       iter->user_data = child;
561       return TRUE;
562     }
563   else
564     return FALSE;
565 }
566
567 static gboolean
568 gtk_list_store_iter_parent (GtkTreeModel *tree_model,
569                             GtkTreeIter  *iter,
570                             GtkTreeIter  *child)
571 {
572   return FALSE;
573 }
574
575 gboolean
576 gtk_list_store_real_set_value (GtkListStore *list_store,
577                                GtkTreeIter  *iter,
578                                gint          column,
579                                GValue       *value)
580 {
581   GtkTreeDataList *list;
582   GtkTreeDataList *prev;
583   GtkTreePath *path;
584   GValue real_value = {0, };
585   gboolean converted = FALSE;
586   gint orig_column = column;
587   gboolean retval = FALSE;
588
589   g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), FALSE);
590   g_return_val_if_fail (VALID_ITER (iter, list_store), FALSE);
591   g_return_val_if_fail (column >= 0 && column < list_store->n_columns, FALSE);
592   g_return_val_if_fail (G_IS_VALUE (value), FALSE);
593
594   if (! g_type_is_a (G_VALUE_TYPE (value), list_store->column_headers[column]))
595     {
596       if (! (g_value_type_compatible (G_VALUE_TYPE (value), list_store->column_headers[column]) &&
597              g_value_type_compatible (list_store->column_headers[column], G_VALUE_TYPE (value))))
598         {
599           g_warning ("%s: Unable to convert from %s to %s\n",
600                      G_STRLOC,
601                      g_type_name (G_VALUE_TYPE (value)),
602                      g_type_name (list_store->column_headers[column]));
603           return retval;
604         }
605       if (!g_value_transform (value, &real_value))
606         {
607           g_warning ("%s: Unable to make conversion from %s to %s\n",
608                      G_STRLOC,
609                      g_type_name (G_VALUE_TYPE (value)),
610                      g_type_name (list_store->column_headers[column]));
611           g_value_unset (&real_value);
612           return retval;
613         }
614       converted = TRUE;
615     }
616
617   prev = list = G_SLIST (iter->user_data)->data;
618
619   while (list != NULL)
620     {
621       if (column == 0)
622         {
623           path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
624           if (converted)
625             _gtk_tree_data_list_value_to_node (list, &real_value);
626           else
627             _gtk_tree_data_list_value_to_node (list, value);
628           retval = TRUE;
629           gtk_tree_path_free (path);
630           if (converted)
631             g_value_unset (&real_value);
632           return retval;
633         }
634
635       column--;
636       prev = list;
637       list = list->next;
638     }
639
640   if (G_SLIST (iter->user_data)->data == NULL)
641     {
642       G_SLIST (iter->user_data)->data = list = _gtk_tree_data_list_alloc ();
643       list->next = NULL;
644     }
645   else
646     {
647       list = prev->next = _gtk_tree_data_list_alloc ();
648       list->next = NULL;
649     }
650
651   while (column != 0)
652     {
653       list->next = _gtk_tree_data_list_alloc ();
654       list = list->next;
655       list->next = NULL;
656       column --;
657     }
658
659   path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
660   if (converted)
661     _gtk_tree_data_list_value_to_node (list, &real_value);
662   else
663     _gtk_tree_data_list_value_to_node (list, value);
664   retval = TRUE;
665   gtk_tree_path_free (path);
666   if (converted)
667     g_value_unset (&real_value);
668
669   if (GTK_LIST_STORE_IS_SORTED (list_store))
670     gtk_list_store_sort_iter_changed (list_store, iter, orig_column);
671
672   return retval;
673 }
674
675
676 /**
677  * gtk_list_store_set_value:
678  * @list_store: A #GtkListStore
679  * @iter: A valid #GtkTreeIter for the row being modified
680  * @column: column number to modify
681  * @value: new value for the cell
682  *
683  * Sets the data in the cell specified by @iter and @column.
684  * The type of @value must be convertible to the type of the
685  * column.
686  *
687  **/
688 void
689 gtk_list_store_set_value (GtkListStore *list_store,
690                           GtkTreeIter  *iter,
691                           gint          column,
692                           GValue       *value)
693 {
694   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
695   g_return_if_fail (VALID_ITER (iter, list_store));
696   g_return_if_fail (column >= 0 && column < list_store->n_columns);
697   g_return_if_fail (G_IS_VALUE (value));
698
699   if (gtk_list_store_real_set_value (list_store, iter, column, value))
700     {
701       GtkTreePath *path;
702
703       path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_store), iter);
704       gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
705       gtk_tree_path_free (path);
706     }
707 }
708
709 /**
710  * gtk_list_store_set_valist:
711  * @list_store: A #GtkListStore
712  * @iter: A valid #GtkTreeIter for the row being modified
713  * @var_args: va_list of column/value pairs
714  *
715  * See @gtk_list_store_set; this version takes a va_list for use by language
716  * bindings.
717  *
718  **/
719 void
720 gtk_list_store_set_valist (GtkListStore *list_store,
721                            GtkTreeIter  *iter,
722                            va_list       var_args)
723 {
724   gint column;
725   gboolean emit_signal = FALSE;
726
727   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
728   g_return_if_fail (VALID_ITER (iter, list_store));
729
730   column = va_arg (var_args, gint);
731
732   while (column != -1)
733     {
734       GValue value = { 0, };
735       gchar *error = NULL;
736
737       if (column >= list_store->n_columns)
738         {
739           g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column);
740           break;
741         }
742       g_value_init (&value, list_store->column_headers[column]);
743
744       G_VALUE_COLLECT (&value, var_args, 0, &error);
745       if (error)
746         {
747           g_warning ("%s: %s", G_STRLOC, error);
748           g_free (error);
749
750           /* we purposely leak the value here, it might not be
751            * in a sane state if an error condition occoured
752            */
753           break;
754         }
755
756       /* FIXME: instead of calling this n times, refactor with above */
757       emit_signal = gtk_list_store_real_set_value (list_store,
758                                                    iter,
759                                                    column,
760                                                    &value) || emit_signal;
761
762       g_value_unset (&value);
763
764       column = va_arg (var_args, gint);
765     }
766
767   if (emit_signal)
768     {
769       GtkTreePath *path;
770
771       path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_store), iter);
772       gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
773       gtk_tree_path_free (path);
774     }
775 }
776
777 /**
778  * gtk_list_store_set:
779  * @list_store: a #GtkListStore
780  * @iter: row iterator
781  * @Varargs: pairs of column number and value, terminated with -1
782  *
783  * Sets the value of one or more cells in the row referenced by @iter.
784  * The variable argument list should contain integer column numbers,
785  * each column number followed by the value to be set.
786  * The list is terminated by a -1. For example, to set column 0 with type
787  * %G_TYPE_STRING to "Foo", you would write gtk_list_store_set (store, iter,
788  * 0, "Foo", -1).
789  **/
790 void
791 gtk_list_store_set (GtkListStore *list_store,
792                     GtkTreeIter  *iter,
793                     ...)
794 {
795   va_list var_args;
796
797   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
798   g_return_if_fail (iter != NULL);
799   g_return_if_fail (iter->stamp == list_store->stamp);
800
801   va_start (var_args, iter);
802   gtk_list_store_set_valist (list_store, iter, var_args);
803   va_end (var_args);
804 }
805
806 static GSList*
807 remove_link_saving_prev (GSList  *list,
808                          GSList  *link,
809                          GSList **prevp)
810 {
811   GSList *tmp;
812   GSList *prev;
813
814   prev = NULL;
815   tmp = list;
816
817   while (tmp)
818     {
819       if (tmp == link)
820         {
821           if (prev)
822             prev->next = link->next;
823
824           if (list == link)
825             list = list->next;
826
827           link->next = NULL;
828           break;
829         }
830
831       prev = tmp;
832       tmp = tmp->next;
833     }
834
835   *prevp = prev;
836
837   return list;
838 }
839
840 static void
841 gtk_list_store_remove_silently (GtkListStore *list_store,
842                                 GtkTreeIter  *iter,
843                                 GtkTreePath  *path)
844 {
845   if (G_SLIST (iter->user_data)->data)
846     {
847       _gtk_tree_data_list_free ((GtkTreeDataList *) G_SLIST (iter->user_data)->data,
848                                 list_store->column_headers);
849       G_SLIST (iter->user_data)->data = NULL;
850     }
851
852   {
853     GSList *prev = NULL;
854
855     list_store->root = remove_link_saving_prev (G_SLIST (list_store->root),
856                                                 G_SLIST (iter->user_data),
857                                                 &prev);
858
859     list_store->length -= 1;
860
861     if (iter->user_data == list_store->tail)
862       list_store->tail = prev;
863   }
864
865   list_store->stamp ++;
866 }
867
868 /**
869  * gtk_list_store_remove:
870  * @list_store: A #GtkListStore
871  * @iter: A valid #GtkTreeIter
872  *
873  * Removes the given row from the list store.  After being removed, @iter is set to be the next valid row, or invalidated if it pointed to the last row inn @list_store
874  *
875  **/
876 void
877 gtk_list_store_remove (GtkListStore *list_store,
878                        GtkTreeIter  *iter)
879 {
880   GtkTreePath *path;
881   GSList *next;
882
883   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
884   g_return_if_fail (VALID_ITER (iter, list_store));
885
886   next = G_SLIST (iter->user_data)->next;
887   path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
888
889   validate_list_store (list_store);
890
891   gtk_list_store_remove_silently (list_store, iter, path);
892
893   validate_list_store (list_store);
894
895   list_store->stamp ++;
896   gtk_tree_model_row_deleted (GTK_TREE_MODEL (list_store), path);
897   gtk_tree_path_free (path);
898
899   if (next)
900     {
901       iter->stamp = list_store->stamp;
902       iter->user_data = next;
903     }
904   else
905     {
906       iter->stamp = 0;
907     }
908 }
909
910 static void
911 insert_after (GtkListStore *list_store,
912               GSList       *sibling,
913               GSList       *new_list)
914 {
915   g_return_if_fail (sibling != NULL);
916   g_return_if_fail (new_list != NULL);
917
918   /* insert new node after list */
919   new_list->next = sibling->next;
920   sibling->next = new_list;
921
922   /* if list was the tail, the new node is the new tail */
923   if (sibling == ((GSList *) list_store->tail))
924     list_store->tail = new_list;
925
926   list_store->length += 1;
927 }
928
929 /**
930  * gtk_list_store_insert:
931  * @list_store: A #GtkListStore
932  * @iter: An unset #GtkTreeIter to set to the new row
933  * @position: position to insert the new row
934  *
935  * Creates a new row at @position.  @iter will be changed to point to this new
936  * row.  If @position is larger than the number of rows on the list, then the
937  * new row will be appended to the list.  The row will be empty before this
938  * function is called.  To fill in values, you need to call @gtk_list_store_set
939  * or @gtk_list_store_set_value.
940  *
941  **/
942 void
943 gtk_list_store_insert (GtkListStore *list_store,
944                        GtkTreeIter  *iter,
945                        gint          position)
946 {
947   GSList *list;
948   GtkTreePath *path;
949   GSList *new_list;
950
951   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
952   g_return_if_fail (iter != NULL);
953   g_return_if_fail (position >= 0);
954
955   if (position == 0 ||
956       GTK_LIST_STORE_IS_SORTED (list_store))
957     {
958       gtk_list_store_prepend (list_store, iter);
959       return;
960     }
961
962   new_list = g_slist_alloc ();
963
964   list = g_slist_nth (G_SLIST (list_store->root), position - 1);
965
966   if (list == NULL)
967     {
968       g_warning ("%s: position %d is off the end of the list\n", G_STRLOC, position);
969       return;
970     }
971
972   insert_after (list_store, list, new_list);
973
974   iter->stamp = list_store->stamp;
975   iter->user_data = new_list;
976
977   validate_list_store (list_store);
978
979   path = gtk_tree_path_new ();
980   gtk_tree_path_append_index (path, position);
981   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
982   gtk_tree_path_free (path);
983 }
984
985 /**
986  * gtk_list_store_insert_before:
987  * @list_store: A #GtkListStore
988  * @iter: An unset #GtkTreeIter to set to the new row
989  * @sibling: A valid #GtkTreeIter, or %NULL
990  *
991  * Inserts a new row before @sibling.  If @sibling is %NULL, then the row will be
992  * appended to the beginning of the list.  @iter will be changed to point to
993  * this new row.  The row will be empty before this function is called.  To fill
994  * in values, you need to call @gtk_list_store_set or @gtk_list_store_set_value.
995  *
996  **/
997 void
998 gtk_list_store_insert_before (GtkListStore *list_store,
999                               GtkTreeIter  *iter,
1000                               GtkTreeIter  *sibling)
1001 {
1002   GtkTreePath *path;
1003   GSList *list, *prev, *new_list;
1004   gint i = 0;
1005
1006   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1007   g_return_if_fail (iter != NULL);
1008   if (sibling)
1009     g_return_if_fail (VALID_ITER (sibling, list_store));
1010
1011
1012   if (GTK_LIST_STORE_IS_SORTED (list_store))
1013     {
1014       gtk_list_store_prepend (list_store, iter);
1015       return;
1016     }
1017
1018   if (sibling == NULL)
1019     {
1020       gtk_list_store_append (list_store, iter);
1021       return;
1022     }
1023
1024   new_list = g_slist_alloc ();
1025
1026   prev = NULL;
1027   list = list_store->root;
1028   while (list && list != sibling->user_data)
1029     {
1030       prev = list;
1031       list = list->next;
1032       i++;
1033     }
1034
1035   if (list != sibling->user_data)
1036     {
1037       g_warning ("%s: sibling iterator invalid? not found in the list", G_STRLOC);
1038       return;
1039     }
1040
1041   /* if there are no nodes, we become the list tail, otherwise we
1042    * are inserting before any existing nodes so we can't change
1043    * the tail
1044    */
1045
1046   if (list_store->root == NULL)
1047     list_store->tail = new_list;
1048
1049   if (prev)
1050     {
1051       new_list->next = prev->next;
1052       prev->next = new_list;
1053     }
1054   else
1055     {
1056       new_list->next = list_store->root;
1057       list_store->root = new_list;
1058     }
1059
1060   iter->stamp = list_store->stamp;
1061   iter->user_data = new_list;
1062
1063   list_store->length += 1;
1064
1065   validate_list_store (list_store);
1066
1067   path = gtk_tree_path_new ();
1068   gtk_tree_path_append_index (path, i);
1069   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1070   gtk_tree_path_free (path);
1071 }
1072
1073 /**
1074  * gtk_list_store_insert_after:
1075  * @list_store: A #GtkListStore
1076  * @iter: An unset #GtkTreeIter to set to the new row
1077  * @sibling: A valid #GtkTreeIter, or %NULL
1078  *
1079  * Inserts a new row after @sibling.  If @sibling is %NULL, then the row will be
1080  * prepended to the beginning of the list.  @iter will be changed to point to
1081  * this new row.  The row will be empty after this function is called.  To fill
1082  * in values, you need to call @gtk_list_store_set or @gtk_list_store_set_value.
1083  *
1084  **/
1085 void
1086 gtk_list_store_insert_after (GtkListStore *list_store,
1087                              GtkTreeIter  *iter,
1088                              GtkTreeIter  *sibling)
1089 {
1090   GtkTreePath *path;
1091   GSList *list, *new_list;
1092   gint i = 0;
1093
1094   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1095   g_return_if_fail (iter != NULL);
1096   if (sibling)
1097     g_return_if_fail (VALID_ITER (sibling, list_store));
1098
1099   if (sibling == NULL ||
1100       GTK_LIST_STORE_IS_SORTED (list_store))
1101     {
1102       gtk_list_store_prepend (list_store, iter);
1103       return;
1104     }
1105
1106   for (list = list_store->root; list && list != sibling->user_data; list = list->next)
1107     i++;
1108
1109   g_return_if_fail (list == sibling->user_data);
1110
1111   new_list = g_slist_alloc ();
1112
1113   insert_after (list_store, list, new_list);
1114
1115   iter->stamp = list_store->stamp;
1116   iter->user_data = new_list;
1117
1118   validate_list_store (list_store);
1119
1120   path = gtk_tree_path_new ();
1121   gtk_tree_path_append_index (path, i);
1122   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1123   gtk_tree_path_free (path);
1124 }
1125
1126 /**
1127  * gtk_list_store_prepend:
1128  * @list_store: A #GtkListStore
1129  * @iter: An unset #GtkTreeIter to set to the prepend row
1130  *
1131  * Prepend a new row to @list_store.  @iter will be changed to point to this new
1132  * row.  The row will be empty after this function is called.  To fill in
1133  * values, you need to call @gtk_list_store_set or @gtk_list_store_set_value.
1134  *
1135  **/
1136 void
1137 gtk_list_store_prepend (GtkListStore *list_store,
1138                         GtkTreeIter  *iter)
1139 {
1140   GtkTreePath *path;
1141
1142   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1143   g_return_if_fail (iter != NULL);
1144
1145   iter->stamp = list_store->stamp;
1146   iter->user_data = g_slist_alloc ();
1147
1148   if (list_store->root == NULL)
1149     list_store->tail = iter->user_data;
1150
1151   G_SLIST (iter->user_data)->next = G_SLIST (list_store->root);
1152   list_store->root = iter->user_data;
1153
1154   list_store->length += 1;
1155
1156   validate_list_store (list_store);
1157
1158   path = gtk_tree_path_new ();
1159   gtk_tree_path_append_index (path, 0);
1160   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1161   gtk_tree_path_free (path);
1162 }
1163
1164 /**
1165  * gtk_list_store_append:
1166  * @list_store: A #GtkListStore
1167  * @iter: An unset #GtkTreeIter to set to the appended row
1168  *
1169  * Appends a new row to @list_store.  @iter will be changed to point to this new
1170  * row.  The row will be empty after this function is called.  To fill in
1171  * values, you need to call @gtk_list_store_set or @gtk_list_store_set_value.
1172  *
1173  **/
1174 void
1175 gtk_list_store_append (GtkListStore *list_store,
1176                        GtkTreeIter  *iter)
1177 {
1178   GtkTreePath *path;
1179
1180   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1181   g_return_if_fail (iter != NULL);
1182
1183   if (GTK_LIST_STORE_IS_SORTED (list_store))
1184     {
1185       gtk_list_store_prepend (list_store, iter);
1186       return;
1187     }
1188
1189   iter->stamp = list_store->stamp;
1190   iter->user_data = g_slist_alloc ();
1191
1192   if (list_store->tail)
1193     ((GSList *)list_store->tail)->next = iter->user_data;
1194   else
1195     list_store->root = iter->user_data;
1196
1197   list_store->tail = iter->user_data;
1198
1199   list_store->length += 1;
1200
1201   validate_list_store (list_store);
1202
1203   path = gtk_tree_path_new ();
1204   gtk_tree_path_append_index (path, list_store->length - 1);
1205   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1206   gtk_tree_path_free (path);
1207 }
1208
1209 void
1210 gtk_list_store_clear (GtkListStore *list_store)
1211 {
1212   GtkTreeIter iter;
1213   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1214
1215   while (list_store->root)
1216     {
1217       iter.stamp = list_store->stamp;
1218       iter.user_data = list_store->root;
1219       gtk_list_store_remove (list_store, &iter);
1220     }
1221 }
1222
1223
1224 static gboolean
1225 gtk_list_store_drag_data_delete (GtkTreeDragSource *drag_source,
1226                                  GtkTreePath       *path)
1227 {
1228   GtkTreeIter iter;
1229   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE);
1230
1231   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source),
1232                                &iter,
1233                                path))
1234     {
1235       gtk_list_store_remove (GTK_LIST_STORE (drag_source), &iter);
1236       return TRUE;
1237     }
1238   return FALSE;
1239 }
1240
1241 static gboolean
1242 gtk_list_store_drag_data_get (GtkTreeDragSource *drag_source,
1243                               GtkTreePath       *path,
1244                               GtkSelectionData  *selection_data)
1245 {
1246   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE);
1247
1248   /* Note that we don't need to handle the GTK_TREE_MODEL_ROW
1249    * target, because the default handler does it for us, but
1250    * we do anyway for the convenience of someone maybe overriding the
1251    * default handler.
1252    */
1253
1254   if (gtk_selection_data_set_tree_row (selection_data,
1255                                        GTK_TREE_MODEL (drag_source),
1256                                        path))
1257     {
1258       return TRUE;
1259     }
1260   else
1261     {
1262       /* FIXME handle text targets at least. */
1263     }
1264
1265   return FALSE;
1266 }
1267
1268 static gboolean
1269 gtk_list_store_drag_data_received (GtkTreeDragDest   *drag_dest,
1270                                    GtkTreePath       *dest,
1271                                    GtkSelectionData  *selection_data)
1272 {
1273   GtkTreeModel *tree_model;
1274   GtkListStore *list_store;
1275   GtkTreeModel *src_model = NULL;
1276   GtkTreePath *src_path = NULL;
1277   gboolean retval = FALSE;
1278
1279   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE);
1280
1281   tree_model = GTK_TREE_MODEL (drag_dest);
1282   list_store = GTK_LIST_STORE (drag_dest);
1283
1284   if (gtk_selection_data_get_tree_row (selection_data,
1285                                        &src_model,
1286                                        &src_path) &&
1287       src_model == tree_model)
1288     {
1289       /* Copy the given row to a new position */
1290       GtkTreeIter src_iter;
1291       GtkTreeIter dest_iter;
1292       GtkTreePath *prev;
1293
1294       if (!gtk_tree_model_get_iter (src_model,
1295                                     &src_iter,
1296                                     src_path))
1297         {
1298           goto out;
1299         }
1300
1301       /* Get the path to insert _after_ (dest is the path to insert _before_) */
1302       prev = gtk_tree_path_copy (dest);
1303
1304       if (!gtk_tree_path_prev (prev))
1305         {
1306           /* dest was the first spot in the list; which means we are supposed
1307            * to prepend.
1308            */
1309           gtk_list_store_prepend (GTK_LIST_STORE (tree_model),
1310                                   &dest_iter);
1311
1312           retval = TRUE;
1313         }
1314       else
1315         {
1316           if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model),
1317                                        &dest_iter,
1318                                        prev))
1319             {
1320               GtkTreeIter tmp_iter = dest_iter;
1321               gtk_list_store_insert_after (GTK_LIST_STORE (tree_model),
1322                                            &dest_iter,
1323                                            &tmp_iter);
1324               retval = TRUE;
1325             }
1326         }
1327
1328       gtk_tree_path_free (prev);
1329
1330       /* If we succeeded in creating dest_iter, copy data from src
1331        */
1332       if (retval)
1333         {
1334           GtkTreeDataList *dl = G_SLIST (src_iter.user_data)->data;
1335           GtkTreeDataList *copy_head = NULL;
1336           GtkTreeDataList *copy_prev = NULL;
1337           GtkTreeDataList *copy_iter = NULL;
1338           GtkTreePath *path;
1339           gint col;
1340
1341           col = 0;
1342           while (dl)
1343             {
1344               copy_iter = _gtk_tree_data_list_node_copy (dl,
1345                                                          list_store->column_headers[col]);
1346
1347               if (copy_head == NULL)
1348                 copy_head = copy_iter;
1349
1350               if (copy_prev)
1351                 copy_prev->next = copy_iter;
1352
1353               copy_prev = copy_iter;
1354
1355               dl = dl->next;
1356               ++col;
1357             }
1358
1359           dest_iter.stamp = GTK_LIST_STORE (tree_model)->stamp;
1360           G_SLIST (dest_iter.user_data)->data = copy_head;
1361
1362           path = gtk_list_store_get_path (GTK_TREE_MODEL (tree_model), &dest_iter);
1363           gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_model), path, &dest_iter);
1364           gtk_tree_path_free (path);
1365         }
1366     }
1367   else
1368     {
1369       /* FIXME maybe add some data targets eventually, or handle text
1370        * targets in the simple case.
1371        */
1372     }
1373
1374  out:
1375
1376   if (src_path)
1377     gtk_tree_path_free (src_path);
1378
1379   return retval;
1380 }
1381
1382 static gboolean
1383 gtk_list_store_row_drop_possible (GtkTreeDragDest *drag_dest,
1384                                   GtkTreeModel    *src_model,
1385                                   GtkTreePath     *src_path,
1386                                   GtkTreePath     *dest_path)
1387 {
1388   gint *indices;
1389
1390   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE);
1391
1392   if (src_model != GTK_TREE_MODEL (drag_dest))
1393     return FALSE;
1394
1395   if (gtk_tree_path_get_depth (dest_path) != 1)
1396     return FALSE;
1397
1398   /* can drop before any existing node, or before one past any existing. */
1399
1400   indices = gtk_tree_path_get_indices (dest_path);
1401
1402   if (indices[0] <= GTK_LIST_STORE (drag_dest)->length)
1403     return TRUE;
1404   else
1405     return FALSE;
1406 }
1407
1408
1409 /* Sorting */
1410 typedef struct _SortTuple
1411 {
1412   gint offset;
1413   GSList *el;
1414 } SortTuple;
1415
1416 static gint
1417 gtk_list_store_compare_func (gconstpointer a,
1418                              gconstpointer b,
1419                              gpointer      user_data)
1420 {
1421   GtkListStore *list_store = user_data;
1422   GSList *el_a; /* Los Angeles? */
1423   GSList *el_b;
1424   GtkTreeIter iter_a;
1425   GtkTreeIter iter_b;
1426   gint retval;
1427   GtkTreeIterCompareFunc func;
1428   gpointer data;
1429
1430
1431   if (list_store->sort_column_id != -1)
1432     {
1433       GtkTreeDataSortHeader *header;
1434
1435       header = _gtk_tree_data_list_get_header (list_store->sort_list,
1436                                                list_store->sort_column_id);
1437       g_return_val_if_fail (header != NULL, 0);
1438       g_return_val_if_fail (header->func != NULL, 0);
1439
1440       func = header->func;
1441       data = header->data;
1442     }
1443   else
1444     {
1445       g_return_val_if_fail (list_store->default_sort_func != NULL, 0);
1446       func = list_store->default_sort_func;
1447       data = list_store->default_sort_data;
1448     }
1449
1450   el_a = ((SortTuple *) a)->el;
1451   el_b = ((SortTuple *) b)->el;
1452
1453   iter_a.stamp = list_store->stamp;
1454   iter_a.user_data = el_a;
1455   iter_b.stamp = list_store->stamp;
1456   iter_b.user_data = el_b;
1457
1458   retval = (* func) (GTK_TREE_MODEL (list_store), &iter_a, &iter_b, data);
1459
1460   if (list_store->order == GTK_SORT_DESCENDING)
1461     {
1462       if (retval > 0)
1463         retval = -1;
1464       else if (retval < 0)
1465         retval = 1;
1466     }
1467   return retval;
1468 }
1469
1470 static void
1471 gtk_list_store_sort (GtkListStore *list_store)
1472 {
1473   GtkTreeIter iter;
1474   GArray *sort_array;
1475   gint i;
1476   gint *new_order;
1477   GSList *list;
1478   GtkTreePath *path;
1479
1480   if (list_store->length <= 1)
1481     return;
1482
1483   g_assert (GTK_LIST_STORE_IS_SORTED (list_store));
1484
1485   list = G_SLIST (list_store->root);
1486
1487   sort_array = g_array_sized_new (FALSE, FALSE,
1488                                   sizeof (SortTuple),
1489                                   list_store->length);
1490
1491   for (i = 0; i < list_store->length; i++)
1492     {
1493       SortTuple tuple;
1494
1495       /* If this fails, we are in an inconsistent state.  Bad */
1496       g_return_if_fail (list != NULL);
1497
1498       tuple.offset = i;
1499       tuple.el = list;
1500       g_array_append_val (sort_array, tuple);
1501
1502       list = list->next;
1503     }
1504
1505   g_array_sort_with_data (sort_array, gtk_list_store_compare_func, list_store);
1506
1507   for (i = 0; i < list_store->length - 1; i++)
1508       g_array_index (sort_array, SortTuple, i).el->next =
1509         g_array_index (sort_array, SortTuple, i + 1).el;
1510   g_array_index (sort_array, SortTuple, list_store->length - 1).el->next = NULL;
1511   list_store->root = g_array_index (sort_array, SortTuple, 0).el;
1512
1513   /* Let the world know about our new order */
1514   new_order = g_new (gint, list_store->length);
1515   for (i = 0; i < list_store->length; i++)
1516     new_order[i] = g_array_index (sort_array, SortTuple, i).offset;
1517   path = gtk_tree_path_new ();
1518   iter.stamp = list_store->stamp;
1519   iter.user_data = NULL;
1520   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (list_store),
1521                                  path, &iter, new_order);
1522   gtk_tree_path_free (path);
1523   g_free (new_order);
1524   g_array_free (sort_array, TRUE);
1525 }
1526
1527 static void
1528 gtk_list_store_sort_iter_changed (GtkListStore *list_store,
1529                                   GtkTreeIter  *iter,
1530                                   gint          column)
1531
1532 {
1533   GSList *prev = NULL;
1534   GSList *next = NULL;
1535   GSList *list = G_SLIST (list_store->root);
1536   GtkTreePath *tmp_path;
1537   GtkTreeIter tmp_iter;
1538   gint cmp_a = 0;
1539   gint cmp_b = 0;
1540   gint i;
1541   gint old_location;
1542   gint new_location;
1543   gint *new_order;
1544   GtkTreeIterCompareFunc func;
1545   gpointer data;
1546
1547   if (list_store->length < 2)
1548     return;
1549
1550   tmp_iter.stamp = list_store->stamp;
1551
1552   if (list_store->sort_column_id != -1)
1553     {
1554       GtkTreeDataSortHeader *header;
1555       header = _gtk_tree_data_list_get_header (list_store->sort_list,
1556                                                list_store->sort_column_id);
1557       g_return_if_fail (header != NULL);
1558       g_return_if_fail (header->func != NULL);
1559       func = header->func;
1560       data = header->data;
1561     }
1562   else
1563     {
1564       g_return_if_fail (list_store->default_sort_func != NULL);
1565       func = list_store->default_sort_func;
1566       data = list_store->default_sort_data;
1567     }
1568
1569   /* If it's the built in function, we don't sort. */
1570   if (func == gtk_tree_data_list_compare_func &&
1571       list_store->sort_column_id != column)
1572     return;
1573
1574   old_location = 0;
1575   /* First we find the iter, its prev, and its next */
1576   while (list)
1577     {
1578       if (list == G_SLIST (iter->user_data))
1579         break;
1580       prev = list;
1581       list = list->next;
1582       old_location++;
1583     }
1584   g_assert (list != NULL);
1585
1586   next = list->next;
1587
1588   /* Check the common case, where we don't need to sort it moved. */
1589   if (prev != NULL)
1590     {
1591       tmp_iter.user_data = prev;
1592       cmp_a = (* func) (GTK_TREE_MODEL (list_store), &tmp_iter, iter, data);
1593     }
1594
1595   if (next != NULL)
1596     {
1597       tmp_iter.user_data = next;
1598       cmp_b = (* func) (GTK_TREE_MODEL (list_store), iter, &tmp_iter, data);
1599     }
1600
1601
1602   if (list_store->order == GTK_SORT_DESCENDING)
1603     {
1604       if (cmp_a < 0)
1605         cmp_a = 1;
1606       else if (cmp_a > 0)
1607         cmp_a = -1;
1608
1609       if (cmp_b < 0)
1610         cmp_b = 1;
1611       else if (cmp_b > 0)
1612         cmp_b = -1;
1613     }
1614
1615   if (prev == NULL && cmp_b <= 0)
1616     return;
1617   else if (next == NULL && cmp_a <= 0)
1618     return;
1619   else if (prev != NULL && next != NULL &&
1620            cmp_a <= 0 && cmp_b <= 0)
1621     return;
1622
1623   /* We actually need to sort it */
1624   /* First, remove the old link. */
1625
1626   if (prev == NULL)
1627     list_store->root = next;
1628   else
1629     prev->next = next;
1630   if (next == NULL)
1631     list_store->tail = prev;
1632   list->next = NULL;
1633   
1634   /* FIXME: as an optimization, we can potentially start at next */
1635   prev = NULL;
1636   list = G_SLIST (list_store->root);
1637   new_location = 0;
1638   tmp_iter.user_data = list;
1639   if (list_store->order == GTK_SORT_DESCENDING)
1640     cmp_a = (* func) (GTK_TREE_MODEL (list_store), &tmp_iter, iter, data);
1641   else
1642     cmp_a = (* func) (GTK_TREE_MODEL (list_store), iter, &tmp_iter, data);
1643
1644   while ((list->next) && (cmp_a > 0))
1645     {
1646       prev = list;
1647       list = list->next;
1648       new_location++;
1649       tmp_iter.user_data = list;
1650       if (list_store->order == GTK_SORT_DESCENDING)
1651         cmp_a = (* func) (GTK_TREE_MODEL (list_store), &tmp_iter, iter, data);
1652       else
1653         cmp_a = (* func) (GTK_TREE_MODEL (list_store), iter, &tmp_iter, data);
1654     }
1655
1656   if ((!list->next) && (cmp_a > 0))
1657     {
1658       list->next = G_SLIST (iter->user_data);
1659       list_store->tail = list->next;
1660     }
1661   else if (prev)
1662     {
1663       prev->next = G_SLIST (iter->user_data);
1664       G_SLIST (iter->user_data)->next = list;
1665     }
1666   else
1667     {
1668       G_SLIST (iter->user_data)->next = G_SLIST (list_store->root);
1669       list_store->root = G_SLIST (iter->user_data);
1670     }
1671
1672   /* Emit the reordered signal. */
1673   new_order = g_new (int, list_store->length);
1674   if (old_location < new_location)
1675     for (i = 0; i < list_store->length; i++)
1676       {
1677         if (i < old_location ||
1678             i > new_location)
1679           new_order[i] = i;
1680         else if (i >= old_location &&
1681                  i < new_location)
1682           new_order[i] = i + 1;
1683         else if (i == new_location)
1684           new_order[i] = old_location;
1685       }
1686   else
1687     for (i = 0; i < list_store->length; i++)
1688       {
1689         if (i < new_location ||
1690             i > old_location)
1691           new_order[i] = i;
1692         else if (i > new_location &&
1693                  i <= old_location)
1694           new_order[i] = i - 1;
1695         else if (i == new_location)
1696           new_order[i] = old_location;
1697       }
1698
1699   tmp_path = gtk_tree_path_new ();
1700   tmp_iter.user_data = NULL;
1701
1702   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (list_store),
1703                                  tmp_path, &tmp_iter,
1704                                  new_order);
1705
1706   gtk_tree_path_free (tmp_path);
1707   g_free (new_order);
1708 }
1709
1710 static gboolean
1711 gtk_list_store_get_sort_column_id (GtkTreeSortable  *sortable,
1712                                    gint             *sort_column_id,
1713                                    GtkSortType      *order)
1714 {
1715   GtkListStore *list_store = (GtkListStore *) sortable;
1716
1717   g_return_val_if_fail (GTK_IS_LIST_STORE (sortable), FALSE);
1718
1719   if (list_store->sort_column_id == -1)
1720     return FALSE;
1721
1722   if (sort_column_id)
1723     * sort_column_id = list_store->sort_column_id;
1724   if (order)
1725     * order = list_store->order;
1726   return TRUE;
1727 }
1728
1729 static void
1730 gtk_list_store_set_sort_column_id (GtkTreeSortable  *sortable,
1731                                    gint              sort_column_id,
1732                                    GtkSortType       order)
1733 {
1734   GtkListStore *list_store = (GtkListStore *) sortable;
1735
1736   g_return_if_fail (GTK_IS_LIST_STORE (sortable));
1737
1738   if ((list_store->sort_column_id == sort_column_id) &&
1739       (list_store->order == order))
1740     return;
1741
1742   if (sort_column_id != -1)
1743     {
1744       GtkTreeDataSortHeader *header = NULL;
1745
1746       header = _gtk_tree_data_list_get_header (list_store->sort_list, sort_column_id);
1747
1748       /* We want to make sure that we have a function */
1749       g_return_if_fail (header != NULL);
1750       g_return_if_fail (header->func != NULL);
1751     }
1752   else
1753     {
1754       g_return_if_fail (list_store->default_sort_func != NULL);
1755     }
1756
1757
1758   list_store->sort_column_id = sort_column_id;
1759   list_store->order = order;
1760
1761   gtk_list_store_sort (list_store);
1762
1763   gtk_tree_sortable_sort_column_changed (sortable);
1764 }
1765
1766 static void
1767 gtk_list_store_set_sort_func (GtkTreeSortable        *sortable,
1768                               gint                    sort_column_id,
1769                               GtkTreeIterCompareFunc  func,
1770                               gpointer                data,
1771                               GtkDestroyNotify        destroy)
1772 {
1773   GtkListStore *list_store = (GtkListStore *) sortable;
1774   GtkTreeDataSortHeader *header = NULL;
1775   GList *list;
1776
1777   g_return_if_fail (GTK_IS_LIST_STORE (sortable));
1778   g_return_if_fail (func != NULL);
1779
1780   for (list = list_store->sort_list; list; list = list->next)
1781     {
1782       header = (GtkTreeDataSortHeader*) list->data;
1783       if (header->sort_column_id == sort_column_id)
1784         break;
1785     }
1786
1787   if (header == NULL)
1788     {
1789       header = g_new0 (GtkTreeDataSortHeader, 1);
1790       header->sort_column_id = sort_column_id;
1791       list_store->sort_list = g_list_append (list_store->sort_list, header);
1792     }
1793
1794   if (header->destroy)
1795     (* header->destroy) (header->data);
1796
1797   header->func = func;
1798   header->data = data;
1799   header->destroy = destroy;
1800 }
1801
1802
1803 static void
1804 gtk_list_store_set_default_sort_func (GtkTreeSortable        *sortable,
1805                                       GtkTreeIterCompareFunc  func,
1806                                       gpointer                data,
1807                                       GtkDestroyNotify        destroy)
1808 {
1809   GtkListStore *list_store = (GtkListStore *) sortable;
1810
1811   g_return_if_fail (GTK_IS_LIST_STORE (sortable));
1812
1813   if (list_store->default_sort_destroy)
1814     (* list_store->default_sort_destroy) (list_store->default_sort_data);
1815
1816   list_store->default_sort_func = func;
1817   list_store->default_sort_data = data;
1818   list_store->default_sort_destroy = destroy;
1819 }
1820
1821 static gboolean
1822 gtk_list_store_has_default_sort_func (GtkTreeSortable *sortable)
1823 {
1824   GtkListStore *list_store = (GtkListStore *) sortable;
1825
1826   g_return_val_if_fail (GTK_IS_LIST_STORE (sortable), FALSE);
1827
1828   return (list_store->default_sort_func != NULL);
1829 }