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

gEDA-cvs: gaf.git: branch: master updated (1.6.1-20100214-114-g84c708e)



The branch, master has been updated
       via  84c708ec13ab8cbd2f66eea3239ce8106232ffab (commit)
       via  1126d3899e03492d5f2f41b244cd685e257792f6 (commit)
      from  8531f91cdf9862ac7f4211b3070fa28be759d0c5 (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
=========

 gschem/include/prototype.h          |    2 +-
 gschem/src/i_callbacks.c            |   47 ++++------
 gschem/src/o_misc.c                 |  168 ++++++++++++++++-------------------
 libgeda/include/libgeda/prototype.h |    1 +
 libgeda/src/s_page.c                |   29 ++++++
 5 files changed, 125 insertions(+), 122 deletions(-)


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

commit 84c708ec13ab8cbd2f66eea3239ce8106232ffab
Author: Peter TB Brett <peter@xxxxxxxxxxxxx>
Commit: Peter TB Brett <peter@xxxxxxxxxxxxx>

    gschem: Rewrite o_update_component() to replace, not modify, OBJECTs.
    
    Instead of deleting the contents of a compound OBJECT and adding new
    contents loaded from file, make o_update_component() create a new
    OBJECT, move attributes across, and then replace the original OBJECT
    with the new OBJECT.
    
    This works much more nicely with the use of an event-based
    connection-update scheme in libgeda.
    
    Fixes a crash bug reported by Peter Clifton <pcjc2@xxxxxxxxx>, where
    component prim_objs were not being correctly removed and re-added to
    the page's tile system.

:100644 100644 e018101... c6129df... M	gschem/include/prototype.h
:100644 100644 4e664ec... 09c4057... M	gschem/src/i_callbacks.c
:100644 100644 fe84603... eb347aa... M	gschem/src/o_misc.c

commit 1126d3899e03492d5f2f41b244cd685e257792f6
Author: Peter TB Brett <peter@xxxxxxxxxxxxx>
Commit: Peter TB Brett <peter@xxxxxxxxxxxxx>

    libgeda: Add s_page_replace().
    
    Add a function to replace one object in the PAGE object list with
    another while preserving its position in the list.

:100644 100644 8021199... 4e9cb0e... M	libgeda/include/libgeda/prototype.h
:100644 100644 d486734... ff21ac2... M	libgeda/src/s_page.c

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

commit 84c708ec13ab8cbd2f66eea3239ce8106232ffab
Author: Peter TB Brett <peter@xxxxxxxxxxxxx>
Commit: Peter TB Brett <peter@xxxxxxxxxxxxx>

    gschem: Rewrite o_update_component() to replace, not modify, OBJECTs.
    
    Instead of deleting the contents of a compound OBJECT and adding new
    contents loaded from file, make o_update_component() create a new
    OBJECT, move attributes across, and then replace the original OBJECT
    with the new OBJECT.
    
    This works much more nicely with the use of an event-based
    connection-update scheme in libgeda.
    
    Fixes a crash bug reported by Peter Clifton <pcjc2@xxxxxxxxx>, where
    component prim_objs were not being correctly removed and re-added to
    the page's tile system.

diff --git a/gschem/include/prototype.h b/gschem/include/prototype.h
index e018101..c6129df 100644
--- a/gschem/include/prototype.h
+++ b/gschem/include/prototype.h
@@ -604,7 +604,7 @@ void o_edit_make_visible(GSCHEM_TOPLEVEL *w_current, const GList *o_list);
 int o_edit_find_text(GSCHEM_TOPLEVEL *w_current, const GList *o_list, char *stext, int descend, int skip);
 void o_edit_hide_specific_text(GSCHEM_TOPLEVEL *w_current, const GList *o_list, char *stext);
 void o_edit_show_specific_text(GSCHEM_TOPLEVEL *w_current, const GList *o_list, char *stext);
-void o_update_component(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current);
+OBJECT *o_update_component(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current);
 void o_autosave_backups(GSCHEM_TOPLEVEL *w_current);
 /* o_move.c */
 void o_move_start(GSCHEM_TOPLEVEL *w_current, int x, int y);
diff --git a/gschem/src/i_callbacks.c b/gschem/src/i_callbacks.c
index 4e664ec..09c4057 100644
--- a/gschem/src/i_callbacks.c
+++ b/gschem/src/i_callbacks.c
@@ -1080,41 +1080,32 @@ DEFINE_I_CALLBACK(edit_update)
 {
   GSCHEM_TOPLEVEL *w_current = (GSCHEM_TOPLEVEL*) data;
   TOPLEVEL *toplevel = w_current->toplevel;
-  OBJECT *o_current;
-  GList* selection_copy;
-  GList* s_current;
+  GList *selection;
+  GList *selected_components = NULL;
+  GList *iter;
 
-  exit_if_null(w_current);
+  g_return_if_fail (w_current != NULL);
 
   i_update_middle_button(w_current, i_callback_edit_update, _("Update"));
-  /* anything selected ? */
   if (o_select_selected(w_current)) {
 
-    /* yes, update each selected component, but operate from a copy of the */
-    /* selection list, since o_update_component will modify the selection */
-
-    /* After the following code executes, only OBJ_COMPLEX object will be */
-    /* left selected. */
-
-    /* g_list_copy does a shallow copy which is exactly what we need here */
-    selection_copy = g_list_copy (
-              geda_list_get_glist (toplevel->page_current->selection_list));
-    s_current = selection_copy;
-    while (s_current != NULL) {
-      o_current = (OBJECT *) s_current->data;
-      g_assert (o_current != NULL);
-      if (o_current->type == OBJ_COMPLEX) {
-        o_update_component (w_current, o_current);
-      }
-      else
-      {
-        /* object was not a OBJ_COMPLEX, so unselect it. */
-        o_selection_remove (toplevel,
-                            toplevel->page_current->selection_list, o_current);
+    /* Updating components modifies the selection. Therefore, create a
+     * new list of only the OBJECTs we want to update from the current
+     * selection, then iterate over that new list to perform the
+     * update. */
+    selection = geda_list_get_glist (toplevel->page_current->selection_list);
+    for (iter = selection; iter != NULL; iter = g_list_next (iter)) {
+      OBJECT *o_current = (OBJECT *) iter->data;
+      if (o_current != NULL && o_current->type == OBJ_COMPLEX) {
+        selected_components = g_list_prepend (selected_components, o_current);
       }
-      s_current = g_list_next(s_current);
     }
-    g_list_free(selection_copy);
+    for (iter = selected_components; iter != NULL; iter = g_list_next (iter)) {
+      OBJECT *o_current = (OBJECT *) iter->data;
+      iter->data = o_update_component (w_current, o_current);
+    }
+    g_list_free (selected_components);
+
   } else {
     /* nothing selected, go back to select state */
     o_redraw_cleanstates(w_current);	
diff --git a/gschem/src/o_misc.c b/gschem/src/o_misc.c
index fe84603..eb347aa 100644
--- a/gschem/src/o_misc.c
+++ b/gschem/src/o_misc.c
@@ -627,29 +627,39 @@ void o_edit_show_specific_text (GSCHEM_TOPLEVEL *w_current,
   o_undo_savestate(w_current, UNDO_ALL);
 }
 
-/*! \todo Finish function documentation!!!
- *  \brief
- *  \par Function Description
+
+/*! \brief Update a component.
  *
+ * \par Function Description
+ * Updates \a o_current to the latest version of the symbol available
+ * in the symbol library, while preserving any attributes set in the
+ * current schematic. On success, returns the new OBJECT which
+ * replaces \a o_current on the page; \a o_current is deleted. On
+ * failure, returns NULL, and \a o_current is left unchanged.
+ *
+ * \param [in]     w_current The GSCHEM_TOPLEVEL object.
+ * \param [in,out] o_current The OBJECT to be updated.
+ *
+ * \return the new OBJECT that replaces \a o_current.
  */
-void o_update_component(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
+OBJECT *
+o_update_component (GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
-  OBJECT *new_complex;
-  OBJECT *a_current;
-  GList *temp_list;
-  GList *a_iter;
-  GList *po_iter;
-  gboolean is_embedded;
+  OBJECT *o_new;
+  PAGE *page;
+  GList *new_attribs;
+  GList *old_attribs;
+  GList *iter;
   const CLibSymbol *clib;
 
-  g_return_if_fail (o_current != NULL);
+  g_return_val_if_fail (o_current != NULL, NULL);
+  g_return_val_if_fail (o_current->type == OBJ_COMPLEX, NULL);
+  g_return_val_if_fail (o_current->complex_basename != NULL, NULL);
 
-  is_embedded = o_complex_is_embedded (o_current);
+  page = o_get_page (toplevel, o_current);
 
-  g_assert (o_current->complex_basename != NULL);
-
-  /* This shuold be replaced with API to invalidate only the specific
+  /* This should be replaced with API to invalidate only the specific
    * symbol name we want to update */
   s_clib_flush_symbol_cache ();
   clib = s_clib_get_symbol_by_name (o_current->complex_basename);
@@ -657,106 +667,78 @@ void o_update_component(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
   if (clib == NULL) {
     s_log_message (_("Could not find symbol [%s] in library. Update failed.\n"),
                    o_current->complex_basename);
-    return;
+    return NULL;
   }
 
-  /* ensure we repaint where the complex object was */
-  o_invalidate (w_current, o_current);
-  /* delete its connections */
-  s_conn_remove_object (toplevel, o_current);
-  /* and unselect it */
-  o_selection_remove (toplevel,
-                      toplevel->page_current->selection_list, o_current);
-
-  new_complex = o_complex_new (toplevel, OBJ_COMPLEX, DEFAULT_COLOR,
-                               o_current->complex->x,
-                               o_current->complex->y,
-                               o_current->complex->angle,
-                               o_current->complex->mirror,
-                               clib, o_current->complex_basename,
-                               1);
-
-  temp_list = o_complex_promote_attribs (toplevel, new_complex);
-  temp_list = g_list_append (temp_list, new_complex);
-
-  /* updating the old complex with data from the new one */
-  /* first process the prim_objs: */
-  /*   - delete the prim_objs of the old component */
-  s_delete_object_glist (toplevel, o_current->complex->prim_objs);
-  /*   - put the prim_objs of the new component in the old one */
-  o_current->complex->prim_objs = new_complex->complex->prim_objs;
-
-  /* set the parent field now */
-  for (po_iter = o_current->complex->prim_objs;
-       po_iter != NULL;
-       po_iter = g_list_next (po_iter)) {
-    OBJECT *tmp = po_iter->data;
-    tmp->parent = o_current;
+  /* Unselect the old object. */
+  o_selection_remove (toplevel, page->selection_list, o_current);
+
+  /* Create new object and set embedded */
+  o_new = o_complex_new (toplevel, OBJ_COMPLEX, DEFAULT_COLOR,
+                         o_current->complex->x,
+                         o_current->complex->y,
+                         o_current->complex->angle,
+                         o_current->complex->mirror,
+                         clib, o_current->complex_basename,
+                         1);
+  if (o_complex_is_embedded (o_current)) {
+    o_embed (toplevel, o_new);
   }
 
-  /*   - reset the new complex prim_objs */
-  new_complex->complex->prim_objs = NULL;
+  new_attribs = o_complex_promote_attribs (toplevel, o_new);
 
-  /* then process the attributes: */
-  /*   - check each attrib of the new complex */
-  a_iter = new_complex->attribs;
-  while (a_iter != NULL) {
-    OBJECT *o_attrib;
+  /* Cull any attributes from new COMPLEX that are already attached to
+   * old COMPLEX. Note that the new_attribs list is kept consistent by
+   * setting GList data pointers to NULL if their OBJECTs are
+   * culled. At the end, the new_attribs list is updated by removing
+   * all list items with NULL data. This is slightly magic, but
+   * works. */
+  for (iter = new_attribs; iter != NULL; iter = g_list_next (iter)) {
+    OBJECT *attr_new = iter->data;
     gchar *name;
-    char *attrfound;
-
-    a_current = a_iter->data;
-    g_assert (a_current->type == OBJ_TEXT);
+    gchar *value;
 
-    o_attrib_get_name_value (a_current, &name, NULL);
+    g_assert (attr_new->type == OBJ_TEXT);
 
-    /* We are only interested in the attributes which were promoted during
-     * load of the new complex. Any which aren't already promoted in the
-     * schematic are migrated.
-     */
-    attrfound = o_attrib_search_attached_attribs_by_name (o_current, name, 0);
+    o_attrib_get_name_value (attr_new, &name, NULL);
 
-    /* free this now since it is no longer being used */
-    g_free(name);
-
-    if (attrfound == NULL) {
-      /* attribute with same name not found in old component: */
-      /* add new attribute to old component */
-
-      /* make a copy of the attribute object */
-      o_attrib = o_object_copy (toplevel, a_current);
-      s_page_append (toplevel, toplevel->page_current, o_attrib);
-      /* add the attribute to old */
-      o_attrib_add (toplevel, o_current, o_attrib);
-      /* note: this object is unselected (not added to selection). */
-    }
-    else
-    {
-      g_free(attrfound);
+    value = o_attrib_search_attached_attribs_by_name (o_current, name, 0);
+    if (value != NULL) {
+      o_attrib_remove (toplevel, &o_new->attribs, attr_new);
+      s_delete_object (toplevel, attr_new);
+      iter->data = NULL;
     }
 
-    a_iter = g_list_next (a_iter);
+    g_free (name);
+    g_free (value);
   }
+  new_attribs = g_list_remove_all (new_attribs, NULL);
 
-  s_delete_object_glist (toplevel, temp_list);
+  /* Detach attributes from old OBJECT and attach to new OBJECT */
+  old_attribs = g_list_copy (o_current->attribs);
+  o_attrib_detach_all (toplevel, o_current);
+  o_attrib_attach_list (toplevel, old_attribs, o_new, 1);
+  g_list_free (old_attribs);
 
-  /* update the pinnumbers to the current slot */
-  s_slot_update_object (toplevel, o_current);
+  /* Add new attributes to page */
+  s_page_append_list (toplevel, page, new_attribs);
+  g_list_free (new_attribs);
 
-  /* Recalculate the bounds of the object */
-  o_recalc_single_object(toplevel, o_current);
+  /* Update pinnumbers for current slot */
+  s_slot_update_object (toplevel, o_new);
 
-  /* reconnect and re-select */
-  s_conn_update_object (toplevel, o_current);
-  o_selection_add (toplevel, toplevel->page_current->selection_list, o_current);
+  /* Replace old OBJECT with new OBJECT */
+  s_page_replace (toplevel, page, o_current, o_new);
+  s_delete_object (toplevel, o_current);
 
-  /* Re-flag as embedded if necessary */
-  o_current->complex_embedded = is_embedded;
+  /* Select new OBJECT */
+  o_selection_add (toplevel, page->selection_list, o_new);
 
   /* mark the page as modified */
   toplevel->page_current->CHANGED = 1;
   o_undo_savestate (w_current, UNDO_ALL);
 
+  return o_new;
 }
 
 /*! \brief Do autosave on all pages that are marked.

commit 1126d3899e03492d5f2f41b244cd685e257792f6
Author: Peter TB Brett <peter@xxxxxxxxxxxxx>
Commit: Peter TB Brett <peter@xxxxxxxxxxxxx>

    libgeda: Add s_page_replace().
    
    Add a function to replace one object in the PAGE object list with
    another while preserving its position in the list.

diff --git a/libgeda/include/libgeda/prototype.h b/libgeda/include/libgeda/prototype.h
index 8021199..4e9cb0e 100644
--- a/libgeda/include/libgeda/prototype.h
+++ b/libgeda/include/libgeda/prototype.h
@@ -364,6 +364,7 @@ gint s_page_autosave (TOPLEVEL *toplevel);
 void s_page_append (TOPLEVEL *toplevel, PAGE *page, OBJECT *object);
 void s_page_append_list (TOPLEVEL *toplevel, PAGE *page, GList *obj_list);
 void s_page_remove (TOPLEVEL *toplevel, PAGE *page, OBJECT *object);
+void s_page_replace (TOPLEVEL *toplevel, PAGE *page, OBJECT *object1, OBJECT *object2);
 void s_page_delete_objects (TOPLEVEL *toplevel, PAGE *page);
 const GList *s_page_objects (PAGE *page);
 GList *s_page_objects_in_region (TOPLEVEL *toplevel, PAGE *page, int min_x, int min_y, int max_x, int max_y);
diff --git a/libgeda/src/s_page.c b/libgeda/src/s_page.c
index d486734..ff21ac2 100644
--- a/libgeda/src/s_page.c
+++ b/libgeda/src/s_page.c
@@ -605,6 +605,35 @@ void s_page_remove (TOPLEVEL *toplevel, PAGE *page, OBJECT *object)
   page->_object_list = g_list_remove (page->_object_list, object);
 }
 
+/*! \brief Replace an OBJECT in a PAGE, in the same list position.
+ *
+ * \par Function Description
+ * Removes \a object1 from \a page's linked list of objects, and puts
+ * \a object2 in the position thus vacated. If \a object1 is not in \a
+ * page, object2 is appended to \a page.
+ *
+ * \param [in] toplevel  The TOPLEVEL object.
+ * \param [in] page      The PAGE to be modified.
+ * \param [in] object1   The OBJECT being removed from the page.
+ * \param [in] object2   The OBJECT being added to the page.
+ */
+void
+s_page_replace (TOPLEVEL *toplevel, PAGE *page,
+                OBJECT *object1, OBJECT *object2)
+{
+  GList *iter = g_list_find (page->_object_list, object1);
+
+  /* If object1 not found, append object2 */
+  if (iter == NULL) {
+    s_page_append (toplevel, page, object2);
+    return;
+  }
+
+  pre_object_removed (toplevel, page, object1);
+  iter->data = object2;
+  object_added (toplevel, page, object2);
+}
+
 /*! \brief Remove and free all OBJECTs from the PAGE
  *
  *  \par Function Description




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