]> Pileus Git - ~andy/gtk/blob - gtk/gtkliststore.c
fix bug in here where prev pointer was set to the wrong thing
[~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
30 enum {
31   CHANGED,
32   INSERTED,
33   CHILD_TOGGLED,
34   DELETED,
35   LAST_SIGNAL
36 };
37
38 static guint list_store_signals[LAST_SIGNAL] = { 0 };
39
40 static void         gtk_list_store_init            (GtkListStore      *list_store);
41 static void         gtk_list_store_class_init      (GtkListStoreClass *class);
42 static void         gtk_list_store_tree_model_init (GtkTreeModelIface *iface);
43 static void         gtk_list_store_drag_source_init(GtkTreeDragSourceIface *iface);
44 static void         gtk_list_store_drag_dest_init  (GtkTreeDragDestIface   *iface);
45 static guint        gtk_list_store_get_flags       (GtkTreeModel      *tree_model);
46 static gint         gtk_list_store_get_n_columns   (GtkTreeModel      *tree_model);
47 static GType        gtk_list_store_get_column_type (GtkTreeModel      *tree_model,
48                                                     gint               index);
49 static gboolean     gtk_list_store_get_iter        (GtkTreeModel      *tree_model,
50                                                     GtkTreeIter       *iter,
51                                                     GtkTreePath       *path);
52 static GtkTreePath *gtk_list_store_get_path        (GtkTreeModel      *tree_model,
53                                                     GtkTreeIter       *iter);
54 static void         gtk_list_store_get_value       (GtkTreeModel      *tree_model,
55                                                     GtkTreeIter       *iter,
56                                                     gint               column,
57                                                     GValue            *value);
58 static gboolean     gtk_list_store_iter_next       (GtkTreeModel      *tree_model,
59                                                     GtkTreeIter       *iter);
60 static gboolean     gtk_list_store_iter_children   (GtkTreeModel      *tree_model,
61                                                     GtkTreeIter       *iter,
62                                                     GtkTreeIter       *parent);
63 static gboolean     gtk_list_store_iter_has_child  (GtkTreeModel      *tree_model,
64                                                     GtkTreeIter       *iter);
65 static gint         gtk_list_store_iter_n_children (GtkTreeModel      *tree_model,
66                                                     GtkTreeIter       *iter);
67 static gboolean     gtk_list_store_iter_nth_child  (GtkTreeModel      *tree_model,
68                                                     GtkTreeIter       *iter,
69                                                     GtkTreeIter       *parent,
70                                                     gint               n);
71 static gboolean     gtk_list_store_iter_parent     (GtkTreeModel      *tree_model,
72                                                     GtkTreeIter       *iter,
73                                                     GtkTreeIter       *child);
74
75 static gboolean gtk_list_store_drag_data_delete   (GtkTreeDragSource *drag_source,
76                                                    GtkTreePath       *path);
77 static gboolean gtk_list_store_drag_data_get      (GtkTreeDragSource *drag_source,
78                                                    GtkTreePath       *path,
79                                                    GtkSelectionData  *selection_data);
80 static gboolean gtk_list_store_drag_data_received (GtkTreeDragDest   *drag_dest,
81                                                    GtkTreePath       *dest,
82                                                    GtkSelectionData  *selection_data);
83 static gboolean gtk_list_store_row_drop_possible  (GtkTreeDragDest   *drag_dest,
84                                                    GtkTreeModel      *src_model,
85                                                    GtkTreePath       *src_path,
86                                                    GtkTreePath       *dest_path);
87 static void
88 validate_list_store (GtkListStore *list_store)
89 {
90   if (gtk_debug_flags & GTK_DEBUG_TREE)
91     {
92       g_assert (g_slist_length (list_store->root) == list_store->length);
93       
94       g_assert (g_slist_last (list_store->root) == list_store->tail);
95     }
96 }
97
98 GtkType
99 gtk_list_store_get_type (void)
100 {
101   static GtkType list_store_type = 0;
102
103   if (!list_store_type)
104     {
105       static const GTypeInfo list_store_info =
106       {
107         sizeof (GtkListStoreClass),
108         NULL,           /* base_init */
109         NULL,           /* base_finalize */
110         (GClassInitFunc) gtk_list_store_class_init,
111         NULL,           /* class_finalize */
112         NULL,           /* class_data */
113         sizeof (GtkListStore),
114         0,
115         (GInstanceInitFunc) gtk_list_store_init,
116       };
117
118       static const GInterfaceInfo tree_model_info =
119       {
120         (GInterfaceInitFunc) gtk_list_store_tree_model_init,
121         NULL,
122         NULL
123       };
124
125       static const GInterfaceInfo drag_source_info =
126       {
127         (GInterfaceInitFunc) gtk_list_store_drag_source_init,
128         NULL,
129         NULL
130       };
131
132       static const GInterfaceInfo drag_dest_info =
133       {
134         (GInterfaceInitFunc) gtk_list_store_drag_dest_init,
135         NULL,
136         NULL
137       };
138       
139       list_store_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkListStore", &list_store_info, 0);
140       g_type_add_interface_static (list_store_type,
141                                    GTK_TYPE_TREE_MODEL,
142                                    &tree_model_info);
143       g_type_add_interface_static (list_store_type,
144                                    GTK_TYPE_TREE_DRAG_SOURCE,
145                                    &drag_source_info);
146       g_type_add_interface_static (list_store_type,
147                                    GTK_TYPE_TREE_DRAG_DEST,
148                                    &drag_dest_info);
149     }
150
151   return list_store_type;
152 }
153
154 static void
155 gtk_list_store_class_init (GtkListStoreClass *class)
156 {
157   GtkObjectClass *object_class;
158
159   object_class = (GtkObjectClass*) class;
160
161   list_store_signals[CHANGED] =
162     gtk_signal_new ("changed",
163                     GTK_RUN_FIRST,
164                     GTK_CLASS_TYPE (object_class),
165                     GTK_SIGNAL_OFFSET (GtkListStoreClass, changed),
166                     gtk_marshal_VOID__BOXED_BOXED,
167                     G_TYPE_NONE, 2,
168                     GTK_TYPE_TREE_PATH,
169                     GTK_TYPE_TREE_ITER);
170   list_store_signals[INSERTED] =
171     gtk_signal_new ("inserted",
172                     GTK_RUN_FIRST,
173                     GTK_CLASS_TYPE (object_class),
174                     GTK_SIGNAL_OFFSET (GtkListStoreClass, inserted),
175                     gtk_marshal_VOID__BOXED_BOXED,
176                     G_TYPE_NONE, 2,
177                     GTK_TYPE_TREE_PATH,
178                     GTK_TYPE_TREE_ITER);
179   list_store_signals[CHILD_TOGGLED] =
180     gtk_signal_new ("child_toggled",
181                     GTK_RUN_FIRST,
182                     GTK_CLASS_TYPE (object_class),
183                     GTK_SIGNAL_OFFSET (GtkListStoreClass, child_toggled),
184                     gtk_marshal_VOID__BOXED_BOXED,
185                     G_TYPE_NONE, 2,
186                     GTK_TYPE_TREE_PATH,
187                     GTK_TYPE_TREE_ITER);
188   list_store_signals[DELETED] =
189     gtk_signal_new ("deleted",
190                     GTK_RUN_FIRST,
191                     GTK_CLASS_TYPE (object_class),
192                     GTK_SIGNAL_OFFSET (GtkListStoreClass, deleted),
193                     gtk_marshal_VOID__BOXED,
194                     G_TYPE_NONE, 1,
195                     GTK_TYPE_TREE_PATH);
196 }
197
198 static void
199 gtk_list_store_tree_model_init (GtkTreeModelIface *iface)
200 {
201   iface->get_flags = gtk_list_store_get_flags;
202   iface->get_n_columns = gtk_list_store_get_n_columns;
203   iface->get_column_type = gtk_list_store_get_column_type;
204   iface->get_iter = gtk_list_store_get_iter;
205   iface->get_path = gtk_list_store_get_path;
206   iface->get_value = gtk_list_store_get_value;
207   iface->iter_next = gtk_list_store_iter_next;
208   iface->iter_children = gtk_list_store_iter_children;
209   iface->iter_has_child = gtk_list_store_iter_has_child;
210   iface->iter_n_children = gtk_list_store_iter_n_children;
211   iface->iter_nth_child = gtk_list_store_iter_nth_child;
212   iface->iter_parent = gtk_list_store_iter_parent;
213 }
214
215 static void
216 gtk_list_store_drag_source_init (GtkTreeDragSourceIface *iface)
217 {
218   iface->drag_data_delete = gtk_list_store_drag_data_delete;
219   iface->drag_data_get = gtk_list_store_drag_data_get;
220 }
221
222 static void
223 gtk_list_store_drag_dest_init   (GtkTreeDragDestIface   *iface)
224 {
225   iface->drag_data_received = gtk_list_store_drag_data_received;
226   iface->row_drop_possible = gtk_list_store_row_drop_possible;
227 }
228
229 static void
230 gtk_list_store_init (GtkListStore *list_store)
231 {
232   list_store->root = NULL;
233   list_store->tail = NULL;
234   list_store->stamp = g_random_int ();
235   list_store->length = 0;
236 }
237
238 GtkListStore *
239 gtk_list_store_new (void)
240 {
241   return GTK_LIST_STORE (gtk_type_new (gtk_list_store_get_type ()));
242 }
243
244 GtkListStore *
245 gtk_list_store_new_with_types (gint n_columns,
246                                ...)
247 {
248   GtkListStore *retval;
249   va_list args;
250   gint i;
251
252   g_return_val_if_fail (n_columns > 0, NULL);
253
254   retval = gtk_list_store_new ();
255   gtk_list_store_set_n_columns (retval, n_columns);
256
257   va_start (args, n_columns);
258
259   for (i = 0; i < n_columns; i++)
260     gtk_list_store_set_column_type (retval, i, va_arg (args, GType));
261
262   va_end (args);
263
264   return retval;
265 }
266
267 void
268 gtk_list_store_set_n_columns (GtkListStore *list_store,
269                               gint          n_columns)
270 {
271   GType *new_columns;
272
273   g_return_if_fail (list_store != NULL);
274   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
275   g_return_if_fail (n_columns > 0);
276
277   if (list_store->n_columns == n_columns)
278     return;
279
280   new_columns = g_new0 (GType, n_columns);
281   if (list_store->column_headers)
282     {
283       /* copy the old header orders over */
284       if (n_columns >= list_store->n_columns)
285         memcpy (new_columns, list_store->column_headers, list_store->n_columns * sizeof (gchar *));
286       else
287         memcpy (new_columns, list_store->column_headers, n_columns * sizeof (GType));
288
289       g_free (list_store->column_headers);
290     }
291
292   list_store->column_headers = new_columns;
293   list_store->n_columns = n_columns;
294 }
295
296 void
297 gtk_list_store_set_column_type (GtkListStore *list_store,
298                                 gint          column,
299                                 GType         type)
300 {
301   g_return_if_fail (list_store != NULL);
302   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
303   g_return_if_fail (column >=0 && column < list_store->n_columns);
304
305   list_store->column_headers[column] = type;
306 }
307
308 /* Fulfill the GtkTreeModel requirements */
309 static guint
310 gtk_list_store_get_flags (GtkTreeModel *tree_model)
311 {
312   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), 0);
313
314   return GTK_TREE_MODEL_ITERS_PERSIST;
315 }
316
317 static gint
318 gtk_list_store_get_n_columns (GtkTreeModel *tree_model)
319 {
320   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), 0);
321
322   return GTK_LIST_STORE (tree_model)->n_columns;
323 }
324
325 static GType
326 gtk_list_store_get_column_type (GtkTreeModel *tree_model,
327                                 gint          index)
328 {
329   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), G_TYPE_INVALID);
330   g_return_val_if_fail (index < GTK_LIST_STORE (tree_model)->n_columns &&
331                         index >= 0, G_TYPE_INVALID);
332
333   return GTK_LIST_STORE (tree_model)->column_headers[index];
334 }
335
336 static gboolean
337 gtk_list_store_get_iter (GtkTreeModel *tree_model,
338                          GtkTreeIter  *iter,
339                          GtkTreePath  *path)
340 {
341   GSList *list;
342   gint i;
343   
344   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
345   g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);  
346
347   i = gtk_tree_path_get_indices (path)[0];
348
349   if (i >= GTK_LIST_STORE (tree_model)->length)
350     return FALSE;
351   
352   list = g_slist_nth (G_SLIST (GTK_LIST_STORE (tree_model)->root),
353                       i);
354
355   /* If this fails, list_store->length has gotten mangled. */
356   g_assert (list);
357   
358   iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
359   iter->user_data = list;
360   return TRUE;
361 }
362
363 static GtkTreePath *
364 gtk_list_store_get_path (GtkTreeModel *tree_model,
365                          GtkTreeIter  *iter)
366 {
367   GtkTreePath *retval;
368   GSList *list;
369   gint i = 0;
370
371   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), NULL);
372   g_return_val_if_fail (iter->stamp == GTK_LIST_STORE (tree_model)->stamp, NULL);
373
374   for (list = G_SLIST (GTK_LIST_STORE (tree_model)->root); list; list = list->next)
375     {
376       if (list == G_SLIST (iter->user_data))
377         break;
378       i++;
379     }
380   if (list == NULL)
381     return NULL;
382
383   retval = gtk_tree_path_new ();
384   gtk_tree_path_append_index (retval, i);
385   return retval;
386 }
387
388 static void
389 gtk_list_store_get_value (GtkTreeModel *tree_model,
390                           GtkTreeIter  *iter,
391                           gint          column,
392                           GValue       *value)
393 {
394   GtkTreeDataList *list;
395   gint tmp_column = column;
396
397   g_return_if_fail (GTK_IS_LIST_STORE (tree_model));
398   g_return_if_fail (column < GTK_LIST_STORE (tree_model)->n_columns);
399   g_return_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp);
400
401   list = G_SLIST (iter->user_data)->data;
402
403   while (tmp_column-- > 0 && list)
404     list = list->next;
405
406   if (list == NULL)
407     g_value_init (value, GTK_LIST_STORE (tree_model)->column_headers[column]);
408   else
409     _gtk_tree_data_list_node_to_value (list,
410                                        GTK_LIST_STORE (tree_model)->column_headers[column],
411                                        value);
412 }
413
414 static gboolean
415 gtk_list_store_iter_next (GtkTreeModel  *tree_model,
416                           GtkTreeIter   *iter)
417 {
418   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
419   g_return_val_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp, FALSE);
420
421   if (G_SLIST (iter->user_data)->next)
422     {
423       iter->user_data = G_SLIST (iter->user_data)->next;
424       return TRUE;
425     }
426   else
427     return FALSE;
428 }
429
430 static gboolean
431 gtk_list_store_iter_children (GtkTreeModel *tree_model,
432                               GtkTreeIter  *iter,
433                               GtkTreeIter  *parent)
434 {
435   /* this is a list, nodes have no children */
436   if (parent)
437     return FALSE;
438
439   /* but if parent == NULL we return the list itself as children of the
440    * "root"
441    */
442   
443   if (GTK_LIST_STORE (tree_model)->root)
444     {
445       iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
446       iter->user_data = GTK_LIST_STORE (tree_model)->root;
447       return TRUE;
448     }
449   else
450     return FALSE;
451 }
452
453 static gboolean
454 gtk_list_store_iter_has_child (GtkTreeModel *tree_model,
455                                GtkTreeIter  *iter)
456 {
457   return FALSE;
458 }
459
460 static gint
461 gtk_list_store_iter_n_children (GtkTreeModel *tree_model,
462                                 GtkTreeIter  *iter)
463 {
464   if (iter == NULL)
465     return GTK_LIST_STORE (tree_model)->length;
466   else
467     return 0;
468 }
469
470 static gboolean
471 gtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
472                                GtkTreeIter  *iter,
473                                GtkTreeIter  *parent,
474                                gint          n)
475 {
476   GSList *child;
477   
478   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
479
480   if (parent)
481     return FALSE;
482
483   child = g_slist_nth (G_SLIST (GTK_LIST_STORE (tree_model)->root), n);
484
485   if (child)
486     {
487       iter->user_data = child;
488       iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
489       return TRUE;
490     }
491   else
492     return FALSE;
493 }
494
495 static gboolean
496 gtk_list_store_iter_parent (GtkTreeModel *tree_model,
497                             GtkTreeIter  *iter,
498                             GtkTreeIter  *child)
499 {
500   return FALSE;
501 }
502
503 /* Public accessors */
504 /* This is a somewhat inelegant function that does a lot of list
505  * manipulations on it's own.
506  */
507 void
508 gtk_list_store_set_cell (GtkListStore *list_store,
509                          GtkTreeIter  *iter,
510                          gint          column,
511                          GValue       *value)
512 {
513   GtkTreeDataList *list;
514   GtkTreeDataList *prev;
515
516   g_return_if_fail (list_store != NULL);
517   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
518   g_return_if_fail (iter != NULL);
519   g_return_if_fail (column >= 0 && column < list_store->n_columns);
520
521   prev = list = G_SLIST (iter->user_data)->data;
522
523   while (list != NULL)
524     {
525       if (column == 0)
526         {
527           _gtk_tree_data_list_value_to_node (list, value);
528           gtk_signal_emit_by_name (GTK_OBJECT (list_store),
529                                    "changed",
530                                    NULL, iter);
531           return;
532         }
533
534       column--;
535       prev = list;
536       list = list->next;
537     }
538
539   if (G_SLIST (iter->user_data)->data == NULL)
540     {
541       G_SLIST (iter->user_data)->data = list = _gtk_tree_data_list_alloc ();
542       list->next = NULL;
543     }
544   else
545     {
546       list = prev->next = _gtk_tree_data_list_alloc ();
547       list->next = NULL;
548     }
549
550   while (column != 0)
551     {
552       list->next = _gtk_tree_data_list_alloc ();
553       list = list->next;
554       list->next = NULL;
555       column --;
556     }
557   _gtk_tree_data_list_value_to_node (list, value);
558   gtk_signal_emit_by_name (GTK_OBJECT (list_store),
559                            "changed",
560                            NULL, iter);
561 }
562
563 void
564 gtk_list_store_set_valist (GtkListStore *list_store,
565                            GtkTreeIter  *iter,
566                            va_list      var_args)
567 {
568   gint column;
569
570   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
571
572   column = va_arg (var_args, gint);
573
574   while (column != -1)
575     {
576       GValue value = { 0, };
577       gchar *error = NULL;
578
579       if (column >= list_store->n_columns)
580         {
581           g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column);
582           break;
583         }
584       g_value_init (&value, list_store->column_headers[column]);
585
586       G_VALUE_COLLECT (&value, var_args, &error);
587       if (error)
588         {
589           g_warning ("%s: %s", G_STRLOC, error);
590           g_free (error);
591
592           /* we purposely leak the value here, it might not be
593            * in a sane state if an error condition occoured
594            */
595           break;
596         }
597
598       gtk_list_store_set_cell (list_store,
599                                iter,
600                                column,
601                                &value);
602
603       g_value_unset (&value);
604
605       column = va_arg (var_args, gint);
606     }
607 }
608
609 /**
610  * gtk_list_store_set:
611  * @list_store: a #GtkListStore
612  * @iter: row iterator
613  * @Varargs: pairs of column number and value, terminated with -1
614  * 
615  * Sets the value of one or more cells in the row referenced by @iter.
616  * The variable argument list should contain integer column numbers,
617  * each column number followed by the value to be set. For example,
618  * The list is terminated by a -1. For example, to set column 0 with type
619  * %G_TYPE_STRING to "Foo", you would write gtk_list_store_set (store, iter,
620  * 0, "Foo", -1).
621  **/
622 void
623 gtk_list_store_set (GtkListStore *list_store,
624                     GtkTreeIter  *iter,
625                     ...)
626 {
627   va_list var_args;
628
629   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
630
631   va_start (var_args, iter);
632   gtk_list_store_set_valist (list_store, iter, var_args);
633   va_end (var_args);
634 }
635
636 void
637 gtk_list_store_get_valist (GtkListStore *list_store,
638                            GtkTreeIter  *iter,
639                            va_list      var_args)
640 {
641   gint column;
642
643   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
644
645   column = va_arg (var_args, gint);
646
647   while (column != -1)
648     {
649       GValue value = { 0, };
650       gchar *error = NULL;
651
652       if (column >= list_store->n_columns)
653         {
654           g_warning ("%s: Invalid column number %d accessed (remember to end your list of columns with a -1)", G_STRLOC, column);
655           break;
656         }
657
658       gtk_list_store_get_value (GTK_TREE_MODEL (list_store), iter, column, &value);
659
660       G_VALUE_LCOPY (&value, var_args, &error);
661       if (error)
662         {
663           g_warning ("%s: %s", G_STRLOC, error);
664           g_free (error);
665
666           /* we purposely leak the value here, it might not be
667            * in a sane state if an error condition occoured
668            */
669           break;
670         }
671
672       g_value_unset (&value);
673
674       column = va_arg (var_args, gint);
675     }
676 }
677
678 void
679 gtk_list_store_get (GtkListStore *list_store,
680                     GtkTreeIter  *iter,
681                     ...)
682 {
683   va_list var_args;
684
685   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
686
687   va_start (var_args, iter);
688   gtk_list_store_get_valist (list_store, iter, var_args);
689   va_end (var_args);
690 }
691
692 static GSList*
693 remove_link_saving_prev (GSList  *list,
694                          GSList  *link,
695                          GSList **prevp)
696 {
697   GSList *tmp;
698   GSList *prev;
699
700   prev = NULL;
701   tmp = list;
702
703   while (tmp)
704     {
705       if (tmp == link)
706         {
707           if (prev)
708             prev->next = link->next;
709
710           if (list == link)
711             list = list->next;
712
713           link->next = NULL;
714           break;
715         }
716
717       prev = tmp;
718       tmp = tmp->next;
719     }
720
721   *prevp = prev;
722   
723   return list;
724 }
725
726 static void
727 gtk_list_store_remove_silently (GtkListStore *list_store,
728                                 GtkTreeIter  *iter,
729                                 GtkTreePath  *path)
730 {
731   if (G_SLIST (iter->user_data)->data)
732     {
733       _gtk_tree_data_list_free ((GtkTreeDataList *) G_SLIST (iter->user_data)->data,
734                                 list_store->column_headers);
735       G_SLIST (iter->user_data)->data = NULL;
736     }
737
738   {
739     GSList *prev = NULL;
740     
741     list_store->root = remove_link_saving_prev (G_SLIST (list_store->root),
742                                                 G_SLIST (iter->user_data),
743                                                 &prev);
744
745     list_store->length -= 1;
746     
747     if (iter->user_data == list_store->tail)
748       list_store->tail = prev;
749   }
750   
751   list_store->stamp ++;
752 }
753
754 void
755 gtk_list_store_remove (GtkListStore *list_store,
756                        GtkTreeIter  *iter)
757 {
758   GtkTreePath *path;
759
760   g_return_if_fail (list_store != NULL);
761   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
762   g_return_if_fail (iter->user_data != NULL);  
763
764   path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
765
766   validate_list_store (list_store);
767   
768   gtk_list_store_remove_silently (list_store, iter, path);
769
770   validate_list_store (list_store);  
771   
772   gtk_signal_emit_by_name (GTK_OBJECT (list_store),
773                            "deleted",
774                            path);
775   gtk_tree_path_free (path);
776 }
777
778 static void
779 insert_after (GtkListStore *list_store,
780               GSList       *sibling,
781               GSList       *new_list)
782 {
783   g_return_if_fail (sibling != NULL);
784   g_return_if_fail (new_list != NULL);
785   
786   /* insert new node after list */
787   new_list->next = sibling->next;
788   sibling->next = new_list;
789
790   /* if list was the tail, the new node is the new tail */
791   if (sibling == list_store->tail)
792     list_store->tail = new_list;
793
794   list_store->length += 1;
795 }
796
797 void
798 gtk_list_store_insert (GtkListStore *list_store,
799                        GtkTreeIter  *iter,
800                        gint          position)
801 {
802   GSList *list;
803   GtkTreePath *path;
804   GSList *new_list;
805   
806   g_return_if_fail (list_store != NULL);
807   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
808   g_return_if_fail (iter != NULL);
809   g_return_if_fail (position >= 0);
810
811   if (position == 0)
812     {
813       gtk_list_store_prepend (list_store, iter);
814       return;
815     }
816
817   new_list = g_slist_alloc ();
818
819   list = g_slist_nth (G_SLIST (list_store->root), position - 1);
820
821   if (list == NULL)
822     {
823       g_warning ("%s: position %d is off the end of the list\n", G_STRLOC, position);
824       return;
825     }
826
827   insert_after (list_store, list, new_list);
828   
829   iter->stamp = list_store->stamp;
830   iter->user_data = new_list;
831
832   validate_list_store (list_store);
833   
834   path = gtk_tree_path_new ();
835   gtk_tree_path_append_index (path, position);
836   gtk_signal_emit_by_name (GTK_OBJECT (list_store),
837                            "inserted",
838                            path, iter);
839   gtk_tree_path_free (path);
840 }
841
842 void
843 gtk_list_store_insert_before (GtkListStore *list_store,
844                               GtkTreeIter  *iter,
845                               GtkTreeIter  *sibling)
846 {
847   GtkTreePath *path;
848   GSList *list, *prev, *new_list;
849   gint i = 0;
850
851   g_return_if_fail (list_store != NULL);
852   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
853   g_return_if_fail (iter != NULL);
854
855   if (sibling == NULL)
856     {
857       gtk_list_store_append (list_store, iter);
858       return;
859     }
860   
861   new_list = g_slist_alloc ();
862
863   prev = NULL;
864   list = list_store->root;
865   while (list && list != sibling->user_data)
866     {
867       prev = list;
868       list = list->next;
869       i++;
870     }
871
872   if (list != sibling->user_data)
873     {
874       g_warning ("%s: sibling iterator invalid? not found in the list", G_STRLOC);
875       return;
876     }
877
878   /* if there are no nodes, we become the list tail, otherwise we
879    * are inserting before any existing nodes so we can't change
880    * the tail
881    */
882
883   if (list_store->root == NULL)
884     list_store->tail = new_list;
885   
886   if (prev)
887     {
888       new_list->next = prev->next;
889       prev->next = new_list;
890     }
891   else
892     {
893       new_list->next = list_store->root;
894       list_store->root = new_list;
895     }
896
897   iter->stamp = list_store->stamp;
898   iter->user_data = new_list;
899
900   list_store->length += 1;
901
902   validate_list_store (list_store);
903   
904   path = gtk_tree_path_new ();
905   gtk_tree_path_append_index (path, i);
906   gtk_signal_emit_by_name (GTK_OBJECT (list_store),
907                            "inserted",
908                            path, iter);
909   gtk_tree_path_free (path);
910 }
911
912 void
913 gtk_list_store_insert_after (GtkListStore *list_store,
914                              GtkTreeIter  *iter,
915                              GtkTreeIter  *sibling)
916 {
917   GtkTreePath *path;
918   GSList *list, *new_list;
919   gint i = 0;
920
921   g_return_if_fail (list_store != NULL);
922   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
923   g_return_if_fail (iter != NULL);
924   if (sibling)
925     g_return_if_fail (sibling->stamp == list_store->stamp);
926
927   if (sibling == NULL)
928     {
929       gtk_list_store_prepend (list_store, iter);
930       return;
931     }
932
933   for (list = list_store->root; list && list != sibling->user_data; list = list->next)
934     i++;
935
936   g_return_if_fail (list == sibling->user_data);
937
938   new_list = g_slist_alloc ();
939
940   insert_after (list_store, list, new_list);
941   
942   iter->stamp = list_store->stamp;
943   iter->user_data = new_list;
944
945   validate_list_store (list_store);
946   
947   path = gtk_tree_path_new ();
948   gtk_tree_path_append_index (path, i);
949   gtk_signal_emit_by_name (GTK_OBJECT (list_store),
950                            "inserted",
951                            path, iter);
952   gtk_tree_path_free (path);
953 }
954
955 void
956 gtk_list_store_prepend (GtkListStore *list_store,
957                         GtkTreeIter  *iter)
958 {
959   GtkTreePath *path;
960
961   g_return_if_fail (list_store != NULL);
962   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
963   g_return_if_fail (iter != NULL);
964
965   iter->stamp = list_store->stamp;
966   iter->user_data = g_slist_alloc ();
967
968   if (list_store->root == NULL)
969     list_store->tail = iter->user_data;
970   
971   G_SLIST (iter->user_data)->next = G_SLIST (list_store->root);
972   list_store->root = iter->user_data;
973
974   list_store->length += 1;
975
976   validate_list_store (list_store);
977   
978   path = gtk_tree_path_new ();
979   gtk_tree_path_append_index (path, 0);
980   gtk_signal_emit_by_name (GTK_OBJECT (list_store),
981                            "inserted",
982                            path, iter);
983   gtk_tree_path_free (path);
984 }
985
986 void
987 gtk_list_store_append (GtkListStore *list_store,
988                        GtkTreeIter  *iter)
989 {
990   GtkTreePath *path;
991   gint i = 0;
992
993   g_return_if_fail (list_store != NULL);
994   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
995   g_return_if_fail (iter != NULL);
996
997   iter->stamp = list_store->stamp;
998   iter->user_data = g_slist_alloc ();
999
1000   if (list_store->tail)
1001     list_store->tail->next = iter->user_data;
1002   else
1003     list_store->root = iter->user_data;
1004
1005   list_store->tail = iter->user_data;
1006
1007   list_store->length += 1;
1008
1009   validate_list_store (list_store);
1010   
1011   path = gtk_tree_path_new ();
1012   gtk_tree_path_append_index (path, i);
1013   gtk_signal_emit_by_name (GTK_OBJECT (list_store),
1014                            "inserted",
1015                            path, iter);
1016   gtk_tree_path_free (path);
1017 }
1018
1019 static gboolean
1020 gtk_list_store_drag_data_delete (GtkTreeDragSource *drag_source,
1021                                  GtkTreePath       *path)
1022 {
1023   GtkTreeIter iter;
1024   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE);
1025   
1026   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source),
1027                                &iter,
1028                                path))
1029     {
1030       gtk_list_store_remove (GTK_LIST_STORE (drag_source),
1031                              &iter);
1032       return TRUE;
1033     }
1034   else
1035     {
1036       return FALSE;
1037     }
1038 }
1039
1040 static gboolean
1041 gtk_list_store_drag_data_get (GtkTreeDragSource *drag_source,
1042                               GtkTreePath       *path,
1043                               GtkSelectionData  *selection_data)
1044 {
1045   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE);
1046
1047   /* Note that we don't need to handle the GTK_TREE_MODEL_ROW
1048    * target, because the default handler does it for us, but
1049    * we do anyway for the convenience of someone maybe overriding the
1050    * default handler.
1051    */
1052
1053   if (gtk_selection_data_set_tree_row (selection_data,
1054                                        GTK_TREE_MODEL (drag_source),
1055                                        path))
1056     {
1057       return TRUE;
1058     }
1059   else
1060     {
1061       /* FIXME handle text targets at least. */
1062     }
1063
1064   return FALSE;
1065 }
1066
1067 static gboolean
1068 gtk_list_store_drag_data_received (GtkTreeDragDest   *drag_dest,
1069                                    GtkTreePath       *dest,
1070                                    GtkSelectionData  *selection_data)
1071 {
1072   GtkTreeModel *tree_model;
1073   GtkListStore *list_store;
1074   GtkTreeModel *src_model = NULL;
1075   GtkTreePath *src_path = NULL;
1076   gboolean retval = FALSE;
1077   
1078   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE);
1079
1080   tree_model = GTK_TREE_MODEL (drag_dest);
1081   list_store = GTK_LIST_STORE (drag_dest);
1082   
1083   if (gtk_selection_data_get_tree_row (selection_data,
1084                                        &src_model,
1085                                        &src_path) &&
1086       src_model == tree_model)
1087     {
1088       /* Copy the given row to a new position */
1089       GtkTreeIter src_iter;
1090       GtkTreeIter dest_iter;
1091       GtkTreePath *prev;
1092       
1093       if (!gtk_tree_model_get_iter (src_model,
1094                                     &src_iter,
1095                                     src_path))
1096         {
1097           g_print ("can't get source path as iter\n");
1098           goto out;
1099         }
1100
1101       /* Get the path to insert _after_ (dest is the path to insert _before_) */
1102       prev = gtk_tree_path_copy (dest);
1103
1104       if (!gtk_tree_path_prev (prev))
1105         {
1106           /* dest was the first spot in the list; which means we are supposed
1107            * to prepend.
1108            */
1109           gtk_list_store_prepend (GTK_LIST_STORE (tree_model),
1110                                   &dest_iter);
1111           
1112           retval = TRUE;
1113
1114           g_print ("prepending to list\n");
1115         }
1116       else
1117         {
1118           if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model),
1119                                        &dest_iter,
1120                                        prev))
1121             {
1122               GtkTreeIter tmp_iter = dest_iter;
1123               gtk_list_store_insert_after (GTK_LIST_STORE (tree_model),
1124                                            &dest_iter,
1125                                            &tmp_iter);
1126               retval = TRUE;
1127
1128               g_print ("inserting into list\n");
1129             }
1130           else
1131             g_print ("can't get iter to insert after\n");
1132         }
1133
1134       gtk_tree_path_free (prev);
1135       
1136       /* If we succeeded in creating dest_iter, copy data from src
1137        */
1138       if (retval)
1139         {
1140           GtkTreeDataList *dl = G_SLIST (src_iter.user_data)->data;
1141           GtkTreeDataList *copy_head = NULL;
1142           GtkTreeDataList *copy_prev = NULL;
1143           GtkTreeDataList *copy_iter = NULL;
1144           gint col;
1145
1146           col = 0;
1147           while (dl)
1148             {
1149               copy_iter = _gtk_tree_data_list_node_copy (dl,
1150                                                          list_store->column_headers[col]);
1151
1152               g_print ("copied col %d type %s\n", col,
1153                        g_type_name (list_store->column_headers[col]));
1154               
1155               if (copy_head == NULL)
1156                 copy_head = copy_iter;
1157
1158               if (copy_prev)
1159                 copy_prev->next = copy_iter;
1160
1161               copy_prev = copy_iter;
1162
1163               dl = dl->next;
1164               ++col;
1165             }
1166           
1167           G_SLIST (dest_iter.user_data)->data = copy_head;
1168           
1169           gtk_signal_emit_by_name (GTK_OBJECT (tree_model),
1170                                    "changed",
1171                                    NULL, &dest_iter);
1172         }
1173     }
1174   else
1175     {
1176       /* FIXME maybe add some data targets eventually, or handle text
1177        * targets in the simple case.
1178        */
1179       g_print ("not accepting target\n");
1180     }
1181
1182  out:
1183   
1184   if (src_path)
1185     gtk_tree_path_free (src_path);
1186   
1187   return retval;  
1188 }
1189
1190 static gboolean
1191 gtk_list_store_row_drop_possible (GtkTreeDragDest *drag_dest,
1192                                   GtkTreeModel    *src_model,
1193                                   GtkTreePath     *src_path,
1194                                   GtkTreePath     *dest_path)
1195 {
1196   gint *indices;
1197   
1198   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE);
1199
1200   if (src_model != GTK_TREE_MODEL (drag_dest))
1201     return FALSE;
1202   
1203   if (gtk_tree_path_get_depth (dest_path) != 1)
1204     return FALSE;
1205
1206   /* can drop before any existing node, or before one past any existing. */
1207
1208   indices = gtk_tree_path_get_indices (dest_path);
1209
1210   if (indices[0] <= GTK_LIST_STORE (drag_dest)->length)
1211     return TRUE;
1212   else
1213     return FALSE;
1214 }