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

gEDA-cvs: branch: master updated (1.1.2.20070818-85-g23ead18)



The branch, master has been updated
       via  23ead18086e59aab22945c37ff95f49e5747f277 (commit)
      from  6f0ab03ed06d5cf0265a4f5bee516866efc16828 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


=========
 Summary
=========

 gattrib/src/s_object.c        |   17 +-
 gattrib/src/s_sheet_data.c    |   16 +-
 gattrib/src/s_table.c         |   16 +-
 gattrib/src/s_toplevel.c      |    8 +-
 gnetlist/src/g_netlist.c      |    4 +-
 gnetlist/src/vams_misc.c      |   75 ++++-----
 gschem/src/g_hook.c           |   21 ++-
 gschem/src/o_attrib.c         |    8 +-
 gschem/src/o_copy.c           |    6 +-
 gschem/src/o_misc.c           |   17 +-
 gschem/src/o_slot.c           |    2 +-
 gschem/src/x_attribedit.c     |   76 +++++-----
 gschem/src/x_autonumber.c     |   22 +--
 libgeda/include/prototype.h   |   23 +--
 libgeda/include/struct.h      |   20 +--
 libgeda/src/a_basic.c         |    8 +-
 libgeda/src/g_smob.c          |   48 +++---
 libgeda/src/o_arc_basic.c     |    2 -
 libgeda/src/o_attrib.c        |  364 ++++++++++++----------------------------
 libgeda/src/o_box_basic.c     |    1 -
 libgeda/src/o_bus_basic.c     |   63 ++------
 libgeda/src/o_circle_basic.c  |    1 -
 libgeda/src/o_complex_basic.c |    2 -
 libgeda/src/o_line_basic.c    |    1 -
 libgeda/src/o_list.c          |   14 +-
 libgeda/src/o_net_basic.c     |   75 ++-------
 libgeda/src/o_picture.c       |    1 -
 libgeda/src/o_pin_basic.c     |    1 -
 libgeda/src/s_basic.c         |    8 +-
 29 files changed, 337 insertions(+), 583 deletions(-)


=================
 Commit Messages
=================

commit 23ead18086e59aab22945c37ff95f49e5747f277
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Wed Oct 17 04:50:39 2007 +0100

    Remove the ATTRIB linked list in favour of a GList
    
    The ATTRIB.copied_to pointer is moved from the ATTRIB struct to reside in
    the source OBJECT being copied.
    
    The ATTRIB *attached_to pointer of an attribute's text OBJECT is changed
    to OBJECT *attached_to, pointing directly at the OBJECT to which that
    attribute is attached. This avoids the need to traverse the ATTRIB list
    and retrieve this pointer from the HEAD attribute node. (A HEAD node is
    not used in the GList of ATTRIBs).
    
    The ATTRIB structure now only contains one element, OBJECT *object. This
    points to the text OBJECT holding and displaying that attribute's
    "name=value".

:100644 100644 cadae21... eec70bc... M	gattrib/src/s_object.c
:100644 100644 ef32852... fc05ad4... M	gattrib/src/s_sheet_data.c
:100644 100644 697b9c8... a1530a1... M	gattrib/src/s_table.c
:100644 100644 d7822c2... fdf2023... M	gattrib/src/s_toplevel.c
:100644 100644 74cbe9c... 9bcbd71... M	gnetlist/src/g_netlist.c
:100644 100644 bd9b024... 21fc5cf... M	gnetlist/src/vams_misc.c
:100644 100644 88681eb... 64a90ce... M	gschem/src/g_hook.c
:100644 100644 2abee7f... 4dba4cb... M	gschem/src/o_attrib.c
:100644 100644 24d1a0c... fe35882... M	gschem/src/o_copy.c
:100644 100644 80c134b... 1d774d6... M	gschem/src/o_misc.c
:100644 100644 e857d0b... 91c5716... M	gschem/src/o_slot.c
:100644 100644 fd7d23f... 91ba130... M	gschem/src/x_attribedit.c
:100644 100644 9142a4f... 7509fbb... M	gschem/src/x_autonumber.c
:100644 100644 8afa473... 96df3bb... M	libgeda/include/prototype.h
:100644 100644 49a8b2a... 6a90324... M	libgeda/include/struct.h
:100644 100644 51e2ac2... b11e493... M	libgeda/src/a_basic.c
:100644 100644 ed57fab... 12afb4b... M	libgeda/src/g_smob.c
:100644 100644 83304d0... c0c4a13... M	libgeda/src/o_arc_basic.c
:100644 100644 5138a01... c2c56ba... M	libgeda/src/o_attrib.c
:100644 100644 6ca35f0... ffe91e2... M	libgeda/src/o_box_basic.c
:100644 100644 7297b5d... 91a5905... M	libgeda/src/o_bus_basic.c
:100644 100644 a6de864... d161989... M	libgeda/src/o_circle_basic.c
:100644 100644 699a2d3... e0b478b... M	libgeda/src/o_complex_basic.c
:100644 100644 8fe3cb5... 5cd6e90... M	libgeda/src/o_line_basic.c
:100644 100644 60d2867... d10a506... M	libgeda/src/o_list.c
:100644 100644 735d95f... 869c359... M	libgeda/src/o_net_basic.c
:100644 100644 6ec5ccd... 48884eb... M	libgeda/src/o_picture.c
:100644 100644 79df6e9... 7b2cb68... M	libgeda/src/o_pin_basic.c
:100644 100644 6ebe35a... 72cfe87... M	libgeda/src/s_basic.c

=========
 Changes
=========

commit 23ead18086e59aab22945c37ff95f49e5747f277
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Wed Oct 17 04:50:39 2007 +0100

    Remove the ATTRIB linked list in favour of a GList
    
    The ATTRIB.copied_to pointer is moved from the ATTRIB struct to reside in
    the source OBJECT being copied.
    
    The ATTRIB *attached_to pointer of an attribute's text OBJECT is changed
    to OBJECT *attached_to, pointing directly at the OBJECT to which that
    attribute is attached. This avoids the need to traverse the ATTRIB list
    and retrieve this pointer from the HEAD attribute node. (A HEAD node is
    not used in the GList of ATTRIBs).
    
    The ATTRIB structure now only contains one element, OBJECT *object. This
    points to the text OBJECT holding and displaying that attribute's
    "name=value".

