/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_move_end_lowlevel (GschemToplevel *w_current, OBJECT *object, int diff_x, int diff_y) { GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current); g_return_if_fail (page_view != NULL); PAGE *page = gschem_page_view_get_page (page_view); g_return_if_fail (page != NULL); switch (object->type) { case (OBJ_NET): case (OBJ_BUS): case (OBJ_PIN): s_conn_remove_object_connections (page->toplevel, object); o_translate_world (page->toplevel, diff_x, diff_y, object); s_conn_update_object (page, object); break; default: o_translate_world (page->toplevel, diff_x, diff_y, object); break; } }
/*! \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 GschemToplevel 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(GschemToplevel *w_current, int centerx, int centery, int angle, GList *list) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); OBJECT *o_current; GList *o_iter; /* this is okay if you just hit rotate and have nothing selected */ if (list == NULL) { i_action_stop (w_current); 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_connections (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 (o_current->page, o_current); } o_invalidate_glist (w_current, list); /* Run rotate-objects-hook */ g_run_hook_object_list (w_current, "%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 */ gschem_toplevel_page_content_changed (w_current, toplevel->page_current); if (!w_current->inside_action) { o_undo_savestate_old(w_current, UNDO_ALL); } if (w_current->event_state == ROTATEMODE) { i_set_state(w_current, SELECT); } }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_mirror_world_update(GschemToplevel *w_current, int centerx, int centery, GList *list) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); OBJECT *o_current; GList *o_iter; if (list == NULL) { i_action_stop (w_current); 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_connections (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 (o_current->page, o_current); } o_invalidate_glist (w_current, list); /* Run mirror-objects-hook */ g_run_hook_object_list (w_current, "%mirror-objects-hook", list); gschem_toplevel_page_content_changed (w_current, toplevel->page_current); o_undo_savestate_old(w_current, UNDO_ALL); if (w_current->event_state == MIRRORMODE) { i_set_state(w_current, SELECT); } }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_move_end_rubberband (GschemToplevel *w_current, int w_dx, int w_dy, GList** objects) { GList *s_iter, *s_iter_next; GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current); g_return_if_fail (page_view != NULL); PAGE *page = gschem_page_view_get_page (page_view); g_return_if_fail (page != NULL); for (s_iter = w_current->stretch_list; s_iter != NULL; s_iter = s_iter_next) { STRETCH *s_current = s_iter->data; OBJECT *object = s_current->object; int whichone = s_current->whichone; /* Store this now, since we may delete the current item */ s_iter_next = g_list_next (s_iter); if (object->type == OBJ_NET || object->type == OBJ_BUS) { /* remove the object's connections */ s_conn_remove_object_connections (page->toplevel, object); object->line->x[whichone] += w_dx; object->line->y[whichone] += w_dy; if (o_move_zero_length (object)) { w_current->stretch_list = s_stretch_remove (w_current->stretch_list, object); o_delete (w_current, object); continue; } object->w_bounds_valid_for = NULL; s_conn_update_object (page, object); *objects = g_list_append (*objects, object); } } }
/* 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(GschemToplevel *w_current, OBJECT *net_obj, GList *prev_conn_objects) { OBJECT *new_obj; 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; GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current); g_return_val_if_fail (page_view != NULL, FALSE); PAGE *page = gschem_page_view_get_page (page_view); g_return_val_if_fail (page != NULL, FALSE); length = o_line_length(net_obj); if (!prev_conn_objects) { return(FALSE); } if (length <= ripper_size) { return(FALSE); } /* 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; net_obj->w_bounds_valid_for = NULL; 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; net_obj->w_bounds_valid_for = NULL; 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; net_obj->w_bounds_valid_for = NULL; 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; net_obj->w_bounds_valid_for = NULL; 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_connections (page->toplevel, net_obj); if (w_current->bus_ripper_type == COMP_BUS_RIPPER) { GList *symlist = s_clib_search (page->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(page->toplevel, OBJ_NET, NET_COLOR, rippers[i].x[0], rippers[i].y[0], rippers[i].x[1], rippers[i].y[1]); s_page_append (page->toplevel, page, new_obj); } else { if (rippersym != NULL) { new_obj = o_complex_new (page->toplevel, OBJ_COMPLEX, DEFAULT_COLOR, rippers[i].x[0], rippers[i].y[0], complex_angle, 0, rippersym, page->toplevel->bus_ripper_symname, 1); s_page_append_list (page->toplevel, page, o_complex_promote_attribs (page->toplevel, new_obj)); s_page_append (page->toplevel, page, new_obj); } else { s_log_message(_("Bus ripper symbol [%s] was not found in any component library\n"), page->toplevel->bus_ripper_symname); } } } s_conn_update_object (page, net_obj); return(TRUE); } return(FALSE); }
/*! \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 */ } }