/*! \brief embed an object into a schematic * \par Function Description * This functions embeds an object \a o_current into a * libgeda. Currently complex objects are just marked to * be embedded later. Picture objects are embedded immediatly. * * \param toplevel The TOPLEVEL object * \param o_current The OBJECT to embed */ void o_embed(TOPLEVEL *toplevel, OBJECT *o_current) { PAGE *page = o_get_page_compat (toplevel, o_current); int page_modified = 0; /* check o_current is a complex and is not already embedded */ if (o_current->type == OBJ_COMPLEX && !o_complex_is_embedded (o_current)) { /* set the embedded flag */ o_current->complex_embedded = TRUE; s_log_message (_("Component [%s] has been embedded\n"), o_current->complex_basename); page_modified = 1; } /* If it's a picture and it's not embedded */ if ( (o_current->type == OBJ_PICTURE) && !o_picture_is_embedded (toplevel, o_current) ) { o_picture_embed (toplevel, o_current); page_modified = 1; } if (page_modified && page != NULL) { /* page content has been modified */ page->CHANGED = 1; } }
/*! \brief unembed an object from a schematic * \par Function Description * This functions unembeds an object \a o_current from a * libgeda structure. Complex objects are just marked to * be not embedded. Picture objects are unembeded immediatly. * * \param toplevel The TOPLEVEL object * \param o_current The OBJECT to unembed */ void o_unembed(TOPLEVEL *toplevel, OBJECT *o_current) { const CLibSymbol *sym; PAGE *page = o_get_page_compat (toplevel, o_current); int page_modified = 0; /* check o_current is an embedded complex */ if (o_current->type == OBJ_COMPLEX && o_complex_is_embedded (o_current)) { /* search for the symbol in the library */ sym = s_clib_get_symbol_by_name (o_current->complex_basename); if (sym == NULL) { /* symbol not found in the symbol library: signal an error */ s_log_message (_("Could not find component [%s], while trying to " "unembed. Component is still embedded\n"), o_current->complex_basename); } else { /* clear the embedded flag */ o_current->complex_embedded = FALSE; s_log_message (_("Component [%s] has been successfully unembedded\n"), o_current->complex_basename); page_modified = 1; } } /* If it's a picture and it's embedded */ if ( (o_current->type == OBJ_PICTURE) && o_picture_is_embedded (toplevel, o_current)) { o_picture_unembed (toplevel, o_current); page_modified = 1; } if (page_modified && page != NULL) { page->CHANGED = 1; } }
/*! \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; }