diff --git a/gattrib/src/s_object.c b/gattrib/src/s_object.c
index cadae21..eec70bc 100644
--- a/gattrib/src/s_object.c
+++ b/gattrib/src/s_object.c
@@ -146,14 +146,16 @@ void s_object_replace_attrib_in_object(OBJECT *o_current,
 				       gint visibility, 
 				       gint show_name_value)
 {
+  GList *a_iter;
   ATTRIB *a_current;
   char *old_attrib_text;
   char *old_attrib_name;
   char *new_attrib_text;
 
 
-  a_current = o_current->attribs;
-  while (a_current != NULL) {
+  a_iter = o_current->attribs;
+  while (a_iter != NULL) {
+    a_current = a_iter->data;
     if (a_current->object->type == OBJ_TEXT 
 	&& a_current->object->text != NULL) {  /* found an attribute */
       
@@ -180,7 +182,7 @@ void s_object_replace_attrib_in_object(OBJECT *o_current,
       }  /* if (strcmp . . . . */
     } /* if (a_current . . . . */
   
-    a_current = a_current->next;
+    a_iter = g_list_next (a_iter);
   }  /* while */
 
   /* if we get here, it's because we have failed to find the attrib on the component.
@@ -198,14 +200,15 @@ void s_object_replace_attrib_in_object(OBJECT *o_current,
  *------------------------------------------------------------------*/
 void s_object_remove_attrib_in_object(OBJECT *o_current, char *new_attrib_name) 
 {
-  
+  GList *a_iter;
   ATTRIB *a_current;
   OBJECT *attribute_object;
   char *old_attrib_text;
   char *old_attrib_name;
   
-  a_current = o_current->attribs;
-  while (a_current != NULL) {
+  a_iter = o_current->attribs;
+  while (a_iter != NULL) {
+    a_current = a_iter->data;
     if (a_current->object->type == OBJ_TEXT 
 	&& a_current->object->text != NULL) {  /* found an attribute */
       
@@ -230,7 +233,7 @@ void s_object_remove_attrib_in_object(OBJECT *o_current, char *new_attrib_name)
     g_free(old_attrib_text);
     g_free(old_attrib_name);
     }
-    a_current = a_current->next;
+    a_iter = g_list_next (a_iter);
   }
   
   /* if we get here, it's because we have failed to find the attrib on the component.
diff --git a/gattrib/src/s_sheet_data.c b/gattrib/src/s_sheet_data.c
index ef32852..fc05ad4 100644
--- a/gattrib/src/s_sheet_data.c
+++ b/gattrib/src/s_sheet_data.c
@@ -165,6 +165,7 @@ void s_sheet_data_add_master_comp_attrib_list_items(OBJECT *start_obj) {
   char *attrib_text;
   char *attrib_name;
   OBJECT *o_current;
+  GList *a_iter;
   ATTRIB *a_current;
   
 #ifdef DEBUG
@@ -194,8 +195,9 @@ void s_sheet_data_add_master_comp_attrib_list_items(OBJECT *start_obj) {
 	verbose_print(" C");
 	
 	/*------ Iterate through all attribs found on component -----*/
-	a_current = o_current->attribs; /* This has a side effect.  Why? */
-	while (a_current != NULL) {
+	a_iter = o_current->attribs; /* This has a side effect.  Why? */
+	while (a_iter != NULL) {
+	  a_current = a_iter->data;
 	  if (a_current->object->type == OBJ_TEXT 
 	      && a_current->object->text != NULL) {  /* found an attribute */
 	    attrib_text = g_strdup(a_current->object->text->string);
@@ -215,7 +217,7 @@ void s_sheet_data_add_master_comp_attrib_list_items(OBJECT *start_obj) {
 	    g_free(attrib_name);
 	    g_free(attrib_text);
 	  }
-	  a_current = a_current->next;
+	  a_iter = g_list_next (a_iter);
 	}   /*  while  */
 	
       }   /* if (o_current->type == OBJ_COMPLEX) */
@@ -367,6 +369,7 @@ void s_sheet_data_add_master_pin_attrib_list_items(OBJECT *start_obj) {
   char *attrib_value;
   OBJECT *o_current;
   OBJECT *o_lower_current;
+  GList *a_iter;
   ATTRIB *pin_attrib;
   
 #ifdef DEBUG
@@ -399,8 +402,9 @@ void s_sheet_data_add_master_pin_attrib_list_items(OBJECT *start_obj) {
 #endif
 	    if (o_lower_current->type == OBJ_PIN) {
 	      /* -----  Found a pin.  Now get attrib head and loop on attribs.  ----- */
-	      pin_attrib = o_lower_current->attribs;
-	      while (pin_attrib != NULL) {
+	      a_iter = o_lower_current->attribs;
+	      while (a_iter != NULL) {
+		pin_attrib = a_iter->data;
 		if (pin_attrib->object->type == OBJ_TEXT 
 		    && pin_attrib->object->text != NULL) {  /* found an attribute */
 		  attrib_text = g_strdup(pin_attrib->object->text->string);
@@ -423,7 +427,7 @@ void s_sheet_data_add_master_pin_attrib_list_items(OBJECT *start_obj) {
 		  g_free(attrib_name);
 		  g_free(attrib_text);
 		}
-		pin_attrib = pin_attrib->next;
+		a_iter = g_list_next (a_iter);
 	      }   /*   while (pin_attrib != NULL)  */
 	    }
 	    o_lower_current = o_lower_current->next;
diff --git a/gattrib/src/s_table.c b/gattrib/src/s_table.c
index 697b9c8..a1530a1 100644
--- a/gattrib/src/s_table.c
+++ b/gattrib/src/s_table.c
@@ -240,6 +240,7 @@ void s_table_add_toplevel_comp_items_to_comp_table(OBJECT *start_obj) {
   gchar *attrib_text;
   gchar *attrib_name;
   gchar *attrib_value;
+  GList *a_iter;
   ATTRIB *a_current;
   gint old_visibility, old_show_name_value;
 
@@ -279,8 +280,9 @@ void s_table_add_toplevel_comp_items_to_comp_table(OBJECT *start_obj) {
         /* Having found a component, we loop over all attribs in this
          * component, and stick them
          * into cells in the table. */
-        a_current = o_current->attribs;
-        while (a_current != NULL) {
+        a_iter = o_current->attribs;
+        while (a_iter != NULL) {
+          a_current = a_iter->data;
           if (a_current->object->type == OBJ_TEXT
               && a_current->object->text != NULL) {  /* found an attribute */
             /* may need to check more thoroughly here. . . . */
@@ -317,7 +319,7 @@ void s_table_add_toplevel_comp_items_to_comp_table(OBJECT *start_obj) {
             g_free(attrib_text);
             g_free(attrib_value);
           }
-          a_current = a_current->next;
+          a_iter = g_list_next (a_iter);
            
         }  /* while (a_current != NULL) */
         g_free(temp_uref);
@@ -434,6 +436,7 @@ void s_table_add_toplevel_pin_items_to_pin_table(OBJECT *start_obj) {
   gchar *attrib_text;
   gchar *attrib_name;
   gchar *attrib_value;
+  GList *a_iter;
   ATTRIB *pin_attrib;
 
   if (verbose_mode) {
@@ -474,8 +477,9 @@ void s_table_add_toplevel_pin_items_to_pin_table(OBJECT *start_obj) {
         printf("      In s_table_add_toplevel_pin_items_to_pin_table, examining pin %s\n", row_label);
 #endif
 
-	    pin_attrib = o_lower_current->attribs;
-	    while (pin_attrib != NULL) {
+	    a_iter = o_lower_current->attribs;
+	    while (a_iter != NULL) {
+	      pin_attrib = a_iter->data;
 	      if (pin_attrib->object->type == OBJ_TEXT
 		  && pin_attrib->object->text != NULL) {  /* found an attribute */
 		attrib_text = g_strdup(pin_attrib->object->text->string);
@@ -507,7 +511,7 @@ void s_table_add_toplevel_pin_items_to_pin_table(OBJECT *start_obj) {
 		g_free(attrib_text);
 		g_free(attrib_value);
 	      }
-	      pin_attrib = pin_attrib->next;
+	      a_iter = g_list_next (a_iter);
            
 	    }  /* while (pin_attrib != NULL) */
 	    g_free(pinnumber);
diff --git a/gattrib/src/s_toplevel.c b/gattrib/src/s_toplevel.c
index d7822c2..fdf2023 100644
--- a/gattrib/src/s_toplevel.c
+++ b/gattrib/src/s_toplevel.c
@@ -589,6 +589,7 @@ void s_toplevel_update_component_attribs_in_toplevel(OBJECT *o_current,
   char *old_attrib_name;
   char *old_attrib_value;
   gchar *refdes;
+  GList *a_iter;
   ATTRIB *a_current;
   int count = 0;  /* This is to fake out a fcn called later */
   gint row, col;
@@ -611,8 +612,9 @@ void s_toplevel_update_component_attribs_in_toplevel(OBJECT *o_current,
 
   /* Now create a complete list of unique attribute names.  This will be used in
   *  the loop below when updating attributes.  */
-  a_current = o_current->attribs;
-  while (a_current != NULL) {
+  a_iter = o_current->attribs;
+  while (a_iter != NULL) {
+    a_current = a_iter->data;
     if (a_current->object->type == OBJ_TEXT
 	&& a_current->object->text != NULL) {  /* found a name=value attribute pair. */
       /* may need to check more thoroughly here. . . . */
@@ -647,7 +649,7 @@ void s_toplevel_update_component_attribs_in_toplevel(OBJECT *o_current,
      g_free(old_name_value_pair);
      g_free(old_attrib_name);
     }
-    a_current = a_current->next;
+    a_iter = g_list_next (a_iter);
   }  /* while (a_current != NULL) */
 
 
diff --git a/gnetlist/src/g_netlist.c b/gnetlist/src/g_netlist.c
index 74cbe9c..9bcbd71 100644
--- a/gnetlist/src/g_netlist.c
+++ b/gnetlist/src/g_netlist.c
@@ -583,7 +583,7 @@ SCM g_get_attribute_by_pinseq(SCM scm_uref, SCM scm_pinseq,
         o_text_object = o_attrib_search_string_single(nl_current->object_ptr,
                                                       pinseq_attrib);
         if (o_text_object && o_text_object->attached_to) {
-          o_pin_object = o_attrib_return_parent(o_text_object->attached_to);
+          o_pin_object = o_text_object->attached_to;
 
           if (o_pin_object) {
             return_value = o_attrib_search_name_single(o_pin_object,
@@ -609,7 +609,7 @@ SCM g_get_attribute_by_pinseq(SCM scm_uref, SCM scm_pinseq,
                                       complex->prim_objs, pinseq_attrib);
 
         if (o_text_object && o_text_object->attached_to) {
-          o_pin_object = o_attrib_return_parent(o_text_object->attached_to);
+          o_pin_object = o_text_object->attached_to;
           if (o_pin_object) {
             return_value = o_attrib_search_name_single(o_pin_object,
                                                        wanted_attrib,
diff --git a/gnetlist/src/vams_misc.c b/gnetlist/src/vams_misc.c
index bd9b024..21fc5cf 100644
--- a/gnetlist/src/vams_misc.c
+++ b/gnetlist/src/vams_misc.c
@@ -39,48 +39,41 @@
 char *
 vams_get_attribs_list(OBJECT *object, SCM *list, OBJECT **return_found) 
 {
-	OBJECT *o_current;
-	ATTRIB *a_current;
-	OBJECT *found;
-	int val;
-	char* found_name = NULL;
-	char* found_value = NULL;
-
-	o_current = object;
-
-	if (o_current->attribs != NULL) 
-	  {
-	    a_current = o_current->attribs;
-	    
-	    while(a_current != NULL) 
-	      {
-		found = a_current->object;
-		if (found != NULL && found->text && found->text->string) 
-		  {
-		    val = o_attrib_get_name_value(
-						  found->text->string, 
-						  &found_name, &found_value);
-		    
-		    if (val) 
-		      {
-                *list = scm_cons (scm_makfrom0str (found_name),
-                                  *list);	
-		      }	
-		   
-		   if (found_name) g_free(found_name); 
-		   if (found_value) g_free(found_value); 
-#if DEBUG 
-		    printf("0 _%s_\n", found->text->string);
-		    printf("1 _%s_\n", found_name);
-		    printf("2 _%s_\n", found_value);
+  OBJECT *o_current;
+  GList *a_iter;
+  ATTRIB *a_current;
+  OBJECT *found;
+  int val;
+  char* found_name = NULL;
+  char* found_value = NULL;
+
+  o_current = object;
+
+  a_iter = o_current->attribs;
+  while(a_iter != NULL) {
+    a_current = a_iter->data;
+    found = a_current->object;
+    if (found != NULL && found->text && found->text->string) {
+      val = o_attrib_get_name_value(found->text->string,
+                                    &found_name, &found_value);
+
+      if (val) {
+        *list = scm_cons (scm_makfrom0str (found_name), *list);
+      }
+
+     if (found_name) g_free(found_name);
+     if (found_value) g_free(found_value);
+#if DEBUG
+      printf("0 _%s_\n", found->text->string);
+      printf("1 _%s_\n", found_name);
+      printf("2 _%s_\n", found_value);
 #endif
-		  }
-	        a_current=a_current->next;
-	      }	
-	  }
-	
-	return (NULL);
-} 
+    }
+    a_iter = g_list_next (a_iter);
+  }
+
+  return (NULL);
+}
 
 SCM
 vams_get_package_attributes(SCM scm_uref)
diff --git a/gschem/src/g_hook.c b/gschem/src/g_hook.c
index 88681eb..64a90ce 100644
--- a/gschem/src/g_hook.c
+++ b/gschem/src/g_hook.c
@@ -60,6 +60,7 @@ SCM g_make_attrib_smob_list(GSCHEM_TOPLEVEL *w_current, OBJECT *curr_object)
 {
   ATTRIB *a_current;      
   OBJECT *object;
+  GList *a_iter;
   SCM smob_list = SCM_EOL;
 
   object = (OBJECT *) o_list_search(curr_object, curr_object);
@@ -72,13 +73,10 @@ SCM g_make_attrib_smob_list(GSCHEM_TOPLEVEL *w_current, OBJECT *curr_object)
     return(SCM_EOL);
   }
 
-  if (!object->attribs->next) {
-    return(SCM_EOL);
-  }
-
   /* go through attribs */
-  a_current = object->attribs->next;      
-  while(a_current != NULL) {
+  a_iter = object->attribs;
+  while(a_iter != NULL) {
+    a_current = a_iter->data;
     if (a_current->object->type == OBJ_TEXT && 
         a_current->object->text) {
       if (a_current->object->text->string) {
@@ -88,7 +86,7 @@ SCM g_make_attrib_smob_list(GSCHEM_TOPLEVEL *w_current, OBJECT *curr_object)
     } else {
       printf(_("Attribute failed ot find.\n"));
     }
-    a_current = a_current->next;
+    a_iter = g_list_next (a_iter);
   }
 
   return smob_list;
@@ -416,6 +414,8 @@ static void custom_world_get_single_object_bounds
                                         GList *exclude_attrib_list,
 					GList *exclude_obj_type_list) {
     OBJECT *obj_ptr = NULL;
+    ATTRIB *a_current;
+    GList *a_iter;
     int rleft, rright, rbottom, rtop;
     char *text_value; 
     char *name_ptr, *value_ptr, aux_ptr[2];
@@ -477,8 +477,9 @@ static void custom_world_get_single_object_bounds
 	
 	/* If it's a pin object, check the pin attributes */
 	if (obj_ptr->type == OBJ_PIN) {
-	  ATTRIB *a_current = obj_ptr->attribs;
-	  while (a_current) {
+	  a_iter = obj_ptr->attribs;
+	  while (a_iter != NULL) {
+      a_current = a_iter->data;
 	    g_assert(a_current->object);
 
 	    if (a_current->object->type == OBJ_TEXT) {
@@ -494,7 +495,7 @@ static void custom_world_get_single_object_bounds
 	      if (rbottom > *bottom) *bottom = rbottom;
 	    }
 	    
-	    a_current = a_current->next;
+	    a_iter = g_list_next (a_iter);
 	  }
 	}
       }      
diff --git a/gschem/src/o_attrib.c b/gschem/src/o_attrib.c
index 2abee7f..4dba4cb 100644
--- a/gschem/src/o_attrib.c
+++ b/gschem/src/o_attrib.c
@@ -57,15 +57,17 @@ void o_attrib_add_selected(GSCHEM_TOPLEVEL *w_current, SELECTION *selection,
                            OBJECT *selected)
 {
   ATTRIB *a_current;
+  GList *a_iter;
 
   g_assert( selection != NULL );
 
   /* deal with attributes here? */
   if (selected->attribs != NULL) {
     /* first node is head */
-    a_current = selected->attribs->next;
+    a_iter = selected->attribs;
 
-    while (a_current != NULL) {
+    while (a_iter != NULL) {
+      a_current = a_iter->data;
 
       if (a_current->object) {
 
@@ -77,7 +79,7 @@ void o_attrib_add_selected(GSCHEM_TOPLEVEL *w_current, SELECTION *selection,
 
       }
 
-      a_current = a_current->next;
+      a_iter = g_list_next (a_iter);
     }
   }
 
diff --git a/gschem/src/o_copy.c b/gschem/src/o_copy.c
index 24d1a0c..fe35882 100644
--- a/gschem/src/o_copy.c
+++ b/gschem/src/o_copy.c
@@ -368,6 +368,10 @@ void o_copy_end(GSCHEM_TOPLEVEL *w_current)
 
     }
 
+  /* Store a reference in the copied object to where it was copied.
+   * Used to retain associations when copying attributes */
+  object->copied_to = new_object;
+
     toplevel->page_current->object_tail =
       (OBJECT *) return_tail(toplevel->page_current->
                              object_head);
@@ -451,7 +455,7 @@ void o_copy_end(GSCHEM_TOPLEVEL *w_current)
   s_current = geda_list_get_glist( toplevel->page_current->selection_list );
   while(s_current != NULL) {
     object = s_current->data;
-    o_attrib_list_copied_to (object->attribs, NULL);
+    object->copied_to = NULL;
     s_current = g_list_next (s_current);
   }
 
diff --git a/gschem/src/o_misc.c b/gschem/src/o_misc.c
index 80c134b..1d774d6 100644
--- a/gschem/src/o_misc.c
+++ b/gschem/src/o_misc.c
@@ -1036,7 +1036,8 @@ void o_update_component(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
   OBJECT *tmp_list, *new_complex;
-  ATTRIB *new_attribs, *a_current;
+  ATTRIB *a_current;
+  GList *a_iter;
   gboolean is_embedded;
   const CLibSymbol *clib;
 
@@ -1084,10 +1085,10 @@ void o_update_component(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
   new_complex->complex->prim_objs = NULL;
 
   /* then process the attributes: */
-  new_attribs = new_complex->attribs;
   /*   - check each attrib of the new complex */
-  a_current = new_attribs ? new_attribs->next : NULL;
-  while (a_current != NULL) {
+  a_iter = new_complex->attribs;
+  while (a_iter != NULL) {
+    a_current = a_iter->data;
     OBJECT *o_attrib;
     gchar *name, *value;
     char *attrfound;
@@ -1108,12 +1109,8 @@ void o_update_component(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
       /* make a copy of the attribute object */
       o_list_copy_to (toplevel, o_current,
                       a_current->object, NORMAL_FLAG, &o_attrib);
-      if (o_current->attribs == NULL) {
-        /* object has no attribute list: create it */
-        o_current->attribs = add_attrib_head(o_current);
-      }
       /* add the attribute to old */
-      o_attrib_add (toplevel, o_current->attribs, o_attrib);
+      o_attrib_add (toplevel, o_current, o_attrib);
       /* redraw the attribute object */
       o_redraw_single (w_current, o_attrib);
       /* note: this object is unselected (not added to selection). */
@@ -1124,7 +1121,7 @@ void o_update_component(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
     }
 
 
-    a_current = a_current->next;
+    a_iter = g_list_next (a_iter);
   }
 
   /* finally delete the temp list with the updated complex */
diff --git a/gschem/src/o_slot.c b/gschem/src/o_slot.c
index e857d0b..91c5716 100644
--- a/gschem/src/o_slot.c
+++ b/gschem/src/o_slot.c
@@ -136,7 +136,7 @@ void o_slot_end(GSCHEM_TOPLEVEL *w_current, char *string, int len)
   /* get the parent object if the selection is only a text object */
   if (object != NULL && object->type == OBJ_TEXT) {
     if (object->attached_to != NULL) {
-      object=o_attrib_return_parent(object->attached_to);
+      object = object->attached_to;
     }
   }
 
diff --git a/gschem/src/x_attribedit.c b/gschem/src/x_attribedit.c
index fd7d23f..91ba130 100644
--- a/gschem/src/x_attribedit.c
+++ b/gschem/src/x_attribedit.c
@@ -82,7 +82,8 @@ void attrib_edit_dialog_ok(GtkWidget * w, GSCHEM_TOPLEVEL *w_current)
   OBJECT *attribptr;
   OBJECT *object;
   GList *s_current = NULL;
-  ATTRIB *a_current = NULL, *a_sav;
+  ATTRIB *a_current;
+  GList *a_iter;
   int vis, show;
   int invocation_flag;
   int nsel=0, addto=0, replace=0, addmask=0;
@@ -188,43 +189,42 @@ void attrib_edit_dialog_ok(GtkWidget * w, GSCHEM_TOPLEVEL *w_current)
       }
 
       while (s_current != NULL) {
-	gboolean replaced;
-
-	object = (OBJECT *) s_current->data;
-	if (object && !object->attached_to && object->type != OBJ_TEXT ) {
-	  addmask = 4;
-	  if (object->type == OBJ_COMPLEX || object->type == OBJ_PLACEHOLDER) {
-	    addmask = 2;
-	  }
-	  if (object->type == OBJ_NET) {
-	    addmask = 1;
-	  }
-	  replaced = FALSE;
-	  if (addmask & addto) {
-	    a_current = object->attribs;
-	    if (replace) {
-	      while (a_current != NULL) {
-		a_sav = a_current;
-		a_current = a_current->next;
-
-		if (a_sav->object->text != NULL) {
-		  if (!strncmp
-		      (a_sav->object->text->string, newtext,
-		       strchr(newtext, '=') - newtext)) {
-		    o_text_change(w_current, a_sav->object, 
-				  newtext, vis, show);
-		    replaced = TRUE;
-		    toplevel->page_current->CHANGED = 1;
-		  }
-		}
-	      }
-	    }
-	    if (!replaced) {
-	      new = o_attrib_add_attrib(w_current, newtext, vis, show, object);
-	    }
-	  }
-	}
-	s_current = g_list_next(s_current);
+        gboolean replaced;
+
+        object = (OBJECT *) s_current->data;
+        if (object && !object->attached_to && object->type != OBJ_TEXT ) {
+          addmask = 4;
+          if (object->type == OBJ_COMPLEX || object->type == OBJ_PLACEHOLDER) {
+            addmask = 2;
+          }
+          if (object->type == OBJ_NET) {
+            addmask = 1;
+          }
+          replaced = FALSE;
+          if (addmask & addto) {
+            a_iter = object->attribs;
+            if (replace) {
+              while (a_iter != NULL) {
+                a_current = a_iter->data;
+
+                if (a_current->object->text != NULL) {
+                  if (!strncmp(a_current->object->text->string, newtext,
+                               strchr(newtext, '=') - newtext)) {
+                    o_text_change(w_current, a_current->object,
+                                  newtext, vis, show);
+                    replaced = TRUE;
+                    toplevel->page_current->CHANGED = 1;
+                  }
+                }
+                a_iter = g_list_next (a_iter);
+              }
+            }
+            if (!replaced) {
+              new = o_attrib_add_attrib(w_current, newtext, vis, show, object);
+            }
+          }
+        }
+        s_current = g_list_next (s_current);
       }
       o_undo_savestate(w_current, UNDO_ALL);
     } else {
diff --git a/gschem/src/x_autonumber.c b/gschem/src/x_autonumber.c
index 9142a4f..7509fbb 100644
--- a/gschem/src/x_autonumber.c
+++ b/gschem/src/x_autonumber.c
@@ -391,7 +391,6 @@ void autonumber_get_used(GSCHEM_TOPLEVEL *w_current, AUTONUMBER_TEXT *autotext)
 {
   gint number, numslots, slotnr, i;
   OBJECT *o_current, *o_parent, *o_numslots;
-  ATTRIB *a_current;
   AUTONUMBER_SLOT *slot;
   GList *slot_item;
   char *numslot_str, *slot_str;
@@ -400,9 +399,8 @@ void autonumber_get_used(GSCHEM_TOPLEVEL *w_current, AUTONUMBER_TEXT *autotext)
        o_current = o_current->next) {
     if (autonumber_match(autotext, o_current, &number) == AUTONUMBER_RESPECT) {
       /* check slot and maybe add it to the lists */
-      if ((autotext->slotting)
-      			&& (a_current = o_current->attached_to) != NULL) {
-	o_parent = o_attrib_return_parent(a_current);
+      o_parent = o_current->attached_to;
+      if (autotext->slotting && o_parent != NULL) {
 	/* check for slotted symbol */
 	if ((numslot_str = o_attrib_search_numslots(o_parent, &o_numslots)) != NULL) {
 	  sscanf(numslot_str," %d",&numslots);
@@ -485,7 +483,6 @@ void autonumber_get_new_numbers(AUTONUMBER_TEXT *autotext, OBJECT *o_current,
   gint new_number, numslots, i;
   AUTONUMBER_SLOT *freeslot;
   OBJECT *o_parent = NULL, *o_numslots;
-  ATTRIB *a_current = NULL;
   GList *freeslot_item;
   gchar *numslot_str;
 
@@ -493,8 +490,8 @@ void autonumber_get_new_numbers(AUTONUMBER_TEXT *autotext, OBJECT *o_current,
   
   /* Check for slots first */
   /* 1. are there any unused slots in the database? */
-  if ((autotext->slotting) && (a_current = o_current->attached_to) != NULL) {
-    o_parent = o_attrib_return_parent(a_current);
+  o_parent = o_current->attached_to;
+  if (autotext->slotting && o_parent != NULL) {
     freeslot = g_new(AUTONUMBER_SLOT,1);
     freeslot->symbolname = o_parent->complex_basename;
     freeslot->number = 0;
@@ -566,7 +563,6 @@ void autonumber_get_new_numbers(AUTONUMBER_TEXT *autotext, OBJECT *o_current,
  */
 void autonumber_remove_number(AUTONUMBER_TEXT * autotext, OBJECT *o_current)
 {
-  ATTRIB *a_current;
   OBJECT *o_parent, *o_slot;
   gchar *slot_str;
 
@@ -583,8 +579,8 @@ void autonumber_remove_number(AUTONUMBER_TEXT * autotext, OBJECT *o_current)
   /* remove the slot attribute if slotting is active */
   if (autotext->slotting) {
     /* get the slot attribute */
-    if ((a_current = o_current->attached_to) != NULL) {
-      o_parent = o_attrib_return_parent(a_current);
+    o_parent = o_current->attached_to;
+    if (o_parent != NULL) {
       slot_str = o_attrib_search_slot(o_parent, &o_slot);
       if (slot_str != NULL && o_slot != NULL) {
 	g_free(slot_str);
@@ -608,14 +604,12 @@ void autonumber_remove_number(AUTONUMBER_TEXT * autotext, OBJECT *o_current)
 void autonumber_apply_new_text(AUTONUMBER_TEXT * autotext, OBJECT *o_current,
 			       gint number, gint slot)
 {
-  ATTRIB *a_current;
   OBJECT *o_parent, *o_slot;
   gchar *slot_str;
 
   /* add the slot as attribute to the object */
-  if (slot != 0
-      && (a_current = o_current->attached_to) != NULL) {
-    o_parent = o_attrib_return_parent(a_current);
+  o_parent = o_current->attached_to;
+  if (slot != 0 && o_parent != NULL) {
     slot_str = o_attrib_search_slot(o_parent, &o_slot);
     if (slot_str != NULL) {
       /* update the slot attribute */
diff --git a/libgeda/include/prototype.h b/libgeda/include/prototype.h
index 8afa473..96df3bb 100644
--- a/libgeda/include/prototype.h
+++ b/libgeda/include/prototype.h
@@ -150,33 +150,29 @@ void o_arc_print_center(TOPLEVEL *toplevel, FILE *fp, int x, int y, int radius,
 void o_arc_print_phantom(TOPLEVEL *toplevel, FILE *fp, int x, int y, int radius, int angle1, int angle2, int color, int arc_width, int length, int space, int origin_x, int origin_y);
 
 /* o_attrib.c */
-ATTRIB *o_attrib_search(ATTRIB *list, OBJECT *item);
-ATTRIB *o_attrib_return_tail(ATTRIB *head);
-ATTRIB *add_attrib_head(OBJECT *parent);
-ATTRIB *o_attrib_add(TOPLEVEL *toplevel, ATTRIB *list_head, OBJECT *item);
+ATTRIB *o_attrib_search(GList *list, OBJECT *item);
+void o_attrib_add(TOPLEVEL *toplevel, OBJECT *object, OBJECT *item);
 void o_attrib_free(TOPLEVEL *toplevel, ATTRIB *current);
 void o_attrib_attach(TOPLEVEL *toplevel, OBJECT *parent_list, OBJECT *text_object, OBJECT *object);
-void o_attrib_free_all(TOPLEVEL *toplevel, ATTRIB *list);
-void o_attrib_print(ATTRIB *attributes);
-void o_attrib_delete(ATTRIB *a_current);
-void o_attrib_remove(ATTRIB *list, ATTRIB *remove);
+void o_attrib_free_all(TOPLEVEL *toplevel, GList *list);
+void o_attrib_print(GList *attributes);
+void o_attrib_remove(GList **list, OBJECT *remove);
 OBJECT *o_read_attribs(TOPLEVEL *toplevel,
 		       OBJECT *object_to_get_attribs, 
 		       TextBuffer *tb,
 		       unsigned int release_ver, 
 		       unsigned int fileformat_ver);
-void o_save_attribs(FILE *fp, ATTRIB *attribs);
+void o_save_attribs(FILE *fp, GList *attribs);
 int o_attrib_get_name_value(char *string, char **name, char **value);
 void o_attrib_free_current(TOPLEVEL *toplevel);
 void o_attrib_set_string(TOPLEVEL *toplevel, char *string);
-OBJECT *o_attrib_return_parent(ATTRIB *attribute);
-void o_attrib_set_color(TOPLEVEL *toplevel, ATTRIB *attributes);
+void o_attrib_set_color(TOPLEVEL *toplevel, GList *attributes);
 char *o_attrib_search_name(OBJECT *list, char *name, int counter);
 OBJECT *o_attrib_search_string_list(OBJECT *list, char *string);
 char *o_attrib_search_string_partial(OBJECT *object, char *search_for, int counter);
 OBJECT *o_attrib_search_string_single(OBJECT *object, char *search_for);
-OBJECT *o_attrib_search_attrib_value(ATTRIB *list, char *value, char *name, int counter);
-char *o_attrib_search_attrib_name(ATTRIB *list, char *name, int counter);
+OBJECT *o_attrib_search_attrib_value(GList *list, char *value, char *name, int counter);
+char *o_attrib_search_attrib_name(GList *list, char *name, int counter);
 char *o_attrib_search_toplevel(OBJECT *list, char *name, int counter);
 char *o_attrib_search_name_single(OBJECT *object, char *name, OBJECT **return_found);
 char *o_attrib_search_name_single_count(OBJECT *object, char *name, int counter);
@@ -191,7 +187,6 @@ void o_attrib_slot_copy(TOPLEVEL *toplevel, OBJECT *original, OBJECT *target);
 char *o_attrib_search_toplevel_all(GedaPageList *page_list, char *name);
 OBJECT **o_attrib_return_attribs(OBJECT *object_list, OBJECT *sel_object);
 void o_attrib_free_returned(OBJECT **found_objects);
-void o_attrib_list_copied_to(ATTRIB *list, OBJECT *to_obj);
 
 /* o_basic.c */
 int inside_region(int xmin, int ymin, int xmax, int ymax, int x, int y);
diff --git a/libgeda/include/struct.h b/libgeda/include/struct.h
index 49a8b2a..6a90324 100644
--- a/libgeda/include/struct.h
+++ b/libgeda/include/struct.h
@@ -257,14 +257,15 @@ struct st_object {
   int font_text_size;			/* used only with fonts defs */
   OBJECT *font_prim_objs;			/* used only with fonts defs */
 
-  ATTRIB *attribs;		/* attribute stuff */
-  ATTRIB *attached_to;	  /* when object is an attribute */
+  int whichend;    /* for pins only, either 0 or 1 */
+  int pin_type;    /* for pins only, either NET or BUS */
+
+  GList *attribs;       /* attribute stuff */
   int attribute;
   int show_name_value;
-  int visibility; 
-
-  int whichend;    /* for pins only, either 0 or 1 */
-  int pin_type;    /* for pins only, either NET or BUS */  
+  int visibility;
+  OBJECT *attached_to;  /* when object is an attribute */
+  OBJECT *copied_to;    /* used when copying attributes */
 
   OBJECT *prev;
   OBJECT *next;
@@ -272,12 +273,7 @@ struct st_object {
 
 
 struct st_attrib {
-  OBJECT *object;	/* object attribute is connected to */
-
-  OBJECT *copied_to; /* used when copying attributes */
-
-  ATTRIB *prev;
-  ATTRIB *next;
+  OBJECT *object;       /* object attribute is connected to */
 };
 
 struct st_conn {
diff --git a/libgeda/src/a_basic.c b/libgeda/src/a_basic.c
index 51e2ac2..b11e493 100644
--- a/libgeda/src/a_basic.c
+++ b/libgeda/src/a_basic.c
@@ -138,9 +138,7 @@ void o_save_embedded(TOPLEVEL *toplevel, OBJECT *object_list, FILE *fp)
 
         /* save those attributes */
         if (o_current->attribs != NULL) {
-          if (o_current->attribs->next != NULL) {
-            o_save_attribs(fp, o_current->attribs->next);
-          }
+          o_save_attribs(fp, o_current->attribs);
         }
 
       }
@@ -275,9 +273,7 @@ int o_save(TOPLEVEL *toplevel, const char *filename)
 
 				/* save those attributes */
         if (o_current->attribs != NULL) {
-          if (o_current->attribs->next != NULL) {
-            o_save_attribs(fp, o_current->attribs->next);
-          }
+          o_save_attribs(fp, o_current->attribs);
         }
 
       }
diff --git a/libgeda/src/g_smob.c b/libgeda/src/g_smob.c
index ed57fab..12afb4b 100644
--- a/libgeda/src/g_smob.c
+++ b/libgeda/src/g_smob.c
@@ -526,6 +526,8 @@ SCM g_get_object_attributes(SCM object_smob)
   TOPLEVEL *toplevel;
   struct st_object_smob *object;
   SCM returned = SCM_EOL;
+  GList *a_iter;
+  ATTRIB *a_current;
 
   SCM_ASSERT ( SCM_NIMP(object_smob) && 
                ((long) SCM_CAR(object_smob) == object_smob_tag),
@@ -535,17 +537,17 @@ SCM g_get_object_attributes(SCM object_smob)
 
   if (object &&
       object->object) {
-    ATTRIB *pointer;
-    
-    pointer = object->object->attribs;
+
     toplevel = object->world;
-    while (pointer != NULL) {
-      if (pointer->object &&
-	  pointer->object->text) {
-	returned = scm_cons (g_make_attrib_smob (toplevel, pointer), returned);
+    a_iter = object->object->attribs;
+    while (a_iter != NULL) {
+      a_current = a_iter->data;
+      if (a_current->object && a_current->object->text) {
+        returned = scm_cons (g_make_attrib_smob (toplevel, a_current),
+                             returned);
       }
-      pointer = pointer->next;
-    }     
+      a_iter = g_list_next (a_iter);
+    }
   }
 
   return returned;
@@ -568,6 +570,8 @@ SCM g_get_attrib_value_by_attrib_name(SCM object_smob, SCM scm_attrib_name)
   gchar *attrib_name=NULL;
   SCM returned = SCM_EOL;
   gchar *name=NULL, *value=NULL;
+  GList *a_iter;
+  ATTRIB *a_current;
 
   SCM_ASSERT ( SCM_NIMP(object_smob) && 
                ((long) SCM_CAR(object_smob) == object_smob_tag),
@@ -580,22 +584,20 @@ SCM g_get_attrib_value_by_attrib_name(SCM object_smob, SCM scm_attrib_name)
   object = (struct st_object_smob *)SCM_CDR(object_smob);
   attrib_name = SCM_STRING_CHARS(scm_attrib_name);
 
-  if (object &&
-      object->object) {
-    ATTRIB *pointer;
-    
-    pointer = object->object->attribs;
+  if (object && object->object) {
+
     toplevel = object->world;
-    while (pointer != NULL) {
-      if (pointer->object &&
-	  pointer->object->text) {
-	o_attrib_get_name_value(pointer->object->text->string, 
-				&name, &value );
-	if (strcmp(name, attrib_name) == 0) 
-	  returned = scm_cons (scm_makfrom0str (value), returned);
+    a_iter = object->object->attribs;
+    while (a_iter != NULL) {
+      a_current = a_iter->data;
+      if (a_current->object && a_current->object->text) {
+        o_attrib_get_name_value(a_current->object->text->string,
+                                &name, &value );
+        if (strcmp(name, attrib_name) == 0)
+          returned = scm_cons (scm_makfrom0str (value), returned);
       }
-      pointer = pointer->next;
-    }     
+      a_iter = g_list_next (a_iter);
+    }
   }
 
   return returned;
diff --git a/libgeda/src/o_arc_basic.c b/libgeda/src/o_arc_basic.c
index 83304d0..c0c4a13 100644
--- a/libgeda/src/o_arc_basic.c
+++ b/libgeda/src/o_arc_basic.c
@@ -170,8 +170,6 @@ OBJECT *o_arc_copy(TOPLEVEL *toplevel, OBJECT *list_tail,
   o_set_fill_options(toplevel, new_obj,
                      FILLING_HOLLOW, -1, -1, -1, -1, -1);
 
-  o_attrib_list_copied_to (o_current->attribs, new_obj);
-
   return(new_obj);
 }
 
diff --git a/libgeda/src/o_attrib.c b/libgeda/src/o_attrib.c
index 5138a01..c2c56ba 100644
--- a/libgeda/src/o_attrib.c
+++ b/libgeda/src/o_attrib.c
@@ -69,106 +69,49 @@
  *  \param [in] list  ATTRIB pointer to the list to be searched.
  *  \param [in] item  item to be found.
  */
-ATTRIB *o_attrib_search(ATTRIB *list, OBJECT *item)
+ATTRIB *o_attrib_search(GList *list, OBJECT *item)
 {
+  GList *a_iter;
   ATTRIB *a_current;
 
   if (item == NULL) {
     return(NULL);
   }
 
-  a_current = list;
+  a_iter = list;
 
-  while(a_current != NULL) {
+  while(a_iter != NULL) {
+    a_current = a_iter->data;
     if (a_current->object != NULL) {
       if (item->sid == a_current->object->sid) {	
         return(a_current);	
       }
     }
 
-    a_current = a_current->next;
+    a_iter = g_list_next (a_iter);
   }
 
   return(NULL);
 }
 
-/*! \brief Get the last attribute in the list.
- *  \par Function Description
- *  Get the last attribute in the list.
- *
- *  \param [in] head  ATTRIB pointer to beginning of list.
- *  \return Returns an ATTRIB pointer to the last attribute in the list.
- */
-ATTRIB *o_attrib_return_tail(ATTRIB *head) 
-{
-  ATTRIB *a_current=NULL;
-  ATTRIB *current=NULL;
-
-  a_current = head;
-  while ( a_current != NULL ) { /* goto end of list */
-    current = a_current;
-    a_current = a_current->next;
-  }
-  return(current); 
-}
-
-/*! \brief Create an attribute list head item.
- *  \par Function Description
- *  Create an attribute list head item.
- *
- *  \param [in] parent  OBJECT pointer that will become the parent
- *                      of this new head item.
- *  \return Returns an ATTRIB pointer to the newly created head item.
- *
- *  \todo Rename this function to be consistant.
- */
-ATTRIB *add_attrib_head(OBJECT *parent)
-{
-  ATTRIB *head = NULL;
-
-  head = (ATTRIB *) g_malloc(sizeof(ATTRIB));
-  head->next = NULL;
-
-  /* highly experimental hack */
-  head->object = parent; 
-  head->copied_to = NULL;
-  head->prev = NULL;
-
-  /* \todo
-   * why the grief? well everywhere a attribute is refered to
-   * you have to skip over the head, you really ought to robustify
-   * all references to this object pointer when talking to attributes
-   * hack of course I think this is okay now though
-   */
-
-  return(head);
-}
-
 /*! \brief Add an attribute to an existing attribute list.
  *  \par Function Description
  *  Add an attribute to an existing attribute list.
  *
- *  \param [in]     toplevel  The TOPLEVEL object.
- *  \param [in,out] list_head  The list where you want to add item to.
- *  \param [in]     item       The item you want to add as an attribute.
- *  \return An ATTRIB pointer to the newly created attribute.
+ *  \param [in]  toplevel   The TOPLEVEL object.
+ *  \param [in]  list_head  The OBJECT we're adding the attribute to.
+ *  \param [in]  item       The item you want to add as an attribute.
+ *  \return The new head of the attributes list.
  */
-ATTRIB *o_attrib_add(TOPLEVEL *toplevel, ATTRIB *list_head, OBJECT *item)
+void o_attrib_add(TOPLEVEL *toplevel, OBJECT *object, OBJECT *item)
 {
-  ATTRIB *end = NULL;
   ATTRIB *new = NULL;
 
-  /* get tail of list_head */
-  end = o_attrib_return_tail(list_head);
-
   /* create an new st_attrib object */
   new = (ATTRIB *) g_malloc(sizeof(ATTRIB));
 
-  /* fill item with correct data (mainly item) */
-  new->next = NULL;
-  new->prev = end;
+  /* fill item with correct data */
   new->object = item;
-  new->copied_to = NULL;
   new->object->attribute = 1; /* Set the attribute to true, hack define */
   /* Show that that item is an attribute */
   new->object->color = toplevel->attribute_color;
@@ -183,15 +126,9 @@ ATTRIB *o_attrib_add(TOPLEVEL *toplevel, ATTRIB *list_head, OBJECT *item)
   }
 
   /* Add link from item to attrib listing */
-  new->object->attached_to = new;
+  new->object->attached_to = object;
 
-  /* set next of tail of end->attrib to item */
-  if (end) {
-    end->next = new;
-    return(new);
-  } else {
-    return(new);
-  }
+  object->attribs = g_list_append (object->attribs, new);
 }
 
 /*! \brief Free single item in attribute list.
@@ -202,7 +139,6 @@ ATTRIB *o_attrib_add(TOPLEVEL *toplevel, ATTRIB *list_head, OBJECT *item)
  *  \param [in] current    ATTRIB pointer to free.
  *
  *  \note
- *  this routine is not nice to next and prev
  *  this routine is only called from free_all
  */
 void o_attrib_free(TOPLEVEL *toplevel, ATTRIB *current)
@@ -210,7 +146,7 @@ void o_attrib_free(TOPLEVEL *toplevel, ATTRIB *current)
   if (current != NULL) {
 
     /* \todo this makes me nervous... very nervous */
-    if (current->object != NULL && current->prev != NULL) {
+    if (current->object != NULL) {
       current->object->attribute = 0;	
       current->object->attached_to=NULL;
       current->object->color = toplevel->detachedattr_color;
@@ -286,18 +222,12 @@ void o_attrib_attach(TOPLEVEL *toplevel, OBJECT *parent_list,
     if (found2) {
       if (found2->type == OBJ_TEXT) {
 
-        if (object->attribs == NULL) {
-          object->attribs = 
-            add_attrib_head(object);
-        }
-
-
         if (found2->attached_to) {
           fprintf(stderr, "You cannot attach this attribute [%s] to more than one object\n", found2->text->string);
         } else {
 
           o_attrib_add(toplevel,
-                       object->attribs, 
+                       object,
                        found2);
 
           o_current->color = toplevel->
@@ -338,23 +268,20 @@ void o_attrib_attach(TOPLEVEL *toplevel, OBJECT *parent_list,
  *  \param [in]     toplevel  The TOPLEVEL object.
  *  \param [in,out] list       The list to free.
  *
- *  \note
- *  this routine uses o_attrib_free (which isn't nice to next, prev)
- *  so it should only be used when an object is being destroyed
- *  goes backwards
  */
-void o_attrib_free_all(TOPLEVEL *toplevel, ATTRIB *list)
+void o_attrib_free_all(TOPLEVEL *toplevel, GList *list)
 {
   ATTRIB *a_current; 
-  ATTRIB *a_next;
+  GList *a_iter;
 
-  a_current = list;
+  a_iter = list;
 
-  while (a_current != NULL) {
-    a_next = a_current->next;
+  while (a_iter != NULL) {
+    a_current = a_iter->data;
     o_attrib_free(toplevel, a_current);
-    a_current = a_next;
+    a_iter = g_list_next (a_iter);
   }
+  g_list_free (list);
 }
 
 /*! \brief Print all attributes to a Postscript document.
@@ -363,13 +290,15 @@ void o_attrib_free_all(TOPLEVEL *toplevel, ATTRIB *list)
  *
  *  \param [in] attributes  List of attributes to print.
  */
-void o_attrib_print(ATTRIB *attributes) 
+void o_attrib_print(GList *attributes)
 {
   ATTRIB *a_current;
+  GList *a_iter;
 
-  a_current = attributes;
+  a_iter = attributes;
 
-  while (a_current != NULL) {
+  while (a_iter != NULL) {
+    a_current = a_iter->data;
     printf("Attribute points to: %s\n", a_current->object->name);
     if (a_current->object && a_current->object->text) {
       printf("\tText is: %s\n", a_current->object->text->string);
@@ -378,69 +307,42 @@ void o_attrib_print(ATTRIB *attributes)
     if (!a_current->object) {
       printf("oops found a null attrib object\n");
     }
-    a_current = a_current->next;
-  }
-}
-
-/*! \brief Delete an attribute.
- *  \par Function Description
- *  This function goes out and removes the current attribute,
- *  while preserving the next, prev pointers.
- *  This function should be used when detaching an attribute.
- *
- *  \param [in] a_current  The attribute to be deleted.
- */
-void o_attrib_delete(ATTRIB *a_current)
-{
-  if (a_current != NULL) {
-
-    if (a_current->next)
-    a_current->next->prev = a_current->prev;
-    else
-    a_current->next = NULL;
-
-    if (a_current->prev)
-    a_current->prev->next = a_current->next;
-    else
-    a_current->prev = NULL;
-
-    if (a_current->object) {
-      a_current->object->attribute=0;
-      a_current->object->attached_to=NULL;
-    }
-    a_current->object = NULL;
-
-    g_free(a_current);
+    a_iter = g_list_next (a_iter);
   }
 }
 
 /*! \todo Finish function.
  *  \brief Remove an attribute item from an attribute list.
  *  \par Function Description
- *  This function goes out and removes an attribute from a list.
- *  It searches for the attribute and then removes it using the
- *  good #o_attrib_delete() routine.
+ *  This function removes the given attribute from an attribute list.
+ *  This function should be used when detaching an attribute.
  *
- *  \param [in] list    ATTRIB list to remove attribute from.
- *  \param [in] remove  The ATTRIB to remove from list.
+ *  \param [in] list    The attribute list to remove attribute from.
+ *  \param [in] remove  The OBJECT to remove from list.
  *
- *  \note
- *  This function is the detach_all routine.
- *  It is not currently being used.
- *  It is not even done.
  */
-void o_attrib_remove(ATTRIB *list, ATTRIB *remove) 
+void o_attrib_remove(GList **list, OBJECT *remove)
 {
+  GList *a_iter;
   ATTRIB *a_current;
 
-  a_current = list;
+  g_assert (remove != NULL);
 
-  while (a_current != NULL) {
-	
-    if (a_current == remove) {
-			
-    }	
-    a_current = a_current->next;
+  a_iter = *list;
+  while (a_iter != NULL) {
+    a_current = a_iter->data;
+    if (a_current->object == remove) {
+
+      remove->attribute = 0;
+      remove->attached_to = NULL;
+
+      /* Modifying the list we're iterating over is
+       * ok, since we return straight afterward */
+      *list = g_list_remove (*list, a_current);
+      g_free(a_current);
+      return;
+    }
+    a_iter = g_list_next (a_iter);
   }
 }
 
@@ -595,17 +497,19 @@ OBJECT *o_read_attribs(TOPLEVEL *toplevel,
  *  \todo
  *  this should be trimmed down to only save attributes which are text items
  */
-void o_save_attribs(FILE *fp, ATTRIB *attribs)
+void o_save_attribs(FILE *fp, GList *attribs)
 {
   ATTRIB *a_current=NULL;
   OBJECT *o_current=NULL;
+  GList *a_iter;
   char *out;
 
-  a_current = attribs;
+  a_iter = attribs;
 
   fprintf(fp, "{\n");
 	
-  while ( a_current != NULL ) {
+  while ( a_iter != NULL ) {
+    a_current = a_iter->data;
 
     o_current = a_current->object;	
 
@@ -668,7 +572,7 @@ void o_save_attribs(FILE *fp, ATTRIB *attribs)
       fprintf(fp, "%s\n", out);
       g_free(out);
     }
-    a_current = a_current->next;
+    a_iter = g_list_next (a_iter);
   } 
 
   fprintf(fp, "}\n");
@@ -802,32 +706,6 @@ void o_attrib_set_string(TOPLEVEL *toplevel, char *string)
   /* be sure to g_free this string somewhere and free the input string */
 }
 
-/*! \brief Get the parent OBJECT of an attribute.
- *  \par Function Description
- *  Get the parent OBJECT of an attribute.
- *
- *  \param [in] attribute  ATTRIB pointer to get parent of.
- *  \return The parent OBJECT if it exists, otherwise NULL.
- */
-OBJECT *o_attrib_return_parent(ATTRIB *attribute) 
-{
-  ATTRIB *a_current;
-
-  a_current = attribute;
-
-  if (!a_current) {
-    return(NULL);
-  }
-  
-  while (a_current->prev != NULL) {
-    a_current = a_current->prev;	
-  }	
-
-  /* should be pointing to the parent */
-	
-  return(a_current->object);	
-}
-
 /*! \brief Set attribute color
  *  \par Function Description
  *  This function sets all attribute objects to the right
@@ -837,17 +715,15 @@ OBJECT *o_attrib_return_parent(ATTRIB *attribute)
  *  \param [in,out] attributes  ATTRIB list to set colors on.
  *
  */
-void o_attrib_set_color(TOPLEVEL *toplevel, ATTRIB *attributes)
+void o_attrib_set_color(TOPLEVEL *toplevel, GList *attributes)
 {
   ATTRIB *a_current;
+  GList *a_iter;
 
-  a_current = attributes;
+  a_iter = attributes;
 
-  /* skip over head */
-  if (a_current) 
-  a_current = a_current->next;
-
-  while (a_current != NULL) {
+  while (a_iter != NULL) {
+    a_current = a_iter->data;
 
     if (a_current->object) {	
 			
@@ -881,7 +757,7 @@ void o_attrib_set_color(TOPLEVEL *toplevel, ATTRIB *attributes)
         }
       }	
 
-      a_current = a_current->next;	
+      a_iter = g_list_next (a_iter);
     }
   }
 }
@@ -910,6 +786,7 @@ char *o_attrib_search_name(OBJECT *list, char *name, int counter)
   OBJECT *o_current;
   ATTRIB *a_current;
   OBJECT *found;
+  GList *a_iter;
   int val;
   int internal_counter=0;
   char *found_name = NULL;
@@ -920,9 +797,9 @@ char *o_attrib_search_name(OBJECT *list, char *name, int counter)
 
   while(o_current != NULL) {
     if (o_current->attribs != NULL) {
-      a_current = o_current->attribs;
-
-      while(a_current != NULL) {
+      a_iter = o_current->attribs;
+      while(a_iter != NULL) {
+        a_current = a_iter->data;
         found = a_current->object;
         if (found != NULL) {
           if (found->type == OBJ_TEXT) {
@@ -953,7 +830,7 @@ char *o_attrib_search_name(OBJECT *list, char *name, int counter)
 #endif
           }
         }
-        a_current=a_current->next;
+        a_iter = g_list_next (a_iter);
       }	
     }
 
@@ -1017,15 +894,17 @@ OBJECT *o_attrib_search_string_list(OBJECT *list, char *string)
   OBJECT *o_current;
   ATTRIB *a_current;
   OBJECT *found;
+  GList *a_iter;
 
   o_current = list;
 
   while(o_current != NULL) {
     /* first search attribute list */
     if (o_current->attribs != NULL) {
-      a_current = o_current->attribs;
+      a_iter = o_current->attribs;
 
-      while(a_current != NULL) {
+      while(a_iter != NULL) {
+        a_current = a_iter->data;
         found = a_current->object;
         if (found != NULL) {
           if (found->type == OBJ_TEXT) {
@@ -1038,7 +917,7 @@ OBJECT *o_attrib_search_string_list(OBJECT *list, char *string)
             }
           }	
         }
-        a_current=a_current->next;
+        a_iter = g_list_next (a_iter);
       }
     }	
   
@@ -1126,6 +1005,7 @@ OBJECT *o_attrib_search_string_single(OBJECT *object, char *search_for)
   OBJECT *o_current;
   OBJECT *found;
   ATTRIB *a_current;
+  GList *a_iter;
 
   o_current = object;
 
@@ -1153,8 +1033,9 @@ OBJECT *o_attrib_search_string_single(OBJECT *object, char *search_for)
   if (o_current->attribs == NULL) 
     return(NULL);
 
-  a_current = o_current->attribs;
-  while(a_current != NULL) {
+  a_iter = o_current->attribs;
+  while(a_iter != NULL) {
+    a_current = a_iter->data;
     found = a_current->object;
     if (found != NULL) {
       if (found->type == OBJ_TEXT) {
@@ -1163,7 +1044,7 @@ OBJECT *o_attrib_search_string_single(OBJECT *object, char *search_for)
         }
       }
     }
-    a_current=a_current->next;
+    a_iter = g_list_next (a_iter);
   }
 	
   return (NULL);
@@ -1186,17 +1067,18 @@ OBJECT *o_attrib_search_string_single(OBJECT *object, char *search_for)
  *  \return The attribute OBJECT if found, NULL otherwise.
  *
  */
-OBJECT *o_attrib_search_attrib_value(ATTRIB *list, char *value, char *name, 
+OBJECT *o_attrib_search_attrib_value(GList *list, char *value, char *name,
 				     int counter) 
 {
   OBJECT *found;
   ATTRIB *a_current;
+  GList *a_iter;
   int val;
   int internal_counter=0;
   char *found_name = NULL;
   char *found_value = NULL;
 
-  a_current = list;
+  a_iter = list;
 	
   if (!value) 
   return(NULL);
@@ -1204,7 +1086,8 @@ OBJECT *o_attrib_search_attrib_value(ATTRIB *list, char *value, char *name,
   if (!name) 
   return(NULL);
 
-  while(a_current != NULL) {
+  while(a_iter != NULL) {
+    a_current = a_iter->data;
     found = a_current->object;
     if (found != NULL) {
       if (found->type == OBJ_TEXT) {
@@ -1233,7 +1116,7 @@ OBJECT *o_attrib_search_attrib_value(ATTRIB *list, char *value, char *name,
 
       }
     }
-    a_current=a_current->next;
+    a_iter = g_list_next (a_iter);
   }
 
   if (found_name) g_free(found_name);
@@ -1257,19 +1140,21 @@ OBJECT *o_attrib_search_attrib_value(ATTRIB *list, char *value, char *name,
  *  Caller must g_free returned character string.
  */
 char *
-o_attrib_search_attrib_name(ATTRIB *list, char *name, int counter) 
+o_attrib_search_attrib_name(GList *list, char *name, int counter)
 {
   OBJECT *found;
   ATTRIB *a_current;
+  GList *a_iter;
   int val;
   int internal_counter=0;
   char *found_name = NULL;
   char *found_value = NULL;
   char *return_string = NULL;
 
-  a_current = list;
+  a_iter = list;
 
-  while(a_current != NULL) {
+  while(a_iter != NULL) {
+    a_current = a_iter->data;
     found = a_current->object;
     if (found != NULL) {
       if (found->type == OBJ_TEXT) {
@@ -1298,7 +1183,7 @@ o_attrib_search_attrib_name(ATTRIB *list, char *name, int counter)
         }	
       }
     }
-    a_current=a_current->next;
+    a_iter = g_list_next (a_iter);
   }
 
   if (found_name) g_free(found_name);
@@ -1387,6 +1272,7 @@ char *o_attrib_search_name_single(OBJECT *object, char *name,
   OBJECT *o_current;
   ATTRIB *a_current;
   OBJECT *found;
+  GList *a_iter;
   int val;
   char *found_name = NULL;
   char *found_value = NULL;
@@ -1399,9 +1285,10 @@ char *o_attrib_search_name_single(OBJECT *object, char *name,
   }
 
   if (o_current->attribs != NULL) {
-    a_current = o_current->attribs;
+    a_iter = o_current->attribs;
 
-    while(a_current != NULL) {
+    while(a_iter != NULL) {
+      a_current = a_iter->data;
       found = a_current->object;
       if (found != NULL) {
         if (found->type == OBJ_TEXT) {
@@ -1431,7 +1318,7 @@ char *o_attrib_search_name_single(OBJECT *object, char *name,
 #endif
         }
       }
-      a_current=a_current->next;
+      a_iter = g_list_next (a_iter);
     }	
   }
   /* search for attributes outside */
@@ -1489,6 +1376,7 @@ char *o_attrib_search_name_single_count(OBJECT *object, char *name,
   OBJECT *o_current;
   ATTRIB *a_current;
   OBJECT *found=NULL;
+  GList *a_iter;
   int val;
   char *found_name = NULL;
   char *found_value = NULL;
@@ -1503,9 +1391,10 @@ char *o_attrib_search_name_single_count(OBJECT *object, char *name,
   }
 
   if (o_current->attribs != NULL) {
-    a_current = o_current->attribs;
+    a_iter = o_current->attribs;
 
-    while(a_current != NULL) {
+    while(a_iter != NULL) {
+      a_current = a_iter->data;
       found = a_current->object;
       if (found != NULL) {
         if (found->type == OBJ_TEXT) {
@@ -1536,7 +1425,7 @@ char *o_attrib_search_name_single_count(OBJECT *object, char *name,
 #endif
         }
       }
-      a_current=a_current->next;
+      a_iter = g_list_next (a_iter);
     }	
 
   }
@@ -1679,7 +1568,7 @@ OBJECT *o_attrib_search_pinseq(OBJECT *list, int pin_number)
   g_free(search_for);
   
   if (pinseq_text_object && pinseq_text_object->attached_to) {
-    return(o_attrib_return_parent(pinseq_text_object->attached_to));
+    return pinseq_text_object->attached_to;
   }
   
   return(NULL);
@@ -2084,34 +1973,23 @@ OBJECT ** o_attrib_return_attribs(OBJECT *object_list, OBJECT *sel_object)
   ATTRIB *a_current;	
   OBJECT *o_current;
   OBJECT *object;
+  GList *a_iter;
 
   object = (OBJECT *) o_list_search(object_list, sel_object);
 
-  if (!object) {
-    return(NULL);	
-  }
-
-  if (!object->attribs) {
+  if (!object || !object->attribs) {
     return(NULL);
   }
 
-  if (!object->attribs->next) {
-    return(NULL);
-  }
-
-
-  /* first go through and count the number of attribs */
-  a_current = object->attribs->next;	
-  while(a_current != NULL) {
-    num_attribs++;
-    a_current = a_current->next;
-  }
+  /* first count the number of attribs */
+  num_attribs = g_list_length (object->attribs);
 
   found_objects = (OBJECT **) g_malloc(sizeof(OBJECT *)*(num_attribs+1));
 
   /* now actually fill the array of objects */
-  a_current = object->attribs->next;	
-  while(a_current != NULL) {
+  a_iter = object->attribs;
+  while(a_iter != NULL) {
+    a_current = a_iter->data;
     if (a_current->object != NULL) {
       o_current = a_current->object;
       if (o_current->type == OBJ_TEXT && 
@@ -2120,7 +1998,7 @@ OBJECT ** o_attrib_return_attribs(OBJECT *object_list, OBJECT *sel_object)
         i++;
       }
     }
-    a_current = a_current->next;
+    a_iter = g_list_next (a_iter);
   }
 
   found_objects[i] = NULL;
@@ -2161,27 +2039,3 @@ void o_attrib_free_returned(OBJECT **found_objects)
 
   g_free(found_objects);
 }
-
-
-/*! \brief Set the copied_to property on a list of attributes
- *  \par Function Description
- *  Sets the copied_to property on a list of attributes.
- *  Used when copying objects with attributes.
- *
- *  \param [in] list    List of attributes to set
- *  \param [in] to_obj  OBEJCT to set copied_to
- */
-void o_attrib_list_copied_to(ATTRIB *list, OBJECT *to_obj)
-{
-  ATTRIB *a_current;
-
-  a_current = list;
-  while ( a_current ) {
-
-    /* head attrib node has prev = NULL */
-    if (a_current->prev != NULL) {
-      a_current->copied_to = to_obj;
-    }
-    a_current = a_current->next;
-  }
-}
diff --git a/libgeda/src/o_box_basic.c b/libgeda/src/o_box_basic.c
index 6ca35f0..ffe91e2 100644
--- a/libgeda/src/o_box_basic.c
+++ b/libgeda/src/o_box_basic.c
@@ -187,7 +187,6 @@ OBJECT *o_box_copy(TOPLEVEL *toplevel, OBJECT *list_tail, OBJECT *o_current)
   o_box_recalc(toplevel, new_obj);
 
   /* new_obj->attribute = 0;*/
-  o_attrib_list_copied_to (o_current->attribs, new_obj);
 
   /* return the new tail of the object list */
   return(new_obj);
diff --git a/libgeda/src/o_bus_basic.c b/libgeda/src/o_bus_basic.c
index 7297b5d..91a5905 100644
--- a/libgeda/src/o_bus_basic.c
+++ b/libgeda/src/o_bus_basic.c
@@ -267,8 +267,6 @@ OBJECT *o_bus_copy(TOPLEVEL *toplevel, OBJECT *list_tail, OBJECT *o_current)
   new_obj->line->x[1] = o_current->line->x[1];
   new_obj->line->y[1] = o_current->line->y[1];
 
-  o_attrib_list_copied_to (o_current->attribs, new_obj);
-
   return(new_obj);
 }
 
@@ -395,7 +393,8 @@ void o_bus_consolidate_lowlevel(OBJECT *object, OBJECT *del_object,
   int temp1, temp2;
   int final1, final2;
   int changed=0;
-  ATTRIB *tail;
+  GList *a_iter;
+  ATTRIB *a_current;
 
 #if DEBUG
   printf("o %d %d %d %d\n", object->line->x[0], object->line->y[0], object->line->x[1], object->line->y[1]);
@@ -448,56 +447,22 @@ void o_bus_consolidate_lowlevel(OBJECT *object, OBJECT *del_object,
   printf("fo %d %d %d %d\n", object->line->x[0], object->line->y[0], object->line->x[1], object->line->y[1]);
 #endif
 
-  if (changed) {
-
-    /* first check for attributes */
-    if (del_object->attribs) {
-      printf("yeah... del object has attributes\n");
-      printf("reconnecting them to the right place\n");
-      if (object->attribs) {
-
-        printf("object DID have attributes\n");
-
-        tail = o_attrib_return_tail(object->attribs);
-
-				/* skip over old attrib head */
-        tail->next = del_object->attribs->next;
-
-				/* step prev object to point to last object */
-        tail->next->prev = tail; 
-
+  /* Move any attributes from the deleted object*/
+  if (changed && del_object->attribs != NULL) {
 
-				/* delete old attrib head */
-				/* and nothing else */
-        del_object->attribs->object=NULL;
-        del_object->attribs->next=NULL;
-        del_object->attribs->prev=NULL;
-        o_attrib_delete(del_object->attribs);
-
-				/* you don't need to free the attribs list */
-				/* since it's been relinked into object's */
-				/* attribs list */
-
-        del_object->attribs = NULL;
-
-      } else {
-
-        printf("object didn't have any attributes\n");
-        object->attribs = del_object->attribs;
-        /*! \todo what should this be? */
-        object->attribs->prev = NULL;
+    /* Reassign the attached_to pointer on attributes from the del object */
+    a_iter = del_object->attribs;
+    while (a_iter != NULL) {
+      a_current = a_iter->data;
+      a_current->object->attached_to = object;
+      a_iter = g_list_next (a_iter);
+    }
 
-				/* setup parent attribute */
-        object->attribs->object = object;
+    object->attribs = g_list_concat (object->attribs, del_object->attribs);
 
-				/* you don't need to free the attribs list */
-				/* since it's been used by object */
-				
-        del_object->attribs = NULL;
-      }	
-    }
+    /* Don't free del_object->attribs as it's relinked into object's list */
+    del_object->attribs = NULL;
   }
-
 }
 
 /* \brief
diff --git a/libgeda/src/o_circle_basic.c b/libgeda/src/o_circle_basic.c
index a6de864..d161989 100644
--- a/libgeda/src/o_circle_basic.c
+++ b/libgeda/src/o_circle_basic.c
@@ -171,7 +171,6 @@ OBJECT *o_circle_copy(TOPLEVEL *toplevel, OBJECT *list_tail,
   o_circle_recalc(toplevel, new_obj);
 
   /*	new_obj->attribute = 0;*/
-  o_attrib_list_copied_to (o_current->attribs, new_obj);
 
   return(new_obj);
 }
diff --git a/libgeda/src/o_complex_basic.c b/libgeda/src/o_complex_basic.c
index 699a2d3..e0b478b 100644
--- a/libgeda/src/o_complex_basic.c
+++ b/libgeda/src/o_complex_basic.c
@@ -897,7 +897,6 @@ OBJECT *o_complex_copy(TOPLEVEL *toplevel, OBJECT *list_tail,
   /* here you need to create a list of attributes which need to be 
    * connected to the new list, probably make an attribute list and
    * fill it with sid's of the attributes */
-  o_attrib_list_copied_to (o_current->attribs, new_obj);
 
   return(new_obj);
 }
@@ -946,7 +945,6 @@ OBJECT *o_complex_copy_embedded(TOPLEVEL *toplevel, OBJECT *list_tail,
   /* here you need to create a list of attributes which need to be 
    * connected to the new list, probably make an attribute list and
    * fill it with sid's of the attributes */
-  o_attrib_list_copied_to (o_current->attribs, new_obj);
 
   return(new_obj);
 }
diff --git a/libgeda/src/o_line_basic.c b/libgeda/src/o_line_basic.c
index 8fe3cb5..5cd6e90 100644
--- a/libgeda/src/o_line_basic.c
+++ b/libgeda/src/o_line_basic.c
@@ -169,7 +169,6 @@ OBJECT *o_line_copy(TOPLEVEL *toplevel, OBJECT *list_tail, OBJECT *o_current)
   o_line_recalc(toplevel, o_current);
   
   /* new_obj->attribute = 0;*/
-  o_attrib_list_copied_to (o_current->attribs, new_obj);
 
   /* return the new tail of the object list */
   return(new_obj);
diff --git a/libgeda/src/o_list.c b/libgeda/src/o_list.c
index 60d2867..d10a506 100644
--- a/libgeda/src/o_list.c
+++ b/libgeda/src/o_list.c
@@ -120,8 +120,12 @@ OBJECT *o_list_copy_to(TOPLEVEL *toplevel, OBJECT *list_head,
       break;
   }
 
+  /* Store a reference in the copied object to where it was copied.
+   * Used to retain associations when copying attributes */
+  selected->copied_to = end;
+
   if (list_head == NULL)
-  list_head = end;
+    list_head = end;
 
   /* make sure sid is the same! */
   if (selected) {
@@ -207,10 +211,10 @@ OBJECT *o_list_copy_all(TOPLEVEL *toplevel, OBJECT *src_list_head,
     src = src->next;
   }
 
-  /* Clean up dangling ATTRIB.copied_to pointers */
+  /* Clean up dangling copied_to pointers */
   src = src_list_head;
   while(src != NULL) {
-    o_attrib_list_copied_to (src->attribs, NULL);
+    src->copied_to = NULL;
     src = src->next;
   }
 
@@ -319,11 +323,11 @@ GList *o_glist_copy_all_to_glist(TOPLEVEL *toplevel,
     src = g_list_next(src);
   }
 
-  /* Clean up dangling ATTRIB.copied_to pointers */
+  /* Clean up dangling copied_to pointers */
   src = src_list;
   while(src != NULL) {
     src_object = src->data;
-    o_attrib_list_copied_to (src_object->attribs, NULL);
+    src_object->copied_to = NULL;
     src = g_list_next (src);
   }
 
diff --git a/libgeda/src/o_net_basic.c b/libgeda/src/o_net_basic.c
index 735d95f..869c359 100644
--- a/libgeda/src/o_net_basic.c
+++ b/libgeda/src/o_net_basic.c
@@ -279,8 +279,6 @@ OBJECT *o_net_copy(TOPLEVEL *toplevel, OBJECT *list_tail,
   new_obj->line->x[1] = o_current->line->x[1];
   new_obj->line->y[1] = o_current->line->y[1];
 
-  o_attrib_list_copied_to (o_current->attribs, new_obj);
-
   return (new_obj);
 }
 
@@ -408,7 +406,8 @@ void o_net_consolidate_lowlevel(OBJECT *object, OBJECT *del_object,
   int temp1, temp2;
   int final1, final2;
   int changed = 0;
-  ATTRIB *tail;
+  GList *a_iter;
+  ATTRIB *a_current;
 
 #if DEBUG
   printf("o %d %d %d %d\n", object->line->x[0], object->line->y[0],
@@ -456,68 +455,22 @@ void o_net_consolidate_lowlevel(OBJECT *object, OBJECT *del_object,
          object->line->x[1], object->line->y[1]);
 #endif
 
-  if (changed) {
-
-    /* first check for attributes */
-    if (del_object->attribs) {
-#if DEBUG
-      printf("yeah... del object has attributes\n");
-      printf("reconnecting them to the right place\n");
-#endif
-      if (object->attribs) {
-
-#if DEBUG
-        printf("object DID have attributes\n");
-#endif
-
-
-        /* NEWSEL, this corrupts the selection / object_head badly */
-        /* fix it, because you can't just go around deleting objects */
-        /* this whole net conslidate needs to be re thought.. since you */
-        /* don't really del the del_object */
-        tail = o_attrib_return_tail(object->attribs);
-
-        /* skip over old attrib head */
-        tail->next = del_object->attribs->next;
-
-        /* step prev object to point to last object */
-        if (tail->next) {
-          tail->next->prev = tail;
-        }
+  /* Move any attributes from the deleted object*/
+  if (changed && del_object->attribs != NULL) {
 
-        /* delete old attrib head */
-        /* and nothing else */
-        del_object->attribs->object = NULL;
-        del_object->attribs->next = NULL;
-        del_object->attribs->prev = NULL;
-        o_attrib_delete(del_object->attribs);
-
-        /* you don't need to free the attribs list */
-        /* since it's been relinked into object's */
-        /* attribs list */
-
-        del_object->attribs = NULL;
-
-      } else {
-
-#if DEBUG
-        printf("object didn't have any attributes\n");
-#endif
-        object->attribs = del_object->attribs;
-        /*! \todo what should this be? */
-        object->attribs->prev = NULL;
-
-        /* setup parent attribute */
-        object->attribs->object = object;
+    /* Reassign the attached_to pointer on attributes from the del object */
+    a_iter = del_object->attribs;
+    while (a_iter != NULL) {
+      a_current = a_iter->data;
+      a_current->object->attached_to = object;
+      a_iter = g_list_next (a_iter);
+    }
 
-        /* you don't need to free the attribs list */
-        /* since it's been used by object */
+    object->attribs = g_list_concat (object->attribs, del_object->attribs);
 
-        del_object->attribs = NULL;
-      }
-    }
+    /* Don't free del_object->attribs as it's relinked into object's list */
+    del_object->attribs = NULL;
   }
-
 }
 
 /*! \todo Finish function documentation!!!
diff --git a/libgeda/src/o_picture.c b/libgeda/src/o_picture.c
index 6ec5ccd..48884eb 100644
--- a/libgeda/src/o_picture.c
+++ b/libgeda/src/o_picture.c
@@ -767,7 +767,6 @@ OBJECT *o_picture_copy(TOPLEVEL *toplevel, OBJECT *list_tail,
                             GDK_INTERP_BILINEAR);
 
   /* new_obj->attribute = 0;*/
-  o_attrib_list_copied_to (o_current->attribs, new_obj);
 
   /* return the new tail of the object list */
   return(new_obj);
diff --git a/libgeda/src/o_pin_basic.c b/libgeda/src/o_pin_basic.c
index 79df6e9..7b2cb68 100644
--- a/libgeda/src/o_pin_basic.c
+++ b/libgeda/src/o_pin_basic.c
@@ -273,7 +273,6 @@ OBJECT *o_pin_copy(TOPLEVEL *toplevel, OBJECT *list_tail, OBJECT *o_current)
   new_obj->line->y[1] = o_current->line->y[1];
 
   /*	new_obj->attribute = 0;*/
-  o_attrib_list_copied_to (o_current->attribs, new_obj);
 
   return(new_obj);
 }
diff --git a/libgeda/src/s_basic.c b/libgeda/src/s_basic.c
index 6ebe35a..72cfe87 100644
--- a/libgeda/src/s_basic.c
+++ b/libgeda/src/s_basic.c
@@ -345,14 +345,9 @@ s_delete_object(TOPLEVEL *toplevel, OBJECT *o_current)
     /* second half of if is odd that we need it? hack */
     /* need to do this early so we can do the printfs */
     if (o_current->attached_to != NULL && o_current->attribute == 1) {
-      if (o_current->attached_to->object) {
-				/*printf("removing %s\n", o_current->attached_to->object->name);*/
-      } else {
-        printf("found a null I didn't expect!!!!!!!!!\n");
-      }
 
       /* do the actual remove */
-      o_attrib_delete(o_current->attached_to);
+      o_attrib_remove(&o_current->attached_to->attribs, o_current);
     }
 
     if (toplevel->page_current->object_lastplace == o_current) {
@@ -452,7 +447,6 @@ s_delete_object(TOPLEVEL *toplevel, OBJECT *o_current)
     }
     o_current->attribs = NULL;
 
-
     g_free(o_current);	/* assuming it is not null */
 
     o_current=NULL;		/* misc clean up */




_______________________________________________
geda-cvs mailing list
geda-cvs@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-cvs