diff --git a/3d-viewer/dialogs/panel_preview_3d_model.cpp b/3d-viewer/dialogs/panel_preview_3d_model.cpp
index 535cdffef1..0a11485a94 100644
--- a/3d-viewer/dialogs/panel_preview_3d_model.cpp
+++ b/3d-viewer/dialogs/panel_preview_3d_model.cpp
@@ -222,8 +222,7 @@ void PANEL_PREVIEW_3D_MODEL::loadSettings()
  */
 static double rotationFromString( const wxString& aValue )
 {
-    double rotation =
-            EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, EDA_UNITS::DEGREES, aValue );
+    double rotation = EDA_UNIT_UTILS::UI::DoubleValueFromString( unityScale, EDA_UNITS::DEGREES, aValue );
 
     if( rotation > MAX_ROTATION )
     {
@@ -251,7 +250,7 @@ wxString PANEL_PREVIEW_3D_MODEL::formatRotationValue( double aValue )
 {
     return wxString::Format( wxT( "%.2f%s" ),
                              aValue,
-                             EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( EDA_UNITS::DEGREES ) );
+                             EDA_UNIT_UTILS::GetText( EDA_UNITS::DEGREES ) );
 }
 
 
@@ -265,7 +264,7 @@ wxString PANEL_PREVIEW_3D_MODEL::formatOffsetValue( double aValue )
 
     return wxString::Format( wxT( "%.6f%s" ),
                              aValue,
-                             EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( m_userUnits ) );
+                             EDA_UNIT_UTILS::GetText( m_userUnits ) );
 }
 
 
@@ -393,7 +392,7 @@ void PANEL_PREVIEW_3D_MODEL::doIncrementRotation( wxSpinEvent& aEvent, double aS
     else if( spinCtrl == m_spinZrot )
         textCtrl = zrot;
 
-    double curr_value = EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, EDA_UNITS::DEGREES,
+    double curr_value = EDA_UNIT_UTILS::UI::DoubleValueFromString( unityScale, EDA_UNITS::DEGREES,
                                                                    textCtrl->GetValue() );
 
     curr_value += ( ROTATION_INCREMENT * aSign );
@@ -468,7 +467,7 @@ void PANEL_PREVIEW_3D_MODEL::onMouseWheelRot( wxMouseEvent& event )
     if( event.GetWheelRotation() >= 0 )
         step = -step;
 
-    double curr_value = EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, EDA_UNITS::DEGREES,
+    double curr_value = EDA_UNIT_UTILS::UI::DoubleValueFromString( unityScale, EDA_UNITS::DEGREES,
                                                                    textCtrl->GetValue() );
 
     curr_value += step;
diff --git a/common/dialogs/dialog_grid_settings.cpp b/common/dialogs/dialog_grid_settings.cpp
index 4e00f4d2ed..4d47a9b6c4 100644
--- a/common/dialogs/dialog_grid_settings.cpp
+++ b/common/dialogs/dialog_grid_settings.cpp
@@ -118,10 +118,8 @@ bool DIALOG_GRID_SETTINGS::TransferDataFromWindow()
 
     gridCfg.last_size_idx = m_currentGridCtrl->GetSelection();
     m_parent->SetGridOrigin( wxPoint( m_gridOriginX.GetValue(), m_gridOriginY.GetValue() ) );
-    gridCfg.user_grid_x = EDA_UNIT_UTILS::UI::StringFromValue( m_parent->GetIuScale(), GetUserUnits(),
-                                                               m_userGridX.GetValue(), true );
-    gridCfg.user_grid_y = EDA_UNIT_UTILS::UI::StringFromValue( m_parent->GetIuScale(), GetUserUnits(), 
-							       m_userGridY.GetValue(), true );
+    gridCfg.user_grid_x = m_parent->StringFromValue( m_userGridX.GetValue(), true );
+    gridCfg.user_grid_y = m_parent->StringFromValue( m_userGridY.GetValue(), true );
     gridCfg.fast_grid_1 = m_grid1Ctrl->GetSelection();
     gridCfg.fast_grid_2 = m_grid2Ctrl->GetSelection();
 
@@ -150,10 +148,8 @@ bool DIALOG_GRID_SETTINGS::TransferDataToWindow()
 
     m_currentGridCtrl->SetSelection( settings->m_Window.grid.last_size_idx );
 
-    m_userGridX.SetValue( EDA_UNIT_UTILS::UI::ValueFromString( m_parent->GetIuScale(), 
-							       GetUserUnits(), gridCfg.user_grid_x ) );
-    m_userGridY.SetValue( EDA_UNIT_UTILS::UI::ValueFromString( m_parent->GetIuScale(), 
-							       GetUserUnits(), gridCfg.user_grid_y ) );
+    m_userGridX.SetValue( m_parent->ValueFromString( gridCfg.user_grid_x ) );
+    m_userGridY.SetValue( m_parent->ValueFromString( gridCfg.user_grid_y ) );
 
     m_gridOriginX.SetValue( m_parent->GetGridOrigin().x );
     m_gridOriginY.SetValue( m_parent->GetGridOrigin().y );
diff --git a/common/dialogs/panel_setup_netclasses.cpp b/common/dialogs/panel_setup_netclasses.cpp
index 96632d7d53..4b35e2b87c 100644
--- a/common/dialogs/panel_setup_netclasses.cpp
+++ b/common/dialogs/panel_setup_netclasses.cpp
@@ -26,19 +26,18 @@
 #include <algorithm>
 
 #include <pgm_base.h>
-#include <base_units.h>
 #include <eda_draw_frame.h>
 #include <bitmaps.h>
 #include <netclass.h>
 #include <confirm.h>
 #include <grid_tricks.h>
 #include <dialogs/panel_setup_netclasses.h>
-#include "widgets/wx_html_report_box.h"
 #include <tool/tool_manager.h>
-#include <widgets/wx_grid.h>
 #include <string_utils.h>
 #include <widgets/grid_color_swatch_helpers.h>
 #include <widgets/grid_icon_text_helpers.h>
+#include <widgets/wx_html_report_box.h>
+#include <widgets/wx_grid.h>
 #include <wx/treebook.h>
 #include <project/net_settings.h>
 
@@ -231,14 +230,12 @@ void PANEL_SETUP_NETCLASSES::onUnitsChanged( wxCommandEvent& aEvent )
 
 bool PANEL_SETUP_NETCLASSES::TransferDataToWindow()
 {
-    EDA_UNITS units = m_frame->GetUserUnits();
-    int       row = 0;
+    int row = 0;
 
     auto setCell =
         [&]( int aRow, int aCol, int aValue )
         {
-            m_netclassGrid->SetCellValue( aRow, aCol,
-                    EDA_UNIT_UTILS::UI::StringFromValue( m_frame->GetIuScale(), units, aValue, true ) );
+            m_netclassGrid->SetCellValue( aRow, aCol, m_frame->StringFromValue( aValue, true ) );
         };
 
     auto netclassToGridRow =
@@ -336,13 +333,12 @@ bool PANEL_SETUP_NETCLASSES::TransferDataFromWindow()
     if( !Validate() )
         return false;
 
-    EDA_UNITS units = m_frame->GetUserUnits();
-    int       row = 0;
+    int row = 0;
 
     auto getCell =
-            [this, units]( int aRow, int aCol ) -> long long int
+            [this]( int aRow, int aCol ) -> long long int
             {
-                return EDA_UNIT_UTILS::UI::ValueFromString( m_frame->GetIuScale(),units, m_netclassGrid->GetCellValue( aRow, aCol ) );
+                return m_frame->ValueFromString( m_netclassGrid->GetCellValue( aRow, aCol ) );
             };
 
     auto getCellStr =
diff --git a/common/drawing_sheet/ds_draw_item.cpp b/common/drawing_sheet/ds_draw_item.cpp
index 38d1dea24c..f4db0bed03 100644
--- a/common/drawing_sheet/ds_draw_item.cpp
+++ b/common/drawing_sheet/ds_draw_item.cpp
@@ -139,19 +139,17 @@ void DS_DRAW_ITEM_BASE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
 
     aList.emplace_back( _( "First Page Option" ), msg );
 
-    msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( aFrame->GetIuScale(), EDA_UNITS::UNSCALED,
+    msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( unityScale, EDA_UNITS::UNSCALED,
                                                     dataItem->m_RepeatCount );
     aList.emplace_back( _( "Repeat Count" ), msg );
 
-    msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( aFrame->GetIuScale(), EDA_UNITS::UNSCALED,
+    msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( unityScale, EDA_UNITS::UNSCALED,
                                                     dataItem->m_IncrementLabel );
     aList.emplace_back( _( "Repeat Label Increment" ), msg );
 
     msg.Printf( wxT( "(%s, %s)" ),
-                EDA_UNIT_UTILS::UI::MessageTextFromValue( aFrame->GetIuScale(), aFrame->GetUserUnits(),
-                                      dataItem->m_IncrementVector.x ),
-                EDA_UNIT_UTILS::UI::MessageTextFromValue( aFrame->GetIuScale(), aFrame->GetUserUnits(),
-                                      dataItem->m_IncrementVector.y ) );
+                aFrame->MessageTextFromValue( dataItem->m_IncrementVector.x ),
+                aFrame->MessageTextFromValue( dataItem->m_IncrementVector.y ) );
 
     aList.emplace_back( _( "Repeat Position Increment" ), msg );
 
diff --git a/common/eda_draw_frame.cpp b/common/eda_draw_frame.cpp
index b93adf9f9d..b53af5f44e 100644
--- a/common/eda_draw_frame.cpp
+++ b/common/eda_draw_frame.cpp
@@ -576,14 +576,11 @@ void EDA_DRAW_FRAME::DisplayConstraintsMsg( const wxString& msg )
 
 void EDA_DRAW_FRAME::DisplayGridMsg()
 {
-    wxString line;
+    wxString msg;
 
-    line.Printf( "grid %s", EDA_UNIT_UTILS::UI::MessageTextFromValue(
-                                    GetIuScale(), GetUserUnits(),
-                                    GetCanvas()->GetGAL()->GetGridSize().x,
-                                    false ) );
+    msg.Printf( "grid %s", MessageTextFromValue( GetCanvas()->GetGAL()->GetGridSize().x, false ) );
 
-    SetStatusText( line, 4 );
+    SetStatusText( msg, 4 );
 }
 
 
diff --git a/common/eda_shape.cpp b/common/eda_shape.cpp
index 9ae61d8a0f..2e6ed115e8 100644
--- a/common/eda_shape.cpp
+++ b/common/eda_shape.cpp
@@ -563,7 +563,6 @@ void EDA_SHAPE::SetArcAngleAndEnd( const EDA_ANGLE& aAngle, bool aCheckNegativeA
 
 void EDA_SHAPE::ShapeGetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
-    EDA_UNITS         units = aFrame->GetUserUnits();
     ORIGIN_TRANSFORMS originTransforms = aFrame->GetOriginTransforms();
     wxString          msg;
 
@@ -573,9 +572,7 @@ void EDA_SHAPE::ShapeGetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PA
     {
     case SHAPE_T::CIRCLE:
         aList.emplace_back( shape, _( "Circle" ) );
-
-        msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( aFrame->GetIuScale(), units, GetRadius() );
-        aList.emplace_back( _( "Radius" ), msg );
+        aList.emplace_back( _( "Radius" ), aFrame->MessageTextFromValue( GetRadius() ) );
         break;
 
     case SHAPE_T::ARC:
@@ -584,15 +581,12 @@ void EDA_SHAPE::ShapeGetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PA
         msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( GetArcAngle() );
         aList.emplace_back( _( "Angle" ), msg );
 
-        msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( aFrame->GetIuScale(), units, GetRadius() );
-        aList.emplace_back( _( "Radius" ), msg );
+        aList.emplace_back( _( "Radius" ), aFrame->MessageTextFromValue( GetRadius() ) );
         break;
 
     case SHAPE_T::BEZIER:
         aList.emplace_back( shape, _( "Curve" ) );
-
-        msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( aFrame->GetIuScale(), units, GetLength() );
-        aList.emplace_back( _( "Length" ), msg );
+        aList.emplace_back( _( "Length" ), aFrame->MessageTextFromValue( GetLength() ) );
         break;
 
     case SHAPE_T::POLY:
@@ -608,22 +602,19 @@ void EDA_SHAPE::ShapeGetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PA
         else
             aList.emplace_back( shape, _( "Rectangle" ) );
 
-        msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( aFrame->GetIuScale(), units,
-                                                        std::abs( GetEnd().x - GetStart().x ) );
-        aList.emplace_back( _( "Width" ), msg );
+        aList.emplace_back( _( "Width" ),
+                            aFrame->MessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) ) );
 
-        msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( aFrame->GetIuScale(), units,
-                                                        std::abs( GetEnd().y - GetStart().y ) );
-        aList.emplace_back( _( "Height" ), msg );
+        aList.emplace_back( _( "Height" ),
+                            aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) ) );
         break;
 
     case SHAPE_T::SEGMENT:
     {
         aList.emplace_back( shape, _( "Segment" ) );
 
-        msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( aFrame->GetIuScale(), units,
-                                                        GetLineLength( GetStart(), GetEnd() ) );
-        aList.emplace_back( _( "Length" ), msg );
+        aList.emplace_back( _( "Length" ),
+                            aFrame->MessageTextFromValue( GetLineLength( GetStart(), GetEnd() ) ));
 
         // angle counter-clockwise from 3'o-clock
         EDA_ANGLE angle( atan2( (double)( GetStart().y - GetEnd().y ),
@@ -637,7 +628,7 @@ void EDA_SHAPE::ShapeGetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PA
         break;
     }
 
-    m_stroke.GetMsgPanelInfo( aFrame->GetIuScale(), units, aList );
+    m_stroke.GetMsgPanelInfo( aFrame->GetIuScale(), aFrame->GetUserUnits(), aList );
 }
 
 
diff --git a/common/eda_units.cpp b/common/eda_units.cpp
index a6e2bab2ef..942b8cb6c9 100644
--- a/common/eda_units.cpp
+++ b/common/eda_units.cpp
@@ -99,26 +99,26 @@ void EDA_UNIT_UTILS::FetchUnitsFromString( const wxString& aTextValue, EDA_UNITS
 }
 
 
-wxString EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( EDA_UNITS aUnits, EDA_DATA_TYPE aType )
+wxString EDA_UNIT_UTILS::GetText( EDA_UNITS aUnits, EDA_DATA_TYPE aType )
 {
     wxString label;
 
     switch( aUnits )
     {
-    case EDA_UNITS::MILLIMETRES: label = wxT( " mm" ); break;
-    case EDA_UNITS::DEGREES: label = wxT( "°" ); break;
-    case EDA_UNITS::MILS: label = wxT( " mils" ); break;
-    case EDA_UNITS::INCHES: label = wxT( " in" ); break;
-    case EDA_UNITS::PERCENT: label = wxT( "%" ); break;
-    case EDA_UNITS::UNSCALED: break;
-    default: UNIMPLEMENTED_FOR( "Unknown units" ); break;
+    case EDA_UNITS::MILLIMETRES: label = wxT( " mm" );   break;
+    case EDA_UNITS::DEGREES:     label = wxT( "°" );     break;
+    case EDA_UNITS::MILS:        label = wxT( " mils" ); break;
+    case EDA_UNITS::INCHES:      label = wxT( " in" );   break;
+    case EDA_UNITS::PERCENT:     label = wxT( "%" );     break;
+    case EDA_UNITS::UNSCALED:                            break;
+    default: UNIMPLEMENTED_FOR( "Unknown units" );       break;
     }
 
     switch( aType )
     {
-    case EDA_DATA_TYPE::VOLUME: label += wxT( "³" ); break;
-    case EDA_DATA_TYPE::AREA: label += wxT( "²" ); break;
-    case EDA_DATA_TYPE::DISTANCE: break;
+    case EDA_DATA_TYPE::VOLUME:   label += wxT( "³" );   break;
+    case EDA_DATA_TYPE::AREA:     label += wxT( "²" );   break;
+    case EDA_DATA_TYPE::DISTANCE:                        break;
     default: UNIMPLEMENTED_FOR( "Unknown measurement" ); break;
     }
 
@@ -126,6 +126,12 @@ wxString EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( EDA_UNITS aUnits, EDA_DATA_TY
 }
 
 
+wxString EDA_UNIT_UTILS::GetLabel( EDA_UNITS aUnits, EDA_DATA_TYPE aType )
+{
+    return GetText( aUnits, aType ).Trim( false );
+}
+
+
 std::string EDA_UNIT_UTILS::FormatAngle( const EDA_ANGLE& aAngle )
 {
     std::string temp = fmt::format( "{:.10g}", aAngle.AsDegrees() );
@@ -225,7 +231,7 @@ double EDA_UNIT_UTILS::UI::ToUserUnit( const EDA_IU_SCALE& aIuScale, EDA_UNITS a
  * in internal units, and therefore modified.
  */
 wxString EDA_UNIT_UTILS::UI::StringFromValue( const EDA_IU_SCALE& aIuScale, EDA_UNITS aUnits,
-                                              double aValue, bool aAddUnitSymbol,
+                                              double aValue, bool aAddUnitsText,
                                               EDA_DATA_TYPE aType )
 {
     double value_to_print = aValue;
@@ -263,8 +269,8 @@ wxString EDA_UNIT_UTILS::UI::StringFromValue( const EDA_IU_SCALE& aIuScale, EDA_
 
     wxString stringValue( buf, wxConvUTF8 );
 
-    if( aAddUnitSymbol )
-        stringValue += EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( aUnits, aType );
+    if( aAddUnitsText )
+        stringValue += EDA_UNIT_UTILS::GetText( aUnits, aType );
 
     return stringValue;
 }
@@ -315,7 +321,7 @@ wxString EDA_UNIT_UTILS::UI::MessageTextFromValue( EDA_ANGLE aValue, bool aAddUn
 
 // A lower-precision (for readability) version of StringFromValue()
 wxString EDA_UNIT_UTILS::UI::MessageTextFromValue( const EDA_IU_SCALE& aIuScale, EDA_UNITS aUnits,
-                                                   double aValue, bool aAddUnitLabel,
+                                                   double aValue, bool aAddUnitsText,
                                                    EDA_DATA_TYPE aType )
 {
     wxString      text;
@@ -377,8 +383,8 @@ wxString EDA_UNIT_UTILS::UI::MessageTextFromValue( const EDA_IU_SCALE& aIuScale,
 
     text.Printf( format, value );
 
-    if( aAddUnitLabel )
-        text += EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( aUnits, aType );
+    if( aAddUnitsText )
+        text += EDA_UNIT_UTILS::GetText( aUnits, aType );
 
     return text;
 }
diff --git a/common/preview_items/preview_utils.cpp b/common/preview_items/preview_utils.cpp
index fdb28e8eb6..243bf251f1 100644
--- a/common/preview_items/preview_utils.cpp
+++ b/common/preview_items/preview_utils.cpp
@@ -56,7 +56,7 @@ wxString KIGFX::PREVIEW::DimensionLabel( const wxString& prefix, double aVal,
     str << wxString::Format( fmtStr, EDA_UNIT_UTILS::UI::ToUserUnit( aIuScale, aUnits, aVal ) );
 
     if( aIncludeUnits )
-        str << EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( aUnits );
+        str << EDA_UNIT_UTILS::GetText( aUnits );
 
     return str;
 }
diff --git a/common/tool/common_tools.cpp b/common/tool/common_tools.cpp
index 5543092954..43e475d3db 100644
--- a/common/tool/common_tools.cpp
+++ b/common/tool/common_tools.cpp
@@ -54,20 +54,21 @@ void COMMON_TOOLS::Reset( RESET_REASON aReason )
     m_frame = getEditFrame<EDA_DRAW_FRAME>();
 
     GRID_SETTINGS& settings = m_toolMgr->GetSettings()->m_Window.grid;
+    EDA_IU_SCALE   scale = m_frame->GetIuScale();
 
     m_grids.clear();
 
     for( const wxString& gridDef : settings.sizes )
     {
-        int gridSize = (int) EDA_UNIT_UTILS::UI::ValueFromString( m_frame->GetIuScale(), EDA_UNITS::MILLIMETRES, gridDef );
+        int gridSize = (int) EDA_UNIT_UTILS::UI::ValueFromString( scale, EDA_UNITS::MILLIMETRES,
+                                                                  gridDef );
         m_grids.emplace_back( gridSize, gridSize );
     }
 
-    m_grids.emplace_back(
-            EDA_UNIT_UTILS::UI::ValueFromString( m_frame->GetIuScale(), EDA_UNITS::MILLIMETRES,
-                                                 settings.user_grid_x ),
-            EDA_UNIT_UTILS::UI::ValueFromString( m_frame->GetIuScale(), EDA_UNITS::MILLIMETRES,
-                                                 settings.user_grid_y ) );
+    m_grids.emplace_back( EDA_UNIT_UTILS::UI::ValueFromString( scale, EDA_UNITS::MILLIMETRES,
+                                                               settings.user_grid_x ),
+                          EDA_UNIT_UTILS::UI::ValueFromString( scale, EDA_UNITS::MILLIMETRES,
+                                                               settings.user_grid_y ) );
 
     OnGridChanged();
 }
diff --git a/common/tool/grid_menu.cpp b/common/tool/grid_menu.cpp
index 0b7f8331cd..468c735433 100644
--- a/common/tool/grid_menu.cpp
+++ b/common/tool/grid_menu.cpp
@@ -85,35 +85,33 @@ void GRID_MENU::update()
 void GRID_MENU::BuildChoiceList( wxArrayString* aGridsList, APP_SETTINGS_BASE* aCfg,
                                  EDA_DRAW_FRAME* aParent )
 {
-    wxString msg;
-
-    EDA_UNITS primaryUnit;
-    EDA_UNITS secondaryUnit;
+    wxString     msg;
+    EDA_IU_SCALE scale = aParent->GetIuScale();
+    EDA_UNITS    primaryUnit;
+    EDA_UNITS    secondaryUnit;
 
     aParent->GetUnitPair( primaryUnit, secondaryUnit );
 
     for( const wxString& gridSize : aCfg->m_Window.grid.sizes )
     {
-        int val = (int) EDA_UNIT_UTILS::UI::ValueFromString( aParent->GetIuScale(), EDA_UNITS::MILLIMETRES, gridSize );
+        int val = (int) EDA_UNIT_UTILS::UI::ValueFromString( scale, EDA_UNITS::MILLIMETRES,
+                                                             gridSize );
 
-        msg.Printf(
-                _( "Grid: %s (%s)" ),
-                EDA_UNIT_UTILS::UI::MessageTextFromValue( aParent->GetIuScale(), primaryUnit, val ),
-                EDA_UNIT_UTILS::UI::MessageTextFromValue( aParent->GetIuScale(), secondaryUnit,
-                                                          val ) );
+        msg.Printf( _( "Grid: %s (%s)" ),
+                    EDA_UNIT_UTILS::UI::MessageTextFromValue( scale, primaryUnit, val ),
+                    EDA_UNIT_UTILS::UI::MessageTextFromValue( scale, secondaryUnit, val ) );
 
         aGridsList->Add( msg );
     }
 
     if( !aCfg->m_Window.grid.user_grid_x.empty() )
     {
-        int val = (int) EDA_UNIT_UTILS::UI::ValueFromString( aParent->GetIuScale(),EDA_UNITS::INCHES,
+        int val = (int) EDA_UNIT_UTILS::UI::ValueFromString( scale, EDA_UNITS::INCHES,
                                                              aCfg->m_Window.grid.user_grid_x );
 
         msg.Printf( _( "User grid: %s (%s)" ),
-                EDA_UNIT_UTILS::UI::MessageTextFromValue( aParent->GetIuScale(), primaryUnit, val ),
-                EDA_UNIT_UTILS::UI::MessageTextFromValue( aParent->GetIuScale(), secondaryUnit,
-                                                          val ) );
+                    EDA_UNIT_UTILS::UI::MessageTextFromValue( scale, primaryUnit, val ),
+                    EDA_UNIT_UTILS::UI::MessageTextFromValue( scale, secondaryUnit, val ) );
 
         aGridsList->Add( msg );
     }
diff --git a/common/widgets/unit_binder.cpp b/common/widgets/unit_binder.cpp
index 6890440e82..a1c6ce54d1 100644
--- a/common/widgets/unit_binder.cpp
+++ b/common/widgets/unit_binder.cpp
@@ -76,8 +76,7 @@ UNIT_BINDER::UNIT_BINDER( EDA_BASE_FRAME* aParent, const EDA_IU_SCALE& aIUScale,
     }
 
     if( m_unitLabel )
-        m_unitLabel->SetLabel(
-                EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( m_units, m_dataType ).Trim( false ) );
+        m_unitLabel->SetLabel( EDA_UNIT_UTILS::GetLabel( m_units, m_dataType ) );
 
     m_valueCtrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( UNIT_BINDER::onSetFocus ),
                           nullptr, this );
@@ -105,8 +104,7 @@ void UNIT_BINDER::SetUnits( EDA_UNITS aUnits )
     m_units = aUnits;
 
     if( m_unitLabel )
-        m_unitLabel->SetLabel(
-                EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( m_units, m_dataType ).Trim( false ) );
+        m_unitLabel->SetLabel( EDA_UNIT_UTILS::GetLabel( m_units, m_dataType ) );
 }
 
 
@@ -121,8 +119,7 @@ void UNIT_BINDER::SetDataType( EDA_DATA_TYPE aDataType )
     m_dataType = aDataType;
 
     if( m_unitLabel )
-        m_unitLabel->SetLabel(
-                EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( m_units, m_dataType ).Trim( false ) );
+        m_unitLabel->SetLabel( EDA_UNIT_UTILS::GetLabel( m_units, m_dataType ) );
 }
 
 
@@ -259,7 +256,8 @@ bool UNIT_BINDER::Validate( double aMin, double aMax, EDA_UNITS aUnits )
         double val_min_iu = EDA_UNIT_UTILS::UI::FromUserUnit( m_iuScale, aUnits, aMin );
         m_errorMessage = wxString::Format( _( "%s must be at least %s." ),
                                            valueDescriptionFromLabel( m_label ),
-                                           EDA_UNIT_UTILS::UI::StringFromValue( m_iuScale, m_units, val_min_iu,  true ) );
+                                           EDA_UNIT_UTILS::UI::StringFromValue( m_iuScale, m_units,
+                                                                                val_min_iu,  true ) );
 
         textEntry->SelectAll();
 
@@ -274,7 +272,8 @@ bool UNIT_BINDER::Validate( double aMin, double aMax, EDA_UNITS aUnits )
         double val_max_iu = EDA_UNIT_UTILS::UI::FromUserUnit( m_iuScale, aUnits, aMax );
         m_errorMessage = wxString::Format( _( "%s must be less than %s." ),
                                            valueDescriptionFromLabel( m_label ),
-                                           EDA_UNIT_UTILS::UI::StringFromValue( m_iuScale, m_units, val_max_iu, true ) );
+                                           EDA_UNIT_UTILS::UI::StringFromValue( m_iuScale, m_units,
+                                                                                val_max_iu, true ) );
 
         textEntry->SelectAll();
 
@@ -290,29 +289,28 @@ bool UNIT_BINDER::Validate( double aMin, double aMax, EDA_UNITS aUnits )
 
 void UNIT_BINDER::SetValue( long long int aValue )
 {
-    double value = aValue;
-    double displayValue = m_originTransforms.ToDisplay( value, m_coordType );
+    double   displayValue = m_originTransforms.ToDisplay( aValue, m_coordType );
+    wxString textValue = EDA_UNIT_UTILS::UI::StringFromValue( m_iuScale, m_units, displayValue,
+                                                              false, m_dataType );
 
     if( displayValue == 0 && m_negativeZero )
-        SetValue( wxT( "-" ) + EDA_UNIT_UTILS::UI::StringFromValue( m_iuScale, m_units, displayValue, false, m_dataType ) );
+        SetValue( wxT( "-" ) + textValue );
     else
-        SetValue( EDA_UNIT_UTILS::UI::StringFromValue( m_iuScale, m_units, displayValue,
-                                                       false, m_dataType ) );
+        SetValue( textValue );
 }
 
 
 void UNIT_BINDER::SetDoubleValue( double aValue )
 {
-    double displayValue = m_originTransforms.ToDisplay( aValue, m_coordType );
-    displayValue = setPrecision( displayValue, false );
+    double   displayValue = m_originTransforms.ToDisplay( aValue, m_coordType );
+    wxString textValue = EDA_UNIT_UTILS::UI::StringFromValue( m_iuScale, m_units,
+                                                              setPrecision( displayValue, false ),
+                                                              false, m_dataType );
 
     if( displayValue == 0 && m_negativeZero )
-        SetValue( wxT( "-" )
-                  + EDA_UNIT_UTILS::UI::StringFromValue( m_iuScale, m_units,
-                                                         displayValue, false, m_dataType ) );
+        SetValue( wxT( "-" ) + textValue );
     else
-        SetValue( EDA_UNIT_UTILS::UI::StringFromValue( m_iuScale, m_units, displayValue,
-                                                       false, m_dataType ) );
+        SetValue( textValue );
 }
 
 
@@ -336,38 +334,35 @@ void UNIT_BINDER::SetValue( const wxString& aValue )
         m_eval.Clear();
 
     if( m_unitLabel )
-        m_unitLabel->SetLabel(
-                EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( m_units, m_dataType ).Trim( false ) );
+        m_unitLabel->SetLabel( EDA_UNIT_UTILS::GetLabel( m_units, m_dataType ) );
 }
 
 
 void UNIT_BINDER::ChangeValue( int aValue )
 {
-    double value = aValue;
-    double displayValue = m_originTransforms.ToDisplay( value, m_coordType );
+    double   displayValue = m_originTransforms.ToDisplay( aValue, m_coordType );
+    wxString textValue = EDA_UNIT_UTILS::UI::StringFromValue( m_iuScale, m_units,
+                                                              setPrecision( displayValue, false ),
+                                                              false, m_dataType );
 
     if( displayValue == 0 && m_negativeZero )
-        ChangeValue( wxT( "-" )
-                     + EDA_UNIT_UTILS::UI::StringFromValue( m_iuScale, m_units,
-                                                            displayValue, false ) );
+        ChangeValue( wxT( "-" ) + textValue );
     else
-        ChangeValue( EDA_UNIT_UTILS::UI::StringFromValue( m_iuScale, m_units,
-                                                          displayValue, false ) );
+        ChangeValue( textValue );
 }
 
 
 void UNIT_BINDER::ChangeDoubleValue( double aValue )
 {
-    double displayValue = m_originTransforms.ToDisplay( aValue, m_coordType );
-    displayValue = setPrecision( displayValue, false );
+    double   displayValue = m_originTransforms.ToDisplay( aValue, m_coordType );
+    wxString textValue = EDA_UNIT_UTILS::UI::StringFromValue( m_iuScale, m_units,
+                                                              setPrecision( displayValue, false ),
+                                                              false, m_dataType );
 
     if( displayValue == 0 && m_negativeZero )
-        ChangeValue( wxT( "-" )
-                     + EDA_UNIT_UTILS::UI::StringFromValue( m_iuScale, m_units,
-                                                            displayValue, false, m_dataType ) );
+        ChangeValue( wxT( "-" ) + textValue );
     else
-        ChangeValue( EDA_UNIT_UTILS::UI::StringFromValue( m_iuScale, m_units,
-                                                          displayValue, false, m_dataType ) );
+        ChangeValue( textValue );
 }
 
 
@@ -391,8 +386,7 @@ void UNIT_BINDER::ChangeValue( const wxString& aValue )
         m_eval.Clear();
 
     if( m_unitLabel )
-        m_unitLabel->SetLabel(
-                EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( m_units, m_dataType ).Trim( false ) );
+        m_unitLabel->SetLabel( EDA_UNIT_UTILS::GetLabel( m_units, m_dataType ) );
 }
 
 
@@ -418,7 +412,8 @@ long long int UNIT_BINDER::GetValue()
         return 0;
     }
 
