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