delorie.com/archives/browse.cgi   search  
Mail Archives: geda-user/2015/10/14/20:41:27

X-Authentication-Warning: delorie.com: mail set sender to geda-user-bounces using -f
X-Recipient: geda-user AT delorie DOT com
To: geda-user AT delorie DOT com
From: Robert Drehmel <robert AT zoot DOT drehmel DOT com>
Subject: [geda-user] Highlighting traces
Message-ID: <561EF5FE.9070706@zoot.drehmel.com>
Date: Thu, 15 Oct 2015 02:40:30 +0200
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101
Thunderbird/38.3.0
MIME-Version: 1.0
X-Provags-ID: V03:K0:++lb+GGUy/yIEGWWmNENwSmA4HT4JWTNHjkl/s6ddQigRAjZTvf
dX71OnrHAmhfckknnP1mFEwXcqJV3Jn3HNtEnUsDzYODR66Y017UIdR0VkJcEsktFFJ/GqQ
6fA7VIFmrC9DHFGofub/HNdb0NNWlm8DynqdAEYlzpp8a3KspVjoDLVmakbXStTSRcO4kAc
db3fFWI97mk+Q1z5q1WLA==
X-UI-Out-Filterresults: notjunk:1;V01:K0:+mPnuF2xCzs=:URUZij8K6KVgItFG419H0Q
Vv06PPImvSbK4/H6pFUJ5J1GnvC4hxPicY0KmeC7viMI0SPhNh6Flu+ZdeBh0fnjsYovy/5He
cDXFmzw7CyLeCj0av8OmI+qABYCIQ94ocWXjXzTta2/VI7wkR5U0gTr6174Wik1zUKyu1Wo1e
nalYsZkghoviBX4XT6Ula0rZWDA5PlFZ6/irv/PsMAG2qYmqTDXNa2/HFCVefdfZOtyyWou59
Y2ubez6dSk8lun7qUUQvvF0PmtdzzzGTT+o7ArcPPeI2NoKccpyunUCl2htSmcMvlgE0Xo8r4
K2FKoUuK105O92pTYY0aU1NLfOlOEPb8fmx/8O9txFy9CmRkEx5Z5ol3tjoHYtqArwlH1YyDk
eUlyOa0mvtJLsQtbzTqTEYQlYGJqattLuV8E6c8K0ezJZWtRKqScQkiMzqBfiU+uw8IzG++Cv
YJ/i5edOQOt5kJdOhUXvjyQwZkJjvoKBrGXUnVtmokqDjBVJI0DzZ2lbCwvyDneT8lj/0AyjV
sTN4ySa8R1hKLyPKFINv7sY7cfT0y3jfb1Cx57T6lHm83gPTwrC37MujuB5sC5Fc8dU7ORN2H
QZ7N4bwuVuGo8sqSzepf3mshkpht/E2VtqsuPZtDh0sYtxsVvlrU6eJzDbYZzL1Tp8YkLFFBc
0BMV97O7BTg5wyVcxz81bJL98k+fs5cFTdzVqSdAQOmvDDFIYV9q9TAKypiux9ZPN3CA=
Reply-To: geda-user AT delorie DOT com

This is a multi-part message in MIME format.
--------------000708030003070003020603
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit

Hi.

When (e.g.) routing 5mm power traces on a small grid, it's not always easy to hit the
point where the trace ended (which is the center of the semicircle at the end of the
line) to start the next line.  If you have selected the line tool, finding the end of
the line can become guesswork as the cursor doesn't change shape like it does with the
select tool.
I want my traces to consist of lines and arcs that are perfectly connected and I want
to work as fast as possible.

