/*! \brief Rotate all objects in list. * \par Function Description * Given an object <B>list</B>, and the center of rotation * (<B>centerx</B>,<B>centery</B>, this function traverses all the selection * list, rotating each object through angle <B>angle</B>. * The list contains a given object and all its attributes * (refdes, pinname, pinlabel, ...). * There is a second pass to run the rotate hooks of non-simple objects, * like pin or complex objects, for example. * * \param [in] w_current The GSCHEM_TOPLEVEL object. * \param [in] centerx Center x coordinate of rotation. * \param [in] centery Center y coordinate of rotation. * \param [in] angle Angle to rotate the objects through. * \param [in] list The list of objects to rotate. */ void o_rotate_world_update(GSCHEM_TOPLEVEL *w_current, int centerx, int centery, int angle, GList *list) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *o_current; GList *o_iter; /* this is okay if you just hit rotate and have nothing selected */ if (list == NULL) { w_current->inside_action = 0; i_set_state(w_current, SELECT); return; } o_invalidate_glist (w_current, list); /* Find connected objects, removing each object in turn from the * connection list. We only _really_ want those objects connected * to the selection, not those within in it. */ for (o_iter = list; o_iter != NULL; o_iter = g_list_next (o_iter)) { o_current = o_iter->data; s_conn_remove_object (toplevel, o_current); } o_glist_rotate_world( toplevel, centerx, centery, angle, list ); /* Find connected objects, adding each object in turn back to the * connection list. We only _really_ want those objects connected * to the selection, not those within in it. */ for (o_iter = list; o_iter != NULL; o_iter = g_list_next (o_iter)) { o_current = o_iter->data; s_conn_update_object (toplevel, o_current); } o_invalidate_glist (w_current, list); /* Run rotate-objects-hook */ g_run_hook_object_list ("%rotate-objects-hook", list); /* Don't save the undo state if we are inside an action */ /* This is useful when rotating the selection while moving, for example */ toplevel->page_current->CHANGED = 1; if (!w_current->inside_action) { o_undo_savestate(w_current, UNDO_ALL); } }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_mirror_world_update(GSCHEM_TOPLEVEL *w_current, int centerx, int centery, GList *list) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *o_current; GList *o_iter; if (list == NULL) { w_current->inside_action = 0; i_set_state(w_current, SELECT); return; } o_invalidate_glist (w_current, list); /* Find connected objects, removing each object in turn from the * connection list. We only _really_ want those objects connected * to the selection, not those within in it. */ for (o_iter = list; o_iter != NULL; o_iter = g_list_next (o_iter)) { o_current = o_iter->data; s_conn_remove_object (toplevel, o_current); } o_glist_mirror_world( toplevel, centerx, centery, list ); /* Find connected objects, adding each object in turn back to the * connection list. We only _really_ want those objects connected * to the selection, not those within in it. */ for (o_iter = list; o_iter != NULL; o_iter = g_list_next (o_iter)) { o_current = o_iter->data; s_conn_update_object (toplevel, o_current); } o_invalidate_glist (w_current, list); /* Run mirror-objects-hook */ g_run_hook_object_list ("%mirror-objects-hook", list); toplevel->page_current->CHANGED=1; o_undo_savestate(w_current, UNDO_ALL); }
/* Called just before removing an OBJECT from a PAGE. */ static void pre_object_removed (TOPLEVEL *toplevel, PAGE *page, OBJECT *object) { o_emit_pre_change_notify (toplevel, object); /* Remove object from the list of connectible objects */ s_conn_remove_object (page, object); /* Clear object parent pointer */ #ifndef NDEBUG if (object->page == NULL) { g_critical ("Object %p has NULL parent page!", object); } #endif object->page = NULL; /* Clear page's object_lastplace pointer if set */ if (page->object_lastplace == object) { page->object_lastplace = NULL; } /* Remove object from connection system */ s_conn_remove_object_connections (toplevel, object); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ int o_net_add_busrippers(GSCHEM_TOPLEVEL *w_current, OBJECT *net_obj, GList *prev_conn_objects) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *new_obj; int color; GList *cl_current = NULL; OBJECT *bus_object = NULL; CONN *found_conn = NULL; int done; int otherone; BUS_RIPPER rippers[2]; int ripper_count = 0; int i; double length; int sign; double distance1, distance2; int first, second; int made_changes = FALSE; const int ripper_size = w_current->bus_ripper_size; int complex_angle = 0; const CLibSymbol *rippersym = NULL; length = o_line_length(net_obj); if (!prev_conn_objects) { return(FALSE); } if (length <= ripper_size) { return(FALSE); } if (toplevel->override_net_color == -1) { color = NET_COLOR; } else { color = toplevel->override_net_color; } /* check for a bus connection and draw rippers if so */ cl_current = prev_conn_objects; while (cl_current != NULL) { bus_object = (OBJECT *) cl_current->data; if (bus_object && bus_object->type == OBJ_BUS) { /* yes, using the net routine is okay */ int bus_orientation = o_net_orientation(bus_object); int net_orientation = o_net_orientation(net_obj); /* find the CONN structure which is associated with this object */ GList *cl_current2 = net_obj->conn_list; done = FALSE; while (cl_current2 != NULL && !done) { CONN *tmp_conn = (CONN *) cl_current2->data; if (tmp_conn && tmp_conn->other_object && tmp_conn->other_object == bus_object) { found_conn = tmp_conn; done = TRUE; } cl_current2 = g_list_next(cl_current2); } if (!found_conn) { return(FALSE); } otherone = !found_conn->whichone; /* now deal with the found connection */ if (bus_orientation == HORIZONTAL && net_orientation == VERTICAL) { /* printf("found horiz bus %s %d!\n", bus_object->name, found_conn->whichone);*/ sign = bus_object->bus_ripper_direction; if (!sign) { if (bus_object->line->x[0] < bus_object->line->x[1]) { first = 0; second = 1; } else { first = 1; second = 0; } distance1 = abs(bus_object->line->x[first] - net_obj->line->x[found_conn->whichone]); distance2 = abs(bus_object->line->x[second] - net_obj->line->x[found_conn->whichone]); if (distance1 <= distance2) { sign = 1; } else { sign = -1; } bus_object->bus_ripper_direction = sign; } /* printf("hor sign: %d\n", sign); */ if (net_obj->line->y[otherone] < bus_object->line->y[0]) { /* new net is below bus */ /*printf("below\n");*/ if (ripper_count >= 2) { /* try to exit gracefully */ fprintf(stderr, _("Tried to add more than two bus rippers. Internal gschem error.\n")); made_changes = FALSE; break; } if (w_current->bus_ripper_rotation == NON_SYMMETRIC) { /* non-symmetric */ if (sign == 1) { complex_angle = 0; } else { complex_angle = 90; } } else { /* symmetric */ complex_angle = 0; } net_obj->line->y[found_conn->whichone] -= ripper_size; o_recalc_single_object(toplevel, net_obj); rippers[ripper_count].x[0] = net_obj->line->x[found_conn->whichone]; rippers[ripper_count].y[0] = net_obj->line->y[found_conn->whichone]; rippers[ripper_count].x[1] = net_obj->line->x[found_conn->whichone] + sign*ripper_size; rippers[ripper_count].y[1] = net_obj->line->y[found_conn->whichone] + ripper_size; ripper_count++; /* printf("done\n"); */ made_changes++; } else { /* new net is above bus */ /* printf("above\n"); */ if (ripper_count >= 2) { /* try to exit gracefully */ fprintf(stderr, _("Tried to add more than two bus rippers. Internal gschem error.\n")); made_changes = FALSE; break; } if (w_current->bus_ripper_rotation == NON_SYMMETRIC) { /* non-symmetric */ if (sign == 1) { complex_angle = 270; } else { complex_angle = 180; } } else { /* symmetric */ complex_angle = 180; } net_obj->line->y[found_conn->whichone] += ripper_size; o_recalc_single_object(toplevel, net_obj); rippers[ripper_count].x[0] = net_obj->line->x[found_conn->whichone]; rippers[ripper_count].y[0] = net_obj->line->y[found_conn->whichone]; rippers[ripper_count].x[1] = net_obj->line->x[found_conn->whichone] + sign*ripper_size; rippers[ripper_count].y[1] = net_obj->line->y[found_conn->whichone] - ripper_size; ripper_count++; /* printf("done\n"); */ made_changes++; } } else if (bus_orientation == VERTICAL && net_orientation == HORIZONTAL) { /* printf("found vert bus %s %d!\n", bus_object->name, found_conn->whichone); */ sign = bus_object->bus_ripper_direction; if (!sign) { if (bus_object->line->y[0] < bus_object->line->y[1]) { first = 0; second = 1; } else { first = 1; second = 0; } distance1 = abs(bus_object->line->y[first] - net_obj->line->y[found_conn->whichone]); distance2 = abs(bus_object->line->y[second] - net_obj->line->y[found_conn->whichone]); if (distance1 <= distance2) { sign = 1; } else { sign = -1; } bus_object->bus_ripper_direction = sign; } /* printf("ver sign: %d\n", sign); */ if (net_obj->line->x[otherone] < bus_object->line->x[0]) { /* new net is to the left of the bus */ /* printf("left\n"); */ if (ripper_count >= 2) { /* try to exit gracefully */ fprintf(stderr, _("Tried to add more than two bus rippers. Internal gschem error.\n")); made_changes = FALSE; break; } if (w_current->bus_ripper_rotation == NON_SYMMETRIC) { /* non-symmetric */ if (sign == 1) { complex_angle = 0; } else { complex_angle = 270; } } else { /* symmetric */ complex_angle = 270; } net_obj->line->x[found_conn->whichone] -= ripper_size; o_recalc_single_object(toplevel, net_obj); rippers[ripper_count].x[0] = net_obj->line->x[found_conn->whichone]; rippers[ripper_count].y[0] = net_obj->line->y[found_conn->whichone]; rippers[ripper_count].x[1] = net_obj->line->x[found_conn->whichone] + ripper_size; rippers[ripper_count].y[1] = net_obj->line->y[found_conn->whichone] + sign*ripper_size; ripper_count++; made_changes++; } else { /* new net is to the right of the bus */ /* printf("right\n"); */ if (ripper_count >= 2) { /* try to exit gracefully */ fprintf(stderr, _("Tried to add more than two bus rippers. Internal gschem error.\n")); made_changes = FALSE; break; } if (w_current->bus_ripper_rotation == NON_SYMMETRIC) { /* non-symmetric */ if (sign == 1) { complex_angle = 90; } else { complex_angle = 180; } } else { /* symmetric */ complex_angle = 90; } net_obj->line->x[found_conn->whichone] += ripper_size; o_recalc_single_object(toplevel, net_obj); rippers[ripper_count].x[0] = net_obj->line->x[found_conn->whichone]; rippers[ripper_count].y[0] = net_obj->line->y[found_conn->whichone]; rippers[ripper_count].x[1] = net_obj->line->x[found_conn->whichone] - ripper_size; rippers[ripper_count].y[1] = net_obj->line->y[found_conn->whichone] + sign*ripper_size; ripper_count++; made_changes++; } } } cl_current = g_list_next(cl_current); } if (made_changes) { s_conn_remove_object (toplevel, net_obj); if (w_current->bus_ripper_type == COMP_BUS_RIPPER) { GList *symlist = s_clib_search (toplevel->bus_ripper_symname, CLIB_EXACT); if (symlist != NULL) { rippersym = (CLibSymbol *) symlist->data; } g_list_free (symlist); } for (i = 0; i < ripper_count; i++) { if (w_current->bus_ripper_type == NET_BUS_RIPPER) { new_obj = o_net_new(toplevel, OBJ_NET, color, rippers[i].x[0], rippers[i].y[0], rippers[i].x[1], rippers[i].y[1]); s_page_append (toplevel->page_current, new_obj); } else { if (rippersym != NULL) { new_obj = o_complex_new (toplevel, OBJ_COMPLEX, DEFAULT_COLOR, rippers[i].x[0], rippers[i].y[0], complex_angle, 0, rippersym, toplevel->bus_ripper_symname, 1); s_page_append_list (toplevel->page_current, o_complex_promote_attribs (toplevel, new_obj)); s_page_append (toplevel->page_current, new_obj); o_invalidate (w_current, new_obj); } else { s_log_message(_("Bus ripper symbol [%s] was not found in any component library\n"), toplevel->bus_ripper_symname); } } } s_conn_update_object (toplevel, net_obj); return(TRUE); } return(FALSE); }
/*! \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); }
/*! \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 (toplevel, o_current); if (o_current->attached_to != NULL) { /* do the actual remove */ o_attrib_remove(toplevel, &o_current->attached_to->attribs, o_current); } if (o_current->line) { /* printf("sdeleting line\n");*/ g_free(o_current->line); } o_current->line = NULL; if (o_current->path) { g_free(o_current->path); } o_current->path = NULL; /* printf("sdeleting circle\n");*/ g_free(o_current->circle); o_current->circle = NULL; /* printf("sdeleting arc\n");*/ g_free(o_current->arc); o_current->arc = NULL; /* printf("sdeleting box\n");*/ g_free(o_current->box); o_current->box = NULL; if (o_current->picture) { /* printf("sdeleting picture\n");*/ g_free(o_current->picture->file_content); if (o_current->picture->pixbuf) g_object_unref (o_current->picture->pixbuf); g_free(o_current->picture->filename); g_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");*/ s_delete_object_glist (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); s_weakref_notify (o_current, o_current->weak_refs); g_free(o_current); /* assuming it is not null */ o_current=NULL; /* misc clean up */ } }