From 1535c83b880eda60a2e8b3f47cf5c415b72fadb8 Mon Sep 17 00:00:00 2001
From: Jeff Young <jeff@rokeby.ie>
Date: Fri, 24 Apr 2020 14:36:10 +0100
Subject: [PATCH] Lay some groundwork for adding distances to DRC errors.

	modified:   eeschema/lib_rectangle.cpp
---
 common/dialogs/panel_setup_severities.cpp     |   2 +-
 common/eda_draw_frame.cpp                     |   2 +-
 common/marker_base.cpp                        |  51 ----
 common/page_layout/ws_draw_item.cpp           |   7 +-
 common/rc_item.cpp                            |  63 +++--
 common/rc_item.h                              | 179 ++-----------
 cvpcb/display_footprints_frame.cpp            |   2 +-
 eeschema/bus-wire-junction.cpp                |  17 +-
 eeschema/connection_graph.cpp                 |  67 ++---
 eeschema/dialogs/dialog_erc.cpp               |  20 +-
 eeschema/dialogs/dialog_schematic_setup.cpp   |   2 +-
 eeschema/erc.cpp                              | 108 ++++----
 eeschema/erc_item.cpp                         |   2 +-
 eeschema/erc_item.h                           | 118 +--------
 eeschema/lib_arc.cpp                          |   8 +-
 eeschema/lib_arc.h                            |   4 +-
 eeschema/lib_bezier.cpp                       |  11 +-
 eeschema/lib_bezier.h                         |   4 +-
 eeschema/lib_circle.cpp                       |  10 +-
 eeschema/lib_circle.h                         |   4 +-
 eeschema/lib_field.cpp                        |   9 +-
 eeschema/lib_field.h                          |   4 +-
 eeschema/lib_item.cpp                         |   2 +-
 eeschema/lib_item.h                           |   3 +-
 eeschema/lib_pin.cpp                          |  24 +-
 eeschema/lib_pin.h                            |  10 +-
 eeschema/lib_polyline.cpp                     |   9 +-
 eeschema/lib_polyline.h                       |   4 +-
 eeschema/lib_rectangle.cpp                    |   8 +-
 eeschema/lib_rectangle.h                      |   4 +-
 eeschema/lib_text.cpp                         |   8 +-
 eeschema/lib_text.h                           |   4 +-
 eeschema/sch_bitmap.cpp                       |  12 +-
 eeschema/sch_bitmap.h                         |   4 +-
 eeschema/sch_bus_entry.cpp                    |   2 +-
 eeschema/sch_bus_entry.h                      |   4 +-
 eeschema/sch_component.cpp                    |  12 +-
 eeschema/sch_component.h                      |   4 +-
 eeschema/sch_eagle_plugin.cpp                 |  48 ++--
 eeschema/sch_edit_frame.cpp                   |  14 +-
 eeschema/sch_edit_frame.h                     |   2 +
 eeschema/sch_field.cpp                        |   9 +-
 eeschema/sch_field.h                          |   2 +-
 eeschema/sch_item.h                           |   8 +-
 eeschema/sch_junction.h                       |   2 +-
 eeschema/sch_line.cpp                         |   2 +-
 eeschema/sch_line.h                           |   4 +-
 eeschema/sch_marker.cpp                       |  14 +-
 eeschema/sch_marker.h                         |   7 +-
 eeschema/sch_no_connect.h                     |   2 +-
 eeschema/sch_pin.cpp                          |  24 +-
 eeschema/sch_pin.h                            |   6 +-
 eeschema/sch_sheet.cpp                        |   2 +-
 eeschema/sch_sheet.h                          |   4 +-
 eeschema/sch_sheet_path.cpp                   | 131 ++++++++-
 eeschema/sch_sheet_path.h                     |  35 +++
 eeschema/sch_text.cpp                         |   4 +-
 eeschema/sch_text.h                           |   4 +-
 eeschema/tools/ee_inspection_tool.cpp         |   2 +-
 eeschema/tools/ee_selection.cpp               |  21 +-
 eeschema/tools/lib_edit_tool.cpp              |   2 +-
 eeschema/tools/lib_pin_tool.cpp               |   2 +-
 gerbview/gerber_draw_item.cpp                 |   2 +-
 gerbview/gerber_draw_item.h                   |   4 +-
 gerbview/gerbview_draw_panel_gal.cpp          |   4 +-
 gerbview/gerbview_draw_panel_gal.h            |   2 +-
 gerbview/tools/gerbview_control.cpp           |   2 +-
 gerbview/tools/gerbview_selection.cpp         |   2 +-
 include/base_struct.h                         |   7 +-
 include/class_board_item.h                    |   2 -
 include/class_draw_panel_gal.h                |   2 +-
 include/eda_draw_frame.h                      |   5 +
 include/marker_base.h                         |  72 -----
 include/pcb_base_frame.h                      |   2 +
 include/ws_draw_item.h                        |   3 +-
 pagelayout_editor/pl_draw_panel_gal.cpp       |   3 +-
 pagelayout_editor/pl_draw_panel_gal.h         |   2 +-
 pagelayout_editor/tools/pl_edit_tool.cpp      |   7 +-
 pagelayout_editor/tools/pl_editor_control.cpp |   2 +-
 pagelayout_editor/tools/pl_selection.cpp      |  18 +-
 pcbnew/board_design_settings.cpp              |   9 +
 pcbnew/class_board.cpp                        |  33 ++-
 pcbnew/class_board.h                          |   4 +-
 pcbnew/class_dimension.cpp                    |   4 +-
 pcbnew/class_dimension.h                      |   2 +-
 pcbnew/class_drawsegment.cpp                  |  27 +-
 pcbnew/class_drawsegment.h                    |   2 +-
 pcbnew/class_edge_mod.cpp                     |   4 +-
 pcbnew/class_edge_mod.h                       |   2 +-
 pcbnew/class_marker_pcb.cpp                   |  88 +++----
 pcbnew/class_marker_pcb.h                     |  58 +---
 pcbnew/class_module.cpp                       |   2 +-
 pcbnew/class_module.h                         |   2 +-
 pcbnew/class_pad.cpp                          |  20 +-
 pcbnew/class_pad.h                            |   2 +-
 pcbnew/class_pcb_text.cpp                     |   8 +-
 pcbnew/class_pcb_text.h                       |   2 +-
 pcbnew/class_text_mod.cpp                     |   8 +-
 pcbnew/class_text_mod.h                       |   2 +-
 pcbnew/class_track.cpp                        |  36 +--
 pcbnew/class_track.h                          |   8 +-
 pcbnew/class_zone.cpp                         |   4 +-
 pcbnew/class_zone.h                           |   2 +-
 pcbnew/cross-probing.cpp                      |   2 +-
 pcbnew/dialogs/dialog_board_setup.cpp         |   2 +-
 .../dialog_cleanup_tracks_and_vias.cpp        |  25 +-
 .../dialog_cleanup_tracks_and_vias_base.cpp   |   2 +-
 .../dialog_cleanup_tracks_and_vias_base.fbp   |   2 +-
 pcbnew/dialogs/dialog_drc.cpp                 |   9 +-
 pcbnew/dialogs/dialog_netlist.cpp             |   2 +-
 pcbnew/drc/courtyard_overlap.cpp              |  33 ++-
 pcbnew/drc/courtyard_overlap.h                |   4 +-
 pcbnew/drc/drc.cpp                            | 249 +++++++++++-------
 pcbnew/drc/drc.h                              |  11 +-
 pcbnew/drc/drc_clearance_test_functions.cpp   | 210 ++++++++++-----
 pcbnew/drc/drc_item.cpp                       |  41 ++-
 pcbnew/drc/drc_item.h                         | 214 +--------------
 pcbnew/drc/drc_provider.h                     | 237 +++++++++++++++--
 pcbnew/footprint_wizard_frame.cpp             |   2 +-
 pcbnew/netinfo.h                              |   2 +-
 pcbnew/netinfo_item.cpp                       |   8 +-
 pcbnew/pcb_base_frame.cpp                     |   6 +
 pcbnew/pcb_draw_panel_gal.cpp                 |   3 +-
 pcbnew/pcb_draw_panel_gal.h                   |   2 +-
 pcbnew/tools/pcb_inspection_tool.cpp          |   2 +-
 pcbnew/tools/pcbnew_control.cpp               |   2 +-
 pcbnew/tools/pcbnew_selection.cpp             |  16 +-
 pcbnew/tools/position_relative_tool.cpp       |   2 +-
 pcbnew/tracks_cleaner.cpp                     |  41 ++-
 pcbnew/undo_redo.cpp                          |   2 +-
 qa/eeschema/test_sch_pin.cpp                  |   2 +-
 qa/pcbnew/drc/test_drc_courtyard_invalid.cpp  |   4 +-
 qa/pcbnew/drc/test_drc_courtyard_overlap.cpp  |  15 +-
 qa/pcbnew_tools/tools/drc_tool/drc_tool.cpp   |  31 ++-
 134 files changed, 1395 insertions(+), 1417 deletions(-)

diff --git a/common/dialogs/panel_setup_severities.cpp b/common/dialogs/panel_setup_severities.cpp
index 12e1cb3b9f..2ef6607b73 100644
--- a/common/dialogs/panel_setup_severities.cpp
+++ b/common/dialogs/panel_setup_severities.cpp
@@ -48,7 +48,7 @@ PANEL_SETUP_SEVERITIES::PANEL_SETUP_SEVERITIES( PAGED_DIALOG* aParent, RC_ITEM&
 
    	for( int errorCode = m_firstErrorCode; errorCode <= m_lastErrorCode; ++errorCode )
     {
-   	    aDummyItem.SetData( errorCode, wxEmptyString );
+   	    aDummyItem.SetErrorCode( errorCode );
    	    wxString msg = aDummyItem.GetErrorText();
 
         // When msg is empty, for some reason, the current errorCode is not supported
diff --git a/common/eda_draw_frame.cpp b/common/eda_draw_frame.cpp
index f7d18b01b3..a6b3633591 100644
--- a/common/eda_draw_frame.cpp
+++ b/common/eda_draw_frame.cpp
@@ -547,7 +547,7 @@ void EDA_DRAW_FRAME::SetMsgPanel( EDA_ITEM* aItem )
     wxCHECK_RET( aItem, wxT( "Invalid EDA_ITEM pointer.  Bad programmer." ) );
 
     MSG_PANEL_ITEMS items;
-    aItem->GetMsgPanelInfo( m_userUnits, items );
+    aItem->GetMsgPanelInfo( this, items );
     SetMsgPanel( items );
 }
 
diff --git a/common/marker_base.cpp b/common/marker_base.cpp
index 50481f97a6..2bf8e90a22 100644
--- a/common/marker_base.cpp
+++ b/common/marker_base.cpp
@@ -32,7 +32,6 @@
 
 #include "fctsys.h"
 #include "base_screen.h"
-#include "common.h"
 #include "macros.h"
 #include "marker_base.h"
 #include <geometry/shape_line_chain.h>
@@ -89,56 +88,6 @@ MARKER_BASE::~MARKER_BASE()
 }
 
 
-void MARKER_BASE::SetData( EDA_UNITS aUnits, int aErrorCode, const wxPoint& aMarkerPos,
-                           EDA_ITEM* aItem, const wxPoint& aPos,
-                           EDA_ITEM* bItem, const wxPoint& bPos )
-{
-    m_Pos = aMarkerPos;
-    m_rcItem->SetData( aUnits, aErrorCode, aItem, aPos, bItem, bPos );
-    m_rcItem->SetParent( this );
-}
-
-
-void MARKER_BASE::SetData( int aErrorCode, const wxPoint& aMarkerPos,
-                           const wxString& aText, const wxPoint& aPos,
-                           const wxString& bText, const wxPoint& bPos )
-{
-    m_Pos = aMarkerPos;
-    m_rcItem->SetData( aErrorCode, aText, aPos, bText, bPos );
-    m_rcItem->SetParent( this );
-}
-
-
-void MARKER_BASE::SetData( EDA_UNITS aUnits, int aErrorCode, const wxPoint& aMarkerPos,
-                           EDA_ITEM* aItem,
-                           EDA_ITEM* bItem )
-{
-    m_Pos = aMarkerPos;
-    m_rcItem->SetData( aUnits, aErrorCode, aItem, bItem );
-    m_rcItem->SetParent( this );
-}
-
-
-void MARKER_BASE::SetData( int aErrorCode, const wxPoint& aMarkerPos,
-                           const wxString& aText,
-                           const wxString& bText )
-{
-    m_Pos = aMarkerPos;
-    m_rcItem->SetData( aErrorCode, aText, bText );
-    m_rcItem->SetParent( this );
-}
-
-
-void MARKER_BASE::SetData( int aErrorCode, const wxPoint& aMarkerPos,
-                           const wxString& aText, const KIID& aID,
-                           const wxString& bText, const KIID& bID )
-{
-    m_Pos = aMarkerPos;
-    m_rcItem->SetData( aErrorCode, aText, aID, bText, bID );
-    m_rcItem->SetParent( this );
-}
-
-
 bool MARKER_BASE::HitTestMarker( const wxPoint& aHitPosition, int aAccuracy ) const
 {
     EDA_RECT bbox = GetBoundingBoxMarker();
diff --git a/common/page_layout/ws_draw_item.cpp b/common/page_layout/ws_draw_item.cpp
index a4e6f1b973..5d7923f182 100644
--- a/common/page_layout/ws_draw_item.cpp
+++ b/common/page_layout/ws_draw_item.cpp
@@ -50,6 +50,7 @@
 
 #include <fctsys.h>
 #include <eda_rect.h>
+#include <eda_draw_frame.h>
 #include <gr_text.h>
 #include <ws_draw_item.h>
 #include <ws_data_model.h>
@@ -95,7 +96,7 @@ bool WS_DRAW_ITEM_BASE::HitTest( const EDA_RECT& aRect, bool aContained, int aAc
 }
 
 
-void WS_DRAW_ITEM_BASE::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
+void WS_DRAW_ITEM_BASE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
 {
     wxString            msg;
     WS_DATA_ITEM* dataItem = GetPeer();
@@ -144,8 +145,8 @@ void WS_DRAW_ITEM_BASE::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aLis
     aList.push_back( MSG_PANEL_ITEM( _( "Repeat Label Increment" ), msg, DARKGRAY ) );
 
     msg.Printf( wxT( "(%s, %s)" ),
-                MessageTextFromValue( aUnits, dataItem->m_IncrementVector.x ),
-                MessageTextFromValue( aUnits, dataItem->m_IncrementVector.y ) );
+                MessageTextFromValue( aFrame->GetUserUnits(), dataItem->m_IncrementVector.x ),
+                MessageTextFromValue( aFrame->GetUserUnits(), dataItem->m_IncrementVector.y ) );
 
     aList.push_back( MSG_PANEL_ITEM( _( "Repeat Position Increment" ), msg, RED ) );
 
diff --git a/common/rc_item.cpp b/common/rc_item.cpp
index 29a8575ed7..b2aaff078f 100644
--- a/common/rc_item.cpp
+++ b/common/rc_item.cpp
@@ -26,7 +26,7 @@
 #include <wx/dataview.h>
 #include <widgets/ui_common.h>
 #include <marker_base.h>
-#include <eda_base_frame.h>
+#include <eda_draw_frame.h>
 #include <rc_item.h>
 #include <base_units.h>
 
@@ -41,25 +41,42 @@ wxString RC_ITEM::ShowCoord( EDA_UNITS aUnits, const wxPoint& aPos )
 }
 
 
-wxString RC_ITEM::ShowReport( EDA_UNITS aUnits ) const
+wxString RC_ITEM::ShowReport( EDA_UNITS aUnits, const std::map<KIID, EDA_ITEM*>& aItemMap ) const
 {
-    if( m_hasSecondItem )
+    EDA_ITEM* mainItem = nullptr;
+    EDA_ITEM* auxItem = nullptr;
+
+    if( m_mainItemUuid != niluuid )
+        mainItem = aItemMap.at( m_mainItemUuid );
+
+    if( m_auxItemUuid != niluuid )
+        auxItem = aItemMap.at( m_auxItemUuid );
+
+    wxString msg = m_errorMessage.IsEmpty() ? GetErrorText() : m_errorMessage;
+
+    if( mainItem && auxItem )
     {
         return wxString::Format( wxT( "ErrType(%d): %s\n    %s: %s\n    %s: %s\n" ),
-                                 m_ErrorCode,
-                                 GetErrorText(),
-                                 ShowCoord( aUnits, m_MainPosition ),
-                                 m_MainText,
-                                 ShowCoord( aUnits, m_AuxPosition ),
-                                 m_AuxText );
+                                 m_errorCode,
+                                 msg,
+                                 ShowCoord( aUnits, mainItem->GetPosition() ),
+                                 mainItem->GetSelectMenuText( aUnits ),
+                                 ShowCoord( aUnits, auxItem->GetPosition() ),
+                                 auxItem->GetSelectMenuText( aUnits ) );
+    }
+    else if( mainItem )
+    {
+        return wxString::Format( wxT( "ErrType(%d): %s\n    %s: %s\n" ),
+                                 m_errorCode,
+                                 msg,
+                                 ShowCoord( aUnits, mainItem->GetPosition() ),
+                                 mainItem->GetSelectMenuText( aUnits ) );
     }
     else
     {
-        return wxString::Format( wxT( "ErrType(%d): %s\n    %s: %s\n" ),
-                                 m_ErrorCode,
-                                 GetErrorText(),
-                                 ShowCoord( aUnits, m_MainPosition ),
-                                 m_MainText );
+        return wxString::Format( wxT( "ErrType(%d): %s\n" ),
+                                 m_errorCode,
+                                 msg );
     }
 }
 
@@ -91,7 +108,7 @@ KIID RC_TREE_MODEL::ToUUID( wxDataViewItem aItem )
 }
 
 
-RC_TREE_MODEL::RC_TREE_MODEL( EDA_BASE_FRAME* aParentFrame, wxDataViewCtrl* aView ) :
+RC_TREE_MODEL::RC_TREE_MODEL( EDA_DRAW_FRAME* aParentFrame, wxDataViewCtrl* aView ) :
         m_editFrame( aParentFrame ),
         m_view( aView ),
         m_severities( 0 ),
@@ -221,8 +238,8 @@ unsigned int RC_TREE_MODEL::GetChildren( wxDataViewItem const& aItem,
  * Called by the wxDataView to fetch an item's value.
  */
 void RC_TREE_MODEL::GetValue( wxVariant&              aVariant,
-                               wxDataViewItem const&   aItem,
-                               unsigned int            aCol ) const
+                              wxDataViewItem const&   aItem,
+                              unsigned int            aCol ) const
 {
     const RC_TREE_NODE* node = ToNode( aItem );
     const RC_ITEM*      rcItem = node->m_RcItem;
@@ -242,11 +259,19 @@ void RC_TREE_MODEL::GetValue( wxVariant&              aVariant,
         break;
 
     case RC_TREE_NODE::MAIN_ITEM:
-        aVariant = rcItem->GetMainText();
+    {
+        EDA_ITEM* item = m_editFrame->GetItem( rcItem->GetMainItemID() );
+
+        aVariant = item->GetSelectMenuText( m_editFrame->GetUserUnits() );
+    }
         break;
 
     case RC_TREE_NODE::AUX_ITEM:
-        aVariant = rcItem->GetAuxText();
+    {
+        EDA_ITEM* item = m_editFrame->GetItem( rcItem->GetAuxItemID() );
+
+        aVariant = item->GetSelectMenuText( m_editFrame->GetUserUnits() );
+    }
         break;
     }
 }
