/*! \brief Recalculate position of a list (GList) of objects. * \par Function Description * This function will take a list (GList) of objects and recalculate their * positions on the screen. * * \param [in] toplevel The TOPLEVEL object. * \param [in,out] object_glist OBJECT list to recalculate. * */ void o_recalc_object_glist(TOPLEVEL *toplevel, GList *object_glist) { GList *list = object_glist; OBJECT *o_current; while (list != NULL) { o_current = (OBJECT *) list->data; o_recalc_single_object(toplevel, o_current); list = g_list_next(list); } }
/*! \brief Set an #OBJECT's line options. * \par Function Description * This function allows a line's end, type, width, length and space to be set. * See #OBJECT_END and #OBJECT_TYPE for information on valid * object end and type values. * * \param [in] toplevel The TOPLEVEL object. * \param [in,out] o_current OBJECT to set line options on. * \param [in] end An OBJECT_END. * \param [in] type An OBJECT_TYPE. * \param [in] width Line width. * \param [in] length Line length. * \param [in] space Spacing between dashes/dots. Cannot be negative. * * \todo Make space an unsigned int and check for a max value instead. * If a max value is not required, then it would simplify the code. */ void o_set_line_options(TOPLEVEL *toplevel, OBJECT *o_current, OBJECT_END end, OBJECT_TYPE type, int width, int length, int space) { if(o_current == NULL) { return; } /* do some error checking / correcting */ switch(type) { case(TYPE_DOTTED): if (space < 1) { space = 100; s_log_message (_("Invalid space specified, setting to 100\n")); } break; case(TYPE_DASHED): case(TYPE_CENTER): case(TYPE_PHANTOM): if (length < 1) { length = 100; s_log_message (_("Invalid length specified, setting to 100\n")); } if (space < 1) { space = 100; s_log_message (_("Invalid space specified, setting to 100\n")); } break; default: break; } o_emit_pre_change_notify (toplevel, o_current); o_current->line_width = width; o_current->line_end = end; o_current->line_type = type; o_current->line_length = length; o_current->line_space = space; /* Recalculate the object's bounding box */ o_recalc_single_object( toplevel, o_current ); o_emit_change_notify (toplevel, o_current); }
/*! \brief Return the bounds of the given object. * \par Given an object, calculate the bounds coordinates. * \param [in] toplevel The toplevel structure. * \param [in] o_current The object to look the bounds for. * \param [out] rleft pointer to the left coordinate of the object. * \param [out] rtop pointer to the top coordinate of the object. * \param [out] rright pointer to the right coordinate of the object. * \param [out] rbottom pointer to the bottom coordinate of the object. * \return If any bounds were found for the object * \retval 0 No bound was found * \retval 1 Bound was found */ int world_get_single_object_bounds(TOPLEVEL *toplevel, OBJECT *o_current, int *rleft, int *rtop, int *rright, int *rbottom) { if (o_current != NULL) { switch(o_current->type) { case(OBJ_TEXT): /* only do bounding boxes for visible or doing show_hidden_text*/ /* you might lose some attrs though */ if (! (o_is_visible (toplevel, o_current) || toplevel->show_hidden_text)) { return 0; } /* This case falls through intentionally */ case(OBJ_LINE): case(OBJ_NET): case(OBJ_BUS): case(OBJ_BOX): case(OBJ_PICTURE): case(OBJ_CIRCLE): case(OBJ_PATH): case(OBJ_PIN): case(OBJ_ARC): case(OBJ_COMPLEX): case(OBJ_PLACEHOLDER): if (!o_current->w_bounds_valid) { o_recalc_single_object (toplevel, o_current); if (!o_current->w_bounds_valid) { return 0; } } *rleft = o_current->w_left; *rtop = o_current->w_top; *rright = o_current->w_right; *rbottom = o_current->w_bottom; return 1; default: break; } } return 0; }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_edit_show_hidden_lowlevel (GSCHEM_TOPLEVEL *w_current, const GList *o_list) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *o_current; const GList *iter; iter = o_list; while (iter != NULL) { o_current = (OBJECT *)iter->data; if (o_current->type == OBJ_TEXT && !o_is_visible (toplevel, o_current)) { /* don't toggle the visibility flag */ o_text_recreate (toplevel, o_current); } if (o_current->type == OBJ_COMPLEX || o_current->type == OBJ_PLACEHOLDER) { o_edit_show_hidden_lowlevel(w_current, o_current->complex->prim_objs); o_recalc_single_object(toplevel, o_current); } iter = g_list_next (iter); } }
/*! \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); }