/*! \todo Finish function documentation!!! * \brief * \par Function Description * Copy all attributes select to the selection list. * * \todo get a better name */ void o_attrib_add_selected(GschemToplevel *w_current, SELECTION *selection, OBJECT *selected) { OBJECT *a_current; GList *a_iter; GList *selected_objects = NULL; g_assert( selection != NULL ); for (a_iter = selected->attribs; a_iter != NULL; a_iter = g_list_next (a_iter)) { a_current = a_iter->data; /* make sure object isn't selected already */ if (!a_current->selected) { o_selection_add (w_current->toplevel, selection, a_current); selected_objects = g_list_prepend (selected_objects, a_current); } } if (selected_objects != NULL) { /* Run select-objects-hook */ g_run_hook_object_list (w_current, "%select-objects-hook", selected_objects); g_list_free (selected_objects); } }
/*! \brief Add invisible attributes of an object to the selection list. * \par Function Description * * Add all invisible attributes attached to the given object * to the selection list. If hidden text is being shown, this * function returns immediately. * * \param [in] w_current The GschemToplevel object. * \param [in,out] selection The SELECTION list to add to. * \param [in] object The OBJECT whose invisible attributes to add. */ void o_attrib_select_invisible (GschemToplevel *w_current, SELECTION *selection, OBJECT *selected) { OBJECT *a_current; GList *a_iter; g_assert( selection != NULL ); if (w_current->toplevel->show_hidden_text) { return; } for (a_iter = selected->attribs; a_iter != NULL; a_iter = g_list_next (a_iter)) { a_current = a_iter->data; if (!a_current->selected && !o_is_visible(a_current)) { o_selection_add (w_current->toplevel, selection, a_current); } } }
/*! \brief Attach attribute to object. * * Attach the name=value pair to the OBJECT "object". This function * was stolen from gschem/src/o_attrib.c:o_attrib_add_attrib and * hacked for gattrib. * \param toplevel TOPLEVEL to operate on * \param text_string * \param visibility * \param show_name_value * \param object * \returns pointer to the object * \todo Does it need to return OBJECT? */ OBJECT * s_object_attrib_add_attrib_in_object (TOPLEVEL *toplevel, char *text_string, int visibility, int show_name_value, OBJECT * object) { int world_x = -1, world_y = -1; int color; int left, right, top, bottom; OBJECT *o_current; OBJECT *new_obj; o_current = object; /* creating a toplevel or unattached attribute */ if (o_current) { /* get coordinates of where to place the text object */ switch (o_current->type) { case (OBJ_COMPLEX): world_x = o_current->complex->x; world_y = o_current->complex->y; color = ATTRIBUTE_COLOR; break; case (OBJ_NET): world_x = o_current->complex->x; world_y = o_current->complex->y; color = ATTRIBUTE_COLOR; break; default: fprintf(stderr, _("In s_object_attrib_add_attrib_in_object, trying to add attrib to non-complex or non-net!\n")); exit(-1); } } else { /* This must be a floating attrib, but what is that !?!?!?!?! */ world_get_object_glist_bounds (toplevel, s_page_objects (toplevel->page_current), &left, &top, &right, &bottom); /* this really is the lower left hand corner */ world_x = left; world_y = top; /* printf("%d %d\n", world_x, world_y); */ color = DETACHED_ATTRIBUTE_COLOR; } /* first create text item */ #if DEBUG printf("=== In s_object_attrib_add_attrib_in_object, about to attach new text attrib with properties:\n"); printf(" color = %d\n", color); printf(" text_string = %s \n", text_string); printf(" text_size = %d \n", toplevel->text_size); printf(" visibility = %d \n", visibility); printf(" show_name_value = %d \n", show_name_value); #endif new_obj = o_text_new (toplevel, color, world_x, world_y, LOWER_LEFT, 0, /* zero is angle */ text_string, DEFAULT_TEXT_SIZE, visibility, show_name_value); s_page_append (toplevel, toplevel->page_current, new_obj); /* now toplevel->page_current->object_tail contains new text item */ /* now attach the attribute to the object (if o_current is not NULL) */ /* remember that o_current contains the object to get the attribute */ if (o_current) { o_attrib_attach (toplevel, new_obj, o_current, FALSE); } o_selection_add (toplevel, toplevel->page_current->selection_list, new_obj); toplevel->page_current->CHANGED = 1; return new_obj; }
/*! \brief try to consolidate a net object * \par Function Description * This function tries to consolidate a net with any other object * that is connected to the current \a object. * * \param toplevel The TOPLEVEL object * \param object The object to consolidate * \return 0 if no consolidation was possible, -1 otherwise * */ static int o_net_consolidate_segments (TOPLEVEL *toplevel, OBJECT *object) { int object_orient; int other_orient; GList *c_current; CONN *conn; OBJECT *other_object; PAGE *page; int changed = 0; g_return_val_if_fail ((toplevel != NULL), 0); g_return_val_if_fail ((object != NULL), 0); g_return_val_if_fail ((object->type == OBJ_NET), 0); /* It's meaningless to do anything here if the object isn't in a page. */ page = o_get_page (toplevel, object); g_return_val_if_fail ((page != NULL), 0); object_orient = o_net_orientation(object); c_current = object->conn_list; while(c_current != NULL) { conn = (CONN *) c_current->data; other_object = conn->other_object; /* only look at end points which have a valid end on the other side */ if (other_object != NULL && conn->type == CONN_ENDPOINT && conn->other_whichone != -1 && conn->whichone != -1 && o_net_consolidate_nomidpoint(object, conn->x, conn->y) ) { if (other_object->type == OBJ_NET) { other_orient = o_net_orientation(other_object); /* - both objects have the same orientation (either vert or horiz) */ /* - it's not the same object */ if (object_orient == other_orient && object->sid != other_object->sid && other_orient != NEITHER) { #if DEBUG printf("consolidating %s to %s\n", object->name, other_object->name); #endif o_net_consolidate_lowlevel(object, other_object, other_orient); changed++; if (other_object->selected == TRUE ) { o_selection_remove (toplevel, page->selection_list, other_object); /* If we're consolidating with a selected object, * ensure we select the resulting object. */ if (object->selected == FALSE) { o_selection_add (toplevel, page->selection_list, object); } } s_delete_object (toplevel, other_object); o_net_recalc(toplevel, object); s_tile_update_object(toplevel, object); s_conn_update_object (toplevel, object); return(-1); } } } c_current = g_list_next (c_current); } return(0); }
/*! \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; }
/* text item */ OBJECT *o_attrib_add_attrib(GschemToplevel *w_current, const char *text_string, int visibility, int show_name_value, OBJECT *object) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); OBJECT *new_obj; int world_x = - 1, world_y = -1; int align = LOWER_LEFT; int angle = 0; int color; int left, right, top, bottom; OBJECT *o_current; color = DETACHED_ATTRIBUTE_COLOR; o_current = object; /* creating a toplevel or unattached attribute */ if (o_current) { /* get coordinates of where to place the text object */ switch(o_current->type) { case(OBJ_COMPLEX): case(OBJ_PLACEHOLDER): world_x = o_current->complex->x; world_y = o_current->complex->y; align = LOWER_LEFT; angle = 0; color = ATTRIBUTE_COLOR; break; case(OBJ_ARC): world_x = o_current->arc->x; world_y = o_current->arc->y; align = LOWER_LEFT; angle = 0; color = ATTRIBUTE_COLOR; break; case(OBJ_CIRCLE): world_x = o_current->circle->center_x; world_y = o_current->circle->center_y; align = LOWER_LEFT; angle = 0; color = ATTRIBUTE_COLOR; break; case(OBJ_BOX): world_x = o_current->box->upper_x; world_y = o_current->box->upper_y; align = LOWER_LEFT; angle = 0; color = ATTRIBUTE_COLOR; break; case(OBJ_LINE): case(OBJ_NET): case(OBJ_PIN): case(OBJ_BUS): { int dx = o_current->line->x[1] - o_current->line->x[0]; int dy = o_current->line->y[1] - o_current->line->y[0]; if (dy == 0) { if (dx > 0) { world_x = o_current->line->x[0] + SPACING_FROM_END; world_y = o_current->line->y[0] + SPACING_PERPENDICULAR; align = LOWER_LEFT; angle = 0; } else { world_x = o_current->line->x[0] - SPACING_FROM_END; world_y = o_current->line->y[0] + SPACING_PERPENDICULAR; align = LOWER_RIGHT; angle = 0; } } else if (dx == 0) { if (dy > 0) { world_x = o_current->line->x[0] - SPACING_PERPENDICULAR; world_y = o_current->line->y[0] + SPACING_FROM_END; align = LOWER_LEFT; angle = 90; } else { world_x = o_current->line->x[0] - SPACING_PERPENDICULAR; world_y = o_current->line->y[0] - SPACING_FROM_END; align = LOWER_RIGHT; angle = 90; } } else { world_x = o_current->line->x[0]; world_y = o_current->line->y[0]; align = LOWER_LEFT; angle = 0; } color = ATTRIBUTE_COLOR; } break; case(OBJ_TEXT): world_x = o_current->text->x; world_y = o_current->text->y; color = DETACHED_ATTRIBUTE_COLOR; align = LOWER_LEFT; angle = 0; o_current = NULL; break; } } else { world_get_object_glist_bounds (toplevel, s_page_objects (toplevel->page_current), &left, &top, &right, &bottom); /* this really is the lower left hand corner */ world_x = left; world_y = top; /* printf("%d %d\n", world_x, world_y); */ align = LOWER_LEFT; angle = 0; color = DETACHED_ATTRIBUTE_COLOR; } /* first create text item */ new_obj = o_text_new(toplevel, color, world_x, world_y, align, angle, text_string, w_current->text_size, /* current text size */ visibility, show_name_value); s_page_append (toplevel, toplevel->page_current, new_obj); /* now attach the attribute to the object (if o_current is not NULL) */ /* remember that o_current contains the object to get the attribute */ if (o_current) { o_attrib_attach (toplevel, new_obj, o_current, FALSE); } o_selection_add (toplevel, toplevel->page_current->selection_list, new_obj); /* handle slot= attribute, it's a special case */ if (o_current != NULL && g_ascii_strncasecmp (text_string, "slot=", 5) == 0) { o_slot_end (w_current, o_current, text_string); } /* Call add-objects-hook. */ g_run_hook_object (w_current, "%add-objects-hook", new_obj); g_run_hook_object (w_current, "%select-objects-hook", new_obj); gschem_toplevel_page_content_changed (w_current, toplevel->page_current); return new_obj; }
/*! \brief try to consolidate a net object * \par Function Description * This function tries to consolidate a net with any other object * that is connected to the current \a object. * * \param toplevel The TOPLEVEL object * \param object The object to consolidate * \return 0 if no consolidation was possible, -1 otherwise * */ int o_net_consolidate_segments(TOPLEVEL *toplevel, OBJECT *object) { int object_orient; int other_orient; GList *c_current; CONN *conn; OBJECT *other_object; int changed = 0; int reselect_new=FALSE; if (object == NULL) { return(0); } if (object->type != OBJ_NET) { return(0); } object_orient = o_net_orientation(object); c_current = object->conn_list; while(c_current != NULL) { conn = (CONN *) c_current->data; other_object = conn->other_object; /* only look at end points which have a valid end on the other side */ if (other_object != NULL && conn->type == CONN_ENDPOINT && conn->other_whichone != -1 && conn->whichone != -1 && o_net_consolidate_nomidpoint(object, conn->x, conn->y) ) { if (other_object->type == OBJ_NET) { other_orient = o_net_orientation(other_object); /* - both objects have the same orientation (either vert or horiz) */ /* - it's not the same object */ if (object_orient == other_orient && object->sid != other_object->sid && other_orient != NEITHER) { #if DEBUG printf("consolidating %s to %s\n", object->name, other_object->name); #endif o_net_consolidate_lowlevel(object, other_object, other_orient); changed++; if (other_object->selected == TRUE ) { o_selection_remove( toplevel->page_current->selection_list, other_object ); reselect_new=TRUE; } if (reselect_new == TRUE) { o_selection_remove( toplevel->page_current->selection_list, object ); o_selection_add( toplevel->page_current->selection_list, object ); } s_conn_remove_object (toplevel, other_object); s_page_remove (toplevel->page_current, other_object); s_delete_object (toplevel, other_object); o_net_recalc(toplevel, object); s_tile_update_object(toplevel, object); s_conn_update_object (toplevel, object); return(-1); } } } c_current = g_list_next (c_current); } return(0); }