diff --git a/common/rc_item.h b/common/rc_item.h
index 31f01ba247..178861a401 100644
--- a/common/rc_item.h
+++ b/common/rc_item.h
@@ -72,18 +72,13 @@ public:
 /**
  * RC_ITEM
  * is a holder for a DRC (in Pcbnew) or ERC (in Eeschema) error item.
- * There are holders for information on two EDA_ITEMs.  Some errors involve only one item
- * (item with an incorrect param) so m_hasSecondItem is set to false in this case.
+ * RC_ITEMs can have zero, one, or two related EDA_ITEMs.
  */
 class RC_ITEM
 {
 protected:
-    int           m_ErrorCode;         // the error code's numeric value
-    wxString      m_MainText;          // text for the first EDA_ITEM
-    wxString      m_AuxText;           // text for the second EDA_ITEM
-    wxPoint       m_MainPosition;      // the location of the first EDA_ITEM
-    wxPoint       m_AuxPosition;       // the location of the second EDA_ITEM
-    bool          m_hasSecondItem;     // true when 2 items create a DRC/ERC error
+    int           m_errorCode;         // the error code's numeric value
+    wxString      m_errorMessage;
     MARKER_BASE*  m_parent;            // The marker this item belongs to, if any
     KIID          m_mainItemUuid;
     KIID          m_auxItemUuid;
@@ -92,8 +87,7 @@ public:
 
     RC_ITEM()
     {
-        m_ErrorCode     = 0;
-        m_hasSecondItem = false;
+        m_errorCode     = 0;
         m_parent        = nullptr;
         m_mainItemUuid  = niluuid;
         m_auxItemUuid   = niluuid;
@@ -101,12 +95,8 @@ public:
 
     RC_ITEM( RC_ITEM* aItem )
     {
-        m_ErrorCode = aItem->m_ErrorCode;
-        m_MainText = aItem->m_MainText;
-        m_AuxText = aItem->m_AuxText;
-        m_MainPosition = aItem->m_MainPosition;
-        m_AuxPosition = aItem->m_AuxPosition;
-        m_hasSecondItem = aItem->m_hasSecondItem;
+        m_errorCode = aItem->m_errorCode;
+        m_errorMessage = aItem->m_errorMessage;
         m_parent = aItem->m_parent;
         m_mainItemUuid = aItem->m_mainItemUuid;
         m_auxItemUuid = aItem->m_auxItemUuid;
@@ -114,160 +104,39 @@ public:
 
     virtual ~RC_ITEM() { }
 
-    /**
-     * Function SetData
-     * initialize all data in item
-     * @param aErrorCode = error code
-     * @param aMainItem = the first (main) schematic or board item
-     * @param bAuxItem = the second schematic or board item
-     */
-    void SetData( EDA_UNITS aUnits, int aErrorCode,
-                  EDA_ITEM* aMainItem,
-                  EDA_ITEM* bAuxItem = nullptr )
-    {
-        m_ErrorCode       = aErrorCode;
-        m_MainText        = aMainItem->GetSelectMenuText( aUnits );
-        m_AuxText         = wxEmptyString;
-        m_hasSecondItem   = bAuxItem != nullptr;
-        m_parent          = nullptr;
-        m_mainItemUuid    = aMainItem->m_Uuid;
+    void SetErrorMessage( const wxString& aMessage ) { m_errorMessage = aMessage; }
 
-        if( m_hasSecondItem )
-        {
-            m_AuxText     = bAuxItem->GetSelectMenuText( aUnits );
-            m_auxItemUuid = bAuxItem->m_Uuid;
-        }
+    void SetItems( EDA_ITEM* aItem, EDA_ITEM* bItem = nullptr )
+    {
+        m_mainItemUuid = aItem->m_Uuid;
+
+        if( bItem )
+            m_auxItemUuid = bItem->m_Uuid;
     }
 
-    /**
-     * Function SetData
-     * initialize all data in item
-     * @param aErrorCode = error code
-     * @param aMainItem = the first (main) schematic or board item
-     * @param bAuxItem = the second schematic or board item
-     * @param aMainPos = position the first item and therefore of this issue
-     * @param bAuxPos = position the second item
-     */
-    void SetData( EDA_UNITS aUnits, int aErrorCode,
-                  EDA_ITEM* aMainItem, const wxPoint& aMainPos,
-                  EDA_ITEM* bAuxItem = nullptr, const wxPoint& bAuxPos = wxPoint() )
+    void SetItems( const KIID& aItem, const KIID& bItem = niluuid )
     {
-        m_ErrorCode       = aErrorCode;
-        m_MainText        = aMainItem->GetSelectMenuText( aUnits );
-        m_AuxText         = wxEmptyString;
-        m_MainPosition    = aMainPos;
-        m_AuxPosition     = bAuxPos;
-        m_hasSecondItem   = bAuxItem != nullptr;
-        m_parent          = nullptr;
-        m_mainItemUuid    = aMainItem->m_Uuid;
-
-        if( m_hasSecondItem )
-        {
-            m_AuxText     = bAuxItem->GetSelectMenuText( aUnits );
-            m_auxItemUuid = bAuxItem->m_Uuid;
-        }
+        m_mainItemUuid = aItem;
+        m_auxItemUuid = bItem;
     }
 
-    /**
-     * Function SetData
-     * initialize all data in item
-     * @param aErrorCode = error code
-     * @param aMainText = a description of the first (main) item
-     * @param bAuxText = a description of the second item
-     */
-    void SetData( int aErrorCode,
-                  const wxString& aMainText,
-                  const wxString& bAuxText = wxEmptyString )
-    {
-        m_ErrorCode     = aErrorCode;
-        m_MainText      = aMainText;
-        m_AuxText       = bAuxText;
-        m_hasSecondItem = !bAuxText.IsEmpty();
-        m_parent        = nullptr;
-        m_mainItemUuid  = niluuid;
-        m_auxItemUuid   = niluuid;
-    }
-
-    /**
-     * Function SetData
-     * initialize all data in item
-     * @param aErrorCode = error code
-     * @param aMainText = a description of the first (main) item
-     * @param aMainPos = position the first item and therefore of this issue
-     * @param bAuxText = a description of the second item
-     * @param bAuxPos = position the second item
-     */
-    void SetData( int aErrorCode,
-                  const wxString& aMainText, const wxPoint& aMainPos,
-                  const wxString& bAuxText = wxEmptyString, const wxPoint& bAuxPos = wxPoint() )
-    {
-        m_ErrorCode     = aErrorCode;
-        m_MainText      = aMainText;
-        m_AuxText       = bAuxText;
-        m_MainPosition  = aMainPos;
-        m_AuxPosition   = bAuxPos;
-        m_hasSecondItem = !bAuxText.IsEmpty();
-        m_parent        = nullptr;
-        m_mainItemUuid  = niluuid;
-        m_auxItemUuid   = niluuid;
-    }
-
-    /**
-     * Function SetData
-     * initialize all data in item
-     * @param aErrorCode = error code
-     * @param aMainText = a description of the first (main) item
-     * @param aMainID = UUID of the main item
-     * @param bAuxText = a description of the second item
-     * @param bAuxID = UUID of the second item
-     */
-    void SetData( int aErrorCode,
-                  const wxString& aMainText, const KIID& aMainID,
-                  const wxString& bAuxText, const KIID& bAuxID )
-    {
-        m_ErrorCode     = aErrorCode;
-        m_MainText      = aMainText;
-        m_AuxText       = bAuxText;
-        m_hasSecondItem = !bAuxText.IsEmpty() || bAuxID != niluuid;
-        m_parent        = nullptr;
-        m_mainItemUuid  = aMainID;
-        m_auxItemUuid   = bAuxID;
-    }
-
-    /**
-     * Function SetAuxiliaryData
-     * initialize data for the second (auxiliary) item
-     * @param aAuxiliaryText = the second text (main text) concerning the second schematic
-     *                         or board item
-     * @param aAuxiliaryPos = position the second item
-     */
-    void SetAuxiliaryData( const wxString& aAuxiliaryText, const wxPoint& aAuxiliaryPos )
-    {
-        m_AuxText       = aAuxiliaryText;
-        m_AuxPosition   = aAuxiliaryPos;
-        m_hasSecondItem = true;
-        m_auxItemUuid   = niluuid;
-    }
+    KIID GetMainItemID() const { return m_mainItemUuid; }
+    KIID GetAuxItemID() const { return m_auxItemUuid; }
 
     void SetParent( MARKER_BASE* aMarker ) { m_parent = aMarker; }
     MARKER_BASE* GetParent() const { return m_parent; }
 
-    bool HasSecondItem() const { return m_hasSecondItem; }
-
-    wxString GetMainText() const { return m_MainText; }
-    wxString GetAuxText() const { return m_AuxText; }
-
-    KIID GetMainItemID() const { return m_mainItemUuid; }
-    KIID GetAuxItemID() const { return m_auxItemUuid; }
 
     /**
      * Function ShowReport
      * translates this object into a text string suitable for saving to disk in a report.
      * @return wxString - the simple multi-line report text.
      */
-    virtual wxString ShowReport( EDA_UNITS aUnits ) const;
+    virtual wxString ShowReport( EDA_UNITS aUnits,
+                                 const std::map<KIID, EDA_ITEM*>& aItemMap ) const;
 
-    int GetErrorCode() const { return m_ErrorCode; }
+    int GetErrorCode() const { return m_errorCode; }
+    void SetErrorCode( int aCode ) { m_errorCode = aCode; }
 
     /**
      * Function GetErrorText
@@ -325,7 +194,7 @@ public:
 
 
 public:
-    RC_TREE_MODEL( EDA_BASE_FRAME* aParentFrame, wxDataViewCtrl* aView );
+    RC_TREE_MODEL( EDA_DRAW_FRAME* aParentFrame, wxDataViewCtrl* aView );
 
     ~RC_TREE_MODEL();
 
@@ -384,7 +253,7 @@ private:
     void onSizeView( wxSizeEvent& aEvent );
 
 private:
-    EDA_BASE_FRAME*            m_editFrame;
+    EDA_DRAW_FRAME*            m_editFrame;
     wxDataViewCtrl*            m_view;
     int                        m_severities;
     RC_ITEMS_PROVIDER*         m_rcItemsProvider;   // I own this, but not its contents
diff --git a/cvpcb/display_footprints_frame.cpp b/cvpcb/display_footprints_frame.cpp
index c7442f63eb..2e9a0cfa42 100644
--- a/cvpcb/display_footprints_frame.cpp
+++ b/cvpcb/display_footprints_frame.cpp
@@ -435,7 +435,7 @@ void DISPLAY_FOOTPRINTS_FRAME::UpdateMsgPanel()
     MSG_PANEL_ITEMS items;
 
     if( footprint )
-        footprint->GetMsgPanelInfo( m_userUnits, items );
+        footprint->GetMsgPanelInfo( this, items );
 
     SetMsgPanel( items );
 }
diff --git a/eeschema/bus-wire-junction.cpp b/eeschema/bus-wire-junction.cpp
index 50f3fab048..4f5483f862 100644
--- a/eeschema/bus-wire-junction.cpp
+++ b/eeschema/bus-wire-junction.cpp
@@ -156,13 +156,13 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen )
 
     BreakSegmentsOnJunctions( aScreen );
 
-    for( auto item : aScreen->Items().OfType( SCH_LINE_T ) )
+    for( SCH_ITEM* item : aScreen->Items().OfType( SCH_LINE_T ) )
     {
         if( item->GetLayer() == LAYER_WIRE || item->GetLayer() == LAYER_BUS )
             lines.push_back( static_cast<SCH_LINE*>( item ) );
     }
 
-    for( auto item : aScreen->Items().OfType( SCH_JUNCTION_T ) )
+    for( SCH_ITEM* item : aScreen->Items().OfType( SCH_JUNCTION_T ) )
     {
         if( !aScreen->IsJunctionNeeded( item->GetPosition() ) )
             remove_item( item );
@@ -170,7 +170,7 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen )
             junctions.push_back( static_cast<SCH_JUNCTION*>( item ) );
     }
 
-    for( auto item : aScreen->Items().OfType( SCH_NO_CONNECT_T ) )
+    for( SCH_ITEM* item : aScreen->Items().OfType( SCH_NO_CONNECT_T ) )
     {
         ncs.push_back( static_cast<SCH_NO_CONNECT*>( item ) );
     }
@@ -333,12 +333,13 @@ bool SCH_EDIT_FRAME::BreakSegmentsOnJunctions( SCH_SCREEN* aScreen )
     bool brokenSegments = false;
 
     std::set<wxPoint> point_set;
-    for( auto item : aScreen->Items().OfType( SCH_JUNCTION_T ) )
+
+    for( SCH_ITEM* item : aScreen->Items().OfType( SCH_JUNCTION_T ) )
         point_set.insert( item->GetPosition() );
 
-    for( auto item : aScreen->Items().OfType( SCH_BUS_WIRE_ENTRY_T ) )
+    for( SCH_ITEM* item : aScreen->Items().OfType( SCH_BUS_WIRE_ENTRY_T ) )
     {
-        auto entry = static_cast<SCH_BUS_WIRE_ENTRY*>( item );
+        SCH_BUS_WIRE_ENTRY* entry = static_cast<SCH_BUS_WIRE_ENTRY*>( item );
         point_set.insert( entry->GetPosition() );
         point_set.insert( entry->m_End() );
     }
@@ -371,9 +372,9 @@ void SCH_EDIT_FRAME::DeleteJunction( SCH_ITEM* aJunction, bool aAppend )
     /// loop below.  This will invalidate iterators in a std::vector or std::deque
     std::list<SCH_LINE*> lines;
 
-    for( auto item : screen->Items().Overlapping( SCH_LINE_T, aJunction->GetPosition() ) )
+    for( SCH_ITEM* item : screen->Items().Overlapping( SCH_LINE_T, aJunction->GetPosition() ) )
     {
-        auto line = static_cast<SCH_LINE*>( item );
+        SCH_LINE* line = static_cast<SCH_LINE*>( item );
 
         if( line->IsType( wiresAndBuses ) && line->IsEndPoint( aJunction->GetPosition() )
                 && !( line->GetEditFlags() & STRUCT_DELETED ) )
diff --git a/eeschema/connection_graph.cpp b/eeschema/connection_graph.cpp
index b0464fc135..66dac4801d 100644
--- a/eeschema/connection_graph.cpp
+++ b/eeschema/connection_graph.cpp
@@ -153,13 +153,14 @@ bool CONNECTION_SUBGRAPH::ResolveDrivers( bool aCreateMarkers )
 
         if( !same )
         {
-            wxPoint pos = ( candidates[0]->Type() == SCH_PIN_T ) ?
-                          static_cast<SCH_PIN*>( candidates[0] )->GetTransformedPosition() :
-                          candidates[0]->GetPosition();
+            wxPoint pos = candidates[0]->Type() == SCH_PIN_T ?
+                              static_cast<SCH_PIN*>( candidates[0] )->GetTransformedPosition() :
+                              candidates[0]->GetPosition();
 
-            auto marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-            marker->SetData( m_frame->GetUserUnits(), ERCE_DRIVER_CONFLICT, pos,
-                             candidates[0], second_item );
+            ERC_ITEM* ercItem = new ERC_ITEM( ERCE_DRIVER_CONFLICT );
+            ercItem->SetItems( candidates[0], second_item );
+
+            SCH_MARKER* marker = new SCH_MARKER( ercItem, pos );
             m_sheet.LastScreen()->Append( marker );
 
             // If aCreateMarkers is true, then this is part of ERC check, so we
@@ -439,7 +440,6 @@ void CONNECTION_GRAPH::updateItemConnectivity( SCH_SHEET_PATH aSheet,
         else if( item->Type() == SCH_COMPONENT_T )
         {
             SCH_COMPONENT* component = static_cast<SCH_COMPONENT*>( item );
-            TRANSFORM t = component->GetTransform();
 
             // TODO(JE) right now this relies on GetSchPins() returning good SCH_PIN pointers
             // that contain good LIB_PIN pointers.  Since these get invalidated whenever the
@@ -452,8 +452,7 @@ void CONNECTION_GRAPH::updateItemConnectivity( SCH_SHEET_PATH aSheet,
             {
                 pin->InitializeConnection( aSheet );
 
-                wxPoint pos = t.TransformCoordinate( pin->GetPosition() ) +
-                              component->GetPosition();
+                wxPoint pos = pin->GetPosition();
 
                 // because calling the first time is not thread-safe
                 pin->GetDefaultNetName( aSheet );
@@ -2006,9 +2005,10 @@ bool CONNECTION_GRAPH::ercCheckBusToNetConflicts( const CONNECTION_SUBGRAPH* aSu
 
     if( net_item && bus_item )
     {
-        auto marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-        marker->SetData( m_frame->GetUserUnits(), ERCE_BUS_TO_NET_CONFLICT,
-                         net_item->GetPosition(), net_item, bus_item );
+        ERC_ITEM* ercItem = new ERC_ITEM( ERCE_BUS_TO_NET_CONFLICT );
+        ercItem->SetItems( net_item, bus_item );
+
+        SCH_MARKER* marker = new SCH_MARKER( ercItem, net_item->GetPosition() );
         screen->Append( marker );
 
         return false;
@@ -2073,9 +2073,10 @@ bool CONNECTION_GRAPH::ercCheckBusToBusConflicts( const CONNECTION_SUBGRAPH* aSu
 
         if( !match )
         {
-            auto marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-            marker->SetData( m_frame->GetUserUnits(), ERCE_BUS_TO_BUS_CONFLICT,
-                             label->GetPosition(), label, port );
+            ERC_ITEM* ercItem = new ERC_ITEM( ERCE_BUS_TO_BUS_CONFLICT );
+            ercItem->SetItems( label, port );
+
+            SCH_MARKER* marker = new SCH_MARKER( ercItem, label->GetPosition() );
             screen->Append( marker );
 
             return false;
@@ -2152,9 +2153,10 @@ bool CONNECTION_GRAPH::ercCheckBusToBusEntryConflicts( const CONNECTION_SUBGRAPH
 
     if( conflict )
     {
-        auto marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-        marker->SetData( m_frame->GetUserUnits(), ERCE_BUS_ENTRY_CONFLICT,
-                         bus_entry->GetPosition(), bus_entry, bus_wire );
+        ERC_ITEM* ercItem = new ERC_ITEM( ERCE_BUS_ENTRY_CONFLICT );
+        ercItem->SetItems( bus_entry, bus_wire );
+
+        SCH_MARKER* marker = new SCH_MARKER( ercItem, bus_entry->GetPosition() );
         screen->Append( marker );
 
         return false;
@@ -2204,9 +2206,10 @@ bool CONNECTION_GRAPH::ercCheckNoConnects( const CONNECTION_SUBGRAPH* aSubgraph
 
         if( pin && has_invalid_items )
         {
-            auto marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-            marker->SetData( ERCE_NOCONNECT_CONNECTED, pin->GetTransformedPosition(),
-                             pin->GetDescription( &aSubgraph->m_sheet ), pin->m_Uuid );
+            ERC_ITEM* ercItem = new ERC_ITEM( ERCE_NOCONNECT_CONNECTED );
+            ercItem->SetItems( pin );
+
+            SCH_MARKER* marker = new SCH_MARKER( ercItem, pin->GetTransformedPosition() );
             screen->Append( marker );
 
             return false;
@@ -2214,9 +2217,10 @@ bool CONNECTION_GRAPH::ercCheckNoConnects( const CONNECTION_SUBGRAPH* aSubgraph
 
         if( !has_other_items )
         {
-            SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-            marker->SetData( m_frame->GetUserUnits(), ERCE_NOCONNECT_NOT_CONNECTED,
-                             aSubgraph->m_no_connect->GetPosition(), aSubgraph->m_no_connect );
+            ERC_ITEM* ercItem = new ERC_ITEM( ERCE_NOCONNECT_NOT_CONNECTED );
+            ercItem->SetItems( aSubgraph->m_no_connect );
+
+            SCH_MARKER* marker = new SCH_MARKER( ercItem, aSubgraph->m_no_connect->GetPosition() );
             screen->Append( marker );
 
             return false;
@@ -2268,9 +2272,10 @@ bool CONNECTION_GRAPH::ercCheckNoConnects( const CONNECTION_SUBGRAPH* aSubgraph
 
         if( pin && !has_other_connections && pin->GetType() != ELECTRICAL_PINTYPE::PT_NC )
         {
-            SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-            marker->SetData( ERCE_PIN_NOT_CONNECTED, pin->GetTransformedPosition(),
-                             pin->GetDescription( &aSubgraph->m_sheet ), pin->m_Uuid );
+            ERC_ITEM* ercItem = new ERC_ITEM( ERCE_PIN_NOT_CONNECTED );
+            ercItem->SetItems( pin );
+
+            SCH_MARKER* marker = new SCH_MARKER( ercItem, pin->GetTransformedPosition() );
             screen->Append( marker );
 
             return false;
@@ -2359,10 +2364,10 @@ bool CONNECTION_GRAPH::ercCheckLabels( const CONNECTION_SUBGRAPH* aSubgraph )
 
     if( !has_other_connections )
     {
-        SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-        marker->SetData( m_frame->GetUserUnits(),
-                         is_global ? ERCE_GLOBLABEL : ERCE_LABEL_NOT_CONNECTED,
-                         text->GetPosition(), text );
+        ERC_ITEM* ercItem = new ERC_ITEM( is_global ? ERCE_GLOBLABEL : ERCE_LABEL_NOT_CONNECTED );
+        ercItem->SetItems( text );
+
+        SCH_MARKER* marker = new SCH_MARKER( ercItem, text->GetPosition() );
         aSubgraph->m_sheet.LastScreen()->Append( marker );
 
         return false;
diff --git a/eeschema/dialogs/dialog_erc.cpp b/eeschema/dialogs/dialog_erc.cpp
index 0d17d4ef14..062b5bc58d 100644
--- a/eeschema/dialogs/dialog_erc.cpp
+++ b/eeschema/dialogs/dialog_erc.cpp
@@ -285,14 +285,16 @@ void DIALOG_ERC::TestErc( REPORTER& aReporter )
                 }
                 else if( pin_to_net_map[pin_name] != item->GetNetName() )
                 {
-                    msg.Printf( _( "Pin %s on %s is connected to both %s and %s" ),
+                    msg.Printf( _( "Pin %s is connected to both %s and %s" ),
                                 item->m_PinNum,
-                                ref,
                                 pin_to_net_map[pin_name],
                                 item->GetNetName() );
 
-                    SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-                    marker->SetData( ERCE_DIFFERENT_UNIT_NET, item->m_Start, msg, item->m_Start );
+                    ERC_ITEM* ercItem = new ERC_ITEM( ERCE_DIFFERENT_UNIT_NET );
+                    ercItem->SetErrorMessage( msg );
+                    ercItem->SetItems( item->m_Comp );
+
+                    SCH_MARKER* marker = new SCH_MARKER( ercItem, item->m_Start );
                     item->m_SheetPath.LastScreen()->Append( marker );
                 }
             }
@@ -578,18 +580,22 @@ bool DIALOG_ERC::writeReport( const wxString& aFullFileName )
 
     wxString msg = wxString::Format( _( "ERC report (%s, Encoding UTF8)\n" ), DateAndTime() );
 
+    std::map<KIID, EDA_ITEM*> itemMap;
+
     int            err_count = 0;
     int            warn_count = 0;
     int            total_count = 0;
     SCH_SHEET_LIST sheetList( g_RootSheet );
 
+    sheetList.FillItemMap( itemMap );
+
     for( unsigned i = 0;  i < sheetList.size(); i++ )
     {
         msg << wxString::Format( _( "\n***** Sheet %s\n" ), sheetList[i].PathHumanReadable() );
 
-        for( auto aItem : sheetList[i].LastScreen()->Items().OfType( SCH_MARKER_T ) )
+        for( SCH_ITEM* aItem : sheetList[i].LastScreen()->Items().OfType( SCH_MARKER_T ) )
         {
-            auto marker = static_cast<const SCH_MARKER*>( aItem );
+            const SCH_MARKER* marker = static_cast<const SCH_MARKER*>( aItem );
 
             if( marker->GetMarkerType() != MARKER_BASE::MARKER_ERC )
                 continue;
@@ -603,7 +609,7 @@ bool DIALOG_ERC::writeReport( const wxString& aFullFileName )
             default:                                 break;
             }
 
-            msg << marker->GetRCItem()->ShowReport( GetUserUnits() );
+            msg << marker->GetRCItem()->ShowReport( GetUserUnits(), itemMap );
         }
     }
 
diff --git a/eeschema/dialogs/dialog_schematic_setup.cpp b/eeschema/dialogs/dialog_schematic_setup.cpp
index e5a4bb1043..b61fa0a90a 100644
--- a/eeschema/dialogs/dialog_schematic_setup.cpp
+++ b/eeschema/dialogs/dialog_schematic_setup.cpp
@@ -40,7 +40,7 @@ DIALOG_SCHEMATIC_SETUP::DIALOG_SCHEMATIC_SETUP( SCH_EDIT_FRAME* aFrame ) :
     m_fieldNameTemplates = new PANEL_EESCHEMA_TEMPLATE_FIELDNAMES( aFrame, m_treebook, false );
     m_pinMap = new PANEL_SETUP_PINMAP( m_treebook, aFrame );
 
-    ERC_ITEM dummyItem;
+    ERC_ITEM dummyItem( 0 );
     m_severities = new PANEL_SETUP_SEVERITIES( this, dummyItem, g_ErcSettings->m_Severities,
                                                ERCE_FIRST, ERCE_LAST );
 
diff --git a/eeschema/erc.cpp b/eeschema/erc.cpp
index c3b8581e2e..d80cc97192 100644
--- a/eeschema/erc.cpp
+++ b/eeschema/erc.cpp
@@ -182,9 +182,10 @@ int TestDuplicateSheetNames( bool aCreateMarker )
                 {
                     if( aCreateMarker )
                     {
-                        SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-                        marker->SetData( EDA_UNITS::UNSCALED, ERCE_DUPLICATE_SHEET_NAME,
-                                         item->GetPosition(), item, test_item );
+                        ERC_ITEM* ercItem = new ERC_ITEM( ERCE_DUPLICATE_SHEET_NAME );
+                        ercItem->SetItems( item, test_item );
+
+                        SCH_MARKER* marker = new SCH_MARKER( ercItem, item->GetPosition() );
                         screen->Append( marker );
                     }
 
@@ -214,12 +215,14 @@ void TestTextVars()
                 {
                     if( field.GetShownText().Matches( wxT( "*${*}*" ) ) )
                     {
-                        wxPoint delta = field.GetPosition() - component->GetPosition();
-                        delta = component->GetTransform().TransformCoordinate( delta );
+                        wxPoint pos = field.GetPosition() - component->GetPosition();
+                        pos = component->GetTransform().TransformCoordinate( pos );
+                        pos += component->GetPosition();
 
-                        SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-                        marker->SetData( EDA_UNITS::UNSCALED, ERCE_UNRESOLVED_VARIABLE,
-                                         component->GetPosition() + delta, &field );
+                        ERC_ITEM* ercItem = new ERC_ITEM( ERCE_UNRESOLVED_VARIABLE );
+                        ercItem->SetItems( &field );
+
+                        SCH_MARKER* marker = new SCH_MARKER( ercItem, pos );
                         screen->Append( marker );
                     }
                 }
@@ -232,9 +235,10 @@ void TestTextVars()
                 {
                     if( field.GetShownText().Matches( wxT( "*${*}*" ) ) )
                     {
-                        SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-                        marker->SetData( EDA_UNITS::UNSCALED, ERCE_UNRESOLVED_VARIABLE,
-                                         field.GetPosition(), &field );
+                        ERC_ITEM* ercItem = new ERC_ITEM( ERCE_UNRESOLVED_VARIABLE );
+                        ercItem->SetItems( &field );
+
+                        SCH_MARKER* marker = new SCH_MARKER( ercItem, field.GetPosition() );
                         screen->Append( marker );
                     }
                 }
@@ -243,9 +247,10 @@ void TestTextVars()
                 {
                     if( pin->GetShownText().Matches( wxT( "*${*}*" ) ) )
                     {
-                        SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-                        marker->SetData( EDA_UNITS::UNSCALED, ERCE_UNRESOLVED_VARIABLE,
-                                         pin->GetPosition(), pin );
+                        ERC_ITEM* ercItem = new ERC_ITEM( ERCE_UNRESOLVED_VARIABLE );
+                        ercItem->SetItems( pin );
+
+                        SCH_MARKER* marker = new SCH_MARKER( ercItem, pin->GetPosition() );
                         screen->Append( marker );
                     }
                 }
@@ -254,9 +259,10 @@ void TestTextVars()
             {
                 if( text->GetShownText().Matches( wxT( "*${*}*" ) ) )
                 {
-                    SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-                    marker->SetData( EDA_UNITS::UNSCALED, ERCE_UNRESOLVED_VARIABLE,
-                                     text->GetPosition(), text );
+                    ERC_ITEM* ercItem = new ERC_ITEM( ERCE_UNRESOLVED_VARIABLE );
+                    ercItem->SetItems( text );
+
+                    SCH_MARKER* marker = new SCH_MARKER( ercItem, text->GetPosition() );
                     screen->Append( marker );
                 }
             }
@@ -287,8 +293,10 @@ int TestConflictingBusAliases()
                                 alias->GetParent()->GetFileName(),
                                 test->GetParent()->GetFileName() );
 
-                    SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-                    marker->SetData( ERCE_BUS_ALIAS_CONFLICT, wxPoint(), msg );
+                    ERC_ITEM* ercItem = new ERC_ITEM( ERCE_BUS_ALIAS_CONFLICT );
+                    ercItem->SetErrorMessage( msg );
+
+                    SCH_MARKER* marker = new SCH_MARKER( ercItem, wxPoint() );
                     test->GetParent()->Append( marker );
 
                     ++err_count;
@@ -321,20 +329,19 @@ int TestMultiunitFootprints( SCH_SHEET_LIST& aSheetList )
         }
 
         // Reference footprint
-        wxString fp;
-        wxString unitName;
-        KIID     unitID;
+        SCH_COMPONENT* unit = nullptr;
+        wxString       unitName;
+        wxString       unitFP;
 
         for( unsigned i = 0; i < component.second.GetCount(); ++i )
         {
-            SCH_COMPONENT* unit = refList.GetItem( i ).GetComp();
             SCH_SHEET_PATH sheetPath = refList.GetItem( i ).GetSheetPath();
-            fp = unit->GetField( FOOTPRINT )->GetText();
+            unitFP = refList.GetItem( i ).GetComp()->GetField( FOOTPRINT )->GetText();
 
-            if( !fp.IsEmpty() )
+            if( !unitFP.IsEmpty() )
             {
+                unit = refList.GetItem( i ).GetComp();
                 unitName = unit->GetRef( &sheetPath, true );
-                unitID = unit->m_Uuid;
                 break;
             }
         }
@@ -343,20 +350,20 @@ int TestMultiunitFootprints( SCH_SHEET_LIST& aSheetList )
         {
             SCH_REFERENCE& secondRef = refList.GetItem( i );
             SCH_COMPONENT* secondUnit = secondRef.GetComp();
-            SCH_SHEET_PATH sheetPath = secondRef.GetSheetPath();
-
+            wxString       secondName = secondUnit->GetRef( &secondRef.GetSheetPath(), true );
             const wxString secondFp = secondUnit->GetField( FOOTPRINT )->GetText();
-            wxString       secondName = secondUnit->GetRef( &sheetPath, true );
-            KIID           secondID = secondUnit->m_Uuid;
+            wxString       msg;
 
-            if( !secondFp.IsEmpty() && fp != secondFp )
+            if( !secondFp.IsEmpty() && unitFP != secondFp )
             {
-                wxString description = _( "%s has '%s' assigned" );
+                msg.Printf( _( "Different footprints assigned to %s and %s" ),
+                            unitName, secondName );
 
-                SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-                marker->SetData( ERCE_DIFFERENT_UNIT_FP, secondUnit->GetPosition(),
-                                 wxString::Format( description, unitName, fp ), unitID,
-                                 wxString::Format( description, secondName, secondFp ), secondID );
+                ERC_ITEM* ercItem = new ERC_ITEM( ERCE_DIFFERENT_UNIT_FP );
+                ercItem->SetErrorMessage( msg );
+                ercItem->SetItems( unit, secondUnit );
+
+                SCH_MARKER* marker = new SCH_MARKER( ercItem, secondUnit->GetPosition() );
                 secondRef.GetSheetPath().LastScreen()->Append( marker );
 
                 ++errors;
@@ -375,28 +382,27 @@ void Diagnose( NETLIST_OBJECT* aNetItemRef, NETLIST_OBJECT* aNetItemTst, int aMi
 
     SCH_PIN* pin = static_cast<SCH_PIN*>( aNetItemRef->m_Comp );
 
-    /* Create new marker for ERC error. */
-    SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-    aNetItemRef->m_SheetPath.LastScreen()->Append( marker );
-
     if( aNetItemTst == NULL)
     {
         if( aMinConn == NOD )    /* Nothing driving the net. */
         {
-            marker->SetData( ERCE_PIN_NOT_DRIVEN, aNetItemRef->m_Start,
-                             pin->GetDescription( &aNetItemRef->m_SheetPath ), pin->m_Uuid );
+            ERC_ITEM* ercItem = new ERC_ITEM( ERCE_PIN_NOT_DRIVEN );
+            ercItem->SetItems( pin );
+
+            SCH_MARKER* marker = new SCH_MARKER( ercItem, aNetItemRef->m_Start );
+            aNetItemRef->m_SheetPath.LastScreen()->Append( marker );
             return;
         }
     }
 
     if( aNetItemTst && aNetItemTst->m_Type == NETLIST_ITEM::PIN )  /* Error between 2 pins */
     {
-        SCH_PIN* pinB = static_cast<SCH_PIN*>( aNetItemTst->m_Comp );
+        ERC_ITEM* ercItem = new ERC_ITEM( aDiag == ERR ? ERCE_PIN_TO_PIN_ERROR
+                                                       : ERCE_PIN_TO_PIN_WARNING );
+        ercItem->SetItems( pin, static_cast<SCH_PIN*>( aNetItemTst->m_Comp ) );
 
-        marker->SetData( aDiag == ERR ? ERCE_PIN_TO_PIN_ERROR : ERCE_PIN_TO_PIN_WARNING,
-                         aNetItemRef->m_Start,
-                         pin->GetDescription( &aNetItemRef->m_SheetPath ), pin->m_Uuid,
-                         pinB->GetDescription( &aNetItemTst->m_SheetPath ), pinB->m_Uuid );
+        SCH_MARKER* marker = new SCH_MARKER( ercItem, aNetItemRef->m_Start );
+        aNetItemRef->m_SheetPath.LastScreen()->Append( marker );
     }
 }
 
@@ -724,9 +730,9 @@ static int countIndenticalLabels( std::vector<NETLIST_OBJECT*>& aList, NETLIST_O
 // Helper function: creates a marker for similar labels ERC warning
 static void SimilarLabelsDiagnose( NETLIST_OBJECT* aItemA, NETLIST_OBJECT* aItemB )
 {
-    // Create new marker for ERC.
-    SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-    marker->SetData( EDA_UNITS::UNSCALED, ERCE_SIMILAR_LABELS, aItemA->m_Start,
-                     aItemA->m_Comp, aItemB->m_Comp );
+    ERC_ITEM* ercItem = new ERC_ITEM( ERCE_SIMILAR_LABELS );
+    ercItem->SetItems( aItemA->m_Comp, aItemB->m_Comp );
+
+    SCH_MARKER* marker = new SCH_MARKER( ercItem, aItemA->m_Start );
     aItemA->m_SheetPath.LastScreen()->Append( marker );
 }
diff --git a/eeschema/erc_item.cpp b/eeschema/erc_item.cpp
index 8e79f42bfc..bb2ecb53e1 100644
--- a/eeschema/erc_item.cpp
+++ b/eeschema/erc_item.cpp
@@ -32,7 +32,7 @@
 
 wxString ERC_ITEM::GetErrorText() const
 {
-    switch( m_ErrorCode )
+    switch( m_errorCode )
     {
     case ERCE_UNSPECIFIED:
         return wxString( _("ERC err unspecified") );
diff --git a/eeschema/erc_item.h b/eeschema/erc_item.h
index 236db71cd5..fd6e26c4ca 100644
--- a/eeschema/erc_item.h
+++ b/eeschema/erc_item.h
@@ -24,19 +24,17 @@
 #ifndef ERC_ITEM_H
 #define ERC_ITEM_H
 
-#include <macros.h>
-#include <base_struct.h>
 #include <rc_item.h>
-#include <marker_base.h>
-#include <sch_marker.h>
-#include <sch_screen.h>
-#include <sch_sheet_path.h>
-#include "erc_settings.h"
 
 
 class ERC_ITEM : public RC_ITEM
 {
 public:
+    ERC_ITEM( int aErrorCode )
+    {
+        m_errorCode = aErrorCode;
+    }
+
     /**
      * Function GetErrorText
      * returns the string form of a drc error code.
@@ -45,110 +43,4 @@ public:
 };
 
 
-
-/**
- * SHEETLIST_ERC_ITEMS_PROVIDER
- * is an implementation of the RC_ITEM_LISTinterface which uses the global SHEETLIST
- * to fulfill the contract.
- */
-class SHEETLIST_ERC_ITEMS_PROVIDER : public RC_ITEMS_PROVIDER
-{
-private:
-    int                      m_severities;
-    std::vector<SCH_MARKER*> m_filteredMarkers;
-
-public:
-    SHEETLIST_ERC_ITEMS_PROVIDER() :
-            m_severities( 0 )
-    { }
-
-    void SetSeverities( int aSeverities ) override
-    {
-        m_severities = aSeverities;
-
-        m_filteredMarkers.clear();
-
-        SCH_SHEET_LIST sheetList( g_RootSheet);
-
-        for( unsigned i = 0; i < sheetList.size(); i++ )
-        {
-            for( SCH_ITEM* aItem : sheetList[i].LastScreen()->Items().OfType( SCH_MARKER_T ) )
-            {
-                SCH_MARKER* marker = static_cast<SCH_MARKER*>( aItem );
-                int markerSeverity;
-
-                if( marker->GetMarkerType() != MARKER_BASE::MARKER_ERC )
-                    continue;
-
-                if( marker->IsExcluded() )
-                    markerSeverity = RPT_SEVERITY_EXCLUSION;
-                else
-                    markerSeverity = GetSeverity( marker->GetRCItem()->GetErrorCode() );
-
-                if( markerSeverity & m_severities )
-                    m_filteredMarkers.push_back( marker );
-            }
-        }
-    }
-
-    int GetCount( int aSeverity = -1 ) override
-    {
-        if( aSeverity < 0 )
-            return m_filteredMarkers.size();
-
-        int count = 0;
-
-        SCH_SHEET_LIST sheetList( g_RootSheet);
-
-        for( unsigned i = 0; i < sheetList.size(); i++ )
-        {
-            for( SCH_ITEM* aItem : sheetList[i].LastScreen()->Items().OfType( SCH_MARKER_T ) )
-            {
-                SCH_MARKER* marker = static_cast<SCH_MARKER*>( aItem );
-                int markerSeverity;
-
-                if( marker->GetMarkerType() != MARKER_BASE::MARKER_ERC )
-                    continue;
-
-                if( marker->IsExcluded() )
-                    markerSeverity = RPT_SEVERITY_EXCLUSION;
-                else
-                    markerSeverity = GetSeverity( marker->GetRCItem()->GetErrorCode() );
-
-                if( markerSeverity == aSeverity )
-                    count++;
-            }
-        }
-
-        return count;
-    }
-
-    ERC_ITEM* GetItem( int aIndex ) override
-    {
-        SCH_MARKER* marker = m_filteredMarkers[ aIndex ];
-
-        return marker ? static_cast<ERC_ITEM*>( marker->GetRCItem() ) : nullptr;
-    }
-
-    void DeleteItem( int aIndex, bool aDeep ) override
-    {
-        SCH_MARKER* marker = m_filteredMarkers[ aIndex ];
-        m_filteredMarkers.erase( m_filteredMarkers.begin() + aIndex );
-
-        if( aDeep )
-        {
-            SCH_SCREENS ScreenList;
-            ScreenList.DeleteMarker( marker );
-        }
-    }
-
-    void DeleteAllItems() override
-    {
-        SCH_SCREENS ScreenList;
-        ScreenList.DeleteAllMarkers( MARKER_BASE::MARKER_ERC );
-        m_filteredMarkers.clear();
-    }
-};
-
-
 #endif      // ERC_ITEM_H
diff --git a/eeschema/lib_arc.cpp b/eeschema/lib_arc.cpp
index 433d855b04..29d7259d15 100644
--- a/eeschema/lib_arc.cpp
+++ b/eeschema/lib_arc.cpp
@@ -33,7 +33,7 @@
 #include <msgpanel.h>
 #include <bitmaps.h>
 #include <math/util.h>      // for KiROUND
-
+#include <eda_draw_frame.h>
 #include <general.h>
 #include <lib_arc.h>
 #include <transform.h>
@@ -398,14 +398,14 @@ const EDA_RECT LIB_ARC::GetBoundingBox() const
 }
 
 
-void LIB_ARC::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void LIB_ARC::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
     wxString msg;
     EDA_RECT bBox = GetBoundingBox();
 
-    LIB_ITEM::GetMsgPanelInfo( aUnits, aList );
+    LIB_ITEM::GetMsgPanelInfo( aFrame, aList );
 
-    msg = MessageTextFromValue( aUnits, m_Width, true );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), m_Width, true );
 
     aList.emplace_back( _( "Line Width" ), msg, BLUE );
 
diff --git a/eeschema/lib_arc.h b/eeschema/lib_arc.h
index 7530a52f2c..ef1d6de2ab 100644
--- a/eeschema/lib_arc.h
+++ b/eeschema/lib_arc.h
@@ -75,7 +75,7 @@ public:
 
     const EDA_RECT GetBoundingBox() const override;
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     int GetPenWidth() const override;
 
@@ -87,7 +87,7 @@ public:
 
     void MoveTo( const wxPoint& aPosition ) override;
 
-    wxPoint GetPosition() const override { return m_Pos; }
+    const wxPoint GetPosition() const override { return m_Pos; }
 
     void MirrorHorizontal( const wxPoint& aCenter ) override;
     void MirrorVertical( const wxPoint& aCenter ) override;
diff --git a/eeschema/lib_bezier.cpp b/eeschema/lib_bezier.cpp
index 7fd80fe651..526f9c121c 100644
--- a/eeschema/lib_bezier.cpp
+++ b/eeschema/lib_bezier.cpp
@@ -29,8 +29,9 @@
 #include <trigo.h>
 #include <bezier_curves.h>
 #include <base_units.h>
+#include <eda_draw_frame.h>
 #include <msgpanel.h>
-
+#include <eda_draw_frame.h>
 #include <general.h>
 #include <lib_bezier.h>
 #include <transform.h>
@@ -330,14 +331,14 @@ const EDA_RECT LIB_BEZIER::GetBoundingBox() const
 }
 
 
-void LIB_BEZIER::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void LIB_BEZIER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
     wxString msg;
     EDA_RECT bBox = GetBoundingBox();
 
-    LIB_ITEM::GetMsgPanelInfo( aUnits, aList );
+    LIB_ITEM::GetMsgPanelInfo( aFrame, aList );
 
-    msg = MessageTextFromValue( aUnits, m_Width, true );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), m_Width, true );
 
     aList.emplace_back( _( "Line Width" ), msg, BLUE );
 
@@ -350,7 +351,7 @@ void LIB_BEZIER::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>&
     aList.emplace_back( _( "Bounding Box" ), msg, BROWN );
 }
 
-wxPoint LIB_BEZIER::GetPosition() const
+const wxPoint LIB_BEZIER::GetPosition() const
 {
     if( !m_PolyPoints.size() )
         return wxPoint(0, 0);
diff --git a/eeschema/lib_bezier.h b/eeschema/lib_bezier.h
index 0094ad10bf..999bb8fd8f 100644
--- a/eeschema/lib_bezier.h
+++ b/eeschema/lib_bezier.h
@@ -74,7 +74,7 @@ public:
 
     void MoveTo( const wxPoint& aPosition ) override;
 
-    wxPoint GetPosition() const override;
+    const wxPoint GetPosition() const override;
 
     void MirrorHorizontal( const wxPoint& aCenter ) override;
     void MirrorVertical( const wxPoint& aCenter ) override;
@@ -88,7 +88,7 @@ public:
 
     int GetPenWidth() const override;
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     EDA_ITEM* Clone() const override;
 
diff --git a/eeschema/lib_circle.cpp b/eeschema/lib_circle.cpp
index b88df02bc4..3b780b826d 100644
--- a/eeschema/lib_circle.cpp
+++ b/eeschema/lib_circle.cpp
@@ -32,7 +32,7 @@
 #include <msgpanel.h>
 #include <bitmaps.h>
 #include <math/util.h>      // for KiROUND
-
+#include <eda_draw_frame.h>
 #include <general.h>
 #include <lib_circle.h>
 #include <settings/color_settings.h>
@@ -240,18 +240,18 @@ const EDA_RECT LIB_CIRCLE::GetBoundingBox() const
 }
 
 
-void LIB_CIRCLE::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
+void LIB_CIRCLE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
 {
     wxString msg;
     EDA_RECT bBox = GetBoundingBox();
 
-    LIB_ITEM::GetMsgPanelInfo( aUnits, aList );
+    LIB_ITEM::GetMsgPanelInfo( aFrame, aList );
 
-    msg = MessageTextFromValue( aUnits, m_Width, true );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), m_Width, true );
 
     aList.push_back( MSG_PANEL_ITEM(  _( "Line Width" ), msg, BLUE ) );
 
-    msg = MessageTextFromValue( aUnits, GetRadius(), true );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), GetRadius(), true );
     aList.push_back( MSG_PANEL_ITEM( _( "Radius" ), msg, RED ) );
 
     msg.Printf( wxT( "(%d, %d, %d, %d)" ),
diff --git a/eeschema/lib_circle.h b/eeschema/lib_circle.h
index 417cb30843..272b8f41c0 100644
--- a/eeschema/lib_circle.h
+++ b/eeschema/lib_circle.h
@@ -59,7 +59,7 @@ public:
 
     const EDA_RECT GetBoundingBox() const override;
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     void BeginEdit( const wxPoint aStartPoint ) override;
     void CalcEdit( const wxPoint& aPosition ) override;
@@ -68,7 +68,7 @@ public:
 
     void MoveTo( const wxPoint& aPosition ) override;
 
-    wxPoint GetPosition() const override { return m_Pos; }
+    const wxPoint GetPosition() const override { return m_Pos; }
 
     void SetEnd( const wxPoint& aPosition ) { m_EndPos = aPosition; }
     wxPoint GetEnd() const { return m_EndPos; }
diff --git a/eeschema/lib_field.cpp b/eeschema/lib_field.cpp
index c3ddce163e..63d2bcc666 100644
--- a/eeschema/lib_field.cpp
+++ b/eeschema/lib_field.cpp
@@ -29,6 +29,7 @@
 #include <gr_text.h>
 #include <kicad_string.h>
 #include <sch_draw_panel.h>
+#include <eda_draw_frame.h>
 #include <plotter.h>
 #include <trigo.h>
 #include <base_units.h>
@@ -420,20 +421,20 @@ void LIB_FIELD::CalcEdit( const wxPoint& aPosition )
 }
 
 
