[gtk+] Bug 346800 - Rework sort/filter models to use indices to parents...



commit a59c39f3703e81f560aa946c25145413192d795b
Author: Kristian Rietveld <kris gtk org>
Date:   Sun Sep 6 13:35:37 2009 +0200

    Bug 346800 - Rework sort/filter models to use indices to parents...
    
    Rework the sort and filter models to store their reference to the parent
    element as an array index instead of a pointer to an array element.
    These pointers could become invalid with any array modification, whereas
    indices do not.

 gtk/gtktreemodelfilter.c |  156 ++++++++++++++++++++++++++----------------
 gtk/gtktreemodelsort.c   |  169 +++++++++++++++++++++++++++-------------------
 2 files changed, 195 insertions(+), 130 deletions(-)
---
diff --git a/gtk/gtktreemodelfilter.c b/gtk/gtktreemodelfilter.c
index 1199598..214bfe4 100644
--- a/gtk/gtktreemodelfilter.c
+++ b/gtk/gtktreemodelfilter.c
@@ -73,7 +73,7 @@ struct _FilterLevel
   gint ref_count;
   gint visible_nodes;
 
-  FilterElt *parent_elt;
+  gint parent_elt_index;
   FilterLevel *parent_level;
 };
 
@@ -129,6 +129,9 @@ enum
 #define FILTER_ELT(filter_elt) ((FilterElt *)filter_elt)
 #define FILTER_LEVEL(filter_level) ((FilterLevel *)filter_level)
 
+#define FILTER_LEVEL_PARENT_ELT(level) (&g_array_index (FILTER_LEVEL ((level))->parent_level->array, FilterElt, FILTER_LEVEL ((level))->parent_elt_index))
+#define FILTER_LEVEL_ELT_INDEX(level, elt) (FILTER_ELT ((elt)) - FILTER_ELT (FILTER_LEVEL ((level))->array->data))
+
 /* general code (object/interface init, properties, etc) */
 static void         gtk_tree_model_filter_tree_model_init                 (GtkTreeModelIface       *iface);
 static void         gtk_tree_model_filter_drag_source_init                (GtkTreeDragSourceIface  *iface);