-    long long int displayValue = EDA_UNIT_UTILS::UI::ValueFromString( m_iuScale, m_units, value, m_dataType );
+    long long int displayValue = EDA_UNIT_UTILS::UI::ValueFromString( m_iuScale, m_units, value,
+                                                                      m_dataType );
     return m_originTransforms.FromDisplay( displayValue, m_coordType );
 }
 
diff --git a/eeschema/dialogs/dialog_lib_edit_pin_table.cpp b/eeschema/dialogs/dialog_lib_edit_pin_table.cpp
index d5cfaf47c3..6e39294047 100644
--- a/eeschema/dialogs/dialog_lib_edit_pin_table.cpp
+++ b/eeschema/dialogs/dialog_lib_edit_pin_table.cpp
@@ -136,10 +136,10 @@ public:
 
     wxString GetValue( int aRow, int aCol ) override
     {
-        return GetValue( m_rows[ aRow ], aCol, m_frame->GetUserUnits() );
+        return GetValue( m_rows[ aRow ], aCol, m_frame );
     }
 
-    static wxString GetValue( const LIB_PINS& pins, int aCol, EDA_UNITS aUserUnits )
+    static wxString GetValue( const LIB_PINS& pins, int aCol, EDA_DRAW_FRAME* aParentFrame )
     {
         wxString fieldValue;
 
@@ -179,28 +179,23 @@ public:
                 break;
 
             case COL_NUMBER_SIZE:
-                val = EDA_UNIT_UTILS::UI::StringFromValue( schIUScale, aUserUnits,
-                                                           pin->GetNumberTextSize(), true );
+                val = aParentFrame->StringFromValue( pin->GetNumberTextSize(), true );
                 break;
 
             case COL_NAME_SIZE:
-                val = EDA_UNIT_UTILS::UI::StringFromValue( schIUScale, aUserUnits,
-                                                           pin->GetNameTextSize(), true );
+                val = aParentFrame->StringFromValue( pin->GetNameTextSize(), true );
                 break;
 
             case COL_LENGTH:
-                val = EDA_UNIT_UTILS::UI::StringFromValue( schIUScale, aUserUnits,
-                                                           pin->GetLength(), true );
+                val = aParentFrame->StringFromValue( pin->GetLength(), true );
                 break;
 
             case COL_POSX:
-                val = EDA_UNIT_UTILS::UI::StringFromValue( schIUScale, aUserUnits,
-                                                           pin->GetPosition().x, true );
+                val = aParentFrame->StringFromValue( pin->GetPosition().x, true );
                 break;
 
             case COL_POSY:
-                val = EDA_UNIT_UTILS::UI::StringFromValue( schIUScale, aUserUnits,
-                                                           -pin->GetPosition().y, true );
+                val = aParentFrame->StringFromValue( -pin->GetPosition().y, true );
                 break;
 
             case COL_VISIBLE:
@@ -259,11 +254,13 @@ public:
 
         LIB_PINS pins = m_rows[ aRow ];
 
-        // If the NUMBER column is edited and the pins are grouped, renumber, and add or remove pins based on the comma separated list of pins.
+        // If the NUMBER column is edited and the pins are grouped, renumber, and add or
+        // remove pins based on the comma separated list of pins.
         if( aCol == COL_NUMBER && m_pinTable->IsDisplayGrouped() )
         {
             wxStringTokenizer tokenizer( aValue, "," );
             size_t            i = 0;
+
             while( tokenizer.HasMoreTokens() )
             {
                 wxString pinName = tokenizer.GetNextToken();
@@ -308,10 +305,9 @@ public:
                 i++;
             }
 
-            while( i < pins.size() )
+            while( pins.size() > i )
             {
-                LIB_PIN* pin = pins.back();
-                m_pinTable->RemovePin( pin );
+                m_pinTable->RemovePin( pins.back() );
                 pins.pop_back();
             }
 
@@ -430,17 +426,17 @@ public:
     }
 
     static bool compare( const LIB_PINS& lhs, const LIB_PINS& rhs, int sortCol, bool ascending,
-                         EDA_UNITS units )
+                         EDA_DRAW_FRAME* parentFrame )
     {
-        wxString lhStr = GetValue( lhs, sortCol, units );
-        wxString rhStr = GetValue( rhs, sortCol, units );
+        wxString lhStr = GetValue( lhs, sortCol, parentFrame );
+        wxString rhStr = GetValue( rhs, sortCol, parentFrame );
 
         if( lhStr == rhStr )
         {
             // Secondary sort key is always COL_NUMBER
             sortCol = COL_NUMBER;
-            lhStr = GetValue( lhs, sortCol, units );
-            rhStr = GetValue( rhs, sortCol, units );
+            lhStr = GetValue( lhs, sortCol, parentFrame );
+            rhStr = GetValue( rhs, sortCol, parentFrame );
         }
 
         bool res;
@@ -463,14 +459,14 @@ public:
             break;
         case COL_NUMBER_SIZE:
         case COL_NAME_SIZE:
-            res = cmp( EDA_UNIT_UTILS::UI::ValueFromString( schIUScale, units, lhStr ),
-                       EDA_UNIT_UTILS::UI::ValueFromString( schIUScale, units, rhStr ) );
+            res = cmp( parentFrame->ValueFromString( lhStr ),
+                       parentFrame->ValueFromString( rhStr ) );
             break;
         case COL_LENGTH:
         case COL_POSX:
         case COL_POSY:
-            res = cmp( EDA_UNIT_UTILS::UI::ValueFromString( schIUScale, units, lhStr ),
-                       EDA_UNIT_UTILS::UI::ValueFromString( schIUScale, units, rhStr ) );
+            res = cmp( parentFrame->ValueFromString( lhStr ),
+                       parentFrame->ValueFromString( rhStr ) );
             break;
         case COL_VISIBLE:
         case COL_DEMORGAN:
@@ -578,7 +574,7 @@ public:
         std::sort( m_rows.begin(), m_rows.end(),
                    [ aSortCol, ascending, this ]( const LIB_PINS& lhs, const LIB_PINS& rhs ) -> bool
                    {
-                       return compare( lhs, rhs, aSortCol, ascending, m_frame->GetUserUnits() );
+                       return compare( lhs, rhs, aSortCol, ascending, m_frame );
                    } );
     }
 
diff --git a/eeschema/dialogs/panel_setup_formatting.cpp b/eeschema/dialogs/panel_setup_formatting.cpp
index c83a578554..d97eea1168 100644
--- a/eeschema/dialogs/panel_setup_formatting.cpp
+++ b/eeschema/dialogs/panel_setup_formatting.cpp
@@ -1,7 +1,7 @@
 /*
  * This program source code file is part of KiCad, a free EDA CAD application.
  *
- * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
+ * Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -100,20 +100,15 @@ bool PANEL_SETUP_FORMATTING::TransferDataToWindow()
     m_suffixCtrl->ChangeValue( settings.m_IntersheetRefsSuffix );
     m_listOwnPage->SetValue( settings.m_IntersheetRefsListOwnPage );
 
-    m_textOffsetRatioCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue( schIUScale, EDA_UNITS::PERCENT,
-                                                      settings.m_TextOffsetRatio * 100.0 ) );
+#define SET_VALUE( ctrl, units, value ) \
+        ctrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue( unityScale, units, value ) )
 
-    m_dashLengthCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue(
-                                                 schIUScale, EDA_UNITS::UNSCALED,
-                                                 settings.m_DashedLineDashRatio ) );
+    SET_VALUE( m_textOffsetRatioCtrl, EDA_UNITS::PERCENT, settings.m_TextOffsetRatio * 100.0 );
+    SET_VALUE( m_dashLengthCtrl, EDA_UNITS::UNSCALED, settings.m_DashedLineDashRatio );
+    SET_VALUE( m_gapLengthCtrl, EDA_UNITS::UNSCALED, settings.m_DashedLineGapRatio );
+    SET_VALUE( m_labelSizeRatioCtrl, EDA_UNITS::PERCENT, settings.m_LabelSizeRatio * 100.0 );
 
-    m_gapLengthCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue(
-                                                schIUScale, EDA_UNITS::UNSCALED,
-                                                settings.m_DashedLineGapRatio ) );
-
-    m_labelSizeRatioCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue(
-                                                     schIUScale, EDA_UNITS::PERCENT,
-                                                     settings.m_LabelSizeRatio * 100.0 ) );
+#undef SET_VALUE
 
     return true;
 }
@@ -157,21 +152,14 @@ bool PANEL_SETUP_FORMATTING::TransferDataFromWindow()
     settings.m_IntersheetRefsSuffix      = m_suffixCtrl->GetValue();
     settings.m_IntersheetRefsListOwnPage = m_listOwnPage->GetValue();
 
-    settings.m_TextOffsetRatio =
-            EDA_UNIT_UTILS::UI::DoubleValueFromString( schIUScale, EDA_UNITS::PERCENT,
-                                                       m_textOffsetRatioCtrl->GetValue() )
-            / 100.0;
+#define GET_VALUE( units, str ) EDA_UNIT_UTILS::UI::DoubleValueFromString( unityScale, units, str )
 
-    settings.m_DashedLineDashRatio = EDA_UNIT_UTILS::UI::DoubleValueFromString(
-            schIUScale, EDA_UNITS::UNSCALED, m_dashLengthCtrl->GetValue() );
+    settings.m_TextOffsetRatio = GET_VALUE( EDA_UNITS::PERCENT, m_textOffsetRatioCtrl->GetValue() ) / 100.0;
+    settings.m_DashedLineDashRatio = GET_VALUE( EDA_UNITS::UNSCALED, m_dashLengthCtrl->GetValue() );
+    settings.m_DashedLineGapRatio = GET_VALUE( EDA_UNITS::UNSCALED, m_gapLengthCtrl->GetValue() );
+    settings.m_LabelSizeRatio = GET_VALUE( EDA_UNITS::PERCENT, m_labelSizeRatioCtrl->GetValue() ) / 100.0;
 
-    settings.m_DashedLineGapRatio = EDA_UNIT_UTILS::UI::DoubleValueFromString(
-            schIUScale, EDA_UNITS::UNSCALED, m_gapLengthCtrl->GetValue() );
-
-    settings.m_LabelSizeRatio =
-            EDA_UNIT_UTILS::UI::DoubleValueFromString( schIUScale, EDA_UNITS::PERCENT,
-                                                       m_labelSizeRatioCtrl->GetValue() )
-            / 100.0;
+#undef GET_VALUE
 
     return true;
 }
@@ -190,17 +178,13 @@ void PANEL_SETUP_FORMATTING::ImportSettingsFrom( SCHEMATIC_SETTINGS& aSettings )
     m_suffixCtrl->ChangeValue( aSettings.m_IntersheetRefsSuffix );
     m_listOwnPage->SetValue( aSettings.m_IntersheetRefsListOwnPage );
 
-    wxString offsetRatio = wxString::Format( "%f", aSettings.m_TextOffsetRatio * 100.0 );
-    m_textOffsetRatioCtrl->SetValue( offsetRatio );
+#define SET_VALUE( ctrl, units, value ) \
+        ctrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue( unityScale, units, value ) )
 
-    wxString labelSizeRatio = wxString::Format( "%f", aSettings.m_LabelSizeRatio * 100.0 );
-    m_labelSizeRatioCtrl->SetValue( labelSizeRatio );
+    SET_VALUE( m_textOffsetRatioCtrl, EDA_UNITS::PERCENT, aSettings.m_TextOffsetRatio * 100.0 );
+    SET_VALUE( m_dashLengthCtrl, EDA_UNITS::UNSCALED, aSettings.m_DashedLineDashRatio );
+    SET_VALUE( m_gapLengthCtrl, EDA_UNITS::UNSCALED, aSettings.m_DashedLineGapRatio );
+    SET_VALUE( m_labelSizeRatioCtrl, EDA_UNITS::PERCENT, aSettings.m_LabelSizeRatio * 100.0 );
 
-    m_dashLengthCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue(
-                                                 schIUScale, EDA_UNITS::UNSCALED,
-                                                 aSettings.m_DashedLineDashRatio ) );
-
-    m_gapLengthCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue(
-                                                schIUScale, EDA_UNITS::UNSCALED,
-                                                aSettings.m_DashedLineGapRatio ) );
+#undef SET_VALUE
 }
diff --git a/eeschema/fields_grid_table.cpp b/eeschema/fields_grid_table.cpp
index cb7b8140ae..2dcdd04f78 100644
--- a/eeschema/fields_grid_table.cpp
+++ b/eeschema/fields_grid_table.cpp
@@ -583,7 +583,7 @@ wxString FIELDS_GRID_TABLE<T>::GetValue( int aRow, int aCol )
         return StringFromBool( field.IsBold() );
 
     case FDC_TEXT_SIZE:
-        return EDA_UNIT_UTILS::UI::StringFromValue( schIUScale, m_frame->GetUserUnits(), field.GetTextHeight(), true );
+        return m_frame->StringFromValue( field.GetTextHeight(), true );
 
     case FDC_ORIENTATION:
         if( field.GetTextAngle().IsHorizontal() )
@@ -592,12 +592,10 @@ wxString FIELDS_GRID_TABLE<T>::GetValue( int aRow, int aCol )
             return _( "Vertical" );
 
     case FDC_POSX:
-        return EDA_UNIT_UTILS::UI::StringFromValue( schIUScale, m_frame->GetUserUnits(),
-                                                    field.GetTextPos().x, true );
+        return m_frame->StringFromValue( field.GetTextPos().x, true );
 
     case FDC_POSY:
-        return EDA_UNIT_UTILS::UI::StringFromValue( schIUScale, m_frame->GetUserUnits(),
-                                                    field.GetTextPos().y, true );
+        return m_frame->StringFromValue( field.GetTextPos().y, true );
 
     case FDC_FONT:
         if( field.GetFont() )
diff --git a/eeschema/lib_field.cpp b/eeschema/lib_field.cpp
index b51e0f62d8..04aa3f896e 100644
--- a/eeschema/lib_field.cpp
+++ b/eeschema/lib_field.cpp
@@ -532,8 +532,7 @@ void LIB_FIELD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_I
 
     aList.emplace_back( _( "Style" ), GetTextStyleName() );
 
-    aList.emplace_back( _( "Text Size" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aFrame->GetUserUnits(),
-                                                                GetTextWidth() ) );
+    aList.emplace_back( _( "Text Size" ), aFrame->MessageTextFromValue( GetTextWidth() ) );
 
     switch ( GetHorizJustify() )
     {
diff --git a/eeschema/lib_pin.cpp b/eeschema/lib_pin.cpp
index 3928c66c31..2fa14ab437 100644
--- a/eeschema/lib_pin.cpp
+++ b/eeschema/lib_pin.cpp
@@ -1141,8 +1141,6 @@ void LIB_PIN::Plot( PLOTTER* aPlotter, bool aBackground, const VECTOR2I& aOffset
 
 void LIB_PIN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
-    EDA_UNITS units = aFrame->GetUserUnits();
-
     LIB_ITEM::GetMsgPanelInfo( aFrame, aList );
 
     aList.emplace_back( _( "Name" ), UnescapeString( GetShownName() ) );
@@ -1153,7 +1151,7 @@ void LIB_PIN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITE
     aList.emplace_back( _( "Style" ), IsVisible() ? _( "Yes" ) : _( "No" ) );
 
     // Display pin length
-    aList.emplace_back( _( "Length" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, units, m_length, true ) );
+    aList.emplace_back( _( "Length" ), aFrame->MessageTextFromValue( m_length, true ) );
 
     int i = PinOrientationIndex( m_orientation );
     aList.emplace_back( _( "Orientation" ), PinOrientationName( (unsigned) i ) );
@@ -1161,8 +1159,8 @@ void LIB_PIN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITE
     VECTOR2I pinpos = GetPosition();
     pinpos.y = -pinpos.y;   // Display coords are top to bottom; lib item coords are bottom to top
 
-    aList.emplace_back( _( "Pos X" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, units, pinpos.x, true ) );
-    aList.emplace_back( _( "Pos Y" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, units, pinpos.y, true ) );
+    aList.emplace_back( _( "Pos X" ), aFrame->MessageTextFromValue( pinpos.x, true ) );
+    aList.emplace_back( _( "Pos Y" ), aFrame->MessageTextFromValue( pinpos.y, true ) );
 }
 
 
diff --git a/eeschema/lib_text.cpp b/eeschema/lib_text.cpp
index 382fdb9d40..0cf1ef1543 100644
--- a/eeschema/lib_text.cpp
+++ b/eeschema/lib_text.cpp
@@ -391,8 +391,7 @@ void LIB_TEXT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_IT
 
     aList.emplace_back( _( "Style" ), GetTextStyleName() );
 
-    aList.emplace_back( _( "Text Size" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aFrame->GetUserUnits(),
-                                                                GetTextWidth() ) );
+    aList.emplace_back( _( "Text Size" ), aFrame->MessageTextFromValue( GetTextWidth() ) );
 
     switch ( GetHorizJustify() )
     {
diff --git a/eeschema/lib_textbox.cpp b/eeschema/lib_textbox.cpp
index 1c14428d87..2887ea4f4d 100644
--- a/eeschema/lib_textbox.cpp
+++ b/eeschema/lib_textbox.cpp
@@ -447,8 +447,6 @@ void LIB_TEXTBOX::Plot( PLOTTER* aPlotter, bool aBackground, const VECTOR2I& aOf
 
 void LIB_TEXTBOX::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
-    EDA_UNITS units = aFrame->GetUserUnits();
-
     // Don't use GetShownText() here; we want to show the user the variable references
     aList.emplace_back( _( "Text Box" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
 
@@ -458,15 +456,15 @@ void LIB_TEXTBOX::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL
     int style = IsBold() && IsItalic() ? 3 : IsBold() ? 2 : IsItalic() ? 1 : 0;
     aList.emplace_back( _( "Style" ), textStyle[style] );
 
-    aList.emplace_back( _( "Text Size" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, units, GetTextWidth() ) );
+    aList.emplace_back( _( "Text Size" ), aFrame->MessageTextFromValue( GetTextWidth() ) );
 
-    wxString msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, units, std::abs( GetEnd().x - GetStart().x ) );
+    wxString msg = aFrame->MessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) );
     aList.emplace_back( _( "Box Width" ), msg );
 
-    msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, units, std::abs( GetEnd().y - GetStart().y ) );
+    msg = aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) );
     aList.emplace_back( _( "Box Height" ), msg );
 
-    m_stroke.GetMsgPanelInfo( schIUScale, units, aList );
+    m_stroke.GetMsgPanelInfo( schIUScale, aFrame->GetUserUnits(), aList );
 }
 
 
diff --git a/eeschema/sch_base_frame.cpp b/eeschema/sch_base_frame.cpp
index 6de50bffcb..159cd57b07 100644
--- a/eeschema/sch_base_frame.cpp
+++ b/eeschema/sch_base_frame.cpp
@@ -184,16 +184,14 @@ void SCH_BASE_FRAME::UpdateStatusBar()
     VECTOR2D d         = cursorPos - screen->m_LocalOrigin;
 
     line.Printf( "X %s  Y %s",
-                 EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(),
-                                                           cursorPos.x, false ),
-                 EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(), cursorPos.y, false ) );
+                 MessageTextFromValue( cursorPos.x, false ),
+                 MessageTextFromValue( cursorPos.y, false ) );
     SetStatusText( line, 2 );
 
     line.Printf( "dx %s  dy %s  dist %s",
-                 EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(), d.x, false ),
-                 EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(), d.y, false ),
-                 EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(),
-                                                              hypot( d.x, d.y ), false ) );
+                 MessageTextFromValue( d.x, false ),
+                 MessageTextFromValue( d.y, false ),
+                 MessageTextFromValue( hypot( d.x, d.y ), false ) );
     SetStatusText( line, 3 );
 
     DisplayGridMsg();
diff --git a/eeschema/sch_bitmap.cpp b/eeschema/sch_bitmap.cpp
index aaf94307a8..21b60b18df 100644
--- a/eeschema/sch_bitmap.cpp
+++ b/eeschema/sch_bitmap.cpp
@@ -204,8 +204,8 @@ void SCH_BITMAP::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_
 {
     aList.emplace_back( _( "Bitmap" ), wxEmptyString );
 
-    aList.emplace_back( _( "Width" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aFrame->GetUserUnits(), GetSize().x ) );
-    aList.emplace_back( _( "Height" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aFrame->GetUserUnits(), GetSize().y ) );
+    aList.emplace_back( _( "Width" ), aFrame->MessageTextFromValue( GetSize().x ) );
+    aList.emplace_back( _( "Height" ), aFrame->MessageTextFromValue( GetSize().y ) );
 }
 
 
diff --git a/eeschema/sch_field.cpp b/eeschema/sch_field.cpp
index 208f13d670..fe8bca3f35 100644
--- a/eeschema/sch_field.cpp
+++ b/eeschema/sch_field.cpp
@@ -725,8 +725,7 @@ void SCH_FIELD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_I
 
     aList.emplace_back( _( "Style" ), GetTextStyleName() );
 
-    aList.emplace_back( _( "Text Size" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aFrame->GetUserUnits(),
-                                                                GetTextWidth() ) );
+    aList.emplace_back( _( "Text Size" ), aFrame->MessageTextFromValue( GetTextWidth() ) );
 
     switch ( GetHorizJustify() )
     {
diff --git a/eeschema/sch_label.cpp b/eeschema/sch_label.cpp
index 41b6bc2501..152088d7ed 100644
--- a/eeschema/sch_label.cpp
+++ b/eeschema/sch_label.cpp
@@ -853,8 +853,7 @@ void SCH_LABEL_BASE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PA
     int style = IsBold() && IsItalic() ? 3 : IsBold() ? 2 : IsItalic() ? 1 : 0;
     aList.emplace_back( _( "Style" ), textStyle[style] );
 
-    aList.emplace_back( _( "Text Size" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aFrame->GetUserUnits(),
-                                                                GetTextWidth() ) );
+    aList.emplace_back( _( "Text Size" ), aFrame->MessageTextFromValue( GetTextWidth() ) );
 
     switch( GetTextSpinStyle() )
     {
diff --git a/eeschema/sch_plugins/altium/sch_altium_plugin.cpp b/eeschema/sch_plugins/altium/sch_altium_plugin.cpp
index f1deca65e1..d6f0f55833 100644
--- a/eeschema/sch_plugins/altium/sch_altium_plugin.cpp
+++ b/eeschema/sch_plugins/altium/sch_altium_plugin.cpp
@@ -1429,29 +1429,30 @@ void SCH_ALTIUM_PLUGIN::ParseEllipse( const std::map<wxString, wxString>& aPrope
     // To do: Import true ellipses when KiCad supports them
     if( elem.Radius != elem.SecondaryRadius )
     {
-        m_reporter->Report(
-                wxString::Format( _( "Unsupported ellipse was not imported at (X = %d; Y = %d)." ),
-                                  ( elem.Center + m_sheetOffset ).x, ( elem.Center + m_sheetOffset ).y ),
-                RPT_SEVERITY_ERROR );
+        m_reporter->Report( wxString::Format( _( "Unsupported ellipse was not imported at "
+                                                 "(X = %d; Y = %d)." ),
+                                              ( elem.Center + m_sheetOffset ).x,
+                                              ( elem.Center + m_sheetOffset ).y ),
+                            RPT_SEVERITY_ERROR );
         return;
     }
 
     if( elem.OwnerPartID == ALTIUM_COMPONENT_NONE )
     {
-            SCH_SHAPE* circle = new SCH_SHAPE( SHAPE_T::CIRCLE );
+        SCH_SHAPE* circle = new SCH_SHAPE( SHAPE_T::CIRCLE );
 
-            circle->SetPosition( elem.Center + m_sheetOffset );
-            circle->SetEnd( circle->GetPosition() + VECTOR2I( elem.Radius, 0 ) );
-            circle->SetStroke( STROKE_PARAMS( 0.1, PLOT_DASH_TYPE::SOLID ) );
+        circle->SetPosition( elem.Center + m_sheetOffset );
+        circle->SetEnd( circle->GetPosition() + VECTOR2I( elem.Radius, 0 ) );
+        circle->SetStroke( STROKE_PARAMS( 1, PLOT_DASH_TYPE::SOLID ) );
 
-            circle->SetFillColor( GetColorFromInt( elem.AreaColor ) );
+        circle->SetFillColor( GetColorFromInt( elem.AreaColor ) );
 
-            if( elem.IsSolid )
-                circle->SetFillMode( FILL_T::FILLED_WITH_COLOR );
-            else
-                circle->SetFilled( false );
+        if( elem.IsSolid )
+            circle->SetFillMode( FILL_T::FILLED_WITH_COLOR );
+        else
+            circle->SetFilled( false );
 
-            m_currentSheet->GetScreen()->Append( circle );
+        m_currentSheet->GetScreen()->Append( circle );
     }
     else
     {
@@ -1460,9 +1461,9 @@ void SCH_ALTIUM_PLUGIN::ParseEllipse( const std::map<wxString, wxString>& aPrope
         if( libSymbolIt == m_libSymbols.end() )
         {
             // TODO: e.g. can depend on Template (RECORD=39
-            m_reporter->Report(
-                    wxString::Format( wxT( "Ellipse's owner (%d) not found." ), elem.OwnerIndex ),
-                    RPT_SEVERITY_DEBUG );
+            m_reporter->Report( wxString::Format( wxT( "Ellipse's owner (%d) not found." ),
+                                                  elem.OwnerIndex ),
+                                RPT_SEVERITY_DEBUG );
             return;
         }
 
@@ -1475,7 +1476,7 @@ void SCH_ALTIUM_PLUGIN::ParseEllipse( const std::map<wxString, wxString>& aPrope
 
         circle->SetPosition( GetRelativePosition( elem.Center + m_sheetOffset, symbol ) );
         circle->SetEnd( circle->GetPosition() + VECTOR2I( elem.Radius, 0 ) );
-        circle->SetStroke( STROKE_PARAMS( 0.1, PLOT_DASH_TYPE::SOLID ) );
+        circle->SetStroke( STROKE_PARAMS( 1, PLOT_DASH_TYPE::SOLID ) );
 
         circle->SetFillColor( GetColorFromInt( elem.AreaColor ) );
 
diff --git a/eeschema/sch_text.cpp b/eeschema/sch_text.cpp
index 26dd0d1890..2bc616b685 100644
--- a/eeschema/sch_text.cpp
+++ b/eeschema/sch_text.cpp
@@ -498,8 +498,7 @@ void SCH_TEXT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_IT
     int style = IsBold() && IsItalic() ? 3 : IsBold() ? 2 : IsItalic() ? 1 : 0;
     aList.emplace_back( _( "Style" ), textStyle[style] );
 
-    aList.emplace_back( _( "Text Size" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aFrame->GetUserUnits(),
-                                                                GetTextWidth() ) );
+    aList.emplace_back( _( "Text Size" ), aFrame->MessageTextFromValue( GetTextWidth() ) );
 
     switch( GetTextSpinStyle() )
     {
diff --git a/eeschema/symbol_checker.cpp b/eeschema/symbol_checker.cpp
index dd07f27441..a58bdc2dc0 100644
--- a/eeschema/symbol_checker.cpp
+++ b/eeschema/symbol_checker.cpp
@@ -23,8 +23,7 @@
 
 #include <vector>
 #include <sch_symbol.h>
-#include <base_units.h>
-#include <math/util.h>      // for KiROUND
+#include <eda_draw_frame.h>
 
 // helper function to sort pins by pin num
 static bool sort_by_pin_number( const LIB_PIN* ref, const LIB_PIN* tst );
@@ -40,10 +39,10 @@ static bool sort_by_pin_number( const LIB_PIN* ref, const LIB_PIN* tst );
  * @param aMessages is a room to store error messages
  * @param aGridForPins (in IU) is the grid to test pin positions ( >= 25 mils )
  * should be 25, 50 or 100 mils (convered to IUs)
- * @param aDisplayUnits is the unit to display coordinates in messages
+ * @param aUnitsProvider a frame to format coordinates in messages
  */
 void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