-void LIB_FIELD::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
+void LIB_FIELD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
 {
     wxString msg;
 
-    LIB_ITEM::GetMsgPanelInfo( aUnits, aList );
+    LIB_ITEM::GetMsgPanelInfo( aFrame, aList );
 
     // Display style:
     msg = GetTextStyleName();
     aList.push_back( MSG_PANEL_ITEM( _( "Style" ), msg, MAGENTA ) );
 
-    msg = MessageTextFromValue( aUnits, GetTextWidth(), true );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), GetTextWidth(), true );
     aList.push_back( MSG_PANEL_ITEM( _( "Width" ), msg, BLUE ) );
 
-    msg = MessageTextFromValue( aUnits, GetTextHeight(), true );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), GetTextHeight(), true );
     aList.push_back( MSG_PANEL_ITEM( _( "Height" ), msg, BLUE ) );
 
     // Display field name (ref, value ...)
diff --git a/eeschema/lib_field.h b/eeschema/lib_field.h
index 3f2703ff5d..09d8269fbd 100644
--- a/eeschema/lib_field.h
+++ b/eeschema/lib_field.h
@@ -151,7 +151,7 @@ public:
 
     const EDA_RECT GetBoundingBox() const override;
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
 
@@ -177,7 +177,7 @@ public:
 
     void MoveTo( const wxPoint& aPosition ) override;
 
-    wxPoint GetPosition() const override { return EDA_TEXT::GetTextPos(); }
+    const wxPoint GetPosition() const override { return EDA_TEXT::GetTextPos(); }
 
     void MirrorHorizontal( const wxPoint& aCenter ) override;
     void MirrorVertical( const wxPoint& aCenter ) override;
diff --git a/eeschema/lib_item.cpp b/eeschema/lib_item.cpp
index 88fe1077bb..764cdd45fa 100644
--- a/eeschema/lib_item.cpp
+++ b/eeschema/lib_item.cpp
@@ -49,7 +49,7 @@ LIB_ITEM::LIB_ITEM( KICAD_T        aType,
 }
 
 
-void LIB_ITEM::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
+void LIB_ITEM::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
 {
     wxString msg;
 
diff --git a/eeschema/lib_item.h b/eeschema/lib_item.h
index dbdd7e002e..909271383d 100644
--- a/eeschema/lib_item.h
+++ b/eeschema/lib_item.h
@@ -209,7 +209,7 @@ public:
      * </p>
      * @param aList is the list to populate.
      */
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     /**
      * Test LIB_ITEM objects for equivalence.
@@ -245,7 +245,6 @@ public:
      */
     virtual void MoveTo( const wxPoint& aPosition ) = 0;
 
-    virtual wxPoint GetPosition() const = 0;
     void SetPosition( const wxPoint& aPosition ) { MoveTo( aPosition ); }
 
     /**
diff --git a/eeschema/lib_pin.cpp b/eeschema/lib_pin.cpp
index 3e5b029ce0..010b1542b3 100644
--- a/eeschema/lib_pin.cpp
+++ b/eeschema/lib_pin.cpp
@@ -1407,11 +1407,11 @@ void LIB_PIN::SetWidth( int aWidth )
 }
 
 
-void LIB_PIN::getMsgPanelInfoBase( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
+void LIB_PIN::getMsgPanelInfoBase( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
 {
     wxString text = m_number.IsEmpty() ? wxT( "?" ) : m_number;
 
-    LIB_ITEM::GetMsgPanelInfo( aUnits, aList );
+    LIB_ITEM::GetMsgPanelInfo( aFrame, aList );
 
     aList.push_back( MSG_PANEL_ITEM( _( "Name" ), m_name, DARKCYAN ) );
     aList.push_back( MSG_PANEL_ITEM( _( "Number" ), text, DARKCYAN ) );
@@ -1424,33 +1424,35 @@ void LIB_PIN::getMsgPanelInfoBase( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
     aList.push_back( MSG_PANEL_ITEM( _( "Visible" ), text, DARKGREEN ) );
 
     // Display pin length
-    text = StringFromValue( aUnits, m_length, true );
+    text = StringFromValue( aFrame->GetUserUnits(), m_length, true );
     aList.push_back( MSG_PANEL_ITEM( _( "Length" ), text, MAGENTA ) );
 
     text = getPinOrientationName( (unsigned) GetOrientationIndex( m_orientation ) );
     aList.push_back( MSG_PANEL_ITEM( _( "Orientation" ), text, DARKMAGENTA ) );
 }
 
-void LIB_PIN::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
+
+void LIB_PIN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
 {
-    getMsgPanelInfoBase( aUnits, aList );
+    getMsgPanelInfoBase( aFrame, aList );
 
     wxString text;
     wxPoint pinpos = GetPosition();
     pinpos.y = -pinpos.y;   // Display coord are top to bottom
                             // lib items coord are bottom to top
 
-    text = MessageTextFromValue( aUnits, pinpos.x, true );
+    text = MessageTextFromValue( aFrame->GetUserUnits(), pinpos.x, true );
     aList.push_back( MSG_PANEL_ITEM( _( "Pos X" ), text, DARKMAGENTA ) );
 
-    text = MessageTextFromValue( aUnits, pinpos.y, true );
+    text = MessageTextFromValue( aFrame->GetUserUnits(), pinpos.y, true );
     aList.push_back( MSG_PANEL_ITEM( _( "Pos Y" ), text, DARKMAGENTA ) );
 }
 
-void LIB_PIN::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList,
+
+void LIB_PIN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList,
                                SCH_COMPONENT* aComponent )
 {
-    getMsgPanelInfoBase( aUnits, aList );
+    getMsgPanelInfoBase( aFrame, aList );
 
     if( !aComponent )
         return;
@@ -1459,10 +1461,10 @@ void LIB_PIN::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aL
     wxPoint pinpos = aComponent->GetTransform().TransformCoordinate( GetPosition() )
                      + aComponent->GetPosition();
 
-    text = MessageTextFromValue( aUnits, pinpos.x, true );
+    text = MessageTextFromValue( aFrame->GetUserUnits(), pinpos.x, true );
     aList.emplace_back( _( "Pos X" ), text, DARKMAGENTA );
 
-    text = MessageTextFromValue( aUnits, pinpos.y, true );
+    text = MessageTextFromValue( aFrame->GetUserUnits(), pinpos.y, true );
     aList.emplace_back( _( "Pos Y" ), text, DARKMAGENTA );
 
     aList.emplace_back( aComponent->GetField( REFERENCE )->GetShownText(),
diff --git a/eeschema/lib_pin.h b/eeschema/lib_pin.h
index 23a4a1bb7b..32757f1baa 100644
--- a/eeschema/lib_pin.h
+++ b/eeschema/lib_pin.h
@@ -113,7 +113,7 @@ public:
 
     bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     /**
      * Display pin info (given by GetMsgPanelInfo) and add some info related to aComponent
@@ -121,8 +121,8 @@ public:
      * @param aList is the message list to fill
      * @param aComponent is the component which "owns" the pin
      */
-    void GetMsgPanelInfo(
-            EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList, SCH_COMPONENT* aComponent );
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList,
+                          SCH_COMPONENT* aComponent );
 
     bool Matches( wxFindReplaceData& aSearchData, void* aAuxData ) override;
 
@@ -427,7 +427,7 @@ public:
 
     void MoveTo( const wxPoint& aPosition ) override;
 
-    wxPoint GetPosition() const override { return m_position; }
+    const wxPoint GetPosition() const override { return m_position; }
 
     /**
      * move this and all linked pins to the new position
@@ -461,7 +461,7 @@ private:
      * they are pin info without the actual pin position, which
      * is not known in schematic without knowing the parent component
      */
-    void getMsgPanelInfoBase( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList );
+    void getMsgPanelInfoBase( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList );
 
 
     /**
diff --git a/eeschema/lib_polyline.cpp b/eeschema/lib_polyline.cpp
index 2e80c71b9f..298018d318 100644
--- a/eeschema/lib_polyline.cpp
+++ b/eeschema/lib_polyline.cpp
@@ -26,12 +26,13 @@
 #include <gr_basic.h>
 #include <macros.h>
 #include <sch_draw_panel.h>
+#include <eda_draw_frame.h>
 #include <plotter.h>
 #include <trigo.h>
 #include <base_units.h>
 #include <msgpanel.h>
 #include <bitmaps.h>
-
+#include <eda_draw_frame.h>
 #include <general.h>
 #include <lib_polyline.h>
 #include <settings/color_settings.h>
@@ -330,14 +331,14 @@ void LIB_POLYLINE::DeleteSegment( const wxPoint aPosition )
 }
 
 
-void LIB_POLYLINE::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
+void LIB_POLYLINE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
 {
     wxString msg;
     EDA_RECT bBox = GetBoundingBox();
 
-    LIB_ITEM::GetMsgPanelInfo( aUnits, aList );
+    LIB_ITEM::GetMsgPanelInfo( aFrame, aList );
 
-    msg = MessageTextFromValue( aUnits, m_Width, true );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), m_Width, true );
 
     aList.push_back( MSG_PANEL_ITEM( _( "Line Width" ), msg, BLUE ) );
 
diff --git a/eeschema/lib_polyline.h b/eeschema/lib_polyline.h
index 255d61a80c..d7580a26dc 100644
--- a/eeschema/lib_polyline.h
+++ b/eeschema/lib_polyline.h
@@ -79,7 +79,7 @@ public:
 
     int GetPenWidth() const override;
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     void BeginEdit( const wxPoint aStartPoint ) override;
     void CalcEdit( const wxPoint& aPosition ) override;
@@ -90,7 +90,7 @@ public:
 
     void MoveTo( const wxPoint& aPosition ) override;
 
-    wxPoint GetPosition() const override { return m_PolyPoints[0]; }
+    const wxPoint GetPosition() const override { return m_PolyPoints[0]; }
 
     void MirrorHorizontal( const wxPoint& aCenter ) override;
     void MirrorVertical( const wxPoint& aCenter ) override;
diff --git a/eeschema/lib_rectangle.cpp b/eeschema/lib_rectangle.cpp
index d8a09e67a6..9861a16825 100644
--- a/eeschema/lib_rectangle.cpp
+++ b/eeschema/lib_rectangle.cpp
@@ -31,7 +31,7 @@
 #include <base_units.h>
 #include <msgpanel.h>
 #include <bitmaps.h>
-
+#include <eda_draw_frame.h>
 #include <general.h>
 #include <lib_rectangle.h>
 #include <settings/color_settings.h>
@@ -191,11 +191,11 @@ void LIB_RECTANGLE::print( RENDER_SETTINGS* aSettings, const wxPoint& aOffset, v
 }
 
 
-void LIB_RECTANGLE::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
+void LIB_RECTANGLE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
 {
-    LIB_ITEM::GetMsgPanelInfo( aUnits, aList );
+    LIB_ITEM::GetMsgPanelInfo( aFrame, aList );
 
-    wxString msg = MessageTextFromValue( aUnits, m_Width, true );
+    wxString msg = MessageTextFromValue( aFrame->GetUserUnits(), m_Width, true );
 
     aList.push_back( MSG_PANEL_ITEM( _( "Line Width" ), msg, BLUE ) );
 }
diff --git a/eeschema/lib_rectangle.h b/eeschema/lib_rectangle.h
index c741f6c548..6e222384c0 100644
--- a/eeschema/lib_rectangle.h
+++ b/eeschema/lib_rectangle.h
@@ -62,7 +62,7 @@ public:
 
     const EDA_RECT GetBoundingBox() const override;
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     void BeginEdit( const wxPoint aStartPoint ) override;
     void CalcEdit( const wxPoint& aPosition ) override;
@@ -71,7 +71,7 @@ public:
 
     void MoveTo( const wxPoint& aPosition ) override;
 
-    wxPoint GetPosition() const override { return m_Pos; }
+    const wxPoint GetPosition() const override { return m_Pos; }
 
     void MirrorHorizontal( const wxPoint& aCenter ) override;
     void MirrorVertical( const wxPoint& aCenter ) override;
diff --git a/eeschema/lib_text.cpp b/eeschema/lib_text.cpp
index 7842b62dde..e20260055e 100644
--- a/eeschema/lib_text.cpp
+++ b/eeschema/lib_text.cpp
@@ -35,7 +35,7 @@
 #include <base_units.h>
 #include <msgpanel.h>
 #include <bitmaps.h>
-
+#include <eda_draw_frame.h>
 #include <lib_item.h>
 #include <general.h>
 #include <transform.h>
@@ -347,11 +347,11 @@ void LIB_TEXT::print( RENDER_SETTINGS* aSettings, const wxPoint& aOffset, void*
 }
 
 
-void LIB_TEXT::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
+void LIB_TEXT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
 {
-    LIB_ITEM::GetMsgPanelInfo( aUnits, aList );
+    LIB_ITEM::GetMsgPanelInfo( aFrame, aList );
 
-    wxString msg = MessageTextFromValue( aUnits, GetTextThickness(), true );
+    wxString msg = MessageTextFromValue( aFrame->GetUserUnits(), GetTextThickness(), true );
     aList.push_back( MSG_PANEL_ITEM( _( "Line Width" ), msg, BLUE ) );
 }
 
diff --git a/eeschema/lib_text.h b/eeschema/lib_text.h
index 381daadd28..026e9db791 100644
--- a/eeschema/lib_text.h
+++ b/eeschema/lib_text.h
@@ -70,7 +70,7 @@ public:
 
     int GetPenWidth() const override;
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     const EDA_RECT GetBoundingBox() const override;
 
@@ -81,7 +81,7 @@ public:
 
     void MoveTo( const wxPoint& aPosition ) override;
 
-    wxPoint GetPosition() const override { return EDA_TEXT::GetTextPos(); }
+    const wxPoint GetPosition() const override { return EDA_TEXT::GetTextPos(); }
 
     void MirrorHorizontal( const wxPoint& aCenter ) override;
     void MirrorVertical( const wxPoint& aCenter ) override;
diff --git a/eeschema/sch_bitmap.cpp b/eeschema/sch_bitmap.cpp
index 64c80e9b99..ee9f0d1f2a 100644
--- a/eeschema/sch_bitmap.cpp
+++ b/eeschema/sch_bitmap.cpp
@@ -34,7 +34,7 @@
 #include <macros.h>
 #include <bitmaps.h>
 #include <base_units.h>
-
+#include <eda_draw_frame.h>
 #include <sch_bitmap.h>
 
 #include <wx/mstream.h>
@@ -196,14 +196,14 @@ BITMAP_DEF SCH_BITMAP::GetMenuImage() const
 }
 
 
-void SCH_BITMAP::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
+void SCH_BITMAP::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
 {
     aList.push_back( MSG_PANEL_ITEM( _( "Bitmap" ), wxEmptyString, RED ) );
 
-    aList.push_back(
-            MSG_PANEL_ITEM( _( "Width" ), MessageTextFromValue( aUnits, GetSize().x ), RED ) );
-    aList.push_back(
-            MSG_PANEL_ITEM( _( "Height" ), MessageTextFromValue( aUnits, GetSize().y ), RED ) );
+    aList.push_back( MSG_PANEL_ITEM( _( "Width" ),
+                     MessageTextFromValue( aFrame->GetUserUnits(), GetSize().x ), RED ) );
+    aList.push_back( MSG_PANEL_ITEM( _( "Height" ),
+                     MessageTextFromValue( aFrame->GetUserUnits(), GetSize().y ), RED ) );
 }
 
 
diff --git a/eeschema/sch_bitmap.h b/eeschema/sch_bitmap.h
index f7bbdceb48..d49d38cfa7 100644
--- a/eeschema/sch_bitmap.h
+++ b/eeschema/sch_bitmap.h
@@ -135,9 +135,9 @@ public:
 
     BITMAP_DEF GetMenuImage() const override;
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
-    wxPoint GetPosition() const override { return m_pos; }
+    const wxPoint GetPosition() const override { return m_pos; }
     void SetPosition( const wxPoint& aPosition ) override { m_pos = aPosition; }
 
     bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
diff --git a/eeschema/sch_bus_entry.cpp b/eeschema/sch_bus_entry.cpp
index b6becbc6df..96f42f660c 100644
--- a/eeschema/sch_bus_entry.cpp
+++ b/eeschema/sch_bus_entry.cpp
@@ -390,7 +390,7 @@ char SCH_BUS_ENTRY_BASE::GetBusEntryShape() const
 }
 
 
-void SCH_BUS_ENTRY_BASE::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
+void SCH_BUS_ENTRY_BASE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
 {
     wxString msg;
 
diff --git a/eeschema/sch_bus_entry.h b/eeschema/sch_bus_entry.h
index 4f8623b091..d3fd8fae78 100644
--- a/eeschema/sch_bus_entry.h
+++ b/eeschema/sch_bus_entry.h
@@ -101,7 +101,7 @@ public:
 
     void GetConnectionPoints( std::vector< wxPoint >& aPoints ) const override;
 
-    wxPoint GetPosition() const override { return m_pos; }
+    const wxPoint GetPosition() const override { return m_pos; }
     void SetPosition( const wxPoint& aPosition ) override { m_pos = aPosition; }
 
     bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
@@ -109,7 +109,7 @@ public:
 
     void Plot( PLOTTER* aPlotter ) override;
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     bool operator <( const SCH_ITEM& aItem ) const override;
 
diff --git a/eeschema/sch_component.cpp b/eeschema/sch_component.cpp
index 0b5f25b1ab..9486a8353b 100644
--- a/eeschema/sch_component.cpp
+++ b/eeschema/sch_component.cpp
@@ -1282,7 +1282,7 @@ const EDA_RECT SCH_COMPONENT::GetBoundingBox() const
 }
 
 
-void SCH_COMPONENT::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
+void SCH_COMPONENT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
 {
     wxString msg;
 
@@ -1463,7 +1463,7 @@ bool SCH_COMPONENT::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemLi
         bool previousState = pin->IsDangling();
         pin->SetIsDangling( true );
 
-        wxPoint pos = m_transform.TransformCoordinate( pin->GetPosition() ) + m_Pos;
+        wxPoint pos = m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_Pos;
 
         for( DANGLING_END_ITEM& each_item : aItemList )
         {
@@ -1528,7 +1528,7 @@ void SCH_COMPONENT::GetConnectionPoints( std::vector< wxPoint >& aPoints ) const
         if( pin_convert > 0 && pin_convert != GetConvert() )
             continue;
 
-        aPoints.push_back( m_transform.TransformCoordinate( pin->GetPosition() ) + m_Pos );
+        aPoints.push_back( m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_Pos );
     }
 }
 
@@ -1796,8 +1796,8 @@ bool SCH_COMPONENT::doIsConnected( const wxPoint& aPosition ) const
     {
         // Collect only pins attached to the current unit and convert.
         // others are not associated to this component instance
-        int pin_unit = pin.get()->GetLibPin()->GetUnit();
-        int pin_convert = pin.get()->GetLibPin()->GetConvert();
+        int pin_unit = pin->GetLibPin()->GetUnit();
+        int pin_convert = pin->GetLibPin()->GetConvert();
 
         if( pin_unit > 0 && pin_unit != GetUnit() )
             continue;
@@ -1805,7 +1805,7 @@ bool SCH_COMPONENT::doIsConnected( const wxPoint& aPosition ) const
         if( pin_convert > 0 && pin_convert != GetConvert() )
             continue;
 
-        if( pin->GetPosition() == new_pos )
+        if( pin->GetLocalPosition() == new_pos )
             return true;
     }
 
diff --git a/eeschema/sch_component.h b/eeschema/sch_component.h
index 756cab8f78..3ea2e0c9a2 100644
--- a/eeschema/sch_component.h
+++ b/eeschema/sch_component.h
@@ -311,7 +311,7 @@ public:
      */
     bool ResolveTextVar( wxString* token, int aDepth = 0 ) const;
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     /**
      * Clear exiting component annotation.
@@ -614,7 +614,7 @@ public:
 
     bool IsReplaceable() const override { return true; }
 
-    wxPoint GetPosition() const override { return m_Pos; }
+    const wxPoint GetPosition() const override { return m_Pos; }
     void SetPosition( const wxPoint& aPosition ) override { Move( aPosition - m_Pos ); }
 
     bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
diff --git a/eeschema/sch_eagle_plugin.cpp b/eeschema/sch_eagle_plugin.cpp
index 9c7eb30b4f..87830e6c02 100644
--- a/eeschema/sch_eagle_plugin.cpp
+++ b/eeschema/sch_eagle_plugin.cpp
@@ -2042,8 +2042,10 @@ void SCH_EAGLE_PLUGIN::addBusEntries()
                             }
                             else
                             {
-                                SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-                                marker->SetData( 0, linestart, "Bus Entry needed" );
+                                ERC_ITEM* ercItem = new ERC_ITEM( 0 );
+                                ercItem->SetErrorMessage( _( "Bus Entry needed" ) );
+
+                                SCH_MARKER* marker = new SCH_MARKER( ercItem, linestart );
                                 m_currentSheet->GetScreen()->Append( marker );
                             }
                         }
@@ -2078,8 +2080,10 @@ void SCH_EAGLE_PLUGIN::addBusEntries()
                             }
                             else
                             {
-                                SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-                                marker->SetData( 0, linestart, "Bus Entry needed" );
+                                ERC_ITEM* ercItem = new ERC_ITEM( 0 );
+                                ercItem->SetErrorMessage( _( "Bus Entry needed" ) );
+
+                                SCH_MARKER* marker = new SCH_MARKER( ercItem, linestart );
                                 m_currentSheet->GetScreen()->Append( marker );
                             }
                         }
@@ -2118,8 +2122,10 @@ void SCH_EAGLE_PLUGIN::addBusEntries()
                             }
                             else
                             {
-                                SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-                                marker->SetData( 0, lineend, "Bus Entry needed" );
+                                ERC_ITEM* ercItem = new ERC_ITEM( 0 );
+                                ercItem->SetErrorMessage( _( "Bus Entry needed" ) );
+
+                                SCH_MARKER* marker = new SCH_MARKER( ercItem, lineend );
                                 m_currentSheet->GetScreen()->Append( marker );
                             }
                         }
@@ -2153,8 +2159,10 @@ void SCH_EAGLE_PLUGIN::addBusEntries()
                             }
                             else
                             {
-                                SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-                                marker->SetData( 0, lineend, "Bus Entry needed" );
+                                ERC_ITEM* ercItem = new ERC_ITEM( 0 );
+                                ercItem->SetErrorMessage( _( "Bus Entry needed" ) );
+
+                                SCH_MARKER* marker = new SCH_MARKER( ercItem, lineend );
                                 m_currentSheet->GetScreen()->Append( marker );
                             }
                         }
@@ -2193,8 +2201,10 @@ void SCH_EAGLE_PLUGIN::addBusEntries()
                             }
                             else
                             {
-                                SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-                                marker->SetData( 0, linestart, "Bus Entry needed" );
+                                ERC_ITEM* ercItem = new ERC_ITEM( 0 );
+                                ercItem->SetErrorMessage( _( "Bus Entry needed" ) );
+
+                                SCH_MARKER* marker = new SCH_MARKER( ercItem, linestart );
                                 m_currentSheet->GetScreen()->Append( marker );
                             }
                         }
@@ -2223,8 +2233,10 @@ void SCH_EAGLE_PLUGIN::addBusEntries()
                             }
                             else
                             {
-                                SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-                                marker->SetData( 0, linestart, "Bus Entry needed" );
+                                ERC_ITEM* ercItem = new ERC_ITEM( 0 );
+                                ercItem->SetErrorMessage( _( "Bus Entry needed" ) );
+
+                                SCH_MARKER* marker = new SCH_MARKER( ercItem, linestart );
                                 m_currentSheet->GetScreen()->Append( marker );
                             }
                         }
@@ -2260,8 +2272,10 @@ void SCH_EAGLE_PLUGIN::addBusEntries()
                             }
                             else
                             {
-                                SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-                                marker->SetData( 0, lineend, "Bus Entry needed" );
+                                ERC_ITEM* ercItem = new ERC_ITEM( 0 );
+                                ercItem->SetErrorMessage( _( "Bus Entry needed" ) );
+
+                                SCH_MARKER* marker = new SCH_MARKER( ercItem, lineend );
                                 m_currentSheet->GetScreen()->Append( marker );
                             }
                         }
@@ -2290,8 +2304,10 @@ void SCH_EAGLE_PLUGIN::addBusEntries()
                             }
                             else
                             {
-                                SCH_MARKER* marker = new SCH_MARKER( MARKER_BASE::MARKER_ERC );
-                                marker->SetData( 0, lineend, "Bus Entry needed" );
+                                ERC_ITEM* ercItem = new ERC_ITEM( 0 );
+                                ercItem->SetErrorMessage( _( "Bus Entry needed" ) );
+
+                                SCH_MARKER* marker = new SCH_MARKER( ercItem, lineend );
                                 m_currentSheet->GetScreen()->Append( marker );
                             }
                         }
diff --git a/eeschema/sch_edit_frame.cpp b/eeschema/sch_edit_frame.cpp
index 1e4ecc4b97..57f2aba757 100644
--- a/eeschema/sch_edit_frame.cpp
+++ b/eeschema/sch_edit_frame.cpp
@@ -362,6 +362,15 @@ void SCH_EDIT_FRAME::SaveCopyForRepeatItem( SCH_ITEM* aItem )
 }
 
 
+EDA_ITEM* SCH_EDIT_FRAME::GetItem( const KIID& aId )
+{
+    SCH_SHEET_LIST schematic( g_RootSheet );
+    SCH_SHEET_PATH dummy;
+
+    return schematic.GetItem( aId, &dummy );
+}
+
+
 void SCH_EDIT_FRAME::SetSheetNumberAndCount()
 {
     SCH_SCREEN* screen;
@@ -1176,12 +1185,11 @@ void SCH_EDIT_FRAME::FixupJunctions()
 
         for( auto aItem : screen->Items().OfType( SCH_COMPONENT_T ) )
         {
-            auto cmp   = static_cast<SCH_COMPONENT*>( aItem );
-            auto xform = cmp->GetTransform();
+            auto cmp = static_cast<SCH_COMPONENT*>( aItem );
 
             for( const SCH_PIN* pin : cmp->GetSchPins( &sheet ) )
             {
-                auto pos = cmp->GetPosition() + xform.TransformCoordinate( pin->GetPosition() );
+                auto pos = pin->GetPosition();
 
                 // Test if a _new_ junction is needed, and add it if missing
                 if( screen->IsJunctionNeeded( pos, true ) )
diff --git a/eeschema/sch_edit_frame.h b/eeschema/sch_edit_frame.h
index 7ec9043297..2156fa5ba4 100644
--- a/eeschema/sch_edit_frame.h
+++ b/eeschema/sch_edit_frame.h
@@ -915,6 +915,8 @@ public:
      */
     SCH_ITEM* GetRepeatItem() const             { return m_item_to_repeat; }
 
+    EDA_ITEM* GetItem( const KIID& aId ) override;
+
     /**
      * Performs an undo of the last edit WITHOUT logging a corresponding redo.  Used to cancel
      * an in-progress operation.
diff --git a/eeschema/sch_field.cpp b/eeschema/sch_field.cpp
index d2e24b12cd..5fd3ad37bd 100644
--- a/eeschema/sch_field.cpp
+++ b/eeschema/sch_field.cpp
@@ -550,7 +550,7 @@ void SCH_FIELD::SetPosition( const wxPoint& aPosition )
 }
 
 
-wxPoint SCH_FIELD::GetPosition() const
+const wxPoint SCH_FIELD::GetPosition() const
 {
     if( m_Parent && m_Parent->Type() == SCH_COMPONENT_T )
     {
@@ -568,12 +568,7 @@ wxPoint SCH_FIELD::GetPosition() const
 
 wxPoint SCH_FIELD::GetParentPosition() const
 {
-    if( m_Parent && m_Parent->Type() == SCH_COMPONENT_T )
-        return static_cast<SCH_COMPONENT*>( m_Parent )->GetPosition();
-    else if( m_Parent && m_Parent->Type() == SCH_SHEET_T )
-        return static_cast<SCH_SHEET*>( m_Parent )->GetPosition();
-    else
-        return wxPoint();
+    return m_Parent->GetPosition();
 }
 
 
diff --git a/eeschema/sch_field.h b/eeschema/sch_field.h
index a15a109d1f..b932a40997 100644
--- a/eeschema/sch_field.h
+++ b/eeschema/sch_field.h
@@ -187,7 +187,7 @@ public:
 
     wxPoint GetLibPosition() const { return EDA_TEXT::GetTextPos(); }
 
-    wxPoint GetPosition() const override;
+    const wxPoint GetPosition() const override;
     void SetPosition( const wxPoint& aPosition ) override;
 
     wxPoint GetParentPosition() const;
diff --git a/eeschema/sch_item.h b/eeschema/sch_item.h
index 6ce242f02c..6d516dfafb 100644
--- a/eeschema/sch_item.h
+++ b/eeschema/sch_item.h
@@ -131,7 +131,7 @@ public:
                 || ( m_pos == rhs.m_pos && m_item < rhs.m_item ) );
     }
 
-    wxPoint GetPosition() const { return m_pos; }
+    const wxPoint GetPosition() const { return m_pos; }
     EDA_ITEM* GetItem() const { return m_item; }
     const EDA_ITEM* GetParent() const { return m_parent; }
     DANGLING_END_T GetType() const { return m_type; }
@@ -444,12 +444,6 @@ public:
     virtual void GetNetListItem( NETLIST_OBJECT_LIST& aNetListItems,
                                  SCH_SHEET_PATH*      aSheetPath ) { }
 
-    /**
-     * Function GetPosition
-     * @return A wxPoint object containing the schematic item position.
-     */
-    virtual wxPoint GetPosition() const = 0;
-
     /**
      * Function SetPosition
      * set the schematic item position to \a aPosition.
diff --git a/eeschema/sch_junction.h b/eeschema/sch_junction.h
index c85e52d119..2fc5b09ae7 100644
--- a/eeschema/sch_junction.h
+++ b/eeschema/sch_junction.h
@@ -94,7 +94,7 @@ public:
 
     void GetNetListItem( NETLIST_OBJECT_LIST& aNetListItems, SCH_SHEET_PATH* aSheetPath ) override;
 
-    wxPoint GetPosition() const override { return m_pos; }
+    const wxPoint GetPosition() const override { return m_pos; }
     void SetPosition( const wxPoint& aPosition ) override { m_pos = aPosition; }
 
     bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
diff --git a/eeschema/sch_line.cpp b/eeschema/sch_line.cpp
index 75477b2f76..bb7954fa8c 100644
--- a/eeschema/sch_line.cpp
+++ b/eeschema/sch_line.cpp
@@ -767,7 +767,7 @@ void SCH_LINE::SetPosition( const wxPoint& aPosition )
 }
 
 
-void SCH_LINE::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
+void SCH_LINE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
 {
     wxString msg;
 
diff --git a/eeschema/sch_line.h b/eeschema/sch_line.h
index 184ae1fc4f..1550fa2d24 100644
--- a/eeschema/sch_line.h
+++ b/eeschema/sch_line.h
@@ -206,7 +206,7 @@ public:
 
     bool operator <( const SCH_ITEM& aItem ) const override;
 
-    wxPoint GetPosition() const override { return m_start; }
+    const wxPoint GetPosition() const override { return m_start; }
     void SetPosition( const wxPoint& aPosition ) override;
 
     bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
@@ -218,7 +218,7 @@ public:
 
     void SwapData( SCH_ITEM* aItem ) override;
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
 #if defined(DEBUG)
     void Show( int nestLevel, std::ostream& os ) const override;
diff --git a/eeschema/sch_marker.cpp b/eeschema/sch_marker.cpp
index 1e58bcbf8f..cca5d8e362 100644
--- a/eeschema/sch_marker.cpp
+++ b/eeschema/sch_marker.cpp
@@ -39,10 +39,14 @@
 #define SCALING_FACTOR  Millimeter2iu( 0.1 )
 
 
-SCH_MARKER::SCH_MARKER( TYPEMARKER aType ) :
+SCH_MARKER::SCH_MARKER( ERC_ITEM* aItem, const wxPoint& aPos ) :
         SCH_ITEM( nullptr, SCH_MARKER_T ),
-        MARKER_BASE( SCALING_FACTOR, new ERC_ITEM(), aType )
+        MARKER_BASE( SCALING_FACTOR, aItem, MARKER_BASE::MARKER_ERC )
 {
+    if( m_rcItem )
+        m_rcItem->SetParent( this );
+
+    m_Pos = aPos;
 }
 
 
@@ -113,9 +117,7 @@ void SCH_MARKER::Print( RENDER_SETTINGS* aSettings, const wxPoint& aOffset )
 
 bool SCH_MARKER::Matches( wxFindReplaceData& aSearchData, void* aAuxData )
 {
-    return SCH_ITEM::Matches( m_rcItem->GetErrorText(), aSearchData )
-                || SCH_ITEM::Matches( m_rcItem->GetMainText(), aSearchData )
-                || SCH_ITEM::Matches( m_rcItem->GetAuxText(), aSearchData );
+    return SCH_ITEM::Matches( m_rcItem->GetErrorText(), aSearchData );
 }
 
 
@@ -125,7 +127,7 @@ const EDA_RECT SCH_MARKER::GetBoundingBox() const
 }
 
 
-void SCH_MARKER::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
+void SCH_MARKER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
 {
     aList.push_back( MSG_PANEL_ITEM( _( "Electronics Rule Check Error" ),
                                      m_rcItem->GetErrorText(), DARKRED ) );
diff --git a/eeschema/sch_marker.h b/eeschema/sch_marker.h
index 911618b3b4..b427088460 100644
--- a/eeschema/sch_marker.h
+++ b/eeschema/sch_marker.h
@@ -25,6 +25,7 @@
 #ifndef TYPE_SCH_MARKER_H_
 #define TYPE_SCH_MARKER_H_
 
+#include <erc_item.h>
 #include <sch_item.h>
 #include <marker_base.h>
 
@@ -32,7 +33,7 @@
 class SCH_MARKER : public SCH_ITEM, public MARKER_BASE
 {
 public:
-    SCH_MARKER( TYPEMARKER aType );
+    SCH_MARKER( ERC_ITEM* aItem, const wxPoint& aPos );
 
     // Do not create a copy constructor.  The one generated by the compiler is adequate.
 
@@ -88,7 +89,7 @@ public:
      */
     bool Matches( wxFindReplaceData& aSearchData, void* aAuxDat ) override;
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     wxString GetSelectMenuText( EDA_UNITS aUnits ) const override
     {
@@ -97,7 +98,7 @@ public:
 
     BITMAP_DEF GetMenuImage() const override;
 
-    wxPoint GetPosition() const override { return m_Pos; }
+    const wxPoint GetPosition() const override { return m_Pos; }
     void SetPosition( const wxPoint& aPosition ) override { m_Pos = aPosition; }
 
     bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
diff --git a/eeschema/sch_no_connect.h b/eeschema/sch_no_connect.h
index fe2d510975..dcd017cf29 100644
--- a/eeschema/sch_no_connect.h
+++ b/eeschema/sch_no_connect.h
@@ -105,7 +105,7 @@ public:
 
     void GetNetListItem( NETLIST_OBJECT_LIST& aNetListItems, SCH_SHEET_PATH* aSheetPath ) override;
 
-    wxPoint GetPosition() const override { return m_pos; }
+    const wxPoint GetPosition() const override { return m_pos; }
     void SetPosition( const wxPoint& aPosition ) override { m_pos = aPosition; }
 
     bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
diff --git a/eeschema/sch_pin.cpp b/eeschema/sch_pin.cpp
index ad25df8a3f..c85ddb6997 100644
--- a/eeschema/sch_pin.cpp
+++ b/eeschema/sch_pin.cpp
@@ -75,27 +75,9 @@ wxString SCH_PIN::GetSelectMenuText( EDA_UNITS aUnits ) const
 }
 
 
