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