-                    int aGridForPins, EDA_UNITS aDisplayUnits )
+                    int aGridForPins, EDA_DRAW_FRAME* aUnitsProvider )
 {
     if( !aSymbol )
         return;
@@ -116,12 +115,12 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
                                " of converted." ),
                             next->GetNumber(),
                             nextName,
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, next->GetPosition().x ),
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, -next->GetPosition().y ),
+                            aUnitsProvider->MessageTextFromValue( next->GetPosition().x ),
+                            aUnitsProvider->MessageTextFromValue( -next->GetPosition().y ),
                             pin->GetNumber(),
                             pin->GetName(),
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, pin->GetPosition().x ),
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, -pin->GetPosition().y ) );
+                            aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
+                            aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ) );
             }
             else
             {
@@ -130,12 +129,12 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
                                " in units %s and %s of converted." ),
                             next->GetNumber(),
                             nextName,
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, next->GetPosition().x ),
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, -next->GetPosition().y ),
+                            aUnitsProvider->MessageTextFromValue( next->GetPosition().x ),
+                            aUnitsProvider->MessageTextFromValue( -next->GetPosition().y ),
                             pin->GetNumber(),
                             pinName,
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, pin->GetPosition().x ),
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, -pin->GetPosition().y ),
+                            aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
+                            aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
                             aSymbol->GetUnitReference( next->GetUnit() ),
                             aSymbol->GetUnitReference( pin->GetUnit() ) );
             }
@@ -148,12 +147,12 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
                                " conflicts with pin %s%s at location <b>(%s, %s)</b>." ),
                             next->GetNumber(),
                             nextName,
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, next->GetPosition().x ),
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, -next->GetPosition().y ),
+                            aUnitsProvider->MessageTextFromValue( next->GetPosition().x ),
+                            aUnitsProvider->MessageTextFromValue( -next->GetPosition().y ),
                             pin->GetNumber(),
                             pinName,
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, pin->GetPosition().x ),
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, -pin->GetPosition().y ) );
+                            aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
+                            aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ) );
             }
             else
             {
@@ -162,12 +161,12 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
                                " in units %s and %s." ),
                             next->GetNumber(),
                             nextName,
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, next->GetPosition().x ),
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, -next->GetPosition().y ),
+                            aUnitsProvider->MessageTextFromValue( next->GetPosition().x ),
+                            aUnitsProvider->MessageTextFromValue( -next->GetPosition().y ),
                             pin->GetNumber(),
                             pinName,
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, pin->GetPosition().x ),
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, -pin->GetPosition().y ),
+                            aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
+                            aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
                             aSymbol->GetUnitReference( next->GetUnit() ),
                             aSymbol->GetUnitReference( pin->GetUnit() ) );
             }
@@ -242,8 +241,8 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
                                    " of converted." ),
                                 pin->GetNumber(),
                                 pinName,
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, pin->GetPosition().x ),
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, -pin->GetPosition().y ) );
+                                aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
+                                aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ) );
                 }
                 else
                 {
@@ -251,8 +250,8 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
                                    " in unit %c of converted." ),
                                 pin->GetNumber(),
                                 pinName,
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, pin->GetPosition().x ),
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, -pin->GetPosition().y ),
+                                aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
+                                aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
                                 'A' + pin->GetUnit() - 1 );
                 }
             }
@@ -263,8 +262,8 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
                     msg.Printf( _( "Info: <b>Hidden power pin %s</b> %s at location <b>(%s, %s)</b>." ),
                                 pin->GetNumber(),
                                 pinName,
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, pin->GetPosition().x ),
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, -pin->GetPosition().y ) );
+                                aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
+                                aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ) );
                 }
                 else
                 {
@@ -272,8 +271,8 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
                                    " in unit %c." ),
                                 pin->GetNumber(),
                                 pinName,
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, pin->GetPosition().x ),
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, -pin->GetPosition().y ),
+                                aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
+                                aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
                                 'A' + pin->GetUnit() - 1 );
                 }
             }
@@ -296,8 +295,8 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
                                    " of converted." ),
                                 pin->GetNumber(),
                                 pinName,
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, pin->GetPosition().x ),
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, -pin->GetPosition().y ) );
+                                aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
+                                aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ) );
                 }
                 else
                 {
@@ -305,8 +304,8 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
                                    " in unit %c of converted." ),
                                 pin->GetNumber(),
                                 pinName,
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, pin->GetPosition().x ),
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, -pin->GetPosition().y ),
+                                aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
+                                aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
                                 'A' + pin->GetUnit() - 1 );
                 }
             }
@@ -317,8 +316,8 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
                     msg.Printf( _( "<b>Off grid pin %s</b> %s at location <b>(%s, %s)</b>." ),
                                 pin->GetNumber(),
                                 pinName,
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, pin->GetPosition().x ),
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, -pin->GetPosition().y ) );
+                                aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
+                                aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ) );
                 }
                 else
                 {
@@ -326,8 +325,8 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
                                    " in unit %c." ),
                                 pin->GetNumber(),
                                 pinName,
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, pin->GetPosition().x ),
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( schIUScale, aDisplayUnits, -pin->GetPosition().y ),
+                                aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
+                                aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
                                 'A' + pin->GetUnit() - 1 );
                 }
             }
diff --git a/eeschema/tools/ee_inspection_tool.cpp b/eeschema/tools/ee_inspection_tool.cpp
index 06660931c4..21f537d1aa 100644
--- a/eeschema/tools/ee_inspection_tool.cpp
+++ b/eeschema/tools/ee_inspection_tool.cpp
@@ -203,7 +203,7 @@ int EE_INSPECTION_TOOL::ExcludeMarker( const TOOL_EVENT& aEvent )
 
 
 extern void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
-                           int aGridForPins, EDA_UNITS aDisplayUnits );
+                           int aGridForPins, EDA_DRAW_FRAME* aUnitsProvider );
 
 int EE_INSPECTION_TOOL::CheckSymbol( const TOOL_EVENT& aEvent )
 {
@@ -216,7 +216,7 @@ int EE_INSPECTION_TOOL::CheckSymbol( const TOOL_EVENT& aEvent )
     std::vector<wxString> messages;
     const int grid_size = KiROUND( getView()->GetGAL()->GetGridSize().x );
 
-    CheckLibSymbol( symbol, messages, grid_size, units );
+    CheckLibSymbol( symbol, messages, grid_size, m_frame );
 
     if( messages.empty() )
     {
diff --git a/gerbview/gerber_file_image.cpp b/gerbview/gerber_file_image.cpp
index 8da2701a07..43acd2970f 100644
--- a/gerbview/gerber_file_image.cpp
+++ b/gerbview/gerber_file_image.cpp
@@ -346,10 +346,8 @@ void GERBER_FILE_IMAGE::DisplayImageInfo(  GERBVIEW_FRAME* aMainFrame  )
     aMainFrame->AppendMsgPanel( _( "Y Justify" ), msg );
 
     msg.Printf( wxT( "X=%s Y=%s" ),
-                EDA_UNIT_UTILS::UI::MessageTextFromValue( gerbIUScale, aMainFrame->GetUserUnits(),
-                                                          m_ImageJustifyOffset.x ),
-                EDA_UNIT_UTILS::UI::MessageTextFromValue( gerbIUScale, aMainFrame->GetUserUnits(),
-                                                          m_ImageJustifyOffset.y ) );
+                aMainFrame->MessageTextFromValue( m_ImageJustifyOffset.x ),
+                aMainFrame->MessageTextFromValue( m_ImageJustifyOffset.y ) );
 
     aMainFrame->AppendMsgPanel( _( "Image Justify Offset" ), msg );
 }
diff --git a/gerbview/gerbview_frame.cpp b/gerbview/gerbview_frame.cpp
index ae923dc86c..d9b3160408 100644
--- a/gerbview/gerbview_frame.cpp
+++ b/gerbview/gerbview_frame.cpp
@@ -782,15 +782,6 @@ void GERBVIEW_FRAME::SetVisibleElementColor( int aLayerID, const COLOR4D& aColor
 }
 
 
-COLOR4D GERBVIEW_FRAME::GetNegativeItemsColor()
-{
-    if( gvconfig()->m_Appearance.show_negative_objects )
-        return GetVisibleElementColor( LAYER_NEGATIVE_OBJECTS );
-    else
-        return GetDrawBgColor();
-}
-
-
 COLOR4D GERBVIEW_FRAME::GetLayerColor( int aLayer ) const
 {
     return GetColorSettings()->GetColor( aLayer );
@@ -900,10 +891,8 @@ void GERBVIEW_FRAME::DisplayGridMsg()
     wxString line;
 
     line.Printf( wxT( "grid X %s  Y %s" ),
-                 EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), m_userUnits, gridSize.x,
-                                                           false ),
-                 EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), m_userUnits, gridSize.y,
-                                                           false ) );
+                 MessageTextFromValue( gridSize.x, false ),
+                 MessageTextFromValue( gridSize.y, false ) );
 
     SetStatusText( line, 4 );
     SetStatusText( line, 4 );
@@ -927,18 +916,16 @@ void GERBVIEW_FRAME::UpdateStatusBar()
         double    ro = hypot( v.x, v.y );
 
         line.Printf( wxT( "r %s  theta %s" ),
-                     EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(), ro, false ),
-                     EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), EDA_UNITS::DEGREES, theta.AsDegrees(), false ) );
+                     MessageTextFromValue( ro, false ),
+                     MessageTextFromValue( theta, false ) );
 
         SetStatusText( line, 3 );
     }
 
     // Display absolute coordinates:
     line.Printf( wxT( "X %s  Y %s" ),
-                 EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(),
-                                                           cursorPos.x, false ),
-                 EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(),
-                                                           cursorPos.y, false ) );
+                 MessageTextFromValue( cursorPos.x, false ),
+                 MessageTextFromValue( cursorPos.y, false ) );
     SetStatusText( line, 2 );
 
     if( !GetShowPolarCoords() )
@@ -948,12 +935,9 @@ void GERBVIEW_FRAME::UpdateStatusBar()
         double dYpos = cursorPos.y - GetScreen()->m_LocalOrigin.y;
 
         line.Printf( wxT( "dx %s  dy %s  dist %s" ),
-                     EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(), dXpos,
-                                                               false ),
-                     EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(), dYpos,
-                                                               false ),
-                     EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(),
-                                                               hypot( dXpos, dYpos ), false ) );
+                     MessageTextFromValue( dXpos, false ),
+                     MessageTextFromValue( dYpos,false ),
+                     MessageTextFromValue( hypot( dXpos, dYpos ), false ) );
         SetStatusText( line, 3 );
     }
 
diff --git a/gerbview/gerbview_frame.h b/gerbview/gerbview_frame.h
index 63683adb1a..290a80cb08 100644
--- a/gerbview/gerbview_frame.h
+++ b/gerbview/gerbview_frame.h
@@ -164,14 +164,6 @@ public:
     COLOR4D GetLayerColor( int aLayer ) const;
     void SetLayerColor( int aLayer, const COLOR4D& aColor );
 
-    /**
-     * This is usually the background color, but can be another color in order to see
-     * negative objects.
-     *
-     * @return the color of negative items.
-     */
-    COLOR4D GetNegativeItemsColor();
-
     /**
      * Change out all the layers in m_Layers; called upon loading new gerber files.
      */
diff --git a/include/base_units.h b/include/base_units.h
index bc07e6676d..37dfc4fff3 100644
--- a/include/base_units.h
+++ b/include/base_units.h
@@ -109,6 +109,7 @@ constexpr EDA_IU_SCALE gerbIUScale = EDA_IU_SCALE( GERB_IU_PER_MM );
 constexpr EDA_IU_SCALE pcbIUScale = EDA_IU_SCALE( PCB_IU_PER_MM );
 constexpr EDA_IU_SCALE drawSheetIUScale = EDA_IU_SCALE( PL_IU_PER_MM );
 constexpr EDA_IU_SCALE schIUScale = EDA_IU_SCALE( SCH_IU_PER_MM );
+constexpr EDA_IU_SCALE unityScale = EDA_IU_SCALE( 1 );
 
 #ifndef SWIG
 // The max error is the distance between the middle of a segment, and the circle
diff --git a/include/eda_draw_frame.h b/include/eda_draw_frame.h
index 897e1cbb79..047b49a665 100644
--- a/include/eda_draw_frame.h
+++ b/include/eda_draw_frame.h
@@ -452,6 +452,65 @@ public:
 
     const EDA_IU_SCALE& GetIuScale() const { return m_iuScale; }
 
+    /**
+     * Converts \a aValue in internal units into a united string.
+     *
+     * For readability, trailing 0s are removed if the mantissa has 3 or more digits.
+     * This function should be used to display values in dialogs because a value entered in mm
+     * (for instance 2.0 mm) could need up to 8 digits mantissa if displayed in inch to avoid
+     * truncation or rounding made just by the printf function.
+     *
+     * @param aValue = value in internal units
+     * @param aAddUnitLabel = true to add symbol unit to the string value
+     * @return A wxString object containing value and optionally the symbol unit (like 2.000 mm)
+     */
+    wxString StringFromValue( double aValue, bool aAddUnitLabel = false,
+                              EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE )
+    {
+        return EDA_UNIT_UTILS::UI::StringFromValue( GetIuScale(), GetUserUnits(), aValue,
+                                                    aAddUnitLabel, aType );
+    }
+
+    wxString StringFromValue( const EDA_ANGLE& aValue, bool aAddUnitLabel = false )
+    {
+        return EDA_UNIT_UTILS::UI::StringFromValue( unityScale, EDA_UNITS::DEGREES,
+                                                    aValue.AsDegrees(), aAddUnitLabel,
+                                                    EDA_DATA_TYPE::DISTANCE );
+    }
+
+    /**
+     * A lower-precision version of StringFromValue().
+     *
+     * Should ONLY be used for status text and messages.  Not suitable for dialogs, files, etc.
+     * where the loss of precision matters.
+     */
+    wxString MessageTextFromValue( double aValue, bool aAddUnitLabel = true,
+                                   EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE )
+    {
+        return EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(), aValue,
+                                                         aAddUnitLabel, aType );
+    }
+
+    wxString MessageTextFromValue( const EDA_ANGLE& aValue, bool aAddUnitLabel = true )
+    {
+        return EDA_UNIT_UTILS::UI::MessageTextFromValue( unityScale, EDA_UNITS::DEGREES,
+                                                         aValue.AsDegrees() );
+    }
+
+    /**
+     * Converts \a aTextValue in \a aUnits to internal units used by the frame.
+     * @warning This utilizes the current locale and will break if decimal formats differ
+     *
+     * @param aTextValue A reference to a wxString object containing the string to convert.
+     * @return internal units value
+     */
+    long long int ValueFromString( const wxString& aTextValue,
+                                   EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE )
+    {
+        return EDA_UNIT_UTILS::UI::ValueFromString( GetIuScale(), GetUserUnits(), aTextValue,
+                                                    aType );
+    }
+
     DECLARE_EVENT_TABLE()
 
 protected:
