Hi all, I've just gotten started working with geda. Up until now I'd been doing all of my work using eaglecad but I'm starting to outgrow its functionality and I'd really like to use truly free tools.
After playing with gschem for a while, I decided to try my hand at an alternate implementation for adding nets. Basically now when you draw a net in orthogonal mode two nets are drawn. Say you started the net at (0,0) and now your mouse is at (15,10). One net will be drawn horizontally from (0,0) to (15,0) and the other from (15,0) to (15,10). See screenshots of these two scenarios: Drawing net: http://oscar.dcarr.org/geda/gschem_net_1.png Net created: http://oscar.dcarr.org/geda/gschem_net_2.png This part seems to be working pretty well. However I used to sometimes get segfaults. Now they've magically disappeared. The problem occurred in the function o_net_end ( in o_net.c --- .nw, whatever) At the second call to "o_cue_undraw_list(w_current, other_objects)" line 546. What do these calls do? Also please look at lines 477, 522 and 559. Am I leaking anything here? I'll attach the actual file (hope thats not uncool). Its also online at: http://oscar.dcarr.org/geda/o_net.c Also note that I added two doubles (second_x, second_y) to libgeda's "struct st_toplevel" in struct.h that hold the last endpoint of the second net. I'd appreciate any comments on this work --- positive or negative. I think that once I finish that this mode may be useful but others may or may not feel that way. Thanks for your time, David Carr
#line 29 "../noweb/o_net.nw" /* gEDA - GPL Electronic Design Automation * gschem - gEDA Schematic Capture * Copyright (C) 1998-2000 Ales V. Hvezda * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA */ #line 11 "../noweb/o_net.nw" /* DO NOT read or edit this file ! Use ../noweb/o_net.nw instead */ #line 52 "../noweb/o_net.nw" #include <config.h> #include <stdio.h> #include <math.h> #include <libgeda/libgeda.h> #include "../include/globals.h" #include "../include/prototype.h" #ifdef HAVE_LIBDMALLOC #include <dmalloc.h> #endif #line 75 "../noweb/o_net.nw" void o_net_draw(TOPLEVEL * w_current, OBJECT * o_current) { int size; int x1, y1, x2, y2; /* screen coords */ #if NET_DEBUG /* debug */ char *tempstring; GdkFont *font; #endif if (o_current == NULL) { return; } if (o_current->line == NULL) { return; } o_net_recalc(w_current, o_current); /* reuse line's routine */ if (!o_line_visible(w_current, o_current->line, &x1, &y1, &x2, &y2)) { return; } #if DEBUG printf("drawing net\n\n"); #endif if (w_current->net_style == THICK) { size = SCREENabs(w_current, NET_WIDTH); if (size < 0) size = 0; gdk_gc_set_line_attributes(w_current->gc, size, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_CAP_NOT_LAST); gdk_gc_set_line_attributes(w_current->bus_gc, size, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_CAP_NOT_LAST); } if (w_current->override_color != -1) { gdk_gc_set_foreground(w_current->gc, x_get_color(w_current->override_color)); gdk_draw_line(w_current->window, w_current->gc, x1, y1, x2, y2); gdk_draw_line(w_current->backingstore, w_current->gc, x1, y1, x2, y2); } else { gdk_gc_set_foreground(w_current->gc, x_get_color(o_current->color)); gdk_draw_line(w_current->window, w_current->gc, x1, y1, x2, y2); gdk_draw_line(w_current->backingstore, w_current->gc, x1, y1, x2, y2); #if NET_DEBUG /* temp debug only */ font = gdk_fontset_load("10x20"); tempstring = g_strdup_printf("%s", o_current->name); gdk_draw_text(w_current->window, font, w_current->gc, x1 + 20, y1 + 20, tempstring, strlen(tempstring)); gdk_draw_text(w_current->backingstore, font, w_current->gc, x1 + 20, y1 + 20, tempstring, strlen(tempstring)); gdk_font_unref(font); free(tempstring); #endif } #if DEBUG printf("drew net\n\n"); #endif /* yes zero is right for the width -> use hardware lines */ if (w_current->net_style == THICK) { gdk_gc_set_line_attributes(w_current->gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); gdk_gc_set_line_attributes(w_current->bus_gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); } if (o_current->draw_grips && w_current->draw_grips == TRUE) { /* pb20011109 - modified to use the new o_line_[draw|erase]_grips() */ /* reuse the line functions */ if (!o_current->selected) { /* object is no more selected, erase the grips */ o_current->draw_grips = FALSE; o_line_erase_grips(w_current, o_current); } else { /* object is selected, draw the grips */ o_line_draw_grips(w_current, o_current); } } } #line 205 "../noweb/o_net.nw" void o_net_erase(TOPLEVEL * w_current, OBJECT * o_current) { w_current->override_color = w_current->background_color; o_net_draw(w_current, o_current); w_current->override_color = -1; } #line 223 "../noweb/o_net.nw" void o_net_draw_xor(TOPLEVEL * w_current, int dx, int dy, OBJECT * o_current) { int size; int color; if (o_current->line == NULL) { return; } if (o_current->saved_color != -1) { color = o_current->saved_color; } else { color = o_current->color; } gdk_gc_set_foreground(w_current->outline_xor_gc, x_get_darkcolor(color)); if (w_current->net_style == THICK) { size = SCREENabs(w_current, NET_WIDTH); gdk_gc_set_line_attributes(w_current->outline_xor_gc, size + 1, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); } gdk_draw_line(w_current->window, w_current->outline_xor_gc, o_current->line->screen_x[0] + dx, o_current->line->screen_y[0] + dy, o_current->line->screen_x[1] + dx, o_current->line->screen_y[1] + dy); /* backing store ? not approriate here */ if (w_current->net_style == THICK) { gdk_gc_set_line_attributes(w_current->outline_xor_gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); } } #line 276 "../noweb/o_net.nw" void o_net_draw_xor_single(TOPLEVEL * w_current, int dx, int dy, int whichone, OBJECT * o_current) { int color; int dx1 = -1, dx2 = -1, dy1 = -1, dy2 = -1; if (o_current->line == NULL) { return; } if (o_current->saved_color != -1) { color = o_current->saved_color; } else { color = o_current->color; } gdk_gc_set_foreground(w_current->outline_xor_gc, x_get_darkcolor(color)); #if 0 /* if I had this enabled, than xoring would leave a lot of mouse drops */ if (w_current->net_style == THICK) { size = SCREENabs(w_current, NET_WIDTH); gdk_gc_set_line_attributes(w_current->outline_xor_gc, size + 1, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); } #endif if (whichone == 0) { dx1 = dx; dy1 = dy; dx2 = 0; dy2 = 0; } else if (whichone == 1) { dx2 = dx; dy2 = dy; dx1 = 0; dy1 = 0; } else { fprintf(stderr, _("Got an invalid which one in o_net_draw_xor_single\n")); } gdk_draw_line(w_current->window, w_current->outline_xor_gc, o_current->line->screen_x[0] + dx1, o_current->line->screen_y[0] + dy1, o_current->line->screen_x[1] + dx2, o_current->line->screen_y[1] + dy2); /* backing store ? not approriate here */ #if 0 /* if I had this enabled, than xoring would leave a lot of mouse drops */ if (w_current->net_style == THICK) { gdk_gc_set_line_attributes(w_current->outline_xor_gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); } #endif } #line 348 "../noweb/o_net.nw" void o_net_start(TOPLEVEL * w_current, int x, int y) { int size; /* initalize all parameters used when drawing the new net */ w_current->last_x = w_current->start_x = w_current->second_x = fix_x(w_current, x); w_current->last_y = w_current->start_y = w_current->second_y = fix_y(w_current, y); #if 0 /* not ready for prime time use, this is the snap any point #if 0 */ int distance1; int distance2; OBJECT *real; OBJECT *o_current; int temp_x, temp_y; o_current = o_CONN_search_closest_range(w_current, w_current->page_current-> object_head, w_current->start_x, w_current->start_y, &temp_x, &temp_y, 200, NULL, NULL); if (o_current) { w_current->last_x = w_current->start_x = temp_x; w_current->last_y = w_current->start_y = temp_y; } else { w_current->last_x = w_current->start_x = fix_x(w_current, x); w_current->last_y = w_current->start_y = fix_y(w_current, y); } #endif #if 0 /* not ready for prime time use */ /* new net extenstion stuff */ o_current = w_current->page_current->selection_head->next; if (o_current != NULL && w_current->event_state == STARTDRAWNET) { if (o_current->type == OBJ_NET) { if (o_current->line) { real = o_list_sear( /* ch */ w_current->page_current->object_head, o_current); if (!real) { fprintf(stderr, _("selected a nonexistant object!\n")); exit(-1); } distance1 = dist(real->line->screen_x[0], real->line->screen_y[0], w_current->start_x, w_current->start_y); distance2 = dist(real->line->screen_x[1], real->line->screen_y[1], w_current->start_x, w_current->start_y); printf("%d %d\n", distance1, distance2); if (distance1 < distance2) { w_current->last_x = w_current->start_x = real->line->screen_x[0]; w_current->last_y = w_current->start_y = real->line->screen_y[0]; } else { w_current->last_x = w_current->start_x = real->line->screen_x[1]; w_current->last_y = w_current->start_y = real->line->screen_y[1]; } } } else if (o_current->type == OBJ_COMPLEX || o_current->type == OBJ_PLACEHOLDER) { real = o_list_sear( /* ch */ w_current->page_current->object_head, o_current); if (!real) { fprintf(stderr, _("selected a nonexistant object!\n")); exit(-1); } o_CONN_search_closest(w_current, o_current->complex, w_current->start_x, w_current->start_y, &temp_x, &temp_y, NULL); w_current->last_x = w_current->start_x = temp_x; w_current->last_y = w_current->start_y = temp_y; } } #endif if (w_current->net_style == THICK) { size = SCREENabs(w_current, NET_WIDTH); gdk_gc_set_line_attributes(w_current->xor_gc, size, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); } gdk_gc_set_foreground(w_current->xor_gc, x_get_darkcolor(w_current->select_color)); gdk_draw_line(w_current->window, w_current->xor_gc, w_current->start_x, w_current->start_y, w_current->last_x, w_current->last_y); if (w_current->net_style == THICK) { gdk_gc_set_line_attributes(w_current->xor_gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); } } #line 468 "../noweb/o_net.nw" int o_net_end(TOPLEVEL * w_current, int x, int y) { int x1, y1; int x2, y2; int x3, y3; int color; int size; /*int temp_x, temp_y; */ /* OBJECT *o_current; */ GList *other_objects = NULL; OBJECT *new_net = NULL; if (w_current->inside_action == 0) { o_redraw(w_current, w_current->page_current->object_head); return (FALSE); } if (w_current->override_net_color == -1) { color = w_current->net_color; } else { color = w_current->override_net_color; } size = SCREENabs(w_current, NET_WIDTH); if (w_current->net_style == THICK) { gdk_gc_set_line_attributes(w_current->xor_gc, size, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); } gdk_gc_set_foreground(w_current->xor_gc, x_get_darkcolor(w_current->select_color)); /* Erase primary rubber net line */ gdk_draw_line(w_current->window, w_current->xor_gc, w_current->start_x, w_current->start_y, w_current->last_x, w_current->last_y); /* Erase secondary rubber net line */ gdk_draw_line(w_current->window, w_current->xor_gc, w_current->last_x, w_current->last_y, w_current->second_x, w_current->second_y); if (w_current->net_style == THICK) { gdk_gc_set_line_attributes(w_current->xor_gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); gdk_gc_set_line_attributes(w_current->gc, size, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); } /* don't allow zero length nets */ /* this ends the net drawing behavior we want this? hack */ if ((w_current->start_x == w_current->last_x) && (w_current->start_y == w_current->last_y)) { w_current->start_x = (-1); w_current->start_y = (-1); w_current->last_x = (-1); w_current->last_y = (-1); w_current->second_x = (-1); w_current->second_y = (-1); w_current->inside_action = 0; i_set_state(w_current, STARTDRAWNET); o_net_eraserubber(w_current); return (FALSE); } #if 0 /* not ready for prime time use */ /* second attempt at all snapping */ o_current = o_CONN_search_closest_range(w_current, w_current->page_current-> object_head, w_current->last_x, w_current->last_y, &temp_x, &temp_y, 200, NULL, NULL); if (o_current) { w_current->last_x = temp_x; w_current->last_y = temp_y; } else { w_current->last_x = fix_x(w_current, x); w_current->last_y = fix_y(w_current, y); } #endif /* Primary net runs from (x1,y1)-(x2,y2) */ /* Secondary net from (x2,y2)-(x3,y3) */ SCREENtoWORLD(w_current, w_current->start_x, w_current->start_y, &x1, &y1); SCREENtoWORLD(w_current, w_current->last_x, w_current->last_y, &x2, &y2); SCREENtoWORLD(w_current, w_current->second_x, w_current->second_y, &x3, &y3); /* Snap points to closest grid location */ x1 = snap_grid(w_current, x1); y1 = snap_grid(w_current, y1); x2 = snap_grid(w_current, x2); y2 = snap_grid(w_current, y2); x3 = snap_grid(w_current, x3); y3 = snap_grid(w_current, y3); w_current->save_x = w_current->second_x; w_current->save_y = w_current->second_y; /* create primary net */ w_current->page_current->object_tail = new_net = o_net_add(w_current, w_current->page_current->object_tail, OBJ_NET, color, x1, y1, x2, y2); /* conn stuff */ other_objects = s_conn_return_others(other_objects, w_current->page_current-> object_tail); if (o_net_add_busrippers(w_current, new_net, other_objects)) { g_list_free(other_objects); other_objects = NULL; other_objects = s_conn_return_others(other_objects, new_net); } #if DEBUG s_conn_print(new_net->conn_list); #endif gdk_gc_set_foreground(w_current->gc, x_get_color(color)); gdk_draw_line(w_current->window, w_current->gc, new_net->line->screen_x[0], new_net->line->screen_y[0], new_net->line->screen_x[1], new_net->line->screen_y[1]); gdk_draw_line(w_current->backingstore, w_current->gc, new_net->line->screen_x[0], new_net->line->screen_y[0], new_net->line->screen_x[1], new_net->line->screen_y[1]); if (w_current->net_style == THICK) { gdk_gc_set_line_attributes(w_current->gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); } o_cue_undraw_list(w_current, other_objects); o_cue_draw_list(w_current, other_objects); o_cue_draw_single(w_current, new_net); /* you don't want to consolidate nets which are drawn non-ortho */ if (w_current->net_consolidate == TRUE && !w_current->CONTROLKEY) { o_net_consolidate_segments(w_current, new_net); } /* If the second net is not zero length, add it as well */ if (x3 != x2 || y3 != y2) { w_current->page_current->object_tail = new_net = o_net_add(w_current, w_current->page_current->object_tail, OBJ_NET, color, x2, y2, x3, y3); /* conn stuff */ other_objects = s_conn_return_others(other_objects, w_current->page_current-> object_tail); if (o_net_add_busrippers(w_current, new_net, other_objects)) { g_list_free(other_objects); other_objects = NULL; other_objects = s_conn_return_others(other_objects, new_net); } #if DEBUG s_conn_print(new_net->conn_list); #endif gdk_gc_set_foreground(w_current->gc, x_get_color(color)); gdk_draw_line(w_current->window, w_current->gc, new_net->line->screen_x[0], new_net->line->screen_y[0], new_net->line->screen_x[1], new_net->line->screen_y[1]); gdk_draw_line(w_current->backingstore, w_current->gc, new_net->line->screen_x[0], new_net->line->screen_y[0], new_net->line->screen_x[1], new_net->line->screen_y[1]); if (w_current->net_style == THICK) { gdk_gc_set_line_attributes(w_current->gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); } o_cue_undraw_list(w_current, other_objects); o_cue_draw_list(w_current, other_objects); o_cue_draw_single(w_current, new_net); /* you don't want to consolidate nets which are drawn non-ortho */ if (w_current->net_consolidate == TRUE && !w_current->CONTROLKEY) { o_net_consolidate_segments(w_current, new_net); } } g_list_free(other_objects); w_current->page_current->CHANGED = 1; w_current->start_x = w_current->save_x; w_current->start_y = w_current->save_y; o_undo_savestate(w_current, UNDO_ALL); #if 0 /* a false attempt at ending the rubberbanding.. */ if (conn_count) { w_current->inside_action = 0; i_set_state(w_current, STARTDRAWNET); o_net_eraserubber(w_current); } #endif return (TRUE); } #line 631 "../noweb/o_net.nw" void o_net_rubbernet(TOPLEVEL * w_current, int x, int y) { int diff_x, diff_y; int size; int ortho; if (w_current->inside_action == 0) { o_redraw(w_current, w_current->page_current->object_head); return; } if (w_current->net_style == THICK) { size = SCREENabs(w_current, NET_WIDTH); gdk_gc_set_line_attributes(w_current->xor_gc, size, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); } gdk_gc_set_foreground(w_current->xor_gc, x_get_darkcolor(w_current->select_color)); /* Orthognal mode enabled when Control Key is NOT pressed */ ortho = !w_current->CONTROLKEY; /* Erase primary line */ gdk_draw_line(w_current->window, w_current->xor_gc, w_current->start_x, w_current->start_y, w_current->last_x, w_current->last_y); /* Erase secondary line*/ if ( w_current->second_x != -1 && w_current->second_y != -1 ) { gdk_draw_line(w_current->window, w_current->xor_gc, w_current->last_x, w_current->last_y, w_current->second_x, w_current->second_y); } /* In orthogonal mode secondary line is the same as the first */ if (!ortho) { w_current->second_x = w_current->last_x; w_current->second_y = w_current->last_y; } w_current->last_x = fix_x(w_current, x); w_current->last_y = fix_y(w_current, y); /* If you press the control key then you can draw non-ortho nets */ if (ortho) { diff_x = abs(w_current->last_x - w_current->start_x); diff_y = abs(w_current->last_y - w_current->start_y); /* calculate the co-ordinates necessary to draw the lines*/ if (diff_x >= diff_y) { w_current->last_y = w_current->start_y; w_current->second_x = w_current->last_x; w_current->second_y = mouse_y; } else { w_current->last_x = w_current->start_x; w_current->second_x = mouse_x; w_current->second_y = w_current->last_y; } } gdk_gc_set_foreground(w_current->xor_gc, x_get_darkcolor(w_current->select_color)); /* draw primary line */ gdk_draw_line(w_current->window, w_current->xor_gc, w_current->start_x, w_current->start_y, w_current->last_x, w_current->last_y); /* Draw secondary line */ gdk_draw_line(w_current->window, w_current->xor_gc, w_current->last_x, w_current->last_y, w_current->second_x, w_current->second_y); if (w_current->net_style == THICK) { gdk_gc_set_line_attributes(w_current->xor_gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); } } #line 701 "../noweb/o_net.nw" /* used in button cancel code in x_events.c */ void o_net_eraserubber(TOPLEVEL * w_current) { int size; if (w_current->net_style == THICK) { size = SCREENabs(w_current, NET_WIDTH); if (size < 0) size = 0; gdk_gc_set_line_attributes(w_current->gc, size, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); } gdk_gc_set_foreground(w_current->gc, x_get_color(w_current->background_color)); /* Erase primary primary rubber net line */ gdk_draw_line(w_current->window, w_current->gc, w_current->start_x, w_current->start_y, w_current->last_x, w_current->last_y); /* Erase secondary rubber net line */ gdk_draw_line(w_current->window, w_current->xor_gc, w_current->last_x, w_current->last_y, w_current->second_x, w_current->second_y); if (w_current->net_style == THICK) { gdk_gc_set_line_attributes(w_current->gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); } } #line 741 "../noweb/o_net.nw" /* used in button cancel code in x_events.c */ void o_net_xorrubber(TOPLEVEL * w_current) { int size; if (w_current->net_style == THICK) { size = SCREENabs(w_current, NET_WIDTH); if (size < 0) size = 0; gdk_gc_set_line_attributes(w_current->gc, size, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); } gdk_gc_set_foreground(w_current->gc, x_get_darkcolor(w_current->select_color)); gdk_draw_line(w_current->window, w_current->gc, w_current->start_x, w_current->start_y, w_current->last_x, w_current->last_y); if (w_current->net_style == THICK) { gdk_gc_set_line_attributes(w_current->gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); } } #line 784 "../noweb/o_net.nw" int o_net_add_busrippers(TOPLEVEL * w_current, OBJECT * net_obj, GList * other_objects) { 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; char *clib = NULL; length = o_line_length(net_obj); if (!other_objects) { return (FALSE); } if (length <= ripper_size) { return (FALSE); } if (w_current->override_net_color == -1) { color = w_current->net_color; } else { color = w_current->override_net_color; } /* check for a bus connection and draw rippers if so */ cl_current = other_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 = cl_current2->next; } 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_net_recalc(w_current, 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_net_recalc(w_current, 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_net_recalc(w_current, 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_net_recalc(w_current, 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 = cl_current->next; } if (made_changes) { s_conn_remove(w_current, net_obj); if (w_current->bus_ripper_type == COMP_BUS_RIPPER) { const GSList *clibs = s_clib_search_basename(w_current->bus_ripper_symname); if (clibs != NULL) { clib = (gchar *) clibs->data; } } for (i = 0; i < ripper_count; i++) { if (w_current->bus_ripper_type == NET_BUS_RIPPER) { w_current->page_current->object_tail = o_net_add(w_current, w_current->page_current->object_tail, OBJ_NET, color, rippers[i].x[0], rippers[i].y[0], rippers[i].x[1], rippers[i].y[1]); } else { if (clib) { w_current->page_current->object_tail = (OBJECT *) o_complex_add(w_current, w_current->page_current-> object_tail, OBJ_COMPLEX, WHITE, rippers[i].x[0], rippers[i].y[0], complex_angle, 0, clib, w_current->bus_ripper_symname, 1, TRUE); o_complex_draw(w_current, w_current->page_current->object_tail); } else { s_log_message(_("Could not find %s in any component-library\n"), w_current->bus_ripper_symname); } } } s_conn_update_object(w_current, net_obj); return (TRUE); } return (FALSE); }