[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

gEDA-cvs: branch: master updated (1.4.0-20080127-50-g1b05cbf)



The branch, master has been updated
       via  1b05cbfcbb07970159c58b2b18d583516e257a45 (commit)
       via  3372a6ff3e99fb1d46c694b1d7bb7a586c9eebb9 (commit)
       via  fadb2326204bb6375749653d1e8a3035462b3479 (commit)
       via  5f62a34fc821ced98f6faa7d4901ccd47e48380e (commit)
      from  deacf7e8bc9a67aa4ac446f8627f177e8daa249a (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


=========
 Summary
=========

 gschem/include/globals.h       |    2 +
 gschem/include/gschem_struct.h |    5 +-
 gschem/src/gschem_toplevel.c   |    7 +-
 gschem/src/i_callbacks.c       |    2 +-
 gschem/src/o_net.c             |  359 +++++++++++++++++++++-------------------
 gschem/src/x_event.c           |   56 +++----
 6 files changed, 218 insertions(+), 213 deletions(-)


=================
 Commit Messages
=================

commit 1b05cbfcbb07970159c58b2b18d583516e257a45
Author: Werner Hoch <werner.ho@xxxxxx>
Date:   Sat Apr 26 17:09:58 2008 +0200

    switched x events to world coordinates in net drawing code
    
    This includes the creation of w_x, w_y, mouse_wx, mouse_wy variables
    in the x_event functions. Call all net drawing functions in world
    coordinates. Print a warning message when connecting to offgrid pins
    and nets.

:100644 100644 6b0ee77... 8833718... M	gschem/include/globals.h
:100644 100644 ccb217d... 782b8a9... M	gschem/src/i_callbacks.c
:100644 100644 6fa6e4d... 29bedc7... M	gschem/src/o_net.c
:100644 100644 83825b1... ca4c2c4... M	gschem/src/x_event.c

commit 3372a6ff3e99fb1d46c694b1d7bb7a586c9eebb9
Author: Werner Hoch <werner.ho@xxxxxx>
Date:   Tue Apr 1 13:50:07 2008 +0200

    removed redundant snap grid code in o_net.c

:100644 100644 67bea42... 6fa6e4d... M	gschem/src/o_net.c

commit fadb2326204bb6375749653d1e8a3035462b3479
Author: Werner Hoch <werner.ho@xxxxxx>
Date:   Tue Apr 1 13:37:05 2008 +0200

    add world coordinates for the rubber lines, use them for net drawing
    
    This commit adds new variables to GSCHEM_TOPLEVEL. first_wx,
    second_wx, third_wx. They are intended to replace the screen
    coordinates start_x, last_x and last_y. Deployed that change in the
    net drawing code. This should finally fix Bug [#1928544].

:100644 100644 eeb2040... d8d139c... M	gschem/include/gschem_struct.h
:100644 100644 78a8070... 2726f7c... M	gschem/src/gschem_toplevel.c
:100644 100644 fcf1aab... 67bea42... M	gschem/src/o_net.c

commit 5f62a34fc821ced98f6faa7d4901ccd47e48380e
Author: Werner Hoch <werner.ho@xxxxxx>
Date:   Tue Apr 1 10:20:18 2008 +0200

    switched the net rubber code from screen to world coordinates
    
    Using screen coordinates for start_x, second_x and last_x causes
    integer arithmetic errors whenever the coordinates are converted between
    the screen an the world. The conversion occurs with the fix_x function
    and whenever the user zooms/pans in the drawing mode.
    This change fixes bug [#1928544] pointed out by Thomas Arndt.
    Note: This breaks the zooming and paning inside net drawing

:100644 100644 13db241... fcf1aab... M	gschem/src/o_net.c
:100644 100644 61cc1b2... 83825b1... M	gschem/src/x_event.c

=========
 Changes
=========

commit 1b05cbfcbb07970159c58b2b18d583516e257a45
Author: Werner Hoch <werner.ho@xxxxxx>
Date:   Sat Apr 26 17:09:58 2008 +0200

    switched x events to world coordinates in net drawing code
    
    This includes the creation of w_x, w_y, mouse_wx, mouse_wy variables
    in the x_event functions. Call all net drawing functions in world
    coordinates. Print a warning message when connecting to offgrid pins
    and nets.

diff --git a/gschem/include/globals.h b/gschem/include/globals.h
index 6b0ee77..8833718 100644
--- a/gschem/include/globals.h
+++ b/gschem/include/globals.h
@@ -43,6 +43,8 @@ extern int logging_dest;
 /* current mouse location */
 extern int mouse_x; /* defined in x_event.c */
 extern int mouse_y;
+extern int mouse_wx;
+extern int mouse_wy;
 
 /* command line options */
 extern int quiet_mode;
diff --git a/gschem/src/i_callbacks.c b/gschem/src/i_callbacks.c
index ccb217d..782b8a9 100644
--- a/gschem/src/i_callbacks.c
+++ b/gschem/src/i_callbacks.c
@@ -2368,7 +2368,7 @@ DEFINE_I_CALLBACK(add_net_hotkey)
   i_set_state(w_current, STARTDRAWNET);
   i_update_toolbar(w_current);
 
-  o_net_start(w_current, mouse_x, mouse_y);
+  o_net_start(w_current, mouse_wx, mouse_wy);
 
   w_current->event_state=DRAWNET;
   w_current->inside_action = 1;
diff --git a/gschem/src/o_net.c b/gschem/src/o_net.c
index 6fa6e4d..29bedc7 100644
--- a/gschem/src/o_net.c
+++ b/gschem/src/o_net.c
@@ -414,11 +414,10 @@ void o_net_guess_direction(GSCHEM_TOPLEVEL *w_current,
  *  are set to -1.
  */
 void o_net_find_magnetic(GSCHEM_TOPLEVEL *w_current,
-			 int x, int y)
+			 int w_x, int w_y)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
-  int x1, x2, y1, y2, min_x, min_y;
-  int world_x, world_y;
+  int x1, x2, y1, y2, min_x, min_y, w_magnetic_reach;
   double mindist, minbest, dist1, dist2;
   double weight, min_weight;
   int magnetic_reach = 0;
@@ -432,12 +431,13 @@ void o_net_find_magnetic(GSCHEM_TOPLEVEL *w_current,
   /* max distance of all the different reaches */
   magnetic_reach = max(MAGNETIC_PIN_REACH, MAGNETIC_NET_REACH);
   magnetic_reach = max(magnetic_reach, MAGNETIC_BUS_REACH);
-
-  SCREENtoWORLD(toplevel, x, y, &world_x, &world_y);
+  w_magnetic_reach = WORLDabs(toplevel, magnetic_reach);
 
   /* get the objects of the tiles around the reach region */
-  SCREENtoWORLD(toplevel, x - magnetic_reach, y - magnetic_reach, &x1, &y1);
-  SCREENtoWORLD(toplevel, x + magnetic_reach, y + magnetic_reach, &x2, &y2);
+  x1 = w_x - w_magnetic_reach;
+  y1 = w_y - w_magnetic_reach;
+  x2 = w_x + w_magnetic_reach;
+  y2 = w_y + w_magnetic_reach;
   objectlists = s_tile_get_objectlists(toplevel, x1, y1, x2, y2);
 
   for (iter1 = objectlists; iter1 != NULL; iter1 = g_list_next(iter1)) {
@@ -452,8 +452,8 @@ void o_net_find_magnetic(GSCHEM_TOPLEVEL *w_current,
 	min_x = o_current->line->x[o_current->whichend];
 	min_y = o_current->line->y[o_current->whichend];
 
-	mindist = sqrt((double) (world_x - min_x)*(world_x - min_x)
-		       + (double) (world_y - min_y)*(world_y - min_y));
+	mindist = sqrt((double) (w_x - min_x)*(w_x - min_x)
+		       + (double) (w_y - min_y)*(w_y - min_y));
 	weight = mindist / MAGNETIC_PIN_WEIGHT;
       }
 
@@ -466,10 +466,10 @@ void o_net_find_magnetic(GSCHEM_TOPLEVEL *w_current,
 	x2 = o_current->line->x[1];
 	y2 = o_current->line->y[1];
 	/* endpoint tests */
-	dist1 = sqrt((double) (world_x - x1)*(world_x - x1)
-		     + (double) (world_y - y1)*(world_y - y1));
-	dist2 = sqrt((double) (world_x - x2)*(world_x - x2)
-		     + (double) (world_y - y2)*(world_y - y2));
+	dist1 = sqrt((double) (w_x - x1)*(w_x - x1)
+		     + (double) (w_y - y1)*(w_y - y1));
+	dist2 = sqrt((double) (w_x - x2)*(w_x - x2)
+		     + (double) (w_y - y2)*(w_y - y2));
 	if (dist1 < dist2) {
 	  min_x = x1;
 	  min_y = y1;
@@ -483,20 +483,20 @@ void o_net_find_magnetic(GSCHEM_TOPLEVEL *w_current,
       
 	/* midpoint tests */
 	if ((x1 == x2)  /* vertical net */
-	    && ((y1 >= world_y && world_y >= y2)
-		|| (y2 >= world_y && world_y >= y1))) {
-	  if (abs(world_x - x1) < mindist) {
-	    mindist = abs(world_x - x1);
+	    && ((y1 >= w_y && w_y >= y2)
+		|| (y2 >= w_y && w_y >= y1))) {
+	  if (abs(w_x - x1) < mindist) {
+	    mindist = abs(w_x - x1);
 	    min_x = x1;
-	    min_y = world_y;
+	    min_y = w_y;
 	  }
 	} 
 	if ((y1 == y2)  /* horitontal net */
-	    && ((x1 >= world_x && world_x >= x2)
-		|| (x2 >= world_x && world_x >= x1))) {  
-	  if (abs(world_y - y1) < mindist) {
-	    mindist = abs(world_y - y1);
-	    min_x = world_x;
+	    && ((x1 >= w_x && w_x >= x2)
+		|| (x2 >= w_x && w_x >= x1))) {  
+	  if (abs(w_y - y1) < mindist) {
+	    mindist = abs(w_y - y1);
+	    min_x = w_x;
 	    min_y = y1;
 	  }
 	}
@@ -515,8 +515,8 @@ void o_net_find_magnetic(GSCHEM_TOPLEVEL *w_current,
 	minbest = mindist;
 	min_weight = weight;
 	o_magnetic = o_current;
-	w_current->magnetic_wx = snap_grid(toplevel, min_x);
-	w_current->magnetic_wy = snap_grid(toplevel, min_y);
+	w_current->magnetic_wx = min_x;
+	w_current->magnetic_wy = min_y;
       }
     }
   }
@@ -528,7 +528,7 @@ void o_net_find_magnetic(GSCHEM_TOPLEVEL *w_current,
     case (OBJ_NET): magnetic_reach = MAGNETIC_NET_REACH; break;
     case (OBJ_BUS): magnetic_reach = MAGNETIC_BUS_REACH; break;
     }
-    if (minbest > magnetic_reach*toplevel->page_current->to_world_x_constant) {
+    if (minbest > WORLDabs(toplevel, magnetic_reach)) {
       w_current->magnetic_wx = -1;
       w_current->magnetic_wy = -1;
     }
@@ -607,21 +607,18 @@ void o_net_finishmagnetic(GSCHEM_TOPLEVEL *w_current)
  *  position of the magnetic marker.
  *  If the controllkey is pressed the magnetic marker follows the mouse.
  */
-void o_net_start_magnetic(GSCHEM_TOPLEVEL *w_current, int x, int y)
+void o_net_start_magnetic(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
 {
-  TOPLEVEL *toplevel = w_current->toplevel;
-
   o_net_eraserubber(w_current);
   /* the dc is completely clean now, reset inside_action. */
   w_current->inside_action = 0;
 
   if (w_current->CONTROLKEY) {
-    SCREENtoWORLD(toplevel, x, y, &w_current->magnetic_wx, &w_current->magnetic_wy);
-    w_current->magnetic_wx = snap_grid(toplevel, w_current->magnetic_wx);
-    w_current->magnetic_wy = snap_grid(toplevel, w_current->magnetic_wy);
+    w_current->magnetic_wx = w_x;
+    w_current->magnetic_wy = w_y;
   }
   else {
-    o_net_find_magnetic(w_current, x, y);
+    o_net_find_magnetic(w_current, w_x, w_y);
   }
 
   o_net_drawrubber(w_current);
@@ -633,7 +630,7 @@ void o_net_start_magnetic(GSCHEM_TOPLEVEL *w_current, int x, int y)
  *  cursor. If we have a visible magnetic marker, we use that instead of 
  *  the cursor position
  */
-void o_net_start(GSCHEM_TOPLEVEL *w_current, int x, int y)
+void o_net_start(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
 
@@ -642,14 +639,17 @@ void o_net_start(GSCHEM_TOPLEVEL *w_current, int x, int y)
     w_current->first_wy = w_current->magnetic_wy;
   }
   else {
-    SCREENtoWORLD(toplevel, x, y, &w_current->first_wx, &w_current->first_wy);
-    w_current->first_wx = snap_grid(toplevel, w_current->first_wx);
-    w_current->first_wy = snap_grid(toplevel, w_current->first_wy);
+    w_current->first_wx = w_x;
+    w_current->first_wy = w_y;
   }
-   
+
   w_current->second_wx = w_current->third_wx = w_current->first_wx;
   w_current->second_wy = w_current->third_wy = w_current->first_wy;
 
+  if (w_current->first_wx != snap_grid(toplevel, w_current->first_wx)
+      || w_current->first_wy != snap_grid(toplevel, w_current->first_wy))
+      s_log_message(_("Warning: Starting net at off grid coordinate\n"));
+
   if (w_current->net_direction_mode)
     o_net_guess_direction(w_current, w_current->first_wx, w_current->first_wy);
 }
@@ -665,7 +665,7 @@ void o_net_start(GSCHEM_TOPLEVEL *w_current, int x, int y)
  *
  * The function returns TRUE if it has drawn a net, FALSE otherwise.
  */
-int o_net_end(GSCHEM_TOPLEVEL *w_current, int x, int y)
+int o_net_end(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
   int color;
@@ -673,7 +673,7 @@ int o_net_end(GSCHEM_TOPLEVEL *w_current, int x, int y)
   int primary_zero_length, secondary_zero_length;
   int found_primary_connection = FALSE;
   int sx[2], sy[2];
-  int save_magnetic;
+  int save_magnetic, save_wx, save_wy;
 
   GList *other_objects = NULL;
   OBJECT *new_net = NULL;
@@ -713,8 +713,8 @@ int o_net_end(GSCHEM_TOPLEVEL *w_current, int x, int y)
     return FALSE;
   }
 
-  w_current->save_x = w_current->third_wx;
-  w_current->save_y = w_current->third_wy;
+  save_wx = w_current->third_wx;
+  save_wy = w_current->third_wy;
 
   if (toplevel->override_net_color == -1) {
     color = w_current->net_color;
@@ -722,6 +722,10 @@ int o_net_end(GSCHEM_TOPLEVEL *w_current, int x, int y)
     color = toplevel->override_net_color;
   }
 
+  if (w_current->third_wx != snap_grid(toplevel, w_current->third_wx)
+      || w_current->third_wy != snap_grid(toplevel, w_current->third_wy))
+      s_log_message(_("Warning: Ending net at off grid coordinate\n"));
+
   if (!primary_zero_length ) {
   /* create primary net */
       toplevel->page_current->object_tail =
@@ -775,8 +779,8 @@ int o_net_end(GSCHEM_TOPLEVEL *w_current, int x, int y)
       if (found_primary_connection)
       {
       	/* if a net connection is found, reset start point of next net */
-	w_current->save_x = w_current->second_wx;
-	w_current->save_y = w_current->second_wy;
+	save_wx = w_current->second_wx;
+	save_wy = w_current->second_wy;
       }
 
       /* you don't want to consolidate nets which are drawn non-ortho */
@@ -845,10 +849,8 @@ int o_net_end(GSCHEM_TOPLEVEL *w_current, int x, int y)
   }
 
   toplevel->page_current->CHANGED = 1;
-  w_current->first_wx = w_current->save_x;
-  w_current->first_wy = w_current->save_y;
-  if (w_current->net_direction_mode)
-    o_net_guess_direction(w_current, w_current->first_wx, w_current->first_wy);
+  w_current->first_wx = save_wx;
+  w_current->first_wy = save_wy;
   o_undo_savestate(w_current, UNDO_ALL);
 
   return (TRUE);
@@ -858,11 +860,9 @@ int o_net_end(GSCHEM_TOPLEVEL *w_current, int x, int y)
  *  \par Function Description
  *  This function draws the rubbernet lines when drawing a net.
  */
-void o_net_rubbernet(GSCHEM_TOPLEVEL *w_current, int x, int y)
+void o_net_rubbernet(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
 {
-  TOPLEVEL *toplevel = w_current->toplevel;
   int ortho, horizontal, quadrant;
-  int world_x, world_y;
 
   g_assert( w_current->inside_action != 0 );
 
@@ -872,25 +872,21 @@ void o_net_rubbernet(GSCHEM_TOPLEVEL *w_current, int x, int y)
 
   o_net_eraserubber(w_current);
 
-  SCREENtoWORLD(toplevel, x, y, &world_x, &world_y);
-  world_x = snap_grid(toplevel, world_x);
-  world_y = snap_grid(toplevel, world_y);
-
   if (w_current->magneticnet_mode) {
     if (w_current->CONTROLKEY) {
       /* set the magnetic marker position to current xy if the
 	 controlkey is pressed. Thus the net will not connect to 
 	 the closest net if we finish the net drawing */
-      w_current->magnetic_wx = world_x;
-      w_current->magnetic_wy = world_y;
+      w_current->magnetic_wx = w_x;
+      w_current->magnetic_wy = w_y;
     }
     else {
-      o_net_find_magnetic(w_current, x, y);
+      o_net_find_magnetic(w_current, w_x, w_y);
     }
   }
 
-  w_current->second_wx = world_x;
-  w_current->second_wy = world_y;
+  w_current->second_wx = w_x;
+  w_current->second_wy = w_y;
 
   /* In orthogonal mode secondary line is the same as the first */
   if (!ortho) {
@@ -914,10 +910,10 @@ void o_net_rubbernet(GSCHEM_TOPLEVEL *w_current, int x, int y)
     if ( horizontal ) {
       w_current->second_wy = w_current->first_wy;
       w_current->third_wx = w_current->second_wx;
-      w_current->third_wy = world_y;
+      w_current->third_wy = w_y;
     } else {
       w_current->second_wx = w_current->first_wx;
-      w_current->third_wx = world_x;
+      w_current->third_wx = w_x;
       w_current->third_wy = w_current->second_wy;
     }
   }
diff --git a/gschem/src/x_event.c b/gschem/src/x_event.c
index 83825b1..ca4c2c4 100644
--- a/gschem/src/x_event.c
+++ b/gschem/src/x_event.c
@@ -38,6 +38,7 @@
 /* used in key_press, since it isn't passed this information */
 /* filled in x_event_motion */
 int mouse_x, mouse_y;
+int mouse_wx, mouse_wy;
 
 /* used by mouse pan */
 extern int current_center_x, current_center_y;
@@ -126,6 +127,10 @@ gint x_event_button_pressed(GtkWidget *widget, GdkEventButton *event,
   w_current->CONTROLKEY = (event->state & GDK_CONTROL_MASK) ? 1 : 0;
   w_current->ALTKEY     = (event->state & GDK_MOD1_MASK) ? 1 : 0;
 
+  SCREENtoWORLD( toplevel, (int) event->x, (int) event->y, &w_x, &w_y );
+  w_x = snap_grid(toplevel, w_x);
+  w_y = snap_grid(toplevel, w_y);
+
   if (event->button == 1) {
     switch(w_current->event_state) {
 
@@ -282,9 +287,7 @@ gint x_event_button_pressed(GtkWidget *widget, GdkEventButton *event,
         break;
 
       case(STARTDRAWNET):  /*! \todo change state name? */
-        o_net_start(w_current,
-                    (int) event->x,
-                    (int) event->y);
+        o_net_start(w_current, w_x, w_y);
         w_current->inside_action = 1;
         w_current->event_state=DRAWNET;
 
@@ -302,8 +305,8 @@ gint x_event_button_pressed(GtkWidget *widget, GdkEventButton *event,
       case(DRAWNET):
       case(NETCONT):
         /* Only continue the net if net end worked */
-        if (o_net_end(w_current, (int) event->x,
-                      (int) event->y)) {
+        if (o_net_end(w_current, w_x, w_y)) {
+	  o_net_start(w_current, w_current->first_wx, w_current->first_wy);
           w_current->event_state=NETCONT;
         }
 	else { /* cleanup and start a new net */
@@ -359,14 +362,6 @@ gint x_event_button_pressed(GtkWidget *widget, GdkEventButton *event,
       case(ENDROTATEP):
         prev_state = toplevel->DONT_REDRAW;
         toplevel->DONT_REDRAW = 0;
-
-        SCREENtoWORLD( toplevel,
-                       (int) event->x,
-                       (int) event->y,
-                       &w_x, &w_y );
-        w_x = snap_grid(toplevel, w_x);
-        w_y = snap_grid(toplevel, w_y);
-
         o_rotate_world_update(w_current, w_x, w_y, 90,
           geda_list_get_glist(toplevel->page_current->selection_list ));
         toplevel->DONT_REDRAW = prev_state;
@@ -377,13 +372,6 @@ gint x_event_button_pressed(GtkWidget *widget, GdkEventButton *event,
         break;
 
       case(ENDMIRROR):
-        SCREENtoWORLD( toplevel,
-                       (int) event->x,
-                       (int) event->y,
-               &w_x, &w_y );
-        w_x = snap_grid(toplevel, w_x);
-        w_y = snap_grid(toplevel, w_y);
-
         o_mirror_world_update(w_current, w_x, w_y,
                               geda_list_get_glist(
                                 toplevel->page_current->selection_list ));
@@ -621,6 +609,10 @@ gint x_event_button_released(GtkWidget *widget, GdkEventButton *event,
   w_current->CONTROLKEY = (event->state & GDK_CONTROL_MASK) ? 1 : 0;
   w_current->ALTKEY     = (event->state & GDK_MOD1_MASK) ? 1 : 0;
 
+  SCREENtoWORLD( toplevel, (int) event->x, (int) event->y, &w_x, &w_y );
+  w_x = snap_grid(toplevel, w_x);
+  w_y = snap_grid(toplevel, w_y);
+
   if (event->button == 1) {
     switch(w_current->event_state) {
       case(SELECT):
@@ -769,11 +761,6 @@ gint x_event_button_released(GtkWidget *widget, GdkEventButton *event,
 	/* skip over head node */
 	redraw_state = toplevel->DONT_REDRAW;
 	toplevel->DONT_REDRAW = 1;
-        SCREENtoWORLD( toplevel,
-                       w_current->start_x, w_current->start_y,
-                       &w_x, &w_y );
-        w_x = snap_grid(toplevel, w_x);
-        w_y = snap_grid(toplevel, w_y);
         o_rotate_world_update(w_current, w_x, w_y, 90,
                               toplevel->page_current->complex_place_list );
 	toplevel->DONT_REDRAW = redraw_state;
@@ -891,6 +878,7 @@ gint x_event_motion(GtkWidget *widget, GdkEventMotion *event,
   TOPLEVEL *toplevel = w_current->toplevel;
   int temp_x, temp_y;
   int pdiff_x, pdiff_y;
+  int w_x, w_y;
 
   int zoom_scale;
   int diff_x; 
@@ -932,6 +920,12 @@ gint x_event_motion(GtkWidget *widget, GdkEventMotion *event,
       return 0;
   }
 
+  SCREENtoWORLD( toplevel, (int) event->x, (int) event->y, &w_x, &w_y );
+  w_x = snap_grid(toplevel, w_x);
+  w_y = snap_grid(toplevel, w_y);
+
+  mouse_wx = w_x;
+  mouse_wy = w_y;
   mouse_x = (int) event->x;
   mouse_y = (int) event->y;
 
@@ -1087,19 +1081,14 @@ gint x_event_motion(GtkWidget *widget, GdkEventMotion *event,
 
     case(STARTDRAWNET):
     if(w_current->magneticnet_mode == 1) {
-      o_net_start_magnetic(w_current,
-			   (int) event->x,
-			   (int) event->y);
+      o_net_start_magnetic(w_current, w_x, w_y);
     }
-
     break;
 
     case(DRAWNET):
     case(NETCONT):
     if (w_current->inside_action)
-    o_net_rubbernet(w_current,
-                    (int) event->x,
-                    (int) event->y);
+      o_net_rubbernet(w_current, w_x, w_y);
     break;
 
     case(DRAWBUS):

commit 3372a6ff3e99fb1d46c694b1d7bb7a586c9eebb9
Author: Werner Hoch <werner.ho@xxxxxx>
Date:   Tue Apr 1 13:50:07 2008 +0200

    removed redundant snap grid code in o_net.c

diff --git a/gschem/src/o_net.c b/gschem/src/o_net.c
index 67bea42..6fa6e4d 100644
--- a/gschem/src/o_net.c
+++ b/gschem/src/o_net.c
@@ -668,9 +668,6 @@ void o_net_start(GSCHEM_TOPLEVEL *w_current, int x, int y)
 int o_net_end(GSCHEM_TOPLEVEL *w_current, int x, int y)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
-  int x1, y1;
-  int x2, y2;
-  int x3, y3;
   int color;
   int size;
   int primary_zero_length, secondary_zero_length;
@@ -716,16 +713,6 @@ int o_net_end(GSCHEM_TOPLEVEL *w_current, int x, int y)
     return FALSE;
   }
 
-  /* Snap points to closest grid location */
-  /* Primary net runs from (x1,y1)-(x2,y2) */
-  /* Secondary net from (x2,y2)-(x3,y3) */
-  x1 = snap_grid(toplevel, w_current->first_wx);
-  y1 = snap_grid(toplevel, w_current->first_wy);
-  x2 = snap_grid(toplevel, w_current->second_wx);
-  y2 = snap_grid(toplevel, w_current->second_wy);
-  x3 = snap_grid(toplevel, w_current->third_wx);
-  y3 = snap_grid(toplevel, w_current->third_wy);
-
   w_current->save_x = w_current->third_wx;
   w_current->save_y = w_current->third_wy;
 
@@ -740,7 +727,9 @@ int o_net_end(GSCHEM_TOPLEVEL *w_current, int x, int y)
       toplevel->page_current->object_tail =
 	  new_net = o_net_add(toplevel,
 			      toplevel->page_current->object_tail,
-			      OBJ_NET, color, x1, y1, x2, y2);
+			      OBJ_NET, color, 
+			      w_current->first_wx, w_current->first_wy,
+			      w_current->second_wx, w_current->second_wy);
   
       /* conn stuff */
       /* LEAK CHECK 1 */
@@ -807,7 +796,9 @@ int o_net_end(GSCHEM_TOPLEVEL *w_current, int x, int y)
       toplevel->page_current->object_tail =
 	  new_net = o_net_add(toplevel,
 			      toplevel->page_current->object_tail,
-			      OBJ_NET, color, x2, y2, x3, y3);
+			      OBJ_NET, color, 
+			      w_current->second_wx, w_current->second_wy,
+			      w_current->third_wx, w_current->third_wy);
   
       /* conn stuff */
       /* LEAK CHECK 2 */

commit fadb2326204bb6375749653d1e8a3035462b3479
Author: Werner Hoch <werner.ho@xxxxxx>
Date:   Tue Apr 1 13:37:05 2008 +0200

    add world coordinates for the rubber lines, use them for net drawing
    
    This commit adds new variables to GSCHEM_TOPLEVEL. first_wx,
    second_wx, third_wx. They are intended to replace the screen
    coordinates start_x, last_x and last_y. Deployed that change in the
    net drawing code. This should finally fix Bug [#1928544].

diff --git a/gschem/include/gschem_struct.h b/gschem/include/gschem_struct.h
index eeb2040..d8d139c 100644
--- a/gschem/include/gschem_struct.h
+++ b/gschem/include/gschem_struct.h
@@ -93,8 +93,11 @@ struct st_gschem_toplevel {
   int last_y;
   int second_x;
   int second_y;
+  int first_wx, first_wy;
+  int second_wx, second_wy;
+  int third_wx, third_wy;
   int loc_x, loc_y;
-  int magnetic_x, magnetic_y;           /* Position of the magnetic marker*/
+  int magnetic_wx, magnetic_wy;         /* Position of the magnetic marker*/
   int distance;
   int inside_action;                    /* Are we doing an action? */
   int rotated_inside;                   /* Was the selection rotated
diff --git a/gschem/src/gschem_toplevel.c b/gschem/src/gschem_toplevel.c
index 78a8070..2726f7c 100644
--- a/gschem/src/gschem_toplevel.c
+++ b/gschem/src/gschem_toplevel.c
@@ -117,11 +117,14 @@ GSCHEM_TOPLEVEL *gschem_toplevel_new ()
   w_current->last_y = -1;
   w_current->second_x = -1;
   w_current->second_y = -1;
+  w_current->first_wx = w_current->first_wy = -1;
+  w_current->second_wx = w_current->second_wy = -1;
+  w_current->third_wx = w_current->third_wy = -1;
   w_current->loc_x = -1;
   w_current->loc_y = -1;
   w_current->distance = -1;
-  w_current->magnetic_x = -1;
-  w_current->magnetic_y = -1;
+  w_current->magnetic_wx = -1;
+  w_current->magnetic_wy = -1;
   w_current->inside_action = 0;
   w_current->rotated_inside = 0;
   w_current->rubbernet_visible = 0;
diff --git a/gschem/src/o_net.c b/gschem/src/o_net.c
index fcf1aab..67bea42 100644
--- a/gschem/src/o_net.c
+++ b/gschem/src/o_net.c
@@ -62,10 +62,10 @@
  */
 void o_net_reset(GSCHEM_TOPLEVEL *w_current) 
 {
-  w_current->start_x = w_current->start_y = -1;
-  w_current->last_x = w_current->last_y = -1;
-  w_current->second_x = w_current->second_y = -1;
-  w_current->magnetic_x = w_current->magnetic_y = -1;
+  w_current->first_wx = w_current->first_wy = -1;
+  w_current->second_wx = w_current->second_wy = -1;
+  w_current->third_wx = w_current->third_wy = -1;
+  w_current->magnetic_wx = w_current->magnetic_wy = -1;
   w_current->magnetic_visible = w_current->rubbernet_visible = 0;
 }
 
@@ -409,8 +409,8 @@ void o_net_guess_direction(GSCHEM_TOPLEVEL *w_current,
  *  and searches the closest connection point.
  *  It searches for pins, nets and busses.
  *  
- *  The connection point is stored in GSCHEM_TOPLEVEL->magnetic_x and
- *  GSCHEM_TOPLEVEL->magnetic_y. If no connection is found. Both variables
+ *  The connection point is stored in GSCHEM_TOPLEVEL->magnetic_wx and
+ *  GSCHEM_TOPLEVEL->magnetic_wy. If no connection is found. Both variables
  *  are set to -1.
  */
 void o_net_find_magnetic(GSCHEM_TOPLEVEL *w_current,
@@ -515,8 +515,8 @@ void o_net_find_magnetic(GSCHEM_TOPLEVEL *w_current,
 	minbest = mindist;
 	min_weight = weight;
 	o_magnetic = o_current;
-	w_current->magnetic_x = snap_grid(toplevel, min_x);
-	w_current->magnetic_y = snap_grid(toplevel, min_y);
+	w_current->magnetic_wx = snap_grid(toplevel, min_x);
+	w_current->magnetic_wy = snap_grid(toplevel, min_y);
       }
     }
   }
@@ -529,13 +529,13 @@ void o_net_find_magnetic(GSCHEM_TOPLEVEL *w_current,
     case (OBJ_BUS): magnetic_reach = MAGNETIC_BUS_REACH; break;
     }
     if (minbest > magnetic_reach*toplevel->page_current->to_world_x_constant) {
-      w_current->magnetic_x = -1;
-      w_current->magnetic_y = -1;
+      w_current->magnetic_wx = -1;
+      w_current->magnetic_wy = -1;
     }
   }
   else {
-    w_current->magnetic_x = -1;
-    w_current->magnetic_y = -1;
+    w_current->magnetic_wx = -1;
+    w_current->magnetic_wy = -1;
   }
 
   g_list_free(objectlists);
@@ -551,53 +551,53 @@ void o_net_finishmagnetic(GSCHEM_TOPLEVEL *w_current)
 {
   int primary_zero_length, secondary_zero_length;
 
-  primary_zero_length = ((w_current->start_x == w_current->last_x) 
-			 && (w_current->start_y == w_current->last_y));
+  primary_zero_length = ((w_current->first_wx == w_current->second_wx) 
+			 && (w_current->first_wy == w_current->second_wy));
  
-  secondary_zero_length = ((w_current->last_x == w_current->second_x) 
-			   && (w_current->last_y == w_current->second_y));
+  secondary_zero_length = ((w_current->second_wx == w_current->third_wx) 
+			   && (w_current->second_wy == w_current->third_wy));
 
   if (!primary_zero_length && secondary_zero_length) {
-    if (w_current->start_x == w_current->last_x) {
-      /* expand vertical line to magnetic_y */
-      w_current->last_y = w_current->magnetic_y;
+    if (w_current->first_wx == w_current->second_wx) {
+      /* expand vertical line to magnetic_wy */
+      w_current->second_wy = w_current->magnetic_wy;
     }
-    else if (w_current->start_y == w_current->last_y) {
-      /* expand horitontal line to vertical to magnetic_x */
-      w_current->last_x = w_current->magnetic_x;
+    else if (w_current->first_wy == w_current->second_wy) {
+      /* expand horitontal line to vertical to magnetic_wx */
+      w_current->second_wx = w_current->magnetic_wx;
     }
     /* connect to magnetic */
-    w_current->second_x = w_current->magnetic_x;
-    w_current->second_y = w_current->magnetic_y;
+    w_current->third_wx = w_current->magnetic_wx;
+    w_current->third_wy = w_current->magnetic_wy;
   }
 
   if (primary_zero_length && !secondary_zero_length) {
     /* move second line to the first (empty line) */
-    w_current->start_x = w_current->last_x;
-    w_current->start_y = w_current->last_y;
-    if (w_current->last_x == w_current->second_x) {
-      /* expand vertical line to magnetic_y */
-      w_current->last_y = w_current->magnetic_y;
+    w_current->first_wx = w_current->second_wx;
+    w_current->first_wy = w_current->second_wy;
+    if (w_current->second_wx == w_current->third_wx) {
+      /* expand vertical line to magnetic_wy */
+      w_current->second_wy = w_current->magnetic_wy;
     }
-    else if (w_current->last_y == w_current->second_y) {
-      /* expand horitontal line to magnetic_x */
-      w_current->last_x = w_current->magnetic_x;
+    else if (w_current->second_wy == w_current->third_wy) {
+      /* expand horitontal line to magnetic_wx */
+      w_current->second_wx = w_current->magnetic_wx;
     }
     /* connect to magnetic */
-    w_current->second_x = w_current->magnetic_x;
-    w_current->second_y = w_current->magnetic_y;
+    w_current->third_wx = w_current->magnetic_wx;
+    w_current->third_wy = w_current->magnetic_wy;
   }
 
   if (!primary_zero_length && !secondary_zero_length) {
     /* expand line in both directions */
-    if (w_current->start_x == w_current->last_x) {
-      w_current->last_y = w_current->magnetic_y;
+    if (w_current->first_wx == w_current->second_wx) {
+      w_current->second_wy = w_current->magnetic_wy;
     }
     else {
-      w_current->last_x = w_current->magnetic_x;
+      w_current->second_wx = w_current->magnetic_wx;
     }
-    w_current->second_x = w_current->magnetic_x;
-    w_current->second_y = w_current->magnetic_y;
+    w_current->third_wx = w_current->magnetic_wx;
+    w_current->third_wy = w_current->magnetic_wy;
   }
 }
 
@@ -616,9 +616,9 @@ void o_net_start_magnetic(GSCHEM_TOPLEVEL *w_current, int x, int y)
   w_current->inside_action = 0;
 
   if (w_current->CONTROLKEY) {
-    SCREENtoWORLD(toplevel, x, y, &w_current->magnetic_x, &w_current->magnetic_y);
-    w_current->magnetic_x = snap_grid(toplevel, w_current->magnetic_x);
-    w_current->magnetic_y = snap_grid(toplevel, w_current->magnetic_y);
+    SCREENtoWORLD(toplevel, x, y, &w_current->magnetic_wx, &w_current->magnetic_wy);
+    w_current->magnetic_wx = snap_grid(toplevel, w_current->magnetic_wx);
+    w_current->magnetic_wy = snap_grid(toplevel, w_current->magnetic_wy);
   }
   else {
     o_net_find_magnetic(w_current, x, y);
@@ -638,20 +638,20 @@ void o_net_start(GSCHEM_TOPLEVEL *w_current, int x, int y)
   TOPLEVEL *toplevel = w_current->toplevel;
 
   if (w_current->magnetic_visible) {
-    w_current->start_x = w_current->magnetic_x;
-    w_current->start_y = w_current->magnetic_y;
+    w_current->first_wx = w_current->magnetic_wx;
+    w_current->first_wy = w_current->magnetic_wy;
   }
   else {
-    SCREENtoWORLD(toplevel, x, y, &w_current->start_x, &w_current->start_y);
-    w_current->start_x = snap_grid(toplevel, w_current->start_x);
-    w_current->start_y = snap_grid(toplevel, w_current->start_y);
+    SCREENtoWORLD(toplevel, x, y, &w_current->first_wx, &w_current->first_wy);
+    w_current->first_wx = snap_grid(toplevel, w_current->first_wx);
+    w_current->first_wy = snap_grid(toplevel, w_current->first_wy);
   }
    
-  w_current->last_x = w_current->second_x = w_current->start_x;
-  w_current->last_y = w_current->second_y = w_current->start_y;
+  w_current->second_wx = w_current->third_wx = w_current->first_wx;
+  w_current->second_wy = w_current->third_wy = w_current->first_wy;
 
   if (w_current->net_direction_mode)
-    o_net_guess_direction(w_current, w_current->start_x, w_current->start_y);
+    o_net_guess_direction(w_current, w_current->first_wx, w_current->first_wy);
 }
 
 /*! \brief finish a net drawing action 
@@ -704,11 +704,11 @@ int o_net_end(GSCHEM_TOPLEVEL *w_current, int x, int y)
 
   /* See if either of the nets are zero length.  We'll only add */
   /* the non-zero ones */
-  primary_zero_length = (w_current->start_x == w_current->last_x) &&
-    (w_current->start_y == w_current->last_y);
+  primary_zero_length = (w_current->first_wx == w_current->second_wx) &&
+    (w_current->first_wy == w_current->second_wy);
  
-  secondary_zero_length = (w_current->last_x == w_current->second_x) &&
-      (w_current->last_y == w_current->second_y);
+  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 */
@@ -719,15 +719,15 @@ int o_net_end(GSCHEM_TOPLEVEL *w_current, int x, int y)
   /* Snap points to closest grid location */
   /* Primary net runs from (x1,y1)-(x2,y2) */
   /* Secondary net from (x2,y2)-(x3,y3) */
-  x1 = snap_grid(toplevel, w_current->start_x);
-  y1 = snap_grid(toplevel, w_current->start_y);
-  x2 = snap_grid(toplevel, w_current->last_x);
-  y2 = snap_grid(toplevel, w_current->last_y);
-  x3 = snap_grid(toplevel, w_current->second_x);
-  y3 = snap_grid(toplevel, w_current->second_y);
+  x1 = snap_grid(toplevel, w_current->first_wx);
+  y1 = snap_grid(toplevel, w_current->first_wy);
+  x2 = snap_grid(toplevel, w_current->second_wx);
+  y2 = snap_grid(toplevel, w_current->second_wy);
+  x3 = snap_grid(toplevel, w_current->third_wx);
+  y3 = snap_grid(toplevel, w_current->third_wy);
 
-  w_current->save_x = w_current->second_x;
-  w_current->save_y = w_current->second_y;
+  w_current->save_x = w_current->third_wx;
+  w_current->save_y = w_current->third_wy;
 
   if (toplevel->override_net_color == -1) {
     color = w_current->net_color;
@@ -786,8 +786,8 @@ int o_net_end(GSCHEM_TOPLEVEL *w_current, int x, int y)
       if (found_primary_connection)
       {
       	/* if a net connection is found, reset start point of next net */
-	w_current->save_x = w_current->last_x;
-	w_current->save_y = w_current->last_y;
+	w_current->save_x = w_current->second_wx;
+	w_current->save_y = w_current->second_wy;
       }
 
       /* you don't want to consolidate nets which are drawn non-ortho */
@@ -854,10 +854,10 @@ int o_net_end(GSCHEM_TOPLEVEL *w_current, int x, int y)
   }
 
   toplevel->page_current->CHANGED = 1;
-  w_current->start_x = w_current->save_x;
-  w_current->start_y = w_current->save_y;
+  w_current->first_wx = w_current->save_x;
+  w_current->first_wy = w_current->save_y;
   if (w_current->net_direction_mode)
-    o_net_guess_direction(w_current, w_current->start_x, w_current->start_y);
+    o_net_guess_direction(w_current, w_current->first_wx, w_current->first_wy);
   o_undo_savestate(w_current, UNDO_ALL);
 
   return (TRUE);
@@ -890,28 +890,28 @@ void o_net_rubbernet(GSCHEM_TOPLEVEL *w_current, int x, int y)
       /* set the magnetic marker position to current xy if the
 	 controlkey is pressed. Thus the net will not connect to 
 	 the closest net if we finish the net drawing */
-      w_current->magnetic_x = world_x;
-      w_current->magnetic_y = world_y;
+      w_current->magnetic_wx = world_x;
+      w_current->magnetic_wy = world_y;
     }
     else {
       o_net_find_magnetic(w_current, x, y);
     }
   }
 
-  w_current->last_x = world_x;
-  w_current->last_y = world_y;
+  w_current->second_wx = world_x;
+  w_current->second_wy = world_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->third_wx = w_current->second_wx;
+      w_current->third_wy = w_current->second_wy;
   }
   /* If you press the control key then you can draw non-ortho nets */
   else {
-    if (w_current->last_y > w_current->start_y) 
-      quadrant = w_current->last_x > w_current->start_x ? QUADRANT1: QUADRANT2;
+    if (w_current->second_wy > w_current->first_wy) 
+      quadrant = w_current->second_wx > w_current->first_wx ? QUADRANT1: QUADRANT2;
     else
-      quadrant = w_current->last_x > w_current->start_x ? QUADRANT4: QUADRANT3;
+      quadrant = w_current->second_wx > w_current->first_wx ? QUADRANT4: QUADRANT3;
 
     horizontal = w_current->net_direction & quadrant;
 
@@ -921,13 +921,13 @@ void o_net_rubbernet(GSCHEM_TOPLEVEL *w_current, int x, int y)
     /* calculate the co-ordinates necessary to draw the lines*/
     /* Pressing the shift key will cause the vertical and horizontal lines to switch places */
     if ( horizontal ) {
-      w_current->last_y = w_current->start_y;
-      w_current->second_x = w_current->last_x;
-      w_current->second_y = world_y;
+      w_current->second_wy = w_current->first_wy;
+      w_current->third_wx = w_current->second_wx;
+      w_current->third_wy = world_y;
     } else {
-      w_current->last_x = w_current->start_x;
-      w_current->second_x = world_x;
-      w_current->second_y = w_current->last_y;
+      w_current->second_wx = w_current->first_wx;
+      w_current->third_wx = world_x;
+      w_current->third_wy = w_current->second_wy;
     }
   }
 
@@ -943,16 +943,16 @@ void o_net_drawrubber(GSCHEM_TOPLEVEL *w_current)
   TOPLEVEL *toplevel = w_current->toplevel;
   int size=0, magnetic_halfsize;
   int magnetic_x, magnetic_y;
-  int start_x, start_y, second_x, second_y, last_x, last_y;
+  int first_x, first_y, third_x, third_y, second_x, second_y;
 
-  WORLDtoSCREEN(toplevel, w_current->magnetic_x, w_current->magnetic_y,
+  WORLDtoSCREEN(toplevel, w_current->magnetic_wx, w_current->magnetic_wy,
 		&magnetic_x, &magnetic_y);
-  WORLDtoSCREEN(toplevel, w_current->start_x, w_current->start_y,
-		&start_x, &start_y);
-  WORLDtoSCREEN(toplevel, w_current->second_x, w_current->second_y,
+  WORLDtoSCREEN(toplevel, w_current->first_wx, w_current->first_wy,
+		&first_x, &first_y);
+  WORLDtoSCREEN(toplevel, w_current->third_wx, w_current->third_wy,
+		&third_x, &third_y);
+  WORLDtoSCREEN(toplevel, w_current->second_wx, w_current->second_wy,
 		&second_x, &second_y);
-  WORLDtoSCREEN(toplevel, w_current->last_x, w_current->last_y,
-		&last_x, &last_y);
 
   w_current->rubbernet_visible = 1;
 
@@ -968,7 +968,7 @@ void o_net_drawrubber(GSCHEM_TOPLEVEL *w_current)
 			x_get_darkcolor(w_current->select_color));
 
   if (w_current->magneticnet_mode) {
-    if (w_current->magnetic_x != -1 && w_current->magnetic_y != -1) {
+    if (w_current->magnetic_wx != -1 && w_current->magnetic_wy != -1) {
       w_current->magnetic_visible = 1;
       w_current->inside_action = 1;
       magnetic_halfsize = max(4*size, MAGNETIC_HALFSIZE);
@@ -987,21 +987,21 @@ void o_net_drawrubber(GSCHEM_TOPLEVEL *w_current)
 
   /* draw primary line */
   gdk_draw_line(w_current->backingstore, w_current->xor_gc,
-		start_x, start_y, last_x, last_y);
+		first_x, first_y, second_x, second_y);
   o_invalidate_rect(w_current, 
-		    min(start_x, last_x) - size/2,
-		    min(start_y, last_y) - size/2,
-		    max(start_x, last_x) + size/2,
-		    max(start_y, last_y) + size/2);
+		    min(first_x, second_x) - size/2,
+		    min(first_y, second_y) - size/2,
+		    max(first_x, second_x) + size/2,
+		    max(first_y, second_y) + size/2);
 
   /* Draw secondary line */
   gdk_draw_line(w_current->backingstore, w_current->xor_gc,
-		last_x, last_y, second_x, second_y);
+		second_x, second_y, third_x, third_y);
   o_invalidate_rect(w_current, 
-		    min(last_x, second_x) - size/2,
-		    min(last_y, second_y) - size/2,
-		    max(last_x, second_x) + size/2,
-		    max(last_y, second_y) + size/2);
+		    min(second_x, third_x) - size/2,
+		    min(second_y, third_y) - size/2,
+		    max(second_x, third_x) + size/2,
+		    max(second_y, third_y) + size/2);
 
   if (toplevel->net_style == THICK) {
     gdk_gc_set_line_attributes(w_current->xor_gc, 0,
@@ -1023,19 +1023,19 @@ void o_net_eraserubber(GSCHEM_TOPLEVEL *w_current)
   TOPLEVEL *toplevel = w_current->toplevel;
   int size=0, magnetic_halfsize;
   int magnetic_x, magnetic_y;
-  int start_x, start_y, second_x, second_y, last_x, last_y;
+  int first_x, first_y, third_x, third_y, second_x, second_y;
 
   if (! w_current->rubbernet_visible)
     return;
 
-  WORLDtoSCREEN(toplevel, w_current->magnetic_x, w_current->magnetic_y,
+  WORLDtoSCREEN(toplevel, w_current->magnetic_wx, w_current->magnetic_wy,
 		&magnetic_x, &magnetic_y);
-  WORLDtoSCREEN(toplevel, w_current->start_x, w_current->start_y,
-		&start_x, &start_y);
-  WORLDtoSCREEN(toplevel, w_current->second_x, w_current->second_y,
+  WORLDtoSCREEN(toplevel, w_current->first_wx, w_current->first_wy,
+		&first_x, &first_y);
+  WORLDtoSCREEN(toplevel, w_current->third_wx, w_current->third_wy,
+		&third_x, &third_y);
+  WORLDtoSCREEN(toplevel, w_current->second_wx, w_current->second_wy,
 		&second_x, &second_y);
-  WORLDtoSCREEN(toplevel, w_current->last_x, w_current->last_y,
-		&last_x, &last_y);
 
   w_current->rubbernet_visible = 0;
 
@@ -1064,21 +1064,21 @@ void o_net_eraserubber(GSCHEM_TOPLEVEL *w_current)
 
   /* Erase primary primary rubber net line */
   gdk_draw_line(w_current->backingstore, w_current->xor_gc, 
-		start_x, start_y, last_x, last_y);
+		first_x, first_y, second_x, second_y);
   o_invalidate_rect(w_current, 
-		    min(start_x, last_x) - size/2,
-		    min(start_y, last_y) - size/2,
-		    max(start_x, last_x) + size/2,
-		    max(start_y, last_y) + size/2);
+		    min(first_x, second_x) - size/2,
+		    min(first_y, second_y) - size/2,
+		    max(first_x, second_x) + size/2,
+		    max(first_y, second_y) + size/2);
 
   /* Erase secondary rubber net line */
   gdk_draw_line(w_current->backingstore, w_current->xor_gc,
-		last_x, last_y, second_x, second_y);
+		second_x, second_y, third_x, third_y);
   o_invalidate_rect(w_current, 
-		    min(last_x, second_x) - size/2,
-		    min(last_y, second_y) - size/2,
-		    max(last_x, second_x) + size/2,
-		    max(last_y, second_y) + size/2);
+		    min(second_x, third_x) - size/2,
+		    min(second_y, third_y) - size/2,
+		    max(second_x, third_x) + size/2,
+		    max(second_y, third_y) + size/2);
 
   if (toplevel->net_style == THICK) {
     gdk_gc_set_line_attributes(w_current->xor_gc, 0,

commit 5f62a34fc821ced98f6faa7d4901ccd47e48380e
Author: Werner Hoch <werner.ho@xxxxxx>
Date:   Tue Apr 1 10:20:18 2008 +0200

    switched the net rubber code from screen to world coordinates
    
    Using screen coordinates for start_x, second_x and last_x causes
    integer arithmetic errors whenever the coordinates are converted between
    the screen an the world. The conversion occurs with the fix_x function
    and whenever the user zooms/pans in the drawing mode.
    This change fixes bug [#1928544] pointed out by Thomas Arndt.
    Note: This breaks the zooming and paning inside net drawing

diff --git a/gschem/src/o_net.c b/gschem/src/o_net.c
index 13db241..fcf1aab 100644
--- a/gschem/src/o_net.c
+++ b/gschem/src/o_net.c
@@ -292,11 +292,11 @@ void o_net_draw_xor_single(GSCHEM_TOPLEVEL *w_current, int dx, int dy, int which
  *  as a bitfield.
  */
 void o_net_guess_direction(GSCHEM_TOPLEVEL *w_current,
-			   int x, int y)
+			   int wx, int wy)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
   int up=0, down=0, left=0, right=0;
-  int x1, y1, x2, y2, wx, wy;
+  int x1, y1, x2, y2;
   int xmin, ymin, xmax, ymax;
   int orientation;
   GList *objectlists, *iter1, *iter2;
@@ -308,10 +308,6 @@ void o_net_guess_direction(GSCHEM_TOPLEVEL *w_current,
   const int bus_rules[] = {90, 0, 40};
   const int net_rules[] = {80, 30, 0};
   
-
-  SCREENtoWORLD(toplevel, x, y, &wx, &wy);
-  wx = snap_grid(toplevel, wx);
-  wy = snap_grid(toplevel, wy);
   objectlists = s_tile_get_objectlists(toplevel, wx, wy, wx, wy);
 
   for (iter1 = objectlists; iter1 != NULL; iter1 = g_list_next(iter1)) {
@@ -422,6 +418,7 @@ void o_net_find_magnetic(GSCHEM_TOPLEVEL *w_current,
 {
   TOPLEVEL *toplevel = w_current->toplevel;
   int x1, x2, y1, y2, min_x, min_y;
+  int world_x, world_y;
   double mindist, minbest, dist1, dist2;
   double weight, min_weight;
   int magnetic_reach = 0;
@@ -436,6 +433,8 @@ void o_net_find_magnetic(GSCHEM_TOPLEVEL *w_current,
   magnetic_reach = max(MAGNETIC_PIN_REACH, MAGNETIC_NET_REACH);
   magnetic_reach = max(magnetic_reach, MAGNETIC_BUS_REACH);
 
+  SCREENtoWORLD(toplevel, x, y, &world_x, &world_y);
+
   /* get the objects of the tiles around the reach region */
   SCREENtoWORLD(toplevel, x - magnetic_reach, y - magnetic_reach, &x1, &y1);
   SCREENtoWORLD(toplevel, x + magnetic_reach, y + magnetic_reach, &x2, &y2);
@@ -450,12 +449,11 @@ void o_net_find_magnetic(GSCHEM_TOPLEVEL *w_current,
 	continue; /* skip invisible objects */
 
       if (o_current->type == OBJ_PIN) {
-	WORLDtoSCREEN(toplevel,
-		      o_current->line->x[o_current->whichend],
-		      o_current->line->y[o_current->whichend],
-		      &min_x, &min_y);
-	mindist = sqrt((double) (x - min_x)*(x - min_x)
-		       + (double) (y - min_y)*(y - min_y));
+	min_x = o_current->line->x[o_current->whichend];
+	min_y = o_current->line->y[o_current->whichend];
+
+	mindist = sqrt((double) (world_x - min_x)*(world_x - min_x)
+		       + (double) (world_y - min_y)*(world_y - min_y));
 	weight = mindist / MAGNETIC_PIN_WEIGHT;
       }
 
@@ -463,15 +461,15 @@ void o_net_find_magnetic(GSCHEM_TOPLEVEL *w_current,
 	       || o_current->type == OBJ_BUS) {
 	/* we have 3 possible points to connect: 
 	   2 endpoints and 1 midpoint point */
-	WORLDtoSCREEN(toplevel, o_current->line->x[0], 
-		      o_current->line->y[0], &x1, &y1);
-	WORLDtoSCREEN(toplevel, o_current->line->x[1],
-		      o_current->line->y[1], &x2, &y2);
+	x1 = o_current->line->x[0];
+	y1 = o_current->line->y[0];
+	x2 = o_current->line->x[1];
+	y2 = o_current->line->y[1];
 	/* endpoint tests */
-	dist1 = sqrt((double) (x - x1)*(x - x1)
-		     + (double) (y - y1)*(y - y1));
-	dist2 = sqrt((double) (x - x2)*(x - x2)
-		     + (double) (y - y2)*(y - y2));
+	dist1 = sqrt((double) (world_x - x1)*(world_x - x1)
+		     + (double) (world_y - y1)*(world_y - y1));
+	dist2 = sqrt((double) (world_x - x2)*(world_x - x2)
+		     + (double) (world_y - y2)*(world_y - y2));
 	if (dist1 < dist2) {
 	  min_x = x1;
 	  min_y = y1;
@@ -485,20 +483,20 @@ void o_net_find_magnetic(GSCHEM_TOPLEVEL *w_current,
       
 	/* midpoint tests */
 	if ((x1 == x2)  /* vertical net */
-	    && ((y1 >= y && y >= y2)
-		|| (y2 >= y && y >= y1))) {
-	  if (abs(x - x1) < mindist) {
-	    mindist = abs(x - x1);
+	    && ((y1 >= world_y && world_y >= y2)
+		|| (y2 >= world_y && world_y >= y1))) {
+	  if (abs(world_x - x1) < mindist) {
+	    mindist = abs(world_x - x1);
 	    min_x = x1;
-	    min_y = y;
+	    min_y = world_y;
 	  }
 	} 
 	if ((y1 == y2)  /* horitontal net */
-	    && ((x1 >= x && x >= x2)
-		|| (x2 >= x && x >= x1))) {  
-	  if (abs(y - y1) < mindist) {
-	    mindist = abs(y - y1);
-	    min_x = x;
+	    && ((x1 >= world_x && world_x >= x2)
+		|| (x2 >= world_x && world_x >= x1))) {  
+	  if (abs(world_y - y1) < mindist) {
+	    mindist = abs(world_y - y1);
+	    min_x = world_x;
 	    min_y = y1;
 	  }
 	}
@@ -517,8 +515,8 @@ void o_net_find_magnetic(GSCHEM_TOPLEVEL *w_current,
 	minbest = mindist;
 	min_weight = weight;
 	o_magnetic = o_current;
-	w_current->magnetic_x = min_x;
-	w_current->magnetic_y = min_y;
+	w_current->magnetic_x = snap_grid(toplevel, min_x);
+	w_current->magnetic_y = snap_grid(toplevel, min_y);
       }
     }
   }
@@ -530,7 +528,7 @@ void o_net_find_magnetic(GSCHEM_TOPLEVEL *w_current,
     case (OBJ_NET): magnetic_reach = MAGNETIC_NET_REACH; break;
     case (OBJ_BUS): magnetic_reach = MAGNETIC_BUS_REACH; break;
     }
-    if (minbest > magnetic_reach) {
+    if (minbest > magnetic_reach*toplevel->page_current->to_world_x_constant) {
       w_current->magnetic_x = -1;
       w_current->magnetic_y = -1;
     }
@@ -611,13 +609,16 @@ void o_net_finishmagnetic(GSCHEM_TOPLEVEL *w_current)
  */
 void o_net_start_magnetic(GSCHEM_TOPLEVEL *w_current, int x, int y)
 {
+  TOPLEVEL *toplevel = w_current->toplevel;
+
   o_net_eraserubber(w_current);
   /* the dc is completely clean now, reset inside_action. */
   w_current->inside_action = 0;
 
   if (w_current->CONTROLKEY) {
-    w_current->magnetic_x = x;
-    w_current->magnetic_y = y;
+    SCREENtoWORLD(toplevel, x, y, &w_current->magnetic_x, &w_current->magnetic_y);
+    w_current->magnetic_x = snap_grid(toplevel, w_current->magnetic_x);
+    w_current->magnetic_y = snap_grid(toplevel, w_current->magnetic_y);
   }
   else {
     o_net_find_magnetic(w_current, x, y);
@@ -637,17 +638,20 @@ void o_net_start(GSCHEM_TOPLEVEL *w_current, int x, int y)
   TOPLEVEL *toplevel = w_current->toplevel;
 
   if (w_current->magnetic_visible) {
-    x = w_current->magnetic_x;
-    y = w_current->magnetic_y;
+    w_current->start_x = w_current->magnetic_x;
+    w_current->start_y = w_current->magnetic_y;
   }
-
-  w_current->last_x = w_current->start_x = w_current->second_x = 
-    fix_x(toplevel, x);
-  w_current->last_y = w_current->start_y = w_current->second_y = 
-    fix_y(toplevel, y);
+  else {
+    SCREENtoWORLD(toplevel, x, y, &w_current->start_x, &w_current->start_y);
+    w_current->start_x = snap_grid(toplevel, w_current->start_x);
+    w_current->start_y = snap_grid(toplevel, w_current->start_y);
+  }
+   
+  w_current->last_x = w_current->second_x = w_current->start_x;
+  w_current->last_y = w_current->second_y = w_current->start_y;
 
   if (w_current->net_direction_mode)
-    o_net_guess_direction(w_current, x, y);
+    o_net_guess_direction(w_current, w_current->start_x, w_current->start_y);
 }
 
 /*! \brief finish a net drawing action 
@@ -701,7 +705,7 @@ int o_net_end(GSCHEM_TOPLEVEL *w_current, int x, int y)
   /* See if either of the nets are zero length.  We'll only add */
   /* the non-zero ones */
   primary_zero_length = (w_current->start_x == w_current->last_x) &&
-      (w_current->start_y == w_current->last_y);
+    (w_current->start_y == w_current->last_y);
  
   secondary_zero_length = (w_current->last_x == w_current->second_x) &&
       (w_current->last_y == w_current->second_y);
@@ -712,19 +716,15 @@ int o_net_end(GSCHEM_TOPLEVEL *w_current, int x, int y)
     return FALSE;
   }
 
+  /* Snap points to closest grid location */
   /* Primary net runs from (x1,y1)-(x2,y2) */
   /* Secondary net from (x2,y2)-(x3,y3) */
-  SCREENtoWORLD(toplevel, w_current->start_x, w_current->start_y, &x1,	&y1);
-  SCREENtoWORLD(toplevel, w_current->last_x, w_current->last_y, &x2, &y2);
-  SCREENtoWORLD(toplevel, w_current->second_x, w_current->second_y, &x3, &y3);
-
-  /* Snap points to closest grid location */
-  x1 = snap_grid(toplevel, x1);
-  y1 = snap_grid(toplevel, y1);
-  x2 = snap_grid(toplevel, x2);
-  y2 = snap_grid(toplevel, y2);
-  x3 = snap_grid(toplevel, x3);
-  y3 = snap_grid(toplevel, y3);
+  x1 = snap_grid(toplevel, w_current->start_x);
+  y1 = snap_grid(toplevel, w_current->start_y);
+  x2 = snap_grid(toplevel, w_current->last_x);
+  y2 = snap_grid(toplevel, w_current->last_y);
+  x3 = snap_grid(toplevel, w_current->second_x);
+  y3 = snap_grid(toplevel, w_current->second_y);
 
   w_current->save_x = w_current->second_x;
   w_current->save_y = w_current->second_y;
@@ -856,6 +856,8 @@ int o_net_end(GSCHEM_TOPLEVEL *w_current, int x, int y)
   toplevel->page_current->CHANGED = 1;
   w_current->start_x = w_current->save_x;
   w_current->start_y = w_current->save_y;
+  if (w_current->net_direction_mode)
+    o_net_guess_direction(w_current, w_current->start_x, w_current->start_y);
   o_undo_savestate(w_current, UNDO_ALL);
 
   return (TRUE);
@@ -869,6 +871,7 @@ void o_net_rubbernet(GSCHEM_TOPLEVEL *w_current, int x, int y)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
   int ortho, horizontal, quadrant;
+  int world_x, world_y;
 
   g_assert( w_current->inside_action != 0 );
 
@@ -878,21 +881,25 @@ void o_net_rubbernet(GSCHEM_TOPLEVEL *w_current, int x, int y)
 
   o_net_eraserubber(w_current);
 
+  SCREENtoWORLD(toplevel, x, y, &world_x, &world_y);
+  world_x = snap_grid(toplevel, world_x);
+  world_y = snap_grid(toplevel, world_y);
+
   if (w_current->magneticnet_mode) {
     if (w_current->CONTROLKEY) {
       /* set the magnetic marker position to current xy if the
 	 controlkey is pressed. Thus the net will not connect to 
 	 the closest net if we finish the net drawing */
-      w_current->magnetic_x = x;
-      w_current->magnetic_y = y;
+      w_current->magnetic_x = world_x;
+      w_current->magnetic_y = world_y;
     }
     else {
       o_net_find_magnetic(w_current, x, y);
     }
   }
 
-  w_current->last_x = fix_x(toplevel, x);
-  w_current->last_y = fix_y(toplevel, y);
+  w_current->last_x = world_x;
+  w_current->last_y = world_y;
 
   /* In orthogonal mode secondary line is the same as the first */
   if (!ortho) {
@@ -901,7 +908,7 @@ void o_net_rubbernet(GSCHEM_TOPLEVEL *w_current, int x, int y)
   }
   /* If you press the control key then you can draw non-ortho nets */
   else {
-    if (w_current->last_y < w_current->start_y) 
+    if (w_current->last_y > w_current->start_y) 
       quadrant = w_current->last_x > w_current->start_x ? QUADRANT1: QUADRANT2;
     else
       quadrant = w_current->last_x > w_current->start_x ? QUADRANT4: QUADRANT3;
@@ -916,10 +923,10 @@ void o_net_rubbernet(GSCHEM_TOPLEVEL *w_current, int x, int y)
     if ( horizontal ) {
       w_current->last_y = w_current->start_y;
       w_current->second_x = w_current->last_x;
-      w_current->second_y = fix_y(toplevel,y);
+      w_current->second_y = world_y;
     } else {
       w_current->last_x = w_current->start_x;
-      w_current->second_x = fix_x(toplevel,x);
+      w_current->second_x = world_x;
       w_current->second_y = w_current->last_y;
     }
   }
@@ -935,6 +942,17 @@ void o_net_drawrubber(GSCHEM_TOPLEVEL *w_current)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
   int size=0, magnetic_halfsize;
+  int magnetic_x, magnetic_y;
+  int start_x, start_y, second_x, second_y, last_x, last_y;
+
+  WORLDtoSCREEN(toplevel, w_current->magnetic_x, w_current->magnetic_y,
+		&magnetic_x, &magnetic_y);
+  WORLDtoSCREEN(toplevel, w_current->start_x, w_current->start_y,
+		&start_x, &start_y);
+  WORLDtoSCREEN(toplevel, w_current->second_x, w_current->second_y,
+		&second_x, &second_y);
+  WORLDtoSCREEN(toplevel, w_current->last_x, w_current->last_y,
+		&last_x, &last_y);
 
   w_current->rubbernet_visible = 1;
 
@@ -951,43 +969,39 @@ void o_net_drawrubber(GSCHEM_TOPLEVEL *w_current)
 
   if (w_current->magneticnet_mode) {
     if (w_current->magnetic_x != -1 && w_current->magnetic_y != -1) {
-      w_current->magnetic_x = fix_x(toplevel, w_current->magnetic_x);
-      w_current->magnetic_y = fix_y(toplevel, w_current->magnetic_y);
       w_current->magnetic_visible = 1;
       w_current->inside_action = 1;
       magnetic_halfsize = max(4*size, MAGNETIC_HALFSIZE);
       gdk_draw_arc(w_current->backingstore, w_current->xor_gc, FALSE,
-		   w_current->magnetic_x - magnetic_halfsize,
-		   w_current->magnetic_y - magnetic_halfsize,
+		   magnetic_x - magnetic_halfsize,
+		   magnetic_y - magnetic_halfsize,
 		   2*magnetic_halfsize, 2*magnetic_halfsize,
 		   0, FULL_CIRCLE);
       o_invalidate_rect(w_current, 
-			w_current->magnetic_x - magnetic_halfsize - size/2,
-			w_current->magnetic_y - magnetic_halfsize - size/2,
-			w_current->magnetic_x + magnetic_halfsize + size/2,
-			w_current->magnetic_y + magnetic_halfsize + size/2);
+			magnetic_x - magnetic_halfsize - size/2,
+			magnetic_y - magnetic_halfsize - size/2,
+			magnetic_x + magnetic_halfsize + size/2,
+			magnetic_y + magnetic_halfsize + size/2);
     }
   }
 
   /* draw primary line */
   gdk_draw_line(w_current->backingstore, w_current->xor_gc,
-		w_current->start_x, w_current->start_y,
-		w_current->last_x, w_current->last_y);
+		start_x, start_y, last_x, last_y);
   o_invalidate_rect(w_current, 
-		    min(w_current->start_x, w_current->last_x) - size/2,
-		    min(w_current->start_y, w_current->last_y) - size/2,
-		    max(w_current->start_x, w_current->last_x) + size/2,
-		    max(w_current->start_y, w_current->last_y) + size/2);
+		    min(start_x, last_x) - size/2,
+		    min(start_y, last_y) - size/2,
+		    max(start_x, last_x) + size/2,
+		    max(start_y, last_y) + size/2);
 
   /* Draw secondary line */
   gdk_draw_line(w_current->backingstore, w_current->xor_gc,
-		w_current->last_x, w_current->last_y,
-		w_current->second_x, w_current->second_y);
+		last_x, last_y, second_x, second_y);
   o_invalidate_rect(w_current, 
-		    min(w_current->last_x, w_current->second_x) - size/2,
-		    min(w_current->last_y, w_current->second_y) - size/2,
-		    max(w_current->last_x, w_current->second_x) + size/2,
-		    max(w_current->last_y, w_current->second_y) + size/2);
+		    min(last_x, second_x) - size/2,
+		    min(last_y, second_y) - size/2,
+		    max(last_x, second_x) + size/2,
+		    max(last_y, second_y) + size/2);
 
   if (toplevel->net_style == THICK) {
     gdk_gc_set_line_attributes(w_current->xor_gc, 0,
@@ -1008,10 +1022,21 @@ void o_net_eraserubber(GSCHEM_TOPLEVEL *w_current)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
   int size=0, magnetic_halfsize;
+  int magnetic_x, magnetic_y;
+  int start_x, start_y, second_x, second_y, last_x, last_y;
 
   if (! w_current->rubbernet_visible)
     return;
 
+  WORLDtoSCREEN(toplevel, w_current->magnetic_x, w_current->magnetic_y,
+		&magnetic_x, &magnetic_y);
+  WORLDtoSCREEN(toplevel, w_current->start_x, w_current->start_y,
+		&start_x, &start_y);
+  WORLDtoSCREEN(toplevel, w_current->second_x, w_current->second_y,
+		&second_x, &second_y);
+  WORLDtoSCREEN(toplevel, w_current->last_x, w_current->last_y,
+		&last_x, &last_y);
+
   w_current->rubbernet_visible = 0;
 
   if (toplevel->net_style == THICK) {
@@ -1026,35 +1051,34 @@ void o_net_eraserubber(GSCHEM_TOPLEVEL *w_current)
     w_current->magnetic_visible = 0;
     magnetic_halfsize = max(4*size, MAGNETIC_HALFSIZE);
     gdk_draw_arc(w_current->backingstore, w_current->xor_gc, FALSE,
-		 w_current->magnetic_x - magnetic_halfsize,
-		 w_current->magnetic_y - magnetic_halfsize,
+		 magnetic_x - magnetic_halfsize,
+		 magnetic_y - magnetic_halfsize,
 		 2*magnetic_halfsize, 2*magnetic_halfsize,
 		 0, FULL_CIRCLE);
       o_invalidate_rect(w_current, 
-			w_current->magnetic_x - magnetic_halfsize - size/2,
-			w_current->magnetic_y - magnetic_halfsize - size/2,
-			w_current->magnetic_x + magnetic_halfsize + size/2,
-			w_current->magnetic_y + magnetic_halfsize + size/2);
+			magnetic_x - magnetic_halfsize - size/2,
+			magnetic_y - magnetic_halfsize - size/2,
+			magnetic_x + magnetic_halfsize + size/2,
+			magnetic_y + magnetic_halfsize + size/2);
   }
 
   /* Erase primary primary rubber net line */
-  gdk_draw_line(w_current->backingstore, w_current->xor_gc, w_current->start_x,
-		w_current->start_y, w_current->last_x, w_current->last_y);
+  gdk_draw_line(w_current->backingstore, w_current->xor_gc, 
+		start_x, start_y, last_x, last_y);
   o_invalidate_rect(w_current, 
-		    min(w_current->start_x, w_current->last_x) - size/2,
-		    min(w_current->start_y, w_current->last_y) - size/2,
-		    max(w_current->start_x, w_current->last_x) + size/2,
-		    max(w_current->start_y, w_current->last_y) + size/2);
+		    min(start_x, last_x) - size/2,
+		    min(start_y, last_y) - size/2,
+		    max(start_x, last_x) + size/2,
+		    max(start_y, last_y) + size/2);
 
   /* Erase secondary rubber net line */
   gdk_draw_line(w_current->backingstore, w_current->xor_gc,
-		w_current->last_x, w_current->last_y,
-		w_current->second_x, w_current->second_y);
+		last_x, last_y, second_x, second_y);
   o_invalidate_rect(w_current, 
-		    min(w_current->last_x, w_current->second_x) - size/2,
-		    min(w_current->last_y, w_current->second_y) - size/2,
-		    max(w_current->last_x, w_current->second_x) + size/2,
-		    max(w_current->last_y, w_current->second_y) + size/2);
+		    min(last_x, second_x) - size/2,
+		    min(last_y, second_y) - size/2,
+		    max(last_x, second_x) + size/2,
+		    max(last_y, second_y) + size/2);
 
   if (toplevel->net_style == THICK) {
     gdk_gc_set_line_attributes(w_current->xor_gc, 0,
diff --git a/gschem/src/x_event.c b/gschem/src/x_event.c
index 61cc1b2..83825b1 100644
--- a/gschem/src/x_event.c
+++ b/gschem/src/x_event.c
@@ -304,9 +304,6 @@ gint x_event_button_pressed(GtkWidget *widget, GdkEventButton *event,
         /* Only continue the net if net end worked */
         if (o_net_end(w_current, (int) event->x,
                       (int) event->y)) {
-          o_net_start(w_current,
-                      (int) w_current->save_x,
-                      (int) w_current->save_y);
           w_current->event_state=NETCONT;
         }
 	else { /* cleanup and start a new net */




_______________________________________________
geda-cvs mailing list
geda-cvs@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-cvs