diff --git a/include/eda_units.h b/include/eda_units.h
index 8284141b5e..1093478a94 100644
--- a/include/eda_units.h
+++ b/include/eda_units.h
@@ -1,7 +1,7 @@
 /*
  * This program source code file is part of KiCad, a free EDA CAD application.
  *
- * Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
+ * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -73,11 +73,24 @@ namespace EDA_UNIT_UTILS
     /**
      * Get the units string for a given units type.
      *
-     * @param aUnits - The units requested.
-     * @param aType - The data type of the unit (e.g. distance, area, etc.)
+     * This version is for appending to a value string.
+     *
+     * @param aUnits The units requested.
+     * @param aType DISTANCE, AREA, or VOLUME
+     * @return The human readable units string with appropriate separators.
+     */
+    wxString GetText( EDA_UNITS aUnits, EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE );
+
+    /**
+     * Get the units string for a given units type.
+     *
+     * This version is for setting a wxStaticText label.
+     *
+     * @param aUnits The units requested.
+     * @param aType DISTANCE, AREA, or VOLUME
      * @return The human readable units string.
      */
-    wxString GetAbbreviatedUnitsLabel( EDA_UNITS aUnit, EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE );
+    wxString GetLabel( EDA_UNITS aUnits, EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE );
 
     /**
      * Converts \a aAngle from board units to a string appropriate for writing to file.
@@ -92,8 +105,7 @@ namespace EDA_UNIT_UTILS
     std::string FormatAngle( const EDA_ANGLE& aAngle );
 
     /**
-     * Converts \a aValue from internal units to a string appropriate for writing
-     * to file.
+     * Converts \a aValue from internal units to a string appropriate for writing to file.
      *
      * This should only be used for writing to files as it ignores locale
      *
@@ -127,64 +139,53 @@ namespace EDA_UNIT_UTILS
         double ToUserUnit( const EDA_IU_SCALE& aIuScale, EDA_UNITS aUnit, double aValue );
 
         /**
-         * Function StringFromValue
-         * returns the string from \a aValue according to units (inch, mm ...) for display,
-         * and the initial unit for value.
+         * Returns the string from \a aValue according to \a aUnits (inch, mm ...) for display.
          *
-         * For readability, the mantissa has 3 or more digits (max 8 digits),
-         * the trailing 0 are removed if the mantissa has more than 3 digits
-         * and some trailing 0
-         * This function should be used to display values in dialogs because a value
-         * entered in mm (for instance 2.0 mm) could need up to 8 digits mantissa
-         * if displayed in inch to avoid truncation or rounding made just by the printf function.
-         * otherwise the actual value is rounded when read from dialog and converted
-         * in internal units, and therefore modified.
+         * For readability, if the mantissa has 3 or more digits then any trailing 0's are removed.
+         * This function should be used to display values in dialogs because a value entered in mm
+         * (for instance 2.0 mm) could need up to 8 digits mantissa to preserve precision.
          *
-         * @param aUnit = display units (INCHES, MILLIMETRE ..)
-         * @param aValue = value in Internal_Unit
-         * @param aAddUnitSymbol = true to add symbol unit to the string value
+         * @param aUnits Units (INCHES, MILLIMETRE ..)
+         * @param aValue Value in internal units
+         * @param aAddUnitsText Add units text with appropriate separators
+         * @param aType DISTANCE, AREA, or VOLUME
          * @return A wxString object containing value and optionally the symbol unit (like 2.000 mm)
          */
-        wxString StringFromValue( const EDA_IU_SCALE& aIuScale, EDA_UNITS aUnit, double aValue,
-                                  bool          aAddUnitSymbol = false,
+        wxString StringFromValue( const EDA_IU_SCALE& aIuScale, EDA_UNITS aUnits, double aValue,
+                                  bool aAddUnitsText = false,
                                   EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE );
 
         /**
-         * Function MessageTextFromValue
-         * is a helper to convert the \a double length \a aValue to a string in inches,
-         * millimeters, or unscaled units.
+         * A helper to convert the \a double length \a aValue to a string in inches, millimeters,
+         * or unscaled units.
          *
-         * Should be used only to display a coordinate in status, but not in dialogs,
-         * files, etc., because the mantissa of the number displayed has 4 digits max
-         * for readability.  The actual internal value could need up to 8 digits to be
-         * printed.
+         * Should be used only to display a coordinate in status, but not in dialogs, files, etc.,
+         * because the mantissa of the number displayed has 4 digits max for readability.  The
+         * actual internal value could need up to 8 digits to preserve precision.
          *
-         * Use StringFromValue() instead where precision matters.
-         *
-         * @param aUnits The units to show the value in.  The unit string is added to the
-         *               message text.
+         * @param aUnits Units (INCHES, MILLIMETRE ..)
          * @param aValue The double value to convert.
-         * @param aAddUnitLabel If true, adds the unit label to the end of the string
-         * @param aType Type of the unit being used (e.g. distance, area, etc.)
+         * @param aAddUnitsText If true, adds the unit label to the end of the string
+         * @param aType DISTANCE, AREA, or VOLUME
          * @return The converted string for display in user interface elements.
          */
-        wxString MessageTextFromValue( const EDA_IU_SCALE& aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitLabel = true,
+        wxString MessageTextFromValue( const EDA_IU_SCALE& aIuScale, EDA_UNITS aUnits,
+                                       double aValue, bool aAddUnitsText = true,
                                        EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE );
 
-        wxString MessageTextFromValue( const EDA_IU_SCALE& aIuScale, EDA_UNITS aUnits, int aValue,
-                                       bool          aAddUnitLabel = true,
+        wxString MessageTextFromValue( const EDA_IU_SCALE& aIuScale, EDA_UNITS aUnits,
+                                       int aValue, bool aAddUnitLabel = true,
                                        EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE );
 
-        wxString MessageTextFromValue( const EDA_IU_SCALE& aIuScale, EDA_UNITS aUnits, long long int aValue,
-                                       bool          aAddUnitLabel = true,
+        wxString MessageTextFromValue( const EDA_IU_SCALE& aIuScale, EDA_UNITS aUnits,
+                                       long long int aValue, bool aAddUnitLabel = true,
                                        EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE );
 
         wxString MessageTextFromValue( EDA_ANGLE aValue, bool aAddUnitLabel = true );
 
 
         /**
-         * Return in internal units the value "val" given in a real unit
-         * such as "in", "mm" or "deg"
+         * Return in internal units the value "val" given in a real unit such as "in", "mm" or "deg"
          */
         double FromUserUnit( const EDA_IU_SCALE& aIuScale, EDA_UNITS aUnit, double aValue );
 
diff --git a/pagelayout_editor/pl_editor_frame.cpp b/pagelayout_editor/pl_editor_frame.cpp
index 41f5b6a15c..f9c70548c1 100644
--- a/pagelayout_editor/pl_editor_frame.cpp
+++ b/pagelayout_editor/pl_editor_frame.cpp
@@ -941,11 +941,8 @@ void PL_EDITOR_FRAME::UpdateMsgPanelInfo()
     VECTOR2D size = GetPageSettings().GetSizeIU( drawSheetIUScale.IU_PER_MILS );
 
     std::vector<MSG_PANEL_ITEM> msgItems;
-    msgItems.emplace_back( _( "Page Width" ), EDA_UNIT_UTILS::UI::MessageTextFromValue(
-                                                      GetIuScale(), GetUserUnits(), size.x ) );
-
-    msgItems.emplace_back( _( "Page Height" ), EDA_UNIT_UTILS::UI::MessageTextFromValue(
-                                                       GetIuScale(), GetUserUnits(), size.y ) );
+    msgItems.emplace_back( _( "Page Width" ), MessageTextFromValue( size.x ) );
+    msgItems.emplace_back( _( "Page Height" ), MessageTextFromValue( size.y ) );
 
     SetMsgPanel( msgItems );
 }
diff --git a/pcbnew/board_stackup_manager/panel_board_stackup.cpp b/pcbnew/board_stackup_manager/panel_board_stackup.cpp
index 5df4e8d6a1..a00bfdef5d 100644
--- a/pcbnew/board_stackup_manager/panel_board_stackup.cpp
+++ b/pcbnew/board_stackup_manager/panel_board_stackup.cpp
@@ -2,7 +2,7 @@
  * This program source code file is part of KiCad, a free EDA CAD application.
  *
  * Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
- * Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors.
+ * Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -85,7 +85,6 @@ PANEL_SETUP_BOARD_STACKUP::PANEL_SETUP_BOARD_STACKUP( PAGED_DIALOG* aParent, PCB
     m_panelLayers = aPanelLayers;
     m_board = m_frame->GetBoard();
     m_brdSettings = &m_board->GetDesignSettings();
-    m_units = aFrame->GetUserUnits();
 
     m_panelLayers->SetPhysicalStackupPanel( this );
 
@@ -175,12 +174,12 @@ void PANEL_SETUP_BOARD_STACKUP::onAdjustDielectricThickness( wxCommandEvent& eve
     if( min_thickness == 0 )
     {
         title.Printf( _( "Enter board thickness in %s:" ),
-                EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( m_frame->GetUserUnits() ).Trim( false ) );
+                      EDA_UNIT_UTILS::GetText( m_frame->GetUserUnits() ).Trim( false ) );
     }
     else
     {
         title.Printf( _( "Enter expected board thickness (min value %s):" ),
-                      EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_frame->GetUserUnits(), min_thickness, true ) );
+                      m_frame->StringFromValue( min_thickness, true ) );
     }
 
     wxTextEntryDialog dlg( this, title, _( "Adjust Unlocked Dielectric Layers" ) );
@@ -188,14 +187,12 @@ void PANEL_SETUP_BOARD_STACKUP::onAdjustDielectricThickness( wxCommandEvent& eve
     if( dlg.ShowModal() != wxID_OK )
         return;
 
-    wxString result = dlg.GetValue();
-
-    int iu_thickness = EDA_UNIT_UTILS::UI::ValueFromString( pcbIUScale, m_frame->GetUserUnits(), result );
+    int iu_thickness = m_frame->ValueFromString( dlg.GetValue() );
 
     if( iu_thickness <= min_thickness )
     {
         wxMessageBox( wxString::Format( _("Value too small (min value %s)." ),
-                      EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_frame->GetUserUnits(), min_thickness, true ) ) );
+                                        m_frame->StringFromValue( min_thickness, true ) ) );
         return;
     }
 
@@ -204,7 +201,7 @@ void PANEL_SETUP_BOARD_STACKUP::onAdjustDielectricThickness( wxCommandEvent& eve
     if( items_candidate.size() )
     {
         int thickness_layer = ( iu_thickness - min_thickness ) / items_candidate.size();
-        wxString txt = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_frame->GetUserUnits(), thickness_layer, true );
+        wxString txt = m_frame->StringFromValue( thickness_layer, true );
 
         for( BOARD_STACKUP_ROW_UI_ITEM* ui_item : items_candidate )
         {
@@ -397,7 +394,7 @@ void PANEL_SETUP_BOARD_STACKUP::onExportToClipboard( wxCommandEvent& event )
         return;
 
     // Build a ASCII representation of stackup and copy it in the clipboard
-    wxString report = BuildStackupReport( m_stackup, m_units );
+    wxString report = BuildStackupReport( m_stackup, m_frame->GetUserUnits() );
 
     wxLogNull doNotLog; // disable logging of failed clipboard actions
 
@@ -440,13 +437,12 @@ int PANEL_SETUP_BOARD_STACKUP::computeBoardThickness()
             continue;
 
         wxTextCtrl* textCtrl = static_cast<wxTextCtrl*>( ui_item.m_ThicknessCtrl );
-        wxString txt = textCtrl->GetValue();
+        int         item_thickness = m_frame->ValueFromString( textCtrl->GetValue() );
 
-        int item_thickness = EDA_UNIT_UTILS::UI::ValueFromString( pcbIUScale, m_frame->GetUserUnits(), txt );
         thickness += item_thickness;
     }
 
-    wxString thicknessStr = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_units, thickness, true );
+    wxString thicknessStr = m_frame->StringFromValue( thickness, true );
 
     // The text in the event will translate to the value for the text control
     // and is only updated if it changed
@@ -517,8 +513,7 @@ void PANEL_SETUP_BOARD_STACKUP::synchronizeWithBoard( bool aFullSync )
             wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( ui_row_item.m_ThicknessCtrl );
 
             if( textCtrl )
-                textCtrl->ChangeValue( EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_units,
-                                        item->GetThickness( sub_item ), true ) );
+                textCtrl->ChangeValue( m_frame->StringFromValue( item->GetThickness( sub_item ), true ) );
 
             if( item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
             {
@@ -763,7 +758,7 @@ BOARD_STACKUP_ROW_UI_ITEM PANEL_SETUP_BOARD_STACKUP::createRowData( int aRow,
     {
         wxTextCtrl* textCtrl = new wxTextCtrl( m_scGridWin, ID_ITEM_THICKNESS+row );
         textCtrl->SetMinSize( m_numericTextCtrlSize );
-        textCtrl->ChangeValue( EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_units, item->GetThickness( aSublayerIdx ), true ) );
+        textCtrl->ChangeValue( m_frame->StringFromValue( item->GetThickness( aSublayerIdx ), true ) );
         m_fgGridSizer->Add( textCtrl, 0, wxLEFT|wxRIGHT|wxALIGN_CENTER_VERTICAL, 2 );
         m_controlItemsList.push_back( textCtrl );
         textCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED,
diff --git a/pcbnew/board_stackup_manager/panel_board_stackup.h b/pcbnew/board_stackup_manager/panel_board_stackup.h
index 99de0a5d5e..a6f76adc16 100644
--- a/pcbnew/board_stackup_manager/panel_board_stackup.h
+++ b/pcbnew/board_stackup_manager/panel_board_stackup.h
@@ -2,7 +2,7 @@
  * This program source code file is part of KiCad, a free EDA CAD application.
  *
  * Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
- * Copyright (C) 2009-2021 KiCad Developers, see AUTHORS.txt for contributors.
+ * Copyright (C) 2009-2022 KiCad Developers, see AUTHORS.txt for contributors.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -247,7 +247,6 @@ private:
     PAGED_DIALOG*   m_parentDialog;
     BOARD*          m_board;
     BOARD_DESIGN_SETTINGS*  m_brdSettings;
-    EDA_UNITS       m_units;
     PCB_EDIT_FRAME* m_frame;
     wxSize          m_numericTextCtrlSize;  // Best size to enter values with units in wxTextCtrl
     wxSize          m_numericFieldsSize;    // Best size to enter double values in wxTextCtrl
diff --git a/pcbnew/dialogs/dialog_board_reannotate.cpp b/pcbnew/dialogs/dialog_board_reannotate.cpp
index 38cfe2c487..5dbad5fcdb 100644
--- a/pcbnew/dialogs/dialog_board_reannotate.cpp
+++ b/pcbnew/dialogs/dialog_board_reannotate.cpp
@@ -367,8 +367,8 @@ void DIALOG_BOARD_REANNOTATE::MakeSampleText( wxString& aMessage )
                                      "rounded to a %s, %s grid." ),
                                   fpLocation ? _( "footprint location" )
                                              : _( "reference designator location" ),
-                                  EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_units, m_sortGridx ),
-                                  EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_units, m_sortGridy ) );
+                                  m_frame->MessageTextFromValue( m_sortGridx ),
+                                  m_frame->MessageTextFromValue( m_sortGridy ) );
 
     ShowReport( aMessage, RPT_SEVERITY_INFO );
 }
@@ -482,8 +482,8 @@ static bool ModuleCompare( const RefDesInfo& aA, const RefDesInfo& aB )
 wxString DIALOG_BOARD_REANNOTATE::CoordTowxString( int aX, int aY )
 {
     return wxString::Format( wxT( "%s, %s" ),
-                             EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_units, aX ),
-                             EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_units, aY ) );
+                             m_frame->MessageTextFromValue( aX ),
+                             m_frame->MessageTextFromValue( aY ) );
 }
 
 
diff --git a/pcbnew/dialogs/dialog_board_statistics.cpp b/pcbnew/dialogs/dialog_board_statistics.cpp
index 9ac92f125d..389373a594 100644
--- a/pcbnew/dialogs/dialog_board_statistics.cpp
+++ b/pcbnew/dialogs/dialog_board_statistics.cpp
@@ -436,14 +436,11 @@ void DIALOG_BOARD_STATISTICS::updateWidets()
     if( m_hasOutline )
     {
         m_gridBoard->SetCellValue( ROW_BOARD_WIDTH, COL_AMOUNT,
-                                   EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, GetUserUnits(),
-                                                         m_boardWidth ) + wxS( " " ) );
+                                   m_parentFrame->MessageTextFromValue( m_boardWidth ) + wxS( " " ) );
         m_gridBoard->SetCellValue( ROW_BOARD_HEIGHT, COL_AMOUNT,
-                                   EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, GetUserUnits(),
-                                                         m_boardHeight ) + wxS( " " ) );
+                                   m_parentFrame->MessageTextFromValue( m_boardHeight ) + wxS( " " ) );
         m_gridBoard->SetCellValue( ROW_BOARD_AREA, COL_AMOUNT,
-                                   EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, GetUserUnits(), m_boardArea, true,
-                                                         EDA_DATA_TYPE::AREA ) );
+                                   m_parentFrame->MessageTextFromValue( m_boardArea, true, EDA_DATA_TYPE::AREA ) );
     }
     else
     {
@@ -476,15 +473,9 @@ void DIALOG_BOARD_STATISTICS::updateDrillGrid()
 
         switch( type.shape )
         {
-        case PAD_DRILL_SHAPE_CIRCLE:
-            shapeStr = _( "Round" );
-            break;
-        case PAD_DRILL_SHAPE_OBLONG:
-            shapeStr = _( "Slot" );
-            break;
-        default:
-            shapeStr = _( "???" );
-            break;
+        case PAD_DRILL_SHAPE_CIRCLE: shapeStr = _( "Round" ); break;
+        case PAD_DRILL_SHAPE_OBLONG: shapeStr = _( "Slot" );  break;
+        default:                     shapeStr = _( "???" );   break;
         }
 
         if( type.startLayer == UNDEFINED_LAYER )
@@ -497,17 +488,17 @@ void DIALOG_BOARD_STATISTICS::updateDrillGrid()
         else
             stopLayerStr = board->GetLayerName( type.stopLayer );
 
-        m_gridDrills->SetCellValue(
-                currentRow, drillType_t::COL_COUNT, wxString::Format( wxT( "%i" ), type.qty ) );
+        m_gridDrills->SetCellValue( currentRow, drillType_t::COL_COUNT,
+                                    wxString::Format( wxT( "%i" ), type.qty ) );
         m_gridDrills->SetCellValue( currentRow, drillType_t::COL_SHAPE, shapeStr );
         m_gridDrills->SetCellValue( currentRow, drillType_t::COL_X_SIZE,
-                EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, GetUserUnits(), type.xSize ) );
+                                    m_parentFrame->MessageTextFromValue( type.xSize ) );
         m_gridDrills->SetCellValue( currentRow, drillType_t::COL_Y_SIZE,
-                EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, GetUserUnits(), type.ySize ) );
-        m_gridDrills->SetCellValue(
-                currentRow, drillType_t::COL_PLATED, type.isPlated ? _( "PTH" ) : _( "NPTH" ) );
-        m_gridDrills->SetCellValue(
-                currentRow, drillType_t::COL_VIA_PAD, type.isPad ? _( "Pad" ) : _( "Via" ) );
+                                    m_parentFrame->MessageTextFromValue( type.ySize ) );
+        m_gridDrills->SetCellValue( currentRow, drillType_t::COL_PLATED,
+                                    type.isPlated ? _( "PTH" ) : _( "NPTH" ) );
+        m_gridDrills->SetCellValue( currentRow, drillType_t::COL_VIA_PAD,
+                                    type.isPad ? _( "Pad" ) : _( "Via" ) );
         m_gridDrills->SetCellValue( currentRow, drillType_t::COL_START_LAYER, startLayerStr );
         m_gridDrills->SetCellValue( currentRow, drillType_t::COL_STOP_LAYER, stopLayerStr );
 
@@ -692,12 +683,12 @@ void DIALOG_BOARD_STATISTICS::saveReportClicked( wxCommandEvent& aEvent )
 
     if( m_hasOutline )
     {
-        msg << wxS( "- " ) << _( "Width" ) << wxS( ": " ) <<
-               EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, GetUserUnits(), m_boardWidth ) << wxT( "\n" );
-        msg << wxS( "- " ) << _( "Height" ) << wxS( ": " ) <<
-               EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, GetUserUnits(), m_boardHeight ) << wxT( "\n" );
-        msg << wxS( "- " ) << _( "Area" ) + wxS( ": " ) <<
-               EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, GetUserUnits(), m_boardArea, true, EDA_DATA_TYPE::AREA );
+        msg << wxS( "- " ) << _( "Width" ) << wxS( ": " )
+                << m_parentFrame->MessageTextFromValue( m_boardWidth ) << wxT( "\n" );
+        msg << wxS( "- " ) << _( "Height" ) << wxS( ": " )
+                << m_parentFrame->MessageTextFromValue( m_boardHeight ) << wxT( "\n" );
+        msg << wxS( "- " ) << _( "Area" ) + wxS( ": " )
+                << m_parentFrame->MessageTextFromValue( m_boardArea, true, EDA_DATA_TYPE::AREA );
         msg << wxT( "\n" );
     }
     else
diff --git a/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp b/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp
index c9fa26aa68..dda9b4f0db 100644
--- a/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp
+++ b/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp
@@ -239,7 +239,7 @@ bool DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::TransferDataToWindow()
     m_LayerCtrl->SetLayerSelection( UNDEFINED_LAYER );
 
 #define SET_INT_VALUE( aRow, aCol, aValue ) \
-        m_grid->SetCellValue( aRow, aCol, EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, GetUserUnits(), aValue, true ) )
+        m_grid->SetCellValue( aRow, aCol, m_parent->StringFromValue( aValue, true ) )
 
 #define SET_BOOL_VALUE( aRow, aCol, aValue ) \
         attr = new wxGridCellAttr; \
diff --git a/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp b/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp
index f658f0a341..e9ec89a9a5 100644
--- a/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp
+++ b/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp
@@ -223,8 +223,7 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::buildFilterLists()
 
 void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::buildNetclassesGrid()
 {
-    EDA_UNITS units = m_parent->GetUserUnits();
-    int       row = 0;
+    int row = 0;
 
     m_netclassGrid->SetCellValue( row, GRID_TRACKSIZE, _( "Track Width" ) );
     m_netclassGrid->SetCellValue( row, GRID_VIASIZE, _( "Via Diameter" ) );
@@ -234,9 +233,9 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::buildNetclassesGrid()
     row++;
 
     auto setNetclassValue =
-            [this, units]( int aRow, int aCol, int aVal )
+            [this]( int aRow, int aCol, int aVal )
             {
-                m_netclassGrid->SetCellValue( aRow, aCol, EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units, aVal, true ) );
+                m_netclassGrid->SetCellValue( aRow, aCol, m_parent->StringFromValue( aVal, true ) );
             };
 
     auto buildRow =
diff --git a/pcbnew/dialogs/dialog_net_inspector.cpp b/pcbnew/dialogs/dialog_net_inspector.cpp
index f88852ad85..575273d094 100644
--- a/pcbnew/dialogs/dialog_net_inspector.cpp
+++ b/pcbnew/dialogs/dialog_net_inspector.cpp
@@ -1295,7 +1295,7 @@ wxString DIALOG_NET_INSPECTOR::formatCount( unsigned int aValue ) const
 
 wxString DIALOG_NET_INSPECTOR::formatLength( int64_t aValue ) const
 {
-    return EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, GetUserUnits(), static_cast<long long int>( aValue ) );
+    return m_frame->MessageTextFromValue( static_cast<long long int>( aValue ) );
 }
 
 