Attached is a small patch that

  - makes it possible to deactivate snapping to "some sensible point along a line".
    (that's what a comment in the code says). This snapping algorithm gets in the way
    sometimes so you have to slowly go over a line to find out where it really ends,
    bouncing back and forth between the points of the small grid, the end of the line
    and these "sensible points", which is wasting time. The command is
    "Display(ToggleSnapOffGridLine)". It is still activated by default to avoid
    violating POLA.

  - more importantly, introduces a new command called "Display(ToggleHighlightOnPoint)"
    that highlights all lines and arcs which have (end)points exactly on the position
    where the cross hair is currently snapped to. It therefore helps finding the end
    points of lines and arcs, but sometimes also shows redundant traces, traces that
    aren't perfectly connected to each other, traces that don't end directly on the
    center of a via but should, etc. It works with thin draw too and I tested it with
    gtk and lesstif.

I use the second option mostly in conjunction with deactivating the first. Both commands
have been added to the menu by means of (g)pcb-menu.res.in and are available as command
line options as well.
Caveats:
  - The HID API expects all HIDs to make a copy of the color string when setting a color.
  - The function that lightens up a color could be improved.
  - I used it for a while, but after porting it from my local fork, it probably needs
    more testing.

Maybe someone else finds it useful.

Best regards,
Robert

--------------000708030003070003020603
Content-Type: text/x-patch;
 name="pcb-onpoint.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="pcb-onpoint.diff"

diff --git a/src/action.c b/src/action.c
index 0be31ab..fd21d0e 100644
--- a/src/action.c
+++ b/src/action.c
@@ -198,6 +198,8 @@ typedef enum
   F_ToggleRubberBandMode,
   F_ToggleStartDirection,
   F_ToggleSnapPin,
+  F_ToggleSnapOffGridLine,
+  F_ToggleHighlightOnPoint,
   F_ToggleThindraw,
   F_ToggleLockNames,
   F_ToggleOnlyNames,
@@ -429,6 +431,8 @@ static FunctionType Functions[] = {
   {"ToggleRubberBandMode", F_ToggleRubberBandMode},
   {"ToggleStartDirection", F_ToggleStartDirection},
   {"ToggleSnapPin", F_ToggleSnapPin},
+  {"ToggleSnapOffGridLine", F_ToggleSnapOffGridLine},
+  {"ToggleHighlightOnPoint", F_ToggleHighlightOnPoint},
   {"ToggleThindraw", F_ToggleThindraw},
   {"ToggleThindrawPoly", F_ToggleThindrawPoly},
   {"ToggleLockNames", F_ToggleLockNames},
@@ -2492,7 +2496,8 @@ static const char display_syntax[] =
   "Display(Grid|Redraw)\n"
   "Display(CycleClip|CycleCrosshair|Toggle45Degree|ToggleStartDirection)\n"
   "Display(ToggleGrid|ToggleRubberBandMode|ToggleUniqueNames)\n"
-  "Display(ToggleMask|ToggleName|ToggleClearLine|ToggleFullPoly|ToggleSnapPin)\n"
+  "Display(ToggleMask|ToggleName|ToggleClearLine|ToggleFullPoly)\n"
+  "Display(ToggleSnapPin|ToggleSnapOffGridLine|ToggleHighlightOnPoint)\n"
   "Display(ToggleThindraw|ToggleThindrawPoly|ToggleOrthoMove|ToggleLocalRef)\n"
   "Display(ToggleCheckPlanes|ToggleShowDRC|ToggleAutoDRC)\n"
   "Display(ToggleLiveRoute|LockNames|OnlyNames)\n"
@@ -2541,6 +2546,13 @@ match that of another element.
 If set, pin centers and pad end points are treated as additional grid
 points that the cursor can snap to.
 
+@item ToggleSnapOffGridLine
+If set, snap at some sensible point along a line.
+
+@item ToggleHighlightOnPoint
+If set, highlights lines and arcs when the crosshair is on one of their
+two (end) points.
+
 @item ToggleLocalRef
 If set, the mark is automatically set to the beginning of any move, so
 you can see the relative distance you've moved.
@@ -2742,6 +2754,18 @@ ActionDisplay (int argc, char **argv, Coord childX, Coord childY)
 	  notify_crosshair_change (true);
 	  break;
 
+        case F_ToggleSnapOffGridLine:
+          notify_crosshair_change (false);
+	  TOGGLE_FLAG (SNAPOFFGRIDLINEFLAG, PCB);
+	  notify_crosshair_change (true);
+          break;
+
+        case F_ToggleHighlightOnPoint:
+          notify_crosshair_change (false);
+	  TOGGLE_FLAG (HIGHLIGHTONPOINTFLAG, PCB);
+	  notify_crosshair_change (true);
+          break;
+
 	case F_ToggleLocalRef:
 	  TOGGLE_FLAG (LOCALREFFLAG, PCB);
 	  break;
diff --git a/src/const.h b/src/const.h
index 3798251..d341854 100644
--- a/src/const.h
+++ b/src/const.h
@@ -268,9 +268,9 @@ If set, this object has been as physically connected by @code{FindConnection()}.
                                              also pinout text for pins is vertical */
 #define VISITFLAG               0x8000  /*!< marker to avoid re-visiting an object */
 #define CONNECTEDFLAG          0x10000  /*!< flag like FOUND flag, but used to identify physically connected objects (not rats) */
+#define ONPOINTFLAG            0x20000  /*!< crosshair is on line point or arc point */
 
-
-#define NOCOPY_FLAGS (FOUNDFLAG | CONNECTEDFLAG)
+#define NOCOPY_FLAGS (FOUNDFLAG | CONNECTEDFLAG | ONPOINTFLAG)
 
 /* ---------------------------------------------------------------------------
  * PCB flags
@@ -327,10 +327,14 @@ Everything but names are locked, the mouse cannot select anything else.
 New polygons are full polygons.
 @item 0x200000
 When set, element names are not drawn.
+@item 0x400000
+snap to certain off-grid points.
+@item 0x800000
+highlight lines and arcs when the crosshair is on one of their endpoints.
 @end table
 %end-doc */
 
-#define	PCB_FLAGS		0x000fffff	/* all used flags */
+#define	PCB_FLAGS		0x00ffffff	/* all used flags */
 
 #define SHOWNUMBERFLAG          0x00000001
 #define LOCALREFFLAG            0x00000002
@@ -354,6 +358,8 @@ When set, element names are not drawn.
 #define ONLYNAMESFLAG           0x00080000
 #define NEWFULLPOLYFLAG         0x00100000
 #define HIDENAMESFLAG           0x00200000
+#define SNAPOFFGRIDLINEFLAG     0x00400000
+#define HIGHLIGHTONPOINTFLAG    0x00800000
 
 /* ---------------------------------------------------------------------------
  * object types
diff --git a/src/create.c b/src/create.c
index 5907a1f..8039a9c 100644
--- a/src/create.c
+++ b/src/create.c
@@ -177,6 +177,10 @@ CreateNewPCB (void)
     SET_FLAG (UNIQUENAMEFLAG, ptr);
   if (Settings.SnapPin)
     SET_FLAG (SNAPPINFLAG, ptr);
+  if (Settings.SnapOffGridLine)
+    SET_FLAG (SNAPOFFGRIDLINEFLAG, ptr);
+  if (Settings.HighlightOnPoint)
+    SET_FLAG (HIGHLIGHTONPOINTFLAG, ptr);
   if (Settings.ClearLine)
     SET_FLAG (CLEARNEWFLAG, ptr);
   if (Settings.FullPoly)
diff --git a/src/crosshair.c b/src/crosshair.c
index fb2ceca..bb7bd1d 100644
--- a/src/crosshair.c
+++ b/src/crosshair.c
@@ -36,10 +36,12 @@
 
 #include <memory.h>
 #include <math.h>
+#include <glib.h>
 
 #include "global.h"
 #include "hid_draw.h"
 
+#include "box.h"
 #include "crosshair.h"
 #include "data.h"
 #include "draw.h"
@@ -47,6 +49,7 @@
 #include "line.h"
 #include "misc.h"
 #include "mymem.h"
+#include "rtree.h"
 #include "search.h"
 #include "polygon.h"
 
@@ -789,6 +792,163 @@ RestoreCrosshair (void)
   notify_mark_change (true);
 }
 
+/*
+ * Below is the implementation of the "highlight on endpoint" functionality.
+ * This highlights lines and arcs when the crosshair is on of their (two)
+ * endpoints.
+ */
+struct onpoint_search_info {
+  CrosshairType *crosshair;
+  Coord X;
+  Coord Y;
+};
+
+static int
+onpoint_line_callback(const BoxType *box, void *cl)
+{
+  struct onpoint_search_info *info = (struct onpoint_search_info *)cl;
+  CrosshairType *crosshair = info->crosshair;
+  LineType *line = (LineType *)box;
+
+#ifdef DEBUG_ONPOINT
+  printf("X=%ld Y=%ld    X1=%ld Y1=%ld X2=%ld Y2=%ld\n", info->X, info->Y,
+	line->Point1.X,
+	line->Point1.Y,
+	line->Point2.X,
+	line->Point2.Y);
+#endif
+  if ((line->Point1.X == info->X && line->Point1.Y == info->Y) ||
+      (line->Point2.X == info->X && line->Point2.Y == info->Y))
+    {
+      crosshair->onpoint_objs =
+        g_list_prepend(crosshair->onpoint_objs, line);
+      crosshair->onpoint_objs_types =
+        g_list_prepend(crosshair->onpoint_objs_types, 
+        GINT_TO_POINTER(LINE_TYPE));
+      SET_FLAG(ONPOINTFLAG, (AnyObjectType *)line);
+      DrawLine(NULL, line);
+      return 1;
+    }
+  else
+    {
+      return 0;
+    }
+}
+
+static int
+onpoint_arc_callback(const BoxType *box, void *cl)
+{
+  struct onpoint_search_info *info = (struct onpoint_search_info *)cl;
+  CrosshairType *crosshair = info->crosshair;
+  ArcType *arc = (ArcType *)box;
+
+  if ((arc->Point1.X == info->X && arc->Point1.Y == info->Y) ||
+      (arc->Point2.X == info->X && arc->Point2.Y == info->Y))
+    {
+      crosshair->onpoint_objs =
+        g_list_prepend(crosshair->onpoint_objs, arc);
+      crosshair->onpoint_objs_types =
+        g_list_prepend(crosshair->onpoint_objs_types, GINT_TO_POINTER(ARC_TYPE));
+      SET_FLAG(ONPOINTFLAG, (AnyObjectType *)arc);
+      DrawArc(NULL, arc);
+      return 1;
+    }
+  else
+    {
+      return 0;
+    }
+}
+
+void DrawLineOrArc(int type, void *obj)
+{
+  switch (type)
+  {
+  case LINEPOINT_TYPE:
+    /* Attention: We can use a NULL pointer here for the layer,
+     * because it is not used in the DrawLine() function anyways.
+     * ATM DrawLine() only alls AddPart() internally, which invalidates
+     * the area specified by the line's bounding box.
+     */
+     DrawLine(NULL, (LineType *)obj);
+    break;
+  case ARCPOINT_TYPE:
+    /* See comment above */
+    DrawArc(NULL, (ArcType *)obj);
+    break;
+  }
+}
+
+/*
+ * Searches for lines or arcs which have points that are exactly
+ * at the given coordinates and adds them to the crosshair's
+ * object list along with their respective type.
+ */
+static void
+onpoint_work(CrosshairType *crosshair, Coord X, Coord Y)
+{
+  BoxType SearchBox = point_box(X, Y);
+  struct onpoint_search_info info;
+  int i;
+  GList *lobjs, *ltypes;
+  GList *old_onpoint_objs = crosshair->onpoint_objs;
+  GList *old_onpoint_objs_types = crosshair->onpoint_objs_types;
+  bool redraw = false;
+
+  crosshair->onpoint_objs = NULL;
+  crosshair->onpoint_objs_types = NULL;
+
+  info.crosshair = crosshair;
+  info.X = X;
+  info.Y = Y;
+
+  for (i = 0; i < max_copper_layer; i++)
+    {
+      LayerType *layer = &PCB->Data->Layer[i];
+      /* Only find points of arcs and lines on currently visible layers. */
+      if (!layer->On)
+        continue;
+      r_search(layer->line_tree, &SearchBox, NULL,
+        onpoint_line_callback, &info);
+      r_search(layer->arc_tree, &SearchBox, NULL,
+        onpoint_arc_callback, &info);
+    }
+
+  /* Undraw the old objects */
+  for (lobjs = old_onpoint_objs, ltypes = old_onpoint_objs_types;
+       lobjs != NULL;
+       lobjs = lobjs->next, ltypes = ltypes->next)
+    {
+      /* only remove and redraw those which aren't in the new list */
+      if (g_list_find(crosshair->onpoint_objs, lobjs->data) != NULL)
+        continue;
+
+      CLEAR_FLAG(ONPOINTFLAG, (AnyObjectType *)lobjs->data);
+      DrawLineOrArc(GPOINTER_TO_INT(ltypes->data), lobjs->data);
+      redraw = true;
+    }
+
+  /* draw the new objects */
+  for (lobjs = crosshair->onpoint_objs,
+       ltypes = crosshair->onpoint_objs_types;
+       lobjs != NULL;
+       lobjs = lobjs->next, ltypes = ltypes->next)
+    {
+      /* only draw those which aren't in the old list */
+      if (g_list_find(old_onpoint_objs, lobjs->data) != NULL)
+        continue;
+      DrawLineOrArc(GPOINTER_TO_INT(ltypes->data), lobjs->data);
+      redraw = true;
+    }
+
+  g_list_free(old_onpoint_objs);
+  g_list_free(old_onpoint_objs_types);
+
+  if (redraw)
+    {
+      Redraw();
+    }
+}
+
 /*!
  * \brief Returns the square of the given number.
  */
@@ -1088,7 +1248,11 @@ FitCrosshairIntoGrid (Coord X, Coord Y)
       check_snap_object (&snap_data, pnt->X, pnt->Y, true);
     }
 
-  check_snap_offgrid_line (&snap_data, nearest_grid_x, nearest_grid_y);
+  /*
+   * Snap to offgrid points on lines.
+   */
+  if (TEST_FLAG (SNAPOFFGRIDLINEFLAG, PCB))
+    check_snap_offgrid_line (&snap_data, nearest_grid_x, nearest_grid_y);
 
   ans = NO_TYPE;
   if (TEST_FLAG (SNAPPINFLAG, PCB))
@@ -1107,6 +1271,9 @@ FitCrosshairIntoGrid (Coord X, Coord Y)
       Crosshair.Y = snap_data.y;
     }
 