-void SCH_PIN::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
+void SCH_PIN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
 {
-    m_libPin->GetMsgPanelInfo( aUnits, aList, GetParentComponent() );
-}
-
-
-wxString SCH_PIN::GetDescription( const SCH_SHEET_PATH* aSheet )
-{
-    if( GetName().IsEmpty() || GetNumber().IsEmpty() )
-    {
-        return wxString::Format( _( "Pin %s of component %s." ),
-                                 GetName().IsEmpty() ? GetNumber() : GetName(),
-                                 GetParentComponent()->GetRef( aSheet ) );
-    }
-    else
-    {
-        return wxString::Format( _( "Pin %s (%s) of component %s." ),
-                                 GetName(),
-                                 GetNumber(),
-                                 GetParentComponent()->GetRef( aSheet ) );
-    }
+    m_libPin->GetMsgPanelInfo( aFrame, aList, GetParentComponent() );
 }
 
 
@@ -134,7 +116,7 @@ wxString SCH_PIN::GetDefaultNetName( const SCH_SHEET_PATH aPath )
 wxPoint SCH_PIN::GetTransformedPosition() const
 {
     TRANSFORM t = GetParentComponent()->GetTransform();
-    return ( t.TransformCoordinate( GetPosition() ) + GetParentComponent()->GetPosition() );
+    return ( t.TransformCoordinate( GetLocalPosition() ) + GetParentComponent()->GetPosition() );
 }
 
 
diff --git a/eeschema/sch_pin.h b/eeschema/sch_pin.h
index 092635ec2f..60fbdd9af0 100644
--- a/eeschema/sch_pin.h
+++ b/eeschema/sch_pin.h
@@ -67,8 +67,7 @@ public:
     wxString GetDefaultNetName( const SCH_SHEET_PATH aPath );
 
     wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
-    void GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList ) override;
-    wxString GetDescription( const SCH_SHEET_PATH* aSheet );
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList ) override;
 
     void Print( RENDER_SETTINGS* aSettings, const wxPoint& aOffset ) override {}
 
@@ -79,7 +78,8 @@ public:
 
     void Rotate( wxPoint aPosition ) override {}
 
-    wxPoint GetPosition() const override { return m_position; }
+    const wxPoint GetPosition() const override { return GetTransformedPosition(); }
+    const wxPoint GetLocalPosition() const { return m_position; }
     void SetPosition( const wxPoint& aPosition ) override { m_position = aPosition; }
 
     const EDA_RECT GetBoundingBox() const override;
diff --git a/eeschema/sch_sheet.cpp b/eeschema/sch_sheet.cpp
index 27e4ff4d36..db1fa79d2e 100644
--- a/eeschema/sch_sheet.cpp
+++ b/eeschema/sch_sheet.cpp
@@ -679,7 +679,7 @@ int SCH_SHEET::CountSheets()
 }
 
 
-void SCH_SHEET::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
+void SCH_SHEET::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
 {
     aList.emplace_back( _( "Sheet Name" ), m_fields[ SHEETNAME ].GetText(), CYAN );
     aList.emplace_back( _( "File Name" ), m_fields[ SHEETFILENAME ].GetText(), BROWN );
diff --git a/eeschema/sch_sheet.h b/eeschema/sch_sheet.h
index 3c9e72f506..ab3f51da57 100644
--- a/eeschema/sch_sheet.h
+++ b/eeschema/sch_sheet.h
@@ -342,7 +342,7 @@ public:
      */
     bool ResolveTextVar( wxString* token, int aDepth = 0 ) const;
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     /* there is no member for orientation in sch_sheet, to preserve file
      * format, we detect orientation based on pin edges
@@ -568,7 +568,7 @@ public:
 
     void ViewGetLayers( int aLayers[], int& aCount ) const override;
 
-    wxPoint GetPosition() const override { return m_pos; }
+    const wxPoint GetPosition() const override { return m_pos; }
     void SetPosition( const wxPoint& aPosition ) override;
 
     bool HitTest( const wxPoint& aPosition, int aAccuracy ) const override;
diff --git a/eeschema/sch_sheet_path.cpp b/eeschema/sch_sheet_path.cpp
index 19dcf97829..3479bb90c8 100644
--- a/eeschema/sch_sheet_path.cpp
+++ b/eeschema/sch_sheet_path.cpp
@@ -27,7 +27,7 @@
 
 #include <sch_screen.h>
 #include <sch_item.h>
-
+#include <sch_marker.h>
 #include <sch_reference_list.h>
 #include <class_library.h>
 #include <sch_sheet_path.h>
@@ -36,7 +36,7 @@
 #include <template_fieldnames.h>
 #include <boost/functional/hash.hpp>
 #include <wx/filename.h>
-
+#include "erc_item.h"
 
 namespace std
 {
@@ -470,6 +470,41 @@ SCH_ITEM* SCH_SHEET_LIST::GetItem( const KIID& aID, SCH_SHEET_PATH* aPathOut )
 }
 
 
+SCH_ITEM* SCH_SHEET_LIST::FillItemMap( std::map<KIID, EDA_ITEM*>& aMap )
+{
+    for( const SCH_SHEET_PATH& sheet : *this )
+    {
+        SCH_SCREEN* screen = sheet.LastScreen();
+
+        for( SCH_ITEM* aItem : screen->Items() )
+        {
+            aMap[ aItem->m_Uuid ] = aItem;
+
+            if( aItem->Type() == SCH_COMPONENT_T )
+            {
+                SCH_COMPONENT* comp = static_cast<SCH_COMPONENT*>( aItem );
+
+                for( SCH_FIELD& field : comp->GetFields() )
+                    aMap[ field.m_Uuid ] = &field;
+
+                for( SCH_PIN* pin : comp->GetSchPins() )
+                    aMap[ pin->m_Uuid ] = pin;
+            }
+            else if( aItem->Type() == SCH_SHEET_T )
+            {
+                SCH_SHEET* sch_sheet = static_cast<SCH_SHEET*>( aItem );
+
+                for( SCH_FIELD& field : sch_sheet->GetFields() )
+                    aMap[ field.m_Uuid ] = &field;
+
+                for( SCH_SHEET_PIN* pin : sch_sheet->GetPins() )
+                    aMap[ pin->m_Uuid ] = pin;
+            }
+        }
+    }
+}
+
+
 void SCH_SHEET_LIST::AnnotatePowerSymbols()
 {
     // List of reference for power symbols
@@ -647,3 +682,95 @@ SCH_SHEET_PATH* SCH_SHEET_LIST::FindSheetForScreen( SCH_SCREEN* aScreen )
 
     return nullptr;
 }
+
+
+void SHEETLIST_ERC_ITEMS_PROVIDER::SetSeverities( int aSeverities )
+{
+    m_severities = aSeverities;
+
+    m_filteredMarkers.clear();
+
+    SCH_SHEET_LIST sheetList( g_RootSheet);
+
+    for( unsigned i = 0; i < sheetList.size(); i++ )
+    {
+        for( SCH_ITEM* aItem : sheetList[i].LastScreen()->Items().OfType( SCH_MARKER_T ) )
+        {
+            SCH_MARKER* marker = static_cast<SCH_MARKER*>( aItem );
+            int markerSeverity;
+
+            if( marker->GetMarkerType() != MARKER_BASE::MARKER_ERC )
+                continue;
+
+            if( marker->IsExcluded() )
+                markerSeverity = RPT_SEVERITY_EXCLUSION;
+            else
+                markerSeverity = GetSeverity( marker->GetRCItem()->GetErrorCode() );
+
+            if( markerSeverity & m_severities )
+                m_filteredMarkers.push_back( marker );
+        }
+    }
+}
+
+
+int SHEETLIST_ERC_ITEMS_PROVIDER::GetCount( int aSeverity )
+{
+    if( aSeverity < 0 )
+        return m_filteredMarkers.size();
+
+    int count = 0;
+
+    SCH_SHEET_LIST sheetList( g_RootSheet);
+
+    for( unsigned i = 0; i < sheetList.size(); i++ )
+    {
+        for( SCH_ITEM* aItem : sheetList[i].LastScreen()->Items().OfType( SCH_MARKER_T ) )
+        {
+            SCH_MARKER* marker = static_cast<SCH_MARKER*>( aItem );
+            int markerSeverity;
+
+            if( marker->GetMarkerType() != MARKER_BASE::MARKER_ERC )
+                continue;
+
+            if( marker->IsExcluded() )
+                markerSeverity = RPT_SEVERITY_EXCLUSION;
+            else
+                markerSeverity = GetSeverity( marker->GetRCItem()->GetErrorCode() );
+
+            if( markerSeverity == aSeverity )
+                count++;
+        }
+    }
+
+    return count;
+}
+
+
+ERC_ITEM* SHEETLIST_ERC_ITEMS_PROVIDER::GetItem( int aIndex )
+{
+    SCH_MARKER* marker = m_filteredMarkers[ aIndex ];
+
+    return marker ? static_cast<ERC_ITEM*>( marker->GetRCItem() ) : nullptr;
+}
+
+
+void SHEETLIST_ERC_ITEMS_PROVIDER::DeleteItem( int aIndex, bool aDeep )
+{
+    SCH_MARKER* marker = m_filteredMarkers[ aIndex ];
+    m_filteredMarkers.erase( m_filteredMarkers.begin() + aIndex );
+
+    if( aDeep )
+    {
+        SCH_SCREENS ScreenList;
+        ScreenList.DeleteMarker( marker );
+    }
+}
+
+
+void SHEETLIST_ERC_ITEMS_PROVIDER::DeleteAllItems()
+{
+    SCH_SCREENS ScreenList;
+    ScreenList.DeleteAllMarkers( MARKER_BASE::MARKER_ERC );
+    m_filteredMarkers.clear();
+}
diff --git a/eeschema/sch_sheet_path.h b/eeschema/sch_sheet_path.h
index 6862c8be71..6ee6332b85 100644
--- a/eeschema/sch_sheet_path.h
+++ b/eeschema/sch_sheet_path.h
@@ -32,6 +32,7 @@
 #define CLASS_DRAWSHEET_PATH_H
 
 #include <base_struct.h>
+#include <erc_item.h>
 
 #include <map>
 
@@ -348,6 +349,11 @@ public:
      */
     SCH_ITEM* GetItem( const KIID& aID, SCH_SHEET_PATH* aPathOut );
 
+    /**
+     * Fill an item cache for temporary use when many items need to be fetched.
+     */
+    SCH_ITEM* FillItemMap( std::map<KIID, EDA_ITEM*>& aMap );
+
     /**
      * Function AnnotatePowerSymbols
      * Silently annotates the not yet annotated power symbols of the entire hierarchy
@@ -440,4 +446,33 @@ public:
     bool NameExists( const wxString& aSheetName );
 };
 
+
+/**
+ * SHEETLIST_ERC_ITEMS_PROVIDER
+ * is an implementation of the RC_ITEM_LISTinterface which uses the global SHEETLIST
+ * to fulfill the contract.
+ */
+class SHEETLIST_ERC_ITEMS_PROVIDER : public RC_ITEMS_PROVIDER
+{
+private:
+    int                      m_severities;
+    std::vector<SCH_MARKER*> m_filteredMarkers;
+
+public:
+    SHEETLIST_ERC_ITEMS_PROVIDER() :
+            m_severities( 0 )
+    { }
+
+    void SetSeverities( int aSeverities ) override;
+
+    int GetCount( int aSeverity = -1 ) override;
+
+    ERC_ITEM* GetItem( int aIndex ) override;
+
+    void DeleteItem( int aIndex, bool aDeep ) override;
+
+    void DeleteAllItems() override;
+};
+
+
 #endif // CLASS_DRAWSHEET_PATH_H
diff --git a/eeschema/sch_text.cpp b/eeschema/sch_text.cpp
index 2c352cac34..1544cd3e0f 100644
--- a/eeschema/sch_text.cpp
+++ b/eeschema/sch_text.cpp
@@ -627,7 +627,7 @@ void SCH_TEXT::Plot( PLOTTER* aPlotter )
 }
 
 
-void SCH_TEXT::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
+void SCH_TEXT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
 {
     wxString msg;
 
@@ -673,7 +673,7 @@ void SCH_TEXT::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
     }
 
     // Display text size (X or Y value, with are the same value in Eeschema)
-    msg = MessageTextFromValue( aUnits, GetTextWidth(), true );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), GetTextWidth(), true );
     aList.push_back( MSG_PANEL_ITEM( _( "Size" ), msg, RED ) );
 
 #if defined(DEBUG)
diff --git a/eeschema/sch_text.h b/eeschema/sch_text.h
index 4728e5e045..de2bb1e7dc 100644
--- a/eeschema/sch_text.h
+++ b/eeschema/sch_text.h
@@ -304,7 +304,7 @@ public:
 
     void GetNetListItem( NETLIST_OBJECT_LIST& aNetListItems, SCH_SHEET_PATH* aSheetPath ) override;
 
-    wxPoint GetPosition() const override { return EDA_TEXT::GetTextPos(); }
+    const wxPoint GetPosition() const override { return EDA_TEXT::GetTextPos(); }
     void SetPosition( const wxPoint& aPosition ) override { EDA_TEXT::SetTextPos( aPosition ); }
 
     bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
@@ -314,7 +314,7 @@ public:
 
     EDA_ITEM* Clone() const override;
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
 #if defined(DEBUG)
     void Show( int nestLevel, std::ostream& os ) const override;
diff --git a/eeschema/tools/ee_inspection_tool.cpp b/eeschema/tools/ee_inspection_tool.cpp
index a7f3082dc1..87d6b1062e 100644
--- a/eeschema/tools/ee_inspection_tool.cpp
+++ b/eeschema/tools/ee_inspection_tool.cpp
@@ -303,7 +303,7 @@ int EE_INSPECTION_TOOL::UpdateMessagePanel( const TOOL_EVENT& aEvent )
         EDA_ITEM* item = (EDA_ITEM*) selection.Front();
 
         MSG_PANEL_ITEMS msgItems;
-        item->GetMsgPanelInfo( m_frame->GetUserUnits(), msgItems );
+        item->GetMsgPanelInfo( m_frame, msgItems );
         m_frame->SetMsgPanel( msgItems );
     }
     else
diff --git a/eeschema/tools/ee_selection.cpp b/eeschema/tools/ee_selection.cpp
index 84f418afb4..ec5534bae8 100644
--- a/eeschema/tools/ee_selection.cpp
+++ b/eeschema/tools/ee_selection.cpp
@@ -22,28 +22,19 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <limits>
-#include <functional>
 #include <tools/ee_selection.h>
-#include <sch_item.h>
-#include <lib_item.h>
+
 
 EDA_ITEM* EE_SELECTION::GetTopLeftItem( bool onlyModules ) const
 {
     EDA_ITEM* topLeftItem = nullptr;
     wxPoint   topLeftPos;
-    wxPoint   pos;
 
-    // find the leftmost (smallest x coord) and highest (smallest y with the smallest x) item in the selection
-    for( auto item : m_items )
+    // find the leftmost (smallest x coord) and highest (smallest y with the smallest x) item
+    // in the selection
+    for( EDA_ITEM* item : m_items )
     {
-        SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item );
-        LIB_ITEM* lib_item = dynamic_cast<LIB_ITEM*>( item );
-
-        if( sch_item )
-            pos = sch_item->GetPosition();
-        else if( lib_item )
-            pos = lib_item->GetPosition();
+        wxPoint pos = item->GetPosition();
 
         if( ( topLeftItem == nullptr )
             || ( pos.x < topLeftPos.x )
@@ -54,5 +45,5 @@ EDA_ITEM* EE_SELECTION::GetTopLeftItem( bool onlyModules ) const
         }
     }
 
-    return static_cast<EDA_ITEM*>( topLeftItem );
+    return topLeftItem;
 }
diff --git a/eeschema/tools/lib_edit_tool.cpp b/eeschema/tools/lib_edit_tool.cpp
index 3959d600bc..ad9b6fe647 100644
--- a/eeschema/tools/lib_edit_tool.cpp
+++ b/eeschema/tools/lib_edit_tool.cpp
@@ -446,7 +446,7 @@ void LIB_EDIT_TOOL::editGraphicProperties( LIB_ITEM* aItem )
     m_frame->m_DrawSpecificUnit    = !dialog.GetApplyToAllUnits();
 
     MSG_PANEL_ITEMS items;
-    aItem->GetMsgPanelInfo( m_frame->GetUserUnits(), items );
+    aItem->GetMsgPanelInfo( m_frame, items );
     m_frame->SetMsgPanel( items );
 }
 
diff --git a/eeschema/tools/lib_pin_tool.cpp b/eeschema/tools/lib_pin_tool.cpp
index fdc59a836a..6d816a2c7e 100644
--- a/eeschema/tools/lib_pin_tool.cpp
+++ b/eeschema/tools/lib_pin_tool.cpp
@@ -121,7 +121,7 @@ bool LIB_PIN_TOOL::EditPinProperties( LIB_PIN* aPin )
     m_frame->OnModify( );
 
     MSG_PANEL_ITEMS items;
-    aPin->GetMsgPanelInfo( m_frame->GetUserUnits(), items );
+    aPin->GetMsgPanelInfo( m_frame, items );
     m_frame->SetMsgPanel( items );
 
     aPin->EnableEditMode( false );
diff --git a/gerbview/gerber_draw_item.cpp b/gerbview/gerber_draw_item.cpp
index aa952be8cb..f51ce70a11 100644
--- a/gerbview/gerber_draw_item.cpp
+++ b/gerbview/gerber_draw_item.cpp
@@ -658,7 +658,7 @@ void GERBER_DRAW_ITEM::PrintGerberPoly( wxDC* aDC, COLOR4D aColor, const wxPoint
 }
 
 
-void GERBER_DRAW_ITEM::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void GERBER_DRAW_ITEM::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
     wxString msg;
     wxString text;
diff --git a/gerbview/gerber_draw_item.h b/gerbview/gerber_draw_item.h
index 3807fbb0e9..dc33d57b33 100644
--- a/gerbview/gerber_draw_item.h
+++ b/gerbview/gerber_draw_item.h
@@ -194,7 +194,7 @@ public:
      * @return const wxPoint& - The position of this object.
      * This function exists mainly to satisfy the virtual GetPosition() in parent class
      */
-    const wxPoint GetPosition() const          { return m_Start; }
+    const wxPoint GetPosition() const override  { return m_Start; }
     void SetPosition( const wxPoint& aPos )     {  m_Start = aPos; }
 
     /**
@@ -250,7 +250,7 @@ public:
     /* divers */
     int Shape() const { return m_Shape; }
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     wxString ShowGBRShape() const;
 
diff --git a/gerbview/gerbview_draw_panel_gal.cpp b/gerbview/gerbview_draw_panel_gal.cpp
index 052cd2bb1c..e15a318b79 100644
--- a/gerbview/gerbview_draw_panel_gal.cpp
+++ b/gerbview/gerbview_draw_panel_gal.cpp
@@ -87,8 +87,8 @@ void GERBVIEW_DRAW_PANEL_GAL::SetHighContrastLayer( int aLayer )
 }
 
 
-void GERBVIEW_DRAW_PANEL_GAL::GetMsgPanelInfo(
-        EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void GERBVIEW_DRAW_PANEL_GAL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
+                                               std::vector<MSG_PANEL_ITEM>& aList )
 {
 
 }
diff --git a/gerbview/gerbview_draw_panel_gal.h b/gerbview/gerbview_draw_panel_gal.h
index b185fa9e96..f8868d1bd4 100644
--- a/gerbview/gerbview_draw_panel_gal.h
+++ b/gerbview/gerbview_draw_panel_gal.h
@@ -42,7 +42,7 @@ public:
     virtual void SetHighContrastLayer( int aLayer ) override;
 
     ///> @copydoc EDA_DRAW_PANEL_GAL::GetMsgPanelInfo()
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     ///> @copydoc EDA_DRAW_PANEL_GAL::OnShow()
     void OnShow() override;
diff --git a/gerbview/tools/gerbview_control.cpp b/gerbview/tools/gerbview_control.cpp
index 3f74149e37..a1208854cf 100644
--- a/gerbview/tools/gerbview_control.cpp
+++ b/gerbview/tools/gerbview_control.cpp
@@ -173,7 +173,7 @@ int GERBVIEW_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent )
         EDA_ITEM* item = (EDA_ITEM*) selection.Front();
 
         MSG_PANEL_ITEMS msgItems;
-        item->GetMsgPanelInfo( m_frame->GetUserUnits(), msgItems );
+        item->GetMsgPanelInfo( m_frame, msgItems );
         m_frame->SetMsgPanel( msgItems );
     }
     else
diff --git a/gerbview/tools/gerbview_selection.cpp b/gerbview/tools/gerbview_selection.cpp
index e51ec1deff..3e6d1893e5 100644
--- a/gerbview/tools/gerbview_selection.cpp
+++ b/gerbview/tools/gerbview_selection.cpp
@@ -29,7 +29,7 @@ VECTOR2I GERBVIEW_SELECTION::GetCenter() const
 
     if( Size() == 1 )
     {
-        centre = static_cast<GERBER_DRAW_ITEM*>( Front() )->GetPosition();
+        centre = Front()->GetPosition();
     }
     else
     {
diff --git a/include/base_struct.h b/include/base_struct.h
index 001020248c..ed23e08c8f 100644
--- a/include/base_struct.h
+++ b/include/base_struct.h
@@ -296,12 +296,9 @@ public:
      * populates \a aList of #MSG_PANEL_ITEM objects with it's internal state for display
      * purposes.
      *
-     * @note This method replaces DisplayInfo() so that KiCad objects no longer have any
-     *       knowledge of wxWidgets UI objects.
-     *
      * @param aList is the list to populate.
      */
-    virtual void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+    virtual void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
     {
     }
 
@@ -343,6 +340,8 @@ public:
      */
     virtual const EDA_RECT GetBoundingBox() const;
 
+    virtual const wxPoint GetPosition() const { return wxPoint(); }
+
     /**
      * Function Clone
      * creates a duplicate of this item with linked list members set to NULL.
diff --git a/include/class_board_item.h b/include/class_board_item.h
index 5f857b8ca1..5675380230 100644
--- a/include/class_board_item.h
+++ b/include/class_board_item.h
@@ -85,8 +85,6 @@ public:
     // Do not create a copy constructor & operator=.
     // The ones generated by the compiler are adequate.
 
-    virtual const wxPoint GetPosition() const = 0;
-
     /**
      * Function GetCenter()
      *
diff --git a/include/class_draw_panel_gal.h b/include/class_draw_panel_gal.h
index 7dc9e3f5bc..639972c890 100644
--- a/include/class_draw_panel_gal.h
+++ b/include/class_draw_panel_gal.h
@@ -147,7 +147,7 @@ public:
      */
     virtual void SetTopLayer( int aLayer );
 
-    virtual void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+    virtual void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
     {
         wxASSERT( false );
     }
diff --git a/include/eda_draw_frame.h b/include/eda_draw_frame.h
index 8ca9db301b..cbf9fab050 100644
--- a/include/eda_draw_frame.h
+++ b/include/eda_draw_frame.h
@@ -437,6 +437,11 @@ public:
      */
     virtual void UpdateMsgPanel();
 
+    /**
+     * Fetch an item by KIID.  Frame-type-specific implementation.
+     */
+    virtual EDA_ITEM* GetItem( const KIID& aId ) { return nullptr; }
+
     /**
      * Print the page pointed by current screen, set by the calling print function.
      *
diff --git a/include/marker_base.h b/include/marker_base.h
index e7856aa9e3..34361a3c4e 100644
--- a/include/marker_base.h
+++ b/include/marker_base.h
@@ -105,78 +105,6 @@ public:
     void SetMarkerType( enum TYPEMARKER aMarkerType ) { m_markerType = aMarkerType; }
     enum TYPEMARKER GetMarkerType() const { return m_markerType; }
 
-    /**
-     * Function SetData
-     * fills in all the reportable data associated with a MARKER.
-     * @param aErrorCode The categorizing identifier for an error
-     * @param aMarkerPos The position of the MARKER on the BOARD
-     * @param aItem The first of two objects
-     * @param aPos The position of the first of two objects
-     * @param bItem The second of the two conflicting objects
-     * @param bPos The position of the second of two objects
-     */
-    void SetData( EDA_UNITS aUnits, int aErrorCode, const wxPoint& aMarkerPos,
-                  EDA_ITEM* aItem, const wxPoint& aPos,
-                  EDA_ITEM* bItem = nullptr, const wxPoint& bPos = wxPoint() );
-
-    /**
-     * Function SetData
-     * fills in all the reportable data associated with a MARKER.
-     * @param aErrorCode The categorizing identifier for an error
-     * @param aMarkerPos The position of the MARKER on the BOARD
-     * @param aText Text describing the first of two objects
-     * @param aPos The position of the first of two objects
-     * @param bText Text describing the second of the two conflicting objects
-     * @param bPos The position of the second of two objects
-     */
-    void SetData( int aErrorCode, const wxPoint& aMarkerPos,
-                  const wxString& aText, const wxPoint& aPos,
-                  const wxString& bText = wxEmptyString, const wxPoint& bPos = wxPoint() );
-
-    /**
-     * Function SetData
-     * fills in all the reportable data associated with a MARKER.
-     * @param aErrorCode The categorizing identifier for an error
-     * @param aMarkerPos The position of the MARKER on the BOARD
-     * @param aItem The first of two objects
-     * @param aPos The position of the first of two objects
-     * @param bItem The second of the two conflicting objects
-     * @param bPos The position of the second of two objects
-     */
-    void SetData( EDA_UNITS aUnits, int aErrorCode, const wxPoint& aMarkerPos,
-                  EDA_ITEM* aItem,
-                  EDA_ITEM* bItem = nullptr );
-
-    /**
-     * Function SetData
-     * fills in all the reportable data associated with a MARKER.
-     * @param aErrorCode The categorizing identifier for an error
-     * @param aMarkerPos The position of the MARKER on the BOARD
-     * @param aText Text describing the first of two objects
-     * @param aPos The position of the first of two objects
-     * @param bText Text describing the second of the two conflicting objects
-     * @param bPos The position of the second of two objects
-     */
-    void SetData( int aErrorCode, const wxPoint& aMarkerPos,
-                  const wxString& aText,
-                  const wxString& bText = wxEmptyString );
-
-    void SetData( int aErrorCode, const wxPoint& aMarkerPos,
-                  const wxString& aText, const KIID& aID,
-                  const wxString& bText = wxEmptyString, const KIID& bID = niluuid );
-
-    /**
-     * Function SetAuxiliaryData
-     * initialize data for the second (auxiliary) item
-     * @param aAuxiliaryText = the second text (main text) concerning the second schematic or
-     *                         board item
-     * @param aAuxiliaryPos = position the second item
-     */
-    void SetAuxiliaryData( const wxString& aAuxiliaryText, const wxPoint& aAuxiliaryPos )
-    {
-        m_rcItem->SetAuxiliaryData( aAuxiliaryText, aAuxiliaryPos );
-    }
-
     bool IsExcluded() const { return m_excluded; }
     void SetExcluded( bool aExcluded ) { m_excluded = aExcluded; }
 
diff --git a/include/pcb_base_frame.h b/include/pcb_base_frame.h
index 01b00e812c..5465ba9557 100644
--- a/include/pcb_base_frame.h
+++ b/include/pcb_base_frame.h
@@ -214,6 +214,8 @@ public:
         return m_Pcb;
     }
 
+    EDA_ITEM* GetItem( const KIID& aId ) override;
+
     void FocusOnItem( BOARD_ITEM* aItem );
 
     // General
diff --git a/include/ws_draw_item.h b/include/ws_draw_item.h
index 7fb6041b40..2387684c4a 100644
--- a/include/ws_draw_item.h
+++ b/include/ws_draw_item.h
@@ -69,7 +69,6 @@ public:
 
     void ViewGetLayers( int aLayers[], int& aCount ) const override;
 
-    virtual const wxPoint GetPosition() const = 0;
     virtual void SetPosition( wxPoint aPos ) = 0;
     virtual void SetEnd( wxPoint aPos ) { /* not all types will need this */ }
 
@@ -103,7 +102,7 @@ public:
 
     bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList ) override;
 };
 
 
diff --git a/pagelayout_editor/pl_draw_panel_gal.cpp b/pagelayout_editor/pl_draw_panel_gal.cpp
index f5ef791921..c77fb7538f 100644
--- a/pagelayout_editor/pl_draw_panel_gal.cpp
+++ b/pagelayout_editor/pl_draw_panel_gal.cpp
@@ -73,7 +73,8 @@ PL_DRAW_PANEL_GAL::~PL_DRAW_PANEL_GAL()
 }
 
 
-void PL_DRAW_PANEL_GAL::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void PL_DRAW_PANEL_GAL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
+                                         std::vector<MSG_PANEL_ITEM>& aList )
 {
 }
 
diff --git a/pagelayout_editor/pl_draw_panel_gal.h b/pagelayout_editor/pl_draw_panel_gal.h
index f7cae89c3a..2256805392 100644
--- a/pagelayout_editor/pl_draw_panel_gal.h
+++ b/pagelayout_editor/pl_draw_panel_gal.h
@@ -35,7 +35,7 @@ public:
     virtual ~PL_DRAW_PANEL_GAL();
 
     ///> @copydoc EDA_DRAW_PANEL_GAL::GetMsgPanelInfo()
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     /**
      * Build and update the list of WS_DRAW_ITEM_xxx showing the frame layout
diff --git a/pagelayout_editor/tools/pl_edit_tool.cpp b/pagelayout_editor/tools/pl_edit_tool.cpp
index 8dbc130e0a..baa5baa39a 100644
--- a/pagelayout_editor/tools/pl_edit_tool.cpp
+++ b/pagelayout_editor/tools/pl_edit_tool.cpp
@@ -281,8 +281,7 @@ bool PL_EDIT_TOOL::updateModificationPoint( PL_SELECTION& aSelection )
     // When there is only one item selected, the reference point is its position...
     if( aSelection.Size() == 1 )
     {
-        WS_DRAW_ITEM_BASE* item =  static_cast<WS_DRAW_ITEM_BASE*>( aSelection.Front() );
-        aSelection.SetReferencePoint( item->GetPosition() );
+        aSelection.SetReferencePoint( aSelection.Front()->GetPosition() );
     }
     // ...otherwise modify items with regard to the grid-snapped cursor position
     else
@@ -493,9 +492,7 @@ int PL_EDIT_TOOL::Paste( const TOOL_EVENT& aEvent )
 
     if( !selection.Empty() )
     {
-        WS_DRAW_ITEM_BASE* item = (WS_DRAW_ITEM_BASE*) selection.GetTopLeftItem();
-
-        selection.SetReferencePoint( item->GetPosition() );
+        selection.SetReferencePoint( selection.GetTopLeftItem()->GetPosition() );
         m_toolMgr->RunAction( PL_ACTIONS::move, false );
     }
 
diff --git a/pagelayout_editor/tools/pl_editor_control.cpp b/pagelayout_editor/tools/pl_editor_control.cpp
index e9d99bbfa4..9ccfc938a9 100644
--- a/pagelayout_editor/tools/pl_editor_control.cpp
+++ b/pagelayout_editor/tools/pl_editor_control.cpp
@@ -150,7 +150,7 @@ int PL_EDITOR_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent )
         EDA_ITEM* item = (EDA_ITEM*) selection.Front();
 
         MSG_PANEL_ITEMS msgItems;
-        item->GetMsgPanelInfo( m_frame->GetUserUnits(), msgItems );
+        item->GetMsgPanelInfo( m_frame, msgItems );
         m_frame->SetMsgPanel( msgItems );
 
         WS_DATA_ITEM* dataItem = static_cast<WS_DRAW_ITEM_BASE*>( item )->GetPeer();
diff --git a/pagelayout_editor/tools/pl_selection.cpp b/pagelayout_editor/tools/pl_selection.cpp
index 725aea9459..3e6b407234 100644
--- a/pagelayout_editor/tools/pl_selection.cpp
+++ b/pagelayout_editor/tools/pl_selection.cpp
@@ -23,38 +23,36 @@
  */
 
 #include <tools/pl_selection.h>