diff --git a/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp b/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp
index 32a963fb4a..12ea215371 100644
--- a/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp
+++ b/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp
@@ -251,6 +251,7 @@ DIALOG_PAD_PRIMITIVE_POLY_PROPS::DIALOG_PAD_PRIMITIVE_POLY_PROPS( wxWindow* aPar
                                                                   PCB_BASE_FRAME* aFrame,
                                                                   PCB_SHAPE* aShape ) :
         DIALOG_PAD_PRIMITIVE_POLY_PROPS_BASE( aParent ),
+        m_frame( aFrame ),
         m_shape( aShape ),
         m_thickness( aFrame, m_thicknessLabel, m_thicknessCtrl, m_thicknessUnits )
 {
@@ -319,10 +320,10 @@ bool DIALOG_PAD_PRIMITIVE_POLY_PROPS::TransferDataToWindow()
         msg.Printf( _( "Corner %d" ), row+1 );
         m_gridCornersList->SetRowLabelValue( row, msg );
 
-        msg = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, GetUserUnits(), m_currPoints[row].x, true );
+        msg = m_frame->StringFromValue( m_currPoints[row].x, true );
         m_gridCornersList->SetCellValue( row, 0, msg );
 
-        msg = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, GetUserUnits(), m_currPoints[row].y, true );
+        msg = m_frame->StringFromValue( m_currPoints[row].y, true );
         m_gridCornersList->SetCellValue( row, 1, msg );
     }
 
diff --git a/pcbnew/dialogs/dialog_pad_properties.h b/pcbnew/dialogs/dialog_pad_properties.h
index 347cd60f05..072419fe24 100644
--- a/pcbnew/dialogs/dialog_pad_properties.h
+++ b/pcbnew/dialogs/dialog_pad_properties.h
@@ -4,7 +4,7 @@
  * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
  * Copyright (C) 2013 Dick Hollenbeck, dick@softplc.com
  * Copyright (C) 2008-2013 Wayne Stambaugh <stambaughw@gmail.com>
- * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
+ * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -28,7 +28,6 @@
 #define _DIALOG_PAD_PROPERTIES_H_
 
 #include <pcb_base_frame.h>
-#include <base_units.h>
 #include <wx/valnum.h>
 #include <board.h>
 #include <footprint.h>
@@ -256,13 +255,12 @@ private:
 
     bool doValidate( bool aRemoveRedundantCorners );
 
-    // The basic shape currently edited
-    PCB_SHAPE*           m_shape;
+private:
+    PCB_BASE_FRAME*       m_frame;
+    PCB_SHAPE*            m_shape;
 
-    // The working copy of the basic shape currently edited
-    std::vector<VECTOR2I> m_currPoints;
-
-    UNIT_BINDER          m_thickness;
+    std::vector<VECTOR2I> m_currPoints;    // The working copy of the data being edited
+    UNIT_BINDER           m_thickness;
 };
 
 
diff --git a/pcbnew/dialogs/dialog_plot.cpp b/pcbnew/dialogs/dialog_plot.cpp
index 7e76783131..f147d8fd4d 100644
--- a/pcbnew/dialogs/dialog_plot.cpp
+++ b/pcbnew/dialogs/dialog_plot.cpp
@@ -237,8 +237,13 @@ void DIALOG_PLOT::init_Dialog()
         m_XScaleAdjust = m_YScaleAdjust = 1.0;
     }
 
-    m_fineAdjustXCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, EDA_UNITS::UNSCALED, m_XScaleAdjust ) );
-    m_fineAdjustYCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, EDA_UNITS::UNSCALED, m_YScaleAdjust ) );
+    m_fineAdjustXCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue( unityScale,
+                                                                      EDA_UNITS::UNSCALED,
+                                                                      m_XScaleAdjust ) );
+
+    m_fineAdjustYCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue( unityScale,
+                                                                      EDA_UNITS::UNSCALED,
+                                                                      m_YScaleAdjust ) );
 
     // Test for a reasonable PS width correction value. Set to 0 if problem.
     if( m_PSWidthAdjust < m_widthAdjustMinValue || m_PSWidthAdjust > m_widthAdjustMaxValue )
@@ -835,8 +840,8 @@ void DIALOG_PLOT::applyPlotSettings()
         m_trackWidthCorrection.SetValue( m_PSWidthAdjust );
         msg.Printf( _( "Width correction constrained.  The width correction value must be in the"
                        " range of [%s; %s] for the current design rules." ),
-                    EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, GetUserUnits(), m_widthAdjustMinValue, true ),
-                    EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, GetUserUnits(), m_widthAdjustMaxValue, true ) );
+                    m_parent->StringFromValue( m_widthAdjustMinValue, true ),
+                    m_parent->StringFromValue( m_widthAdjustMaxValue, true ) );
         reporter.Report( msg, RPT_SEVERITY_WARNING );
     }
 
diff --git a/pcbnew/dialogs/dialog_plot.h b/pcbnew/dialogs/dialog_plot.h
index 7d92b6890b..7cf1fa02c5 100644
--- a/pcbnew/dialogs/dialog_plot.h
+++ b/pcbnew/dialogs/dialog_plot.h
@@ -1,11 +1,7 @@
-/**
- * @file dialog_plot.h
- */
-
 /*
  * This program source code file is part of KiCad, a free EDA CAD application.
  *
- * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
+ * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff --git a/pcbnew/dialogs/dialog_track_via_properties.cpp b/pcbnew/dialogs/dialog_track_via_properties.cpp
index da150edab7..520305301c 100644
--- a/pcbnew/dialogs/dialog_track_via_properties.cpp
+++ b/pcbnew/dialogs/dialog_track_via_properties.cpp
@@ -2,7 +2,7 @@
  * This program source code file is part of KiCad, a free EDA CAD application.
  *
  * Copyright (C) 2015 CERN
- * Copyright (C) 2018-2021 KiCad Developers, see AUTHORS.txt for contributors.
+ * Copyright (C) 2018-2022 KiCad Developers, see AUTHORS.txt for contributors.
  * @author Maciej Suminski <maciej.suminski@cern.ch>
  *
  * This program is free software; you can redistribute it and/or
@@ -298,8 +298,7 @@ DIALOG_TRACK_VIA_PROPERTIES::DIALOG_TRACK_VIA_PROPERTIES( PCB_BASE_FRAME* aParen
             m_netSelector->Disable();
         }
 
-        m_DesignRuleViasUnit->SetLabel(
-                EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( m_frame->GetUserUnits() ).Trim( false ) );
+        m_DesignRuleViasUnit->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
 
         int viaSelection = wxNOT_FOUND;
 
@@ -307,9 +306,9 @@ DIALOG_TRACK_VIA_PROPERTIES::DIALOG_TRACK_VIA_PROPERTIES( PCB_BASE_FRAME* aParen
         for( unsigned ii = 1; ii < aParent->GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
         {
             VIA_DIMENSION* viaDimension = &aParent->GetDesignSettings().m_ViasDimensionsList[ii];
-            wxString msg = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_frame->GetUserUnits(), viaDimension->m_Diameter )
-                            + wxT( " / " )
-                            + EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_frame->GetUserUnits(), viaDimension->m_Drill );
+            wxString       msg = m_frame->StringFromValue( viaDimension->m_Diameter )
+                                    + wxT( " / " )
+                                    + m_frame->StringFromValue( viaDimension->m_Drill );
             m_DesignRuleViasCtrl->Append( msg, viaDimension );
 
             if( viaSelection == wxNOT_FOUND
@@ -343,16 +342,15 @@ DIALOG_TRACK_VIA_PROPERTIES::DIALOG_TRACK_VIA_PROPERTIES( PCB_BASE_FRAME* aParen
 
     if( m_tracks )
     {
-        m_DesignRuleWidthsUnits->SetLabel(
-                EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( m_frame->GetUserUnits() ).Trim( false ) );
+        m_DesignRuleWidthsUnits->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
 
         int widthSelection = wxNOT_FOUND;
 
         // 0 is the netclass place-holder
         for( unsigned ii = 1; ii < aParent->GetDesignSettings().m_TrackWidthList.size(); ii++ )
         {
-            int width = aParent->GetDesignSettings().m_TrackWidthList[ii];
-            wxString msg = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_frame->GetUserUnits(), width );
+            int      width = aParent->GetDesignSettings().m_TrackWidthList[ii];
+            wxString msg = m_frame->StringFromValue( width );
             m_DesignRuleWidthsCtrl->Append( msg );
 
             if( widthSelection == wxNOT_FOUND && m_trackWidth.GetValue() == width )
@@ -407,15 +405,14 @@ void DIALOG_TRACK_VIA_PROPERTIES::onUnitsChanged( wxCommandEvent& aEvent )
         for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
         {
             VIA_DIMENSION* viaDimension = &m_frame->GetDesignSettings().m_ViasDimensionsList[ii];
-            wxString msg = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_frame->GetUserUnits(), viaDimension->m_Diameter )
-                            + wxT( " / " )
-                            + EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_frame->GetUserUnits(), viaDimension->m_Drill );
+            wxString       msg = m_frame->StringFromValue( viaDimension->m_Diameter )
+                                    + wxT( " / " )
+                                    + m_frame->StringFromValue( viaDimension->m_Drill );
             m_DesignRuleViasCtrl->Append( msg, viaDimension );
         }
 
         m_DesignRuleViasCtrl->SetSelection( viaSel );
-        m_DesignRuleViasUnit->SetLabel(
-                EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( m_frame->GetUserUnits() ) );
+        m_DesignRuleViasUnit->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
     }
 
     if( m_tracks )
@@ -427,14 +424,13 @@ void DIALOG_TRACK_VIA_PROPERTIES::onUnitsChanged( wxCommandEvent& aEvent )
         // 0 is the netclass place-holder
         for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_TrackWidthList.size(); ii++ )
         {
-            int width = m_frame->GetDesignSettings().m_TrackWidthList[ii];
-            wxString msg = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_frame->GetUserUnits(), width );
+            int      width = m_frame->GetDesignSettings().m_TrackWidthList[ii];
+            wxString msg = m_frame->StringFromValue( width );
             m_DesignRuleWidthsCtrl->Append( msg );
         }
 
         m_DesignRuleWidthsCtrl->SetSelection( trackSel );
-        m_DesignRuleWidthsUnits->SetLabel(
-                EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( m_frame->GetUserUnits() ) );
+        m_DesignRuleWidthsUnits->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
     }
 
     aEvent.Skip();
diff --git a/pcbnew/dialogs/panel_setup_constraints.cpp b/pcbnew/dialogs/panel_setup_constraints.cpp
index 74d2dcb863..9818c4c03c 100644
--- a/pcbnew/dialogs/panel_setup_constraints.cpp
+++ b/pcbnew/dialogs/panel_setup_constraints.cpp
@@ -64,8 +64,7 @@ PANEL_SETUP_CONSTRAINTS::PANEL_SETUP_CONSTRAINTS( PAGED_DIALOG* aParent, PCB_EDI
 bool PANEL_SETUP_CONSTRAINTS::TransferDataToWindow()
 {
     wxString msg;
-    msg.Printf( m_stCircleToPolyWarning->GetLabel(),
-                EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_Frame->GetUserUnits(), ARC_HIGH_DEF, true ) );
+    msg.Printf( m_stCircleToPolyWarning->GetLabel(), m_Frame->StringFromValue( ARC_HIGH_DEF, true ) );
     m_stCircleToPolyWarning->SetLabel( msg );
 
     m_useHeightForLengthCalcs->SetValue( m_BrdSettings->m_UseHeightForLengthCalcs );
diff --git a/pcbnew/dialogs/panel_setup_formatting.cpp b/pcbnew/dialogs/panel_setup_formatting.cpp
index 2f03e467f2..25ecc25fe6 100644
--- a/pcbnew/dialogs/panel_setup_formatting.cpp
+++ b/pcbnew/dialogs/panel_setup_formatting.cpp
@@ -41,11 +41,11 @@ bool PANEL_SETUP_FORMATTING::TransferDataToWindow()
 {
     const PCB_PLOT_PARAMS& settings = m_frame->GetBoard()->GetPlotOptions();
 
-    m_dashLengthCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, EDA_UNITS::UNSCALED,
-                                                 settings.GetDashedLineDashRatio() ) );
+    m_dashLengthCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue( unityScale, EDA_UNITS::UNSCALED,
+                                                                     settings.GetDashedLineDashRatio() ) );
 
-    m_gapLengthCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, EDA_UNITS::UNSCALED,
-                                                settings.GetDashedLineGapRatio() ) );
+    m_gapLengthCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue( unityScale, EDA_UNITS::UNSCALED,
+                                                                    settings.GetDashedLineGapRatio() ) );
 
     return true;
 }
@@ -56,7 +56,6 @@ bool PANEL_SETUP_FORMATTING::TransferDataFromWindow()
     PCB_PLOT_PARAMS settings = m_frame->GetBoard()->GetPlotOptions();
 
     settings.SetDashedLineDashRatio( EDA_UNIT_UTILS::UI::DoubleValueFromString( m_dashLengthCtrl->GetValue() ) );
-
     settings.SetDashedLineGapRatio( EDA_UNIT_UTILS::UI::DoubleValueFromString( m_gapLengthCtrl->GetValue() ) );
 
     m_frame->GetBoard()->SetPlotOptions( settings );
@@ -77,9 +76,9 @@ void PANEL_SETUP_FORMATTING::ImportSettingsFrom( BOARD* aBoard )
 {
     const PCB_PLOT_PARAMS& importedSettings = aBoard->GetPlotOptions();
 
-    m_dashLengthCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, EDA_UNITS::UNSCALED,
-                                                 importedSettings.GetDashedLineDashRatio() ) );
+    m_dashLengthCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue( unityScale, EDA_UNITS::UNSCALED,
+                                                                     importedSettings.GetDashedLineDashRatio() ) );
 
-    m_gapLengthCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, EDA_UNITS::UNSCALED,
-                                                importedSettings.GetDashedLineGapRatio() ) );
+    m_gapLengthCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue( unityScale, EDA_UNITS::UNSCALED,
+                                                                    importedSettings.GetDashedLineGapRatio() ) );
 }
diff --git a/pcbnew/dialogs/panel_setup_text_and_graphics.cpp b/pcbnew/dialogs/panel_setup_text_and_graphics.cpp
index b3ba54ae87..93a1ed9ed0 100644
--- a/pcbnew/dialogs/panel_setup_text_and_graphics.cpp
+++ b/pcbnew/dialogs/panel_setup_text_and_graphics.cpp
@@ -126,7 +126,7 @@ bool PANEL_SETUP_TEXT_AND_GRAPHICS::TransferDataToWindow()
     wxColour disabledColour = wxSystemSettings::GetColour( wxSYS_COLOUR_BACKGROUND );
 
 #define SET_MILS_CELL( row, col, val ) \
-    m_grid->SetCellValue( row, col, EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_Frame->GetUserUnits(), val, true ) )
+    m_grid->SetCellValue( row, col, m_Frame->StringFromValue( val, true ) )
 
 #define DISABLE_CELL( row, col ) \
     m_grid->SetReadOnly( row, col ); m_grid->SetCellBackgroundColour( row, col, disabledColour );
diff --git a/pcbnew/dialogs/panel_setup_tracks_and_vias.cpp b/pcbnew/dialogs/panel_setup_tracks_and_vias.cpp
index ebecc8534a..f3c34a3578 100644
--- a/pcbnew/dialogs/panel_setup_tracks_and_vias.cpp
+++ b/pcbnew/dialogs/panel_setup_tracks_and_vias.cpp
@@ -401,49 +401,36 @@ void PANEL_SETUP_TRACKS_AND_VIAS::AppendTrackWidth( const int aWidth )
 
     m_trackWidthsGrid->AppendRows( 1 );
 
-    wxString val = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_Frame->GetUserUnits(), aWidth, true );
-    m_trackWidthsGrid->SetCellValue( i, TR_WIDTH_COL, val );
+    m_trackWidthsGrid->SetCellValue( i, TR_WIDTH_COL, m_Frame->StringFromValue( aWidth, true ) );
 }
 
 
-void PANEL_SETUP_TRACKS_AND_VIAS::AppendViaSize( const int aSize, const int aDrill )
+void PANEL_SETUP_TRACKS_AND_VIAS::AppendViaSize( int aSize, int aDrill )
 {
     int i = m_viaSizesGrid->GetNumberRows();
 
     m_viaSizesGrid->AppendRows( 1 );
 
-    wxString val = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_Frame->GetUserUnits(), aSize, true );
-    m_viaSizesGrid->SetCellValue( i, VIA_SIZE_COL, val );
+    m_viaSizesGrid->SetCellValue( i, VIA_SIZE_COL, m_Frame->StringFromValue( aSize, true ) );
 
     if( aDrill > 0 )
-    {
-        val = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_Frame->GetUserUnits(), aDrill, true );
-        m_viaSizesGrid->SetCellValue( i, VIA_DRILL_COL, val );
-    }
+        m_viaSizesGrid->SetCellValue( i, VIA_DRILL_COL, m_Frame->StringFromValue( aDrill, true ) );
 }
 
 
-void PANEL_SETUP_TRACKS_AND_VIAS::AppendDiffPairs( const int aWidth, const int aGap,
-                                                   const int aViaGap )
+void PANEL_SETUP_TRACKS_AND_VIAS::AppendDiffPairs( int aWidth, int aGap, int aViaGap )
 {
     int i = m_diffPairsGrid->GetNumberRows();
 
     m_diffPairsGrid->AppendRows( 1 );
 
-    wxString val = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_Frame->GetUserUnits(), aWidth, true );
-    m_diffPairsGrid->SetCellValue( i, DP_WIDTH_COL, val );
+    m_diffPairsGrid->SetCellValue( i, DP_WIDTH_COL, m_Frame->StringFromValue( aWidth, true ) );
 
     if( aGap > 0 )
-    {
-        val = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_Frame->GetUserUnits(), aGap, true );
-        m_diffPairsGrid->SetCellValue( i, DP_GAP_COL, val );
-    }
+        m_diffPairsGrid->SetCellValue( i, DP_GAP_COL, m_Frame->StringFromValue( aGap, true ) );
 
     if( aViaGap > 0 )
-    {
-        val = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_Frame->GetUserUnits(), aViaGap, true );
-        m_diffPairsGrid->SetCellValue( i, DP_VIA_GAP_COL, val );
-    }
+        m_diffPairsGrid->SetCellValue( i, DP_VIA_GAP_COL, m_Frame->StringFromValue( aViaGap, true ) );
 }
 
 
diff --git a/pcbnew/dialogs/panel_setup_tracks_and_vias.h b/pcbnew/dialogs/panel_setup_tracks_and_vias.h
index 07af248862..ce4a7268ec 100644
--- a/pcbnew/dialogs/panel_setup_tracks_and_vias.h
+++ b/pcbnew/dialogs/panel_setup_tracks_and_vias.h
@@ -62,9 +62,9 @@ protected:
 
     void onUnitsChanged( wxCommandEvent& aEvent );
 
-    void AppendTrackWidth( const int aWidth );
-    void AppendViaSize( const int aSize, const int aDrill );
-    void AppendDiffPairs( const int aWidth, const int aGap, const int aViaGap );
+    void AppendTrackWidth( int aWidth );
+    void AppendViaSize( int aSize, int aDrill );
+    void AppendDiffPairs( int aWidth, int aGap, int aViaGap );
 
 private:
     PAGED_DIALOG*            m_Parent;
diff --git a/pcbnew/drc/drc_engine.cpp b/pcbnew/drc/drc_engine.cpp
index 68f571e2b9..378cde95e0 100644
--- a/pcbnew/drc/drc_engine.cpp
+++ b/pcbnew/drc/drc_engine.cpp
@@ -608,6 +608,8 @@ void DRC_ENGINE::RunTests( EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aT
 #define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } }
 #define UNITS aReporter ? aReporter->GetUnits() : EDA_UNITS::MILLIMETRES
 #define REPORT_VALUE( v ) EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, UNITS, v )
+#define REPORT_UNSCALED_VALUE( v ) \
+                EDA_UNIT_UTILS::UI::MessageTextFromValue( unityScale, EDA_UNITS::UNSCALED, v )
 
 DRC_CONSTRAINT DRC_ENGINE::EvalZoneConnection( const BOARD_ITEM* a, const BOARD_ITEM* b,
                                                PCB_LAYER_ID aLayer, REPORTER* aReporter )
@@ -910,7 +912,7 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
                 case MIN_RESOLVED_SPOKES_CONSTRAINT:
                     REPORT( wxString::Format( _( "Checking %s min spoke count: %s." ),
                                               EscapeHTML( c->constraint.GetName() ),
-                                              EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, EDA_UNITS::UNSCALED, c->constraint.m_Value.Min() ) ) )
+                                              REPORT_UNSCALED_VALUE( c->constraint.m_Value.Min() ) ) )
                     break;
 
                 case ZONE_CONNECTION_CONSTRAINT:
@@ -938,10 +940,8 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
 
                         if( implicit )
                         {
-                            min = EDA_UNIT_UTILS::UI::StringFromValue(
-                                    pcbIUScale, UNITS, c->constraint.m_Value.Min(), true );
-                            opt = EDA_UNIT_UTILS::UI::StringFromValue(
-                                    pcbIUScale, UNITS, c->constraint.m_Value.Opt(), true );
+                            min = REPORT_VALUE( c->constraint.m_Value.Min() );
+                            opt = REPORT_VALUE( c->constraint.m_Value.Opt() );
 
                             switch( c->constraint.m_Type )
                             {
@@ -1037,16 +1037,13 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
                         else
                         {
                             if( c->constraint.m_Value.HasMin() )
-                                min = EDA_UNIT_UTILS::UI::StringFromValue(
-                                        pcbIUScale, UNITS, c->constraint.m_Value.Min(), true );
+                                min = REPORT_VALUE( c->constraint.m_Value.Min() );
 
                             if( c->constraint.m_Value.HasOpt() )
-                                opt = EDA_UNIT_UTILS::UI::StringFromValue(
-                                        pcbIUScale, UNITS, c->constraint.m_Value.Opt(), true );
+                                opt = REPORT_VALUE( c->constraint.m_Value.Opt() );
 
                             if( c->constraint.m_Value.HasMax() )
-                                max = EDA_UNIT_UTILS::UI::StringFromValue(
-                                        pcbIUScale, UNITS, c->constraint.m_Value.Max(), true );
+                                max = REPORT_VALUE( c->constraint.m_Value.Max() );
 
                             REPORT( wxString::Format( _( "Checking %s: min %s; opt %s; max %s." ),
                                                       EscapeHTML( c->constraint.GetName() ),
diff --git a/pcbnew/footprint_editor_settings.cpp b/pcbnew/footprint_editor_settings.cpp
index b35fe22c55..2c0e0fcce8 100644
--- a/pcbnew/footprint_editor_settings.cpp
+++ b/pcbnew/footprint_editor_settings.cpp
@@ -403,7 +403,7 @@ bool FOOTPRINT_EDITOR_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
     if( aCfg->Read( f + "PcbUserGrid_X", &x ) && aCfg->Read( f + "PcbUserGrid_Y", &y ) )
     {
         EDA_UNITS u = static_cast<EDA_UNITS>( aCfg->ReadLong( f + "PcbUserGrid_Unit",
-                static_cast<long>( EDA_UNITS::INCHES ) ) );
+                                                              static_cast<long>( EDA_UNITS::INCHES ) ) );
 
         // Convert to internal units
         x = EDA_UNIT_UTILS::UI::FromUserUnit( pcbIUScale, u, x );
diff --git a/pcbnew/fp_text.cpp b/pcbnew/fp_text.cpp
index 14950e01b7..9c6eeece7e 100644
--- a/pcbnew/fp_text.cpp
+++ b/pcbnew/fp_text.cpp
@@ -259,7 +259,6 @@ EDA_ANGLE FP_TEXT::GetDrawRotation() const
 
 void FP_TEXT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
-    EDA_UNITS units = aFrame->GetUserUnits();
     wxString msg;
 
     static const wxString text_type_msg[3] =
@@ -295,9 +294,9 @@ void FP_TEXT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITE
     aList.emplace_back( _( "Angle" ), msg );
 
     aList.emplace_back( _( "Font" ), GetDrawFont()->GetName() );
-    aList.emplace_back( _( "Thickness" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, GetTextThickness() ) );
-    aList.emplace_back( _( "Width" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, GetTextWidth() ) );
-    aList.emplace_back( _( "Height" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, GetTextHeight() ) );
+    aList.emplace_back( _( "Thickness" ), aFrame->MessageTextFromValue( GetTextThickness() ) );
+    aList.emplace_back( _( "Width" ), aFrame->MessageTextFromValue( GetTextWidth() ) );
+    aList.emplace_back( _( "Height" ), aFrame->MessageTextFromValue( GetTextHeight() ) );
 }
 
 
diff --git a/pcbnew/fp_text_grid_table.cpp b/pcbnew/fp_text_grid_table.cpp
index 6b23e4d6dd..cb6469b778 100644
--- a/pcbnew/fp_text_grid_table.cpp
+++ b/pcbnew/fp_text_grid_table.cpp
@@ -1,7 +1,7 @@
 /*
  * This program source code file is part of KiCad, a free EDA CAD application.
  *
- * Copyright (C) 2018-2021 KiCad Developers, see AUTHORS.txt for contributors.
+ * Copyright (C) 2018-2022 KiCad Developers, see AUTHORS.txt for contributors.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -54,14 +54,10 @@ FP_TEXT_GRID_TABLE::FP_TEXT_GRID_TABLE( PCB_BASE_FRAME* aFrame ) :
 
     if( g_menuOrientations.IsEmpty() )
     {
-        g_menuOrientations.push_back(
-                "0" + EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( EDA_UNITS::DEGREES ) );
-        g_menuOrientations.push_back(
-                "90" + EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( EDA_UNITS::DEGREES ) );
-        g_menuOrientations.push_back(
-                "-90" + EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( EDA_UNITS::DEGREES ) );
-        g_menuOrientations.push_back(
-                "180" + EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( EDA_UNITS::DEGREES ) );
+        g_menuOrientations.push_back( "0" + EDA_UNIT_UTILS::GetText( EDA_UNITS::DEGREES ) );
+        g_menuOrientations.push_back( "90" + EDA_UNIT_UTILS::GetText( EDA_UNITS::DEGREES ) );
+        g_menuOrientations.push_back( "-90" + EDA_UNIT_UTILS::GetText( EDA_UNITS::DEGREES ) );
+        g_menuOrientations.push_back( "180" + EDA_UNIT_UTILS::GetText( EDA_UNITS::DEGREES ) );
     }
 
     m_orientationColAttr = new wxGridCellAttr;
@@ -203,25 +199,25 @@ wxString FP_TEXT_GRID_TABLE::GetValue( int aRow, int aCol )
         return text.GetText();
 
     case FPT_WIDTH:
-        return EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_frame->GetUserUnits(), text.GetTextWidth(), true );
+        return m_frame->StringFromValue( text.GetTextWidth(), true );
 
     case FPT_HEIGHT:
-        return EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_frame->GetUserUnits(), text.GetTextHeight(), true );
+        return m_frame->StringFromValue( text.GetTextHeight(), true );
 
     case FPT_THICKNESS:
-        return EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_frame->GetUserUnits(), text.GetTextThickness(), true );
+        return m_frame->StringFromValue( text.GetTextThickness(), true );
 
     case FPT_LAYER:
         return text.GetLayerName();
 
     case FPT_ORIENTATION:
-        return EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, EDA_UNITS::DEGREES, text.GetTextAngle().AsDegrees(), true );
+        return m_frame->StringFromValue( text.GetTextAngle(), true );
 
     case FPT_XOFFSET:
-        return EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_frame->GetUserUnits(), text.GetPos0().x, true );
+        return m_frame->StringFromValue( text.GetPos0().x, true );
 
     case FPT_YOFFSET:
-        return EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, m_frame->GetUserUnits(), text.GetPos0().y, true );
+        return m_frame->StringFromValue( text.GetPos0().y, true );
 
     default:
         // we can't assert here because wxWidgets sometimes calls this without checking
diff --git a/pcbnew/fp_textbox.cpp b/pcbnew/fp_textbox.cpp
index 5424af83fa..1e99ef4ac0 100644
--- a/pcbnew/fp_textbox.cpp
+++ b/pcbnew/fp_textbox.cpp
@@ -301,8 +301,6 @@ void FP_TEXTBOX::Mirror( const VECTOR2I& aCentre, bool aMirrorAroundXAxis )
 
 void FP_TEXTBOX::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
-    EDA_UNITS units = aFrame->GetUserUnits();
-
     // Don't use GetShownText() here; we want to show the user the variable references
     aList.emplace_back( _( "Text Box" ), UnescapeString( GetText() ) );
 
@@ -314,17 +312,17 @@ void FP_TEXTBOX::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_
     aList.emplace_back( _( "Angle" ), wxString::Format( "%g", GetTextAngle().AsDegrees() ) );
 
     aList.emplace_back( _( "Font" ), GetDrawFont()->GetName() );
-    aList.emplace_back( _( "Thickness" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, GetTextThickness() ) );
-    aList.emplace_back( _( "Text Width" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, GetTextWidth() ) );
-    aList.emplace_back( _( "Text Height" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, GetTextHeight() ) );
+    aList.emplace_back( _( "Thickness" ), aFrame->MessageTextFromValue( GetTextThickness() ) );
+    aList.emplace_back( _( "Text Width" ), aFrame->MessageTextFromValue( GetTextWidth() ) );
+    aList.emplace_back( _( "Text Height" ), aFrame->MessageTextFromValue( GetTextHeight() ) );
 
-    wxString msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, std::abs( GetEnd().x - GetStart().x ) );
+    wxString msg = aFrame->MessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) );
     aList.emplace_back( _( "Box Width" ), msg );
 
-    msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, std::abs( GetEnd().y - GetStart().y ) );
+    msg = aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) );
     aList.emplace_back( _( "Box Height" ), msg );
 
-    m_stroke.GetMsgPanelInfo( pcbIUScale, units, aList );
+    m_stroke.GetMsgPanelInfo( pcbIUScale, aFrame->GetUserUnits(), aList );
 }
 
 
@@ -445,8 +443,8 @@ std::shared_ptr<SHAPE> FP_TEXTBOX::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASH
 
 
 void FP_TEXTBOX::TransformTextShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
-                                                        PCB_LAYER_ID aLayer, int aClearance,
-                                                        int aError, ERROR_LOC aErrorLoc ) const
+                                                           PCB_LAYER_ID aLayer, int aClearance,
+                                                           int aError, ERROR_LOC aErrorLoc ) const
 {
     KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
     KIFONT::FONT*              font = GetDrawFont();
@@ -476,9 +474,9 @@ void FP_TEXTBOX::TransformTextShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCorn
 
 
 void FP_TEXTBOX::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
-                                                    PCB_LAYER_ID aLayer, int aClearance,
-                                                    int aError, ERROR_LOC aErrorLoc,
-                                                    bool aIgnoreLineWidth ) const
+                                                       PCB_LAYER_ID aLayer, int aClearance,
+                                                       int aError, ERROR_LOC aErrorLoc,
+                                                       bool aIgnoreLineWidth ) const
 {
     // Don't use FP_SHAPE::TransformShapeWithClearanceToPolygon.  We want to treat the
     // textbox as filled even if there's no background colour.
diff --git a/pcbnew/microwave/microwave_footprint.cpp b/pcbnew/microwave/microwave_footprint.cpp
index aabe3661da..e7b625a896 100644
--- a/pcbnew/microwave/microwave_footprint.cpp
+++ b/pcbnew/microwave/microwave_footprint.cpp
@@ -41,14 +41,14 @@ FOOTPRINT* MICROWAVE_TOOL::createFootprint( MICROWAVE_FOOTPRINT_SHAPE aFootprint
     int        pad_count = 2;
     EDA_ANGLE  angle     = ANGLE_0;
 
-    PCB_EDIT_FRAME& editFrame  = *getEditFrame<PCB_EDIT_FRAME>();
+    PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
 
     // Ref and value text size (O = use board default value.
     // will be set to a value depending on the footprint size, if possible
     int text_size = 0;
 
     // Enter the size of the gap or stub
-    int gap_size = editFrame.GetDesignSettings().GetCurrentTrackWidth();
+    int gap_size = editFrame->GetDesignSettings().GetCurrentTrackWidth();
 
     switch( aFootprintShape )
     {
@@ -76,21 +76,21 @@ FOOTPRINT* MICROWAVE_TOOL::createFootprint( MICROWAVE_FOOTPRINT_SHAPE aFootprint
         break;
     }
 
-    wxString value = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, editFrame.GetUserUnits(), gap_size );
-    WX_TEXT_ENTRY_DIALOG dlg( &editFrame, msg, _( "Create Microwave Footprint" ), value );
+    wxString             value = editFrame->StringFromValue( gap_size );
+    WX_TEXT_ENTRY_DIALOG dlg( editFrame, msg, _( "Create Microwave Footprint" ), value );
 
     if( dlg.ShowQuasiModal() != wxID_OK )
         return nullptr; // cancelled by user
 
     value    = dlg.GetValue();
-    gap_size = EDA_UNIT_UTILS::UI::ValueFromString( pcbIUScale, editFrame.GetUserUnits(), value );
+    gap_size = editFrame->ValueFromString( value );
 
     bool abort = false;
 
     if( aFootprintShape == MICROWAVE_FOOTPRINT_SHAPE::STUB_ARC )
     {
         msg = wxT( "0.0" );
-        WX_TEXT_ENTRY_DIALOG angledlg( &editFrame, _( "Angle in degrees:" ),
+        WX_TEXT_ENTRY_DIALOG angledlg( editFrame, _( "Angle in degrees:" ),
                                        _( "Create Microwave Footprint" ), msg );
 
         if( angledlg.ShowQuasiModal() != wxID_OK )
@@ -102,7 +102,7 @@ FOOTPRINT* MICROWAVE_TOOL::createFootprint( MICROWAVE_FOOTPRINT_SHAPE aFootprint
 
         if( !msg.ToDouble( &fval ) )
         {
-            DisplayError( &editFrame, _( "Incorrect number, abort" ) );
+            DisplayError( editFrame, _( "Incorrect number, abort" ) );
             abort = true;
         }
 
@@ -181,7 +181,7 @@ FOOTPRINT* MICROWAVE_TOOL::createFootprint( MICROWAVE_FOOTPRINT_SHAPE aFootprint
     }
 
     // Update the footprint and board
-    editFrame.OnModify();
+    editFrame->OnModify();
 
     return footprint;
 }
diff --git a/pcbnew/microwave/microwave_inductor.cpp b/pcbnew/microwave/microwave_inductor.cpp
index 47caadc959..d6f153a249 100644
--- a/pcbnew/microwave/microwave_inductor.cpp
+++ b/pcbnew/microwave/microwave_inductor.cpp
@@ -354,25 +354,21 @@ FOOTPRINT* MICROWAVE_TOOL::createMicrowaveInductor( MICROWAVE_INDUCTOR_PATTERN&
      * (Radius decreases if necessary)
      */
 