+  if (TEST_FLAG (HIGHLIGHTONPOINTFLAG, PCB))
+    onpoint_work(&Crosshair, Crosshair.X, Crosshair.Y);
+
   if (Settings.Mode == ARROW_MODE)
     {
       ans = SearchObjectByLocation (LINEPOINT_TYPE | ARCPOINT_TYPE,
@@ -1189,6 +1356,10 @@ InitCrosshair (void)
   Crosshair.MaxX = PCB->MaxWidth;
   Crosshair.MaxY = PCB->MaxHeight;
 
+  /* Initialize the onpoint data. */
+  Crosshair.onpoint_objs = NULL;
+  Crosshair.onpoint_objs_types = NULL;
+
   /* clear the mark */
   Marked.status = false;
 }
diff --git a/src/draw.c b/src/draw.c
index 3ba4266..cf1127a 100644
--- a/src/draw.c
+++ b/src/draw.c
@@ -87,9 +87,31 @@ static void DrawEMark (ElementType *, Coord, Coord, bool);
 static void DrawRats (const BoxType *);
 
 static void
+LightenColor(const char *orig, char buf[8], double factor)
+{
+  unsigned int r, g, b;
+
+  if (orig[0] == '#')
+    {
+      sscanf(&orig[1], "%2x%2x%2x", &r, &g, &b);
+      r = MIN(255, r * factor);
+      g = MIN(255, g * factor);
+      b = MIN(255, b * factor);
+    }
+  else
+    {
+      r = 0xff;
+      g = 0xff;
+      b = 0xff;
+    }
+  snprintf(buf, sizeof("#XXXXXX"), "#%02x%02x%02x", r, g, b);
+}
+
+static void
 set_object_color (AnyObjectType *obj, char *warn_color, char *selected_color,
                   char *connected_color, char *found_color, char *normal_color)
 {
+  char buf[sizeof("#XXXXXX")];
   char *color;
 
   if      (warn_color      != NULL && TEST_FLAG (WARNFLAG,      obj)) color = warn_color;
@@ -98,6 +120,13 @@ set_object_color (AnyObjectType *obj, char *warn_color, char *selected_color,
   else if (found_color     != NULL && TEST_FLAG (FOUNDFLAG,     obj)) color = found_color;
   else                                                                color = normal_color;
 
+  if (TEST_FLAG(ONPOINTFLAG, obj))
+    {
+      assert(color != NULL);
+      LightenColor(color, buf, 1.75);
+      color = buf;
+    }
+
   gui->graphics->set_color (Output.fgGC, color);
 }
 
diff --git a/src/flags.c b/src/flags.c
index 471d497..6f058c3 100644
--- a/src/flags.c
+++ b/src/flags.c
@@ -252,6 +252,8 @@ HID_Flag flags_flag_list[] = {
   {"onlynames",            FlagTESTFLAG,     GINT_TO_POINTER (ONLYNAMESFLAG)},
   {"newfullpoly",          FlagTESTFLAG,     GINT_TO_POINTER (NEWFULLPOLYFLAG)},
   {"hidenames",            FlagTESTFLAG,     GINT_TO_POINTER (HIDENAMESFLAG)},
+  {"snapoffgridline",      FlagTESTFLAG,     GINT_TO_POINTER (SNAPOFFGRIDLINEFLAG)},
+  {"highlightonpoint",     FlagTESTFLAG,     GINT_TO_POINTER (HIGHLIGHTONPOINTFLAG)},
 
   {"grid_units_mm",        FlagUnitsMm,      NULL},
   {"grid_units_mil",       FlagUnitsMil,     NULL},
diff --git a/src/global.h b/src/global.h
index cf91f03..3deba02 100644
--- a/src/global.h
+++ b/src/global.h
@@ -717,6 +717,8 @@ typedef struct
   PolygonType AttachedPolygon;
   AttachedObjectType AttachedObject; /*!< Data of attached objects. */
   enum crosshair_shape shape; /*!< Shape of Crosshair. */
+  GList *onpoint_objs;		/* list of associated lines/arc */
+  GList *onpoint_objs_types;	/* ..and a list of their respective types */
 } CrosshairType;
 
 typedef struct
@@ -823,6 +825,8 @@ typedef struct
     FullPoly,
     UniqueNames, /*!< Force unique names. */
     SnapPin, /*!< Snap to pins and pads. */
+    SnapOffGridLine, /*!< Snap to certain off-grid points along a line. */
+    HighlightOnPoint, /*!< Highlight if crosshair is on endpoints. */
     ShowBottomSide, /*!< Mirror output. */
     SaveLastCommand, /*!< Save the last command entered by user. */
     SaveInTMP, /*!< Always save data in /tmp. */
diff --git a/src/gpcb-menu.res.in b/src/gpcb-menu.res.in
index 4cea179..adeeb5d 100644
--- a/src/gpcb-menu.res.in
+++ b/src/gpcb-menu.res.in
@@ -202,6 +202,7 @@ MainMenu =
    {"Auto swap line start angle" checked=swapstartdir Display(ToggleStartDirection)}
    {"Orthogonal moves" checked=orthomove Display(ToggleOrthoMove)}
    {"Crosshair snaps to pins and pads" checked=snappin Display(ToggleSnapPin)}
+   {"Crosshair snaps to off-grid points on lines" checked=snapoffgridline Display(ToggleSnapOffGridLine)}
    {"Crosshair shows DRC clearance" checked=showdrc Display(ToggleShowDRC)}
    {"Auto enforce DRC clearance" checked=autodrc Display(ToggleAutoDRC)}
    {"Lock Names" checked=locknames Display(ToggleLockNames)}
@@ -214,6 +215,7 @@ MainMenu =
    {"New lines, arcs clear polygons" checked=clearnew Display(ToggleClearLine)}
    {"New polygons are full ones" checked=newfullpoly Display(ToggleFullPoly)}
    {"Show autorouter trials" checked=liveroute Display(ToggleLiveRoute)}
+   {"Highlighting on line, arc points" checked=highlightonpoint Display(ToggleHighlightOnPoint)}
    {"Thin draw" checked=thindraw Display(ToggleThindraw) a={"|" "<Key>|"}}
    {"Thin draw poly" checked=thindrawpoly Display(ToggleThindrawPoly) a={"Ctrl-Shift-P" "Ctrl Shift<Key>p"}}
    {"Check polygons" checked=checkplanes Display(ToggleCheckPlanes)}
diff --git a/src/hid/gtk/gtkhid-gdk.c b/src/hid/gtk/gtkhid-gdk.c
index 8857c65..a490b3d 100644
--- a/src/hid/gtk/gtkhid-gdk.c
+++ b/src/hid/gtk/gtkhid-gdk.c
@@ -113,6 +113,8 @@ ghid_destroy_gc (hidGC gc)
 {
   if (gc->gc)
     g_object_unref (gc->gc);
+  if (gc->colorname != NULL)
+    g_free(gc->colorname);
   g_free (gc);
 }
 
@@ -123,7 +125,7 @@ ghid_make_gc (void)
 
   rv = g_new0 (hid_gc_struct, 1);
   rv->me_pointer = &ghid_hid;
-  rv->colorname = Settings.BackgroundColor;
+  rv->colorname = g_strdup(Settings.BackgroundColor);
   return rv;
 }
 
@@ -378,7 +380,13 @@ ghid_set_color (hidGC gc, const char *name)
       name = "magenta";
     }
 