-#include <ws_draw_item.h>
 
 
 EDA_ITEM* PL_SELECTION::GetTopLeftItem( bool onlyModules ) const
 {
-    WS_DRAW_ITEM_BASE* topLeftItem = nullptr;
-    EDA_RECT           topLeftItemBB;
+    EDA_ITEM* topLeftItem = nullptr;
+    EDA_RECT  topLeftItemBB;
 
     // find the leftmost (smallest x coord) and highest (smallest y with the smallest x) item in the selection
-    for( auto item : m_items )
+    for( EDA_ITEM* item : m_items )
     {
-        WS_DRAW_ITEM_BASE* currentItem = static_cast<WS_DRAW_ITEM_BASE*>( item );
-        EDA_RECT currentItemBB = currentItem->GetBoundingBox();
+        EDA_RECT currentItemBB = item->GetBoundingBox();
 
         if( topLeftItem == nullptr )
         {
-            topLeftItem = currentItem;
+            topLeftItem = item;
             topLeftItemBB = currentItemBB;
         }
         else if( currentItemBB.GetLeft() < topLeftItemBB.GetLeft() )
         {
-            topLeftItem = currentItem;
+            topLeftItem = item;
             topLeftItemBB = currentItemBB;
         }
         else if( topLeftItemBB.GetLeft() == currentItemBB.GetLeft()
                     && currentItemBB.GetTop() < topLeftItemBB.GetTop() )
         {
-            topLeftItem = currentItem;
+            topLeftItem = item;
             topLeftItemBB = currentItemBB;
         }
     }
 
-    return static_cast<EDA_ITEM*>( topLeftItem );
+    return topLeftItem;
 }
 
diff --git a/pcbnew/board_design_settings.cpp b/pcbnew/board_design_settings.cpp
index 257fb90d32..1d557cf717 100644
--- a/pcbnew/board_design_settings.cpp
+++ b/pcbnew/board_design_settings.cpp
@@ -97,6 +97,15 @@ public:
                 bds.m_DRCSeverities[ DRCE_OVERLAPPING_FOOTPRINTS ] = RPT_SEVERITY_IGNORE;
         }
 
+        bds.m_DRCSeverities[ DRCE_SHORT ] = RPT_SEVERITY_ACTION;
+        bds.m_DRCSeverities[ DRCE_REDUNDANT_VIA ] = RPT_SEVERITY_ACTION;
+        bds.m_DRCSeverities[ DRCE_DUPLICATE_TRACK ] = RPT_SEVERITY_ACTION;
+        bds.m_DRCSeverities[ DRCE_MERGE_TRACKS ] = RPT_SEVERITY_ACTION;
+        bds.m_DRCSeverities[ DRCE_DANGLING_TRACK ] = RPT_SEVERITY_ACTION;
+        bds.m_DRCSeverities[ DRCE_DANGLING_VIA ] = RPT_SEVERITY_ACTION;
+        bds.m_DRCSeverities[ DRCE_ZERO_LENGTH_TRACK ] = RPT_SEVERITY_ACTION;
+        bds.m_DRCSeverities[ DRCE_TRACK_IN_PAD ] = RPT_SEVERITY_ACTION;
+
         // TO DO: figure out what we're going to use as keys here so we can read/write these....
 
         aConfig->SetPath( oldPath );
diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp
index 716828ceb8..4794f110ad 100644
--- a/pcbnew/class_board.cpp
+++ b/pcbnew/class_board.cpp
@@ -76,7 +76,6 @@ public:
     }
 
     // pure virtuals:
-    const wxPoint GetPosition() const override { return wxPoint(); }
     void SetPosition( const wxPoint& ) override {}
 
 #if defined(DEBUG)
@@ -761,6 +760,36 @@ BOARD_ITEM* BOARD::GetItem( const KIID& aID )
 }
 
 
+void BOARD::FillItemMap( std::map<KIID, EDA_ITEM*>& aMap )
+{
+    for( TRACK* track : Tracks() )
+        aMap[ track->m_Uuid ] = track;
+
+    for( MODULE* module : Modules() )
+    {
+        aMap[ module->m_Uuid ] = module;
+
+        for( D_PAD* pad : module->Pads() )
+            aMap[ pad->m_Uuid ] = pad;
+
+        aMap[ module->Reference().m_Uuid ] = &module->Reference();
+        aMap[ module->Value().m_Uuid ] = &module->Value();
+
+        for( BOARD_ITEM* drawing : module->GraphicalItems() )
+            aMap[ drawing->m_Uuid ] = drawing;
+    }
+
+    for( ZONE_CONTAINER* zone : Zones() )
+        aMap[ zone->m_Uuid ] = zone;
+
+    for( BOARD_ITEM* drawing : Drawings() )
+        aMap[ drawing->m_Uuid ] = drawing;
+
+    for( MARKER_PCB* marker : m_markers )
+        aMap[ marker->m_Uuid ] = marker;
+}
+
+
 unsigned BOARD::GetNodesCount( int aNet )
 {
     unsigned retval = 0;
@@ -841,7 +870,7 @@ EDA_RECT BOARD::ComputeBoundingBox( bool aBoardEdgesOnly ) const
 }
 
 
-void BOARD::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void BOARD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
     wxString txt;
     int      viasCount = 0;
diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h
index 2950eb4b6b..4309f6d774 100644
--- a/pcbnew/class_board.h
+++ b/pcbnew/class_board.h
@@ -327,6 +327,8 @@ public:
 
     BOARD_ITEM* GetItem( const KIID& aID );
 
+    void FillItemMap( std::map<KIID, EDA_ITEM*>& aMap );
+
     /**
      * Function GetConnectivity()
      * returns list of missing connections between components/tracks.
@@ -782,7 +784,7 @@ public:
         return ComputeBoundingBox( true );
     }
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     /**
      * Function Visit
diff --git a/pcbnew/class_dimension.cpp b/pcbnew/class_dimension.cpp
index 213de29acd..ad235c39a7 100644
--- a/pcbnew/class_dimension.cpp
+++ b/pcbnew/class_dimension.cpp
@@ -357,10 +357,10 @@ void DIMENSION::AdjustDimensionDetails( int aPrecision )
 
 
 // see class_cotation.h
-void DIMENSION::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void DIMENSION::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
     // for now, display only the text within the DIMENSION using class TEXTE_PCB.
-    m_Text.GetMsgPanelInfo( aUnits, aList );
+    m_Text.GetMsgPanelInfo( aFrame, aList );
 }
 
 
diff --git a/pcbnew/class_dimension.h b/pcbnew/class_dimension.h
index 4bb10d7f7d..deac48ae8b 100644
--- a/pcbnew/class_dimension.h
+++ b/pcbnew/class_dimension.h
@@ -220,7 +220,7 @@ public:
      */
     void Mirror( const wxPoint& axis_pos, bool aMirrorLeftRight = false );
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     bool HitTest( const wxPoint& aPosition, int aAccuracy ) const override;
     bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp
index bd8688e67f..857fc09bae 100644
--- a/pcbnew/class_drawsegment.cpp
+++ b/pcbnew/class_drawsegment.cpp
@@ -342,9 +342,10 @@ MODULE* DRAWSEGMENT::GetParentModule() const
 }
 
 
-void DRAWSEGMENT::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void DRAWSEGMENT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
-    wxString msg;
+    EDA_UNITS units = aFrame->GetUserUnits();
+    wxString  msg;
 
     msg = _( "Drawing" );
 
@@ -357,7 +358,7 @@ void DRAWSEGMENT::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>
     case S_CIRCLE:
         aList.emplace_back( shape, _( "Circle" ), RED );
 
-        msg = MessageTextFromValue( aUnits, GetLineLength( m_Start, m_End ) );
+        msg = MessageTextFromValue( units, GetLineLength( m_Start, m_End ) );
         aList.emplace_back( _( "Radius" ), msg, RED );
         break;
 
@@ -366,14 +367,14 @@ void DRAWSEGMENT::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>
         msg.Printf( wxT( "%.1f" ), m_Angle / 10.0 );
         aList.emplace_back( _( "Angle" ), msg, RED );
 
-        msg = MessageTextFromValue( aUnits, GetLineLength( m_Start, m_End ) );
+        msg = MessageTextFromValue( units, GetLineLength( m_Start, m_End ) );
         aList.emplace_back( _( "Radius" ), msg, RED );
         break;
 
     case S_CURVE:
         aList.emplace_back( shape, _( "Curve" ), RED );
 
-        msg = MessageTextFromValue( aUnits, GetLength() );
+        msg = MessageTextFromValue( units, GetLength() );
         aList.emplace_back( _( "Length" ), msg, DARKGREEN );
         break;
 
@@ -388,7 +389,7 @@ void DRAWSEGMENT::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>
     {
         aList.emplace_back( shape, _( "Segment" ), RED );
 
-        msg = MessageTextFromValue( aUnits, GetLineLength( m_Start, m_End ) );
+        msg = MessageTextFromValue( units, GetLineLength( m_Start, m_End ) );
         aList.emplace_back( _( "Length" ), msg, DARKGREEN );
 
         // angle counter-clockwise from 3'o-clock
@@ -403,26 +404,26 @@ void DRAWSEGMENT::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>
     {
         VECTOR2I point0 = GetPolyShape().Outline(0).CPoint(0);
         wxString origin = wxString::Format( "@(%s, %s)",
-                                           MessageTextFromValue( aUnits, point0.x ),
-                                           MessageTextFromValue( aUnits, point0.y ) );
+                                           MessageTextFromValue( units, point0.x ),
+                                           MessageTextFromValue( units, point0.y ) );
 
         aList.emplace_back( _( "Origin" ), origin, DARKGREEN );
     }
     else
     {
         wxString start = wxString::Format( "@(%s, %s)",
-                                           MessageTextFromValue( aUnits, GetStart().x ),
-                                           MessageTextFromValue( aUnits, GetStart().y ) );
+                                           MessageTextFromValue( units, GetStart().x ),
+                                           MessageTextFromValue( units, GetStart().y ) );
         wxString end   = wxString::Format( "@(%s, %s)",
-                                           MessageTextFromValue( aUnits, GetEnd().x ),
-                                           MessageTextFromValue( aUnits, GetEnd().y ) );
+                                           MessageTextFromValue( units, GetEnd().x ),
+                                           MessageTextFromValue( units, GetEnd().y ) );
 
         aList.emplace_back( start, end, DARKGREEN );
     }
 
     aList.emplace_back( _( "Layer" ), GetLayerName(), DARKBROWN );
 
-    msg = MessageTextFromValue( aUnits, m_Width, true );
+    msg = MessageTextFromValue( units, m_Width, true );
     aList.emplace_back( _( "Width" ), msg, DARKCYAN );
 }
 
diff --git a/pcbnew/class_drawsegment.h b/pcbnew/class_drawsegment.h
index fce2767549..5921d59412 100644
--- a/pcbnew/class_drawsegment.h
+++ b/pcbnew/class_drawsegment.h
@@ -215,7 +215,7 @@ public:
 
     void SetPolyPoints( const std::vector<wxPoint>& aPoints );
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     const EDA_RECT GetBoundingBox() const override;
 
diff --git a/pcbnew/class_edge_mod.cpp b/pcbnew/class_edge_mod.cpp
index 592a8d66c5..58cb9aeb67 100644
--- a/pcbnew/class_edge_mod.cpp
+++ b/pcbnew/class_edge_mod.cpp
@@ -122,7 +122,7 @@ void EDGE_MODULE::SetDrawCoord()
 
 
 // see class_edge_mod.h
-void EDGE_MODULE::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void EDGE_MODULE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
     wxString msg;
 
@@ -139,7 +139,7 @@ void EDGE_MODULE::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>
     aList.emplace_back( _( "Footprint" ), module->GetReference(), DARKCYAN );
 
     // append the features shared with the base class
-    DRAWSEGMENT::GetMsgPanelInfo( aUnits, aList );
+    DRAWSEGMENT::GetMsgPanelInfo( aFrame, aList );
 }
 
 
diff --git a/pcbnew/class_edge_mod.h b/pcbnew/class_edge_mod.h
index d88b50b056..6d6514372e 100644
--- a/pcbnew/class_edge_mod.h
+++ b/pcbnew/class_edge_mod.h
@@ -114,7 +114,7 @@ public:
      */
     void SetDrawCoord();
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     wxString GetClass() const override
     {
diff --git a/pcbnew/class_marker_pcb.cpp b/pcbnew/class_marker_pcb.cpp
index e48c474fd8..520c373dd2 100644
--- a/pcbnew/class_marker_pcb.cpp
+++ b/pcbnew/class_marker_pcb.cpp
@@ -43,55 +43,13 @@
 /// Factor to convert the maker unit shape to internal units:
 #define SCALING_FACTOR  Millimeter2iu( 0.1 )
 
-MARKER_PCB::MARKER_PCB( BOARD_ITEM* aParent ) :
-        BOARD_ITEM( aParent, PCB_MARKER_T ),
-        MARKER_BASE( SCALING_FACTOR, new DRC_ITEM() ),
-        m_item( nullptr )
-{
-}
 
-
-MARKER_PCB::MARKER_PCB( EDA_UNITS aUnits, int aErrorCode, const wxPoint& aMarkerPos,
-                        BOARD_ITEM* aItem,
-                        BOARD_ITEM* bItem ) :
-        BOARD_ITEM( nullptr, PCB_MARKER_T ), // parent set during BOARD::Add()
-        MARKER_BASE( SCALING_FACTOR, new DRC_ITEM() ),
-        m_item( nullptr )
-{
-    SetData( aUnits, aErrorCode, aMarkerPos, aItem, bItem );
-}
-
-
-MARKER_PCB::MARKER_PCB( EDA_UNITS aUnits, int aErrorCode, const wxPoint& aMarkerPos,
-                        BOARD_ITEM* aItem, const wxPoint& aPos,
-                        BOARD_ITEM* bItem, const wxPoint& bPos ) :
-        BOARD_ITEM( nullptr, PCB_MARKER_T ), // parent set during BOARD::Add()
-        MARKER_BASE( SCALING_FACTOR, new DRC_ITEM() ),
-        m_item( nullptr )
-{
-    SetData( aUnits, aErrorCode, aMarkerPos, aItem, aPos, bItem, bPos );
-}
-
-
-MARKER_PCB::MARKER_PCB( int aErrorCode, const wxPoint& aMarkerPos,
-                        const wxString& aText, const wxPoint& aPos,
-                        const wxString& bText, const wxPoint& bPos ) :
+MARKER_PCB::MARKER_PCB( DRC_ITEM* aItem, const wxPoint& aPosition ) :
         BOARD_ITEM( nullptr, PCB_MARKER_T ),  // parent set during BOARD::Add()
-        MARKER_BASE( SCALING_FACTOR, new DRC_ITEM() ),
-        m_item( nullptr )
+        MARKER_BASE( SCALING_FACTOR, aItem )
 {
-    SetData( aErrorCode, aMarkerPos, aText, aPos, bText, bPos );
-}
-
-
-MARKER_PCB::MARKER_PCB( int aErrorCode,
-                        const wxString& aText,
-                        const wxString& bText) :
-        BOARD_ITEM( nullptr, PCB_MARKER_T ),  // parent set during BOARD::Add()
-        MARKER_BASE( SCALING_FACTOR, new DRC_ITEM() ),
-        m_item( nullptr )
-{
-    SetData( aErrorCode, wxDefaultPosition, aText, bText );
+    if( m_rcItem )
+        m_rcItem->SetParent( this );
 }
 
 
@@ -103,13 +61,11 @@ MARKER_PCB::~MARKER_PCB()
 
 wxString MARKER_PCB::Serialize() const
 {
-    return wxString::Format( wxT( "%d|%d|%d|%s|%s|%s|%s" ),
+    return wxString::Format( wxT( "%d|%d|%d|%s|%s" ),
                              m_rcItem->GetErrorCode(),
                              m_Pos.x,
                              m_Pos.y,
-                             m_rcItem->GetMainText(),
                              m_rcItem->GetMainItemID().AsString(),
-                             m_rcItem->GetAuxText(),
                              m_rcItem->GetAuxItemID().AsString() );
 }
 
@@ -118,13 +74,13 @@ MARKER_PCB* MARKER_PCB::Deserialize( const wxString& data )
 {
     wxArrayString props = wxSplit( data, '|' );
     int           errorCode = (int) strtol( props[0].c_str(), nullptr, 10 );
-    MARKER_PCB*   marker = new MARKER_PCB( nullptr );   // parent set during BOARD::Add()
+    wxPoint       markerPos( (int) strtol( props[1].c_str(), nullptr, 10 ),
+                             (int) strtol( props[2].c_str(), nullptr, 10 ) );
 
-    marker->m_Pos.x = (int) strtol( props[1].c_str(), nullptr, 10 );
-    marker->m_Pos.y = (int) strtol( props[2].c_str(), nullptr, 10 );
-    marker->m_rcItem->SetData( errorCode, props[3], KIID( props[4] ), props[5], KIID( props[6] ) );
-    marker->m_rcItem->SetParent( marker );
-    return marker;
+    DRC_ITEM* drcItem = new DRC_ITEM( errorCode );
+    drcItem->SetItems( KIID( props[3] ), KIID( props[4] ) );
+
+    return new MARKER_PCB( drcItem, markerPos );
 }
 
 
@@ -141,11 +97,29 @@ bool MARKER_PCB::IsOnLayer( PCB_LAYER_ID aLayer ) const
 }
 
 
-void MARKER_PCB::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void MARKER_PCB::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
     aList.emplace_back( _( "Type" ), _( "Marker" ), DARKCYAN );
     aList.emplace_back( _( "Violation" ), m_rcItem->GetErrorText(), RED );
-    aList.emplace_back( m_rcItem->GetMainText(), m_rcItem->GetAuxText(), DARKBROWN );
+
+    wxString  mainText;
+    wxString  auxText;
+    EDA_ITEM* mainItem = nullptr;
+    EDA_ITEM* auxItem = nullptr;
+
+    if( m_rcItem->GetMainItemID() != niluuid )
+        mainItem = aFrame->GetItem( m_rcItem->GetMainItemID() );
+
+    if( m_rcItem->GetAuxItemID() != niluuid )
+        auxItem = aFrame->GetItem( m_rcItem->GetAuxItemID() );
+
+    if( mainItem )
+        mainText = mainItem->GetSelectMenuText( aFrame->GetUserUnits() );
+
+    if( auxItem )
+        auxText = auxItem->GetSelectMenuText( aFrame->GetUserUnits() );
+
+    aList.emplace_back( mainText, auxText, DARKBROWN );
 }
 
 
diff --git a/pcbnew/class_marker_pcb.h b/pcbnew/class_marker_pcb.h
index 2ba4045c8c..92062a44fb 100644
--- a/pcbnew/class_marker_pcb.h
+++ b/pcbnew/class_marker_pcb.h
@@ -33,6 +33,7 @@
 
 #include <class_board_item.h>
 #include <marker_base.h>
+#include <drc/drc_item.h>
 
 // Coordinates count for the basic shape marker
 #define MARKER_SHAPE_POINT_COUNT 9
@@ -43,56 +44,7 @@ class MSG_PANEL_ITEM;
 class MARKER_PCB : public BOARD_ITEM, public MARKER_BASE
 {
 public:
-
-    MARKER_PCB( BOARD_ITEM* aParent );
-
-    /**
-     * Constructor
-     * @param aErrorCode The categorizing identifier for an error
-     * @param aMarkerPos The position of the MARKER_PCB on the BOARD
-     * @param aItem The first of two objects
-     * @param bItem The second of the two conflicting objects
-     */
-    MARKER_PCB( EDA_UNITS aUnits, int aErrorCode, const wxPoint& aMarkerPos,
-                BOARD_ITEM* aItem,
-                BOARD_ITEM* bItem = nullptr );
-
-    /**
-     * Constructor
-     * @param aErrorCode The categorizing identifier for an error
-     * @param aMarkerPos The position of the MARKER_PCB on the BOARD
-     * @param aItem The first of two objects
-     * @param aPos The position of the first of two objects
-     * @param bItem The second of the two conflicting objects
-     * @param bPos The position of the second of two objects
-     */
-    MARKER_PCB( EDA_UNITS aUnits, int aErrorCode, const wxPoint& aMarkerPos,
-                BOARD_ITEM* aItem, const wxPoint& aPos,
-                BOARD_ITEM* bItem = nullptr, const wxPoint& bPos = wxPoint() );
-
-    /**
-     * Constructor
-     * @param aErrorCode The categorizing identifier for an error
-     * @param aMarkerPos The position of the MARKER_PCB on the BOARD
-     * @param aText Text describing the first of two objects
-     * @param aPos The position of the first of two objects
-     * @param bText Text describing the second of the two conflicting objects
-     * @param bPos The position of the second of two objects
-     */
-    MARKER_PCB( int aErrorCode, const wxPoint& aMarkerPos,
-                const wxString& aText, const wxPoint& aPos,
-                const wxString& bText = wxEmptyString, const wxPoint& bPos = wxPoint() );
-
-    /**
-     * Constructor
-     * @param aErrorCode The categorizing identifier for an error
-     * @param aMarkerPos The position of the MARKER_PCB on the BOARD
-     * @param aText Text describing the first of two objects
-     * @param bText Text describing the second of the two conflicting objects
-     */
-    MARKER_PCB( int aErrorCode,
-                const wxString& aText,
-                const wxString& bText = wxEmptyString );
+    MARKER_PCB( DRC_ITEM* aItem, const wxPoint& aPosition );
 
     ~MARKER_PCB();
 
@@ -128,7 +80,7 @@ public:
 
     GAL_LAYER_ID GetColorLayer() const;
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     bool Matches( wxFindReplaceData& aSearchData, void* aAuxData ) override
     {
@@ -159,10 +111,6 @@ public:
 
 protected:
     KIGFX::COLOR4D getColor() const override;
-
-protected:
-    ///> Pointer to BOARD_ITEM that causes DRC error.
-    const BOARD_ITEM* m_item;
 };
 
 #endif      //  CLASS_MARKER_PCB_H
diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp
index d64f49af1f..a91efa92dc 100644
--- a/pcbnew/class_module.cpp
+++ b/pcbnew/class_module.cpp
@@ -545,7 +545,7 @@ SHAPE_POLY_SET MODULE::GetBoundingPoly() const
 }
 
 
-void MODULE::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void MODULE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
     wxString msg;
 
diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h
index cdc5c7b14b..191f1d9ea9 100644
--- a/pcbnew/class_module.h
+++ b/pcbnew/class_module.h
@@ -411,7 +411,7 @@ public:
     bool ResolveTextVar( wxString* token, int aDepth = 0 ) const;
 
     ///> @copydoc EDA_ITEM::GetMsgPanelInfo
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
 
diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp
index 91a65b90d4..68fd0bcf97 100644
--- a/pcbnew/class_pad.cpp
+++ b/pcbnew/class_pad.cpp
@@ -35,7 +35,7 @@
 #include <base_units.h>
 #include <bitmaps.h>
 #include <math/util.h>      // for KiROUND
-
+#include <eda_draw_frame.h>
 #include <geometry/geometry_utils.h>
 #include <pcbnew.h>
 #include <view/view.h>
@@ -940,7 +940,7 @@ void D_PAD::BuildPadPolygon( wxPoint aCoord[4], wxSize aInflateValue,
 }
 
 
-void D_PAD::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void D_PAD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
     MODULE*     module;
     wxString    msg;
@@ -984,13 +984,13 @@ void D_PAD::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aLis
 
     aList.emplace_back( ShowPadShape(), props, DARKGREEN );
 
-    msg = MessageTextFromValue( aUnits, m_Size.x, true );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), m_Size.x, true );
     aList.emplace_back( _( "Width" ), msg, RED );
 
-    msg = MessageTextFromValue( aUnits, m_Size.y, true );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), m_Size.y, true );
     aList.emplace_back( _( "Height" ), msg, RED );
 
-    msg = MessageTextFromValue( aUnits, m_Drill.x, true );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), m_Drill.x, true );
 
     if( GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
     {
@@ -998,9 +998,9 @@ void D_PAD::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aLis
     }
     else
     {
-        msg = MessageTextFromValue( aUnits, m_Drill.x, true )
+        msg = MessageTextFromValue( aFrame->GetUserUnits(), m_Drill.x, true )
                + wxT( "/" )
-               + MessageTextFromValue( aUnits, m_Drill.y, true );
+               + MessageTextFromValue( aFrame->GetUserUnits(), m_Drill.y, true );
         aList.emplace_back( _( "Drill X / Y" ), msg, RED );
     }
 
@@ -1015,14 +1015,14 @@ void D_PAD::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aLis
 
     aList.emplace_back( _( "Angle" ), msg, LIGHTBLUE );
 
-    msg = MessageTextFromValue( aUnits, m_Pos.x )
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), m_Pos.x )
            + wxT( ", " )
-           + MessageTextFromValue( aUnits, m_Pos.y );
+           + MessageTextFromValue( aFrame->GetUserUnits(), m_Pos.y );
     aList.emplace_back( _( "Position" ), msg, LIGHTBLUE );
 
     if( GetPadToDieLength() )
     {
-        msg = MessageTextFromValue( aUnits, GetPadToDieLength(), true );
+        msg = MessageTextFromValue( aFrame->GetUserUnits(), GetPadToDieLength(), true );
         aList.emplace_back( _( "Length in package" ), msg, CYAN );
     }
 }
diff --git a/pcbnew/class_pad.h b/pcbnew/class_pad.h
index 7e09698dfd..c873ee719b 100644
--- a/pcbnew/class_pad.h
+++ b/pcbnew/class_pad.h
@@ -705,7 +705,7 @@ public:
     int GetSubRatsnest() const                  { return m_SubRatsnest; }
     void SetSubRatsnest( int aSubRatsnest )     { m_SubRatsnest = aSubRatsnest; }
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     bool IsOnLayer( PCB_LAYER_ID aLayer ) const override
     {
diff --git a/pcbnew/class_pcb_text.cpp b/pcbnew/class_pcb_text.cpp
index 9b92498ecc..819776efc8 100644
--- a/pcbnew/class_pcb_text.cpp
+++ b/pcbnew/class_pcb_text.cpp
@@ -111,7 +111,7 @@ void TEXTE_PCB::SetTextAngle( double aAngle )
 }
 
 
-void TEXTE_PCB::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void TEXTE_PCB::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
     wxString    msg;
 
@@ -132,13 +132,13 @@ void TEXTE_PCB::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>&
     msg.Printf( wxT( "%.1f" ), GetTextAngle() / 10.0 );
     aList.emplace_back( _( "Angle" ), msg, DARKGREEN );
 
-    msg = MessageTextFromValue( aUnits, GetTextThickness() );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), GetTextThickness() );
     aList.emplace_back( _( "Thickness" ), msg, MAGENTA );
 
-    msg = MessageTextFromValue( aUnits, GetTextWidth() );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), GetTextWidth() );
     aList.emplace_back( _( "Width" ), msg, RED );
 
-    msg = MessageTextFromValue( aUnits, GetTextHeight() );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), GetTextHeight() );
     aList.emplace_back( _( "Height" ), msg, RED );
 }
 
diff --git a/pcbnew/class_pcb_text.h b/pcbnew/class_pcb_text.h
index 44ac48d3a7..6146e3d80d 100644
--- a/pcbnew/class_pcb_text.h
+++ b/pcbnew/class_pcb_text.h
@@ -81,7 +81,7 @@ public:
 
     void Flip( const wxPoint& aCentre, bool aFlipLeftRight ) override;
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     bool HitTest( const wxPoint& aPosition, int aAccuracy ) const override
     {
diff --git a/pcbnew/class_text_mod.cpp b/pcbnew/class_text_mod.cpp
index f77d9710d6..0141de1542 100644
--- a/pcbnew/class_text_mod.cpp
+++ b/pcbnew/class_text_mod.cpp
@@ -288,7 +288,7 @@ double TEXTE_MODULE::GetDrawRotation() const
 
 
 // see class_text_mod.h
-void TEXTE_MODULE::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void TEXTE_MODULE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
     MODULE* module = (MODULE*) m_Parent;
 
@@ -331,13 +331,13 @@ void TEXTE_MODULE::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM
     msg.Printf( wxT( "%.1f" ), GetTextAngleDegrees() );
     aList.emplace_back( _( "Angle" ), msg, DARKGREEN );
 
-    msg = MessageTextFromValue( aUnits, GetTextThickness(), true );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), GetTextThickness(), true );
     aList.emplace_back( _( "Thickness" ), msg, DARKGREEN );
 
-    msg = MessageTextFromValue( aUnits, GetTextWidth(), true );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), GetTextWidth(), true );
     aList.emplace_back( _( "Width" ), msg, RED );
 
-    msg = MessageTextFromValue( aUnits, GetTextHeight(), true );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), GetTextHeight(), true );
     aList.emplace_back( _( "Height" ), msg, RED );
 }
 
diff --git a/pcbnew/class_text_mod.h b/pcbnew/class_text_mod.h
index 4c7312d402..af30c68ad5 100644
--- a/pcbnew/class_text_mod.h
+++ b/pcbnew/class_text_mod.h
@@ -179,7 +179,7 @@ public:
     ///> Set relative coordinates.
     void SetLocalCoord();
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     bool TextHitTest( const wxPoint& aPoint, int aAccuracy = 0 ) const override;
     bool TextHitTest( const EDA_RECT& aRect, bool aContains, int aAccuracy = 0 ) const override;
diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp
index 93a11b597c..1be6481a93 100644
--- a/pcbnew/class_track.cpp
+++ b/pcbnew/class_track.cpp
@@ -507,13 +507,13 @@ unsigned int VIA::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
 
 
 // see class_track.h
-void TRACK::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void TRACK::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
     wxString msg;
     BOARD*   board = GetBoard();
 
     // Display basic infos
-    GetMsgPanelInfoBase( aUnits, aList );
+    GetMsgPanelInfoBase( aFrame, aList );
 
     // Display full track length (in Pcbnew)
     if( board )
@@ -524,15 +524,15 @@ void TRACK::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aLis
 
         std::tie( count, trackLen, lenPadToDie ) = board->GetTrackLength( *this );
 
-        msg = MessageTextFromValue( aUnits, trackLen );
+        msg = MessageTextFromValue( aFrame->GetUserUnits(), trackLen );
         aList.emplace_back( _( "Length" ), msg, DARKCYAN );
 
         if( lenPadToDie != 0 )
         {
-            msg = MessageTextFromValue( aUnits, trackLen + lenPadToDie );
+            msg = MessageTextFromValue( aFrame->GetUserUnits(), trackLen + lenPadToDie );
             aList.emplace_back( _( "Full Length" ), msg, DARKCYAN );
 
-            msg = MessageTextFromValue( aUnits, lenPadToDie, true );
+            msg = MessageTextFromValue( aFrame->GetUserUnits(), lenPadToDie, true );
             aList.emplace_back( _( "Pad To Die Length" ), msg, DARKCYAN );
         }
     }
@@ -543,21 +543,21 @@ void TRACK::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aLis
     {
         aList.emplace_back( _( "NC Name" ), netclass->GetName(), DARKMAGENTA );
 
-        msg = MessageTextFromValue( aUnits, netclass->GetClearance(), true );
+        msg = MessageTextFromValue( aFrame->GetUserUnits(), netclass->GetClearance(), true );
         aList.emplace_back( _( "NC Clearance" ), msg, DARKMAGENTA );
 
-        msg = MessageTextFromValue( aUnits, netclass->GetTrackWidth(), true );
+        msg = MessageTextFromValue( aFrame->GetUserUnits(), netclass->GetTrackWidth(), true );
         aList.emplace_back( _( "NC Width" ), msg, DARKMAGENTA );
 
-        msg = MessageTextFromValue( aUnits, netclass->GetViaDiameter(), true );
+        msg = MessageTextFromValue( aFrame->GetUserUnits(), netclass->GetViaDiameter(), true );
         aList.emplace_back( _( "NC Via Size" ), msg, DARKMAGENTA );
 
-        msg = MessageTextFromValue( aUnits, netclass->GetViaDrill(), true );
+        msg = MessageTextFromValue( aFrame->GetUserUnits(), netclass->GetViaDrill(), true );
         aList.emplace_back( _( "NC Via Drill"), msg, DARKMAGENTA );
     }
 }
 