-    PAD*     pad;
-    wxString msg;
-
-    PCB_EDIT_FRAME& editFrame = *getEditFrame<PCB_EDIT_FRAME>();
+    PAD*            pad;
+    PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
 
     wxPoint pt      = aInductorPattern.m_End - aInductorPattern.m_Start;
-    int  min_len = KiROUND( EuclideanNorm( pt ) );
+    int     min_len = KiROUND( EuclideanNorm( pt ) );
     aInductorPattern.m_Length = min_len;
 
     // Enter the desired length.
-    msg = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, editFrame.GetUserUnits(), aInductorPattern.m_Length );
-    WX_TEXT_ENTRY_DIALOG dlg( &editFrame, _( "Length of Trace:" ), wxEmptyString, msg );
+    wxString             msg = editFrame->StringFromValue( aInductorPattern.m_Length );
+    WX_TEXT_ENTRY_DIALOG dlg( editFrame, _( "Length of Trace:" ), wxEmptyString, msg );
 
     if( dlg.ShowQuasiModal() != wxID_OK )
         return nullptr; // canceled by user
 
-    msg = dlg.GetValue();
-    aInductorPattern.m_Length =
-            EDA_UNIT_UTILS::UI::ValueFromString( pcbIUScale, editFrame.GetUserUnits(), msg );
+    aInductorPattern.m_Length = editFrame->ValueFromString( dlg.GetValue() );
 
     // Control values (ii = minimum length)
     if( aInductorPattern.m_Length < min_len )
@@ -405,13 +401,13 @@ FOOTPRINT* MICROWAVE_TOOL::createMicrowaveInductor( MICROWAVE_INDUCTOR_PATTERN&
 
     // Generate footprint. the value is also used as footprint name.
     msg = wxT( "L" );
-    WX_TEXT_ENTRY_DIALOG cmpdlg( &editFrame, _( "Component Value:" ), wxEmptyString, msg );
+    WX_TEXT_ENTRY_DIALOG cmpdlg( editFrame, _( "Component Value:" ), wxEmptyString, msg );
     cmpdlg.SetTextValidator( FOOTPRINT_NAME_VALIDATOR( &msg ) );
 
     if( ( cmpdlg.ShowQuasiModal() != wxID_OK ) || msg.IsEmpty() )
         return nullptr;    //  Aborted by user
 
-    FOOTPRINT* footprint = editFrame.CreateNewFootprint( msg, true );
+    FOOTPRINT* footprint = editFrame->CreateNewFootprint( msg, true );
 
     footprint->SetFPID( LIB_ID( wxEmptyString, wxT( "mw_inductor" ) ) );
     footprint->SetAttributes( FP_EXCLUDE_FROM_POS_FILES | FP_EXCLUDE_FROM_BOM );
diff --git a/pcbnew/netinfo_item.cpp b/pcbnew/netinfo_item.cpp
index 0e0f1afbff..0741245ec5 100644
--- a/pcbnew/netinfo_item.cpp
+++ b/pcbnew/netinfo_item.cpp
@@ -128,16 +128,14 @@ void NETINFO_ITEM::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANE
             std::tie( count, lengthNet, lengthPadToDie ) = board->GetTrackLength( *startTrack );
 
             // Displays the full net length (tracks on pcb + internal ICs connections ):
-            msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, aFrame->GetUserUnits(), lengthNet + lengthPadToDie );
-            aList.emplace_back( _( "Net Length" ), msg );
+            aList.emplace_back( _( "Net Length" ),
+                                aFrame->MessageTextFromValue( lengthNet + lengthPadToDie ) );
 
             // Displays the net length of tracks only:
-            msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, aFrame->GetUserUnits(), lengthNet );
-            aList.emplace_back( _( "On Board" ), msg );
+            aList.emplace_back( _( "On Board" ), aFrame->MessageTextFromValue( lengthNet ) );
 
             // Displays the net length of internal ICs connections (wires inside ICs):
-            msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, aFrame->GetUserUnits(), lengthPadToDie );
-            aList.emplace_back( _( "In Package" ), msg );
+            aList.emplace_back( _( "In Package" ), aFrame->MessageTextFromValue( lengthPadToDie ) );
         }
     }
 }
diff --git a/pcbnew/netlist_reader/board_netlist_updater.cpp b/pcbnew/netlist_reader/board_netlist_updater.cpp
index 4ccd6e6c80..e61fbf7cf8 100644
--- a/pcbnew/netlist_reader/board_netlist_updater.cpp
+++ b/pcbnew/netlist_reader/board_netlist_updater.cpp
@@ -806,8 +806,8 @@ bool BOARD_NETLIST_UPDATER::updateCopperZoneNets( NETLIST& aNetlist )
 
                     msg.Printf( _( "Copper zone on layer %s at (%s, %s) has no pads connected." ),
                                 m_board->GetLayerName( layer ),
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_frame->GetUserUnits(), pos.x ),
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_frame->GetUserUnits(), pos.y ) );
+                                m_frame->MessageTextFromValue( pos.x ),
+                                m_frame->MessageTextFromValue( pos.y ) );
                 }
 
                 m_reporter->Report( msg, RPT_SEVERITY_WARNING );
diff --git a/pcbnew/pad.cpp b/pcbnew/pad.cpp
index 5ff7b49f1e..63d4be3eaf 100644
--- a/pcbnew/pad.cpp
+++ b/pcbnew/pad.cpp
@@ -933,7 +933,6 @@ int PAD::GetLocalThermalGapOverride( wxString* aSource ) const
 
 void PAD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
-    EDA_UNITS  units = aFrame->GetUserUnits();
     wxString   msg;
     FOOTPRINT* parentFootprint = static_cast<FOOTPRINT*>( m_parent );
 
@@ -984,15 +983,15 @@ void PAD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>&
 
     aList.emplace_back( ShowPadShape(), props );
 
-    if( ( GetShape() == PAD_SHAPE::CIRCLE || GetShape() == PAD_SHAPE::OVAL ) &&
-        m_size.x == m_size.y )
+    if( ( GetShape() == PAD_SHAPE::CIRCLE || GetShape() == PAD_SHAPE::OVAL )
+            && m_size.x == m_size.y )
     {
-        aList.emplace_back( _( "Diameter" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, m_size.x ) );
+        aList.emplace_back( _( "Diameter" ), aFrame->MessageTextFromValue( m_size.x ) );
     }
     else
     {
-        aList.emplace_back( _( "Width" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, m_size.x ) );
-        aList.emplace_back( _( "Height" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, m_size.y ) );
+        aList.emplace_back( _( "Width" ), aFrame->MessageTextFromValue( m_size.x ) );
+        aList.emplace_back( _( "Height" ), aFrame->MessageTextFromValue( m_size.y ) );
     }
 
     EDA_ANGLE fp_orient = parentFootprint ? parentFootprint->GetOrientation() : ANGLE_0;
@@ -1008,8 +1007,8 @@ void PAD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>&
 
     if( GetPadToDieLength() )
     {
-        msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, GetPadToDieLength() );
-        aList.emplace_back( _( "Length in Package" ), msg );
+        aList.emplace_back( _( "Length in Package" ),
+                            aFrame->MessageTextFromValue( GetPadToDieLength() ) );
     }
 
     if( m_drill.x > 0 || m_drill.y > 0 )
@@ -1018,14 +1017,14 @@ void PAD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>&
         {
             aList.emplace_back( _( "Hole" ),
                                 wxString::Format( wxT( "%s" ),
-                                                  EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, m_drill.x ) ) );
+                                                  aFrame->MessageTextFromValue( m_drill.x ) ) );
         }
         else
         {
             aList.emplace_back( _( "Hole X / Y" ),
                                 wxString::Format( wxT( "%s / %s" ),
-                                                  EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, m_drill.x ),
-                                                  EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, m_drill.y ) ) );
+                                                  aFrame->MessageTextFromValue( m_drill.x ),
+                                                  aFrame->MessageTextFromValue( m_drill.y ) ) );
         }
     }
 
@@ -1035,7 +1034,7 @@ void PAD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>&
     if( !source.IsEmpty() )
     {
         aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
-                                              EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, clearance ) ),
+                                              aFrame->MessageTextFromValue( clearance ) ),
                             wxString::Format( _( "(from %s)" ),
                                               source ) );
     }
diff --git a/pcbnew/pcb_base_frame.cpp b/pcbnew/pcb_base_frame.cpp
index fd9ba9487f..8f3ae60674 100644
--- a/pcbnew/pcb_base_frame.cpp
+++ b/pcbnew/pcb_base_frame.cpp
@@ -783,10 +783,8 @@ void PCB_BASE_FRAME::DisplayGridMsg()
     wxString line;
 
     line.Printf( wxT( "grid X %s  Y %s" ),
-                 EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), m_userUnits, gridSize.x,
-                                                           false ),
-                 EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), m_userUnits, gridSize.y,
-                                                           false ) );
+                 MessageTextFromValue( gridSize.x, false ),
+                 MessageTextFromValue( gridSize.y, false ) );
 
     SetStatusText( line, 4 );
 }
@@ -812,8 +810,8 @@ void PCB_BASE_FRAME::UpdateStatusBar()
         double   ro = hypot( dx, dy );
 
         line.Printf( wxT( "r %s  theta %.3f" ),
-                EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(), ro, false ),
-                theta );
+                     MessageTextFromValue( ro, false ),
+                     theta );
 
         SetStatusText( line, 3 );
     }
@@ -824,10 +822,8 @@ void PCB_BASE_FRAME::UpdateStatusBar()
 
     // Display absolute coordinates:
     line.Printf( wxT( "X %s  Y %s" ),
-                 EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(), userXpos,
-                                                           false ),
-                 EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(), userYpos,
-                                                           false ) );
+                 MessageTextFromValue( userXpos, false ),
+                 MessageTextFromValue( userYpos, false ) );
     SetStatusText( line, 2 );
 
     if( !GetShowPolarCoords() )  // display relative cartesian coordinates
@@ -841,12 +837,9 @@ void PCB_BASE_FRAME::UpdateStatusBar()
         userYpos = m_originTransforms.ToDisplayRelY( relYpos );
 
         line.Printf( wxT( "dx %s  dy %s  dist %s" ),
-                     EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(),
-                                                               userXpos, false ),
-                     EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(),
-                                                               userYpos, false ),
-                     EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(),
-                                                               hypot( userXpos, userYpos ), false ) );
+                     MessageTextFromValue( userXpos, false ),
+                     MessageTextFromValue( userYpos, false ),
+                     MessageTextFromValue( hypot( userXpos, userYpos ), false ) );
         SetStatusText( line, 3 );
     }
 
diff --git a/pcbnew/pcb_bitmap.cpp b/pcbnew/pcb_bitmap.cpp
index 7ef9053bad..39195000c5 100644
--- a/pcbnew/pcb_bitmap.cpp
+++ b/pcbnew/pcb_bitmap.cpp
@@ -208,9 +208,8 @@ void PCB_BITMAP::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_
 {
     aList.emplace_back( _( "Bitmap" ), wxEmptyString );
 
-    aList.emplace_back( _( "Width" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, aFrame->GetUserUnits(), GetSize().x ) );
-    aList.emplace_back( _( "Height" ),
-                        EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, aFrame->GetUserUnits(), GetSize().y ) );
+    aList.emplace_back( _( "Width" ), aFrame->MessageTextFromValue( GetSize().x ) );
+    aList.emplace_back( _( "Height" ), aFrame->MessageTextFromValue( GetSize().y ) );
     aList.emplace_back( _( "Layer" ), LayerName( m_layer ) );
 }
 
diff --git a/pcbnew/pcb_dimension.cpp b/pcbnew/pcb_dimension.cpp
index 5ef6f6a266..5d79e32902 100644
--- a/pcbnew/pcb_dimension.cpp
+++ b/pcbnew/pcb_dimension.cpp
@@ -78,13 +78,11 @@ void PCB_DIMENSION_BASE::updateText()
         break;
 
     case DIM_UNITS_FORMAT::BARE_SUFFIX: // normal
-        text += EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( m_units );
+        text += EDA_UNIT_UTILS::GetText( m_units );
         break;
 
     case DIM_UNITS_FORMAT::PAREN_SUFFIX: // parenthetical
-        text += wxT( " (" );
-        text += EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( m_units ).Trim( false );
-        text += wxT( ")" );
+        text += wxT( " (" ) + EDA_UNIT_UTILS::GetText( m_units ).Trim( false ) + wxT( ")" );
         break;
     }
 
@@ -308,20 +306,11 @@ void PCB_DIMENSION_BASE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
 
         switch( GetPrecision() )
         {
-        case 6:
-            msg = wxT( "0.00 in / 0 mils / 0.0 mm" );
-            break;
-        case 7:
-            msg = wxT( "0.000 in / 0 mils / 0.00 mm" );
-            break;
-        case 8:
-            msg = wxT( "0.0000 in / 0.0 mils / 0.000 mm" );
-            break;
-        case 9:
-            msg = wxT( "0.00000 in / 0.00 mils / 0.0000 mm" );
-            break;
-        default:
-            msg = wxT( "%" ) + wxString::Format( wxT( "1.%df" ), GetPrecision() );
+        case 6:  msg = wxT( "0.00 in / 0 mils / 0.0 mm" );          break;
+        case 7:  msg = wxT( "0.000 in / 0 mils / 0.00 mm" );        break;
+        case 8:  msg = wxT( "0.0000 in / 0.0 mils / 0.000 mm" );    break;
+        case 9:  msg = wxT( "0.00000 in / 0.00 mils / 0.0000 mm" ); break;
+        default: msg = wxT( "%" ) + wxString::Format( wxT( "1.%df" ), GetPrecision() );
         }
 
         aList.emplace_back( _( "Precision" ), wxString::Format( msg, 0.0 ) );
@@ -332,13 +321,15 @@ void PCB_DIMENSION_BASE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
     EDA_UNITS units;
 
     GetUnits( units );
-    aList.emplace_back( _( "Units" ), EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( units ).Trim( false ) );
+    aList.emplace_back( _( "Units" ), EDA_UNIT_UTILS::GetLabel( units ) );
 
     aList.emplace_back( _( "Font" ), m_text.GetDrawFont()->GetName() );
     aList.emplace_back( _( "Text Thickness" ),
                         EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, m_text.GetTextThickness() ) );
