On Jan 12, 2008 9:37 PM, a r <[EMAIL PROTECTED]> wrote:
>
> I have found a bug in the logic of previously attached patch. New
> patch will follow soon but first I want to clean up it a bit more and
> test.

I've attached an updated patch (sorry, again it's for v.1.3.0). The
logic was changed to match the previously described behaviour. As far
as the placement algorithm is concerned, I am done with it.

During testing I've got a SIGSEGV, which, as far as I can see, is not
directly related to my changes (although it is fairly possible that
these changes expose the error somehow). The best method to recreate
it is to switch the net drawing mode on and start clicking wildly on
the schematic.

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1221187904 (LWP 15757)]
0x08098147 in o_cue_erase_lowlevel (w_current=0x80cdb08, object=0x83a0010,
    whichone=0) at o_cue.c:295
295       x = object->line->x[whichone];
(gdb) bt
#0  0x08098147 in o_cue_erase_lowlevel (w_current=0x80cdb08, object=0x83a0010,
    whichone=0) at o_cue.c:295
#1  0x0809829d in o_cue_erase_single (w_current=0x80cdb08, object=0x83a0010)
    at o_cue.c:425
#2  0x0809838b in o_cue_undraw (w_current=0x80cdb08, object=0x83a0010)
    at o_cue.c:445
#3  0x08098442 in o_cue_undraw_list (w_current=0x80cdb08,
    object_list=0x83991b0) at o_cue.c:537
#4  0x080730ca in o_net_end (w_current=0x80cdb08, x=614, y=445) at o_net.c:559
#5  0x080868f4 in x_event_button_pressed (widget=0x817ba10, event=0x814f730,
    w_current=0x80cdb08) at x_event.c:305
#6  0xb767b1b0 in gtk_marshal_BOOLEAN__VOID ()
   from /opt/gnome/lib/libgtk-x11-2.0.so.0
#7  0xb7bb0c0b in g_closure_invoke () from /opt/gnome/lib/libgobject-2.0.so.0
#8  0xb7bc1d3d in g_signal_override_class_closure ()
   from /opt/gnome/lib/libgobject-2.0.so.0
#9  0xb7bc300f in g_signal_emit_valist ()
   from /opt/gnome/lib/libgobject-2.0.so.0
#10 0xb7bc3415 in g_signal_emit () from /opt/gnome/lib/libgobject-2.0.so.0
#11 0xb778eb18 in gtk_widget_get_default_style ()
   from /opt/gnome/lib/libgtk-x11-2.0.so.0
#12 0xb7674653 in gtk_propagate_event ()
   from /opt/gnome/lib/libgtk-x11-2.0.so.0

Cheers,
-r.
diff -ruN geda-gschem-1.3.0/include/gschem_struct.h geda-gschem-1.3.0ar/include/gschem_struct.h
--- geda-gschem-1.3.0/include/gschem_struct.h	2007-12-30 02:50:19.000000000 +0000
+++ geda-gschem-1.3.0ar/include/gschem_struct.h	2008-01-12 00:03:27.000000000 +0000
@@ -98,7 +98,8 @@
   int inside_action;                    /* Are we doing an action? */
   int rotated_inside;                   /* Was the selection rotated
                                            inside an action? */
-
+  int directions;
+  
   /* --------------------- */
   /* Gschem internal state */
   /* --------------------- */
diff -ruN geda-gschem-1.3.0/src/o_net.c geda-gschem-1.3.0ar/src/o_net.c
--- geda-gschem-1.3.0/src/o_net.c	2007-12-30 02:50:19.000000000 +0000
+++ geda-gschem-1.3.0ar/src/o_net.c	2008-01-13 00:42:13.000000000 +0000
@@ -32,6 +32,13 @@
 #include <dmalloc.h>
 #endif
 
+#define VERT_UP     1
+#define VERT_DOWN   2
+#define VERT        3
+#define HORIZ_LEFT  4
+#define HORIZ_RIGHT 8
+#define HORIZ      12
+
 /*! \todo Finish function documentation!!!
  *  \brief
  *  \par Function Description
@@ -244,6 +251,39 @@
 
 }
 
+/*!
+ *  \brief
+ *  \par Function Description
+ *  The function checks the o_current OBJECT (must be of a type: OBJ_NET, OBJ_BUS or OBJ_PIN)
+ *  at the current position (x, y) (world coordinates) and returns the preferrable directions
+ *  of connecting to this object. The return value is a bit field in which each direction is
+ *  denoted as a single bit.
+ */
+int o_net_get_directions(OBJECT *o_current, int x, int y) {
+  g_assert(o_current->type == OBJ_NET || o_current->type == OBJ_BUS || o_current->type == OBJ_PIN);
+  int directions = HORIZ | VERT;
+  int dmin, dmax;
+  /* FIX: assumes that OBJ_BUS and OBJ_PIN are compatible with OBJ_NET */
+  if (o_net_orientation(o_current) == HORIZONTAL && o_current->line->y[0] == y) {
+    dmin = min(o_current->line->x[0], o_current->line->x[1]);
+    dmax = max(o_current->line->x[0], o_current->line->x[1]);
+    if (x >  dmin && x <= dmax)
+      directions &= ~HORIZ_LEFT;
+    if (x >= dmin && x <  dmax)
+      directions &= ~HORIZ_RIGHT;
+  }
+  if (o_net_orientation(o_current) == VERTICAL && o_current->line->x[0] == x) {
+    dmin = min(o_current->line->y[0], o_current->line->y[1]);
+    dmax = max(o_current->line->y[0], o_current->line->y[1]);
+    if (y >  dmin && y <= dmax)
+      directions &= ~VERT_DOWN;
+    if (y >= dmin && y <  dmax)
+      directions &= ~VERT_UP;
+  }
+  return directions;
+}
+
+
 /*! \todo Finish function documentation!!!
  *  \brief
  *  \par Function Description
@@ -252,7 +292,9 @@
 void o_net_start(GSCHEM_TOPLEVEL *w_current, int x, int y)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
+  OBJECT *o_current, *o_current2;
   int size;
+  int x1, y1;
 
   /* initalize all parameters used when drawing the new net */
   w_current->last_x = w_current->start_x = w_current->second_x = 