-void TRACK::GetMsgPanelInfoBase_Common( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void TRACK::GetMsgPanelInfoBase_Common( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
     wxString msg;
 
@@ -618,14 +618,14 @@ void TRACK::GetMsgPanelInfoBase_Common( EDA_UNITS aUnits, std::vector<MSG_PANEL_
 }
 
 
-void TRACK::GetMsgPanelInfoBase( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void TRACK::GetMsgPanelInfoBase( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
     wxString msg;
     BOARD* board = GetBoard();
 
     aList.emplace_back( _( "Type" ), _( "Track" ), DARKCYAN );
 
-    GetMsgPanelInfoBase_Common( aUnits, aList );
+    GetMsgPanelInfoBase_Common( aFrame, aList );
 
     // Display layer
     if( board )
@@ -636,17 +636,17 @@ void TRACK::GetMsgPanelInfoBase( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>&
     aList.emplace_back( _( "Layer" ), msg, BROWN );
 
     // Display width
-    msg = MessageTextFromValue( aUnits, m_Width, true );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), m_Width, true );
 
     aList.emplace_back( _( "Width" ), msg, DARKCYAN );
 
     // Display segment length
-    msg = ::MessageTextFromValue( aUnits, GetLength() );
+    msg = ::MessageTextFromValue( aFrame->GetUserUnits(), GetLength() );
     aList.emplace_back( _( "Segment Length" ), msg, DARKCYAN );
 }
 
 
-void VIA::GetMsgPanelInfoBase( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void VIA::GetMsgPanelInfoBase( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
     wxString msg;
     BOARD*   board = GetBoard();
@@ -675,7 +675,7 @@ void VIA::GetMsgPanelInfoBase( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aL
 
     aList.emplace_back( _( "Type" ), msg, DARKCYAN );
 
-    GetMsgPanelInfoBase_Common( aUnits, aList );
+    GetMsgPanelInfoBase_Common( aFrame, aList );
 
 
     // Display layer pair
@@ -692,13 +692,13 @@ void VIA::GetMsgPanelInfoBase( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aL
     aList.emplace_back( _( "Layers" ), msg, BROWN );
 
     // Display width
-    msg = MessageTextFromValue( aUnits, m_Width, true );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), m_Width, true );
 
     // Display diameter value:
     aList.emplace_back( _( "Diameter" ), msg, DARKCYAN );
 
     // Display drill value
-    msg = MessageTextFromValue( aUnits, GetDrillValue() );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), GetDrillValue() );
 
     wxString title = _( "Drill" );
     title += wxT( " " );
diff --git a/pcbnew/class_track.h b/pcbnew/class_track.h
index 62da08bc71..c27822fd41 100644
--- a/pcbnew/class_track.h
+++ b/pcbnew/class_track.h
@@ -174,7 +174,7 @@ public:
         return ( Type() == PCB_VIA_T ) || ( m_Start == m_End );
     }
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     SEARCH_RESULT Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] ) override;
 
@@ -244,10 +244,10 @@ protected:
      * Display info about the track segment only, and does not calculate the full track length
      * @param aList A list of #MSG_PANEL_ITEM objects to add status information.
      */
-    virtual void GetMsgPanelInfoBase( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList );
+    virtual void GetMsgPanelInfoBase( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList );
 
 
-    void GetMsgPanelInfoBase_Common( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList );
+    void GetMsgPanelInfoBase_Common( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList );
 
 
     int         m_Width;            ///< Thickness of track, or via diameter
@@ -456,7 +456,7 @@ public:
     virtual void SwapData( BOARD_ITEM* aImage ) override;
 
 protected:
-    void GetMsgPanelInfoBase( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfoBase( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
 private:
     /// The bottom layer of the via (the top layer is in m_Layer)
diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp
index 699ee89085..458ddfa5c4 100644
--- a/pcbnew/class_zone.cpp
+++ b/pcbnew/class_zone.cpp
@@ -510,7 +510,7 @@ bool ZONE_CONTAINER::HitTestCutout( const VECTOR2I& aRefPos, int* aOutlineIdx, i
 }
 
 
-void ZONE_CONTAINER::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void ZONE_CONTAINER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
     wxString msg;
 
@@ -585,7 +585,7 @@ void ZONE_CONTAINER::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_IT
 
     aList.emplace_back( MSG_PANEL_ITEM( _( "Fill Mode" ), msg, BROWN ) );
 
-    msg = MessageTextFromValue( aUnits, m_area, false, EDA_DATA_TYPE::AREA );
+    msg = MessageTextFromValue( aFrame->GetUserUnits(), m_area, false, EDA_DATA_TYPE::AREA );
     aList.emplace_back( MSG_PANEL_ITEM( _( "Filled Area" ), msg, BLUE ) );
 
     // Useful for statistics :
diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h
index 54325cbd43..4801cf1eb5 100644
--- a/pcbnew/class_zone.h
+++ b/pcbnew/class_zone.h
@@ -99,7 +99,7 @@ public:
      */
     unsigned GetPriority() const { return m_priority; }
 
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     void SetLayerSet( LSET aLayerSet );
 
diff --git a/pcbnew/cross-probing.cpp b/pcbnew/cross-probing.cpp
index 1b8350c0cc..6c5e39e893 100644
--- a/pcbnew/cross-probing.cpp
+++ b/pcbnew/cross-probing.cpp
@@ -95,7 +95,7 @@ void PCB_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
             netcode = netinfo->GetNet();
 
             MSG_PANEL_ITEMS items;
-            netinfo->GetMsgPanelInfo( GetUserUnits(), items );
+            netinfo->GetMsgPanelInfo( this, items );
             SetMsgPanel( items );
         }
     }
diff --git a/pcbnew/dialogs/dialog_board_setup.cpp b/pcbnew/dialogs/dialog_board_setup.cpp
index ca25778e9f..ba90f3f65b 100644
--- a/pcbnew/dialogs/dialog_board_setup.cpp
+++ b/pcbnew/dialogs/dialog_board_setup.cpp
@@ -46,7 +46,7 @@ DIALOG_BOARD_SETUP::DIALOG_BOARD_SETUP( PCB_EDIT_FRAME* aFrame ) :
     m_maskAndPaste = new PANEL_SETUP_MASK_AND_PASTE( this, aFrame );
     m_physicalStackup = new PANEL_SETUP_BOARD_STACKUP( this, aFrame, m_layers );
 
-    DRC_ITEM               dummyItem;
+    DRC_ITEM               dummyItem( 0 );
     BOARD_DESIGN_SETTINGS& bds = aFrame->GetDesignSettings();
     m_severities = new PANEL_SETUP_SEVERITIES( this, dummyItem, bds.m_DRCSeverities,
                                                DRCE_FIRST, DRCE_LAST );
diff --git a/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp b/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp
index 9f3eea0386..87656b1e44 100644
--- a/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp
+++ b/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp
@@ -32,6 +32,7 @@
 #include <tools/pcb_actions.h>
 #include <tracks_cleaner.h>
 #include <drc/drc_item.h>
+#include <drc/drc_provider.h>
 
 DIALOG_CLEANUP_TRACKS_AND_VIAS::DIALOG_CLEANUP_TRACKS_AND_VIAS( PCB_EDIT_FRAME* aParentFrame ):
         DIALOG_CLEANUP_TRACKS_AND_VIAS_BASE( aParentFrame ),
@@ -48,6 +49,8 @@ DIALOG_CLEANUP_TRACKS_AND_VIAS::DIALOG_CLEANUP_TRACKS_AND_VIAS( PCB_EDIT_FRAME*
     m_changesTreeModel = new RC_TREE_MODEL( m_parentFrame, m_changesDataView );
     m_changesDataView->AssociateModel( m_changesTreeModel );
 
+    m_changesTreeModel->SetSeverities( RPT_SEVERITY_ACTION );
+
     // We use a sdbSizer to get platform-dependent ordering of the action buttons, but
     // that requires us to correct the button labels here.
     m_sdbSizerOK->SetLabel( _( "Update PCB" ) );
@@ -99,11 +102,6 @@ bool DIALOG_CLEANUP_TRACKS_AND_VIAS::TransferDataFromWindow()
 
 void DIALOG_CLEANUP_TRACKS_AND_VIAS::doCleanup( bool aDryRun )
 {
-    for( DRC_ITEM* item : m_items )
-        delete item;
-
-    m_items.clear();
-
     wxBusyCursor busy;
     BOARD_COMMIT commit( m_parentFrame );
     TRACKS_CLEANER cleaner( m_parentFrame->GetUserUnits(), m_parentFrame->GetBoard(), commit );
@@ -112,14 +110,25 @@ void DIALOG_CLEANUP_TRACKS_AND_VIAS::doCleanup( bool aDryRun )
     {
         // Clear current selection list to avoid selection of deleted items
         m_parentFrame->GetToolManager()->RunAction( PCB_ACTIONS::selectionClear, true );
+
+        // ... and to keep the treeModel from trying to refresh a deleted item
+        m_changesTreeModel->SetProvider( nullptr );
     }
 
+    for( DRC_ITEM* item : m_items )
+        delete item;
+
+    m_items.clear();
+
     // Old model has to be refreshed, GAL normally does not keep updating it
     m_parentFrame->Compile_Ratsnest( false );
 
-    bool modified = cleaner.CleanupBoard( aDryRun, &m_items, m_cleanShortCircuitOpt->GetValue(),
-            m_cleanViasOpt->GetValue(), m_mergeSegmOpt->GetValue(),
-            m_deleteUnconnectedOpt->GetValue(), m_deleteTracksInPadsOpt->GetValue() );
+    bool modified = cleaner.CleanupBoard( aDryRun, &m_items,
+                                          m_cleanShortCircuitOpt->GetValue(),
+                                          m_cleanViasOpt->GetValue(),
+                                          m_mergeSegmOpt->GetValue(),
+                                          m_deleteUnconnectedOpt->GetValue(),
+                                          m_deleteTracksInPadsOpt->GetValue() );
 
     if( aDryRun )
     {
diff --git a/pcbnew/dialogs/dialog_cleanup_tracks_and_vias_base.cpp b/pcbnew/dialogs/dialog_cleanup_tracks_and_vias_base.cpp
index a9bf42afd5..9e6b2b0e49 100644
--- a/pcbnew/dialogs/dialog_cleanup_tracks_and_vias_base.cpp
+++ b/pcbnew/dialogs/dialog_cleanup_tracks_and_vias_base.cpp
@@ -55,7 +55,7 @@ DIALOG_CLEANUP_TRACKS_AND_VIAS_BASE::DIALOG_CLEANUP_TRACKS_AND_VIAS_BASE( wxWind
 	staticChangesLabel->Wrap( -1 );
 	bLowerSizer->Add( staticChangesLabel, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
 
-	m_changesDataView = new wxDataViewCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
+	m_changesDataView = new wxDataViewCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_NO_HEADER );
 	bLowerSizer->Add( m_changesDataView, 1, wxALL|wxEXPAND, 5 );
 
 
diff --git a/pcbnew/dialogs/dialog_cleanup_tracks_and_vias_base.fbp b/pcbnew/dialogs/dialog_cleanup_tracks_and_vias_base.fbp
index 1f91efb1c9..5f5d71f441 100644
--- a/pcbnew/dialogs/dialog_cleanup_tracks_and_vias_base.fbp
+++ b/pcbnew/dialogs/dialog_cleanup_tracks_and_vias_base.fbp
@@ -483,7 +483,7 @@
                                 <property name="permission">protected</property>
                                 <property name="pos"></property>
                                 <property name="size"></property>
-                                <property name="style"></property>
+                                <property name="style">wxDV_NO_HEADER</property>
                                 <property name="subclass">; ; forward_declare</property>
                                 <property name="tooltip"></property>
                                 <property name="window_extra_style"></property>
diff --git a/pcbnew/dialogs/dialog_drc.cpp b/pcbnew/dialogs/dialog_drc.cpp
index 2a69adca11..37cc0b6147 100644
--- a/pcbnew/dialogs/dialog_drc.cpp
+++ b/pcbnew/dialogs/dialog_drc.cpp
@@ -509,6 +509,9 @@ bool DIALOG_DRC::writeReport( const wxString& aFullFileName )
     if( fp == NULL )
         return false;
 
+    std::map<KIID, EDA_ITEM*> itemMap;
+    m_brdEditor->GetBoard()->FillItemMap( itemMap );
+
     int       count;
     EDA_UNITS units = GetUserUnits();
 
@@ -523,21 +526,21 @@ bool DIALOG_DRC::writeReport( const wxString& aFullFileName )
     fprintf( fp, "\n** Found %d DRC violations **\n", count );
 
     for( int i = 0; i < count; ++i )
-        fprintf( fp, "%s", TO_UTF8( m_markersProvider->GetItem( i )->ShowReport( units ) ) );
+        fprintf( fp, "%s", TO_UTF8( m_markersProvider->GetItem( i )->ShowReport( units, itemMap ) ) );
 
     count = m_unconnectedItemsProvider->GetCount();
 
     fprintf( fp, "\n** Found %d unconnected pads **\n", count );
 
     for( int i = 0; i < count; ++i )
-        fprintf( fp, "%s", TO_UTF8( m_unconnectedItemsProvider->GetItem( i )->ShowReport( units ) ) );
+        fprintf( fp, "%s", TO_UTF8( m_unconnectedItemsProvider->GetItem( i )->ShowReport( units, itemMap ) ) );
 
     count = m_footprintWarningsProvider->GetCount();
 
     fprintf( fp, "\n** Found %d Footprint errors **\n", count );
 
     for( int i = 0; i < count; ++i )
-        fprintf( fp, "%s", TO_UTF8( m_footprintWarningsProvider->GetItem( i )->ShowReport( units ) ) );
+        fprintf( fp, "%s", TO_UTF8( m_footprintWarningsProvider->GetItem( i )->ShowReport( units, itemMap ) ) );
 
 
     fprintf( fp, "\n** End of Report **\n" );
diff --git a/pcbnew/dialogs/dialog_netlist.cpp b/pcbnew/dialogs/dialog_netlist.cpp
index 411f35f371..a5950959fa 100644
--- a/pcbnew/dialogs/dialog_netlist.cpp
+++ b/pcbnew/dialogs/dialog_netlist.cpp
@@ -193,7 +193,7 @@ void DIALOG_NETLIST::OnTestFootprintsClick( wxCommandEvent& event )
     DRC::TestFootprints( netlist, m_parent->GetBoard(), GetUserUnits(), drcItems );
 
     for( DRC_ITEM* item : drcItems )
-        dlg.AddHTML_Text( item->ShowHtml( GetUserUnits() ) );
+        dlg.AddHTML_Text( item->ShowHtml( m_parent ) );
 
     dlg.ShowModal();
 }
diff --git a/pcbnew/drc/courtyard_overlap.cpp b/pcbnew/drc/courtyard_overlap.cpp
index 85a419e3bb..fb3f067fdf 100644
--- a/pcbnew/drc/courtyard_overlap.cpp
+++ b/pcbnew/drc/courtyard_overlap.cpp
@@ -48,12 +48,12 @@ static const wxChar* DRC_COURTYARD_TRACE = wxT( "KICAD_DRC_COURTYARD" );
 
 
 DRC_COURTYARD_OVERLAP::DRC_COURTYARD_OVERLAP( MARKER_HANDLER aMarkerHandler ) :
-        DRC_PROVIDER( aMarkerHandler )
+        DRC_TEST_PROVIDER( aMarkerHandler )
 {
 }
 
 
-bool DRC_COURTYARD_OVERLAP::RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) const
+bool DRC_COURTYARD_OVERLAP::RunDRC( BOARD& aBoard ) const
 {
     wxLogTrace( DRC_COURTYARD_TRACE, "Running DRC: Courtyard" );
 
@@ -65,14 +65,13 @@ bool DRC_COURTYARD_OVERLAP::RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) const
     // Update courtyard polygons, and test for missing courtyard definition:
     for( MODULE* footprint : aBoard.Modules() )
     {
-        wxPoint pos = footprint->GetPosition();
-        bool    is_ok = footprint->BuildPolyCourtyard();
+        bool is_ok = footprint->BuildPolyCourtyard();
 
         if( !is_ok && !aBoard.GetDesignSettings().Ignore( DRCE_OVERLAPPING_FOOTPRINTS ) )
         {
-            auto m = std::make_unique<MARKER_PCB>( aUnits, DRCE_MALFORMED_COURTYARD_IN_FOOTPRINT,
-                                                   pos, footprint );
-            HandleMarker( std::move( m ) );
+            DRC_ITEM* drcItem = new DRC_ITEM( DRCE_MALFORMED_COURTYARD_IN_FOOTPRINT );
+            drcItem->SetItems( footprint );
+            HandleMarker( new MARKER_PCB( drcItem, footprint->GetPosition() ) );
             success = false;
         }
 
@@ -82,9 +81,9 @@ bool DRC_COURTYARD_OVERLAP::RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) const
         if( footprint->GetPolyCourtyardFront().OutlineCount() == 0
                 && footprint->GetPolyCourtyardBack().OutlineCount() == 0 && is_ok )
         {
-            auto m = std::make_unique<MARKER_PCB>( aUnits, DRCE_MISSING_COURTYARD_IN_FOOTPRINT,
-                                                   pos, footprint );
-            HandleMarker( std::move( m ) );
+            DRC_ITEM* drcItem = new DRC_ITEM( DRCE_MISSING_COURTYARD_IN_FOOTPRINT );
+            drcItem->SetItems( footprint );
+            HandleMarker( new MARKER_PCB( drcItem, footprint->GetPosition() ) );
             success = false;
         }
     }
@@ -123,10 +122,9 @@ bool DRC_COURTYARD_OVERLAP::RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) const
             if( courtyard.OutlineCount() )
             {
                 //Overlap between footprint and candidate
-                auto  m = std::make_unique<MARKER_PCB>( aUnits, DRCE_OVERLAPPING_FOOTPRINTS,
-                                                        (wxPoint) courtyard.CVertex( 0, 0, -1 ),
-                                                        footprint, candidate );
-                HandleMarker( std::move( m ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_OVERLAPPING_FOOTPRINTS );
+                drcItem->SetItems( footprint, candidate );
+                HandleMarker( new MARKER_PCB( drcItem, (wxPoint) courtyard.CVertex( 0, 0, -1 ) ) );
                 success = false;
             }
         }
@@ -159,10 +157,9 @@ bool DRC_COURTYARD_OVERLAP::RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) const
             if( courtyard.OutlineCount() )
             {
                 //Overlap between footprint and candidate
-                auto  m = std::make_unique<MARKER_PCB>( aUnits, DRCE_OVERLAPPING_FOOTPRINTS,
-                                                        (wxPoint) courtyard.CVertex( 0, 0, -1 ),
-                                                        footprint, candidate );
-                HandleMarker( std::move( m ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_OVERLAPPING_FOOTPRINTS );
+                drcItem->SetItems( footprint, candidate );
+                HandleMarker( new MARKER_PCB( drcItem, (wxPoint) courtyard.CVertex( 0, 0, -1 ) ) );
                 success = false;
             }
         }
diff --git a/pcbnew/drc/courtyard_overlap.h b/pcbnew/drc/courtyard_overlap.h
index 71ba99ba62..79d12deb3f 100644
--- a/pcbnew/drc/courtyard_overlap.h
+++ b/pcbnew/drc/courtyard_overlap.h
@@ -32,12 +32,12 @@
 /**
  * A class that provides the courtyard-based DRC checks.
  */
-class DRC_COURTYARD_OVERLAP : public DRC_PROVIDER
+class DRC_COURTYARD_OVERLAP : public DRC_TEST_PROVIDER
 {
 public:
     DRC_COURTYARD_OVERLAP( MARKER_HANDLER aMarkerHandler );
 
-    bool RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) const override;
+    bool RunDRC( BOARD& aBoard ) const override;
 };
 
 #endif // DRC_COURTYARD_OVERLAP__H
\ No newline at end of file
diff --git a/pcbnew/drc/drc.cpp b/pcbnew/drc/drc.cpp
index a8a2d7b88e..de0775a2f3 100644
--- a/pcbnew/drc/drc.cpp
+++ b/pcbnew/drc/drc.cpp
@@ -246,8 +246,11 @@ int DRC::TestZoneToZoneOutlines()
 
                 if( smoothed_polys[ia2].Contains( currentVertex ) )
                 {
-                    addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_ZONES_INTERSECT, pt,
-                                                    zoneRef, zoneToTest ) );
+                    DRC_ITEM* drcItem = new DRC_ITEM( DRCE_ZONES_INTERSECT );
+                    drcItem->SetItems( zoneRef, zoneToTest );
+
+                    MARKER_PCB* marker = new MARKER_PCB( drcItem, pt );
+                    addMarkerToPcb( marker );
                     nerrors++;
                 }
             }
@@ -260,8 +263,11 @@ int DRC::TestZoneToZoneOutlines()
 
                 if( smoothed_polys[ia].Contains( currentVertex ) )
                 {
-                    addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_ZONES_INTERSECT, pt,
-                                                    zoneToTest, zoneRef ) );
+                    DRC_ITEM* drcItem = new DRC_ITEM( DRCE_ZONES_INTERSECT );
+                    drcItem->SetItems( zoneToTest, zoneRef );
+
+                    MARKER_PCB* marker = new MARKER_PCB( drcItem, pt );
+                    addMarkerToPcb( marker );
                     nerrors++;
                 }
             }
@@ -307,8 +313,11 @@ int DRC::TestZoneToZoneOutlines()
 
             for( wxPoint pt : conflictPoints )
             {
-                addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_ZONES_TOO_CLOSE, pt,
-                                                zoneRef, zoneToTest ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_ZONES_TOO_CLOSE );
+                drcItem->SetItems( zoneRef, zoneToTest );
+
+                MARKER_PCB* marker = new MARKER_PCB( drcItem, pt );
+                addMarkerToPcb( marker );
                 nerrors++;
             }
         }
@@ -531,12 +540,13 @@ bool DRC::doNetClass( const NETCLASSPTR& nc, wxString& msg )
     if( nc->GetClearance() < g.m_MinClearance )
     {
         msg.Printf( _( "NETCLASS: \"%s\" has Clearance:%s which is less than global:%s" ),
-                    GetChars( nc->GetName() ),
+                    nc->GetName(),
                     FmtVal( nc->GetClearance() ),
-                    FmtVal( g.m_TrackClearance )
-                    );
+                    FmtVal( g.m_TrackClearance ) );
 
-        addMarkerToPcb( new MARKER_PCB( DRCE_NETCLASS_CLEARANCE, msg ) );
+        DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_CLEARANCE );
+        drcItem->SetErrorMessage( msg );
+        addMarkerToPcb( new MARKER_PCB( drcItem, wxPoint() ) );
         ret = false;
     }
 #endif
@@ -544,58 +554,65 @@ bool DRC::doNetClass( const NETCLASSPTR& nc, wxString& msg )
     if( nc->GetTrackWidth() < g.m_TrackMinWidth )
     {
         msg.Printf( _( "NETCLASS: \"%s\" has TrackWidth:%s which is less than global:%s" ),
-                    GetChars( nc->GetName() ),
+                    nc->GetName(),
                     FmtVal( nc->GetTrackWidth() ),
-                    FmtVal( g.m_TrackMinWidth )
-                    );
+                    FmtVal( g.m_TrackMinWidth ) );
 
-        addMarkerToPcb( new MARKER_PCB( DRCE_NETCLASS_TRACKWIDTH, msg ) );
+        DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_TRACKWIDTH );
+        drcItem->SetErrorMessage( msg );
+        addMarkerToPcb( new MARKER_PCB( drcItem, wxPoint() ) );
         ret = false;
     }
 
     if( nc->GetViaDiameter() < g.m_ViasMinSize )
     {
         msg.Printf( _( "NETCLASS: \"%s\" has Via Dia:%s which is less than global:%s" ),
-                    GetChars( nc->GetName() ),
+                    nc->GetName(),
                     FmtVal( nc->GetViaDiameter() ),
-                    FmtVal( g.m_ViasMinSize )
-                    );
+                    FmtVal( g.m_ViasMinSize ) );
 
-        addMarkerToPcb( new MARKER_PCB( DRCE_NETCLASS_VIASIZE, msg ) );
+        DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_VIASIZE );
+        drcItem->SetErrorMessage( msg );
+        addMarkerToPcb( new MARKER_PCB( drcItem, wxPoint() ) );
         ret = false;
     }
 
     if( nc->GetViaDrill() < g.m_ViasMinDrill )
     {
         msg.Printf( _( "NETCLASS: \"%s\" has Via Drill:%s which is less than global:%s" ),
-                    GetChars( nc->GetName() ),
+                    nc->GetName(),
                     FmtVal( nc->GetViaDrill() ),
-                    FmtVal( g.m_ViasMinDrill )
-                    );
+                    FmtVal( g.m_ViasMinDrill ) );
 
-        addMarkerToPcb( new MARKER_PCB( DRCE_NETCLASS_VIADRILLSIZE, msg ) );
+        DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_VIADRILLSIZE );
+        drcItem->SetErrorMessage( msg );
+        addMarkerToPcb( new MARKER_PCB( drcItem, wxPoint() ) );
         ret = false;
     }
 
     if( nc->GetuViaDiameter() < g.m_MicroViasMinSize )
     {
         msg.Printf( _( "NETCLASS: \"%s\" has uVia Dia:%s which is less than global:%s" ),
-                    GetChars( nc->GetName() ),
+                    nc->GetName(),
                     FmtVal( nc->GetuViaDiameter() ),
                     FmtVal( g.m_MicroViasMinSize ) );
 
-        addMarkerToPcb( new MARKER_PCB( DRCE_NETCLASS_uVIASIZE, msg ) );
+        DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_uVIASIZE );
+        drcItem->SetErrorMessage( msg );
+        addMarkerToPcb( new MARKER_PCB( drcItem, wxPoint() ) );
         ret = false;
     }
 
     if( nc->GetuViaDrill() < g.m_MicroViasMinDrill )
     {
         msg.Printf( _( "NETCLASS: \"%s\" has uVia Drill:%s which is less than global:%s" ),
-                    GetChars( nc->GetName() ),
+                    nc->GetName(),
                     FmtVal( nc->GetuViaDrill() ),
                     FmtVal( g.m_MicroViasMinDrill ) );
 
-        addMarkerToPcb( new MARKER_PCB( DRCE_NETCLASS_uVIADRILLSIZE, msg ) );
+        DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_uVIADRILLSIZE );
+        drcItem->SetErrorMessage( msg );
+        addMarkerToPcb( new MARKER_PCB( drcItem, wxPoint() ) );
         ret = false;
     }
 
@@ -721,10 +738,11 @@ void DRC::testDrilledHoles()
             if( KiROUND( GetLineLength( checkHole.m_location, refHole.m_location ) )
                     <  checkHole.m_drillRadius + refHole.m_drillRadius + holeToHoleMin )
             {
-                addMarkerToPcb( new MARKER_PCB( m_pcbEditorFrame->GetUserUnits(),
-                                                DRCE_DRILLED_HOLES_TOO_CLOSE, refHole.m_location,
-                                                refHole.m_owner, refHole.m_location,
-                                                checkHole.m_owner, checkHole.m_location ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_DRILLED_HOLES_TOO_CLOSE );
+                drcItem->SetItems( refHole.m_owner, checkHole.m_owner );
+
+                MARKER_PCB* marker = new MARKER_PCB( drcItem, refHole.m_location );
+                addMarkerToPcb( marker );
             }
         }
     }
@@ -799,10 +817,8 @@ void DRC::testUnconnected()
 
     for( const auto& edge : edges )
     {
-        DRC_ITEM* item = new DRC_ITEM();
-        item->SetData( m_pcbEditorFrame->GetUserUnits(), DRCE_UNCONNECTED_ITEMS,
-                       edge.GetSourceNode()->Parent(), (wxPoint) edge.GetSourcePos(),
-                       edge.GetTargetNode()->Parent(), (wxPoint) edge.GetTargetPos() );
+        DRC_ITEM* item = new DRC_ITEM( DRCE_UNCONNECTED_ITEMS );
+        item->SetItems( edge.GetSourceNode()->Parent(), edge.GetTargetNode()->Parent() );
         m_unconnected.push_back( item );
     }
 }
@@ -833,9 +849,11 @@ void DRC::testZones()
 
         if( ( netcode < 0 ) || pads_in_net == 0 )
         {
-            wxPoint markerPos = zone->GetPosition();
-            addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE,
-                                            markerPos, zone ) );
+            DRC_ITEM* drcItem = new DRC_ITEM( DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE );
+            drcItem->SetItems( zone );
+
+            MARKER_PCB* marker = new MARKER_PCB( drcItem, zone->GetPosition() );
+            addMarkerToPcb( marker );
         }
     }
 
@@ -871,8 +889,11 @@ void DRC::testKeepoutAreas()
 
                 if( area->Outline()->Distance( trackSeg, segm->GetWidth() ) == 0 )
                 {
-                    addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACK_INSIDE_KEEPOUT,
-                                                    getLocation( segm, area ), segm, area ) );
+                    DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_INSIDE_KEEPOUT );
+                    drcItem->SetItems( segm, area );
+
+                    MARKER_PCB* marker = new MARKER_PCB( drcItem, getLocation( segm, area ) );
+                    addMarkerToPcb( marker );
                 }
             }
             else if( segm->Type() == PCB_VIA_T )
@@ -887,8 +908,11 @@ void DRC::testKeepoutAreas()
 
                 if( area->Outline()->Distance( segm->GetPosition() ) < segm->GetWidth()/2 )
                 {
-                    addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_VIA_INSIDE_KEEPOUT,
-                                                    getLocation( segm, area ), segm, area ) );
+                    DRC_ITEM* drcItem = new DRC_ITEM( DRCE_VIA_INSIDE_KEEPOUT );
+                    drcItem->SetItems( segm, area );
+
+                    MARKER_PCB* marker = new MARKER_PCB( drcItem, getLocation( segm, area ) );
+                    addMarkerToPcb( marker );
                 }
             }
         }
@@ -1010,15 +1034,21 @@ void DRC::testCopperDrawItem( DRAWSEGMENT* aItem )
             {
                 if( track->Type() == PCB_VIA_T )
                 {
-                    addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_VIA_NEAR_COPPER,
-                                                    getLocation( track, aItem, itemSeg ),
-                                                    track, aItem ) );
+                    DRC_ITEM* drcItem = new DRC_ITEM( DRCE_VIA_NEAR_COPPER );
+                    drcItem->SetItems( track, aItem );
+
+                    wxPoint     pos = getLocation( track, aItem, itemSeg );
+                    MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
+                    addMarkerToPcb( marker );
                 }
                 else
                 {
-                    addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACK_NEAR_COPPER,
-                                                    getLocation( track, aItem, itemSeg ),
-                                                    track, aItem ) );
+                    DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_COPPER );
+                    drcItem->SetItems( track, aItem );
+
+                    wxPoint     pos = getLocation( track, aItem, itemSeg );
+                    MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
+                    addMarkerToPcb( marker );
                 }
                 break;
             }
@@ -1042,8 +1072,11 @@ void DRC::testCopperDrawItem( DRAWSEGMENT* aItem )
         {
             if( padOutline.Distance( itemSeg, itemWidth ) == 0 )
             {
-                addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_PAD_NEAR_COPPER,
-                                                pad->GetPosition(), pad, aItem ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_PAD_NEAR_COPPER );
+                drcItem->SetItems( pad, aItem );
+
+                MARKER_PCB* marker = new MARKER_PCB( drcItem, pad->GetPosition() );
+                addMarkerToPcb( marker );
                 break;
             }
         }
@@ -1091,15 +1124,21 @@ void DRC::testCopperTextItem( BOARD_ITEM* aTextItem )
             {
                 if( track->Type() == PCB_VIA_T )
                 {
-                    addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_VIA_NEAR_COPPER,
-                                                    getLocation( track, aTextItem, textSeg ),
-                                                    track, aTextItem ) );
+                    DRC_ITEM* drcItem = new DRC_ITEM( DRCE_VIA_NEAR_COPPER );
+                    drcItem->SetItems( track, aTextItem );
+
+                    wxPoint     pos = getLocation( track, aTextItem, textSeg );
+                    MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
+                    addMarkerToPcb( marker );
                 }
                 else
                 {
-                    addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACK_NEAR_COPPER,
-                                                    getLocation( track, aTextItem, textSeg ),
-                                                    track, aTextItem ) );
+                    DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_COPPER );
+                    drcItem->SetItems( track, aTextItem );
+
+                    wxPoint     pos = getLocation( track, aTextItem, textSeg );
+                    MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
+                    addMarkerToPcb( marker );
                 }
                 break;
             }
@@ -1131,8 +1170,11 @@ void DRC::testCopperTextItem( BOARD_ITEM* aTextItem )
 
             if( padOutline.Distance( textSeg, 0 ) <= minDist )
             {
-                addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_PAD_NEAR_COPPER,
-                                                pad->GetPosition(), pad, aTextItem ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_PAD_NEAR_COPPER );
+                drcItem->SetItems( pad, aTextItem );
+
+                MARKER_PCB* marker = new MARKER_PCB( drcItem, pad->GetPosition() );
+                addMarkerToPcb( marker );
                 break;
             }
         }
@@ -1148,8 +1190,11 @@ void DRC::testOutline()
 
     if( !m_pcb->GetBoardPolygonOutlines( m_board_outlines, nullptr, &error_loc ) )
     {
-        addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_INVALID_OUTLINE, error_loc, m_pcb ) );
-        return;
+        DRC_ITEM* drcItem = new DRC_ITEM( DRCE_INVALID_OUTLINE );
+        drcItem->SetItems( m_pcb );
+
+        MARKER_PCB* marker = new MARKER_PCB( drcItem, error_loc );
+        addMarkerToPcb( marker );
     }
 }
 
@@ -1167,8 +1212,11 @@ void DRC::testDisabledLayers()
     {
         if( disabledLayers.test( track->GetLayer() ) )
         {
-            addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_DISABLED_LAYER_ITEM,
-                                            track->GetPosition(), track ) );
+            DRC_ITEM* drcItem = new DRC_ITEM( DRCE_DISABLED_LAYER_ITEM );
+            drcItem->SetItems( track );
+
+            MARKER_PCB* marker = new MARKER_PCB( drcItem, track->GetPosition() );
+            addMarkerToPcb( marker );
         }
     }
 