-    aList.emplace_back( _( "Text Width" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, m_text.GetTextWidth() ) );
-    aList.emplace_back( _( "Text Height" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, m_text.GetTextHeight() ) );
+    aList.emplace_back( _( "Text Width" ),
+                        EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, m_text.GetTextWidth() ) );
+    aList.emplace_back( _( "Text Height" ),
+                        EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, m_text.GetTextHeight() ) );
 
     ORIGIN_TRANSFORMS originTransforms = aFrame->GetOriginTransforms();
     units = aFrame->GetUserUnits();
@@ -738,7 +729,11 @@ void PCB_DIM_ALIGNED::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_P
 {
     PCB_DIMENSION_BASE::GetMsgPanelInfo( aFrame, aList );
 
-    aList.emplace_back( _( "Height" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, aFrame->GetUserUnits(), m_height ) );
+    EDA_UNITS units;
+    GetUnits( units );
+
+    aList.emplace_back( _( "Height" ),
+                        EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, m_height ) );
 }
 
 
diff --git a/pcbnew/pcb_target.cpp b/pcbnew/pcb_target.cpp
index 0b18bdf608..594bf47218 100644
--- a/pcbnew/pcb_target.cpp
+++ b/pcbnew/pcb_target.cpp
@@ -148,22 +148,20 @@ void PCB_TARGET::SwapData( BOARD_ITEM* aImage )
 
 void PCB_TARGET::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
-    EDA_UNITS units = aFrame->GetUserUnits();
-
     aList.emplace_back( _( "PCB Target" ), wxEmptyString );
 
     aList.emplace_back( _( "Layer" ), GetLayerName() );
 
-    aList.emplace_back( _( "Size" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, GetSize() ) );
-    aList.emplace_back( _( "Width" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, GetWidth() ) );
+    aList.emplace_back( _( "Size" ), aFrame->MessageTextFromValue( GetSize() ) );
+    aList.emplace_back( _( "Width" ), aFrame->MessageTextFromValue( GetWidth() ) );
     aList.emplace_back( _( "Shape" ), GetShape() == 0 ? wxT( "+" ) : wxT( "X" ) );
 }
 
 
 void PCB_TARGET::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
-                                               PCB_LAYER_ID aLayer, int aClearanceValue,
-                                               int aError, ERROR_LOC aErrorLoc,
-                                               bool ignoreLineWidth ) const
+                                                       PCB_LAYER_ID aLayer, int aClearanceValue,
+                                                       int aError, ERROR_LOC aErrorLoc,
+                                                       bool ignoreLineWidth ) const
 {
     int size = GetShape() ? GetSize() / 1.5 : GetSize() / 2.0;
     int radius = GetShape() ? GetSize() / 2.0 : GetSize() / 3.0;
diff --git a/pcbnew/pcb_text.cpp b/pcbnew/pcb_text.cpp
index 8b9d5c19fd..d26b963ac2 100644
--- a/pcbnew/pcb_text.cpp
+++ b/pcbnew/pcb_text.cpp
@@ -127,8 +127,6 @@ double PCB_TEXT::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
 
 void PCB_TEXT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
-    EDA_UNITS units = aFrame->GetUserUnits();
-
     // Don't use GetShownText() here; we want to show the user the variable references
     aList.emplace_back( _( "PCB Text" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
 
@@ -142,9 +140,9 @@ void PCB_TEXT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_IT
     aList.emplace_back( _( "Angle" ), wxString::Format( wxT( "%g" ), GetTextAngle().AsDegrees() ) );
 
     aList.emplace_back( _( "Font" ), GetDrawFont()->GetName() );
-    aList.emplace_back( _( "Thickness" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, GetTextThickness() ) );
-    aList.emplace_back( _( "Width" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, GetTextWidth() ) );
-    aList.emplace_back( _( "Height" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, GetTextHeight() ) );
+    aList.emplace_back( _( "Thickness" ), aFrame->MessageTextFromValue( GetTextThickness() ) );
+    aList.emplace_back( _( "Width" ), aFrame->MessageTextFromValue( GetTextWidth() ) );
+    aList.emplace_back( _( "Height" ), aFrame->MessageTextFromValue( GetTextHeight() ) );
 }
 
 
diff --git a/pcbnew/pcb_textbox.cpp b/pcbnew/pcb_textbox.cpp
index 922fb1d6ab..f5a9fa34e9 100644
--- a/pcbnew/pcb_textbox.cpp
+++ b/pcbnew/pcb_textbox.cpp
@@ -295,8 +295,6 @@ wxString PCB_TEXTBOX::GetShownText( int aDepth ) const
 
 void PCB_TEXTBOX::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
-    EDA_UNITS units = aFrame->GetUserUnits();
-
     // Don't use GetShownText() here; we want to show the user the variable references
     aList.emplace_back( _( "Text Box" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
 
@@ -308,17 +306,17 @@ void PCB_TEXTBOX::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL
     aList.emplace_back( _( "Angle" ), wxString::Format( "%g", GetTextAngle().AsDegrees() ) );
 
     aList.emplace_back( _( "Font" ), GetDrawFont()->GetName() );
-    aList.emplace_back( _( "Text Thickness" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, GetTextThickness() ) );
-    aList.emplace_back( _( "Text Width" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, GetTextWidth() ) );
-    aList.emplace_back( _( "Text Height" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, GetTextHeight() ) );
+    aList.emplace_back( _( "Text Thickness" ), aFrame->MessageTextFromValue( GetTextThickness() ) );
+    aList.emplace_back( _( "Text Width" ), aFrame->MessageTextFromValue( GetTextWidth() ) );
+    aList.emplace_back( _( "Text Height" ), aFrame->MessageTextFromValue( GetTextHeight() ) );
 
-    wxString msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, std::abs( GetEnd().x - GetStart().x ) );
-    aList.emplace_back( _( "Box Width" ), msg );
+    aList.emplace_back( _( "Box Width" ),
+                        aFrame->MessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) ) );
 
-    msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, std::abs( GetEnd().y - GetStart().y ) );
-    aList.emplace_back( _( "Box Height" ), msg );
+    aList.emplace_back( _( "Box Height" ),
+                        aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) ));
 
-    m_stroke.GetMsgPanelInfo( pcbIUScale, units, aList );
+    m_stroke.GetMsgPanelInfo( pcbIUScale, aFrame->GetUserUnits(), aList );
 }
 
 
diff --git a/pcbnew/pcb_track.cpp b/pcbnew/pcb_track.cpp
index 9fa6cd72ec..4af88c1c38 100644
--- a/pcbnew/pcb_track.cpp
+++ b/pcbnew/pcb_track.cpp
@@ -776,7 +776,6 @@ double PCB_VIA::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
 // see class_track.h
 void PCB_TRACK::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
-    EDA_UNITS units = aFrame->GetUserUnits();
     wxString  msg;
     BOARD*    board = GetBoard();
 
@@ -788,15 +787,15 @@ void PCB_TRACK::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_I
 
     aList.emplace_back( _( "Layer" ), layerMaskDescribe() );
 
-    aList.emplace_back( _( "Width" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, m_Width ) );
+    aList.emplace_back( _( "Width" ), aFrame->MessageTextFromValue( m_Width ) );
 
     if( Type() == PCB_ARC_T )
     {
         double radius = static_cast<PCB_ARC*>( this )->GetRadius();
-        aList.emplace_back( _( "Radius" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, radius ) );
+        aList.emplace_back( _( "Radius" ), aFrame->MessageTextFromValue( radius ) );
     }
 
-    aList.emplace_back( _( "Segment Length" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, GetLength() ) );
+    aList.emplace_back( _( "Segment Length" ), aFrame->MessageTextFromValue( GetLength() ) );
 
     // Display full track length (in Pcbnew)
     if( board && GetNetCode() > 0 )
@@ -807,14 +806,14 @@ void PCB_TRACK::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_I
 
         std::tie( count, trackLen, lenPadToDie ) = board->GetTrackLength( *this );
 
-        aList.emplace_back( _( "Routed Length" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, trackLen ) );
+        aList.emplace_back( _( "Routed Length" ), aFrame->MessageTextFromValue( trackLen ) );
 
         if( lenPadToDie != 0 )
         {
-            msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, lenPadToDie );
+            msg = aFrame->MessageTextFromValue( lenPadToDie );
             aList.emplace_back( _( "Pad To Die Length" ), msg );
 
-            msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, trackLen + lenPadToDie );
+            msg = aFrame->MessageTextFromValue( trackLen + lenPadToDie );
             aList.emplace_back( _( "Full Length" ), msg );
         }
     }
@@ -823,7 +822,7 @@ void PCB_TRACK::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_I
     int clearance = GetOwnClearance( GetLayer(), &source );
 
     aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
-                                          EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, clearance ) ),
+                                          aFrame->MessageTextFromValue( clearance ) ),
                         wxString::Format( _( "(from %s)" ), source ) );
 
     MINOPTMAX<int> c = GetWidthConstraint( &source );
@@ -831,14 +830,14 @@ void PCB_TRACK::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_I
     if( c.HasMax() )
     {
         aList.emplace_back( wxString::Format( _( "Width Constraints: min %s, max %s" ),
-                                              EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, c.Min() ),
-                                              EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, c.Max() ) ),
+                                              aFrame->MessageTextFromValue( c.Min() ),
+                                              aFrame->MessageTextFromValue( c.Max() ) ),
                             wxString::Format( _( "(from %s)" ), source ) );
     }
     else
     {
         aList.emplace_back( wxString::Format( _( "Width Constraints: min %s" ),
-                                              EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, c.Min() ) ),
+                                              aFrame->MessageTextFromValue( c.Min() ) ),
                             wxString::Format( _( "(from %s)" ), source ) );
     }
 }
@@ -846,7 +845,6 @@ void PCB_TRACK::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_I
 
 void PCB_VIA::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
-    EDA_UNITS units = aFrame->GetUserUnits();
     wxString  msg;
 
     switch( GetViaType() )
@@ -862,26 +860,20 @@ void PCB_VIA::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITE
     GetMsgPanelInfoBase_Common( aFrame, aList );
 
     aList.emplace_back( _( "Layer" ), layerMaskDescribe() );
-
-    msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, aFrame->GetUserUnits(), m_Width );
-
-    aList.emplace_back( _( "Diameter" ), msg );
-
-    msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, aFrame->GetUserUnits(), GetDrillValue() );
-
-    aList.emplace_back( _( "Hole" ), msg );
+    aList.emplace_back( _( "Diameter" ), aFrame->MessageTextFromValue( m_Width ) );
+    aList.emplace_back( _( "Hole" ), aFrame->MessageTextFromValue( GetDrillValue() ) );
 
     wxString  source;
     int clearance = GetOwnClearance( GetLayer(), &source );
 
     aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
-                                          EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, clearance ) ),
+                                          aFrame->MessageTextFromValue( clearance ) ),
                         wxString::Format( _( "(from %s)" ), source ) );
 
     int minAnnulus = GetMinAnnulus( GetLayer(), &source );
 
     aList.emplace_back( wxString::Format( _( "Min Annular Width: %s" ),
-                                          EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, minAnnulus ) ),
+                                          aFrame->MessageTextFromValue( minAnnulus ) ),
                         wxString::Format( _( "(from %s)" ), source ) );
 }
 
@@ -1181,39 +1173,6 @@ void PCB_TRACK::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf
 }
 
 
-#if defined(DEBUG)
-
-wxString PCB_TRACK::ShowState( int stateBits )
-{
-    wxString ret;
-
-    if( stateBits & IS_LINKED )
-        ret << wxT( " | IS_LINKED" );
-
-    if( stateBits & IN_EDIT )
-        ret << wxT( " | IN_EDIT" );
-
-    if( stateBits & IS_DRAGGING )
-        ret << wxT( " | IS_DRAGGING" );
-
-    if( stateBits & DO_NOT_DRAW )
-        ret << wxT( " | DO_NOT_DRAW" );
-
-    if( stateBits & IS_DELETED )
-        ret << wxT( " | IS_DELETED" );
-
-    if( stateBits & END_ONPAD )
-        ret << wxT( " | END_ONPAD" );
-
-    if( stateBits & BEGIN_ONPAD )
-        ret << wxT( " | BEGIN_ONPAD" );
-
-    return ret;
-}
-
-#endif
-
-
 static struct TRACK_VIA_DESC
 {
     TRACK_VIA_DESC()
diff --git a/pcbnew/pcb_track.h b/pcbnew/pcb_track.h
index 3185c00f5a..de7f770fc6 100644
--- a/pcbnew/pcb_track.h
+++ b/pcbnew/pcb_track.h
@@ -225,14 +225,6 @@ public:
 
 #if defined (DEBUG)
     virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
-
-    /**
-     * Function ShowState
-     * converts a set of state bits to a wxString
-     * @param stateBits Is an OR-ed together set of bits like IN_EDIT, etc.
-     */
-    static wxString ShowState( int stateBits );
-
 #endif
 
 protected:
diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp
index 7c3fc99ea7..02e280615c 100644
--- a/pcbnew/router/router_tool.cpp
+++ b/pcbnew/router/router_tool.cpp
@@ -199,7 +199,6 @@ protected:
 
     void update() override
     {
-        EDA_UNITS              units = m_frame.GetUserUnits();
         BOARD_DESIGN_SETTINGS& bds = m_frame.GetBoard()->GetDesignSettings();
         bool                   useIndex = !bds.m_UseConnectedTrackWidth &&
                                           !bds.UseCustomTrackViaSize();
@@ -231,7 +230,7 @@ protected:
             if( i == 0 )
                 msg = _( "Track netclass width" );
             else
-                msg.Printf( _( "Track %s" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, width ) );
+                msg.Printf( _( "Track %s" ), m_frame.MessageTextFromValue( width ) );
 
             int menuIdx = ID_POPUP_PCB_SELECT_WIDTH1 + i;
             Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
@@ -249,11 +248,16 @@ protected:
             else
             {
                 if( via.m_Drill > 0 )
+                {
                     msg.Printf( _("Via %s, hole %s" ),
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, via.m_Diameter ),
-                                EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, via.m_Drill ) );
+                                m_frame.MessageTextFromValue( via.m_Diameter ),
+                                m_frame.MessageTextFromValue( via.m_Drill ) );
+                }
                 else
-                    msg.Printf( _( "Via %s" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, via.m_Diameter ) );
+                {
+                    msg.Printf( _( "Via %s" ),
+                                m_frame.MessageTextFromValue( via.m_Diameter ) );
+                }
             }
 
             int menuIdx = ID_POPUP_PCB_SELECT_VIASIZE1 + i;
@@ -328,7 +332,6 @@ protected:
 
     void update() override
     {
-        EDA_UNITS                    units = m_frame.GetUserUnits();
         const BOARD_DESIGN_SETTINGS& bds = m_frame.GetBoard()->GetDesignSettings();
 
         Clear();
@@ -357,13 +360,13 @@ protected:
                 if( diffPair.m_ViaGap <= 0 )
                 {
                     msg.Printf( _( "Width %s" ),
-                                    EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, diffPair.m_Width ) );
+                                m_frame.MessageTextFromValue( diffPair.m_Width ) );
                 }
                 else
                 {
                     msg.Printf( _( "Width %s, via gap %s" ),
-                                    EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, diffPair.m_Width ),
-                                    EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, diffPair.m_ViaGap ) );
+                                m_frame.MessageTextFromValue( diffPair.m_Width ),
+                                m_frame.MessageTextFromValue( diffPair.m_ViaGap ) );
                 }
             }
             else
@@ -371,15 +374,15 @@ protected:
                 if( diffPair.m_ViaGap <= 0 )
                 {
                     msg.Printf( _( "Width %s, gap %s" ),
-                                    EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, diffPair.m_Width ),
-                                    EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, diffPair.m_Gap ) );
+                                m_frame.MessageTextFromValue( diffPair.m_Width ),
+                                m_frame.MessageTextFromValue( diffPair.m_Gap ) );
                 }
                 else
                 {
                     msg.Printf( _( "Width %s, gap %s, via gap %s" ),
-                                    EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, diffPair.m_Width ),
-                                    EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, diffPair.m_Gap ),
-                                    EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, diffPair.m_ViaGap ) );
+                                m_frame.MessageTextFromValue( diffPair.m_Width ),
+                                m_frame.MessageTextFromValue( diffPair.m_Gap ),
+                                m_frame.MessageTextFromValue( diffPair.m_ViaGap ) );
                 }
             }
 
@@ -2410,12 +2413,11 @@ void ROUTER_TOOL::UpdateMessagePanel()
 
     items.emplace_back( _( "Corner Style" ), cornerMode );
 
-    EDA_UNITS units = frame()->GetUserUnits();
-
     int width = isDiffPair ? sizes.DiffPairWidth() : sizes.TrackWidth();
     items.emplace_back( wxString::Format( _( "Track Width: %s" ),
-                                          EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, width ) ),
-                        wxString::Format( _( "(from %s)" ), sizes.GetWidthSource() ) );
+                                          frame()->MessageTextFromValue( width ) ),
+                        wxString::Format( _( "(from %s)" ),
+                                          sizes.GetWidthSource() ) );
 
     if( m_startItem )
     {
@@ -2428,15 +2430,16 @@ void ROUTER_TOOL::UpdateMessagePanel()
                                        m_router->GetCurrentLayer(), &constraint ) )
         {
             items.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
-                                        EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, constraint.m_Value.Min() ) ),
-                                wxString::Format( _( "(from %s)" ), constraint.m_RuleName ) );
+                                                  frame()->MessageTextFromValue( constraint.m_Value.Min() ) ),
+                                wxString::Format( _( "(from %s)" ),
+                                                  constraint.m_RuleName ) );
         }
     }
 
     if( isDiffPair )
     {
         items.emplace_back( _( "Diff Pair Gap" ),
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, sizes.DiffPairGap() ) );
+                            frame()->MessageTextFromValue( sizes.DiffPairGap() ) );
     }
 
     frame()->SetMsgPanel( items );
diff --git a/pcbnew/toolbars_pcb_editor.cpp b/pcbnew/toolbars_pcb_editor.cpp
index 8fb82987df..43f1d610b9 100644
--- a/pcbnew/toolbars_pcb_editor.cpp
+++ b/pcbnew/toolbars_pcb_editor.cpp
@@ -635,7 +635,7 @@ static wxString ComboBoxUnits( EDA_UNITS aUnits, double aValue, bool aIncludeLab
     text.Printf( format, EDA_UNIT_UTILS::UI::ToUserUnit( pcbIUScale, aUnits, aValue ) );
 
     if( aIncludeLabel )
-        text += EDA_UNIT_UTILS::GetAbbreviatedUnitsLabel( aUnits, EDA_DATA_TYPE::DISTANCE );
+        text += EDA_UNIT_UTILS::GetText( aUnits, EDA_DATA_TYPE::DISTANCE );
 
     return text;
 }
diff --git a/pcbnew/tools/board_inspection_tool.cpp b/pcbnew/tools/board_inspection_tool.cpp
index 3e8b75f681..bb637fd576 100644
--- a/pcbnew/tools/board_inspection_tool.cpp
+++ b/pcbnew/tools/board_inspection_tool.cpp
@@ -204,28 +204,28 @@ void BOARD_INSPECTION_TOOL::reportHeader( const wxString& aTitle, BOARD_ITEM* a,
 }
 
 
-wxString reportMin( EDA_UNITS aUnits, DRC_CONSTRAINT& aConstraint )
+wxString reportMin( PCB_BASE_FRAME* aFrame, DRC_CONSTRAINT& aConstraint )
 {
     if( aConstraint.m_Value.HasMin() )
-        return EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, aUnits, aConstraint.m_Value.Min(), true );
+        return aFrame->StringFromValue( aConstraint.m_Value.Min(), true );
     else
         return wxT( "<i>" ) + _( "undefined" ) + wxT( "</i>" );
 }
 
 
-wxString reportOpt( EDA_UNITS aUnits, DRC_CONSTRAINT& aConstraint )
+wxString reportOpt( PCB_BASE_FRAME* aFrame, DRC_CONSTRAINT& aConstraint )
 {
     if( aConstraint.m_Value.HasOpt() )
-        return EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, aUnits, aConstraint.m_Value.Opt(), true );
+        return aFrame->StringFromValue( aConstraint.m_Value.Opt(), true );
     else
         return wxT( "<i>" ) + _( "undefined" ) + wxT( "</i>" );
 }
 
 
-wxString reportMax( EDA_UNITS aUnits, DRC_CONSTRAINT& aConstraint )
+wxString reportMax( PCB_BASE_FRAME* aFrame, DRC_CONSTRAINT& aConstraint )
 {
     if( aConstraint.m_Value.HasMax() )
-        return EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, aUnits, aConstraint.m_Value.Max(), true );
+        return aFrame->StringFromValue( aConstraint.m_Value.Max(), true );
     else
         return wxT( "<i>" ) + _( "undefined" ) + wxT( "</i>" );
 }
@@ -278,7 +278,7 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
 
         r->Report( "" );
         r->Report( wxString::Format( _( "Resolved max uncoupled length: %s." ),
-                                     reportMax( r->GetUnits(),  constraint ) ) );
+                                     reportMax( m_frame, constraint ) ) );
         break;
     }
 
@@ -293,8 +293,8 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
 
         r->Report( "" );
         r->Report( wxString::Format( _( "Resolved height constraints: min %s; max %s." ),
-                                     reportMin( r->GetUnits(),  constraint ),
-                                     reportMax( r->GetUnits(),  constraint ) ) );
+                                     reportMin( m_frame, constraint ),
+                                     reportMax( m_frame, constraint ) ) );
         break;
 
     case DRCE_TEXT_THICKNESS:
@@ -308,8 +308,8 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
 
         r->Report( "" );
         r->Report( wxString::Format( _( "Resolved thickness constraints: min %s; max %s." ),
-                                     reportMin( r->GetUnits(),  constraint ),
-                                     reportMax( r->GetUnits(),  constraint ) ) );
+                                     reportMin( m_frame, constraint ),
+                                     reportMax( m_frame, constraint ) ) );
         break;
 
     case DRCE_TRACK_WIDTH:
@@ -323,8 +323,8 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
 
         r->Report( "" );
         r->Report( wxString::Format( _( "Resolved width constraints: min %s; max %s." ),
-                                     reportMin( r->GetUnits(),  constraint ),
-                                     reportMax( r->GetUnits(),  constraint ) ) );
+                                     reportMin( m_frame, constraint ),
+                                     reportMax( m_frame, constraint ) ) );
         break;
 
     case DRCE_CONNECTION_WIDTH:
@@ -338,7 +338,7 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
 
         r->Report( "" );
         r->Report( wxString::Format( _( "Resolved min connection width constraint: %s." ),
-                                     reportMin( r->GetUnits(),  constraint ) ) );
+                                     reportMin( m_frame, constraint ) ) );
         break;
 
     case DRCE_VIA_DIAMETER:
@@ -352,8 +352,8 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
 
         r->Report( "" );
         r->Report( wxString::Format( _( "Resolved diameter constraints: min %s; max %s." ),
-                                     reportMin( r->GetUnits(),  constraint ),
-                                     reportMax( r->GetUnits(),  constraint ) ) );
+                                     reportMin( m_frame, constraint ),
+                                     reportMax( m_frame, constraint ) ) );
         break;
 
     case DRCE_ANNULAR_WIDTH:
@@ -367,8 +367,8 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
 
         r->Report( "" );
         r->Report( wxString::Format( _( "Resolved annular width constraints: min %s; max %s." ),
-                                     reportMin( r->GetUnits(),  constraint ),
-                                     reportMax( r->GetUnits(),  constraint ) ) );
+                                     reportMin( m_frame, constraint ),
+                                     reportMax( m_frame, constraint ) ) );
         break;
 
     case DRCE_DRILL_OUT_OF_RANGE:
@@ -383,8 +383,8 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
 
         r->Report( "" );
         r->Report( wxString::Format( _( "Resolved diameter constraints: min %s; max %s." ),
-                                     reportMin( r->GetUnits(),  constraint ),
-                                     reportMax( r->GetUnits(),  constraint ) ) );
+                                     reportMin( m_frame, constraint ),
+                                     reportMax( m_frame, constraint ) ) );
         break;
 
     case DRCE_HOLE_CLEARANCE:
@@ -403,7 +403,7 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
         {
             constraint = drcEngine.EvalRules( HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r );
             clearance = constraint.m_Value.Min();
-            clearanceStr = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, r->GetUnits(), clearance, true );
+            clearanceStr = m_frame->StringFromValue( clearance, true );
 
             r->Report( "" );
             r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) );
@@ -416,7 +416,7 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
 
         constraint = drcEngine.EvalRules( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r );
         clearance = constraint.m_Value.Min();
