--- gtkwidgetpath.c.0	2012-07-15 20:36:23.000000000 -0400
+++ gtkwidgetpath.c	2012-07-16 18:36:06.712024198 -0400
@@ -1,5 +1,6 @@
 /* GTK - The GIMP Toolkit
  * Copyright (C) 2010 Carlos Garnacho <carlosg@gnome.org>
+ * Copyright (C) 2012 John Lindgren <john.lindgren@aol.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -87,6 +88,8 @@
 
 struct GtkPathElement
 {
+  volatile guint ref_count;
+
   GType type;
   GQuark name;
   GHashTable *regions;
@@ -117,18 +120,55 @@
   GtkWidgetPath *path;
 
   path = g_slice_new0 (GtkWidgetPath);
-  path->elems = g_array_new (FALSE, TRUE, sizeof (GtkPathElement));
+  path->elems = g_array_new (FALSE, TRUE, sizeof (GtkPathElement *));
   path->ref_count = 1;
 
   return path;
 }
 
+static GtkPathElement *
+gtk_path_element_new (void)
+{
+  GtkPathElement *elem;
+
+  elem = g_slice_new0 (GtkPathElement);
+  elem->ref_count = 1;
+
+  return elem;
+}
+
+static GtkPathElement *
+gtk_path_element_ref (GtkPathElement *elem)
+{
+  g_atomic_int_add (&elem->ref_count, 1);
+
+  return elem;
+}
+
 static void
-gtk_path_element_copy (GtkPathElement       *dest,
-                       const GtkPathElement *src)
+gtk_path_element_unref (GtkPathElement *elem)
 {
-  memset (dest, 0, sizeof (GtkPathElement));
+  if (!g_atomic_int_dec_and_test (&elem->ref_count))
+    return;
+
+  if (elem->regions)
+    g_hash_table_destroy (elem->regions);
 
+  if (elem->classes)
+    g_array_free (elem->classes, TRUE);
+
+  if (elem->siblings)
+    gtk_widget_path_unref (elem->siblings);
+
+  g_slice_free (GtkPathElement, elem);
+}
+
+static GtkPathElement *
+gtk_path_element_copy (const GtkPathElement *src)
+{
+  GtkPathElement *dest;
+
+  dest = gtk_path_element_new ();
   dest->type = src->type;
   dest->name = src->name;
   if (src->siblings)
@@ -152,6 +192,35 @@
       dest->classes = g_array_new (FALSE, FALSE, sizeof (GQuark));
       g_array_append_vals (dest->classes, src->classes->data, src->classes->len);
     }
+
+  return dest;
+}
+
+static GtkPathElement *
+gtk_path_element_break_refs (GtkPathElement *elem)
+{
+  GtkPathElement *copy;
+
+  if (g_atomic_int_get (&elem->ref_count) == 1)
+    return elem;
+
+  copy = gtk_path_element_copy (elem);
+  gtk_path_element_unref (elem);
+
+  return copy;
+}
+
+static GtkPathElement *
+break_element_refs (GtkWidgetPath *path,
+                    guint pos)
+{
+  GtkPathElement *elem;
+
+  elem = g_array_index (path->elems, GtkPathElement *, pos);
+  elem = gtk_path_element_break_refs (elem);
+  g_array_index (path->elems, GtkPathElement *, pos) = elem;
+
+  return elem;
 }
 
 /**
@@ -178,12 +247,11 @@
 
   for (i = 0; i < path->elems->len; i++)
     {
-      GtkPathElement *elem, *dest;
-
-      elem = &g_array_index (path->elems, GtkPathElement, i);
-      dest = &g_array_index (new_path->elems, GtkPathElement, i);
+      GtkPathElement *elem;
 
-      gtk_path_element_copy (dest, elem);
+      elem = g_array_index (path->elems, GtkPathElement *, i);
+      gtk_path_element_ref (elem);
+      g_array_index (new_path->elems, GtkPathElement *, i) = elem;
     }
 
   return new_path;
@@ -232,16 +300,8 @@
     {
       GtkPathElement *elem;
 
-      elem = &g_array_index (path->elems, GtkPathElement, i);
-
-      if (elem->regions)
-        g_hash_table_destroy (elem->regions);
-
-      if (elem->classes)
-        g_array_free (elem->classes, TRUE);
-
-      if (elem->siblings)
-        gtk_widget_path_unref (elem->siblings);
+      elem = g_array_index (path->elems, GtkPathElement *, i);
+      gtk_path_element_unref (elem);
     }
 
   g_array_free (path->elems, TRUE);
@@ -311,9 +371,9 @@
 
   for (i = 0; i < path->elems->len; i++)
     {
-      GtkPathElement *elem;
+      const GtkPathElement *elem;
 
-      elem = &g_array_index (path->elems, GtkPathElement, i);
+      elem = g_array_index (path->elems, GtkPathElement *, i);
 
       if (i > 0)
         g_string_append_c (string, ' ');
@@ -390,11 +450,12 @@
 gtk_widget_path_prepend_type (GtkWidgetPath *path,
                               GType          type)
 {
-  GtkPathElement new = { 0 };
+  GtkPathElement *new;
 
   g_return_if_fail (path != NULL);
 
-  new.type = type;
+  new = gtk_path_element_new ();
+  new->type = type;
   g_array_prepend_val (path->elems, new);
 }
 
@@ -413,11 +474,12 @@
 gtk_widget_path_append_type (GtkWidgetPath *path,
                              GType          type)
 {
-  GtkPathElement new = { 0 };
+  GtkPathElement *new;
 
   g_return_val_if_fail (path != NULL, 0);
 
-  new.type = type;
+  new = gtk_path_element_new ();
+  new->type = type;
   g_array_append_val (path->elems, new);
 
   return path->elems->len - 1;
@@ -449,15 +511,18 @@
                                       GtkWidgetPath *siblings,
                                       guint          sibling_index)
 {
-  GtkPathElement new;
+  const GtkPathElement *old;
+  GtkPathElement *new;
 
   g_return_val_if_fail (path != NULL, 0);
   g_return_val_if_fail (siblings != NULL, 0);
   g_return_val_if_fail (sibling_index < gtk_widget_path_length (siblings), 0);
 
-  gtk_path_element_copy (&new, &g_array_index (siblings->elems, GtkPathElement, sibling_index));
-  new.siblings = gtk_widget_path_ref (siblings);
-  new.sibling_index = sibling_index;
+  old = g_array_index (siblings->elems, GtkPathElement *, sibling_index);
+
+  new = gtk_path_element_copy (old);
+  new->siblings = gtk_widget_path_ref (siblings);
+  new->sibling_index = sibling_index;
   g_array_append_val (path->elems, new);
 
   return path->elems->len - 1;
@@ -477,7 +542,7 @@
 gtk_widget_path_iter_get_siblings (const GtkWidgetPath *path,
                                    gint                 pos)
 {
-  GtkPathElement *elem;
+  const GtkPathElement *elem;
 
   g_return_val_if_fail (path != NULL, G_TYPE_INVALID);
   g_return_val_if_fail (path->elems->len != 0, G_TYPE_INVALID);
@@ -485,7 +550,7 @@
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  elem = g_array_index (path->elems, GtkPathElement *, pos);
   return elem->siblings;
 }
 
@@ -505,7 +570,7 @@
 gtk_widget_path_iter_get_sibling_index (const GtkWidgetPath *path,
                                         gint                 pos)
 {
-  GtkPathElement *elem;
+  const GtkPathElement *elem;
 
   g_return_val_if_fail (path != NULL, G_TYPE_INVALID);
   g_return_val_if_fail (path->elems->len != 0, G_TYPE_INVALID);
@@ -513,7 +578,7 @@
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  elem = g_array_index (path->elems, GtkPathElement *, pos);
   return elem->sibling_index;
 }
 
@@ -533,7 +598,7 @@
 gtk_widget_path_iter_get_object_type (const GtkWidgetPath *path,
                                       gint                 pos)
 {
-  GtkPathElement *elem;
+  const GtkPathElement *elem;
 
   g_return_val_if_fail (path != NULL, G_TYPE_INVALID);
   g_return_val_if_fail (path->elems->len != 0, G_TYPE_INVALID);
@@ -541,7 +606,7 @@
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  elem = g_array_index (path->elems, GtkPathElement *, pos);
   return elem->type;
 }
 
@@ -569,7 +634,7 @@
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  elem = break_element_refs (path, pos);
   elem->type = type;
 }
 
@@ -588,7 +653,7 @@
 gtk_widget_path_iter_get_name (const GtkWidgetPath *path,
                                gint                 pos)
 {
-  GtkPathElement *elem;
+  const GtkPathElement *elem;
 
   g_return_val_if_fail (path != NULL, NULL);
   g_return_val_if_fail (path->elems->len != 0, NULL);
@@ -596,7 +661,7 @@
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  elem = g_array_index (path->elems, GtkPathElement *, pos);
   return g_quark_to_string (elem->name);
 }
 
@@ -625,8 +690,7 @@
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
-
+  elem = break_element_refs (path, pos);
   elem->name = g_quark_from_string (name);
 }
 
@@ -648,7 +712,7 @@
                                 gint                 pos,
                                 GQuark               qname)
 {
-  GtkPathElement *elem;
+  const GtkPathElement *elem;
 
   g_return_val_if_fail (path != NULL, FALSE);
   g_return_val_if_fail (path->elems->len != 0, FALSE);
@@ -657,7 +721,7 @@
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  elem = g_array_index (path->elems, GtkPathElement *, pos);
 
   return (elem->name == qname);
 }
@@ -725,7 +789,7 @@
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  elem = break_element_refs (path, pos);
   qname = g_quark_from_string (name);
 
   if (!elem->classes)
@@ -787,7 +851,7 @@
   if (qname == 0)
     return;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  elem = break_element_refs (path, pos);
 
   if (!elem->classes)
     return;
@@ -830,7 +894,7 @@
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  elem = break_element_refs (path, pos);
 
   if (!elem->classes)
     return;
@@ -858,7 +922,7 @@
 gtk_widget_path_iter_list_classes (const GtkWidgetPath *path,
                                    gint                 pos)
 {
-  GtkPathElement *elem;
+  const GtkPathElement *elem;
   GSList *list = NULL;
   guint i;
 
@@ -868,7 +932,7 @@
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  elem = g_array_index (path->elems, GtkPathElement *, pos);
 
   if (!elem->classes)
     return NULL;
@@ -902,7 +966,7 @@
                                  gint                 pos,
                                  GQuark               qname)
 {
-  GtkPathElement *elem;
+  const GtkPathElement *elem;
   guint i;
 
   g_return_val_if_fail (path != NULL, FALSE);
@@ -912,7 +976,7 @@
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  elem = g_array_index (path->elems, GtkPathElement *, pos);
 
   if (!elem->classes)
     return FALSE;
@@ -1000,7 +1064,7 @@
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  elem = break_element_refs (path, pos);
   qname = g_quark_from_string (name);
 
   if (!elem->regions)
@@ -1042,7 +1106,7 @@
   if (qname == 0)
     return;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  elem = break_element_refs (path, pos);
 
   if (elem->regions)
     g_hash_table_remove (elem->regions, GUINT_TO_POINTER (qname));
@@ -1070,7 +1134,7 @@
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  elem = break_element_refs (path, pos);
 
   if (elem->regions)
     g_hash_table_remove_all (elem->regions);
@@ -1095,7 +1159,7 @@
 gtk_widget_path_iter_list_regions (const GtkWidgetPath *path,
                                    gint                 pos)
 {
-  GtkPathElement *elem;
+  const GtkPathElement *elem;
   GHashTableIter iter;
   GSList *list = NULL;
   gpointer key;
@@ -1106,7 +1170,7 @@
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  elem = g_array_index (path->elems, GtkPathElement *, pos);
 
   if (!elem->regions)
     return NULL;
@@ -1144,7 +1208,7 @@
                                   GQuark               qname,
                                   GtkRegionFlags      *flags)
 {
-  GtkPathElement *elem;
+  const GtkPathElement *elem;
   gpointer value;
 
   g_return_val_if_fail (path != NULL, FALSE);
@@ -1154,7 +1218,7 @@
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  elem = g_array_index (path->elems, GtkPathElement *, pos);
 
   if (!elem->regions)
     return FALSE;
@@ -1221,12 +1285,12 @@
 GType
 gtk_widget_path_get_object_type (const GtkWidgetPath *path)
 {
-  GtkPathElement *elem;
+  const GtkPathElement *elem;
 
   g_return_val_if_fail (path != NULL, G_TYPE_INVALID);
 
-  elem = &g_array_index (path->elems, GtkPathElement,
-                         path->elems->len - 1);
+  elem = g_array_index (path->elems, GtkPathElement *,
+                        path->elems->len - 1);
   return elem->type;
 }
 
@@ -1246,12 +1310,12 @@
 gtk_widget_path_is_type (const GtkWidgetPath *path,
                          GType                type)
 {
-  GtkPathElement *elem;
+  const GtkPathElement *elem;
 
   g_return_val_if_fail (path != NULL, FALSE);
 
-  elem = &g_array_index (path->elems, GtkPathElement,
-                         path->elems->len - 1);
+  elem = g_array_index (path->elems, GtkPathElement *,
+                        path->elems->len - 1);
 
   if (elem->type == type ||
       g_type_is_a (elem->type, type))
@@ -1282,9 +1346,9 @@
 
   for (i = 0; i < path->elems->len - 1; i++)
     {
-      GtkPathElement *elem;
+      const GtkPathElement *elem;
 
-      elem = &g_array_index (path->elems, GtkPathElement, i);
+      elem = g_array_index (path->elems, GtkPathElement *, i);
 
       if (elem->type == type ||
           g_type_is_a (elem->type, type))