@@ -214,7 +217,7 @@ static gboolean    gtk_tree_model_filter_drag_data_delete                 (GtkTr
 /* private functions */
 static void        gtk_tree_model_filter_build_level                      (GtkTreeModelFilter     *filter,
                                                                            FilterLevel            *parent_level,
-                                                                           FilterElt              *parent_elt,
+                                                                           gint                    parent_elt_index,
                                                                            gboolean                emit_inserted);
 
 static void        gtk_tree_model_filter_free_level                       (GtkTreeModelFilter     *filter,
@@ -438,12 +441,13 @@ gtk_tree_model_filter_get_property (GObject    *object,
 static void
 gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter,
                                    FilterLevel        *parent_level,
-                                   FilterElt          *parent_elt,
+                                   gint                parent_elt_index,
                                    gboolean            emit_inserted)
 {
   GtkTreeIter iter;
   GtkTreeIter first_node;
   GtkTreeIter root;
+  FilterElt *parent_elt = NULL;
   FilterLevel *new_level;
   gint length = 0;
   gint i;
@@ -476,6 +480,8 @@ gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter,
       GtkTreeIter parent_iter;
       GtkTreeIter child_parent_iter;
 
+      parent_elt = &g_array_index (parent_level->array, FilterElt, parent_elt_index);
+
       parent_iter.stamp = filter->priv->stamp;
       parent_iter.user_data = parent_level;
       parent_iter.user_data2 = parent_elt;
@@ -501,10 +507,10 @@ gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter,
                                         length);
   new_level->ref_count = 0;
   new_level->visible_nodes = 0;
-  new_level->parent_elt = parent_elt;
+  new_level->parent_elt_index = parent_elt_index;
   new_level->parent_level = parent_level;
 
-  if (parent_elt)
+  if (parent_elt_index >= 0)
     parent_elt->children = new_level;
   else
     filter->priv->root = new_level;
@@ -512,9 +518,9 @@ gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter,
   /* increase the count of zero ref_counts */
   while (parent_level)
     {
-      parent_elt->zero_ref_count++;
+      g_array_index (parent_level->array, FilterElt, parent_elt_index).zero_ref_count++;
 
-      parent_elt = parent_level->parent_elt;
+      parent_elt_index = parent_level->parent_elt_index;
       parent_level = parent_level->parent_level;
     }
   if (new_level != filter->priv->root)
@@ -628,13 +634,13 @@ gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter,
   if (filter_level->ref_count == 0)
     {
       FilterLevel *parent_level = filter_level->parent_level;
-      FilterElt *parent_elt = filter_level->parent_elt;
+      gint parent_elt_index = filter_level->parent_elt_index;
 
       while (parent_level)
         {
-	  parent_elt->zero_ref_count--;
+	  g_array_index (parent_level->array, FilterElt, parent_elt_index).zero_ref_count--;
 
-	  parent_elt = parent_level->parent_elt;
+	  parent_elt_index = parent_level->parent_elt_index;
 	  parent_level = parent_level->parent_level;
         }
 
@@ -642,8 +648,8 @@ gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter,
         filter->priv->zero_ref_count--;
     }
 
-  if (filter_level->parent_elt)
-    filter_level->parent_elt->children = NULL;
+  if (filter_level->parent_elt_index >= 0)
+    FILTER_LEVEL_PARENT_ELT (filter_level)->children = NULL;
   else
     filter->priv->root = NULL;
 
@@ -674,7 +680,10 @@ gtk_tree_model_filter_elt_get_path (FilterLevel *level,
     {
       gtk_tree_path_prepend_index (path, walker2->offset);
 
-      walker2 = walker->parent_elt;
+      if (!walker->parent_level)
+        break;
+
+      walker2 = FILTER_LEVEL_PARENT_ELT (walker);
       walker = walker->parent_level;
     }
 
@@ -810,18 +819,21 @@ static gboolean
 gtk_tree_model_filter_elt_is_visible_in_target (FilterLevel *level,
                                                 FilterElt   *elt)
 {
+  gint elt_index;
+
   if (!elt->visible)
     return FALSE;
 
-  if (!level->parent_elt)
+  if (level->parent_elt_index == -1)
     return TRUE;
 
   do
     {
-      elt = level->parent_elt;
+      elt_index = level->parent_elt_index;
       level = level->parent_level;
 
-      if (elt && !elt->visible)
+      if (elt_index >= 0
+          && !g_array_index (level->array, FilterElt, elt_index).visible)
         return FALSE;
     }
   while (level);
@@ -873,11 +885,11 @@ gtk_tree_model_filter_fetch_child (GtkTreeModelFilter *filter,
   FilterElt elt;
 
   /* check if child exists and is visible */
-  if (level->parent_elt)
+  if (level->parent_elt_index >= 0)
     {
       c_parent_path =
         gtk_tree_model_filter_elt_get_path (level->parent_level,
-                                            level->parent_elt,
+                                            FILTER_LEVEL_PARENT_ELT (level),
                                             filter->priv->virtual_root);
       if (!c_parent_path)
         return NULL;
@@ -956,7 +968,7 @@ gtk_tree_model_filter_fetch_child (GtkTreeModelFilter *filter,
     {
       FilterElt *e = &(g_array_index (level->array, FilterElt, i));
       if (e->children)
-        e->children->parent_elt = e;
+        e->children->parent_elt_index = i;
     }
 
   c_iter.stamp = filter->priv->stamp;
@@ -975,14 +987,18 @@ gtk_tree_model_filter_remove_node (GtkTreeModelFilter *filter,
 {
   FilterElt *elt, *parent;
   FilterLevel *level, *parent_level;
-  gint i, length;
+  gint i, length, parent_elt_index;
 
   gboolean emit_child_toggled = FALSE;
 
   level = FILTER_LEVEL (iter->user_data);
   elt = FILTER_ELT (iter->user_data2);
 
-  parent = level->parent_elt;
+  parent_elt_index = level->parent_elt_index;
+  if (parent_elt_index >= 0)
+    parent = FILTER_LEVEL_PARENT_ELT (level);
+  else
+    parent = NULL;
   parent_level = level->parent_level;
 
   length = level->array->len;
@@ -999,8 +1015,8 @@ gtk_tree_model_filter_remove_node (GtkTreeModelFilter *filter,
 
   if (level != filter->priv->root
       && level->visible_nodes == 0
-      && level->parent_elt
-      && level->parent_elt->visible)
+      && parent
+      && parent->visible)
     emit_child_toggled = TRUE;
 
   if (length > 1)
@@ -1047,7 +1063,7 @@ gtk_tree_model_filter_remove_node (GtkTreeModelFilter *filter,
                */
               elt = &g_array_index (level->array, FilterElt, i);
               if (elt->children)
-                elt->children->parent_elt = elt;
+                elt->children->parent_elt_index = i;
             }
         }
     }
@@ -1294,7 +1310,7 @@ gtk_tree_model_filter_row_changed (GtkTreeModel *c_model,
     {
       FilterLevel *root;
 
-      gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
+      gtk_tree_model_filter_build_level (filter, NULL, -1, FALSE);
 
       root = FILTER_LEVEL (filter->priv->root);
     }
@@ -1432,7 +1448,7 @@ gtk_tree_model_filter_row_inserted (GtkTreeModel *c_model,
         goto done;
 
       /* build level will pull in the new child */
-      gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
+      gtk_tree_model_filter_build_level (filter, NULL, -1, FALSE);
 
       if (filter->priv->root
           && FILTER_LEVEL (filter->priv->root)->visible_nodes)
@@ -1559,7 +1575,7 @@ gtk_tree_model_filter_row_inserted (GtkTreeModel *c_model,
     {
       FilterElt *e = &g_array_index (level->array, FilterElt, i);
       if (e->children)
-        e->children->parent_elt = e;
+        e->children->parent_elt_index = i;
     }
 
   /* don't emit the signal if we aren't visible */
@@ -1618,7 +1634,7 @@ gtk_tree_model_filter_row_has_child_toggled (GtkTreeModel *c_model,
   if (filter->priv->virtual_root && !filter->priv->root
       && !gtk_tree_path_compare (c_path, filter->priv->virtual_root))
     {
-      gtk_tree_model_filter_build_level (filter, NULL, NULL, TRUE);
+      gtk_tree_model_filter_build_level (filter, NULL, -1, TRUE);
       return;
     }
 
@@ -1686,7 +1702,9 @@ gtk_tree_model_filter_row_has_child_toggled (GtkTreeModel *c_model,
    * can monitor it for changes.
    */
   if (elt->ref_count > 1 && gtk_tree_model_iter_has_child (c_model, c_iter))
-    gtk_tree_model_filter_build_level (filter, level, elt, TRUE);
+    gtk_tree_model_filter_build_level (filter, level,
+                                       FILTER_LEVEL_ELT_INDEX (level, elt),
+                                       TRUE);
 
   /* get a path taking only visible nodes into account */
   path = gtk_tree_model_get_path (GTK_TREE_MODEL (data), &iter);
@@ -1844,7 +1862,7 @@ gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model,
           if (elt->offset > offset)
             elt->offset--;
           if (elt->children)
-            elt->children->parent_elt = elt;
+            elt->children->parent_elt_index = i;
         }
 
       return;
@@ -1869,7 +1887,7 @@ gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model,
         {
           emit_child_toggled = TRUE;
           parent_level = level->parent_level;
-          parent = level->parent_elt;
+          parent = FILTER_LEVEL_PARENT_ELT (level);
         }
 
       /* emit row_deleted */
@@ -1914,7 +1932,7 @@ gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model,
           if (elt->offset > offset)
             elt->offset--;
           if (elt->children)
-            elt->children->parent_elt = elt;
+            elt->children->parent_elt_index = i;
         }
     }
 
@@ -2108,7 +2126,7 @@ gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model,
     {
       FilterElt *e = &g_array_index (level->array, FilterElt, i);
       if (e->children)
-        e->children->parent_elt = e;
+        e->children->parent_elt_index = i;
     }
 
   /* emit rows_reordered */
@@ -2209,7 +2227,7 @@ gtk_tree_model_filter_get_iter_full (GtkTreeModel *model,
   indices = gtk_tree_path_get_indices (path);
 
   if (filter->priv->root == NULL)
-    gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
+    gtk_tree_model_filter_build_level (filter, NULL, -1, FALSE);
   level = FILTER_LEVEL (filter->priv->root);
 
   depth = gtk_tree_path_get_depth (path);
@@ -2229,7 +2247,9 @@ gtk_tree_model_filter_get_iter_full (GtkTreeModel *model,
       elt = gtk_tree_model_filter_get_nth (filter, level, indices[i]);
 
       if (!elt->children)
-        gtk_tree_model_filter_build_level (filter, level, elt, FALSE);
+        gtk_tree_model_filter_build_level (filter, level,
+                                           FILTER_LEVEL_ELT_INDEX (level, elt),
+                                           FALSE);
       level = elt->children;
     }
 
@@ -2264,7 +2284,7 @@ gtk_tree_model_filter_get_iter (GtkTreeModel *model,
   indices = gtk_tree_path_get_indices (path);
 
   if (filter->priv->root == NULL)
-    gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
+    gtk_tree_model_filter_build_level (filter, NULL, -1, FALSE);
   level = FILTER_LEVEL (filter->priv->root);
 
   depth = gtk_tree_path_get_depth (path);
@@ -2284,7 +2304,9 @@ gtk_tree_model_filter_get_iter (GtkTreeModel *model,
       elt = gtk_tree_model_filter_get_nth_visible (filter, level, indices[i]);
 
       if (!elt->children)
-        gtk_tree_model_filter_build_level (filter, level, elt, FALSE);
+        gtk_tree_model_filter_build_level (filter, level,
+                                           FILTER_LEVEL_ELT_INDEX (level, elt),
+                                           FALSE);
       level = elt->children;
     }
 
@@ -2311,6 +2333,7 @@ gtk_tree_model_filter_get_path (GtkTreeModel *model,
   GtkTreePath *retval;
   FilterLevel *level;
   FilterElt *elt;
+  gint elt_index;
 
   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), NULL);
   g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, NULL);
@@ -2318,6 +2341,7 @@ gtk_tree_model_filter_get_path (GtkTreeModel *model,
 
   level = iter->user_data;
   elt = iter->user_data2;
+  elt_index = FILTER_LEVEL_ELT_INDEX (level, elt);
 
   if (!elt->visible)
     return NULL;
@@ -2328,7 +2352,7 @@ gtk_tree_model_filter_get_path (GtkTreeModel *model,
     {
       int i = 0, index = 0;
 
-      while (&g_array_index (level->array, FilterElt, i) != elt)
+      while (i < elt_index)
         {
           if (g_array_index (level->array, FilterElt, i).visible)
             index++;
@@ -2338,7 +2362,7 @@ gtk_tree_model_filter_get_path (GtkTreeModel *model,
         }
 
       gtk_tree_path_prepend_index (retval, index);
-      elt = level->parent_elt;
+      elt_index = level->parent_elt_index;
       level = level->parent_level;
     }
 
@@ -2431,7 +2455,7 @@ gtk_tree_model_filter_iter_children (GtkTreeModel *model,
       int i = 0;
 
       if (!filter->priv->root)
-        gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
+        gtk_tree_model_filter_build_level (filter, NULL, -1, FALSE);
       if (!filter->priv->root)
         return FALSE;
 
@@ -2461,20 +2485,24 @@ gtk_tree_model_filter_iter_children (GtkTreeModel *model,
   else
     {
       int i = 0;
+      FilterElt *elt;
+
+      elt = FILTER_ELT (parent->user_data2);
 
-      if (FILTER_ELT (parent->user_data2)->children == NULL)
+      if (elt->children == NULL)
         gtk_tree_model_filter_build_level (filter,
                                            FILTER_LEVEL (parent->user_data),
-                                           FILTER_ELT (parent->user_data2),
+                                           FILTER_LEVEL_ELT_INDEX (parent->user_data, elt),
                                            FALSE);
-      if (FILTER_ELT (parent->user_data2)->children == NULL)
+
+      if (elt->children == NULL)
         return FALSE;
 
-      if (FILTER_ELT (parent->user_data2)->children->visible_nodes <= 0)
+      if (elt->children->visible_nodes <= 0)
         return FALSE;
 
       iter->stamp = filter->priv->stamp;
-      iter->user_data = FILTER_ELT (parent->user_data2)->children;
+      iter->user_data = elt->children;
 
       level = FILTER_LEVEL (iter->user_data);
 
@@ -2524,7 +2552,8 @@ gtk_tree_model_filter_iter_has_child (GtkTreeModel *model,
   if (!elt->children
       && gtk_tree_model_iter_has_child (filter->priv->child_model, &child_iter))
     gtk_tree_model_filter_build_level (filter, FILTER_LEVEL (iter->user_data),
-                                       elt, FALSE);
+                                       FILTER_LEVEL_ELT_INDEX (iter->user_data, elt),
+                                       FALSE);
 
   if (elt->children && elt->children->visible_nodes > 0)
     return TRUE;
@@ -2548,7 +2577,7 @@ gtk_tree_model_filter_iter_n_children (GtkTreeModel *model,
   if (!iter)
     {
       if (!filter->priv->root)
-        gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
+        gtk_tree_model_filter_build_level (filter, NULL, -1, FALSE);
 
       if (filter->priv->root)
         return FILTER_LEVEL (filter->priv->root)->visible_nodes;
@@ -2567,7 +2596,8 @@ gtk_tree_model_filter_iter_n_children (GtkTreeModel *model,
       gtk_tree_model_iter_has_child (filter->priv->child_model, &child_iter))
     gtk_tree_model_filter_build_level (filter,
                                        FILTER_LEVEL (iter->user_data),
-                                       elt, FALSE);
+                                       FILTER_LEVEL_ELT_INDEX (iter->user_data, elt),
+                                       FALSE);
 
   if (elt->children)
     return elt->children->visible_nodes;
@@ -2633,7 +2663,7 @@ gtk_tree_model_filter_iter_parent (GtkTreeModel *model,
     {
       iter->stamp = GTK_TREE_MODEL_FILTER (model)->priv->stamp;
       iter->user_data = level->parent_level;
-      iter->user_data2 = level->parent_elt;
+      iter->user_data2 = FILTER_LEVEL_PARENT_ELT (level);
 
       return TRUE;
     }
@@ -2666,14 +2696,14 @@ gtk_tree_model_filter_ref_node (GtkTreeModel *model,
   if (level->ref_count == 1)
     {
       FilterLevel *parent_level = level->parent_level;
-      FilterElt *parent_elt = level->parent_elt;
+      gint parent_elt_index = level->parent_elt_index;
 
       /* we were at zero -- time to decrease the zero_ref_count val */
       while (parent_level)
         {
-	  parent_elt->zero_ref_count--;
+          g_array_index (parent_level->array, FilterElt, parent_elt_index).zero_ref_count--;
 
-	  parent_elt = parent_level->parent_elt;
+          parent_elt_index = parent_level->parent_elt_index;
 	  parent_level = parent_level->parent_level;
         }
 
@@ -2719,14 +2749,14 @@ gtk_tree_model_filter_real_unref_node (GtkTreeModel *model,
   if (level->ref_count == 0)
     {
       FilterLevel *parent_level = level->parent_level;
-      FilterElt *parent_elt = level->parent_elt;
+      gint parent_elt_index = level->parent_elt_index;
 
       /* we are at zero -- time to increase the zero_ref_count val */
       while (parent_level)
         {
-          parent_elt->zero_ref_count++;
+          g_array_index (parent_level->array, FilterElt, parent_elt_index).zero_ref_count++;
 
-          parent_elt = parent_level->parent_elt;
+          parent_elt_index = parent_level->parent_elt_index;
           parent_level = parent_level->parent_level;
         }
 
@@ -3221,7 +3251,7 @@ gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filte
   child_indices = gtk_tree_path_get_indices (real_path);
 
   if (filter->priv->root == NULL && build_levels)
-    gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
+    gtk_tree_model_filter_build_level (filter, NULL, -1, FALSE);
   level = FILTER_LEVEL (filter->priv->root);
 
   for (i = 0; i < gtk_tree_path_get_depth (real_path); i++)
@@ -3241,7 +3271,9 @@ gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filte
         {
           gtk_tree_path_append_index (retval, j);
           if (!tmp->children && build_levels)
-            gtk_tree_model_filter_build_level (filter, level, tmp, FALSE);
+            gtk_tree_model_filter_build_level (filter, level,
+                                               FILTER_LEVEL_ELT_INDEX (level, tmp),
+                                               FALSE);
           level = tmp->children;
           found_child = TRUE;
         }
@@ -3263,7 +3295,9 @@ gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filte
 
           gtk_tree_path_append_index (retval, j);
           if (!tmp->children && build_levels)
-            gtk_tree_model_filter_build_level (filter, level, tmp, FALSE);
+            gtk_tree_model_filter_build_level (filter, level,
+                                               FILTER_LEVEL_ELT_INDEX (level, tmp),
+                                               FALSE);
           level = tmp->children;
           found_child = TRUE;
         }
@@ -3355,7 +3389,7 @@ gtk_tree_model_filter_convert_path_to_child_path (GtkTreeModelFilter *filter,
   retval = gtk_tree_path_new ();
   filter_indices = gtk_tree_path_get_indices (filter_path);
   if (!filter->priv->root)
-    gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
+    gtk_tree_model_filter_build_level (filter, NULL, -1, FALSE);
   level = FILTER_LEVEL (filter->priv->root);
 
   for (i = 0; i < gtk_tree_path_get_depth (filter_path); i++)
@@ -3372,7 +3406,9 @@ gtk_tree_model_filter_convert_path_to_child_path (GtkTreeModelFilter *filter,
                                                    filter_indices[i]);
 
       if (elt->children == NULL)
-        gtk_tree_model_filter_build_level (filter, level, elt, FALSE);
+        gtk_tree_model_filter_build_level (filter, level,
+                                           FILTER_LEVEL_ELT_INDEX (level, elt),
+                                           FALSE);
 
       if (!level || level->visible_nodes <= filter_indices[i])
         {
diff --git a/gtk/gtktreemodelsort.c b/gtk/gtktreemodelsort.c
index 4525bca..f07795c 100644
--- a/gtk/gtktreemodelsort.c
+++ b/gtk/gtktreemodelsort.c
@@ -67,7 +67,7 @@ struct _SortLevel
 {
   GArray    *array;
   gint       ref_count;
-  SortElt   *parent_elt;
+  gint       parent_elt_index;
   SortLevel *parent_level;
 };
 
@@ -101,6 +101,10 @@ enum {
 #define SORT_ELT(sort_elt) ((SortElt *)sort_elt)
 #define SORT_LEVEL(sort_level) ((SortLevel *)sort_level)
 
+#define SORT_LEVEL_PARENT_ELT(level) (&g_array_index (SORT_LEVEL ((level))->parent_level->array, SortElt, SORT_LEVEL ((level))->parent_elt_index))
+#define SORT_LEVEL_ELT_INDEX(level, elt) (SORT_ELT ((elt)) - SORT_ELT (SORT_LEVEL ((level))->array->data))
+
+
 #define GET_CHILD_ITER(tree_model_sort,ch_iter,so_iter) gtk_tree_model_sort_convert_iter_to_child_iter((GtkTreeModelSort*)(tree_model_sort), (ch_iter), (so_iter));
 
 #define NO_SORT_FUNC ((GtkTreeIterCompareFunc) 0x1)
@@ -211,7 +215,7 @@ static gboolean     gtk_tree_model_sort_has_default_sort_func (GtkTreeSortable
 /* Private functions (sort funcs, level handling and other utils) */
 static void         gtk_tree_model_sort_build_level       (GtkTreeModelSort *tree_model_sort,
 							   SortLevel        *parent_level,
-							   SortElt          *parent_elt);
+							   gint              parent_elt_index);
 static void         gtk_tree_model_sort_free_level        (GtkTreeModelSort *tree_model_sort,
 							   SortLevel        *sort_level);
 static void         gtk_tree_model_sort_increment_stamp   (GtkTreeModelSort *tree_model_sort);
@@ -499,7 +503,7 @@ gtk_tree_model_sort_row_changed (GtkTreeModel *s_model,
 
   for (i = 0; i < level->array->len; i++)
     if (g_array_index (level->array, SortElt, i).children)
-      g_array_index (level->array, SortElt, i).children->parent_elt = &g_array_index (level->array, SortElt, i);
+      g_array_index (level->array, SortElt, i).children->parent_elt_index = i;
 
   gtk_tree_path_up (path);
   gtk_tree_path_append_index (path, index);
@@ -539,11 +543,11 @@ gtk_tree_model_sort_row_changed (GtkTreeModel *s_model,
 	  /* else? shouldn't really happen */
 	}
 
-      if (level->parent_elt)
+      if (level->parent_elt_index >= 0)
         {
 	  iter.stamp = tree_model_sort->stamp;
 	  iter.user_data = level->parent_level;
-	  iter.user_data2 = level->parent_elt;
+	  iter.user_data2 = SORT_LEVEL_PARENT_ELT (level);
 
 	  tmppath = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_model_sort), &iter);
 
@@ -609,7 +613,7 @@ gtk_tree_model_sort_row_inserted (GtkTreeModel          *s_model,
 
   if (!tree_model_sort->root)
     {
-      gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
+      gtk_tree_model_sort_build_level (tree_model_sort, NULL, -1);
 
       /* the build level already put the inserted iter in the level,
 	 so no need to handle this signal anymore */
@@ -785,7 +789,7 @@ gtk_tree_model_sort_row_deleted (GtkTreeModel *s_model,
       if (elt->offset > offset)
 	elt->offset--;
       if (elt->children)
-	elt->children->parent_elt = elt;
+	elt->children->parent_elt_index = i;
     }
 
   gtk_tree_path_free (path);
@@ -934,7 +938,7 @@ gtk_tree_model_sort_get_iter (GtkTreeModel *tree_model,
   indices = gtk_tree_path_get_indices (path);
 
   if (tree_model_sort->root == NULL)
-    gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
+    gtk_tree_model_sort_build_level (tree_model_sort, NULL, -1);
   level = SORT_LEVEL (tree_model_sort->root);
 
   depth = gtk_tree_path_get_depth (path);
@@ -948,7 +952,7 @@ gtk_tree_model_sort_get_iter (GtkTreeModel *tree_model,
 	return FALSE;
 
       if (g_array_index (level->array, SortElt, indices[i]).children == NULL)
-	gtk_tree_model_sort_build_level (tree_model_sort, level, &g_array_index (level->array, SortElt, indices[i]));
+	gtk_tree_model_sort_build_level (tree_model_sort, level, indices[i]);
       level = g_array_index (level->array, SortElt, indices[i]).children;
     }
 
@@ -972,19 +976,21 @@ gtk_tree_model_sort_get_path (GtkTreeModel *tree_model,
   GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
   GtkTreePath *retval;
   SortLevel *level;
-  SortElt *elt;
+  gint elt_index;
 
   g_return_val_if_fail (tree_model_sort->child_model != NULL, NULL);
   g_return_val_if_fail (tree_model_sort->stamp == iter->stamp, NULL);
 
   retval = gtk_tree_path_new ();
-  level = iter->user_data;
-  elt = iter->user_data2;
-  while (level != NULL)
+
+  level = SORT_LEVEL (iter->user_data);
+  elt_index = SORT_LEVEL_ELT_INDEX (level, iter->user_data2);
+
+  while (level)
     {
-      gtk_tree_path_prepend_index (retval, elt - (SortElt *)level->array->data);
+      gtk_tree_path_prepend_index (retval, elt_index);
 
-      elt = level->parent_elt;
+      elt_index = level->parent_elt_index;
       level = level->parent_level;
     }
 
@@ -1048,7 +1054,7 @@ gtk_tree_model_sort_iter_children (GtkTreeModel *tree_model,
   if (parent == NULL)
     {
       if (tree_model_sort->root == NULL)
-	gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
+	gtk_tree_model_sort_build_level (tree_model_sort, NULL, -1);
       if (tree_model_sort->root == NULL)
 	return FALSE;
 
@@ -1059,15 +1065,21 @@ gtk_tree_model_sort_iter_children (GtkTreeModel *tree_model,
     }
   else
     {
-      if (((SortElt *)parent->user_data2)->children == NULL)
-	gtk_tree_model_sort_build_level (tree_model_sort,
-					 (SortLevel *)parent->user_data,
-					 (SortElt *)parent->user_data2);
-      if (((SortElt *)parent->user_data2)->children == NULL)
+      SortElt *elt;
+
+      level = SORT_LEVEL (parent->user_data);
+      elt = SORT_ELT (parent->user_data2);
+
+      if (elt->children == NULL)
+        gtk_tree_model_sort_build_level (tree_model_sort, level,
+                                         SORT_LEVEL_ELT_INDEX (level, elt));
+
+      if (elt->children == NULL)
 	return FALSE;
+
       iter->stamp = tree_model_sort->stamp;
-      iter->user_data = ((SortElt *)parent->user_data2)->children;
-      iter->user_data2 = ((SortLevel *)iter->user_data)->array->data;
+      iter->user_data = elt->children;
+      iter->user_data2 = elt->children->array->data;
     }
 
   return TRUE;
@@ -1160,7 +1172,7 @@ gtk_tree_model_sort_iter_parent (GtkTreeModel *tree_model,
     {
       iter->stamp = tree_model_sort->stamp;
       iter->user_data = level->parent_level;
-      iter->user_data2 = level->parent_elt;
+      iter->user_data2 = SORT_LEVEL_PARENT_ELT (level);
 
       return TRUE;
     }
@@ -1173,9 +1185,9 @@ gtk_tree_model_sort_ref_node (GtkTreeModel *tree_model,
 {
   GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
   GtkTreeIter child_iter;
-  GtkTreeIter tmp_iter;
-  SortLevel *level;
+  SortLevel *level, *parent_level;
   SortElt *elt;
+  gint parent_elt_index;
 
   g_return_if_fail (tree_model_sort->child_model != NULL);
   g_return_if_fail (VALID_ITER (iter, tree_model_sort));
@@ -1193,28 +1205,34 @@ gtk_tree_model_sort_ref_node (GtkTreeModel *tree_model,
   level->ref_count++;
 
   /* Increase the reference count of all parent elements */
-  tmp_iter.stamp = tree_model_sort->stamp;
-  tmp_iter.user_data = level->parent_level;
-  tmp_iter.user_data2 = level->parent_elt;;
+  parent_level = level->parent_level;
+  parent_elt_index = level->parent_elt_index;
 
-  while (tmp_iter.user_data2)
+  while (parent_level)
     {
+      GtkTreeIter tmp_iter;
+
+      tmp_iter.stamp = tree_model_sort->stamp;
+      tmp_iter.user_data = parent_level;
+      tmp_iter.user_data2 = &g_array_index (parent_level->array, SortElt, parent_elt_index);
+
       gtk_tree_model_sort_ref_node (tree_model, &tmp_iter);
 
-      tmp_iter.user_data2 = SORT_LEVEL (tmp_iter.user_data)->parent_elt;
-      tmp_iter.user_data = SORT_LEVEL (tmp_iter.user_data)->parent_level;
+      parent_elt_index = parent_level->parent_elt_index;
+      parent_level = parent_level->parent_level;
     }
 
   if (level->ref_count == 1)
     {
       SortLevel *parent_level = level->parent_level;
-      SortElt *parent_elt = level->parent_elt;
+      gint parent_elt_index = level->parent_elt_index;
+
       /* We were at zero -- time to decrement the zero_ref_count val */
       while (parent_level)
-	{
-	  parent_elt->zero_ref_count--;
+        {
+	  g_array_index (parent_level->array, SortElt, parent_elt_index).zero_ref_count--;
 
-	  parent_elt = parent_level->parent_elt;
+          parent_elt_index = parent_level->parent_elt_index;
 	  parent_level = parent_level->parent_level;
 	}
 
@@ -1229,9 +1247,9 @@ gtk_tree_model_sort_real_unref_node (GtkTreeModel *tree_model,
 				     gboolean      propagate_unref)
 {
   GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
-  GtkTreeIter tmp_iter;
-  SortLevel *level;
+  SortLevel *level, *parent_level;
   SortElt *elt;
+  gint parent_elt_index;
 
   g_return_if_fail (tree_model_sort->child_model != NULL);
   g_return_if_fail (VALID_ITER (iter, tree_model_sort));
@@ -1253,29 +1271,34 @@ gtk_tree_model_sort_real_unref_node (GtkTreeModel *tree_model,
   level->ref_count--;
 
   /* Decrease the reference count of all parent elements */
-  tmp_iter.stamp = tree_model_sort->stamp;
-  tmp_iter.user_data = level->parent_level;
-  tmp_iter.user_data2 = level->parent_elt;;
+  parent_level = level->parent_level;
+  parent_elt_index = level->parent_elt_index;
 
-  while (tmp_iter.user_data2)
+  while (parent_level)
     {
+      GtkTreeIter tmp_iter;
+
+      tmp_iter.stamp = tree_model_sort->stamp;
+      tmp_iter.user_data = parent_level;
+      tmp_iter.user_data2 = &g_array_index (parent_level->array, SortElt, parent_elt_index);
+
       gtk_tree_model_sort_real_unref_node (tree_model, &tmp_iter, FALSE);
 
-      tmp_iter.user_data2 = SORT_LEVEL (tmp_iter.user_data)->parent_elt;
-      tmp_iter.user_data = SORT_LEVEL (tmp_iter.user_data)->parent_level;
+      parent_elt_index = parent_level->parent_elt_index;
+      parent_level = parent_level->parent_level;
     }
 
   if (level->ref_count == 0)
     {
       SortLevel *parent_level = level->parent_level;
-      SortElt *parent_elt = level->parent_elt;
+      gint parent_elt_index = level->parent_elt_index;
 
       /* We are at zero -- time to increment the zero_ref_count val */
       while (parent_level)
 	{
-	  parent_elt->zero_ref_count++;
+	  g_array_index (parent_level->array, SortElt, parent_elt_index).zero_ref_count++;
 
-	  parent_elt = parent_level->parent_elt;
+	  parent_elt_index = parent_level->parent_elt_index;
 	  parent_level = parent_level->parent_level;
 	}
 
@@ -1558,10 +1581,10 @@ gtk_tree_model_sort_sort_level (GtkTreeModelSort *tree_model_sort,
 
   /* Set up data */
   data.tree_model_sort = tree_model_sort;
-  if (level->parent_elt)
+  if (level->parent_elt_index >= 0)
     {
       data.parent_path = gtk_tree_model_sort_elt_get_path (level->parent_level,
-							   level->parent_elt);
+							   SORT_LEVEL_PARENT_ELT (level));
       gtk_tree_path_append_index (data.parent_path, 0);
     }
   else
@@ -1627,9 +1650,8 @@ gtk_tree_model_sort_sort_level (GtkTreeModelSort *tree_model_sort,
       new_order[i] = g_array_index (sort_array, SortTuple, i).offset;
 
       g_array_append_val (new_array, *elt);
-      elt = &g_array_index (new_array, SortElt, i);
       if (elt->children)
-	elt->children->parent_elt = elt;
+	elt->children->parent_elt_index = i;
     }
 
   g_array_free (level->array, TRUE);
@@ -1639,11 +1661,11 @@ gtk_tree_model_sort_sort_level (GtkTreeModelSort *tree_model_sort,
   if (emit_reordered)
     {
       gtk_tree_model_sort_increment_stamp (tree_model_sort);
-      if (level->parent_elt)
+      if (level->parent_elt_index >= 0)
 	{
 	  iter.stamp = tree_model_sort->stamp;
 	  iter.user_data = level->parent_level;
-	  iter.user_data2 = level->parent_elt;
+	  iter.user_data2 = SORT_LEVEL_PARENT_ELT (level);
 
 	  path = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_model_sort),
 					  &iter);
@@ -1846,7 +1868,7 @@ gtk_tree_model_sort_insert_value (GtkTreeModelSort *tree_model_sort,
   tmp_elt = SORT_ELT (level->array->data);
   for (i = 0; i < level->array->len; i++, tmp_elt++)
     if (tmp_elt->children)
-      tmp_elt->children->parent_elt = tmp_elt;
+      tmp_elt->children->parent_elt_index = i;
 
   return TRUE;
 }
@@ -1869,7 +1891,10 @@ gtk_tree_model_sort_elt_get_path (SortLevel *level,
     {
       gtk_tree_path_prepend_index (path, walker2->offset);
 
-      walker2 = walker->parent_elt;
+      if (!walker->parent_level)
+	break;
+
+      walker2 = SORT_LEVEL_PARENT_ELT (walker);
       walker = walker->parent_level;
     }
 
@@ -1992,7 +2017,7 @@ gtk_real_tree_model_sort_convert_child_path_to_path (GtkTreeModelSort *tree_mode
   child_indices = gtk_tree_path_get_indices (child_path);
 
   if (tree_model_sort->root == NULL && build_levels)
-    gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
+    gtk_tree_model_sort_build_level (tree_model_sort, NULL, -1);
   level = SORT_LEVEL (tree_model_sort->root);
 
   for (i = 0; i < gtk_tree_path_get_depth (child_path); i++)
@@ -2018,7 +2043,7 @@ gtk_real_tree_model_sort_convert_child_path_to_path (GtkTreeModelSort *tree_mode
 	      gtk_tree_path_append_index (retval, j);
 	      if (g_array_index (level->array, SortElt, j).children == NULL && build_levels)
 		{
-		  gtk_tree_model_sort_build_level (tree_model_sort, level, &g_array_index (level->array, SortElt, j));
+		  gtk_tree_model_sort_build_level (tree_model_sort, level, j);
 		}
 	      level = g_array_index (level->array, SortElt, j).children;
 	      found_child = TRUE;
@@ -2136,7 +2161,7 @@ gtk_tree_model_sort_convert_path_to_child_path (GtkTreeModelSort *tree_model_sor
   retval = gtk_tree_path_new ();
   sorted_indices = gtk_tree_path_get_indices (sorted_path);
   if (tree_model_sort->root == NULL)
-    gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
+    gtk_tree_model_sort_build_level (tree_model_sort, NULL, -1);
   level = SORT_LEVEL (tree_model_sort->root);
 
   for (i = 0; i < gtk_tree_path_get_depth (sorted_path); i++)
@@ -2151,7 +2176,7 @@ gtk_tree_model_sort_convert_path_to_child_path (GtkTreeModelSort *tree_model_sor
 	}
 
       if (g_array_index (level->array, SortElt, count).children == NULL)
-	gtk_tree_model_sort_build_level (tree_model_sort, level, &g_array_index (level->array, SortElt, count));
+	gtk_tree_model_sort_build_level (tree_model_sort, level, count);
 
       if (level == NULL)
         {
@@ -2203,9 +2228,10 @@ gtk_tree_model_sort_convert_iter_to_child_iter (GtkTreeModelSort *tree_model_sor
 static void
 gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
 				 SortLevel        *parent_level,
-				 SortElt          *parent_elt)
+				 gint              parent_elt_index)
 {
   GtkTreeIter iter;
+  SortElt *parent_elt = NULL;
   SortLevel *new_level;
   gint length = 0;
   gint i;
@@ -2223,6 +2249,8 @@ gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
       GtkTreeIter parent_iter;
       GtkTreeIter child_parent_iter;
 
+      parent_elt = &g_array_index (parent_level->array, SortElt, parent_elt_index);
+
       parent_iter.stamp = tree_model_sort->stamp;
       parent_iter.user_data = parent_level;
       parent_iter.user_data2 = parent_elt;
@@ -2248,10 +2276,10 @@ gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
   new_level = g_new (SortLevel, 1);
   new_level->array = g_array_sized_new (FALSE, FALSE, sizeof (SortElt), length);
   new_level->ref_count = 0;
-  new_level->parent_elt = parent_elt;
   new_level->parent_level = parent_level;
+  new_level->parent_elt_index = parent_elt_index;
 
-  if (parent_elt)
+  if (parent_elt_index >= 0)
     parent_elt->children = new_level;
   else
     tree_model_sort->root = new_level;
@@ -2259,11 +2287,12 @@ gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
   /* increase the count of zero ref_counts.*/
   while (parent_level)
     {
-      parent_elt->zero_ref_count++;
+      g_array_index (parent_level->array, SortElt, parent_elt_index).zero_ref_count++;
 
-      parent_elt = parent_level->parent_elt;
+      parent_elt_index = parent_level->parent_elt_index;
       parent_level = parent_level->parent_level;
     }
+
   if (new_level != tree_model_sort->root)
     tree_model_sort->zero_ref_count++;
 
@@ -2334,13 +2363,13 @@ gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort,
   if (sort_level->ref_count == 0)
     {
       SortLevel *parent_level = sort_level->parent_level;
-      SortElt *parent_elt = sort_level->parent_elt;
+      gint parent_elt_index = sort_level->parent_elt_index;
 
       while (parent_level)
-	{
-	  parent_elt->zero_ref_count--;
+        {
+	  g_array_index (parent_level->array, SortElt, parent_elt_index).zero_ref_count--;
 
-	  parent_elt = parent_level->parent_elt;
+          parent_elt_index = parent_level->parent_elt_index;
 	  parent_level = parent_level->parent_level;
 	}
 
@@ -2348,8 +2377,8 @@ gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort,
 	tree_model_sort->zero_ref_count--;
     }
 
-  if (sort_level->parent_elt)
-    sort_level->parent_elt->children = NULL;
+  if (sort_level->parent_elt_index >= 0)
+    SORT_LEVEL_PARENT_ELT (sort_level)->children = NULL;
   else
     tree_model_sort->root = NULL;
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]