@@ -260,6 +302,31 @@
   w_current->last_y = w_current->start_y = w_current->second_y = 
     fix_y(toplevel, y);
 
+
+  o_current = toplevel->page_current->object_head;
+
+  SCREENtoWORLD(toplevel, w_current->start_x, w_current->start_y, &x1,	&y1);
+  x1 = snap_grid(toplevel, x1);
+  y1 = snap_grid(toplevel, y1);
+
+  /* check all nets under cursor and mark invalid start directions */
+
+  w_current->directions = HORIZ | VERT;
+
+  while (o_current != NULL) {
+    if (o_current->type == OBJ_NET || o_current->type == OBJ_BUS || o_current->type == OBJ_PIN)
+      w_current->directions &= o_net_get_directions(o_current, x1, y1);
+    if (o_current->type == OBJ_COMPLEX) {
+      o_current2 = o_current->complex->prim_objs;
+      while (o_current2 != NULL) {
+	if (o_current2->type == OBJ_PIN)
+	  w_current->directions &= o_net_get_directions(o_current2, x1, y1);
+	o_current2 = o_current2->next;
+      }
+    }
+    o_current = o_current->next;
+  }
+
   if (toplevel->net_style == THICK ) {
     size = SCREENabs(toplevel, NET_WIDTH);
     gdk_gc_set_line_attributes(w_current->xor_gc, size,
@@ -521,7 +588,8 @@
   int diff_x, diff_y;
   int size;
   int ortho;
-
+  int horiz = 0, vert = 0;
+  
   g_assert( w_current->inside_action != 0 );
 
   if (toplevel->net_style == THICK) {
@@ -567,9 +635,43 @@
     diff_x = abs(w_current->last_x - w_current->start_x);
     diff_y = abs(w_current->last_y - w_current->start_y);
 
+    horiz = ((w_current->last_x > w_current->start_x) && (w_current->directions & HORIZ_RIGHT)) ||
+            ((w_current->last_x < w_current->start_x) && (w_current->directions & HORIZ_LEFT));
+    vert = ((w_current->last_y < w_current->start_y) && (w_current->directions & VERT_UP)) ||
+           ((w_current->last_y > w_current->start_y) && (w_current->directions & VERT_DOWN));
+
+    /*
+    printf ("%d %d, %d %d %d %d, %d %d\n", w_current->last_x - w_current->start_x, -w_current->last_y + w_current->start_y,
+           w_current->directions & HORIZ_LEFT, w_current->directions & HORIZ_RIGHT,
+           w_current->directions & VERT_DOWN, w_current->directions & VERT_UP,
+	   horiz, vert);
+    */
+
+    /* if both directions are invalid start with longer segment */
+    if (!horiz && !vert)
+      horiz = diff_x > diff_y;
+
+    /* if both directions are valid then if preferred direction exists start with this one,
+       or, otherwise, start with a longer segment */
+    if (horiz && vert) {
+      if ((w_current->directions & HORIZ) != HORIZ && (w_current->directions & VERT) == VERT)
+	horiz = 1;
+      else if ((w_current->directions & VERT) != VERT && (w_current->directions & HORIZ) == HORIZ)
+	horiz = 0;
+      else    
+	horiz = diff_x > diff_y;
+    }
+
+    /* if only one net is to be drawn force the direction even if not valid */
+    if (!diff_x)
+      horiz = 0;
+    if (!diff_y)
+      horiz = 1;
+      
+      
     /* calculate the co-ordinates necessary to draw the lines*/
     /* Pressing the shift key will cause the vertical and horizontal lines to switch places */
-    if ( !w_current->SHIFTKEY ) {
+    if ( horiz == !w_current->SHIFTKEY ) {
       w_current->last_y = w_current->start_y;
       w_current->second_x = w_current->last_x;
       w_current->second_y = fix_y(toplevel,y);

_______________________________________________
geda-dev mailing list
[email protected]
http://www.seul.org/cgi-bin/mailman/listinfo/geda-dev

Reply via email to