-  gc->colorname = (char *) name;
+  if (name != gc->colorname)
+    {
+      if (gc->colorname != NULL)
+        g_free(gc->colorname);
+      gc->colorname = g_strdup(name);
+    }
+
   if (!gc->gc)
     return;
   if (gport->colormap == 0)
diff --git a/src/hid/gtk/gtkhid-gl.c b/src/hid/gtk/gtkhid-gl.c
index c67fbd1..82fa9d0 100644
--- a/src/hid/gtk/gtkhid-gl.c
+++ b/src/hid/gtk/gtkhid-gl.c
@@ -85,7 +85,7 @@ typedef struct hid_gc_struct
 {
   HID *me_pointer;
 
-  const char *colorname;
+  char *colorname;
   double alpha_mult;
   Coord width;
   gint cap, join;
@@ -198,6 +198,8 @@ ghid_end_layer (void)
 void
 ghid_destroy_gc (hidGC gc)
 {
+  if (gc->colorname != NULL)
+    g_free(gc->colorname);
   g_free (gc);
 }
 
@@ -208,7 +210,7 @@ ghid_make_gc (void)
 
   rv = g_new0 (hid_gc_struct, 1);
   rv->me_pointer = &ghid_hid;
-  rv->colorname = Settings.BackgroundColor;
+  rv->colorname = g_strdup(Settings.BackgroundColor);
   rv->alpha_mult = 1.0;
   return rv;
 }
