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

Re: gEDA-user: DRC-GUI



On Thu, 2009-04-02 at 18:23 +0200, Bert Timmerman wrote:
> Hi Peter,
> 
> On Thu, 2009-04-02 at 03:34 +0100, Peter Clifton wrote:
> > More eye-candy.. again, a real screen-shot, not a mockup.
> > 
> > http://www2.eng.cam.ac.uk/~pcjc2/geda/drc_for_real2.png
> > 
> 
> Totally awesome !
> 
> Now to double-click on the thumbnail image to move the cursor on the
> spot would be the icing on top of the cake :)

Good idea. (Currently, the code just jumps the mouse cursor as soon as
you select a particular violation).

> I'm looking forward for your patches / git fork.

It is in my git repository under the "better_drc" branch.

It is based on top of my local customisation patches, and the
"before_pours" PCB+GL branch. The relevant patches could probably just
be applied on top of the "before_pours" branch. (I've attached them).

Beware that the GL code seems to cause an X server crash occasionally on
my box. Something wrong there.. not sure if its something I'm doing
wrong, or just a bug I'm inadvertently triggering.

It shouldn't be too hard to modify src/hid/gtk/gui-pixmap-render.c to
render the preview images to a pixmap using the old GDK code either.
Currently I'm just testing with GL.

It works in the same way as the pinout / footprint preview widget, by
temporarily diverting the GUI's zoom and rendering target. A bit of a
kludge perhaps, but it works. (I must get round to refactoring out the
common GL setup code though, it's in 3 places now!).

Thanks for the feedback!

-- 
Peter Clifton

Electrical Engineering Division,
Engineering Department,
University of Cambridge,
9, JJ Thomson Avenue,
Cambridge
CB3 0FA

Tel: +44 (0)7729 980173 - (No signal in the lab!)
From b2e8f90bdd4583ec3c1516604b2323b1a1363d31 Mon Sep 17 00:00:00 2001
From: Peter Clifton <pcjc2@xxxxxxxxx>
Date: Wed, 1 Apr 2009 13:45:12 +0100
Subject: [PATCH] Improve reporting of DRC errors to the GUI

---
 src/Makefile.am              |    1 +
 src/find.c                   |  464 ++++++++++++++++++++----
 src/hid.h                    |   20 +-
 src/hid/gtk/gtkhid-main.c    |    3 +-
 src/hid/gtk/gui-drc-window.c |  840 ++++++++++++++++++++++++++++++++++++++++--
 src/hid/gtk/gui-drc-window.h |  111 ++++++
 src/hid/gtk/gui.h            |    1 +
 7 files changed, 1351 insertions(+), 89 deletions(-)
 create mode 100644 src/hid/gtk/gui-drc-window.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 77e4467..f35a45f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -242,6 +242,7 @@ LIBGTK_SRCS = \
 	hid/gtk/gui-dialog-size.c \
 	hid/gtk/gui-dialog.c \
 	hid/gtk/gui-drc-window.c \
+	hid/gtk/gui-drc-window.h \
 	hid/gtk/gui-keyref-window.c \
 	hid/gtk/gui-library-window.c \
 	hid/gtk/gui-library-window.h \
diff --git a/src/find.c b/src/find.c
index 748d389..8f3ebb8 100644
--- a/src/find.c
+++ b/src/find.c
@@ -157,6 +157,52 @@ RCSID ("$Id$");
 #define	IS_PV_ON_PAD(PV,Pad) \
 	( IsPointInPad((PV)->X, (PV)->Y, MAX((PV)->Thickness/2 +Bloat,0), (Pad)))
 
+#define LENGTH_TO_HUMAN(value) (Settings.grid_units_mm ? ((value) / 100000.0 * 25.4) : ((value) / 100.0))
+#define LENGTH_DIGITS (Settings.grid_units_mm ? 4 : 2)
+#define LENGTH_UNITS_STRING (Settings.grid_units_mm ? "mm" : "mils")
+
+
+static DRC_VIOLATION
+*pcb_drc_violation_new (char *title,
+                        char *explanation,
+                        int x, int y,
+                        int angle,
+                        int have_measured,
+                        double measured_value,
+                        double required_value,
+                        int value_digits,
+                        const char *value_units,
+                        int object_count,
+                        long int *object_id_list,
+                        int *object_type_list)
+{
+  DRC_VIOLATION *violation = malloc (sizeof (DRC_VIOLATION));
+
+  violation->title = strdup (title);
+  violation->explanation = strdup (explanation);
+  violation->x = x;
+  violation->y = y;
+  violation->angle = angle;
+  violation->have_measured = have_measured;
+  violation->measured_value = measured_value;
+  violation->required_value = required_value;
+  violation->value_digits = value_digits;
+  violation->value_units = value_units;
+  violation->object_count = object_count;
+  violation->object_id_list = object_id_list;
+  violation->object_type_list = object_type_list;
+
+  return violation;
+}
+
+static void
+pcb_drc_violation_free (DRC_VIOLATION *violation)
+{
+  free (violation->title);
+  free (violation->explanation);
+  free (violation);
+}
+
 static char drc_dialog_message[289] = {0,};
 static void
 reset_drc_dialog_message(void)
@@ -184,7 +230,8 @@ append_drc_dialog_message(const char *fmt, ...)
 
   if (gui->drc_gui != NULL)
     {
-      gui->drc_gui->append_drc_dialog_messagev (fmt, ap);
+      printf ("FUBAR\n");
+      //gui->drc_gui->append_drc_dialog_messagev (fmt, ap);
     }
   else
     {
@@ -200,6 +247,18 @@ append_drc_dialog_message(const char *fmt, ...)
   va_end (ap);
 }
 
+static void
+append_drc_violation (DRC_VIOLATION *violation)
+{
+  if (gui->drc_gui != NULL)
+    {
+      gui->drc_gui->append_drc_violation (violation);
+    }
+  else
+    {
+      /* FALLBACK TO THE OLD WAY? */
+    }
+}
 /*
  * message when asked about continuing DRC checks after next 
  * violation is found.
@@ -216,7 +275,7 @@ throw_drc_dialog(void)
   if (gui->drc_gui != NULL)
     {
       r = gui->drc_gui->throw_drc_dialog ();
-      gui->drc_gui->reset_drc_dialog_message ();
+//      gui->drc_gui->reset_drc_dialog_message ();
     }
   else
     {
@@ -288,6 +347,8 @@ static Boolean PrintAndSelectUnusedPinsAndPadsOfElement (ElementTypePtr,
 static void DrawNewConnections (void);
 static void ResetConnections (Boolean);
 static void DumpList (void);
+static void LocateError (LocationType *, LocationType *);
+static void BuildObjectList (int *, long int **, int **);
 static void GotoError (void);
 static Boolean DRCFind (int, void *, void *, void *);
 static Boolean ListStart (int, void *, void *, void *);
@@ -3494,6 +3555,12 @@ DumpList (void)
 static Boolean
 DRCFind (int What, void *ptr1, void *ptr2, void *ptr3)
 {
+  LocationType x, y;
+  int object_count;
+  long int *object_id_list;
+  int *object_type_list;
+  DRC_VIOLATION *violation;
+
 //  reset_drc_dialog_message();
   if (PCB->Shrink != 0)
     {
@@ -3515,7 +3582,6 @@ DRCFind (int What, void *ptr1, void *ptr2, void *ptr3)
           Message
             (_
              ("WARNING!!  Design Rule Error - potential for broken trace!\n"));
-          append_drc_dialog_message(_("potential for broken trace\n"));
           /* make the flag changes undoable */
           TheFlag = FOUNDFLAG | SELECTEDFLAG;
           ResetConnections (False);
@@ -3538,7 +3604,26 @@ DRCFind (int What, void *ptr1, void *ptr2, void *ptr3)
           User = False;
           drc = False;
           drcerr_count++;
-          GotoError ();
+          LocateError (&x, &y);
+          BuildObjectList (&object_count, &object_id_list, &object_type_list);
+          violation = pcb_drc_violation_new (_("Potential for broken trace"),
+                                             _("Insufficient overlap between objects can lead to broken tracks\n"
+                                               "due to registration errors with old wheel style photo-plotters."),
+                                             x, y,
+                                             0, /* ANGLE OF ERROR UNKNOWN */
+                                             FALSE, /* MEASUREMENT OF ERROR UNKNOWN */
+                                             0, /* MAGNITUDE OF ERROR UNKNOWN */
+                                             LENGTH_TO_HUMAN(PCB->Shrink),
+                                             LENGTH_DIGITS,
+                                             LENGTH_UNITS_STRING,
+                                             object_count,
+                                             object_id_list,
+                                             object_type_list);
+          append_drc_violation (violation);
+          pcb_drc_violation_free (violation);
+          free (object_id_list);
+          free (object_type_list);
+
           if (!throw_drc_dialog())
             return (True);
           IncrementUndoSerialNumber ();
@@ -3558,7 +3643,6 @@ DRCFind (int What, void *ptr1, void *ptr2, void *ptr3)
     {
       DumpList ();
       Message (_("WARNING!  Design Rule error - copper areas too close!\n"));
-      append_drc_dialog_message(_("copper areas too close\n"));
       /* make the flag changes undoable */
       TheFlag = FOUNDFLAG | SELECTEDFLAG;
       ResetConnections (False);
@@ -3579,7 +3663,25 @@ DRCFind (int What, void *ptr1, void *ptr2, void *ptr3)
       DoIt (True, True);
       DumpList ();
       drcerr_count++;
-      GotoError ();
+      LocateError (&x, &y);
+      BuildObjectList (&object_count, &object_id_list, &object_type_list);
+      violation = pcb_drc_violation_new (_("Copper areas too close"),
+                                         _("Circuits that are too close may bridge during imaging, etching,\n"
+                                           "plating, or soldering processes resulting in a direct short."),
+                                         x, y,
+                                         0, /* ANGLE OF ERROR UNKNOWN */
+                                         FALSE, /* MEASUREMENT OF ERROR UNKNOWN */
+                                         0, /* MAGNITUDE OF ERROR UNKNOWN */
+                                         LENGTH_TO_HUMAN(PCB->Bloat),
+                                         LENGTH_DIGITS,
+                                         LENGTH_UNITS_STRING,
+                                         object_count,
+                                         object_id_list,
+                                         object_type_list);
+      append_drc_violation (violation);
+      pcb_drc_violation_free (violation);
+      free (object_id_list);
+      free (object_type_list);
       User = False;
       drc = False;
       if (!throw_drc_dialog())
@@ -3630,6 +3732,13 @@ static int
 drc_callback (DataTypePtr data, LayerTypePtr layer, PolygonTypePtr polygon,
               int type, void *ptr1, void *ptr2)
 {
+  char *message;
+  LocationType x, y;
+  int object_count;
+  long int *object_id_list;
+  int *object_type_list;
+  DRC_VIOLATION *violation;
+
   LineTypePtr line = (LineTypePtr) ptr2;
   ArcTypePtr arc = (ArcTypePtr) ptr2;
   PinTypePtr pin = (PinTypePtr) ptr2;
@@ -3646,9 +3755,8 @@ drc_callback (DataTypePtr data, LayerTypePtr layer, PolygonTypePtr polygon,
         {
           AddObjectToFlagUndoList (type, ptr1, ptr2, ptr2);
           SET_FLAG (TheFlag, line);
-          Message (_("Line with insufficient clearance inside polygon\n"));
-          append_drc_dialog_message(_("line inside polygon\n"
-            "with insufficient clearance\n"));
+          message = _("Line with insufficient clearance inside polygon\n");
+          Message (message);
           goto doIsBad;
         }
       break;
@@ -3657,9 +3765,8 @@ drc_callback (DataTypePtr data, LayerTypePtr layer, PolygonTypePtr polygon,
         {
           AddObjectToFlagUndoList (type, ptr1, ptr2, ptr2);
           SET_FLAG (TheFlag, arc);
-          Message (_("Arc with insufficient clearance inside polygon\n"));
-          append_drc_dialog_message(_("arc inside polygon\n"
-            "with insufficient clearance\n"));
+          message = _("Arc with insufficient clearance inside polygon\n");
+          Message (message);
           goto doIsBad;
         }
       break;
@@ -3669,9 +3776,8 @@ drc_callback (DataTypePtr data, LayerTypePtr layer, PolygonTypePtr polygon,
 	  {
 	    AddObjectToFlagUndoList (type, ptr1, ptr2, ptr2);
 	    SET_FLAG (TheFlag, pad);
-	    Message (_("Pad with insufficient clearance inside polygon\n"));
-	    append_drc_dialog_message(_("pad inside polygon\n"
-          "with insufficient clearance\n"));
+	    message = _("Pad with insufficient clearance inside polygon\n");
+	    Message (message);
 	    goto doIsBad;
 	  }
       break;
@@ -3680,9 +3786,8 @@ drc_callback (DataTypePtr data, LayerTypePtr layer, PolygonTypePtr polygon,
         {
           AddObjectToFlagUndoList (type, ptr1, ptr2, ptr2);
           SET_FLAG (TheFlag, pin);
-          Message (_("Pin with insufficient clearance inside polygon\n"));
-          append_drc_dialog_message(_("pin inside polygon\n"
-            "with insufficient clearance\n"));
+          message = _("Pin with insufficient clearance inside polygon\n");
+          Message (message);
           goto doIsBad;
         }
       break;
@@ -3691,16 +3796,15 @@ drc_callback (DataTypePtr data, LayerTypePtr layer, PolygonTypePtr polygon,
         {
           AddObjectToFlagUndoList (type, ptr1, ptr2, ptr2);
           SET_FLAG (TheFlag, pin);
-          Message (_("Via with insufficient clearance inside polygon\n"));
-          append_drc_dialog_message(_("via inside polygon\n"
-            "with insufficient clearance\n"));
+          message = _("Via with insufficient clearance inside polygon\n");
+          Message (message);
           goto doIsBad;
         }
       break;
     default:
       Message ("hace: Bad Plow object in callback\n");
-      append_drc_dialog_message(_("wrong object inside polygon\n"
-        "with insufficient clearance\n"));
+//      append_drc_dialog_message(_("wrong object inside polygon\n"
+//        "with insufficient clearance\n"));
     }
   return 0;
 
@@ -3710,7 +3814,25 @@ doIsBad:
   DrawPolygon (layer, polygon, 0);
   DrawObject (type, ptr1, ptr2, 0);
   drcerr_count++;
-  GotoError ();
+  LocateError (&x, &y);
+  BuildObjectList (&object_count, &object_id_list, &object_type_list);
+  violation = pcb_drc_violation_new (message,
+                                     _("Circuits that are too close may bridge during imaging, etching,\n"
+                                       "plating, or soldering processes resulting in a direct short."),
+                                     x, y,
+                                     0, /* ANGLE OF ERROR UNKNOWN */
+                                     FALSE, /* MEASUREMENT OF ERROR UNKNOWN */
+                                     0, /* MAGNITUDE OF ERROR UNKNOWN */
+                                     LENGTH_TO_HUMAN(PCB->Bloat),
+                                     LENGTH_DIGITS,
+                                     LENGTH_UNITS_STRING,
+                                     object_count,
+                                     object_id_list,
+                                     object_type_list);
+  append_drc_violation (violation);
+  pcb_drc_violation_free (violation);
+  free (object_id_list);
+  free (object_type_list);
   if (!throw_drc_dialog())
     {
       IsBad = True;
@@ -3728,9 +3850,16 @@ doIsBad:
 int
 DRCAll (void)
 {
+  LocationType x, y;
+  int object_count;
+  long int *object_id_list;
+  int *object_type_list;
+  DRC_VIOLATION *violation;
   int tmpcnt;
   int nopastecnt = 0;
 
+  reset_drc_dialog_message();
+
   IsBad = False;
   drcerr_count = 0;
   SaveStackAndVisibility ();
@@ -3806,11 +3935,28 @@ DRCAll (void)
             AddObjectToFlagUndoList (LINE_TYPE, layer, line, line);
             SET_FLAG (TheFlag, line);
             Message (_("Line is too thin\n"));
-            append_drc_dialog_message(_("too thin line\n"));
             DrawLine (layer, line, 0);
             drcerr_count++;
             SetThing (LINE_TYPE, layer, line, line);
-            GotoError ();
+            LocateError (&x, &y);
+            BuildObjectList (&object_count, &object_id_list, &object_type_list);
+            violation = pcb_drc_violation_new (_("Line width is too thin"),
+                                               _("Process specifications dictate a minimum feature-width\n"
+                                                 "that can reliably be reproduced"),
+                                               x, y,
+                                               0, /* ANGLE OF ERROR UNKNOWN */
+                                               TRUE, /* MEASUREMENT OF ERROR KNOWN */
+                                               LENGTH_TO_HUMAN(line->Thickness),
+                                               LENGTH_TO_HUMAN(PCB->minWid),
+                                               LENGTH_DIGITS,
+                                               LENGTH_UNITS_STRING,
+                                               object_count,
+                                               object_id_list,
+                                               object_type_list);
+            append_drc_violation (violation);
+            pcb_drc_violation_free (violation);
+            free (object_id_list);
+            free (object_type_list);
             if (!throw_drc_dialog())
               {
                 IsBad = True;
@@ -3834,11 +3980,28 @@ DRCAll (void)
             AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc);
             SET_FLAG (TheFlag, arc);
             Message (_("Arc is too thin\n"));
-            append_drc_dialog_message(_("too thin arc\n"));
             DrawArc (layer, arc, 0);
             drcerr_count++;
             SetThing (ARC_TYPE, layer, arc, arc);
-            GotoError ();
+            LocateError (&x, &y);
+            BuildObjectList (&object_count, &object_id_list, &object_type_list);
+            violation = pcb_drc_violation_new (_("Arc width is too thin"),
+                                               _("Process specifications dictate a minimum feature-width\n"
+                                                 "that can reliably be reproduced"),
+                                               x, y,
+                                               0, /* ANGLE OF ERROR UNKNOWN */
+                                               TRUE, /* MEASUREMENT OF ERROR KNOWN */
+                                               LENGTH_TO_HUMAN(arc->Thickness),
+                                               LENGTH_TO_HUMAN(PCB->minWid),
+                                               LENGTH_DIGITS,
+                                               LENGTH_UNITS_STRING,
+                                               object_count,
+                                               object_id_list,
+                                               object_type_list);
+            append_drc_violation (violation);
+            pcb_drc_violation_free (violation);
+            free (object_id_list);
+            free (object_type_list);
             if (!throw_drc_dialog())
               {
                 IsBad = True;
@@ -3864,11 +4027,28 @@ DRCAll (void)
             SET_FLAG (TheFlag, pin);
             Message (_
                      ("Pin annular ring is too small based on minimum annular ring\n"));
-            append_drc_dialog_message(_("pin ring thinner\nthan min annular ring\n"));
             DrawPin (pin, 0);
             drcerr_count++;
             SetThing (PIN_TYPE, element, pin, pin);
-            GotoError ();
+            LocateError (&x, &y);
+            BuildObjectList (&object_count, &object_id_list, &object_type_list);
+            violation = pcb_drc_violation_new (_("Pin annular ring too small"),
+                                               _("Annular rings that are too small may erode during etching,\n"
+                                                 "resulting in a broken connection"),
+                                               x, y,
+                                               0, /* ANGLE OF ERROR UNKNOWN */
+                                               TRUE, /* MEASUREMENT OF ERROR KNOWN */
+                                               LENGTH_TO_HUMAN((pin->Thickness - pin->DrillingHole) / 2),
+                                               LENGTH_TO_HUMAN(PCB->minRing),
+                                               LENGTH_DIGITS,
+                                               LENGTH_UNITS_STRING,
+                                               object_count,
+                                               object_id_list,
+                                               object_type_list);
+            append_drc_violation (violation);
+            pcb_drc_violation_free (violation);
+            free (object_id_list);
+            free (object_type_list);
             if (!throw_drc_dialog())
               {
                 IsBad = True;
@@ -3882,11 +4062,27 @@ DRCAll (void)
             AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
             SET_FLAG (TheFlag, pin);
             Message (_("Pin drill size is too small\n"));
-            append_drc_dialog_message(_("too small pin drill\n"));
             DrawPin (pin, 0);
             drcerr_count++;
             SetThing (PIN_TYPE, element, pin, pin);
-            GotoError ();
+            LocateError (&x, &y);
+            BuildObjectList (&object_count, &object_id_list, &object_type_list);
+            violation = pcb_drc_violation_new (_("Pin drill size is too small"),
+                                               _("Process rules dictate the minimum drill size which can be used"),
+                                               x, y,
+                                               0, /* ANGLE OF ERROR UNKNOWN */
+                                               TRUE, /* MEASUREMENT OF ERROR KNOWN */
+                                               LENGTH_TO_HUMAN(pin->DrillingHole),
+                                               LENGTH_TO_HUMAN(PCB->minDrill),
+                                               LENGTH_DIGITS,
+                                               LENGTH_UNITS_STRING,
+                                               object_count,
+                                               object_id_list,
+                                               object_type_list);
+            append_drc_violation (violation);
+            pcb_drc_violation_free (violation);
+            free (object_id_list);
+            free (object_type_list);
             if (!throw_drc_dialog())
               {
                 IsBad = True;
@@ -3910,11 +4106,28 @@ DRCAll (void)
             AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
             SET_FLAG (TheFlag, pad);
             Message (_("Pad is too thin\n"));
-            append_drc_dialog_message(_("too thin pad\n"));
             DrawPad (pad, 0);
             drcerr_count++;
             SetThing (PAD_TYPE, element, pad, pad);
-            GotoError ();
+            LocateError (&x, &y);
+            BuildObjectList (&object_count, &object_id_list, &object_type_list);
+            violation = pcb_drc_violation_new (_("Pad is too thin"),
+                                               _("Pads which are too thin may erode during etching,\n"
+                                                  "resulting in a broken or unreliable connection"),
+                                               x, y,
+                                               0, /* ANGLE OF ERROR UNKNOWN */
+                                               TRUE, /* MEASUREMENT OF ERROR KNOWN */
+                                               LENGTH_TO_HUMAN(pad->Thickness),
+                                               LENGTH_TO_HUMAN(PCB->minWid),
+                                               LENGTH_DIGITS,
+                                               LENGTH_UNITS_STRING,
+                                               object_count,
+                                               object_id_list,
+                                               object_type_list);
+            append_drc_violation (violation);
+            pcb_drc_violation_free (violation);
+            free (object_id_list);
+            free (object_type_list);
             if (!throw_drc_dialog())
               {
                 IsBad = True;
@@ -3940,11 +4153,28 @@ DRCAll (void)
             SET_FLAG (TheFlag, via);
             Message (_
                      ("Via annular ring is too small based on minimum annular ring\n"));
-            append_drc_dialog_message(_("via ring thinner\nthan min annular ring\n"));
             DrawVia (via, 0);
             drcerr_count++;
             SetThing (VIA_TYPE, via, via, via);
-            GotoError ();
+            LocateError (&x, &y);
+            BuildObjectList (&object_count, &object_id_list, &object_type_list);
+            violation = pcb_drc_violation_new (_("Via annular ring too small"),
+                                               _("Annular rings that are too small may erode during etching,\n"
+                                                 "resulting in a broken connection"),
+                                               x, y,
+                                               0, /* ANGLE OF ERROR UNKNOWN */
+                                               TRUE, /* MEASUREMENT OF ERROR KNOWN */
+                                               LENGTH_TO_HUMAN((via->Thickness - via->DrillingHole) / 2),
+                                               LENGTH_TO_HUMAN(PCB->minRing),
+                                               LENGTH_DIGITS,
+                                               LENGTH_UNITS_STRING,
+                                               object_count,
+                                               object_id_list,
+                                               object_type_list);
+            append_drc_violation (violation);
+            pcb_drc_violation_free (violation);
+            free (object_id_list);
+            free (object_type_list);
             if (!throw_drc_dialog())
               {
                 IsBad = True;
@@ -3958,11 +4188,27 @@ DRCAll (void)
             AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
             SET_FLAG (TheFlag, via);
             Message (_("Via drill size is too small\n"));
-            append_drc_dialog_message(_("too small via drill\n"));
             DrawVia (via, 0);
             drcerr_count++;
             SetThing (VIA_TYPE, via, via, via);
-            GotoError ();
+            LocateError (&x, &y);
+            BuildObjectList (&object_count, &object_id_list, &object_type_list);
+            violation = pcb_drc_violation_new (_("Via drill size is too small"),
+                                               _("Process rules dictate the minimum drill size which can be used"),
+                                               x, y,
+                                               0, /* ANGLE OF ERROR UNKNOWN */
+                                               TRUE, /* MEASUREMENT OF ERROR KNOWN */
+                                               LENGTH_TO_HUMAN(via->DrillingHole),
+                                               LENGTH_TO_HUMAN(PCB->minDrill),
+                                               LENGTH_DIGITS,
+                                               LENGTH_UNITS_STRING,
+                                               object_count,
+                                               object_id_list,
+                                               object_type_list);
+            append_drc_violation (violation);
+            pcb_drc_violation_free (violation);
+            free (object_id_list);
+            free (object_type_list);
             if (!throw_drc_dialog())
               {
                 IsBad = True;
@@ -3991,11 +4237,28 @@ DRCAll (void)
           {
             SET_FLAG (TheFlag, line);
             Message (_("Silk line is too thin\n"));
-            append_drc_dialog_message(_("too thin silk line\n"));
             DrawLine (layer, line, 0);
             drcerr_count++;
             SetThing (LINE_TYPE, layer, line, line);
-            GotoError ();
+            LocateError (&x, &y);
+            BuildObjectList (&object_count, &object_id_list, &object_type_list);
+            violation = pcb_drc_violation_new (_("Silk line is too thin"),
+                                               _("Process specifications dictate a minimum silkscreen feature-width\n"
+                                                 "that can reliably be reproduced"),
+                                               x, y,
+                                               0, /* ANGLE OF ERROR UNKNOWN */
+                                               TRUE, /* MEASUREMENT OF ERROR KNOWN */
+                                               LENGTH_TO_HUMAN(line->Thickness),
+                                               LENGTH_TO_HUMAN(PCB->minSlk),
+                                               LENGTH_DIGITS,
+                                               LENGTH_UNITS_STRING,
+                                               object_count,
+                                               object_id_list,
+                                               object_type_list);
+            append_drc_violation (violation);
+            pcb_drc_violation_free (violation);
+            free (object_id_list);
+            free (object_type_list);
             if (!throw_drc_dialog())
               {
                 IsBad = True;
@@ -4022,16 +4285,51 @@ DRCAll (void)
         END_LOOP;
         if (tmpcnt > 0)
           {
+            char *title;
+            char *name;
+            char *buffer;
+            int buflen;
+
             SET_FLAG (TheFlag, element);
             Message (_("Element %s has %d silk lines which are too thin\n"),
                      UNKNOWN (NAMEONPCB_NAME (element)), tmpcnt);
-            append_drc_dialog_message (_
-                     ("%i silk lines\n of element %s\nare too thin\n"),
-                     tmpcnt, UNKNOWN (NAMEONPCB_NAME (element)));
+//            append_drc_dialog_message (_
+//                     ("%i silk lines\n of element %s\nare too thin\n"),
+//                     tmpcnt, UNKNOWN (NAMEONPCB_NAME (element)));
             DrawElement (element, 0);
             drcerr_count++;
             SetThing (ELEMENT_TYPE, element, element, element);
-            GotoError ();
+            LocateError (&x, &y);
+            BuildObjectList (&object_count, &object_id_list, &object_type_list);
+
+            title = _("Element %s has %i silk lines which are too thin");
+            name = UNKNOWN (NAMEONPCB_NAME (element));
+
+            /* -4 is for the %s and %i place-holders */
+            /* +11 is the max printed length for a 32 bit integer */
+            /* +1 is for the \0 termination */
+            buflen = strlen (title) - 4 + strlen (name) + 11 + 1;
+            buffer = malloc (buflen);
+            snprintf (buffer, buflen, title, name, tmpcnt);
+
+            violation = pcb_drc_violation_new (buffer,
+                                               _("Process specifications dictate a minimum silkscreen\n"
+                                               "feature-width that can reliably be reproduced"),
+                                               x, y,
+                                               0, /* ANGLE OF ERROR UNKNOWN */
+                                               0, /* MINIMUM OFFENDING WIDTH UNKNOWN */
+                                               TRUE, /* MEASUREMENT OF ERROR KNOWN */
+                                               LENGTH_TO_HUMAN(PCB->minSlk),
+                                               LENGTH_DIGITS,
+                                               LENGTH_UNITS_STRING,
+                                               object_count,
+                                               object_id_list,
+                                               object_type_list);
+            free (buffer);
+            append_drc_violation (violation);
+            pcb_drc_violation_free (violation);
+            free (object_id_list);
+            free (object_type_list);
             if (!throw_drc_dialog())
               {
                 IsBad = True;
@@ -4063,36 +4361,34 @@ DRCAll (void)
 }
 
 /*----------------------------------------------------------------------------
- * center the display to show the offending item (thing)
+ * Locate the coordinatates of offending item (thing)
  */
 static void
-GotoError (void)
+LocateError (LocationType *x, LocationType *y)
 {
-  LocationType X, Y;
-
   switch (thing_type)
     {
     case LINE_TYPE:
       {
         LineTypePtr line = (LineTypePtr) thing_ptr3;
-        X = (line->Point1.X + line->Point2.X) / 2;
-        Y = (line->Point1.Y + line->Point2.Y) / 2;
+        *x = (line->Point1.X + line->Point2.X) / 2;
+        *y = (line->Point1.Y + line->Point2.Y) / 2;
         break;
       }
     case ARC_TYPE:
       {
         ArcTypePtr arc = (ArcTypePtr) thing_ptr3;
-        X = arc->X;
-        Y = arc->Y;
+        *x = arc->X;
+        *y = arc->Y;
         break;
       }
     case POLYGON_TYPE:
       {
         PolygonTypePtr polygon = (PolygonTypePtr) thing_ptr3;
-        X =
+        *x =
           (polygon->Clipped->contours->xmin +
            polygon->Clipped->contours->xmax) / 2;
-        Y =
+        *y =
           (polygon->Clipped->contours->ymin +
            polygon->Clipped->contours->ymax) / 2;
         break;
@@ -4101,33 +4397,75 @@ GotoError (void)
     case VIA_TYPE:
       {
         PinTypePtr pin = (PinTypePtr) thing_ptr3;
-        X = pin->X;
-        Y = pin->Y;
+        *x = pin->X;
+        *y = pin->Y;
         break;
       }
     case PAD_TYPE:
       {
         PadTypePtr pad = (PadTypePtr) thing_ptr3;
-        X = (pad->Point1.X + pad->Point2.X) / 2;
-        Y = (pad->Point1.Y + pad->Point2.Y) / 2;
+        *x = (pad->Point1.X + pad->Point2.X) / 2;
+        *y = (pad->Point1.Y + pad->Point2.Y) / 2;
         break;
       }
     case ELEMENT_TYPE:
       {
         ElementTypePtr element = (ElementTypePtr) thing_ptr3;
-        X = element->MarkX;
-        Y = element->MarkY;
+        *x = element->MarkX;
+        *y = element->MarkY;
         break;
       }
     default:
       return;
     }
+}
+
+
+/*----------------------------------------------------------------------------
+ * Build a list of the of offending items by ID. (Currently just "thing")
+ */
+static void
+BuildObjectList (int *object_count, long int **object_id_list, int **object_type_list)
+{
+  *object_count = 0;
+  *object_id_list = NULL;
+
+  switch (thing_type)
+    {
+    case LINE_TYPE:
+    case ARC_TYPE:
+    case POLYGON_TYPE:
+    case PIN_TYPE:
+    case VIA_TYPE:
+    case PAD_TYPE:
+    case ELEMENT_TYPE:
+      *object_count = 1;
+      *object_id_list = malloc (sizeof (long int));
+      *object_type_list = malloc (sizeof (int));
+      **object_id_list = ((AnyObjectType *)thing_ptr3)->ID;
+      **object_type_list = thing_type;
+      return;
+
+    default:
+      return;
+    }
+}
+
+
+/*----------------------------------------------------------------------------
+ * center the display to show the offending item (thing)
+ */
+static void
+GotoError (void)
+{
+  LocationType X, Y;
+
+  LocateError (&X, &Y);
+
   {
-    int digits = Settings.grid_units_mm ? 4: 2;
     double scale = Settings.grid_units_mm ? COOR_TO_MM : 1./100,
       x = X * scale, y = Y * scale;
-    Message (_("near location (%.*f,%.*f)\n"), digits, x, digits, y);
-    append_drc_dialog_message("near (%.*f,%.*f)\n", digits, x, digits, y);
+    Message (_("near location (%.*f,%.*f)\n"), LENGTH_DIGITS, x, LENGTH_DIGITS, y);
   }
   switch (thing_type)
     {
diff --git a/src/hid.h b/src/hid.h
index ee62369..2bbe9fd 100644
--- a/src/hid.h
+++ b/src/hid.h
@@ -229,11 +229,29 @@ typedef enum
   PCB_WATCH_HANGUP   = 1 << 3  /**< As in POLLHUP */
 } PCBWatchFlags;
 
+typedef struct
+{
+  char *title;
+  char *explanation;
+  int x;
+  int y;
+  int angle;
+  int have_measured;
+  double measured_value;
+  double required_value;
+  int value_digits;
+  const char *value_units;
+  int object_count;
+  long int *object_id_list;
+  int *object_type_list;
+} DRC_VIOLATION;
+
 /* DRC GUI Hooks */
   typedef struct
   {
     void (*reset_drc_dialog_message) (void);
-    void (*append_drc_dialog_messagev) (const char *fmt, va_list va);
+    void (*append_drc_violation) (DRC_VIOLATION *violation);
+//    void (*append_drc_dialog_messagev) (const char *fmt, va_list va);
     int (*throw_drc_dialog) (void);
   } HID_DRC_GUI;
 
diff --git a/src/hid/gtk/gtkhid-main.c b/src/hid/gtk/gtkhid-main.c
index bb5b3d7..4653335 100644
--- a/src/hid/gtk/gtkhid-main.c
+++ b/src/hid/gtk/gtkhid-main.c
@@ -1476,7 +1476,8 @@ ghid_progress (int so_far, int total, const char *message)
 /* ---------------------------------------------------------------------- */
 HID_DRC_GUI ghid_drc_gui = {
   ghid_drc_window_reset_message,
-  ghid_drc_window_append_messagev,
+  ghid_drc_window_append_violation,
+//  ghid_drc_window_append_messagev,
   ghid_drc_window_throw_dialog
 };
 
diff --git a/src/hid/gtk/gui-drc-window.c b/src/hid/gtk/gui-drc-window.c
index 9298729..b443a0d 100644
--- a/src/hid/gtk/gui-drc-window.c
+++ b/src/hid/gtk/gui-drc-window.c
@@ -30,7 +30,13 @@
 #include "config.h"
 #endif
 
+#include "error.h"
+#include "search.h"
+#include "draw.h"
+#include "undo.h"
+#include "set.h"
 #include "gui.h"
+#include "gui-drc-window.h"
 
 #ifdef HAVE_LIBDMALLOC
 #include <dmalloc.h>
@@ -39,7 +45,8 @@
 RCSID ("$Id$");
 
 static GtkWidget *drc_window, *drc_list;
-
+static GtkListStore *drc_list_model = NULL;
+static int num_violations = 0;
 
 /* Remember user window resizes. */
 static gint
@@ -66,10 +73,720 @@ drc_destroy_cb (GtkWidget * widget, gpointer data)
   drc_window = NULL;
 }
 
+enum {
+  DRC_VIOLATION_NUM_COL = 0,
+  DRC_VIOLATION_OBJ_COL,
+  DRC_OBJECT_COUNT_COL,
+  DRC_OBJECT_ID_LIST_COL,
+  DRC_OBJECT_TYPE_LIST_COL,
+  NUM_DRC_COLUMNS
+};
+
+
+#warning NASTY, DOESNT USE UNDO PROPERLY
+static void
+unset_found_flags (int AndDraw)
+{
+  int flag = FOUNDFLAG;
+  int change = 0;
+
+  VIA_LOOP (PCB->Data);
+  {
+    if (TEST_FLAG (flag, via))
+      {
+        if (AndDraw)
+          AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
+        CLEAR_FLAG (flag, via);
+        if (AndDraw)
+          DrawVia (via, 0);
+        change = True;
+      }
+  }
+  END_LOOP;
+  ELEMENT_LOOP (PCB->Data);
+  {
+    PIN_LOOP (element);
+    {
+      if (TEST_FLAG (flag, pin))
+        {
+          if (AndDraw)
+            AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
+          CLEAR_FLAG (flag, pin);
+          if (AndDraw)
+            DrawPin (pin, 0);
+          change = True;
+        }
+    }
+    END_LOOP;
+    PAD_LOOP (element);
+    {
+      if (TEST_FLAG (flag, pad))
+        {
+          if (AndDraw)
+            AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
+          CLEAR_FLAG (flag, pad);
+          if (AndDraw)
+            DrawPad (pad, 0);
+          change = True;
+        }
+    }
+    END_LOOP;
+  }
+  END_LOOP;
+  RAT_LOOP (PCB->Data);
+  {
+    if (TEST_FLAG (flag, line))
+      {
+        if (AndDraw)
+          AddObjectToFlagUndoList (RATLINE_TYPE, line, line, line);
+        CLEAR_FLAG (flag, line);
+        if (AndDraw)
+          DrawRat (line, 0);
+        change = True;
+      }
+  }
+  END_LOOP;
+  COPPERLINE_LOOP (PCB->Data);
+  {
+    if (TEST_FLAG (flag, line))
+      {
+        if (AndDraw)
+          AddObjectToFlagUndoList (LINE_TYPE, layer, line, line);
+        CLEAR_FLAG (flag, line);
+        if (AndDraw)
+          DrawLine (layer, line, 0);
+        change = True;
+      }
+  }
+  ENDALL_LOOP;
+  COPPERARC_LOOP (PCB->Data);
+  {
+    if (TEST_FLAG (flag, arc))
+      {
+        if (AndDraw)
+          AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc);
+        CLEAR_FLAG (flag, arc);
+        if (AndDraw)
+          DrawArc (layer, arc, 0);
+        change = True;
+      }
+  }
+  ENDALL_LOOP;
+  COPPERPOLYGON_LOOP (PCB->Data);
+  {
+    if (TEST_FLAG (flag, polygon))
+      {
+        if (AndDraw)
+          AddObjectToFlagUndoList (POLYGON_TYPE, layer, polygon, polygon);
+        CLEAR_FLAG (flag, polygon);
+        if (AndDraw)
+          DrawPolygon (layer, polygon, 0);
+        change = True;
+      }
+  }
+  ENDALL_LOOP;
+  if (change)
+    {
+      SetChangedFlag (True);
+      if (AndDraw)
+        {
+          IncrementUndoSerialNumber ();
+          Draw ();
+        }
+    }
+}
+
+static void
+selection_changed_cb (GtkTreeSelection *selection, gpointer user_data)
+{
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+  GhidDrcViolation *violation;
+  int object_count;
+#if 0
+  long int *object_id_list;
+  int *object_type_list;
+#else
+  long int object_id;
+  int object_type;
+#endif
+  int i;
+
+#warning CHEATING HERE!
+  /* I happen to know I'm only putting 0 or 1 items in the lists of objects.
+     To do this properly requires some memory allocation and tracking to
+     avoid leaks! */
+
+  /* Check there is anything selected, if not; return */
+  if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+    {
+      /* Unflag objects */
+      unset_found_flags (True);
+      return;
+    }
+
+  /* Check the selected node has children, if so; return. */
+  if (gtk_tree_model_iter_has_child (model, &iter))
+    return;
+
+  gtk_tree_model_get (model, &iter,
+                      DRC_VIOLATION_OBJ_COL,    &violation,
+                      DRC_OBJECT_COUNT_COL,     &object_count,
+#if 0
+                      DRC_OBJECT_ID_LIST_COL,   &object_id_list,
+                      DRC_OBJECT_TYPE_LIST_COL, &object_type_list,
+#else
+                      DRC_OBJECT_ID_LIST_COL,   &object_id,
+                      DRC_OBJECT_TYPE_LIST_COL, &object_type,
+#endif
+                      -1);
+
+  unset_found_flags (False);
+
+  if (violation == NULL)
+    return;
+
+  /* Flag the objects listed against this DRC violation */
+  for (i = 0; i < object_count; i++)
+    {
+      int found_type;
+      void *ptr1, *ptr2, *ptr3;
+
+      found_type = SearchObjectByID (PCB->Data, &ptr1, &ptr2, &ptr3,
+                                     object_id, object_type);
+      if (found_type == NO_TYPE)
+        {
+          Message (_("Object ID %i identified during DRC was not found. Stale DRC window?\n"),
+                   object_id);
+          continue;
+        }
+      SET_FLAG (FOUNDFLAG, (AnyObjectType *)ptr2);
+      switch (object_type)
+        {
+        case LINE_TYPE:
+        case ARC_TYPE:
+        case POLYGON_TYPE:
+          ChangeGroupVisibility (GetLayerNumber (PCB->Data, (LayerTypePtr) ptr1), True, True);
+        }
+      DrawObject (object_type, ptr1, ptr2, 0);
+    }
+  Draw();
+  CenterDisplay (violation->x_coord, violation->y_coord, False);
+}
+
+
+enum
+{
+  PROP_TITLE = 1,
+  PROP_EXPLANATION,
+  PROP_X_COORD,
+  PROP_Y_COORD,
+  PROP_ANGLE,
+  PROP_HAVE_MEASURED,
+  PROP_MEASURED_VALUE,
+  PROP_REQUIRED_VALUE,
+  PROP_VALUE_DIGITS,
+  PROP_VALUE_UNITS
+};
+
+
+static GObjectClass *ghid_drc_violation_parent_class = NULL;
+
+
+/*! \brief GObject finalise handler
+ *
+ *  \par Function Description
+ *  Just before the GhidDrcViolation GObject is finalized, free our
+ *  allocated data, and then chain up to the parent's finalize handler.
+ *
+ *  \param [in] widget  The GObject being finalized.
+ */
+static void
+ghid_drc_violation_finalize (GObject * object)
+{
+  GhidDrcViolation *violation = GHID_DRC_VIOLATION (object);
+
+  g_free (violation->title);
+  g_free (violation->explanation);
+  g_free (violation->value_units);
+
+  G_OBJECT_CLASS (ghid_drc_violation_parent_class)->finalize (object);
+}
+
+/*! \brief GObject property setter function
+ *
+ *  \par Function Description
+ *  Setter function for GhidDrcViolation's GObject properties,
+ *  "settings-name" and "toplevel"
+ *
+ *  \param [in]  object       The GObject whose properties we are setting
+ *  \param [in]  property_id  The numeric id. under which the property was
+ *                            registered with g_object_class_install_property()
+ *  \param [in]  value        The GValue the property is being set from
+ *  \param [in]  pspec        A GParamSpec describing the property being set
+ */
+static void
+ghid_drc_violation_set_property (GObject * object, guint property_id,
+				  const GValue * value, GParamSpec * pspec)
+{
+  GhidDrcViolation *violation = GHID_DRC_VIOLATION (object);
+
+  switch (property_id)
+    {
+    case PROP_TITLE:
+      g_free (violation->title);
+      violation->title = g_value_dup_string (value);
+      break;
+    case PROP_EXPLANATION:
+      g_free (violation->explanation);
+      violation->explanation = g_value_dup_string (value);
+      break;
+    case PROP_X_COORD:
+      violation->x_coord = g_value_get_int (value);
+      break;
+    case PROP_Y_COORD:
+      violation->y_coord = g_value_get_int (value);
+      break;
+    case PROP_ANGLE:
+      violation->angle = g_value_get_int (value);
+      break;
+    case PROP_HAVE_MEASURED:
+      violation->have_measured = g_value_get_int (value);
+      break;
+    case PROP_MEASURED_VALUE:
+      violation->measured_value = g_value_get_double (value);
+      break;
+    case PROP_REQUIRED_VALUE:
+      violation->required_value = g_value_get_double (value);
+      break;
+    case PROP_VALUE_DIGITS:
+      violation->value_digits = g_value_get_int (value);
+      break;
+    case PROP_VALUE_UNITS:
+      g_free (violation->value_units);
+      violation->value_units = g_value_dup_string (value);
+      break;
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      return;
+    }
+}
+
+
+/*! \brief GObject property getter function
+ *
+ *  \par Function Description
+ *  Getter function for GhidDrcViolation's GObject properties,
+ *  "settings-name" and "toplevel".
+ *
+ *  \param [in]  object       The GObject whose properties we are getting
+ *  \param [in]  property_id  The numeric id. under which the property was
+ *                            registered with g_object_class_install_property()
+ *  \param [out] value        The GValue in which to return the value of the property
+ *  \param [in]  pspec        A GParamSpec describing the property being got
+ */
+static void
+ghid_drc_violation_get_property (GObject * object, guint property_id,
+				  GValue * value, GParamSpec * pspec)
+{
+  switch (property_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+
+}
+
+
+/*! \brief GType class initialiser for GhidDrcViolation
+ *
+ *  \par Function Description
+ *  GType class initialiser for GhidDrcViolation. We override our parent
+ *  virtual class methods as needed and register our GObject properties.
+ *
+ *  \param [in]  klass       The GhidDrcViolationClass we are initialising
+ */
+static void
+ghid_drc_violation_class_init (GhidViolationRendererClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->finalize = ghid_drc_violation_finalize;
+  gobject_class->set_property = ghid_drc_violation_set_property;
+  gobject_class->get_property = ghid_drc_violation_get_property;
+
+  ghid_drc_violation_parent_class = g_type_class_peek_parent (klass);
+
+  g_object_class_install_property (gobject_class, PROP_TITLE,
+				   g_param_spec_string ("title",
+							"",
+							"",
+							"",
+							G_PARAM_WRITABLE));
+  g_object_class_install_property (gobject_class, PROP_EXPLANATION,
+				   g_param_spec_string ("explanation",
+							"",
+							"",
+							"",
+							G_PARAM_WRITABLE));
+  g_object_class_install_property (gobject_class, PROP_X_COORD,
+				   g_param_spec_int ("x-coord",
+						     "",
+						     "",
+						     G_MININT,
+						     G_MAXINT,
+						     0,
+						     G_PARAM_WRITABLE));
+  g_object_class_install_property (gobject_class, PROP_Y_COORD,
+				   g_param_spec_int ("y-coord",
+						     "",
+						     "",
+						     G_MININT,
+						     G_MAXINT,
+						     0,
+						     G_PARAM_WRITABLE));
+  g_object_class_install_property (gobject_class, PROP_ANGLE,
+				   g_param_spec_int ("angle",
+						     "",
+						     "",
+						     G_MININT,
+						     G_MAXINT,
+						     0,
+						     G_PARAM_WRITABLE));
+  g_object_class_install_property (gobject_class, PROP_HAVE_MEASURED,
+				   g_param_spec_int ("have-measured",
+						     "",
+						     "",
+						     G_MININT,
+						     G_MAXINT,
+						     0,
+						     G_PARAM_WRITABLE));
+  g_object_class_install_property (gobject_class, PROP_MEASURED_VALUE,
+				   g_param_spec_double ("measured-value",
+						     "",
+						     "",
+						     -G_MAXDOUBLE,
+						     G_MAXDOUBLE,
+						     0.,
+						     G_PARAM_WRITABLE));
+  g_object_class_install_property (gobject_class, PROP_REQUIRED_VALUE,
+				   g_param_spec_double ("required-value",
+						     "",
+						     "",
+						     -G_MINDOUBLE,
+						     G_MAXDOUBLE,
+						     0.,
+						     G_PARAM_WRITABLE));
+  g_object_class_install_property (gobject_class, PROP_VALUE_DIGITS,
+				   g_param_spec_int ("value-digits",
+						     "",
+						     "",
+						     0,
+						     G_MAXINT,
+						     0,
+						     G_PARAM_WRITABLE));
+  g_object_class_install_property (gobject_class, PROP_VALUE_UNITS,
+				   g_param_spec_string ("value-units",
+							"",
+							"",
+							"",
+							G_PARAM_WRITABLE));
+}
+
+
+
+/*! \brief Function to retrieve GhidViolationRenderer's GType identifier.
+ *
+ *  \par Function Description
+ *  Function to retrieve GhidViolationRenderer's GType identifier.
+ *  Upon first call, this registers the GhidViolationRenderer in the GType system.
+ *  Subsequently it returns the saved value from its first execution.
+ *
+ *  \return the GType identifier associated with GhidViolationRenderer.
+ */
+GType
+ghid_drc_violation_get_type ()
+{
+  static GType ghid_drc_violation_type = 0;
+
+  if (!ghid_drc_violation_type)
+    {
+      static const GTypeInfo ghid_drc_violation_info = {
+	sizeof (GhidDrcViolationClass),
+	NULL,			/* base_init */
+	NULL,			/* base_finalize */
+	(GClassInitFunc) ghid_drc_violation_class_init,
+	NULL,			/* class_finalize */
+	NULL,			/* class_data */
+	sizeof (GhidDrcViolation),
+	0,			/* n_preallocs */
+	NULL,			/* instance_init */
+      };
+
+      ghid_drc_violation_type =
+	g_type_register_static (G_TYPE_OBJECT, "GhidDrcViolation",
+				&ghid_drc_violation_info, 0);
+    }
+
+  return ghid_drc_violation_type;
+}
+
+
+GhidDrcViolation *ghid_drc_violation_new (char *title,
+                                          char *explanation,
+                                          int x_coord,
+                                          int y_coord,
+                                          int angle,
+                                          int have_measured,
+                                          double measured_value,
+                                          double required_value,
+                                          int value_digits,
+                                          const char *value_units,
+                                          int object_count,
+                                          long int object_id,
+                                          int object_type)
+{
+  GhidDrcViolation *violation = g_object_new (GHID_TYPE_DRC_VIOLATION,
+                                             "title",          title,
+                                             "explanation",    explanation,
+                                             "x-coord",        x_coord,
+                                             "y-coord",        y_coord,
+                                             "angle",          angle,
+                                             "have-measured",  have_measured,
+                                             "measured-value", measured_value,
+                                             "required-value", required_value,
+                                             "value-digits",   value_digits,
+                                             "value-units",    value_units,
+                                             NULL);
+//  violation->object_count     = object_count;
+//  violation->object_id        = object_id;
+//  violation->object_type      = object_type;
+  return violation;
+}
+
+enum
+{
+  PROP_VIOLATION = 1,
+};
+
+
+static GObjectClass *ghid_violation_renderer_parent_class = NULL;
+
+
+/*! \brief GObject finalise handler
+ *
+ *  \par Function Description
+ *  Just before the GhidViolationRenderer GObject is finalized, free our
+ *  allocated data, and then chain up to the parent's finalize handler.
+ *
+ *  \param [in] widget  The GObject being finalized.
+ */
+static void
+ghid_violation_renderer_finalize (GObject * object)
+{
+  GhidViolationRenderer *renderer = GHID_VIOLATION_RENDERER (object);
+
+  if (renderer->violation != NULL)
+    g_object_unref (renderer->violation);
+
+  G_OBJECT_CLASS (ghid_violation_renderer_parent_class)->finalize (object);
+}
+
+
+/*! \brief GObject property setter function
+ *
+ *  \par Function Description
+ *  Setter function for GhidViolationRenderer's GObject properties,
+ *  "settings-name" and "toplevel".
+ *
+ *  \param [in]  object       The GObject whose properties we are setting
+ *  \param [in]  property_id  The numeric id. under which the property was
+ *                            registered with g_object_class_install_property()
+ *  \param [in]  value        The GValue the property is being set from
+ *  \param [in]  pspec        A GParamSpec describing the property being set
+ */
+static void
+ghid_violation_renderer_set_property (GObject * object, guint property_id,
+				  const GValue * value, GParamSpec * pspec)
+{
+  GhidViolationRenderer *renderer = GHID_VIOLATION_RENDERER (object);
+  char *markup;
+
+  switch (property_id)
+    {
+    case PROP_VIOLATION:
+      if (renderer->violation != NULL)
+        g_object_unref (renderer->violation);
+      renderer->violation = g_value_dup_object (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      return;
+    }
+
+  if (renderer->violation == NULL)
+    return;
+
+  if (renderer->violation->have_measured)
+    {
+      markup = g_strdup_printf ("<b>%s (%.*f %s)</b>\n"
+                                "<span font_size='1024'> </span>\n"
+                                "<small>"
+                                  "<i>%s</i>\n"
+                                  "<span font_size='5120'> </span>\n"
+                                  "Required: %.*f %s"
+                                "</small>",
+                                renderer->violation->title,
+                                renderer->violation->value_digits,
+                                renderer->violation->measured_value,
+                                renderer->violation->value_units,
+
+                                renderer->violation->explanation,
+
+                                renderer->violation->value_digits,
+                                renderer->violation->required_value,
+                                renderer->violation->value_units);
+    }
+  else
+    {
+      markup = g_strdup_printf ("<b>%s</b>\n"
+                                "<span font_size='1024'> </span>\n"
+                                "<small>"
+                                  "<i>%s</i>\n"
+                                  "<span font_size='5120'> </span>\n"
+                                  "Required: %.*f %s"
+                                "</small>",
+                                renderer->violation->title,
+
+                                renderer->violation->explanation,
+
+                                renderer->violation->value_digits,
+                                renderer->violation->required_value,
+                                renderer->violation->value_units);
+    }
+
+  /* FIXME: Doing this for every property change along the way is going to be slow! */
+  g_object_set (object, "markup", markup, NULL);
+  g_free (markup);
+}
+
+
+/*! \brief GObject property getter function
+ *
+ *  \par Function Description
+ *  Getter function for GhidViolationRenderer's GObject properties,
+ *  "settings-name" and "toplevel".
+ *
+ *  \param [in]  object       The GObject whose properties we are getting
+ *  \param [in]  property_id  The numeric id. under which the property was
+ *                            registered with g_object_class_install_property()
+ *  \param [out] value        The GValue in which to return the value of the property
+ *  \param [in]  pspec        A GParamSpec describing the property being got
+ */
+static void
+ghid_violation_renderer_get_property (GObject * object, guint property_id,
+				  GValue * value, GParamSpec * pspec)
+{
+  switch (property_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+
+}
+
+
+/*! \brief GType class initialiser for GhidViolationRenderer
+ *
+ *  \par Function Description
+ *  GType class initialiser for GhidViolationRenderer. We override our parent
+ *  virtual class methods as needed and register our GObject properties.
+ *
+ *  \param [in]  klass       The GhidViolationRendererClass we are initialising
+ */
+static void
+ghid_violation_renderer_class_init (GhidViolationRendererClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->finalize = ghid_violation_renderer_finalize;
+  gobject_class->set_property = ghid_violation_renderer_set_property;
+  gobject_class->get_property = ghid_violation_renderer_get_property;
+
+  ghid_violation_renderer_parent_class = g_type_class_peek_parent (klass);
+
+  g_object_class_install_property (gobject_class, PROP_VIOLATION,
+				   g_param_spec_object ("violation",
+							"",
+							"",
+							GHID_TYPE_DRC_VIOLATION,
+							G_PARAM_WRITABLE));
+}
+
+
+/*! \brief Function to retrieve GhidViolationRenderer's GType identifier.
+ *
+ *  \par Function Description
+ *  Function to retrieve GhidViolationRenderer's GType identifier.
+ *  Upon first call, this registers the GhidViolationRenderer in the GType system.
+ *  Subsequently it returns the saved value from its first execution.
+ *
+ *  \return the GType identifier associated with GhidViolationRenderer.
+ */
+GType
+ghid_violation_renderer_get_type ()
+{
+  static GType ghid_violation_renderer_type = 0;
+
+  if (!ghid_violation_renderer_type)
+    {
+      static const GTypeInfo ghid_violation_renderer_info = {
+	sizeof (GhidViolationRendererClass),
+	NULL,			/* base_init */
+	NULL,			/* base_finalize */
+	(GClassInitFunc) ghid_violation_renderer_class_init,
+	NULL,			/* class_finalize */
+	NULL,			/* class_data */
+	sizeof (GhidViolationRenderer),
+	0,			/* n_preallocs */
+	NULL,			/* instance_init */
+      };
+
+      ghid_violation_renderer_type =
+	g_type_register_static (GTK_TYPE_CELL_RENDERER_TEXT, "GhidViolationRenderer",
+				&ghid_violation_renderer_info, 0);
+    }
+
+  return ghid_violation_renderer_type;
+}
+
+
+/*! \brief Convenience function to create a new violation renderer
+ *
+ *  \par Function Description
+ *  Convenience function which creates a GhidViolationRenderer.
+ *
+ *  \return  The GhidViolationRenderer created.
+ */
+GtkCellRenderer *
+ghid_violation_renderer_new (void)
+{
+  GhidViolationRenderer *renderer;
+
+  renderer = g_object_new (GHID_TYPE_VIOLATION_RENDERER,
+                           "ypad", 6,
+                           NULL);
+
+  return GTK_CELL_RENDERER (renderer);
+}
+
+
 void
 ghid_drc_window_show (gboolean raise)
 {
-  GtkWidget *vbox, *hbox, *button;
+  GtkWidget *vbox, *hbox, *button, *scrolled_window;
+  GtkCellRenderer *violation_renderer;
 
   if (drc_window)
     {
@@ -78,7 +795,7 @@ ghid_drc_window_show (gboolean raise)
       return;
     }
 
-  drc_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ drc_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
   g_signal_connect (G_OBJECT (drc_window), "destroy",
 		    G_CALLBACK (drc_destroy_cb), NULL);
   g_signal_connect (G_OBJECT (drc_window), "configure_event",
@@ -93,9 +810,51 @@ ghid_drc_window_show (gboolean raise)
   gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
   gtk_container_add (GTK_CONTAINER (drc_window), vbox);
 
-  drc_list = ghid_scrolled_text_view (vbox, NULL,
-				      GTK_POLICY_AUTOMATIC,
-				      GTK_POLICY_AUTOMATIC);
+  drc_list_model = gtk_list_store_new (NUM_DRC_COLUMNS,
+                                       G_TYPE_INT,      /* DRC_VIOLATION_NUM_COL    */
+                                       G_TYPE_OBJECT,   /* DRC_VIOLATION_OBJ_COL    */
+                                       G_TYPE_INT,      /* DRC_OBJECT_COUNT_COL     */
+#warning CHEATING HERE!
+  /* I happen to know I'm only putting 0 or 1 items in the lists of objects.
+     To do this properly requires some memory allocation and tracking to
+     avoid leaks! */
+#if 0
+                                       G_TYPE_POINTER,  /* DRC_OBJECT_ID_LIST_COL   */
+                                       G_TYPE_POINTER); /* DRC_OBJECT_TYPE_LIST_COL */
+#else
+                                       G_TYPE_LONG,     /* DRC_OBJECT_ID_LIST_COL   */
+                                       G_TYPE_INT);     /* DRC_OBJECT_TYPE_LIST_COL */
+#endif
+
+  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+  gtk_box_pack_start (GTK_BOX (vbox), scrolled_window,
+                      TRUE /* EXPAND */, TRUE /* FILL */, 0 /* PADDING */);
+
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+  drc_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (drc_list_model));
+  gtk_container_add (GTK_CONTAINER (scrolled_window), drc_list);
+
+  gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (drc_list), TRUE);
+  g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (drc_list)), "changed",
+                    G_CALLBACK (selection_changed_cb), NULL);
+
+  violation_renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (drc_list),
+                                               -1, /* APPEND */
+                                               _("No."), /* TITLE */
+                                               violation_renderer,
+                                               "text",           DRC_VIOLATION_NUM_COL,
+                                                NULL);
+
+  violation_renderer = ghid_violation_renderer_new ();
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (drc_list),
+                                               -1, /* APPEND */
+                                               _("Violation details"), /* TITLE */
+                                               violation_renderer,
+                                               "violation", DRC_VIOLATION_OBJ_COL,
+                                                NULL);
 
   hbox = gtk_hbutton_box_new ();
   gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_END);
@@ -111,35 +870,68 @@ ghid_drc_window_show (gboolean raise)
   gtk_widget_show_all (drc_window);
 }
 
-static void
-ghid_drc_append_violation (gchar * s)
+#define UNIT1(value) (Settings.grid_units_mm ? ((value) / 100000.0 * 25.4) : ((value) / 100.0))
+#define UNIT(value) UNIT1(value) , (Settings.grid_units_mm ? "mm" : "mils")
+
+void ghid_drc_window_append_violation (DRC_VIOLATION *violation)
 {
+  GhidDrcViolation *violation_obj;
+  GtkTreeIter iter;
+  long int ID = 0;
+  int type = NO_TYPE;
+
+  /* Ensure the required structures are setup */
   ghid_drc_window_show (FALSE);
-}
 
-void ghid_drc_window_reset_message (void)
-{
-  printf ("RESET DRC WINDOW\n");
-}
+  num_violations++;
 
-#if 0
-void ghid_drc_window_append_message (const char *fmt, ...)
-{
-  va_list va;
-  va_start (va, fmt);
-  vprintf (fmt, va);
-  va_end (va);
+  /* Copy the violating object lists */
+#warning CHEATING HERE!
+  /* I happen to know I'm only putting 0 or 1 items in the lists of objects.
+     To do this properly requires some memory allocation and tracking to
+     avoid leaks! */
+  if (violation->object_count > 0)
+    {
+      ID = violation->object_id_list[0];
+      type = violation->object_type_list[0];
+    }
+
+  violation_obj = ghid_drc_violation_new (violation->title,
+                                          violation->explanation,
+                                          violation->x,
+                                          violation->y,
+                                          violation->angle,
+                                          violation->have_measured,
+                                          violation->measured_value,
+                                          violation->required_value,
+                                          violation->value_digits,
+                                          violation->value_units,
+                                          violation->object_count,
+                                          ID, /* violation->object_id_list */
+                                          type); /* violation->object_type_list */
+
+  gtk_list_store_append (drc_list_model, &iter);
+  gtk_list_store_set (drc_list_model, &iter,
+                      DRC_VIOLATION_NUM_COL,    num_violations,
+                      DRC_VIOLATION_OBJ_COL,    violation_obj,
+                      DRC_OBJECT_COUNT_COL,     violation->object_count,
+                      DRC_OBJECT_ID_LIST_COL,   ID, /* violation->object_id_list, */
+                      DRC_OBJECT_TYPE_LIST_COL, type, /* violation->object_type_list, */
+                      -1);
+
+  g_object_unref (violation_obj);
 }
-#endif
 
-void ghid_drc_window_append_messagev (const char *fmt, va_list va)
+void ghid_drc_window_reset_message (void)
 {
-  vprintf (fmt, va);
+  if (drc_list_model != NULL)
+    gtk_list_store_clear (drc_list_model);
+  num_violations = 0;
 }
 
 int ghid_drc_window_throw_dialog (void)
 {
-  printf ("THROW DRC WINDOW\n");
   ghid_drc_window_show (TRUE);
+  return 1;
 }
 
diff --git a/src/hid/gtk/gui-drc-window.h b/src/hid/gtk/gui-drc-window.h
new file mode 100644
index 0000000..56e8769
--- /dev/null
+++ b/src/hid/gtk/gui-drc-window.h
@@ -0,0 +1,111 @@
+/* $Id$ */
+
+/*
+ *                            COPYRIGHT
+ *
+ *  PCB, interactive printed circuit board design
+ *  Copyright (C) 1994,1995,1996 Thomas Nau
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Contact addresses for paper mail and Email:
+ *  Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
+ *  Thomas.Nau@xxxxxxxxxxxxx
+ *
+ */
+
+/* This file written by Peter Clifton */
+
+#ifndef __GUI_DRC_WINDOW_H__
+#define __GUI_DRC_WINDOW_H__
+
+
+#define GHID_TYPE_DRC_VIOLATION           (ghid_drc_violation_get_type())
+#define GHID_DRC_VIOLATION(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GHID_TYPE_DRC_VIOLATION, GhidDrcViolation))
+#define GHID_DRC_VIOLATION_CLASS(klass)   (G_TYPE_CHECK_CLASS_CAST ((klass),  GHID_TYPE_DRC_VIOLATION, GhidDrcViolationClass))
+#define GHID_IS_DRC_VIOLATION(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GHID_TYPE_DRC_VIOLATION))
+#define GHID_DRC_VIOLATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),  GHID_TYPE_DRC_VIOLATION, GhidDrcViolationClass))
+
+typedef struct _GhidDrcViolationClass GhidDrcViolationClass;
+typedef struct _GhidDrcViolation GhidDrcViolation;
+
+
+struct _GhidDrcViolationClass
+{
+  GObjectClass parent_class;
+};
+
+struct _GhidDrcViolation
+{
+  GObject parent_instance;
+
+  char *title;
+  char *explanation;
+  int x_coord;
+  int y_coord;
+  int angle;
+  int have_measured;
+  double measured_value;
+  double required_value;
+  int value_digits;
+  char *value_units;
+};
+
+
+GType ghid_drc_violation_get_type (void);
+
+GhidDrcViolation *ghid_drc_violation_new (char *title,
+                                          char *explanation,
+                                          int x_coord,
+                                          int y_coord,
+                                          int angle,
+                                          int have_measured,
+                                          double measured_value,
+                                          double required_value,
+                                          int value_digits,
+                                          const char *value_units,
+                                          int object_count,
+                                          long int object_id,
+                                          int object_type);
+
+
+#define GHID_TYPE_VIOLATION_RENDERER           (ghid_violation_renderer_get_type())
+#define GHID_VIOLATION_RENDERER(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GHID_TYPE_VIOLATION_RENDERER, GhidViolationRenderer))
+#define GHID_VIOLATION_RENDERER_CLASS(klass)   (G_TYPE_CHECK_CLASS_CAST ((klass),  GHID_TYPE_VIOLATION_RENDERER, GhidViolationRendererClass))
+#define GHID_IS_VIOLATION_RENDERER(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GHID_TYPE_VIOLATION_RENDERER))
+#define GHID_VIOLATION_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),  GHID_TYPE_VIOLATION_RENDERER, GhidViolationRendererClass))
+
+typedef struct _GhidViolationRendererClass GhidViolationRendererClass;
+typedef struct _GhidViolationRenderer GhidViolationRenderer;
+
+
+struct _GhidViolationRendererClass
+{
+  GtkCellRendererTextClass parent_class;
+};
+
+struct _GhidViolationRenderer
+{
+  GtkCellRendererText parent_instance;
+
+  GhidDrcViolation *violation;
+};
+
+
+GType ghid_violation_renderer_get_type (void);
+
+GtkCellRenderer *ghid_violation_renderer_new (void);
+
+#endif /* __GUI_DRC_WINDOW_H__ */
diff --git a/src/hid/gtk/gui.h b/src/hid/gtk/gui.h
index 734d923..f76e3b3 100644
--- a/src/hid/gtk/gui.h
+++ b/src/hid/gtk/gui.h
@@ -407,6 +407,7 @@ int ghid_attribute_dialog (HID_Attribute *, int, HID_Attr_Val *, const char *, c
 /* gui-drc-window.c */
 void ghid_drc_window_show (gboolean raise);
 void ghid_drc_window_reset_message (void);
+void ghid_drc_window_append_violation (DRC_VIOLATION *violation);
 //void ghid_drc_window_append_mesage (const char *fmt, ...);
 void ghid_drc_window_append_messagev (const char *fmt, va_list va);
 int ghid_drc_window_throw_dialog (void);
-- 
1.6.0.4

From 52b4fe59449f15df0611a410ff68b54b69a7137a Mon Sep 17 00:00:00 2001
From: Peter Clifton <pcjc2@xxxxxxxxx>
Date: Thu, 2 Apr 2009 17:26:42 +0100
Subject: [PATCH] Remove log messages for individual design rule violatons

---
 src/find.c                   |   21 ---------------------
 src/hid/gtk/gui-drc-window.c |   10 +++++-----
 2 files changed, 5 insertions(+), 26 deletions(-)

diff --git a/src/find.c b/src/find.c
index 8f3ebb8..d224409 100644
--- a/src/find.c
+++ b/src/find.c
@@ -3579,9 +3579,6 @@ DRCFind (int What, void *ptr1, void *ptr2, void *ptr3)
       if (DoIt (True, False))
         {
           DumpList ();
-          Message
-            (_
-             ("WARNING!!  Design Rule Error - potential for broken trace!\n"));
           /* make the flag changes undoable */
           TheFlag = FOUNDFLAG | SELECTEDFLAG;
           ResetConnections (False);
@@ -3642,7 +3639,6 @@ DRCFind (int What, void *ptr1, void *ptr2, void *ptr3)
   while (DoIt (True, False))
     {
       DumpList ();
-      Message (_("WARNING!  Design Rule error - copper areas too close!\n"));
       /* make the flag changes undoable */
       TheFlag = FOUNDFLAG | SELECTEDFLAG;
       ResetConnections (False);
@@ -3756,7 +3752,6 @@ drc_callback (DataTypePtr data, LayerTypePtr layer, PolygonTypePtr polygon,
           AddObjectToFlagUndoList (type, ptr1, ptr2, ptr2);
           SET_FLAG (TheFlag, line);
           message = _("Line with insufficient clearance inside polygon\n");
-          Message (message);
           goto doIsBad;
         }
       break;
@@ -3766,7 +3761,6 @@ drc_callback (DataTypePtr data, LayerTypePtr layer, PolygonTypePtr polygon,
           AddObjectToFlagUndoList (type, ptr1, ptr2, ptr2);
           SET_FLAG (TheFlag, arc);
           message = _("Arc with insufficient clearance inside polygon\n");
-          Message (message);
           goto doIsBad;
         }
       break;
@@ -3777,7 +3771,6 @@ drc_callback (DataTypePtr data, LayerTypePtr layer, PolygonTypePtr polygon,
 	    AddObjectToFlagUndoList (type, ptr1, ptr2, ptr2);
 	    SET_FLAG (TheFlag, pad);
 	    message = _("Pad with insufficient clearance inside polygon\n");
-	    Message (message);
 	    goto doIsBad;
 	  }
       break;
@@ -3787,7 +3780,6 @@ drc_callback (DataTypePtr data, LayerTypePtr layer, PolygonTypePtr polygon,
           AddObjectToFlagUndoList (type, ptr1, ptr2, ptr2);
           SET_FLAG (TheFlag, pin);
           message = _("Pin with insufficient clearance inside polygon\n");
-          Message (message);
           goto doIsBad;
         }
       break;
@@ -3797,7 +3789,6 @@ drc_callback (DataTypePtr data, LayerTypePtr layer, PolygonTypePtr polygon,
           AddObjectToFlagUndoList (type, ptr1, ptr2, ptr2);
           SET_FLAG (TheFlag, pin);
           message = _("Via with insufficient clearance inside polygon\n");
-          Message (message);
           goto doIsBad;
         }
       break;
@@ -3934,7 +3925,6 @@ DRCAll (void)
           {
             AddObjectToFlagUndoList (LINE_TYPE, layer, line, line);
             SET_FLAG (TheFlag, line);
-            Message (_("Line is too thin\n"));
             DrawLine (layer, line, 0);
             drcerr_count++;
             SetThing (LINE_TYPE, layer, line, line);
@@ -3979,7 +3969,6 @@ DRCAll (void)
           {
             AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc);
             SET_FLAG (TheFlag, arc);
-            Message (_("Arc is too thin\n"));
             DrawArc (layer, arc, 0);
             drcerr_count++;
             SetThing (ARC_TYPE, layer, arc, arc);
@@ -4025,8 +4014,6 @@ DRCAll (void)
           {
             AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
             SET_FLAG (TheFlag, pin);
-            Message (_
-                     ("Pin annular ring is too small based on minimum annular ring\n"));
             DrawPin (pin, 0);
             drcerr_count++;
             SetThing (PIN_TYPE, element, pin, pin);
@@ -4061,7 +4048,6 @@ DRCAll (void)
           {
             AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
             SET_FLAG (TheFlag, pin);
-            Message (_("Pin drill size is too small\n"));
             DrawPin (pin, 0);
             drcerr_count++;
             SetThing (PIN_TYPE, element, pin, pin);
@@ -4105,7 +4091,6 @@ DRCAll (void)
           {
             AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
             SET_FLAG (TheFlag, pad);
-            Message (_("Pad is too thin\n"));
             DrawPad (pad, 0);
             drcerr_count++;
             SetThing (PAD_TYPE, element, pad, pad);
@@ -4151,8 +4136,6 @@ DRCAll (void)
           {
             AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
             SET_FLAG (TheFlag, via);
-            Message (_
-                     ("Via annular ring is too small based on minimum annular ring\n"));
             DrawVia (via, 0);
             drcerr_count++;
             SetThing (VIA_TYPE, via, via, via);
@@ -4187,7 +4170,6 @@ DRCAll (void)
           {
             AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
             SET_FLAG (TheFlag, via);
-            Message (_("Via drill size is too small\n"));
             DrawVia (via, 0);
             drcerr_count++;
             SetThing (VIA_TYPE, via, via, via);
@@ -4236,7 +4218,6 @@ DRCAll (void)
         if (line->Thickness < PCB->minSlk)
           {
             SET_FLAG (TheFlag, line);
-            Message (_("Silk line is too thin\n"));
             DrawLine (layer, line, 0);
             drcerr_count++;
             SetThing (LINE_TYPE, layer, line, line);
@@ -4291,8 +4272,6 @@ DRCAll (void)
             int buflen;
 
             SET_FLAG (TheFlag, element);
-            Message (_("Element %s has %d silk lines which are too thin\n"),
-                     UNKNOWN (NAMEONPCB_NAME (element)), tmpcnt);
 //            append_drc_dialog_message (_
 //                     ("%i silk lines\n of element %s\nare too thin\n"),
 //                     tmpcnt, UNKNOWN (NAMEONPCB_NAME (element)));
diff --git a/src/hid/gtk/gui-drc-window.c b/src/hid/gtk/gui-drc-window.c
index b443a0d..620c272 100644
--- a/src/hid/gtk/gui-drc-window.c
+++ b/src/hid/gtk/gui-drc-window.c
@@ -845,8 +845,8 @@ ghid_drc_window_show (gboolean raise)
                                                -1, /* APPEND */
                                                _("No."), /* TITLE */
                                                violation_renderer,
-                                               "text",           DRC_VIOLATION_NUM_COL,
-                                                NULL);
+                                               "text", DRC_VIOLATION_NUM_COL,
+                                               NULL);
 
   violation_renderer = ghid_violation_renderer_new ();
   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (drc_list),
@@ -854,7 +854,7 @@ ghid_drc_window_show (gboolean raise)
                                                _("Violation details"), /* TITLE */
                                                violation_renderer,
                                                "violation", DRC_VIOLATION_OBJ_COL,
-                                                NULL);
+                                               NULL);
 
   hbox = gtk_hbutton_box_new ();
   gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_END);
@@ -907,7 +907,7 @@ void ghid_drc_window_append_violation (DRC_VIOLATION *violation)
                                           violation->value_digits,
                                           violation->value_units,
                                           violation->object_count,
-                                          ID, /* violation->object_id_list */
+                                          ID,    /* violation->object_id_list */
                                           type); /* violation->object_type_list */
 
   gtk_list_store_append (drc_list_model, &iter);
@@ -915,7 +915,7 @@ void ghid_drc_window_append_violation (DRC_VIOLATION *violation)
                       DRC_VIOLATION_NUM_COL,    num_violations,
                       DRC_VIOLATION_OBJ_COL,    violation_obj,
                       DRC_OBJECT_COUNT_COL,     violation->object_count,
-                      DRC_OBJECT_ID_LIST_COL,   ID, /* violation->object_id_list, */
+                      DRC_OBJECT_ID_LIST_COL,   ID,   /* violation->object_id_list, */
                       DRC_OBJECT_TYPE_LIST_COL, type, /* violation->object_type_list, */
                       -1);
 
-- 
1.6.0.4

From 0400258cdada2fef4333c2c267b2f5c2f1a63cef Mon Sep 17 00:00:00 2001
From: Peter Clifton <pcjc2@xxxxxxxxx>
Date: Thu, 2 Apr 2009 17:26:43 +0100
Subject: [PATCH] Attempt to preview the drc violations on the board

---
 src/Makefile.am                 |    1 +
 src/hid/gtk/gui-drc-window.c    |  103 ++++++++++++++++++++++++-
 src/hid/gtk/gui-drc-window.h    |    4 +-
 src/hid/gtk/gui-pixmap-render.c |  159 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 263 insertions(+), 4 deletions(-)
 create mode 100644 src/hid/gtk/gui-pixmap-render.c

diff --git a/src/Makefile.am b/src/Makefile.am
index f35a45f..3ce2fc1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -253,6 +253,7 @@ LIBGTK_SRCS = \
 	hid/gtk/gui-pinout-preview.c \
 	hid/gtk/gui-pinout-preview.h \
 	hid/gtk/gui-pinout-window.c \
+	hid/gtk/gui-pixmap-render.c \
 	hid/gtk/gui-top-window.c \
 	hid/gtk/gui-utils.c \
 	hid/gtk/snavi.c \
diff --git a/src/hid/gtk/gui-drc-window.c b/src/hid/gtk/gui-drc-window.c
index 620c272..e6c3e2f 100644
--- a/src/hid/gtk/gui-drc-window.c
+++ b/src/hid/gtk/gui-drc-window.c
@@ -42,6 +42,9 @@
 #include <dmalloc.h>
 #endif
 
+#define VIOLATION_PIXMAP_SIZE 100
+#define VIOLATION_PIXMAP_BORDER 5
+
 RCSID ("$Id$");
 
 static GtkWidget *drc_window, *drc_list;
@@ -286,7 +289,8 @@ enum
   PROP_MEASURED_VALUE,
   PROP_REQUIRED_VALUE,
   PROP_VALUE_DIGITS,
-  PROP_VALUE_UNITS
+  PROP_VALUE_UNITS,
+  PROP_PIXMAP
 };
 
 
@@ -309,6 +313,8 @@ ghid_drc_violation_finalize (GObject * object)
   g_free (violation->title);
   g_free (violation->explanation);
   g_free (violation->value_units);
+  if (violation->pixmap != NULL)
+    g_object_unref (violation->pixmap);
 
   G_OBJECT_CLASS (ghid_drc_violation_parent_class)->finalize (object);
 }
@@ -366,6 +372,10 @@ ghid_drc_violation_set_property (GObject * object, guint property_id,
       g_free (violation->value_units);
       violation->value_units = g_value_dup_string (value);
       break;
+    case PROP_PIXMAP:
+      if (violation->pixmap)
+        g_object_unref (violation->pixmap);           /* Frees our old reference */
+      violation->pixmap = g_value_dup_object (value); /* Takes a new reference */
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -492,6 +502,12 @@ ghid_drc_violation_class_init (GhidViolationRendererClass * klass)
 							"",
 							"",
 							G_PARAM_WRITABLE));
+  g_object_class_install_property (gobject_class, PROP_PIXMAP,
+				   g_param_spec_object ("pixmap",
+							"",
+							"",
+							GDK_TYPE_DRAWABLE,
+							G_PARAM_WRITABLE));
 }
 
 
@@ -545,7 +561,8 @@ GhidDrcViolation *ghid_drc_violation_new (char *title,
                                           const char *value_units,
                                           int object_count,
                                           long int object_id,
-                                          int object_type)
+                                          int object_type,
+                                          GdkDrawable *pixmap)
 {
   GhidDrcViolation *violation = g_object_new (GHID_TYPE_DRC_VIOLATION,
                                              "title",          title,
@@ -558,6 +575,7 @@ GhidDrcViolation *ghid_drc_violation_new (char *title,
                                              "required-value", required_value,
                                              "value-digits",   value_digits,
                                              "value-units",    value_units,
+                                             "pixmap",         pixmap,
                                              NULL);
 //  violation->object_count     = object_count;
 //  violation->object_id        = object_id;
@@ -565,6 +583,7 @@ GhidDrcViolation *ghid_drc_violation_new (char *title,
   return violation;
 }
 
+
 enum
 {
   PROP_VIOLATION = 1,
@@ -696,6 +715,79 @@ ghid_violation_renderer_get_property (GObject * object, guint property_id,
 
 }
 
+static void
+ghid_violation_renderer_get_size (GtkCellRenderer      *cell,
+                                  GtkWidget            *widget,
+                                  GdkRectangle         *cell_area,
+                                  gint                 *x_offset,
+                                  gint                 *y_offset,
+                                  gint                 *width,
+                                  gint                 *height)
+{
+  GTK_CELL_RENDERER_CLASS (ghid_violation_renderer_parent_class)->get_size (cell,
+                                                                            widget,
+                                                                            cell_area,
+                                                                            x_offset,
+                                                                            y_offset,
+                                                                            width,
+                                                                            height);
+  if (width != NULL)
+    *width += VIOLATION_PIXMAP_SIZE;
+  if (height != NULL)
+    *height = MAX (*height, VIOLATION_PIXMAP_SIZE);
+}
+
+extern GdkPixmap *pixmap_render (int cx, int cy, double zoom, int width, int height);
+
+static void
+ghid_violation_renderer_render (GtkCellRenderer      *cell,
+                                GdkDrawable          *window,
+                                GtkWidget            *widget,
+                                GdkRectangle         *background_area,
+                                GdkRectangle         *cell_area,
+                                GdkRectangle         *expose_area,
+                                GtkCellRendererState  flags)
+{
+  GdkGC *gc;
+  GdkDrawable *mydrawable;
+  GhidViolationRenderer *renderer = GHID_VIOLATION_RENDERER (cell);
+  GhidDrcViolation *violation = renderer->violation;
+  int pixmap_size = VIOLATION_PIXMAP_SIZE - 2 * VIOLATION_PIXMAP_BORDER;
+
+  cell_area->width -= VIOLATION_PIXMAP_SIZE;
+  GTK_CELL_RENDERER_CLASS (ghid_violation_renderer_parent_class)->render (cell,
+                                                                          window,
+                                                                          widget,
+                                                                          background_area,
+                                                                          cell_area,
+                                                                          expose_area,
+                                                                          flags);
+
+  if (violation == NULL)
+    return;
+
+  if (violation->pixmap == NULL)
+    {
+      GdkPixmap *pixmap = pixmap_render (violation->x_coord,
+                                         violation->y_coord,
+                                         10000 / pixmap_size,
+                                         pixmap_size, pixmap_size);
+      g_object_set (violation, "pixmap", pixmap, NULL);
+      g_object_unref (pixmap);
+    }
+
+  if (violation->pixmap == NULL)
+    return;
+
+  mydrawable = GDK_DRAWABLE (violation->pixmap);
+
+  gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
+  gdk_draw_drawable (window, gc, mydrawable,
+                     0, 0,
+                     cell_area->x + cell_area->width + VIOLATION_PIXMAP_BORDER,
+                     cell_area->y + VIOLATION_PIXMAP_BORDER, -1, -1);
+}
+
 
 /*! \brief GType class initialiser for GhidViolationRenderer
  *
@@ -709,11 +801,15 @@ static void
 ghid_violation_renderer_class_init (GhidViolationRendererClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GtkCellRendererClass *cellrenderer_class = GTK_CELL_RENDERER_CLASS (klass);
 
   gobject_class->finalize = ghid_violation_renderer_finalize;
   gobject_class->set_property = ghid_violation_renderer_set_property;
   gobject_class->get_property = ghid_violation_renderer_get_property;
 
+  cellrenderer_class->get_size = ghid_violation_renderer_get_size;
+  cellrenderer_class->render = ghid_violation_renderer_render;
+
   ghid_violation_renderer_parent_class = g_type_class_peek_parent (klass);
 
   g_object_class_install_property (gobject_class, PROP_VIOLATION,
@@ -908,7 +1004,8 @@ void ghid_drc_window_append_violation (DRC_VIOLATION *violation)
                                           violation->value_units,
                                           violation->object_count,
                                           ID,    /* violation->object_id_list */
-                                          type); /* violation->object_type_list */
+                                          type,  /* violation->object_type_list */
+                                          NULL); /* pixmap */
 
   gtk_list_store_append (drc_list_model, &iter);
   gtk_list_store_set (drc_list_model, &iter,
diff --git a/src/hid/gtk/gui-drc-window.h b/src/hid/gtk/gui-drc-window.h
index 56e8769..9998d18 100644
--- a/src/hid/gtk/gui-drc-window.h
+++ b/src/hid/gtk/gui-drc-window.h
@@ -61,6 +61,7 @@ struct _GhidDrcViolation
   double required_value;
   int value_digits;
   char *value_units;
+  GdkDrawable *pixmap;
 };
 
 
@@ -78,7 +79,8 @@ GhidDrcViolation *ghid_drc_violation_new (char *title,
                                           const char *value_units,
                                           int object_count,
                                           long int object_id,
-                                          int object_type);
+                                          int object_type,
+                                          GdkDrawable *pixmap);
 
 
 #define GHID_TYPE_VIOLATION_RENDERER           (ghid_violation_renderer_get_type())
diff --git a/src/hid/gtk/gui-pixmap-render.c b/src/hid/gtk/gui-pixmap-render.c
new file mode 100644
index 0000000..7fc58d1
--- /dev/null
+++ b/src/hid/gtk/gui-pixmap-render.c
@@ -0,0 +1,159 @@
+/* $Id$ */
+
+/*
+ *                            COPYRIGHT
+ *
+ *  PCB, interactive printed circuit board design
+ *  Copyright (C) 1994,1995,1996 Thomas Nau
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Contact addresses for paper mail and Email:
+ *  Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
+ *  Thomas.Nau@xxxxxxxxxxxxx
+ *
+ */
+
+/* This file written by Peter Clifton, starting from
+ * gui-pinout-preview.c */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "global.h"
+
+#include "gui.h"
+
+#include "copy.h"
+#include "data.h"
+#include "draw.h"
+#include "mymem.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+RCSID ("$Id$");
+
+
+#define Z_NEAR 3.0
+
+GdkPixmap *
+pixmap_render (int cx, int cy, double zoom, int width, int height)
+{
+  extern HID ghid_hid;
+  GdkGLConfig *glconfig;
+  GdkPixmap *pixmap;
+  GdkGLPixmap *glpixmap;
+  GdkGLContext* glcontext;
+  GdkGLDrawable* gldrawable;
+  double save_zoom;
+  int save_left, save_top;
+  int save_width, save_height;
+  int save_view_width, save_view_height;
+
+  save_zoom = gport->zoom;
+  save_width = gport->width;
+  save_height = gport->height;
+  save_left = gport->view_x0;
+  save_top = gport->view_y0;
+  save_view_width = gport->view_width;
+  save_view_height = gport->view_height;
+
+
+  /* Try single-buffered visual */
+  glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB     |
+                                        GDK_GL_MODE_STENCIL |
+//                                        GDK_GL_MODE_DEPTH   |
+                                        GDK_GL_MODE_SINGLE);
+
+  pixmap = gdk_pixmap_new (NULL, width, height, 24); /* FIXME HARDCODING 24 */
+  glpixmap = gdk_pixmap_set_gl_capability (pixmap, glconfig, NULL);
+  gldrawable = GDK_GL_DRAWABLE (glpixmap);
+  glcontext = gdk_gl_context_new (gldrawable, NULL, FALSE, GDK_GL_RGBA_TYPE);
+
+  /* Setup zoom factor for drawing routines */
+
+  gport->zoom = zoom;
+  gport->width = width;                         // Pixels
+  gport->height = height;                       // Pixels
+  gport->view_width = width * gport->zoom;      // PCB Units
+  gport->view_height = height * gport->zoom;    // PCB Units
+  gport->view_x0 = cx - gport->view_height / 2; // PCB Units
+  gport->view_y0 = cy - gport->view_width / 2;  // PCB Units
+
+  /* make GL-context "current" */
+  if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext)) {
+    return FALSE;
+  }
+
+  glEnable (GL_BLEND);
+  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+  glViewport (0, 0, width, height);
+
+//  glEnable (GL_SCISSOR_TEST);
+//  glScissor (0, 0, width, height);
+
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity ();
+  glOrtho (0, width, height, 0, 0, 100);
+  glMatrixMode (GL_MODELVIEW);
+  glLoadIdentity ();
+  glTranslatef (0.0f, 0.0f, -Z_NEAR);
+
+  glClearColor (gport->bg_color.red / 65535.,
+                gport->bg_color.green / 65535.,
+                gport->bg_color.blue / 65535.,
+                1.);
+  glClearStencil (0);
+  glClear (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+  /* call the drawing routine */
+  hidgl_init_triangle_array (&buffer);
+  ghid_invalidate_current_gc ();
+  glPushMatrix ();
+  glScalef ((ghid_flip_x ? -1. : 1.) / gport->zoom,
+            (ghid_flip_y ? -1. : 1.) / gport->zoom, 1);
+  glTranslatef (ghid_flip_x ? gport->view_x0 - PCB->MaxWidth  :
+                             -gport->view_x0,
+                ghid_flip_y ? gport->view_y0 - PCB->MaxHeight :
+                             -gport->view_y0, 0);
+  hid_expose_callback (&ghid_hid, NULL, NULL);
+  hidgl_flush_triangles (&buffer);
+  glPopMatrix ();
+
+  glFlush ();
+
+  /* end drawing to current GL-context */
+  gdk_gl_drawable_gl_end (gldrawable);
+//  gdk_gl_context_destroy (glcontext);
+
+  gdk_pixmap_unset_gl_capability (pixmap);
+
+  g_object_unref (glconfig);
+  g_object_unref (glcontext);
+
+  gport->zoom = save_zoom;
+  gport->width = save_width;
+  gport->height = save_height;
+  gport->view_x0 = save_left;
+  gport->view_y0 = save_top;
+  gport->view_width = save_view_width;
+  gport->view_height = save_view_height;
+
+  return pixmap;
+}
-- 
1.6.0.4


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