@@ -1179,8 +1227,11 @@ void DRC::testDisabledLayers()
                     {
                         if( disabledLayers.test( child->GetLayer() ) )
                         {
-                            addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_DISABLED_LAYER_ITEM,
-                                                            child->GetPosition(), child ) );
+                            DRC_ITEM* drcItem = new DRC_ITEM( DRCE_DISABLED_LAYER_ITEM );
+                            drcItem->SetItems( child );
+
+                            MARKER_PCB* marker = new MARKER_PCB( drcItem, child->GetPosition() );
+                            addMarkerToPcb( marker );
                         }
                     } );
     }
@@ -1189,8 +1240,11 @@ void DRC::testDisabledLayers()
     {
         if( disabledLayers.test( zone->GetLayer() ) )
         {
-            addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_DISABLED_LAYER_ITEM,
-                                            zone->GetPosition(), zone ) );
+            DRC_ITEM* drcItem = new DRC_ITEM( DRCE_DISABLED_LAYER_ITEM );
+            drcItem->SetItems( zone );
+
+            MARKER_PCB* marker = new MARKER_PCB( drcItem, zone->GetPosition() );
+            addMarkerToPcb( marker );
         }
     }
 }
@@ -1211,8 +1265,11 @@ void DRC::testTextVars()
 
                     if( text->GetShownText().Matches( wxT( "*${*}*" ) ) )
                     {
-                        addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_UNRESOLVED_VARIABLE,
-                                                        text->GetPosition(), text ) );
+                        DRC_ITEM* drcItem = new DRC_ITEM( DRCE_UNRESOLVED_VARIABLE );
+                        drcItem->SetItems( text );
+
+                        MARKER_PCB* marker = new MARKER_PCB( drcItem, text->GetPosition() );
+                        addMarkerToPcb( marker );
                     }
                 }
             } );
@@ -1226,8 +1283,11 @@ void DRC::testTextVars()
 
             if( text->GetShownText().Matches( wxT( "*${*}*" ) ) )
             {
-                addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_UNRESOLVED_VARIABLE,
-                                                text->GetPosition(), text ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_UNRESOLVED_VARIABLE );
+                drcItem->SetItems( text );
+
+                MARKER_PCB* marker = new MARKER_PCB( drcItem, text->GetPosition() );
+                addMarkerToPcb( marker );
             }
         }
     }
@@ -1305,9 +1365,11 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_li
 
                 if( !checkClearancePadToPad( aRefPad, &dummypad ) )
                 {
-                    // here we have a drc error on pad!
-                    addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_HOLE_NEAR_PAD,
-                                                    pad->GetPosition(), pad, aRefPad ) );
+                    DRC_ITEM* drcItem = new DRC_ITEM( DRCE_HOLE_NEAR_PAD );
+                    drcItem->SetItems( pad, aRefPad );
+
+                    MARKER_PCB* marker = new MARKER_PCB( drcItem, pad->GetPosition() );
+                    addMarkerToPcb( marker );
                     return false;
                 }
             }
@@ -1322,9 +1384,11 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_li
 
                 if( !checkClearancePadToPad( pad, &dummypad ) )
                 {
-                    // here we have a drc error on aRefPad!
-                    addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_HOLE_NEAR_PAD,
-                                                    aRefPad->GetPosition(), aRefPad, pad ) );
+                    DRC_ITEM* drcItem = new DRC_ITEM( DRCE_HOLE_NEAR_PAD );
+                    drcItem->SetItems( aRefPad, pad );
+
+                    MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefPad->GetPosition() );
+                    addMarkerToPcb( marker );
                     return false;
                 }
             }
@@ -1358,9 +1422,11 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_li
 
         if( !checkClearancePadToPad( aRefPad, pad ) )
         {
-            // here we have a drc error!
-            addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_PAD_NEAR_PAD1,
-                                            aRefPad->GetPosition(), aRefPad, pad ) );
+            DRC_ITEM* drcItem = new DRC_ITEM( DRCE_PAD_NEAR_PAD1 );
+            drcItem->SetItems( aRefPad, pad );
+
+            MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefPad->GetPosition() );
+            addMarkerToPcb( marker );
             return false;
         }
     }
@@ -1373,13 +1439,14 @@ void DRC::doOverlappingCourtyardsDrc()
 {
     DRC_COURTYARD_OVERLAP drc_overlap( [&]( MARKER_PCB* aMarker ) { addMarkerToPcb( aMarker ); } );
 
-    drc_overlap.RunDRC( userUnits(), *m_pcb );
+    drc_overlap.RunDRC( *m_pcb );
 }
 
 
 void DRC::TestFootprints( NETLIST& aNetlist, BOARD* aPCB, EDA_UNITS aUnits,
                           std::vector<DRC_ITEM*>& aDRCList )
 {
+    wxString msg;
 
     // Search for duplicate footprints on the board
     auto comp = []( const MODULE* x, const MODULE* y )
@@ -1388,15 +1455,14 @@ void DRC::TestFootprints( NETLIST& aNetlist, BOARD* aPCB, EDA_UNITS aUnits,
     };
     auto mods = std::set<MODULE*, decltype( comp )>( comp );
 
-    for( auto mod : aPCB->Modules() )
+    for( MODULE* mod : aPCB->Modules() )
     {
         auto ins = mods.insert( mod );
 
         if( !ins.second )
         {
-            DRC_ITEM* item = new DRC_ITEM();
-            item->SetData( aUnits, DRCE_DUPLICATE_FOOTPRINT, mod, mod->GetPosition(),
-                           *ins.first, ( *ins.first )->GetPosition() );
+            DRC_ITEM* item = new DRC_ITEM( DRCE_DUPLICATE_FOOTPRINT );
+            item->SetItems( mod, *ins.first );
             aDRCList.push_back( item );
         }
     }
@@ -1405,15 +1471,16 @@ void DRC::TestFootprints( NETLIST& aNetlist, BOARD* aPCB, EDA_UNITS aUnits,
     for( unsigned ii = 0; ii < aNetlist.GetCount(); ii++ )
     {
         COMPONENT* component = aNetlist.GetComponent( ii );
-
-        auto module = aPCB->FindModuleByReference( component->GetReference() );
+        MODULE*    module = aPCB->FindModuleByReference( component->GetReference() );
 
         if( module == NULL )
         {
-            DRC_ITEM* item = new DRC_ITEM();
-            item->SetData( DRCE_MISSING_FOOTPRINT, wxString::Format( wxT( "%s (%s)" ),
-                                                                     component->GetReference(),
-                                                                     component->GetValue() ) );
+            msg.Printf( _( "Missing footprint %s (%s)" ),
+                        component->GetReference(),
+                        component->GetValue() );
+
+            DRC_ITEM* item = new DRC_ITEM( DRCE_MISSING_FOOTPRINT );
+            item->SetErrorMessage( msg );
             aDRCList.push_back( item );
         }
     }
@@ -1425,8 +1492,8 @@ void DRC::TestFootprints( NETLIST& aNetlist, BOARD* aPCB, EDA_UNITS aUnits,
 
         if( component == NULL )
         {
-            DRC_ITEM* item = new DRC_ITEM();
-            item->SetData( aUnits, DRCE_EXTRA_FOOTPRINT, module, module->GetPosition() );
+            DRC_ITEM* item = new DRC_ITEM( DRCE_EXTRA_FOOTPRINT );
+            item->SetItems( module );
             aDRCList.push_back( item );
         }
     }
diff --git a/pcbnew/drc/drc.h b/pcbnew/drc/drc.h
index 22b21ede2e..124f61e42c 100644
--- a/pcbnew/drc/drc.h
+++ b/pcbnew/drc/drc.h
@@ -91,6 +91,11 @@ enum PCB_DRC_CODE {
     DRCE_DUPLICATE_FOOTPRINT,               ///< more than one footprints found for netlist item
     DRCE_EXTRA_FOOTPRINT,                   ///< netlist item not found for footprint
 
+    DRCE_UNRESOLVED_VARIABLE,
+
+    DRCE_LAST = DRCE_UNRESOLVED_VARIABLE,
+
+    // These are actually Cleanup Tracks and Vias actions, not DRCE errors
     DRCE_SHORT,
     DRCE_REDUNDANT_VIA,
     DRCE_DUPLICATE_TRACK,
@@ -98,11 +103,7 @@ enum PCB_DRC_CODE {
     DRCE_DANGLING_TRACK,
     DRCE_DANGLING_VIA,
     DRCE_ZERO_LENGTH_TRACK,
-    DRCE_TRACK_IN_PAD,
-
-    DRCE_UNRESOLVED_VARIABLE,
-
-    DRCE_LAST = DRCE_UNRESOLVED_VARIABLE
+    DRCE_TRACK_IN_PAD
 };
 
 
diff --git a/pcbnew/drc/drc_clearance_test_functions.cpp b/pcbnew/drc/drc_clearance_test_functions.cpp
index 5219a8062b..3fa3b249cd 100644
--- a/pcbnew/drc/drc_clearance_test_functions.cpp
+++ b/pcbnew/drc/drc_clearance_test_functions.cpp
@@ -143,28 +143,40 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
         {
             if( refvia->GetWidth() < dsnSettings.m_MicroViasMinSize )
             {
-                addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TOO_SMALL_MICROVIA,
-                                                refvia->GetPosition(), refvia ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TOO_SMALL_MICROVIA );
+                drcItem->SetItems( refvia );
+
+                MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
+                addMarkerToPcb( marker );
             }
 
             if( refvia->GetDrillValue() < dsnSettings.m_MicroViasMinDrill )
             {
-                addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TOO_SMALL_MICROVIA_DRILL,
-                                                refvia->GetPosition(), refvia ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TOO_SMALL_MICROVIA_DRILL );
+                drcItem->SetItems( refvia );
+
+                MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
+                addMarkerToPcb( marker );
             }
         }
         else
         {
             if( refvia->GetWidth() < dsnSettings.m_ViasMinSize )
             {
-                addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TOO_SMALL_VIA,
-                                                refvia->GetPosition(), refvia ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TOO_SMALL_VIA );
+                drcItem->SetItems( refvia );
+
+                MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
+                addMarkerToPcb( marker );
             }
 
             if( refvia->GetDrillValue() < dsnSettings.m_ViasMinDrill )
             {
-                addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TOO_SMALL_VIA_DRILL,
-                                                refvia->GetPosition(), refvia ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TOO_SMALL_VIA_DRILL );
+                drcItem->SetItems( refvia );
+
+                MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
+                addMarkerToPcb( marker );
             }
         }
 
@@ -173,22 +185,31 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
         // and a default via hole can be bigger than some vias sizes
         if( refvia->GetDrillValue() > refvia->GetWidth() )
         {
-            addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_VIA_HOLE_BIGGER,
-                                            refvia->GetPosition(), refvia ) );
+            DRC_ITEM* drcItem = new DRC_ITEM( DRCE_VIA_HOLE_BIGGER );
+            drcItem->SetItems( refvia );
+
+            MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
+            addMarkerToPcb( marker );
         }
 
         // test if the type of via is allowed due to design rules
         if( refvia->GetViaType() == VIATYPE::MICROVIA && !dsnSettings.m_MicroViasAllowed )
         {
-            addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_MICRO_VIA_NOT_ALLOWED,
-                                            refvia->GetPosition(), refvia ) );
+            DRC_ITEM* drcItem = new DRC_ITEM( DRCE_MICRO_VIA_NOT_ALLOWED );
+            drcItem->SetItems( refvia );
+
+            MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
+            addMarkerToPcb( marker );
         }
 
         // test if the type of via is allowed due to design rules
         if( refvia->GetViaType() == VIATYPE::BLIND_BURIED && !dsnSettings.m_BlindBuriedViaAllowed )
         {
-            addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_BURIED_VIA_NOT_ALLOWED,
-                                            refvia->GetPosition(), refvia ) );
+            DRC_ITEM* drcItem = new DRC_ITEM( DRCE_BURIED_VIA_NOT_ALLOWED );
+            drcItem->SetItems( refvia );
+
+            MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
+            addMarkerToPcb( marker );
         }
 
         // For microvias: test if they are blind vias and only between 2 layers
@@ -211,8 +232,11 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
 
             if( err )
             {
-                addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_MICRO_VIA_INCORRECT_LAYER_PAIR,
-                                                refvia->GetPosition(), refvia ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_MICRO_VIA_INCORRECT_LAYER_PAIR );
+                drcItem->SetItems( refvia );
+
+                MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
+                addMarkerToPcb( marker );
             }
         }
 
@@ -223,8 +247,11 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
         {
             wxPoint refsegMiddle = ( aRefSeg->GetStart() + aRefSeg->GetEnd() ) / 2;
 
-            addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TOO_SMALL_TRACK_WIDTH,
-                                            refsegMiddle, aRefSeg ) );
+            DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TOO_SMALL_TRACK_WIDTH );
+            drcItem->SetItems( aRefSeg );
+
+            MARKER_PCB* marker = new MARKER_PCB( drcItem, refsegMiddle );
+            addMarkerToPcb( marker );
         }
     }
 
@@ -286,9 +313,11 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
 
                 if( !checkClearanceSegmToPad( &dummypad, ref_seg_width, ref_seg_clearance ) )
                 {
-                    addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACK_NEAR_THROUGH_HOLE,
-                                                    getLocation( aRefSeg, pad, padSeg ),
-                                                    aRefSeg, pad ) );
+                    DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_THROUGH_HOLE );
+                    drcItem->SetItems( aRefSeg, pad );
+
+                    MARKER_PCB* marker = new MARKER_PCB( drcItem, getLocation( aRefSeg, pad, padSeg ) );
+                    addMarkerToPcb( marker );
 
                     if( !m_reportAllTrackErrors )
                         return;
@@ -310,9 +339,11 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
 
             if( !checkClearanceSegmToPad( pad, ref_seg_width, segToPadClearance ) )
             {
-                addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACK_NEAR_PAD,
-                                                getLocation( aRefSeg, pad, padSeg ),
-                                                aRefSeg, pad ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_PAD );
+                drcItem->SetItems( aRefSeg, pad );
+
+                MARKER_PCB* marker = new MARKER_PCB( drcItem, getLocation( aRefSeg, pad, padSeg ) );
+                addMarkerToPcb( marker );
 
                 if( !m_reportAllTrackErrors )
                     return;
@@ -364,8 +395,11 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
                 // Test distance between two vias, i.e. two circles, trivial case
                 if( EuclideanNorm( segStartPoint ) < w_dist )
                 {
-                    addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_VIA_NEAR_VIA,
-                                                    aRefSeg->GetPosition(), aRefSeg, track ) );
+                    DRC_ITEM* drcItem = new DRC_ITEM( DRCE_VIA_NEAR_VIA );
+                    drcItem->SetItems( aRefSeg, track );
+
+                    MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefSeg->GetPosition() );
+                    addMarkerToPcb( marker );
 
                     if( !m_reportAllTrackErrors )
                         return;
@@ -382,8 +416,11 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
 
                 if( !checkMarginToCircle( segStartPoint, w_dist, delta.x ) )
                 {
-                    addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_VIA_NEAR_TRACK,
-                                                    aRefSeg->GetPosition(), aRefSeg, track ) );
+                    DRC_ITEM* drcItem = new DRC_ITEM( DRCE_VIA_NEAR_TRACK );
+                    drcItem->SetItems( aRefSeg, track );
+
+                    MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefSeg->GetPosition() );
+                    addMarkerToPcb( marker );
 
                     if( !m_reportAllTrackErrors )
                         return;
@@ -409,8 +446,11 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
             if( checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
                 continue;
 
-            addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACK_NEAR_VIA,
-                                            getLocation( aRefSeg, track, seg ), aRefSeg, track ) );
+            DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_VIA );
+            drcItem->SetItems( aRefSeg, track );
+
+            MARKER_PCB* marker = new MARKER_PCB( drcItem, getLocation( aRefSeg, track, seg ) );
+            addMarkerToPcb( marker );
 
             if( !m_reportAllTrackErrors )
                 return;
@@ -438,9 +478,11 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
                 // Fine test : we consider the rounded shape of each end of the track segment:
                 if( segStartPoint.x >= 0 && segStartPoint.x <= m_segmLength )
                 {
-                    addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACK_ENDS,
-                                                    getLocation( aRefSeg, track, seg ),
-                                                    aRefSeg, track ) );
+                    DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_ENDS );
+                    drcItem->SetItems( aRefSeg, track );
+
+                    MARKER_PCB* marker = new MARKER_PCB( drcItem, getLocation( aRefSeg, track, seg ) );
+                    addMarkerToPcb( marker );
 
                     if( !m_reportAllTrackErrors )
                         return;
@@ -448,9 +490,11 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
 
                 if( !checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
                 {
-                    addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACK_ENDS,
-                                                    getLocation( aRefSeg, track, seg ),
-                                                    aRefSeg, track ) );
+                    DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_ENDS );
+                    drcItem->SetItems( aRefSeg, track );
+
+                    MARKER_PCB* marker = new MARKER_PCB( drcItem, getLocation( aRefSeg, track, seg ) );
+                    addMarkerToPcb( marker );
 
                     if( !m_reportAllTrackErrors )
                         return;
@@ -465,9 +509,11 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
                 // Fine test : we consider the rounded shape of the ends
                 if( segEndPoint.x >= 0 && segEndPoint.x <= m_segmLength )
                 {
-                    addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACK_ENDS,
-                                                    getLocation( aRefSeg, track, seg ),
-                                                    aRefSeg, track ) );
+                    DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_ENDS );
+                    drcItem->SetItems( aRefSeg, track );
+
+                    MARKER_PCB* marker = new MARKER_PCB( drcItem, getLocation( aRefSeg, track, seg ) );
+                    addMarkerToPcb( marker );
 
                     if( !m_reportAllTrackErrors )
                         return;
@@ -475,9 +521,11 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
 
                 if( !checkMarginToCircle( segEndPoint, w_dist, m_segmLength ) )
                 {
-                    addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACK_ENDS,
-                                                    getLocation( aRefSeg, track, seg ),
-                                                    aRefSeg, track ) );
+                    DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_ENDS );
+                    drcItem->SetItems( aRefSeg, track );
+
+                    MARKER_PCB* marker = new MARKER_PCB( drcItem, getLocation( aRefSeg, track, seg ) );
+                    addMarkerToPcb( marker );
 
                     if( !m_reportAllTrackErrors )
                         return;
@@ -491,9 +539,11 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
                 // handled)
                 //  X.............X
                 //    O--REF--+
-                addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACK_SEGMENTS_TOO_CLOSE,
-                                                getLocation( aRefSeg, track, seg ),
-                                                aRefSeg, track ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_SEGMENTS_TOO_CLOSE );
+                drcItem->SetItems( aRefSeg, track );
+
+                MARKER_PCB* marker = new MARKER_PCB( drcItem, getLocation( aRefSeg, track, seg ) );
+                addMarkerToPcb( marker );
 
                 if( !m_reportAllTrackErrors )
                     return;
@@ -510,9 +560,12 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
 
             if( ( segStartPoint.y < 0 ) && ( segEndPoint.y > 0 ) )
             {
-                addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACKS_CROSSING,
-                                                wxPoint( track->GetStart().x, aRefSeg->GetStart().y ),
-                                                aRefSeg, track ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACKS_CROSSING );
+                drcItem->SetItems( aRefSeg, track );
+
+                wxPoint     pos( track->GetStart().x, aRefSeg->GetStart().y );
+                MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
+                addMarkerToPcb( marker );
 
                 if( !m_reportAllTrackErrors )
                     return;
@@ -521,18 +574,22 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
             // At this point the drc error is due to an end near a reference segm end
             if( !checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
             {
-                addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACK_ENDS,
-                                                getLocation( aRefSeg, track, seg ),
-                                                aRefSeg, track ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_ENDS );
+                drcItem->SetItems( aRefSeg, track );
+
+                MARKER_PCB* marker = new MARKER_PCB( drcItem, getLocation( aRefSeg, track, seg ) );
+                addMarkerToPcb( marker );
 
                 if( !m_reportAllTrackErrors )
                     return;
             }
             if( !checkMarginToCircle( segEndPoint, w_dist, m_segmLength ) )
             {
-                addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACK_ENDS,
-                                                getLocation( aRefSeg, track, seg ),
-                                                aRefSeg, track ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_ENDS );
+                drcItem->SetItems( aRefSeg, track );
+
+                MARKER_PCB* marker = new MARKER_PCB( drcItem, getLocation( aRefSeg, track, seg ) );
+                addMarkerToPcb( marker );
 
                 if( !m_reportAllTrackErrors )
                     return;
@@ -567,14 +624,19 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
                                                   track->GetStart(), track->GetEnd(),
                                                   &failurePoint ) )
                     {
-                        addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACKS_CROSSING,
-                                                        failurePoint, aRefSeg, track ) );
+                        DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACKS_CROSSING );
+                        drcItem->SetItems( aRefSeg, track );
+
+                        MARKER_PCB* marker = new MARKER_PCB( drcItem, failurePoint );
+                        addMarkerToPcb( marker );
                     }
                     else
                     {
-                        addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACK_ENDS,
-                                                        getLocation( aRefSeg, track, seg ),
-                                                        aRefSeg, track ) );
+                        DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_ENDS );
+                        drcItem->SetItems( aRefSeg, track );
+
+                        MARKER_PCB* marker = new MARKER_PCB( drcItem, getLocation( aRefSeg, track, seg ) );
+                        addMarkerToPcb( marker );
                     }
 
                     if( !m_reportAllTrackErrors )
@@ -604,9 +666,11 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
 
                     if( !checkMarginToCircle( relStartPos, w_dist, delta.x ) )
                     {
-                        addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACK_ENDS,
-                                                        getLocation( aRefSeg, track, seg ),
-                                                        aRefSeg, track ) );
+                        DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_ENDS );
+                        drcItem->SetItems( aRefSeg, track );
+
+                        MARKER_PCB* marker = new MARKER_PCB( drcItem, getLocation( aRefSeg, track, seg ) );
+                        addMarkerToPcb( marker );
 
                         if( !m_reportAllTrackErrors )
                             return;
@@ -614,9 +678,11 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
 
                     if( !checkMarginToCircle( relEndPos, w_dist, delta.x ) )
                     {
-                        addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACK_ENDS,
-                                                        getLocation( aRefSeg, track, seg ),
-                                                        aRefSeg, track ) );
+                        DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_ENDS );
+                        drcItem->SetItems( aRefSeg, track );
+
+                        MARKER_PCB* marker = new MARKER_PCB( drcItem, getLocation( aRefSeg, track, seg ) );
+                        addMarkerToPcb( marker );
 
                         if( !m_reportAllTrackErrors )
                             return;
@@ -656,8 +722,11 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
             #define THRESHOLD_DIST Millimeter2iu( 0.001 )
             if( error > THRESHOLD_DIST )
             {
-                addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACK_NEAR_ZONE,
-                                                getLocation( aRefSeg, zone ), aRefSeg, zone  ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_ZONE );
+                drcItem->SetItems( aRefSeg, zone );
+
+                MARKER_PCB* marker = new MARKER_PCB( drcItem, getLocation( aRefSeg, zone ) );
+                addMarkerToPcb( marker );
             }
         }
     }
@@ -701,8 +770,11 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
                 // Best-efforts search for edge segment
                 BOARD::IterateForward<BOARD_ITEM*>( m_pcb->Drawings(), inspector, nullptr, types );
 
-                addMarkerToPcb( new MARKER_PCB( userUnits(), DRCE_TRACK_NEAR_EDGE, (wxPoint) pt,
-                                                aRefSeg, edge ) );
+                DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_EDGE );
+                drcItem->SetItems( aRefSeg, edge );
+
+                MARKER_PCB* marker = new MARKER_PCB( drcItem, (wxPoint) pt );
+                addMarkerToPcb( marker );
             }
         }
     }
diff --git a/pcbnew/drc/drc_item.cpp b/pcbnew/drc/drc_item.cpp
index 53e305d623..f2dc9ff8c5 100644
--- a/pcbnew/drc/drc_item.cpp
+++ b/pcbnew/drc/drc_item.cpp
@@ -34,7 +34,7 @@
 
 wxString DRC_ITEM::GetErrorText() const
 {
-    switch( m_ErrorCode )
+    switch( m_errorCode )
     {
     case DRCE_UNCONNECTED_ITEMS:
         return wxString( _( "Unconnected items" ) );
@@ -175,22 +175,45 @@ wxString escapeHtml( wxString aString )
 }
 
 
-wxString DRC_ITEM::ShowHtml( EDA_UNITS aUnits ) const
+wxString DRC_ITEM::ShowHtml( PCB_BASE_FRAME* aFrame ) const
 {
-    if( m_hasSecondItem )
+    BOARD_ITEM* mainItem = nullptr;
+    BOARD_ITEM* auxItem = nullptr;
+    wxString    msg = m_errorMessage.IsEmpty() ? GetErrorText() : m_errorMessage;
+    wxString    mainText;
+    wxString    auxText;
+
+    if( m_mainItemUuid != niluuid )
+        mainItem = aFrame->GetBoard()->GetItem( m_mainItemUuid );
+
+    if( m_auxItemUuid != niluuid )
+        auxItem = aFrame->GetBoard()->GetItem( m_auxItemUuid );
+
+    if( mainItem )
+        mainText = mainItem->GetSelectMenuText( aFrame->GetUserUnits() );
+
+    if( auxItem )
+        auxText = auxItem->GetSelectMenuText( aFrame->GetUserUnits() );
+
+    if( mainItem && auxItem )
     {
         // an html fragment for the entire message in the listbox.  feel free
         // to add color if you want:
         return wxString::Format( wxT( "<b>%s</b><br>&nbsp;&nbsp; %s<br>&nbsp;&nbsp; %s" ),
-                                 escapeHtml( GetErrorText() ),
-                                 escapeHtml( m_MainText ),
-                                 escapeHtml( m_AuxText ) );
+                                 escapeHtml( msg ),
+                                 escapeHtml( mainText ),
+                                 escapeHtml( auxText ) );
+    }
+    else if( mainItem )
+    {
+        return wxString::Format( wxT( "<b>%s</b><br>&nbsp;&nbsp; %s" ),
+                                 escapeHtml( msg ),
+                                 escapeHtml( mainText ) );
     }
     else
     {
-        return wxString::Format( wxT( "<b>%s</b><br>&nbsp;&nbsp; %s" ),
-                                 escapeHtml( GetErrorText() ),
-                                 escapeHtml( m_MainText ) );
+        return wxString::Format( wxT( "<b>%s</b>" ),
+                                 escapeHtml( msg ) );
     }
 }
 
diff --git a/pcbnew/drc/drc_item.h b/pcbnew/drc/drc_item.h
index 6749df11dc..f1203c007e 100644
--- a/pcbnew/drc/drc_item.h
+++ b/pcbnew/drc/drc_item.h
@@ -30,13 +30,17 @@
 #include <rc_item.h>
 #include <marker_base.h>
 #include <class_board.h>
-#include <class_marker_pcb.h>
 #include <pcb_base_frame.h>
 
 
 class DRC_ITEM : public RC_ITEM
 {
 public:
+    DRC_ITEM( int aErrorCode )
+    {
+        m_errorCode = aErrorCode;
+    }
+
     /**
      * Function GetErrorText
      * returns the string form of a drc error code.
@@ -48,213 +52,7 @@ public:
      * translates this object into a fragment of HTML suitable for the wxHtmlListBox class.
      * @return wxString - the html text.
      */
-    wxString ShowHtml( EDA_UNITS aUnits ) const;
-};
-
-
-/**
- * BOARD_DRC_ITEMS_PROVIDER
- * is an implementation of the interface named DRC_ITEM_LIST which uses a BOARD instance
- * to fulfill the interface.  No ownership is taken of the BOARD.
- */
-class BOARD_DRC_ITEMS_PROVIDER : public RC_ITEMS_PROVIDER
-{
-private:
-    BOARD*                   m_board;
-
-    int                      m_severities;
-    std::vector<MARKER_PCB*> m_filteredMarkers;
-
-public:
-    BOARD_DRC_ITEMS_PROVIDER( BOARD* aBoard ) :
-            m_board( aBoard ),
-            m_severities( 0 )
-    {
-    }
-
-    void SetSeverities( int aSeverities ) override
-    {
-        m_severities = aSeverities;
-
-        BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
-
-        m_filteredMarkers.clear();
-
-        for( MARKER_PCB* marker : m_board->Markers() )
-        {
-            int markerSeverity;
-
-            if( marker->IsExcluded() )
-                markerSeverity = RPT_SEVERITY_EXCLUSION;
-            else
-                markerSeverity = bds.GetSeverity( marker->GetRCItem()->GetErrorCode() );
-
-            if( markerSeverity & m_severities )
-                m_filteredMarkers.push_back( marker );
-        }
-    }
-
-    int GetCount( int aSeverity = -1 ) override
-    {
-        if( aSeverity < 0 )
-            return m_filteredMarkers.size();
-
-        BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
-
-        int count = 0;
-
-        for( MARKER_PCB* marker : m_board->Markers() )
-        {
-            int markerSeverity;
-
-            if( marker->IsExcluded() )
-                markerSeverity = RPT_SEVERITY_EXCLUSION;
-            else
-                markerSeverity = bds.GetSeverity( marker->GetRCItem()->GetErrorCode() );
-
-            if( markerSeverity == aSeverity )
-                count++;
-        }
-
-        return count;
-    }
-
-    DRC_ITEM* GetItem( int aIndex ) override
-    {
-        MARKER_PCB* marker = m_filteredMarkers[ aIndex ];
-
-        return marker ? static_cast<DRC_ITEM*>( marker->GetRCItem() ) : nullptr;
-    }
-
-    void DeleteItem( int aIndex, bool aDeep ) override
-    {
-        MARKER_PCB* marker = m_filteredMarkers[ aIndex ];
-        m_filteredMarkers.erase( m_filteredMarkers.begin() + aIndex );
-
-        if( aDeep )
-            m_board->Delete( marker );
-    }
-
-    void DeleteAllItems() override
-    {
-        m_board->DeleteMARKERs();
-        m_filteredMarkers.clear();
-    }
-};
-
-
-/**
- * VECTOR_DRC_ITEMS_PROVIDER
- * is an implementation of the interface named DRC_ITEMS_PROVIDER which uses a vector
- * of pointers to DRC_ITEMs to fulfill the interface.  No ownership is taken of the
- * vector.
- */
-class VECTOR_DRC_ITEMS_PROVIDER : public RC_ITEMS_PROVIDER
-{
-    PCB_BASE_FRAME*         m_frame;
-    std::vector<DRC_ITEM*>* m_sourceVector;     // owns its DRC_ITEMs
-
-    int                     m_severities;
-    std::vector<DRC_ITEM*>  m_filteredVector;   // does not own its DRC_ITEMs
-
-public:
-
-    VECTOR_DRC_ITEMS_PROVIDER( PCB_BASE_FRAME* aFrame, std::vector<DRC_ITEM*>* aList ) :
-            m_frame( aFrame ),
-            m_sourceVector( aList ),
-            m_severities( 0 )
-    {
-    }
-
-    void SetSeverities( int aSeverities ) override
-    {
-        m_severities = aSeverities;
-
-        BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings();
-
-        m_filteredVector.clear();
-
-        if( m_sourceVector )
-        {
-            for( DRC_ITEM* item : *m_sourceVector )
-            {
-                if( bds.GetSeverity( item->GetErrorCode() ) & aSeverities )
-                    m_filteredVector.push_back( item );
-            }
-        }
-    }
-
-    int  GetCount( int aSeverity = -1 ) override
-    {
-        if( aSeverity < 0 )
-            return m_filteredVector.size();
-
-        int count = 0;
-        BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings();
-
-        if( m_sourceVector )
-        {
-            for( DRC_ITEM* item : *m_sourceVector )
-            {
-                if( bds.GetSeverity( item->GetErrorCode() ) == aSeverity )
-                    count++;
-            }
-        }
-
-        return count;
-    }
-
-    DRC_ITEM* GetItem( int aIndex ) override
-    {
-        return (m_filteredVector)[aIndex];
-    }
-
-    void DeleteItem( int aIndex, bool aDeep ) override
-    {
-        DRC_ITEM* item = m_filteredVector[aIndex];
-        m_filteredVector.erase( m_filteredVector.begin() + aIndex );
-
-        if( aDeep )
-        {
-            for( size_t i = 0; i < m_sourceVector->size(); ++i )
-            {
-                if( m_sourceVector->at( i ) == item )
-                {
-                    delete item;
-                    m_sourceVector->erase( m_sourceVector->begin() + i );
-                    break;
-                }
-            }
-        }
-    }
-
-    void DeleteAllItems() override
-    {
-        if( m_sourceVector )
-        {
-            for( DRC_ITEM* item : *m_sourceVector )
-                delete item;
-
-            m_sourceVector->clear();
-        }
-
-        m_filteredVector.clear();   // no ownership of DRC_ITEM pointers
-    }
-};
-
-
-/**
- * RATSNEST_DRC_ITEMS_PROVIDER
- */
-class RATSNEST_DRC_ITEMS_PROVIDER : public VECTOR_DRC_ITEMS_PROVIDER
-{
-    // TODO: for now this is just a vector, but we need to map it to some board-level
-    // data-structure so that deleting/excluding things can do a deep delete/exclusion
-    // which will be reflected in the ratsnest....
-public:
-    RATSNEST_DRC_ITEMS_PROVIDER( PCB_BASE_FRAME* aFrame, std::vector<DRC_ITEM*>* aList ) :
-            VECTOR_DRC_ITEMS_PROVIDER( aFrame, aList )
-    { }
+    wxString ShowHtml( PCB_BASE_FRAME* aFrame ) const;
 };
 
 
