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