/*! \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. */ OBJECT * o_update_component (GSCHEM_TOPLEVEL *w_current, OBJECT *o_current) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *o_new; PAGE *page; GList *new_attribs; GList *old_attribs; GList *iter; const CLibSymbol *clib; 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); page = o_get_page (toplevel, o_current); /* 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); if (clib == NULL) { s_log_message (_("Could not find symbol [%s] in library. Update failed.\n"), o_current->complex_basename); return NULL; } /* 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); } new_attribs = o_complex_promote_attribs (toplevel, o_new); /* 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; gchar *value; g_assert (attr_new->type == OBJ_TEXT); o_attrib_get_name_value (attr_new, &name, NULL); 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; } g_free (name); g_free (value); } new_attribs = g_list_remove_all (new_attribs, NULL); /* 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); /* Add new attributes to page */ s_page_append_list (toplevel, page, new_attribs); /* Update pinnumbers for current slot */ s_slot_update_object (toplevel, o_new); /* Replace old OBJECT with new OBJECT */ s_page_replace (toplevel, page, o_current, o_new); s_delete_object (toplevel, o_current); /* 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; }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void s_delete_object(TOPLEVEL *toplevel, OBJECT *o_current) { if (o_current != NULL) { /* If currently attached to a page, remove it from the page */ if (o_current->page != NULL) { s_page_remove (toplevel, o_current->page, o_current); } s_conn_remove_object_connections (toplevel, o_current); if (o_current->attached_to != NULL) { /* do the actual remove */ o_attrib_remove(toplevel, &o_current->attached_to->attribs, o_current); } /* printf("sdeleting line\n"); */ geda_line_free (o_current->line); o_current->line = NULL; geda_path_free (o_current->path); o_current->path = NULL; /* printf("sdeleting circle\n");*/ geda_circle_free (o_current->circle); o_current->circle = NULL; /* printf("sdeleting arc\n");*/ geda_arc_free (o_current->arc); o_current->arc = NULL; /* printf("sdeleting box\n");*/ geda_box_free (o_current->box); o_current->box = NULL; geda_picture_free (o_current->picture); o_current->picture = NULL; if (o_current->text) { /*printf("sdeleting text->string\n");*/ g_free(o_current->text->string); o_current->text->string = NULL; g_free(o_current->text->disp_string); /* printf("sdeleting text\n");*/ g_free(o_current->text); } o_current->text = NULL; /* printf("sdeleting name\n");*/ g_free(o_current->name); o_current->name = NULL; /* printf("sdeleting complex_basename\n");*/ g_free(o_current->complex_basename); o_current->complex_basename = NULL; if (o_current->complex) { if (o_current->complex->prim_objs) { /* printf("sdeleting complex->primitive_objects\n");*/ geda_object_list_delete (toplevel, o_current->complex->prim_objs); o_current->complex->prim_objs = NULL; } g_free(o_current->complex); o_current->complex = NULL; } o_attrib_detach_all (toplevel, o_current); o_current->weak_refs = s_weakref_notify (o_current, o_current->weak_refs); g_free(o_current); /* assuming it is not null */ o_current=NULL; /* misc clean up */ } }