-        clearanceStr = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, r->GetUnits(), clearance, true );
+        clearanceStr = m_frame->StringFromValue( clearance, true );
 
         if( !drcEngine.HasRulesForConstraintType( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT ) )
         {
@@ -440,7 +440,7 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
 
         constraint = drcEngine.EvalRules( HOLE_TO_HOLE_CONSTRAINT, a, b, UNDEFINED_LAYER, r );
         clearance = constraint.m_Value.Min();
-        clearanceStr = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, r->GetUnits(), clearance, true );
+        clearanceStr = m_frame->StringFromValue( clearance, true );
 
         r->Report( "" );
         r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) );
@@ -455,7 +455,7 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
 
         constraint = drcEngine.EvalRules( EDGE_CLEARANCE_CONSTRAINT, a, b, layer, r );
         clearance = constraint.m_Value.Min();
-        clearanceStr = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, r->GetUnits(), clearance, true );
+        clearanceStr = m_frame->StringFromValue( clearance, true );
 
         r->Report( "" );
         r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) );
@@ -504,7 +504,7 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
         {
             constraint = drcEngine.EvalRules( CLEARANCE_CONSTRAINT, a, a, layer, r );
             clearance = constraint.m_Value.Min();
-            clearanceStr = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, r->GetUnits(), clearance, true );
+            clearanceStr = m_frame->StringFromValue( clearance, true );
 
             r->Report( "" );
             r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) );
@@ -517,7 +517,7 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
 
         constraint = drcEngine.EvalRules( PHYSICAL_CLEARANCE_CONSTRAINT, a, b, layer, r );
         clearance = constraint.m_Value.Min();
-        clearanceStr = EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, r->GetUnits(), clearance, true );
+        clearanceStr = m_frame->StringFromValue( clearance, true );
 
         if( !drcEngine.HasRulesForConstraintType( PHYSICAL_CLEARANCE_CONSTRAINT ) )
         {
@@ -606,8 +606,6 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
         std::swap( a, b );
 
     WX_HTML_REPORT_BOX*   r = nullptr;
-    EDA_UNITS             units = m_frame->GetUserUnits();
-
     PCB_LAYER_ID          active = m_frame->GetActiveLayer();
     LSET                  layerIntersection = a->GetLayerSet() & b->GetLayerSet();
     LSET                  copperIntersection = layerIntersection & LSET::AllCuMask();
@@ -651,7 +649,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
 
             r->Report( "" );
             r->Report( wxString::Format( _( "Resolved thermal relief gap: %s." ),
-                                         EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units, gap, true ) ) );
+                                         m_frame->StringFromValue( gap, true ) ) );
 
             r->Report( "" );
             r->Report( "" );
@@ -665,7 +663,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
 
             r->Report( "" );
             r->Report( wxString::Format( _( "Resolved thermal relief spoke width: %s." ),
-                                         EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units, width, true ) ) );
+                                         m_frame->StringFromValue( width, true ) ) );
 
             r->Report( "" );
             r->Report( "" );
@@ -692,7 +690,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
             clearance = zone->GetLocalClearance();
             r->Report( "" );
             r->Report( wxString::Format( _( "Zone clearance: %s." ),
-                                         EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units, clearance, true ) ) );
+                                         m_frame->StringFromValue( clearance, true ) ) );
 
             constraint = drcEngine.EvalRules( PHYSICAL_CLEARANCE_CONSTRAINT, pad, zone, layer, r );
 
@@ -704,7 +702,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
                 r->Report( wxString::Format( _( "Overridden by larger physical clearance from %s;"
                                                 "clearance: %s." ),
                                              EscapeHTML( constraint.GetName() ),
-                                             EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units, clearance, true ) ) );
+                                             m_frame->StringFromValue( clearance, true ) ) );
             }
 
             if( !pad->FlashLayer( layer ) )
@@ -720,7 +718,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
                     r->Report( wxString::Format( _( "Overridden by larger physical hole clearance from %s;"
                                                     "clearance: %s." ),
                                                  EscapeHTML( constraint.GetName() ),
-                                                 EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units, clearance, true ) ) );
+                                                 m_frame->StringFromValue( clearance, true ) ) );
                 }
             }
 
@@ -729,7 +727,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
 
             r->Report( "" );
             r->Report( wxString::Format( _( "Resolved clearance: %s." ),
-                                         EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units, clearance, true ) ) );
+                                         m_frame->StringFromValue( clearance, true ) ) );
         }
         else
         {
@@ -743,7 +741,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
             // Report a 0 clearance for solid connections
             r->Report( "" );
             r->Report( wxString::Format( _( "Resolved clearance: %s." ),
-                                         EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units, 0, true ) ) );
+                                         m_frame->StringFromValue( 0, true ) ) );
         }
 
         r->Flush();
@@ -774,7 +772,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
 
             r->Report( "" );
             r->Report( wxString::Format( _( "Resolved clearance: %s." ),
-                                         EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units, clearance, true ) ) );
+                                         m_frame->StringFromValue( clearance, true ) ) );
         }
 
         r->Flush();
@@ -796,9 +794,9 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
 
             r->Report( "" );
             r->Report( wxString::Format( _( "Resolved gap constraints: min %s; opt %s; max %s." ),
-                                         reportMin( r->GetUnits(),  constraint ),
-                                         reportOpt( r->GetUnits(),  constraint ),
-                                         reportMax( r->GetUnits(),  constraint ) ) );
+                                         reportMin( m_frame, constraint ),
+                                         reportOpt( m_frame, constraint ),
+                                         reportMax( m_frame, constraint ) ) );
 
             r->Report( "" );
             r->Report( "" );
@@ -817,7 +815,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
 
                 r->Report( "" );
                 r->Report( wxString::Format( _( "Resolved max uncoupled length: %s." ),
-                                             reportMax( r->GetUnits(),  constraint ) ) );
+                                             reportMax( m_frame, constraint ) ) );
             }
             r->Flush();
         }
@@ -871,7 +869,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
                 r->Report( warning );
 
             r->Report( wxString::Format( _( "Resolved clearance: %s." ),
-                                         EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units, clearance, true ) ) );
+                                         m_frame->StringFromValue( clearance, true ) ) );
 
             r->Flush();
         }
@@ -895,7 +893,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
 
             r->Report( "" );
             r->Report( wxString::Format( _( "Resolved clearance: %s." ),
-                                         EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units, clearance, true ) ) );
+                                         m_frame->StringFromValue( clearance, true ) ) );
 
             r->Flush();
         }
@@ -939,7 +937,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
 
             r->Report( "" );
             r->Report( wxString::Format( _( "Resolved clearance: %s." ),
-                                         EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units, clearance, true ) ) );
+                                         m_frame->StringFromValue( clearance, true ) ) );
 
             r->Flush();
         }
@@ -968,7 +966,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
 
             r->Report( "" );
             r->Report( wxString::Format( _( "Resolved clearance: %s." ),
-                                         EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units, clearance, true ) ) );
+                                         m_frame->StringFromValue( clearance, true ) ) );
 
             r->Flush();
         }
@@ -1007,7 +1005,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
 
             r->Report( "" );
             r->Report( wxString::Format( _( "Resolved clearance: %s." ),
-                                         EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units, clearance, true ) ) );
+                                         m_frame->StringFromValue( clearance, true ) ) );
 
             r->Flush();
         }
@@ -1036,7 +1034,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
                 {
                     r->Report( "" );
                     r->Report( wxString::Format( _( "Resolved clearance: %s." ),
-                                                 EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units, clearance, true ) ) );
+                                                 m_frame->StringFromValue( clearance, true ) ) );
                 }
 
                 r->Report( "" );
@@ -1102,7 +1100,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
         {
             r->Report( "" );
             r->Report( wxString::Format( _( "Resolved clearance: %s." ),
-                                         EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, units, clearance, true ) ) );
+                                         m_frame->StringFromValue( clearance, true ) ) );
         }
     }
 
@@ -1159,9 +1157,9 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent )
 
         r->Report( "" );
         r->Report( wxString::Format( _( "Width constraints: min %s; opt %s; max %s." ),
-                                     reportMin( r->GetUnits(), constraint ),
-                                     reportOpt( r->GetUnits(), constraint ),
-                                     reportMax( r->GetUnits(), constraint ) ) );
+                                     reportMin( m_frame, constraint ),
+                                     reportOpt( m_frame, constraint ),
+                                     reportMax( m_frame, constraint ) ) );
 
         r->Flush();
     }
@@ -1179,9 +1177,9 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent )
 
         r->Report( "" );
         r->Report( wxString::Format( _( "Diameter constraints: min %s; opt %s; max %s." ),
-                                     reportMin( r->GetUnits(), constraint ),
-                                     reportOpt( r->GetUnits(), constraint ),
-                                     reportMax( r->GetUnits(), constraint ) ) );
+                                     reportMin( m_frame, constraint ),
+                                     reportOpt( m_frame, constraint ),
+                                     reportMax( m_frame, constraint ) ) );
 
         r->Flush();
 
@@ -1196,9 +1194,9 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent )
 
         r->Report( "" );
         r->Report( wxString::Format( _( "Annular width constraints: min %s; opt %s; max %s." ),
-                                     reportMin( r->GetUnits(), constraint ),
-                                     reportOpt( r->GetUnits(), constraint ),
-                                     reportMax( r->GetUnits(), constraint ) ) );
+                                     reportMin( m_frame, constraint ),
+                                     reportOpt( m_frame, constraint ),
+                                     reportMax( m_frame, constraint ) ) );
 
         r->Flush();
     }
@@ -1217,9 +1215,9 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent )
 
         r->Report( "" );
         r->Report( wxString::Format( _( "Diameter constraints: min %s; opt %s; max %s." ),
-                                     reportMin( r->GetUnits(), constraint ),
-                                     reportOpt( r->GetUnits(), constraint ),
-                                     reportMax( r->GetUnits(), constraint ) ) );
+                                     reportMin( m_frame, constraint ),
+                                     reportOpt( m_frame, constraint ),
+                                     reportMax( m_frame, constraint ) ) );
 
         r->Flush();
     }
@@ -1238,9 +1236,9 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent )
 
         r->Report( "" );
         r->Report( wxString::Format( _( "Text height constraints: min %s; opt %s; max %s." ),
-                                     reportMin( r->GetUnits(),  constraint ),
-                                     reportOpt( r->GetUnits(),  constraint ),
-                                     reportMax( r->GetUnits(),  constraint ) ) );
+                                     reportMin( m_frame, constraint ),
+                                     reportOpt( m_frame, constraint ),
+                                     reportMax( m_frame, constraint ) ) );
 
         r->Report( "" );
         r->Report( "" );
@@ -1254,9 +1252,9 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent )
 
         r->Report( "" );
         r->Report( wxString::Format( _( "Text thickness constraints: min %s; opt %s; max %s." ),
-                                     reportMin( r->GetUnits(),  constraint ),
-                                     reportOpt( r->GetUnits(),  constraint ),
-                                     reportMax( r->GetUnits(),  constraint ) ) );
+                                     reportMin( m_frame, constraint ),
+                                     reportOpt( m_frame, constraint ),
+                                     reportMax( m_frame, constraint ) ) );
 
         r->Flush();
     }
diff --git a/pcbnew/tools/drawing_stackup_table_tool.cpp b/pcbnew/tools/drawing_stackup_table_tool.cpp
index ab9b934c06..c72d625e60 100644
--- a/pcbnew/tools/drawing_stackup_table_tool.cpp
+++ b/pcbnew/tools/drawing_stackup_table_tool.cpp
@@ -317,8 +317,7 @@ std::vector<BOARD_ITEM*> DRAWING_TOOL::DrawSpecificationStackup( const VECTOR2I&
             colMaterial.push_back( t );
 
             t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
-            t->SetText( EDA_UNIT_UTILS::UI::StringFromValue(
-                    pcbIUScale, m_frame->GetUserUnits(), stackup_item->GetThickness( j ), true ) );
+            t->SetText( m_frame->StringFromValue( stackup_item->GetThickness( j ), true ) );
             colThickness.push_back( t );
 
             t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
@@ -326,13 +325,13 @@ std::vector<BOARD_ITEM*> DRAWING_TOOL::DrawSpecificationStackup( const VECTOR2I&
             colColor.push_back( t );
 
             t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
-            t->SetText( EDA_UNIT_UTILS::UI::StringFromValue(
-                    pcbIUScale, EDA_UNITS::UNSCALED, stackup_item->GetEpsilonR( j ), false ) );
+            t->SetText( EDA_UNIT_UTILS::UI::StringFromValue( unityScale, EDA_UNITS::UNSCALED,
+                                                             stackup_item->GetEpsilonR( j ), false ) );
             colEpsilon.push_back( t );
 
             t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
-            t->SetText( EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, EDA_UNITS::UNSCALED, stackup_item->GetLossTangent( j ),
-                                         false ) );
+            t->SetText( EDA_UNIT_UTILS::UI::StringFromValue( unityScale, EDA_UNITS::UNSCALED,
+                                                             stackup_item->GetLossTangent( j ), false ) );
             colTanD.push_back( t );
         }
     }
@@ -408,14 +407,14 @@ std::vector<BOARD_ITEM*> DRAWING_TOOL::DrawBoardCharacteristics( const VECTOR2I&
     std::vector<PCB_TEXT*>              colbreak;
     std::vector<PCB_TEXT*>              colLabel2;
     std::vector<PCB_TEXT*>              colData2;
-    wxString                            text;
 
     t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
     t->SetText( _( "Copper Layer Count: " ) );
     colLabel1.push_back( t );
 
     t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
-    t->SetText( EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, EDA_UNITS::UNSCALED, settings.GetCopperLayerCount(), false ) );
+    t->SetText( EDA_UNIT_UTILS::UI::StringFromValue( unityScale, EDA_UNITS::UNSCALED,
+                                                     settings.GetCopperLayerCount(), false ) );
     colData1.push_back( t );
 
     SHAPE_POLY_SET outline;
@@ -427,8 +426,8 @@ std::vector<BOARD_ITEM*> DRAWING_TOOL::DrawBoardCharacteristics( const VECTOR2I&
 
     t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
     t->SetText( wxString::Format( wxT( "%s x %s" ),
-                EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_frame->GetUserUnits(), size.GetWidth(), true ),
-                EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_frame->GetUserUnits(), size.GetHeight(), true ) ) );
+                                  m_frame->MessageTextFromValue( size.GetWidth(), true ),
+                                  m_frame->MessageTextFromValue( size.GetHeight(), true ) ) );
     colData1.push_back( t );
 
     t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
@@ -437,8 +436,8 @@ std::vector<BOARD_ITEM*> DRAWING_TOOL::DrawBoardCharacteristics( const VECTOR2I&
 
     t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
     t->SetText( wxString::Format( wxT( "%s / %s" ),
-                EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_frame->GetUserUnits(), settings.m_TrackMinWidth, true ),
-                EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_frame->GetUserUnits(), settings.m_MinClearance, true ) ) );
+                                  m_frame->MessageTextFromValue( settings.m_TrackMinWidth, true ),
+                                  m_frame->MessageTextFromValue( settings.m_MinClearance, true ) ) );
     colData1.push_back( t );
 
     t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
@@ -462,9 +461,7 @@ std::vector<BOARD_ITEM*> DRAWING_TOOL::DrawBoardCharacteristics( const VECTOR2I&
     colLabel2.push_back( t );
 
     t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
-    text = EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_frame->GetUserUnits(), settings.GetBoardThickness(), true );
-
-    t->SetText( text );
+    t->SetText( m_frame->MessageTextFromValue( settings.GetBoardThickness(), true ) );
     colData2.push_back( t );
 
     // some empty cells
@@ -479,8 +476,7 @@ std::vector<BOARD_ITEM*> DRAWING_TOOL::DrawBoardCharacteristics( const VECTOR2I&
     t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
 
     double holeSize = std::min( settings.m_MinThroughDrill, settings.m_ViasMinSize );
-    text            = EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_frame->GetUserUnits(), holeSize, true );
-    t->SetText( text );
+    t->SetText( m_frame->MessageTextFromValue( holeSize, true ) );
     colData2.push_back( t );
 
     t = static_cast<PCB_TEXT*>( dataStyle->Duplicate() );
diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp
index 3a080ff4fa..a2cdbde824 100644
--- a/pcbnew/tools/drawing_tool.cpp
+++ b/pcbnew/tools/drawing_tool.cpp
@@ -97,7 +97,6 @@ protected:
     void update() override
     {
         PCB_EDIT_FRAME*        frame = (PCB_EDIT_FRAME*) getToolManager()->GetToolHolder();
-        EDA_UNITS              units = frame->GetUserUnits();
         BOARD_DESIGN_SETTINGS& bds = frame->GetBoard()->GetDesignSettings();
         bool                   useIndex = !bds.m_UseConnectedTrackWidth
                                                 && !bds.UseCustomTrackViaSize();
@@ -118,12 +117,13 @@ protected:
             if( via.m_Drill > 0 )
             {
                 msg.Printf( _("Via %s, hole %s" ),
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, via.m_Diameter ),
-                            EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, via.m_Drill ) );
+                            frame->MessageTextFromValue( via.m_Diameter ),
+                            frame->MessageTextFromValue( via.m_Drill ) );
             }
             else
             {
-                msg.Printf( _( "Via %s" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, via.m_Diameter ) );
+                msg.Printf( _( "Via %s" ),
+                            frame->MessageTextFromValue( via.m_Diameter ) );
             }
 
             int menuIdx = ID_POPUP_PCB_SELECT_VIASIZE1 + i;
diff --git a/pcbnew/tools/pcb_control.cpp b/pcbnew/tools/pcb_control.cpp
index d29eb48eae..78936f216c 100644
--- a/pcbnew/tools/pcb_control.cpp
+++ b/pcbnew/tools/pcb_control.cpp
@@ -1299,7 +1299,6 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent )
     std::shared_ptr<DRC_ENGINE> drcEngine = m_frame->GetBoard()->GetDesignSettings().m_DRCEngine;
     DRC_CONSTRAINT              constraint;
 
-    EDA_UNITS                   units = m_frame->GetUserUnits();
     std::vector<MSG_PANEL_ITEM> msgItems;
 
     if( routerTool && routerTool->RoutingInProgress() )
@@ -1346,8 +1345,8 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent )
         BOARD_ITEM* a = static_cast<BOARD_ITEM*>( selection[0] );
         BOARD_ITEM* b = static_cast<BOARD_ITEM*>( selection[1] );
 
-        msgItems.emplace_back( MSG_PANEL_ITEM( a->GetSelectMenuText( units ),
-                                               b->GetSelectMenuText( units ) ) );
+        msgItems.emplace_back( MSG_PANEL_ITEM( a->GetSelectMenuText( m_frame->GetUserUnits() ),
+                                               b->GetSelectMenuText( m_frame->GetUserUnits() ) ) );
 
         BOARD_CONNECTED_ITEM* a_conn = dyn_cast<BOARD_CONNECTED_ITEM*>( a );
         BOARD_CONNECTED_ITEM* b_conn = dyn_cast<BOARD_CONNECTED_ITEM*>( b );
@@ -1371,12 +1370,12 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent )
                 int actual_clearance = a_shape->GetClearance( b_shape.get() );
 
                 msgItems.emplace_back( _( "Resolved clearance" ),
-                                       EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, constraint.m_Value.Min() ) );
+                                       m_frame->MessageTextFromValue( constraint.m_Value.Min() ) );
 
                 if( actual_clearance > -1 && actual_clearance < std::numeric_limits<int>::max() )
                 {
                     msgItems.emplace_back( _( "Actual clearance" ),
-                                           EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, actual_clearance ) );
+                                           m_frame->MessageTextFromValue( actual_clearance ) );
                 }
             }
         }
@@ -1417,12 +1416,12 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent )
 
                 constraint = drcEngine->EvalRules( HOLE_CLEARANCE_CONSTRAINT, a, b, layer );
                 msgItems.emplace_back( _( "Resolved hole clearance" ),
-                                       EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, constraint.m_Value.Min() ) );
+                                       m_frame->MessageTextFromValue( constraint.m_Value.Min() ) );
 
                 if( actual > -1 && actual < std::numeric_limits<int>::max() )
                 {
                     msgItems.emplace_back( _( "Actual hole clearance" ),
-                                           EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, actual ) );
+                                           m_frame->MessageTextFromValue( actual ) );
                 }
             }
         }
@@ -1454,12 +1453,12 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent )
                 if( edgeLayer == Edge_Cuts )
                 {
                     msgItems.emplace_back( _( "Resolved edge clearance" ),
-                                           EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, constraint.m_Value.Min() ) );
+                                           m_frame->MessageTextFromValue( constraint.m_Value.Min() ) );
                 }
                 else
                 {
                     msgItems.emplace_back( _( "Resolved margin clearance" ),
-                                           EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, constraint.m_Value.Min() ) );
+                                           m_frame->MessageTextFromValue( constraint.m_Value.Min() ) );
                 }
             }
         }
diff --git a/pcbnew/widgets/search_handlers.cpp b/pcbnew/widgets/search_handlers.cpp
index c09e758129..9dea651bd9 100644
--- a/pcbnew/widgets/search_handlers.cpp
+++ b/pcbnew/widgets/search_handlers.cpp
@@ -71,9 +71,9 @@ wxString FOOTPRINT_SEARCH_HANDLER::GetResultCell( int row, int col )
     else if( col == 2 )
         return fp->GetLayerName();
     else if( col == 3 )
-        return EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_frame->GetUserUnits(), fp->GetX() );
+        return m_frame->MessageTextFromValue( fp->GetX() );
     else if( col == 4 )
-        return EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_frame->GetUserUnits(), fp->GetY() );
+        return m_frame->MessageTextFromValue( fp->GetY() );
 
     return wxEmptyString;
 }
@@ -130,9 +130,9 @@ wxString ZONE_SEARCH_HANDLER::GetResultCell( int row, int col )
     else if( col == 1 )
         return zone->GetLayerName();
     else if( col == 2 )
-        return EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_frame->GetUserUnits(), zone->GetX() );
+        return m_frame->MessageTextFromValue( zone->GetX() );
     else if( col == 3 )
-        return EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_frame->GetUserUnits(), zone->GetY() );
+        return m_frame->MessageTextFromValue( zone->GetY() );
 
     return wxEmptyString;
 }
@@ -189,9 +189,9 @@ wxString TEXT_SEARCH_HANDLER::GetResultCell( int row, int col )
     if( col == 1 )
         return text->GetLayerName();
     else if( col == 2 )
-        return EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_frame->GetUserUnits(), text->GetX() );
+        return m_frame->MessageTextFromValue( text->GetX() );
     else if( col == 3 )
-        return EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_frame->GetUserUnits(), text->GetY() );
+        return m_frame->MessageTextFromValue( text->GetY() );
 
     return wxEmptyString;
 }
diff --git a/pcbnew/zone.cpp b/pcbnew/zone.cpp
index 0931db38dc..38a367b33d 100644
--- a/pcbnew/zone.cpp
+++ b/pcbnew/zone.cpp
@@ -26,8 +26,6 @@
 #include <bitmaps.h>
 #include <geometry/geometry_utils.h>
 #include <geometry/shape_null.h>
-#include <core/mirror.h>
-#include <advanced_config.h>
 #include <pcb_edit_frame.h>
 #include <pcb_screen.h>
 #include <board.h>
@@ -487,8 +485,7 @@ bool ZONE::HitTestCutout( const VECTOR2I& aRefPos, int* aOutlineIdx, int* aHoleI
 
 void ZONE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
 {
-    EDA_UNITS units = aFrame->GetUserUnits();
-    wxString  msg;
+    wxString msg;
 
     if( GetIsRuleArea() )
         msg = _( "Rule Area" );
@@ -577,8 +574,8 @@ void ZONE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>&
 
     aList.emplace_back( _( "Fill Mode" ), msg );
 
-    msg = EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, m_area, true, EDA_DATA_TYPE::AREA );
-    aList.emplace_back( _( "Filled Area" ), msg );
+    aList.emplace_back( _( "Filled Area" ),
+                        aFrame->MessageTextFromValue( m_area, true, EDA_DATA_TYPE::AREA ) );
 
     wxString source;
     int      clearance = GetOwnClearance( UNDEFINED_LAYER, &source );
@@ -586,7 +583,7 @@ void ZONE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>&
     if( !source.IsEmpty() )
     {
         aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
-                                              EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, units, clearance ) ),
+                                              aFrame->MessageTextFromValue( clearance ) ),
                             wxString::Format( _( "(from %s)" ),
                                               source ) );
     }
@@ -768,8 +765,7 @@ int ZONE::GetBorderHatchPitch() const
 
 
 void ZONE::SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE aBorderHatchStyle,
-                                  int aBorderHatchPitch,
-                                  bool aRebuildBorderHatch )
+                                  int aBorderHatchPitch, bool aRebuildBorderHatch )
 {
     aBorderHatchPitch = std::max( aBorderHatchPitch,
                                   pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MINDIST_MM ) );