@@ -470,7 +472,12 @@ set_gl_color_for_gc (hidGC gc)
 void
 ghid_set_color (hidGC gc, const char *name)
 {
-  gc->colorname = name;
+  if (name != gc->colorname)
+    {
+      if (gc->colorname != NULL)
+        g_free((void *)gc->colorname);
+      gc->colorname = g_strdup(name);
+    }
   set_gl_color_for_gc (gc);
 }
 
diff --git a/src/hid/lesstif/main.c b/src/hid/lesstif/main.c
index 2cb3393..e96e1cf 100644
--- a/src/hid/lesstif/main.c
+++ b/src/hid/lesstif/main.c
@@ -50,7 +50,7 @@ typedef struct hid_gc_struct
 {
   HID *me_pointer;
   Pixel color;
-  const char *colorname;
+  char *colorname;
   int width;
   EndCapStyle cap;
   char xor_set;
@@ -3063,12 +3063,15 @@ lesstif_make_gc (void)
   hidGC rv = (hid_gc_struct *) malloc (sizeof (hid_gc_struct));
   memset (rv, 0, sizeof (hid_gc_struct));
   rv->me_pointer = &lesstif_hid;
+  rv->colorname = NULL;
   return rv;
 }
 
 static void
 lesstif_destroy_gc (hidGC gc)
 {
+  if (gc->colorname != NULL)
+    g_free(gc->colorname);
   free (gc);
 }
 
