/*! \brief End the input of a line. * \par Function Description * This function ends the process of interactively adding a line to the * current sheet. * * It first erases the last temporary line displayed, calculates the * corresponding world coordinates of the two ends of the line and finally * adds a new initialized line object to the list of object of the current * sheet. * * \param [in] w_current The GSCHEM_TOPLEVEL object. * \param [in] w_x (unused) * \param [in] w_y (unused) */ void o_line_end(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *new_obj; g_assert( w_current->inside_action != 0 ); /* Don't bother.. the real object is invalidated, its in the same place */ /* o_line_invalidate_rubber (w_current); */ w_current->rubber_visible = 0; /* don't allow zero length lines */ if ( (w_current->first_wx == w_current->second_wx) && (w_current->first_wy == w_current->second_wy) ) { return; } /* create the line object and draw it */ new_obj = o_line_new (toplevel, OBJ_LINE, GRAPHIC_COLOR, w_current->first_wx, w_current->first_wy, w_current->second_wx, w_current->second_wy); s_page_append (toplevel, toplevel->page_current, new_obj); toplevel->page_current->CHANGED=1; o_undo_savestate(w_current, UNDO_ALL); }
/*! \brief Ends the process of arc input. * \par Function Description * The #o_arc_end4() function ends the process of the input of an arc. * <B>start_angle</B> and <B>sweep_angle</B> are the start and sweep angle of the * arc in degrees. The partial internal representation of the arc, i.e. * the center and the radius of the arc, are converted in world units. * A new object is created and linked to the object list. * * \param [in] w_current The GschemToplevel object. * \param [in] radius Radius of the arc * \param [in] start_angle Start of angle in degrees. * \param [in] sweep_angle Angle sweep in degrees. */ void o_arc_end4(GschemToplevel *w_current, int radius, int start_angle, int sweep_angle) { 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); TOPLEVEL *toplevel = page->toplevel; g_return_if_fail (toplevel != NULL); OBJECT *new_obj; /* create, initialize and link the new arc object */ new_obj = geda_arc_object_new (toplevel, GRAPHIC_COLOR, w_current->first_wx, w_current->first_wy, radius, start_angle, sweep_angle); s_page_append (toplevel, page, new_obj); w_current->first_wx = -1; w_current->first_wy = -1; w_current->distance = 0; /* Call add-objects-hook */ g_run_hook_object (w_current, "%add-objects-hook", new_obj); gschem_toplevel_page_content_changed (w_current, page); o_undo_savestate(w_current, page, UNDO_ALL); }
/*! \brief End the input of a box. * \par Function Description * This function ends the input of the second corner of a box. * The (<B>w_x</B>,<B>w_y</B>) point is set to be this second corner. The box is * then defined by (<B>w_current->first_wx</B>,<B>w_current->first_wy</B> and * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>. * <B>w_x</B> and <B>w_y</B> are in screen unit. * * The temporary box is erased ; a new box object is allocated, initialized * and linked to the object list ; The object is finally drawn on the * current sheet. * * \param [in] w_current The GSCHEM_TOPLEVEL object. * \param [in] w_x Current x coordinate of pointer in world units. * \param [in] w_y Current y coordinate of pointer in world units. */ void o_box_end(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *new_obj; int box_width, box_height; int box_left, box_top; g_assert( w_current->inside_action != 0 ); /* get the last coords of the pointer */ w_current->second_wx = w_x; w_current->second_wy = w_y; /* erase the temporary box */ /* o_box_invalidate_rubber (w_current); */ w_current->rubber_visible = 0; box_width = GET_BOX_WIDTH (w_current); box_height = GET_BOX_HEIGHT(w_current); box_left = GET_BOX_LEFT (w_current); box_top = GET_BOX_TOP (w_current); /* boxes with null width or height are not allowed */ if ((box_width == 0) || (box_height == 0)) { /* cancel the object creation */ w_current->first_wx = (-1); w_current->first_wy = (-1); w_current->second_wx = (-1); w_current->second_wy = (-1); return; } /* create the object */ new_obj = o_box_new (toplevel, OBJ_BOX, GRAPHIC_COLOR, box_left, box_top, box_left + box_width, box_top - box_height); s_page_append (toplevel, toplevel->page_current, new_obj); #if DEBUG printf("coords: %d %d %d %d\n", box_left, box_top, box_width, box_height); #endif w_current->first_wx = (-1); w_current->first_wy = (-1); w_current->second_wx = (-1); w_current->second_wy = (-1); /* Call add-objects-hook */ g_run_hook_object (w_current, "%add-objects-hook", new_obj); toplevel->page_current->CHANGED = 1; o_undo_savestate(w_current, UNDO_ALL); }
/*! \brief finish a bus drawing action * \par Function Description * This function finishes a net drawing action. The function draws * a bus from the point (<B>first_wx</B>,<B>first_wy</B>) to * (<B>second_wx</B>,<B>second_wy</B>). Both points are taken from * the <B>GschemToplevel</B> structure. * * The function returns TRUE if a bus object has been created and * FALSE if no bus object has been created. * * \param [in] w_current The GschemToplevel object. * \param [in] w_x (unused) * \param [in] w_y (unused) */ void o_bus_end(GschemToplevel *w_current, int w_x, int w_y) { OBJECT *new_obj; GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current); g_return_if_fail (page_view != NULL); g_assert( w_current->inside_action != 0 ); PAGE *page = gschem_page_view_get_page (page_view); g_return_if_fail (page != NULL); TOPLEVEL *toplevel = page->toplevel; g_return_if_fail (toplevel != NULL); GList *prev_conn_objects = NULL; /* erase the rubberbus */ /* o_bus_invalidate_rubber (w_current); */ w_current->rubber_visible = 0; /* don't allow zero length bus */ /* this ends the bus drawing behavior we want this? hack */ if ( (w_current->first_wx != w_current->second_wx) || (w_current->first_wy != w_current->second_wy) ) { new_obj = geda_bus_object_new (toplevel, BUS_COLOR, w_current->first_wx, w_current->first_wy, w_current->second_wx, w_current->second_wy, 0); s_page_append (toplevel, page, new_obj); /* connect the new bus to the other busses */ prev_conn_objects = s_conn_return_others (prev_conn_objects, new_obj); o_invalidate_glist (w_current, prev_conn_objects); g_list_free (prev_conn_objects); /* Call add-objects-hook */ g_run_hook_object (w_current, "%add-objects-hook", new_obj); w_current->first_wx = w_current->second_wx; w_current->first_wy = w_current->second_wy; gschem_toplevel_page_content_changed (w_current, page); o_undo_savestate(w_current, page, UNDO_ALL); } /* Don't reset w_current->inside_action here since we want to continue drawing */ }
/*! \brief Replace an OBJECT in a PAGE, in the same list position. * * \par Function Description * Removes \a object1 from \a page's linked list of objects, and puts * \a object2 in the position thus vacated. If \a object1 is not in \a * page, object2 is appended to \a page. * * \param [in] toplevel The TOPLEVEL object. * \param [in] page The PAGE to be modified. * \param [in] object1 The OBJECT being removed from the page. * \param [in] object2 The OBJECT being added to the page. */ void s_page_replace (TOPLEVEL *toplevel, PAGE *page, OBJECT *object1, OBJECT *object2) { GList *iter = g_list_find (page->_object_list, object1); /* If object1 not found, append object2 */ if (iter == NULL) { s_page_append (toplevel, page, object2); return; } pre_object_removed (toplevel, page, object1); iter->data = object2; object_added (toplevel, page, object2); }
/*! \brief End the input of a circle. * \par Function Description * This function ends the input of the radius of the circle. * The (<B>w_x</B>,<B>w_y</B>) point is taken as the other end of the radius * segment, i.e. on the circle. The distance between this point and the * center is the radius of the circle. * <B>w_x</B> and <B>w_y</B> are in world coords. * * The center has previously been input and saved as * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>). * * The temporary circle drawn during the input of the radius is erased. * A new object is allocated, initialized and linked in the object list. * This new object is finally drawn. * * \param [in] w_current The GschemToplevel object. * \param [in] w_x (unused) * \param [in] w_y (unused) */ void o_circle_end(GschemToplevel *w_current, int w_x, int w_y) { OBJECT *new_obj; GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current); g_return_if_fail (page_view != NULL); g_assert( w_current->inside_action != 0 ); PAGE *page = gschem_page_view_get_page (page_view); g_return_if_fail (page != NULL); TOPLEVEL *toplevel = page->toplevel; g_return_if_fail (toplevel != NULL); /* erase the temporary circle */ /* o_circle_invalidate_rubber (w_current); */ w_current->rubber_visible = 0; /* circle with null radius are not allowed */ if (w_current->distance == 0) { /* cancel the object creation */ return; } /* create the object */ new_obj = geda_circle_object_new (toplevel, GRAPHIC_COLOR, w_current->first_wx, w_current->first_wy, w_current->distance); s_page_append (toplevel, page, new_obj); /* Call add-objects-hook */ g_run_hook_object (w_current, "%add-objects-hook", new_obj); gschem_toplevel_page_content_changed (w_current, page); o_undo_savestate(w_current, page, UNDO_ALL); i_action_stop (w_current); }
/*! \brief End the input of a circle. * \par Function Description * This function ends the input of the second corner of a picture. * The picture is defined by (<B>w_current->first_wx</B>,<B>w_current->first_wy</B> * and (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>. * * The temporary picture frame is erased ; a new picture object is allocated, * initialized and linked to the object list ; The object is finally * drawn on the current sheet. * * \param [in] w_current The GschemToplevel object. * \param [in] w_x (unused) * \param [in] w_y (unused) */ void o_picture_end(GschemToplevel *w_current, int w_x, int w_y) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); OBJECT *new_obj; int picture_width, picture_height; int picture_left, picture_top; g_assert( w_current->inside_action != 0 ); /* erase the temporary picture */ /* o_picture_draw_rubber(w_current); */ w_current->rubber_visible = 0; picture_width = GET_PICTURE_WIDTH (w_current); picture_height = GET_PICTURE_HEIGHT(w_current); picture_left = GET_PICTURE_LEFT (w_current); picture_top = GET_PICTURE_TOP (w_current); /* pictures with null width and height are not allowed */ if ((picture_width == 0) && (picture_height == 0)) { /* cancel the object creation */ return; } /* create the object */ new_obj = o_picture_new(toplevel, NULL, 0, w_current->pixbuf_filename, OBJ_PICTURE, picture_left, picture_top, picture_left + picture_width, picture_top - picture_height, 0, FALSE, FALSE); s_page_append (toplevel, toplevel->page_current, new_obj); /* Run %add-objects-hook */ g_run_hook_object (w_current, "%add-objects-hook", new_obj); gschem_toplevel_page_content_changed (w_current, toplevel->page_current); o_undo_savestate_old(w_current, UNDO_ALL); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_pin_end(GSCHEM_TOPLEVEL *w_current, int x, int y) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *new_obj; int color; g_assert( w_current->inside_action != 0 ); if (toplevel->override_pin_color == -1) { color = PIN_COLOR; } else { color = toplevel->override_pin_color; } /* undraw rubber line */ /* o_pin_invalidate_rubber (w_current); */ w_current->rubber_visible = 0; /* don't allow zero length pins */ if ((w_current->first_wx == w_current->second_wx) && (w_current->first_wy == w_current->second_wy)) { return; } new_obj = o_pin_new(toplevel, OBJ_PIN, color, w_current->first_wx, w_current->first_wy, w_current->second_wx, w_current->second_wy, PIN_TYPE_NET, 0); s_page_append (toplevel, toplevel->page_current, new_obj); /* Call add-objects-hook */ g_run_hook_object (w_current, "%add-objects-hook", new_obj); toplevel->page_current->CHANGED=1; o_undo_savestate(w_current, UNDO_ALL); }
/*! \brief finish a net drawing action * \par Function Description * This function finishes the drawing of a net. If we have a visible * magnetic marker, we use that instead of the current cursor * position. * * The rubber nets are removed, the nets and cues are drawn and the * net is added to the TOPLEVEL structure. * * The function returns TRUE if it has drawn a net, FALSE otherwise. */ int o_net_end(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y) { TOPLEVEL *toplevel = w_current->toplevel; int color; int primary_zero_length, secondary_zero_length; int found_primary_connection = FALSE; int save_wx, save_wy; GList *prev_conn_objects; OBJECT *new_net = NULL; /* Save a list of added objects to run the %add-objects-hook later */ GList *added_objects = NULL; g_assert( w_current->inside_action != 0 ); o_net_invalidate_rubber (w_current); if (w_current->magnetic_wx != -1 && w_current->magnetic_wy != -1) o_net_finishmagnetic(w_current); w_current->rubber_visible = 0; /* See if either of the nets are zero length. We'll only add */ /* the non-zero ones */ primary_zero_length = (w_current->first_wx == w_current->second_wx) && (w_current->first_wy == w_current->second_wy); secondary_zero_length = (w_current->second_wx == w_current->third_wx) && (w_current->second_wy == w_current->third_wy); /* If both nets are zero length... */ /* this ends the net drawing behavior */ if ( primary_zero_length && secondary_zero_length ) { return FALSE; } save_wx = w_current->third_wx; save_wy = w_current->third_wy; if (toplevel->override_net_color == -1) { color = NET_COLOR; } else { color = toplevel->override_net_color; } if (w_current->third_wx != snap_grid (w_current, w_current->third_wx) || w_current->third_wy != snap_grid (w_current, w_current->third_wy)) s_log_message(_("Warning: Ending net at off grid coordinate\n")); if (!primary_zero_length ) { /* create primary net */ new_net = o_net_new(toplevel, OBJ_NET, color, w_current->first_wx, w_current->first_wy, w_current->second_wx, w_current->second_wy); s_page_append (toplevel, toplevel->page_current, new_net); added_objects = g_list_prepend (added_objects, new_net); /* conn stuff */ /* LEAK CHECK 1 */ prev_conn_objects = s_conn_return_others (NULL, new_net); o_net_add_busrippers (w_current, new_net, prev_conn_objects); g_list_free (prev_conn_objects); #if DEBUG printf("primary:\n"); s_conn_print(new_net->conn_list); #endif /* Go off and search for valid connection on this newly created net */ found_primary_connection = s_conn_net_search(new_net, 1, new_net->conn_list); if (found_primary_connection) { /* if a net connection is found, reset start point of next net */ save_wx = w_current->second_wx; save_wy = w_current->second_wy; } } /* If the second net is not zero length, add it as well */ /* Also, a valid net connection from the primary net was not found */ if (!secondary_zero_length && !found_primary_connection) { /* Add secondary net */ new_net = o_net_new(toplevel, OBJ_NET, color, w_current->second_wx, w_current->second_wy, w_current->third_wx, w_current->third_wy); s_page_append (toplevel, toplevel->page_current, new_net); added_objects = g_list_prepend (added_objects, new_net); /* conn stuff */ /* LEAK CHECK 2 */ prev_conn_objects = s_conn_return_others (NULL, new_net); o_net_add_busrippers (w_current, new_net, prev_conn_objects); g_list_free (prev_conn_objects); #if DEBUG s_conn_print(new_net->conn_list); #endif } /* Call add-objects-hook */ if (added_objects != NULL) { g_run_hook_object_list ("%add-objects-hook", added_objects); g_list_free (added_objects); } toplevel->page_current->CHANGED = 1; w_current->first_wx = save_wx; w_current->first_wy = save_wy; o_undo_savestate(w_current, UNDO_ALL); return (TRUE); }
/*! \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); }
/*! \brief finish a net drawing action * \par Function Description * This function finishes the drawing of a net. If we have a visible * magnetic marker, we use that instead of the current cursor * position. * * The rubber nets are removed, the nets and cues are drawn and the * net is added to the TOPLEVEL structure. * * The function returns TRUE if it has drawn a net, FALSE otherwise. */ void o_net_end(GschemToplevel *w_current, int w_x, int w_y) { int primary_zero_length, secondary_zero_length; int found_primary_connection = FALSE; int save_wx, save_wy; GList *prev_conn_objects; OBJECT *new_net = NULL; /* Save a list of added objects to run the %add-objects-hook later */ GList *added_objects = NULL; g_assert( w_current->inside_action != 0 ); 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); o_net_invalidate_rubber (w_current); if (w_current->magnetic_wx != -1 && w_current->magnetic_wy != -1) o_net_finishmagnetic(w_current); w_current->rubber_visible = 0; /* See if either of the nets are zero length. We'll only add */ /* the non-zero ones */ primary_zero_length = (w_current->first_wx == w_current->second_wx) && (w_current->first_wy == w_current->second_wy); secondary_zero_length = (w_current->second_wx == w_current->third_wx) && (w_current->second_wy == w_current->third_wy); /* If both nets are zero length... */ /* this ends the net drawing behavior */ if ( primary_zero_length && secondary_zero_length ) { o_net_reset(w_current); return; } save_wx = w_current->third_wx; save_wy = w_current->third_wy; if (w_current->third_wx != snap_grid (w_current, w_current->third_wx) || w_current->third_wy != snap_grid (w_current, w_current->third_wy)) s_log_message(_("Warning: Ending net at off grid coordinate\n")); if (!primary_zero_length ) { /* create primary net */ new_net = o_net_new(page->toplevel, OBJ_NET, NET_COLOR, w_current->first_wx, w_current->first_wy, w_current->second_wx, w_current->second_wy); s_page_append (page->toplevel, page, new_net); added_objects = g_list_prepend (added_objects, new_net); /* conn stuff */ /* LEAK CHECK 1 */ prev_conn_objects = s_conn_return_others (NULL, new_net); o_net_add_busrippers (w_current, new_net, prev_conn_objects); g_list_free (prev_conn_objects); #if DEBUG printf("primary:\n"); s_conn_print(new_net->conn_list); #endif /* Go off and search for valid connection on this newly created net */ found_primary_connection = s_conn_net_search(new_net, 1, new_net->conn_list); if (found_primary_connection) { /* if a net connection is found, reset start point of next net */ save_wx = w_current->second_wx; save_wy = w_current->second_wy; } } /* If the second net is not zero length, add it as well */ /* Also, a valid net connection from the primary net was not found */ if (!secondary_zero_length && !found_primary_connection) { /* Add secondary net */ new_net = o_net_new(page->toplevel, OBJ_NET, NET_COLOR, w_current->second_wx, w_current->second_wy, w_current->third_wx, w_current->third_wy); s_page_append (page->toplevel, page, new_net); added_objects = g_list_prepend (added_objects, new_net); /* conn stuff */ /* LEAK CHECK 2 */ prev_conn_objects = s_conn_return_others (NULL, new_net); o_net_add_busrippers (w_current, new_net, prev_conn_objects); g_list_free (prev_conn_objects); #if DEBUG s_conn_print(new_net->conn_list); #endif } /* Call add-objects-hook */ if (added_objects != NULL) { g_run_hook_object_list (w_current, "%add-objects-hook", added_objects); g_list_free (added_objects); } w_current->first_wx = save_wx; w_current->first_wy = save_wy; gschem_toplevel_page_content_changed (w_current, page); o_undo_savestate_old(w_current, UNDO_ALL); /* Continue net drawing */ o_net_start(w_current, w_current->first_wx, w_current->first_wy); }
/*! \brief Updates the preview widget. * \par Function Description * This function updates the preview: if the preview is active and a * filename has been given, it opens the file and displays * it. Otherwise it displays a blank page. * * \param [in] preview The preview widget. */ static void preview_update (Preview *preview) { int left, top, right, bottom; int width, height; GError * err = NULL; GschemPageView *preview_view = GSCHEM_PAGE_VIEW (preview); g_return_if_fail (preview_view != NULL); PAGE *preview_page = gschem_page_view_get_page (preview_view); if (preview_page == NULL) { return; } TOPLEVEL *preview_toplevel = preview_page->toplevel; /* delete old preview */ s_page_delete_objects (preview_toplevel, preview_page); if (preview->active) { g_assert ((preview->filename == NULL) || (preview->buffer == NULL)); if (preview->filename != NULL) { /* open up file in current page */ f_open_flags (preview_toplevel, preview_page, preview->filename, F_OPEN_RC | F_OPEN_RESTORE_CWD, NULL); /* test value returned by f_open... - Fix me */ /* we should display something if there an error occured - Fix me */ } if (preview->buffer != NULL) { /* Load the data buffer */ GList * objects = o_read_buffer (preview_toplevel, NULL, preview->buffer, -1, _("Preview Buffer"), &err); if (err == NULL) { s_page_append_list (preview_toplevel, preview_page, objects); } else { s_page_append (preview_toplevel, preview_page, o_text_new(preview_toplevel, OBJ_TEXT, 2, 100, 100, LOWER_MIDDLE, 0, err->message, 10, VISIBLE, SHOW_NAME_VALUE)); g_error_free(err); } } } if (world_get_object_glist_bounds (preview_toplevel, s_page_objects (preview_page), &left, &top, &right, &bottom)) { /* Clamp the canvas size to the extents of the page being previewed */ width = right - left; height = bottom - top; GschemPageGeometry *geometry = gschem_page_view_get_page_geometry (preview_view); geometry->world_left = left - ((double)width * OVER_ZOOM_FACTOR); geometry->world_right = right + ((double)width * OVER_ZOOM_FACTOR); geometry->world_top = top - ((double)height * OVER_ZOOM_FACTOR); geometry->world_bottom = bottom + ((double)height * OVER_ZOOM_FACTOR); } /* display current page (possibly empty) */ gschem_page_view_zoom_extents (preview_view, NULL); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_slot_end(GSCHEM_TOPLEVEL *w_current, const char *string, int len) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *new_obj; OBJECT *object; OBJECT *temp; char *slot_value; char *numslots_value; OBJECT *slot_text_object; char *value = NULL; int numslots; int new_slot_number; int status; status = o_attrib_get_name_value(string, NULL, &value); if (!status) { s_log_message(_("Slot attribute malformed\n")); return; } object = o_select_return_first_object(w_current); /* get the parent object if the selection is only a text object */ if (object != NULL && object->type == OBJ_TEXT) { if (object->attached_to != NULL) { object = object->attached_to; } } /* now find the slot attribute on the outside first */ if (object != NULL) { numslots_value = o_attrib_search_numslots(object, NULL); if (!numslots_value) { s_log_message(_("numslots attribute missing\n")); s_log_message( _("Slotting not allowed for this component\n")); g_free(value); return; } numslots = atoi(numslots_value); g_free(numslots_value); new_slot_number = atoi(value); #if DEBUG printf("numslots = %d\n", numslots); #endif if (new_slot_number > numslots || new_slot_number <=0 ) { s_log_message(_("New slot number out of range\n")); g_free(value); return; } /* first see if slot attribute already exists outside * complex */ slot_value = o_attrib_search_slot(object, &slot_text_object); if (slot_value) { o_text_set_string (toplevel, slot_text_object, string); temp = slot_text_object; if (temp->visibility == VISIBLE || (temp->visibility == INVISIBLE && toplevel->show_hidden_text)) { o_invalidate (w_current,temp); } o_text_recreate(toplevel, temp); /* this doesn't deal with the selection list * item */ if (temp->visibility == VISIBLE || (temp->visibility == INVISIBLE && toplevel->show_hidden_text)) { o_invalidate (w_current,temp); } g_free(slot_value); } else { /* here you need to do the add the slot attribute since it doesn't exist */ new_obj = o_text_new (toplevel, OBJ_TEXT, ATTRIBUTE_COLOR, object->complex->x, object->complex->y, LOWER_LEFT, 0, /* zero is angle */ string, 10, INVISIBLE, SHOW_NAME_VALUE); s_page_append (toplevel->page_current, new_obj); /* manually attach attribute */ o_attrib_attach (toplevel, new_obj, object, FALSE); slot_text_object = new_obj; } o_invalidate (w_current, object); o_attrib_slot_update(toplevel, object); o_invalidate (w_current,object); toplevel->page_current->CHANGED = 1; g_free(value); } else { fprintf(stderr, _("uggg! you tried to slot edit something that doesn't exist!\n")); g_free(value); exit(-1); } }
/*! \brief End the input of a path. * \par Function Description * This function ends the process of interactively adding a path to the * current sheet. * * It first erases the last temporary path displayed, calculates the * corresponding world coordinates of the two ends of the path and finally * adds a new initialized path object to the list of object of the current * sheet. * * \param [in] w_current The GschemToplevel object. * \param [in] w_x (unused) * \param [in] w_y (unused) */ gboolean o_path_end(GschemToplevel *w_current, int w_x, int w_y) { GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current); TOPLEVEL *toplevel = gschem_page_view_get_toplevel (page_view); PAGE *page = gschem_page_view_get_page (page_view); gboolean close_path, end_path, start_path; PATH *p; PATH_SECTION *section, *prev_section; int x1, y1, x2, y2; g_assert (w_current); g_assert (w_current->toplevel); g_assert (w_current->temp_path != NULL); g_assert (w_current->temp_path->sections != NULL); g_assert (toplevel != NULL); g_assert (page != NULL); o_path_invalidate_rubber (w_current); x1 = w_current->first_wx; y1 = w_current->first_wy; x2 = w_current->second_wx; y2 = w_current->second_wy; p = w_current->temp_path; /* Check whether the section that's being added is the initial * MOVETO. This is detected if the path is currently empty. */ start_path = (p->num_sections == 0); prev_section = start_path ? NULL : &p->sections[p->num_sections - 1]; /* Check whether the section that's being added closes the path. * This is detected if the location of the node is the same as the * location of the starting node, and there is at least one section * in the path in addition to the initial MOVETO section. */ section = &p->sections[0]; close_path = (!start_path && x1 == section->x3 && y1 == section->y3); /* Check whether the section that's being added ends the path. This * is detected if the location of the node is the same as the * location of the previous node. */ end_path = (!start_path && x1 == prev_section->x3 && y1 == prev_section->y3); /* Add predicted next sections */ path_next_sections (w_current); if (end_path || close_path) { /* Add object to page and clean up path drawing state */ OBJECT *obj = o_path_new_take_path (toplevel, OBJ_PATH, GRAPHIC_COLOR, p); w_current->temp_path = NULL; w_current->first_wx = -1; w_current->first_wy = -1; w_current->second_wx = -1; w_current->second_wy = -1; w_current->third_wx = -1; w_current->third_wy = -1; s_page_append (toplevel, page, obj); g_run_hook_object (w_current, "%add-objects-hook", obj); gschem_toplevel_page_content_changed (w_current, page); o_undo_savestate (w_current, page, UNDO_ALL); w_current->rubber_visible = FALSE; return FALSE; } else { /* Leave state as it is and continue path drawing... */ /* Save the control point coordinates for the next section */ w_current->third_wx = x2; w_current->third_wy = y2; return TRUE; } }
/*! \brief End placement action * * \par Function Description * This function finishes the current placement action by adding * objects to the current page at the given new world coordinates * and redrawing them on the canvas. It also saves the current * state in the undo list and updates the menus. * * If \a continue_placing is TRUE, a copy of the placement list * is saved to start a new place action. * * \param [in] w_current GschemToplevel which we're drawing for. * \param [in] w_x The current world X coordinate. * \param [in] w_y The current world Y coordinate. * \param [in] hook_name The hook to run after adding the objects. */ void o_place_end (GschemToplevel *w_current, int w_x, int w_y, int continue_placing, const char* hook_name) { int w_diff_x, w_diff_y; OBJECT *o_current; GList *temp_dest_list = NULL; GList *connected_objects = NULL; GList *iter; g_return_if_fail (w_current != NULL); g_assert (w_current->inside_action != 0); 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); /* erase old image */ /* o_place_invalidate_rubber (w_current, FALSE); */ w_current->rubber_visible = 0; /* Calc final object positions */ w_current->second_wx = w_x; w_current->second_wy = w_y; w_diff_x = w_current->second_wx - w_current->first_wx; w_diff_y = w_current->second_wy - w_current->first_wy; if (continue_placing) { /* Make a copy of the place list if we want to keep it afterwards */ temp_dest_list = o_glist_copy_all (page->toplevel, page->place_list, temp_dest_list); } else { /* Otherwise just take it */ temp_dest_list = page->place_list; page->place_list = NULL; } geda_object_list_translate (temp_dest_list, w_diff_x, w_diff_y); /* Attach each item back onto the page's object list. Update object * connectivity and add the new objects to the selection list.*/ for (iter = temp_dest_list; iter != NULL; iter = g_list_next (iter)) { o_current = (OBJECT*) iter->data; s_page_append (page->toplevel, page, o_current); /* Update object connectivity */ s_conn_update_object (page, o_current); connected_objects = s_conn_return_others (connected_objects, o_current); } if (hook_name != NULL) { g_run_hook_object_list (w_current, hook_name, temp_dest_list); } o_invalidate_glist (w_current, connected_objects); g_list_free (connected_objects); connected_objects = NULL; gschem_toplevel_page_content_changed (w_current, page); o_invalidate_glist (w_current, temp_dest_list); /* only redraw new objects */ g_list_free (temp_dest_list); o_undo_savestate_old (w_current, UNDO_ALL); i_update_menus (w_current); if (!continue_placing) { i_set_state(w_current, SELECT); i_action_stop (w_current); } }
/* 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; }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_slot_end(GSCHEM_TOPLEVEL *w_current, OBJECT *object, const char *string) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *new_obj; char *slot_value; char *numslots_value; OBJECT *o_slot; char *value = NULL; int numslots; int new_slot_number; int status; g_return_if_fail (object != NULL); status = o_attrib_string_get_name_value (string, NULL, &value); if (!status) { s_log_message (_("Slot attribute malformed\n")); return; } numslots_value = o_attrib_search_object_attribs_by_name (object, "numslots", 0); if (!numslots_value) { s_log_message (_("numslots attribute missing\n")); s_log_message (_("Slotting not allowed for this component\n")); g_free (value); return; } numslots = atoi (numslots_value); g_free (numslots_value); new_slot_number = atoi (value); #if DEBUG printf ("numslots = %d\n", numslots); #endif if (new_slot_number > numslots || new_slot_number <=0 ) { s_log_message (_("New slot number out of range\n")); g_free (value); return; } /* first see if slot attribute already exists outside * complex */ slot_value = s_slot_search_slot (object, &o_slot); g_free (slot_value); if (o_slot != NULL && !o_attrib_is_inherited (o_slot)) { o_text_set_string (toplevel, o_slot, string); } else { /* here you need to do the add the slot attribute since it doesn't exist */ new_obj = o_text_new (toplevel, OBJ_TEXT, ATTRIBUTE_COLOR, object->complex->x, object->complex->y, LOWER_LEFT, 0, /* zero is angle */ string, 10, INVISIBLE, SHOW_NAME_VALUE); s_page_append (toplevel, toplevel->page_current, new_obj); /* manually attach attribute */ o_attrib_attach (toplevel, new_obj, object, FALSE); } s_slot_update_object (toplevel, object); toplevel->page_current->CHANGED = 1; g_free (value); }
/*! \brief Add a component to the page. * \par Function Description * Adds a component <B>scm_comp_name</B> to the schematic, at * position (<B>scm_x</B>, <B>scm_y</B>), with some properties set by * the parameters: * \param [in] scm_x Coordinate X of the symbol. * \param [in] scm_y Coordinate Y of the symbol. * \param [in] angle Angle of rotation of the symbol. * \param [in] selectable True if the symbol is selectable, false otherwise. * \param [in] mirror True if the symbol is mirrored, false otherwise. * If scm_comp_name is a scheme empty list, SCM_BOOL_F, or an empty * string (""), then g_add_component returns SCM_BOOL_F without writing * to the log. * \return TRUE if the component was added, FALSE otherwise. * */ SCM g_add_component(SCM page_smob, SCM scm_comp_name, SCM scm_x, SCM scm_y, SCM scm_angle, SCM scm_selectable, SCM scm_mirror) { TOPLEVEL *toplevel; PAGE *page; gboolean selectable, mirror; gchar *comp_name; int x, y, angle; OBJECT *new_obj; const CLibSymbol *clib; /* Return if scm_comp_name is NULL (an empty list) or scheme's FALSE */ if (SCM_NULLP(scm_comp_name) || (SCM_BOOLP(scm_comp_name) && !(SCM_NFALSEP(scm_comp_name))) ) { return SCM_BOOL_F; } /* Get toplevel and the page */ SCM_ASSERT (g_get_data_from_page_smob (page_smob, &toplevel, &page), page_smob, SCM_ARG1, "add-component-at-xy"); /* Check the arguments */ SCM_ASSERT (scm_is_string(scm_comp_name), scm_comp_name, SCM_ARG2, "add-component-at-xy"); SCM_ASSERT ( scm_is_integer(scm_x), scm_x, SCM_ARG3, "add-component-at-xy"); SCM_ASSERT ( scm_is_integer(scm_y), scm_y, SCM_ARG4, "add-component-at-xy"); SCM_ASSERT ( scm_is_integer(scm_angle), scm_angle, SCM_ARG5, "add-component-at-xy"); SCM_ASSERT ( scm_boolean_p(scm_selectable), scm_selectable, SCM_ARG6, "add-component-at-xy"); SCM_ASSERT ( scm_boolean_p(scm_mirror), scm_mirror, SCM_ARG7, "add-component-at-xy"); /* Get the parameters */ comp_name = SCM_STRING_CHARS(scm_comp_name); x = scm_to_int(scm_y); y = scm_to_int(scm_y); angle = scm_to_int(scm_angle); selectable = SCM_NFALSEP(scm_selectable); mirror = SCM_NFALSEP(scm_mirror); SCM_ASSERT (comp_name, scm_comp_name, SCM_ARG2, "add-component-at-xy"); if (strcmp(comp_name, "") == 0) { return SCM_BOOL_F; } clib = s_clib_get_symbol_by_name (comp_name); new_obj = o_complex_new (toplevel, 'C', DEFAULT_COLOR, x, y, angle, mirror, clib, comp_name, selectable); s_page_append_list (page, o_complex_promote_attribs (toplevel, new_obj)); s_page_append (page, new_obj); /* * For now, do not redraw the newly added complex, since this might cause * flicker if you are zoom/panning right after this function executes */ #if 0 /* Now the new component should be added to the object's list and drawn in the screen */ o_invalidate (toplevel, new_object); #endif return SCM_BOOL_T; }
/*! \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; }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_move_check_endpoint(GschemToplevel *w_current, OBJECT * object) { GList *cl_current; CONN *c_current; OBJECT *other; int whichone; 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); if (!object) return; if (object->type != OBJ_NET && object->type != OBJ_PIN && object->type != OBJ_BUS) { fprintf(stderr, _("Got a non line object in o_move_check_endpoint\n")); return; } for (cl_current = object->conn_list; cl_current != NULL; cl_current = g_list_next(cl_current)) { c_current = (CONN *) cl_current->data; other = c_current->other_object; if (other == NULL) continue; /* really make sure that the object is not selected */ if (other->selected) continue; /* Catch pins, whos parent object is selected. */ if (other->parent != NULL && other->parent->selected) continue; if (c_current->type != CONN_ENDPOINT && (c_current->type != CONN_MIDPOINT || c_current->other_whichone == -1)) continue; if (/* (net)pin to (net)pin contact */ (object->type == OBJ_PIN && object->pin_type == PIN_TYPE_NET && other->type == OBJ_PIN && other->pin_type == PIN_TYPE_NET)) { /* net to (net)pin contact */ /* (object->type == OBJ_NET && other->type == OBJ_PIN && other->pin_type == PIN_TYPE_NET) */ OBJECT *new_net; /* other object is a pin, insert a net */ new_net = o_net_new (page->toplevel, OBJ_NET, NET_COLOR, c_current->x, c_current->y, c_current->x, c_current->y); s_page_append (page->toplevel, page, new_net); /* This new net object is only picked up for stretching later, * somewhat of a kludge. If the move operation is cancelled, these * new 0 length nets are removed by the "undo" operation invoked. */ } /* Only attempt to stretch nets and buses */ if (other->type != OBJ_NET && other->type != OBJ_BUS) continue; whichone = o_move_return_whichone (other, c_current->x, c_current->y); #if DEBUG printf ("FOUND: %s type: %d, whichone: %d, x,y: %d %d\n", other->name, c_current->type, whichone, c_current->x, c_current->y); printf("other x,y: %d %d\n", c_current->x, c_current->y); printf("type: %d return: %d real: [ %d %d ]\n", c_current->type, whichone, c_current->whichone, c_current->other_whichone); #endif if (whichone >= 0 && whichone <= 1) { w_current->stretch_list = s_stretch_add (w_current->stretch_list, other, whichone); } } }
/*! \brief finish a net drawing action * \par Function Description * This function finishes the drawing of a net. If we have a visible * magnetic marker, we use that instead of the current cursor * position. * * The rubber nets are removed, the nets and cues are drawn and the * net is added to the TOPLEVEL structure. * * The function returns TRUE if it has drawn a net, FALSE otherwise. */ int o_net_end(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y) { TOPLEVEL *toplevel = w_current->toplevel; int color; int primary_zero_length, secondary_zero_length; int found_primary_connection = FALSE; int save_wx, save_wy; GList *prev_conn_objects = NULL; OBJECT *new_net = NULL; g_assert( w_current->inside_action != 0 ); o_net_invalidate_rubber (w_current); if (w_current->magnetic_wx != -1 && w_current->magnetic_wy != -1) o_net_finishmagnetic(w_current); w_current->rubber_visible = 0; /* See if either of the nets are zero length. We'll only add */ /* the non-zero ones */ primary_zero_length = (w_current->first_wx == w_current->second_wx) && (w_current->first_wy == w_current->second_wy); secondary_zero_length = (w_current->second_wx == w_current->third_wx) && (w_current->second_wy == w_current->third_wy); /* If both nets are zero length... */ /* this ends the net drawing behavior */ if ( primary_zero_length && secondary_zero_length ) { return FALSE; } save_wx = w_current->third_wx; save_wy = w_current->third_wy; if (toplevel->override_net_color == -1) { color = NET_COLOR; } else { color = toplevel->override_net_color; } if (w_current->third_wx != snap_grid (w_current, w_current->third_wx) || w_current->third_wy != snap_grid (w_current, w_current->third_wy)) s_log_message(_("Warning: Ending net at off grid coordinate\n")); if (!primary_zero_length ) { /* create primary net */ new_net = o_net_new(toplevel, OBJ_NET, color, w_current->first_wx, w_current->first_wy, w_current->second_wx, w_current->second_wy); s_page_append (toplevel->page_current, new_net); /* conn stuff */ /* LEAK CHECK 1 */ prev_conn_objects = s_conn_return_others (prev_conn_objects, new_net); if (o_net_add_busrippers (w_current, new_net, prev_conn_objects)) { g_list_free (prev_conn_objects); prev_conn_objects = NULL; prev_conn_objects = s_conn_return_others (prev_conn_objects, new_net); } #if DEBUG printf("primary:\n"); s_conn_print(new_net->conn_list); #endif o_invalidate (w_current, new_net); o_invalidate_glist (w_current, prev_conn_objects); g_list_free (prev_conn_objects); prev_conn_objects = NULL; /* Go off and search for valid connection on this newly created net */ found_primary_connection = s_conn_net_search(new_net, 1, new_net->conn_list); if (found_primary_connection) { /* if a net connection is found, reset start point of next net */ save_wx = w_current->second_wx; save_wy = w_current->second_wy; } /* you don't want to consolidate nets which are drawn non-ortho */ if (toplevel->net_consolidate == TRUE && !w_current->CONTROLKEY) { /* CAUTION: Object list will change when nets are consolidated, don't * keep pointers to other objects than new_net after this. */ o_net_consolidate_segments(toplevel, new_net); } } /* If the second net is not zero length, add it as well */ /* Also, a valid net connection from the primary net was not found */ if (!secondary_zero_length && !found_primary_connection) { /* Add secondary net */ new_net = o_net_new(toplevel, OBJ_NET, color, w_current->second_wx, w_current->second_wy, w_current->third_wx, w_current->third_wy); s_page_append (toplevel->page_current, new_net); /* conn stuff */ /* LEAK CHECK 2 */ prev_conn_objects = s_conn_return_others (prev_conn_objects, new_net); if (o_net_add_busrippers (w_current, new_net, prev_conn_objects)) { g_list_free (prev_conn_objects); prev_conn_objects = NULL; prev_conn_objects = s_conn_return_others (prev_conn_objects, new_net); } #if DEBUG s_conn_print(new_net->conn_list); #endif o_invalidate (w_current, new_net); o_invalidate_glist (w_current, prev_conn_objects); g_list_free (prev_conn_objects); prev_conn_objects = NULL; /* you don't want to consolidate nets which are drawn non-ortho */ if (toplevel->net_consolidate == TRUE && !w_current->CONTROLKEY) { /* CAUTION: Object list will change when nets are consolidated, don't * keep pointers to other objects than new_net after this. */ o_net_consolidate_segments(toplevel, new_net); } } toplevel->page_current->CHANGED = 1; w_current->first_wx = save_wx; w_current->first_wy = save_wy; o_undo_savestate(w_current, UNDO_ALL); return (TRUE); }
/*! \brief End the input of a box. * \par Function Description * This function ends the input of the second corner of a box. * The (<B>w_x</B>,<B>w_y</B>) point is set to be this second corner. The box is * then defined by (<B>w_current->first_wx</B>,<B>w_current->first_wy</B> and * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>. * <B>w_x</B> and <B>w_y</B> are in screen unit. * * The temporary box is erased ; a new box object is allocated, initialized * and linked to the object list ; The object is finally drawn on the * current sheet. * * \param [in] w_current The GschemToplevel object. * \param [in] w_x Current x coordinate of pointer in world units. * \param [in] w_y Current y coordinate of pointer in world units. */ void o_box_end(GschemToplevel *w_current, int w_x, int w_y) { OBJECT *new_obj; GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current); g_return_if_fail (page_view != NULL); g_assert( w_current->inside_action != 0 ); PAGE *page = gschem_page_view_get_page (page_view); g_return_if_fail (page != NULL); TOPLEVEL *toplevel = page->toplevel; g_return_if_fail (toplevel != NULL); int box_width, box_height; int box_left, box_top; /* get the last coords of the pointer */ w_current->second_wx = w_x; w_current->second_wy = w_y; /* erase the temporary box */ /* o_box_invalidate_rubber (w_current); */ w_current->rubber_visible = 0; box_width = GET_BOX_WIDTH (w_current); box_height = GET_BOX_HEIGHT(w_current); box_left = GET_BOX_LEFT (w_current); box_top = GET_BOX_TOP (w_current); /* boxes with null width or height are not allowed */ if ((box_width == 0) || (box_height == 0)) { /* cancel the object creation */ w_current->first_wx = (-1); w_current->first_wy = (-1); w_current->second_wx = (-1); w_current->second_wy = (-1); } else { /* create the object */ new_obj = geda_box_object_new (toplevel, OBJ_BOX, GRAPHIC_COLOR, box_left, box_top, box_left + box_width, box_top - box_height); s_page_append (toplevel, page, new_obj); #if DEBUG printf("coords: %d %d %d %d\n", box_left, box_top, box_width, box_height); #endif w_current->first_wx = (-1); w_current->first_wy = (-1); w_current->second_wx = (-1); w_current->second_wy = (-1); /* Call add-objects-hook */ g_run_hook_object (w_current, "%add-objects-hook", new_obj); gschem_toplevel_page_content_changed (w_current, page); o_undo_savestate(w_current, page, UNDO_ALL); } i_action_stop (w_current); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_place_end (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y, int continue_placing, GList **ret_new_objects, const char* hook_name) { TOPLEVEL *toplevel = w_current->toplevel; int w_diff_x, w_diff_y; OBJECT *o_current; PAGE *p_current; GList *temp_dest_list = NULL; GList *connected_objects = NULL; GList *iter; /* erase old image */ /* o_place_invaidate_rubber (w_current, FALSE); */ w_current->rubber_visible = 0; /* Calc final object positions */ w_current->second_wx = w_x; w_current->second_wy = w_y; w_diff_x = w_current->second_wx - w_current->first_wx; w_diff_y = w_current->second_wy - w_current->first_wy; if (continue_placing) { /* Make a copy of the place list if we want to keep it afterwards */ temp_dest_list = o_glist_copy_all (toplevel, toplevel->page_current->place_list, temp_dest_list); } else { /* Otherwise just take it */ temp_dest_list = toplevel->page_current->place_list; toplevel->page_current->place_list = NULL; } if (ret_new_objects != NULL) { *ret_new_objects = g_list_copy (temp_dest_list); } o_glist_translate_world(toplevel, w_diff_x, w_diff_y, temp_dest_list); /* Attach each item back onto the page's object list. Update object * connectivity and add the new objects to the selection list.*/ p_current = toplevel->page_current; for (iter = temp_dest_list; iter != NULL; iter = g_list_next (iter)) { o_current = iter->data; s_page_append (toplevel, p_current, o_current); /* Update object connectivity */ s_conn_update_object (toplevel, o_current); connected_objects = s_conn_return_others (connected_objects, o_current); } if (hook_name != NULL) { g_run_hook_object_list (hook_name, temp_dest_list); } o_invalidate_glist (w_current, connected_objects); g_list_free (connected_objects); connected_objects = NULL; toplevel->page_current->CHANGED = 1; o_invalidate_glist (w_current, temp_dest_list); /* only redraw new objects */ g_list_free (temp_dest_list); o_undo_savestate (w_current, UNDO_ALL); i_update_menus (w_current); }