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