@@ -3137,7 +3140,14 @@ lesstif_set_color (hidGC gc, const char *name)
     return;
   if (!name)
     name = "red";
-  gc->colorname = name;
+
+  if (name != gc->colorname)
+    {
+      if (gc->colorname != NULL)
+        g_free(gc->colorname);
+      gc->colorname = g_strdup(name);
+    }
+
   if (strcmp (name, "erase") == 0)
     {
       gc->color = bgcolor;
diff --git a/src/main.c b/src/main.c
index ce95361..c25e21a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1474,6 +1474,27 @@ that the cursor can snap to.
   BSET (SnapPin, 1, "snap-pin",
        "If set, the cursor snaps to pads and pin centers"),
 
+/* %start-doc options "2 General GUI Options"
+@ftable @code
+@item --snap-offgrid-line
+If set, the cursor snaps at sensible points along a line
+@end ftable
+%end-doc
+*/
+  BSET (SnapOffGridLine, 1, "snap-offgrid-line",
+       "If set, the cursor snaps at sensible points along a line"),
+
+/* %start-doc options "2 General GUI Options"
+@ftable @code
+@item --highlight-on-point
+If set, highlights lines and arcs when the crosshair is on one of their
+two (end) points.
+@end ftable
+%end-doc
+*/
+  BSET (HighlightOnPoint, 0, "highlight-on-point",
+       "If set, highlights lines and arcs when the cursor is on their endpoints"),
+
 /* %start-doc options "1 General Options"
 @ftable @code
 @item --save-last-command
diff --git a/src/pcb-menu.res.in b/src/pcb-menu.res.in
index e37bd7c..b188a96 100644
--- a/src/pcb-menu.res.in
+++ b/src/pcb-menu.res.in
@@ -191,6 +191,7 @@ MainMenu =
    {"Auto swap line start angle" checked=swapstartdir Display(ToggleStartDirection)}
    {"Orthogonal moves" checked=orthomove Display(ToggleOrthoMove)}
    {"Crosshair snaps to pins and pads" checked=snappin Display(ToggleSnapPin)}
+   {"Crosshair snaps to off-grid points on lines" checked=snapoffgridline Display(ToggleSnapOffGridLine)}
    {"Crosshair shows DRC clearance" checked=showdrc Display(ToggleShowDRC)}
    {"Auto enforce DRC clearance" checked=autodrc Display(ToggleAutoDRC)}
    -
@@ -200,6 +201,7 @@ MainMenu =
    {"New lines, arcs clear polygons" checked=clearnew Display(ToggleClearLine)}
    {"New polygons are full ones" checked=newfullpoly Display(ToggleFullPoly)}
    {"Show autorouter trials" checked=liveroute Display(ToggleLiveRoute)}
+   {"Highlighting on line, arc points" checked=highlightonpoint Display(ToggleHighlightOnPoint)}
    {"Thin draw" checked=thindraw Display(ToggleThindraw) a={"|" "<Key>|"}}
    {"Thin draw poly" checked=thindrawpoly Display(ToggleThindrawPoly) a={"Ctrl-Shift-P" "Ctrl Shift<Key>p"}}
    {"Check polygons" checked=checkplanes Display(ToggleCheckPlanes)}
diff --git a/src/strflags.c b/src/strflags.c
index 38ff104..aee280c 100644
--- a/src/strflags.c
+++ b/src/strflags.c
@@ -129,6 +129,8 @@ static FlagBitsType pcb_flagbits[] = {
   { LOCKNAMESFLAG, N ("locknames"), ALL_TYPES },
   { ONLYNAMESFLAG, N ("onlynames"), ALL_TYPES },
   { HIDENAMESFLAG, N ("hidenames"), ALL_TYPES },
+  { SNAPOFFGRIDLINEFLAG, N ("snapoffgridline"), ALL_TYPES },
+  { HIGHLIGHTONPOINTFLAG, N ("highlightonpoint"), ALL_TYPES }
 };
 
 #undef N

--------------000708030003070003020603--

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019