diff --git a/pcbnew/drc/drc_provider.h b/pcbnew/drc/drc_provider.h
index 7301e99e75..7ce4f3495b 100644
--- a/pcbnew/drc/drc_provider.h
+++ b/pcbnew/drc/drc_provider.h
@@ -32,10 +32,11 @@
 
 
 /**
- * that represents a DRC "provider" which runs some
- * DRC functions over a #BOARD and spits out #PCB_MARKERs as needed.
+ * DRC_TEST_PROVIDER
+ * is a base class that represents a DRC "provider" which runs some DRC functions over a
+ * #BOARD and spits out #PCB_MARKERs as needed.
  */
-class DRC_PROVIDER
+class DRC_TEST_PROVIDER
 {
 public:
     /**
@@ -43,22 +44,16 @@ public:
      */
     using MARKER_HANDLER = std::function<void( MARKER_PCB* )>;
 
-    // This class can be handled by base pointer
-    virtual ~DRC_PROVIDER()
-    {
-    }
-
     /**
-     * Runs this provider against the given PCB with
-     * configured options (if any).
+     * Runs this provider against the given PCB with configured options (if any).
      *
-     * Note: Board is non-const, as some DRC functions modify the board
-     * (e.g. zone fill or polygon coalescing)
+     * Note: Board is non-const, as some DRC functions modify the board (e.g. zone fill
+     * or polygon coalescing)
      */
-    virtual bool RunDRC( EDA_UNITS aUnits, BOARD& aBoard ) const = 0;
+    virtual bool RunDRC( BOARD& aBoard ) const = 0;
 
 protected:
-    DRC_PROVIDER( MARKER_HANDLER aMarkerHandler ) :
+    DRC_TEST_PROVIDER( MARKER_HANDLER aMarkerHandler ) :
             m_marker_handler( std::move( aMarkerHandler ) )
     {
     }
@@ -66,17 +61,221 @@ protected:
     /**
      * Pass a given marker to the marker handler
      */
-    void HandleMarker( std::unique_ptr<MARKER_PCB> aMarker ) const
+    void HandleMarker( MARKER_PCB* aMarker ) const
     {
-        // The marker hander currently takes a raw pointer,
-        // but it also assumes ownership
-        m_marker_handler( aMarker.release() );
+        m_marker_handler( aMarker );
     }
 
-
 private:
     /// The handler for any generated markers
     MARKER_HANDLER m_marker_handler;
 };
 
+
+/**
+ * BOARD_DRC_ITEMS_PROVIDER
+ * is an implementation of the RC_ITEMS_PROVIDER interface which uses a BOARD instance
+ * to fulfill the interface.
+ */
+class BOARD_DRC_ITEMS_PROVIDER : public RC_ITEMS_PROVIDER
+{
+private:
+    BOARD*                   m_board;
+
+    int                      m_severities;
+    std::vector<MARKER_PCB*> m_filteredMarkers;
+
+public:
+    BOARD_DRC_ITEMS_PROVIDER( BOARD* aBoard ) :
+            m_board( aBoard ),
+            m_severities( 0 )
+    {
+    }
+
+    void SetSeverities( int aSeverities ) override
+    {
+        m_severities = aSeverities;
+
+        BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
+
+        m_filteredMarkers.clear();
+
+        for( MARKER_PCB* marker : m_board->Markers() )
+        {
+            int markerSeverity;
+
+            if( marker->IsExcluded() )
+                markerSeverity = RPT_SEVERITY_EXCLUSION;
+            else
+                markerSeverity = bds.GetSeverity( marker->GetRCItem()->GetErrorCode() );
+
+            if( markerSeverity & m_severities )
+                m_filteredMarkers.push_back( marker );
+        }
+    }
+
+    int GetCount( int aSeverity = -1 ) override
+    {
+        if( aSeverity < 0 )
+            return m_filteredMarkers.size();
+
+        BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
+
+        int count = 0;
+
+        for( MARKER_PCB* marker : m_board->Markers() )
+        {
+            int markerSeverity;
+
+            if( marker->IsExcluded() )
+                markerSeverity = RPT_SEVERITY_EXCLUSION;
+            else
+                markerSeverity = bds.GetSeverity( marker->GetRCItem()->GetErrorCode() );
+
+            if( markerSeverity == aSeverity )
+                count++;
+        }
+
+        return count;
+    }
+
+    DRC_ITEM* GetItem( int aIndex ) override
+    {
+        MARKER_PCB* marker = m_filteredMarkers[ aIndex ];
+
+        return marker ? static_cast<DRC_ITEM*>( marker->GetRCItem() ) : nullptr;
+    }
+
+    void DeleteItem( int aIndex, bool aDeep ) override
+    {
+        MARKER_PCB* marker = m_filteredMarkers[ aIndex ];
+        m_filteredMarkers.erase( m_filteredMarkers.begin() + aIndex );
+
+        if( aDeep )
+            m_board->Delete( marker );
+    }
+
+    void DeleteAllItems() override
+    {
+        m_board->DeleteMARKERs();
+        m_filteredMarkers.clear();
+    }
+};
+
+
+/**
+ * VECTOR_DRC_ITEMS_PROVIDER
+ * is an implementation of the interface named DRC_ITEMS_PROVIDER which uses a vector
+ * of pointers to DRC_ITEMs to fulfill the interface.  No ownership is taken of the
+ * vector.
+ */
+class VECTOR_DRC_ITEMS_PROVIDER : public RC_ITEMS_PROVIDER
+{
+    PCB_BASE_FRAME*         m_frame;
+    std::vector<DRC_ITEM*>* m_sourceVector;     // owns its DRC_ITEMs
+
+    int                     m_severities;
+    std::vector<DRC_ITEM*>  m_filteredVector;   // does not own its DRC_ITEMs
+
+public:
+
+    VECTOR_DRC_ITEMS_PROVIDER( PCB_BASE_FRAME* aFrame, std::vector<DRC_ITEM*>* aList ) :
+            m_frame( aFrame ),
+            m_sourceVector( aList ),
+            m_severities( 0 )
+    {
+    }
+
+    void SetSeverities( int aSeverities ) override
+    {
+        m_severities = aSeverities;
+
+        BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings();
+
+        m_filteredVector.clear();
+
+        if( m_sourceVector )
+        {
+            for( DRC_ITEM* item : *m_sourceVector )
+            {
+                if( bds.GetSeverity( item->GetErrorCode() ) & aSeverities )
+                    m_filteredVector.push_back( item );
+            }
+        }
+    }
+
+    int  GetCount( int aSeverity = -1 ) override
+    {
+        if( aSeverity < 0 )
+            return m_filteredVector.size();
+
+        int count = 0;
+        BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings();
+
+        if( m_sourceVector )
+        {
+            for( DRC_ITEM* item : *m_sourceVector )
+            {
+                if( bds.GetSeverity( item->GetErrorCode() ) == aSeverity )
+                    count++;
+            }
+        }
+
+        return count;
+    }
+
+    DRC_ITEM* GetItem( int aIndex ) override
+    {
+        return (m_filteredVector)[aIndex];
+    }
+
+    void DeleteItem( int aIndex, bool aDeep ) override
+    {
+        DRC_ITEM* item = m_filteredVector[aIndex];
+        m_filteredVector.erase( m_filteredVector.begin() + aIndex );
+
+        if( aDeep )
+        {
+            for( size_t i = 0; i < m_sourceVector->size(); ++i )
+            {
+                if( m_sourceVector->at( i ) == item )
+                {
+                    delete item;
+                    m_sourceVector->erase( m_sourceVector->begin() + i );
+                    break;
+                }
+            }
+        }
+    }
+
+    void DeleteAllItems() override
+    {
+        if( m_sourceVector )
+        {
+            for( DRC_ITEM* item : *m_sourceVector )
+                delete item;
+
+            m_sourceVector->clear();
+        }
+
+        m_filteredVector.clear();   // no ownership of DRC_ITEM pointers
+    }
+};
+
+
+/**
+ * RATSNEST_DRC_ITEMS_PROVIDER
+ */
+class RATSNEST_DRC_ITEMS_PROVIDER : public VECTOR_DRC_ITEMS_PROVIDER
+{
+    // TODO: for now this is just a vector, but we need to map it to some board-level
+    // data-structure so that deleting/excluding things can do a deep delete/exclusion
+    // which will be reflected in the ratsnest....
+public:
+    RATSNEST_DRC_ITEMS_PROVIDER( PCB_BASE_FRAME* aFrame, std::vector<DRC_ITEM*>* aList ) :
+            VECTOR_DRC_ITEMS_PROVIDER( aFrame, aList )
+    { }
+};
+
+
 #endif // DRC_PROVIDER__H
\ No newline at end of file
diff --git a/pcbnew/footprint_wizard_frame.cpp b/pcbnew/footprint_wizard_frame.cpp
index ed2149b842..7e3719d474 100644
--- a/pcbnew/footprint_wizard_frame.cpp
+++ b/pcbnew/footprint_wizard_frame.cpp
@@ -308,7 +308,7 @@ void FOOTPRINT_WIZARD_FRAME::UpdateMsgPanel()
     {
         MSG_PANEL_ITEMS items;
 
-        footprint->GetMsgPanelInfo( m_userUnits, items );
+        footprint->GetMsgPanelInfo( this, items );
         SetMsgPanel( items );
     }
     else
diff --git a/pcbnew/netinfo.h b/pcbnew/netinfo.h
index 3c93d83e48..8a879930e3 100644
--- a/pcbnew/netinfo.h
+++ b/pcbnew/netinfo.h
@@ -241,7 +241,7 @@ public:
      *
      * @param aList is the list in which to place the  status information.
      */
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     /**
      * Function Clear
diff --git a/pcbnew/netinfo_item.cpp b/pcbnew/netinfo_item.cpp
index e9725b7dac..96b79e12ec 100644
--- a/pcbnew/netinfo_item.cpp
+++ b/pcbnew/netinfo_item.cpp
@@ -75,7 +75,7 @@ void NETINFO_ITEM::SetClass( const NETCLASSPTR& aNetClass )
 }
 
 
-void NETINFO_ITEM::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void NETINFO_ITEM::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
     wxString  txt;
     double    lengthnet = 0.0;      // This  is the length of tracks on pcb
@@ -130,14 +130,14 @@ void NETINFO_ITEM::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM
     aList.emplace_back( _( "Vias" ), txt, BLUE );
 
     // Displays the full net length (tracks on pcb + internal ICs connections ):
-    txt = MessageTextFromValue( aUnits, lengthnet + lengthPadToDie );
+    txt = MessageTextFromValue( aFrame->GetUserUnits(), lengthnet + lengthPadToDie );
     aList.emplace_back( _( "Net Length" ), txt, RED );
 
     // Displays the net length of tracks only:
-    txt = MessageTextFromValue( aUnits, lengthnet );
+    txt = MessageTextFromValue( aFrame->GetUserUnits(), lengthnet );
     aList.emplace_back( _( "On Board" ), txt, RED );
 
     // Displays the net length of internal ICs connections (wires inside ICs):
-    txt = MessageTextFromValue( aUnits, lengthPadToDie, true );
+    txt = MessageTextFromValue( aFrame->GetUserUnits(), lengthPadToDie, true );
     aList.emplace_back( _( "In Package" ), txt, RED );
 }
diff --git a/pcbnew/pcb_base_frame.cpp b/pcbnew/pcb_base_frame.cpp
index 3364f25c68..fdb4956cc6 100644
--- a/pcbnew/pcb_base_frame.cpp
+++ b/pcbnew/pcb_base_frame.cpp
@@ -187,6 +187,12 @@ void PCB_BASE_FRAME::AddModuleToBoard( MODULE* module )
 }
 
 
+EDA_ITEM* PCB_BASE_FRAME::GetItem( const KIID& aId )
+{
+    return GetBoard()->GetItem( aId );
+}
+
+
 void PCB_BASE_FRAME::FocusOnItem( BOARD_ITEM* aItem )
 {
     static KIID lastBrightenedItemID( niluuid );
diff --git a/pcbnew/pcb_draw_panel_gal.cpp b/pcbnew/pcb_draw_panel_gal.cpp
index 66fc8b1181..fb33bbf0e3 100644
--- a/pcbnew/pcb_draw_panel_gal.cpp
+++ b/pcbnew/pcb_draw_panel_gal.cpp
@@ -352,7 +352,8 @@ void PCB_DRAW_PANEL_GAL::SyncLayersVisibility( const BOARD* aBoard )
 }
 
 
-void PCB_DRAW_PANEL_GAL::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList )
+void PCB_DRAW_PANEL_GAL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
+                                          std::vector<MSG_PANEL_ITEM>& aList )
 {
     BOARD* board = static_cast<PCB_BASE_FRAME*>( m_parent )->GetBoard();
     wxString txt;
diff --git a/pcbnew/pcb_draw_panel_gal.h b/pcbnew/pcb_draw_panel_gal.h
index 556b19fb99..3b2065c5d8 100644
--- a/pcbnew/pcb_draw_panel_gal.h
+++ b/pcbnew/pcb_draw_panel_gal.h
@@ -92,7 +92,7 @@ public:
     void SyncLayersVisibility( const BOARD* aBoard );
 
     ///> @copydoc EDA_DRAW_PANEL_GAL::GetMsgPanelInfo()
-    void GetMsgPanelInfo( EDA_UNITS aUnits, std::vector<MSG_PANEL_ITEM>& aList ) override;
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
 
     ///> @copydoc EDA_DRAW_PANEL_GAL::OnShow()
     void OnShow() override;
diff --git a/pcbnew/tools/pcb_inspection_tool.cpp b/pcbnew/tools/pcb_inspection_tool.cpp
index 23e8ba2363..1fbc252662 100644
--- a/pcbnew/tools/pcb_inspection_tool.cpp
+++ b/pcbnew/tools/pcb_inspection_tool.cpp
@@ -197,7 +197,7 @@ int PCB_INSPECTION_TOOL::HighlightItem( const TOOL_EVENT& aEvent )
         if( netinfo )
         {
             MSG_PANEL_ITEMS items;
-            netinfo->GetMsgPanelInfo( m_frame->GetUserUnits(), items );
+            netinfo->GetMsgPanelInfo( m_frame, items );
             m_frame->SetMsgPanel( items );
             m_frame->SendCrossProbeNetName( netinfo->GetNetname() );
         }
diff --git a/pcbnew/tools/pcbnew_control.cpp b/pcbnew/tools/pcbnew_control.cpp
index af69e0242c..65e7c0771d 100644
--- a/pcbnew/tools/pcbnew_control.cpp
+++ b/pcbnew/tools/pcbnew_control.cpp
@@ -1087,7 +1087,7 @@ int PCBNEW_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent )
         EDA_ITEM*       item = selection.Front();
         MSG_PANEL_ITEMS msgItems;
 
-        item->GetMsgPanelInfo( m_frame->GetUserUnits(), msgItems );
+        item->GetMsgPanelInfo( m_frame, msgItems );
         m_frame->SetMsgPanel( msgItems );
     }
     else if( selection.GetSize() > 1 )
diff --git a/pcbnew/tools/pcbnew_selection.cpp b/pcbnew/tools/pcbnew_selection.cpp
index d3edc831b1..70d5e7a25d 100644
--- a/pcbnew/tools/pcbnew_selection.cpp
+++ b/pcbnew/tools/pcbnew_selection.cpp
@@ -57,18 +57,16 @@ using namespace std::placeholders;
 
 EDA_ITEM* PCBNEW_SELECTION::GetTopLeftItem( bool onlyModules ) const
 {
-    BOARD_ITEM* topLeftItem = nullptr;
-    BOARD_ITEM* currentItem;
+    EDA_ITEM* topLeftItem = nullptr;
 
     wxPoint pnt;
 
     // find the leftmost (smallest x coord) and highest (smallest y with the smallest x) item in the selection
-    for( auto item : m_items )
+    for( EDA_ITEM* item : m_items )
     {
-        currentItem = static_cast<BOARD_ITEM*>( item );
-        pnt = currentItem->GetPosition();
+        pnt = item->GetPosition();
 
-        if( ( currentItem->Type() != PCB_MODULE_T ) && onlyModules )
+        if( ( item->Type() != PCB_MODULE_T ) && onlyModules )
         {
             continue;
         }
@@ -76,18 +74,18 @@ EDA_ITEM* PCBNEW_SELECTION::GetTopLeftItem( bool onlyModules ) const
         {
             if( topLeftItem == nullptr )
             {
-                topLeftItem = currentItem;
+                topLeftItem = item;
             }
             else if( ( pnt.x < topLeftItem->GetPosition().x ) ||
                      ( ( topLeftItem->GetPosition().x == pnt.x ) &&
                      ( pnt.y < topLeftItem->GetPosition().y ) ) )
             {
-                topLeftItem = currentItem;
+                topLeftItem = item;
             }
         }
     }
 
-    return static_cast<EDA_ITEM*>( topLeftItem );
+    return topLeftItem;
 }
 
 
diff --git a/pcbnew/tools/position_relative_tool.cpp b/pcbnew/tools/position_relative_tool.cpp
index 34639ef41b..9baf9c68cb 100644
--- a/pcbnew/tools/position_relative_tool.cpp
+++ b/pcbnew/tools/position_relative_tool.cpp
@@ -94,7 +94,7 @@ int POSITION_RELATIVE_TOOL::PositionRelative( const TOOL_EVENT& aEvent )
 
 wxPoint POSITION_RELATIVE_TOOL::GetSelectionAnchorPosition() const
 {
-    return static_cast<BOARD_ITEM*>( m_selection.GetTopLeftItem() )->GetPosition();
+    return m_selection.GetTopLeftItem()->GetPosition();
 }
 
 
diff --git a/pcbnew/tracks_cleaner.cpp b/pcbnew/tracks_cleaner.cpp
index dc55f8a961..78cc33711b 100644
--- a/pcbnew/tracks_cleaner.cpp
+++ b/pcbnew/tracks_cleaner.cpp
@@ -133,8 +133,8 @@ bool TRACKS_CLEANER::removeBadTrackSegments()
         {
             if( segment->GetNetCode() != testedPad->GetNetCode() )
             {
-                DRC_ITEM* item = new DRC_ITEM();
-                item->SetData( m_units, DRCE_SHORT, segment, segment->GetPosition() );
+                DRC_ITEM* item = new DRC_ITEM( DRCE_SHORT );
+                item->SetItems( segment );
                 m_itemsList->push_back( item );
 
                 toRemove.insert( segment );
@@ -145,8 +145,8 @@ bool TRACKS_CLEANER::removeBadTrackSegments()
         {
             if( segment->GetNetCode() != testedTrack->GetNetCode() && !testedTrack->GetState( FLAG0 ) )
             {
-                DRC_ITEM* item = new DRC_ITEM();
-                item->SetData( m_units, DRCE_SHORT, segment, segment->GetPosition() );
+                DRC_ITEM* item = new DRC_ITEM( DRCE_SHORT );
+                item->SetItems( segment );
                 m_itemsList->push_back( item );
 
                 toRemove.insert( segment );
@@ -190,9 +190,8 @@ bool TRACKS_CLEANER::cleanupVias()
 
             if( ( pad->GetLayerSet() & all_cu ) == all_cu )
             {
-                DRC_ITEM* item = new DRC_ITEM();
-                item->SetData( m_units, DRCE_REDUNDANT_VIA, via1, via1->GetPosition(), pad,
-                               pad->GetPosition() );
+                DRC_ITEM* item = new DRC_ITEM( DRCE_REDUNDANT_VIA );
+                item->SetItems( via1, pad );
                 m_itemsList->push_back( item );
 
                 // redundant: delete the via
@@ -210,9 +209,8 @@ bool TRACKS_CLEANER::cleanupVias()
 
             if( via1->GetViaType() == via2->GetViaType() )
             {
-                DRC_ITEM* item = new DRC_ITEM();
-                item->SetData( m_units, DRCE_REDUNDANT_VIA, via1, via1->GetPosition(), via2,
-                               via2->GetPosition() );
+                DRC_ITEM* item = new DRC_ITEM( DRCE_REDUNDANT_VIA );
+                item->SetItems( via1, via2 );
                 m_itemsList->push_back( item );
 
                 toRemove.insert( via2 );
@@ -309,9 +307,9 @@ bool TRACKS_CLEANER::deleteDanglingTracks()
 
             if( flag_erase )
             {
-                int code = track->IsTrack() ? DRCE_DANGLING_TRACK : DRCE_DANGLING_VIA;
-                DRC_ITEM* item = new DRC_ITEM();
-                item->SetData( m_units, code, track, track->GetPosition() );
+                int errorCode = track->IsTrack() ? DRCE_DANGLING_TRACK : DRCE_DANGLING_VIA;
+                DRC_ITEM* item = new DRC_ITEM( errorCode );
+                item->SetItems( track );
                 m_itemsList->push_back( item );
 
                 if( !m_dryRun )
@@ -343,8 +341,8 @@ bool TRACKS_CLEANER::deleteNullSegments( TRACKS& aTracks )
     {
         if( segment->IsNull() && segment->Type() == PCB_TRACE_T && !segment->IsLocked() )
         {
-            DRC_ITEM* item = new DRC_ITEM();
-            item->SetData( m_units, DRCE_ZERO_LENGTH_TRACK, segment, segment->GetPosition() );
+            DRC_ITEM* item = new DRC_ITEM( DRCE_ZERO_LENGTH_TRACK );
+            item->SetItems( segment );
             m_itemsList->push_back( item );
 
             toRemove.insert( segment );
@@ -369,8 +367,8 @@ bool TRACKS_CLEANER::deleteTracksInPads()
         {
             if( pad->HitTest( track->GetStart() ) && pad->HitTest( track->GetEnd() ) )
             {
-                DRC_ITEM* item = new DRC_ITEM();
-                item->SetData( m_units, DRCE_TRACK_IN_PAD, track, track->GetPosition() );
+                DRC_ITEM* item = new DRC_ITEM( DRCE_TRACK_IN_PAD );
+                item->SetItems( track );
                 m_itemsList->push_back( item );
 
                 toRemove.insert( track );
@@ -412,8 +410,8 @@ bool TRACKS_CLEANER::cleanupSegments()
                     && track1->GetWidth() == track2->GetWidth()
                     && track1->GetLayer() == track2->GetLayer() )
             {
-                DRC_ITEM* item = new DRC_ITEM();
-                item->SetData( m_units, DRCE_DUPLICATE_TRACK, track2, track2->GetPosition() );
+                DRC_ITEM* item = new DRC_ITEM( DRCE_DUPLICATE_TRACK );
+                item->SetItems( track2 );
                 m_itemsList->push_back( item );
 
                 track2->SetFlags( IS_DELETED );
@@ -512,9 +510,8 @@ bool TRACKS_CLEANER::mergeCollinearSegments( TRACK* aSeg1, TRACK* aSeg2 )
             return false;
     }
 
-    DRC_ITEM* item = new DRC_ITEM();
-    item->SetData( m_units, DRCE_MERGE_TRACKS, aSeg1, aSeg1->GetPosition(), aSeg2,
-                   aSeg2->GetPosition() );
+    DRC_ITEM* item = new DRC_ITEM( DRCE_MERGE_TRACKS );
+    item->SetItems( aSeg1, aSeg2 );
     m_itemsList->push_back( item );
 
     aSeg2->SetFlags( IS_DELETED );
diff --git a/pcbnew/undo_redo.cpp b/pcbnew/undo_redo.cpp
index b8e4ad5c7f..6c9be7ae36 100644
--- a/pcbnew/undo_redo.cpp
+++ b/pcbnew/undo_redo.cpp
@@ -539,7 +539,7 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool
             BOARD_ITEM* item = (BOARD_ITEM*) eda_item;
             BOARD_ITEM* image = (BOARD_ITEM*) aList->GetPickedItemLink( ii );
             VECTOR2D origin = image->GetPosition();
-            image->SetPosition( item->GetPosition() );
+            image->SetPosition( eda_item->GetPosition() );
 
             if( aList->GetPickedItemStatus( ii ) == UR_DRILLORIGIN )
                 PCB_EDITOR_CONTROL::DoSetDrillOrigin( view, this, item, origin );
diff --git a/qa/eeschema/test_sch_pin.cpp b/qa/eeschema/test_sch_pin.cpp
index b986f93993..4e45b05e75 100644
--- a/qa/eeschema/test_sch_pin.cpp
+++ b/qa/eeschema/test_sch_pin.cpp
@@ -77,7 +77,7 @@ BOOST_AUTO_TEST_CASE( DefaultProperties )
     BOOST_CHECK_EQUAL( m_sch_pin.GetParentComponent(), &m_parent_comp );
     BOOST_CHECK_EQUAL( m_sch_pin.GetLibPin(), &m_lib_pin );
 
-    BOOST_CHECK_EQUAL( m_sch_pin.GetPosition(), wxPoint( 0, 0 ) );
+    BOOST_CHECK_EQUAL( m_sch_pin.GetLocalPosition(), wxPoint( 0, 0 ) );
 
     // These just forward to LIB_PIN for now, so this isn't very interesting
     // but later we will want to test these functions for SCH_PIN's own functionality
diff --git a/qa/pcbnew/drc/test_drc_courtyard_invalid.cpp b/qa/pcbnew/drc/test_drc_courtyard_invalid.cpp
index a1f0667e50..4d62e8f25a 100644
--- a/qa/pcbnew/drc/test_drc_courtyard_invalid.cpp
+++ b/qa/pcbnew/drc/test_drc_courtyard_invalid.cpp
@@ -258,7 +258,7 @@ static bool InvalidMatchesExpected( BOARD& aBoard, const MARKER_PCB& aMarker,
     const MODULE*   item_a = dynamic_cast<MODULE*>( aBoard.GetItem( reporter->GetMainItemID() ) );
 
     // This one is more than just a mis-match!
-    if( reporter->HasSecondItem() )
+    if( reporter->GetAuxItemID() != niluuid )
     {
         BOOST_WARN_MESSAGE( false, "Expected no auxiliary item for invalid courtyard DRC." );
         return false;
@@ -313,7 +313,7 @@ void DoCourtyardInvalidTest(
                 markers.push_back( std::unique_ptr<MARKER_PCB>( aMarker ) );
             } );
 
-    drc_overlap.RunDRC( EDA_UNITS::MILLIMETRES, *board );
+    drc_overlap.RunDRC( *board );
 
     CheckInvalidsMatchExpected( *board, markers, aCase.m_exp_errors );
 }
diff --git a/qa/pcbnew/drc/test_drc_courtyard_overlap.cpp b/qa/pcbnew/drc/test_drc_courtyard_overlap.cpp
index 0664eef202..7a2388f306 100644
--- a/qa/pcbnew/drc/test_drc_courtyard_overlap.cpp
+++ b/qa/pcbnew/drc/test_drc_courtyard_overlap.cpp
@@ -391,8 +391,7 @@ static std::vector<COURTYARD_OVERLAP_TEST_CASE> courtyard_cases = {
 
 
 /**
- * Check if a #MARKER_PCB is described by a particular #COURTYARD_COLLISION
- * object.
+ * Check if a #MARKER_PCB is described by a particular #COURTYARD_COLLISION object.
  */
 static bool CollisionMatchesExpected( BOARD& aBoard, const MARKER_PCB& aMarker,
                                       const COURTYARD_COLLISION& aCollision )
@@ -418,8 +417,8 @@ static bool CollisionMatchesExpected( BOARD& aBoard, const MARKER_PCB& aMarker,
 
 
 /**
- * Check that the produced markers match the expected. This does NOT
- * check ordering, as that is not part of the contract of the DRC function.
+ * Check that the produced markers match the expected. This does NOT check ordering,
+ * as that is not part of the contract of the DRC function.
  *
  * @param aMarkers    list of markers produced by the DRC
  * @param aCollisions list of expected collisions
@@ -435,15 +434,15 @@ static void CheckCollisionsMatchExpected( BOARD&        aBoard,
     }
 
     KI_TEST::CheckUnorderedMatches( aExpCollisions, aMarkers,
-            [&]( const COURTYARD_COLLISION& aColl, const std::unique_ptr<MARKER_PCB>& aMarker ) {
+            [&]( const COURTYARD_COLLISION& aColl, const std::unique_ptr<MARKER_PCB>& aMarker )
+            {
                 return CollisionMatchesExpected( aBoard, *aMarker, aColl );
             } );
 }
 
 
 /**
- * Get a #BOARD_DESIGN_SETTINGS object that will cause DRC to
- * check for courtyard overlaps
+ * Get a #BOARD_DESIGN_SETTINGS object that will cause DRC to check for courtyard overlaps
  */
 static BOARD_DESIGN_SETTINGS GetOverlapCheckDesignSettings()
 {
@@ -480,7 +479,7 @@ static void DoCourtyardOverlapTest(
                 markers.push_back( std::unique_ptr<MARKER_PCB>( aMarker ) );
             } );
 
-    drc_overlap.RunDRC( EDA_UNITS::MILLIMETRES, *board );
+    drc_overlap.RunDRC( *board );
 
     CheckCollisionsMatchExpected( *board, markers, aCase.m_collisions );
 }
diff --git a/qa/pcbnew_tools/tools/drc_tool/drc_tool.cpp b/qa/pcbnew_tools/tools/drc_tool/drc_tool.cpp
index ef457d8ad5..8487266ac9 100644
--- a/qa/pcbnew_tools/tools/drc_tool/drc_tool.cpp
+++ b/qa/pcbnew_tools/tools/drc_tool/drc_tool.cpp
@@ -39,7 +39,7 @@ using DRC_DURATION = std::chrono::microseconds;
 
 /**
  * DRC runner: provides a simple framework to run some DRC checks on #BOARDS.
- * The DRC_RUNNER can be set up as needed to instantiate a #DRC_PROVIDER to
+ * The DRC_RUNNER can be set up as needed to instantiate a #DRC_TEST_PROVIDER to
  * perform the desired DRC on the #BOARD and provide some basic information
  * about what happened.
  */
@@ -78,12 +78,12 @@ public:
                                   markers.push_back( std::unique_ptr<MARKER_PCB>( aMarker ) );
                               };
 
-        std::unique_ptr<DRC_PROVIDER> drc_prov = createDrcProvider( aBoard, marker_handler );
+        std::unique_ptr<DRC_TEST_PROVIDER> drc_prov = createDrcProvider( aBoard, marker_handler );
 
         DRC_DURATION duration;
         {
             SCOPED_PROF_COUNTER<DRC_DURATION> timer( duration );
-            drc_prov->RunDRC( EDA_UNITS::MILLIMETRES, aBoard );
+            drc_prov->RunDRC( aBoard );
         }
 
         // report results
@@ -91,7 +91,7 @@ public:
             reportDuration( duration );
 
         if( m_exec_context.m_print_markers )
-            reportMarkers( markers );
+            reportMarkers( aBoard, markers );
     }
 
 private:
@@ -105,22 +105,29 @@ private:
      */
     virtual BOARD_DESIGN_SETTINGS getDesignSettings() const = 0;
 
-    virtual std::unique_ptr<DRC_PROVIDER> createDrcProvider(
-            BOARD& aBoard, DRC_PROVIDER::MARKER_HANDLER aHandler ) = 0;
+    virtual std::unique_ptr<DRC_TEST_PROVIDER> createDrcProvider(
+            BOARD& aBoard, DRC_TEST_PROVIDER::MARKER_HANDLER aHandler ) = 0;
 
     void reportDuration( const DRC_DURATION& aDuration ) const
     {
         std::cout << "Took: " << aDuration.count() << "us" << std::endl;
     }
 
-    void reportMarkers( const std::vector<std::unique_ptr<MARKER_PCB>>& aMarkers ) const
+    void reportMarkers( BOARD& aBoard,
+                        const std::vector<std::unique_ptr<MARKER_PCB>>& aMarkers ) const
     {
+        std::map<KIID, EDA_ITEM*> itemMap;
+        aBoard.FillItemMap( itemMap );
+
         std::cout << "DRC markers: " << aMarkers.size() << std::endl;
 
         int index = 0;
 
         for( const auto& m : aMarkers )
-            std::cout << index++ << ": " << m->GetRCItem()->ShowReport( EDA_UNITS::MILLIMETRES );
+        {
+            std::cout << index++ << ": " ;
+            std::cout << m->GetRCItem()->ShowReport( EDA_UNITS::MILLIMETRES, itemMap );
+        }
 
         if( index )
             std::cout << std::endl;
@@ -159,8 +166,8 @@ private:
         return des_settings;
     }
 
-    std::unique_ptr<DRC_PROVIDER> createDrcProvider(
-            BOARD& aBoard, DRC_PROVIDER::MARKER_HANDLER aHandler ) override
+    std::unique_ptr<DRC_TEST_PROVIDER> createDrcProvider(
+            BOARD& aBoard, DRC_TEST_PROVIDER::MARKER_HANDLER aHandler ) override
     {
         return std::make_unique<DRC_COURTYARD_OVERLAP>( aHandler );
     }
@@ -196,8 +203,8 @@ private:
         return des_settings;
     }
 
-    std::unique_ptr<DRC_PROVIDER> createDrcProvider(
-            BOARD& aBoard, DRC_PROVIDER::MARKER_HANDLER aHandler ) override
+    std::unique_ptr<DRC_TEST_PROVIDER> createDrcProvider(
+            BOARD& aBoard, DRC_TEST_PROVIDER::MARKER_HANDLER aHandler ) override
     {
         return std::make_unique<DRC_COURTYARD_OVERLAP>( aHandler );
     }