← Back to team overview

kicad-developers team mailing list archive

[PATCH] Add mils as user unit

 

Hi all,


below is a patch to add "mils" as a user unit to pcbnew, the gerber
viewer and the module editor. I left out eeschema because I do not think
it's useful there, but if required adding it would be easy.

I probably missed some places needing modification. In any case somebody
with the requisite skills needs to create a proper toolbar icon for
mils.


Have fun,

MGri


diff --git a/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp b/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp
index 2588edee8..3e596d914 100644
--- a/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp
+++ b/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp
@@ -228,6 +228,12 @@ void PANEL_PREV_3D::SetModelDataIdx( int idx, bool aReloadPreviewModule )
                 zoff->SetValue( wxString::Format( "%.4f", aModel->m_Offset.z ) );
                 break;
 
+            case MILS:
+                xoff->SetValue( wxString::Format( "%.1f", aModel->m_Offset.x * 1000. ) );
+                yoff->SetValue( wxString::Format( "%.1f", aModel->m_Offset.y * 1000. ) );
+                zoff->SetValue( wxString::Format( "%.1f", aModel->m_Offset.z * 1000. ) );
+                break;
+
             case DEGREES:
             case UNSCALED_UNITS:
             default:
@@ -454,7 +460,13 @@ void PANEL_PREV_3D::onIncrementOffset( wxSpinEvent& event )
     double step = OFFSET_INCREMENT_MM;
 
     if( g_UserUnit == INCHES )
+    {
         step = OFFSET_INCREMENT_MIL/1000.0;
+    }
+    else if( g_UserUnit == MILS )
+    {
+        step = OFFSET_INCREMENT_MIL;
+    }
 
     incrementTextCtrl( textCtrl, step, -MAX_OFFSET, MAX_OFFSET );
 }
@@ -474,7 +486,13 @@ void PANEL_PREV_3D::onDecrementOffset( wxSpinEvent& event )
     double step = OFFSET_INCREMENT_MM;
 
     if( g_UserUnit == INCHES )
+    {
         step = OFFSET_INCREMENT_MIL/1000.0;
+    }
+    else if( g_UserUnit == MILS )
+    {
+        step = OFFSET_INCREMENT_MIL;
+    }
 
     incrementTextCtrl( textCtrl, -step, -MAX_OFFSET, MAX_OFFSET );
 }
@@ -527,6 +545,12 @@ void PANEL_PREV_3D::onMouseWheelOffset( wxMouseEvent& event )
         if( event.ShiftDown( ) )
             step = OFFSET_INCREMENT_MIL_FINE/1000.0;
     }
+    else if( g_UserUnit == MILS )
+    {
+        step = OFFSET_INCREMENT_MIL;
+        if( event.ShiftDown( ) )
+            step = OFFSET_INCREMENT_MIL_FINE;
+    }
 
     if( event.GetWheelRotation() >= 0 )
         step = -step;
@@ -572,6 +596,12 @@ void PANEL_PREV_3D::getOrientationVars( SGPOINT& aScale, SGPOINT& aRotation, SGP
         // It is already in Inches
         break;
 
+    case MILS:
+        aOffset.x = aOffset.x / 1000.;
+        aOffset.y = aOffset.y / 1000.;
+        aOffset.z = aOffset.z / 1000.;
+        break;
+
     case DEGREES:
     case UNSCALED_UNITS:
     default:
diff --git a/bitmaps_png/CMakeLists.txt b/bitmaps_png/CMakeLists.txt
index a646f19ee..cc587a0a7 100644
--- a/bitmaps_png/CMakeLists.txt
+++ b/bitmaps_png/CMakeLists.txt
@@ -507,6 +507,7 @@ set( BMAPS_MID
     undo
     unit_inch
     unit_mm
+    unit_mil
     unknown
     unlocked
     unzip
diff --git a/bitmaps_png/cpp_26/unit_mil.cpp b/bitmaps_png/cpp_26/unit_mil.cpp
new file mode 100644
index 000000000..307cae2e7
--- /dev/null
+++ b/bitmaps_png/cpp_26/unit_mil.cpp
@@ -0,0 +1,24 @@
+
+/* Do not modify this file, it was automatically generated by the
+ * PNG2cpp CMake script, using a *.png file as input.
+ */
+
+#include <bitmaps.h>
+
+static const unsigned char png[] = {
+ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
+ 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4a, 0x4c,
+ 0xce, 0x00, 0x00, 0x00, 0x70, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0x63, 0x60, 0x18, 0x05, 0xa3,
+ 0x60, 0x14, 0x8c, 0x82, 0x51, 0x30, 0x0a, 0x06, 0x27, 0x60, 0x02, 0x62, 0x33, 0x20, 0x2e, 0x03,
+ 0x62, 0x0e, 0x12, 0xf4, 0x71, 0x02, 0x71, 0x15, 0x10, 0x5b, 0x41, 0xcd, 0xc0, 0x09, 0x94, 0x80,
+ 0x38, 0x07, 0x88, 0xb7, 0x01, 0xf1, 0x19, 0x20, 0xae, 0x21, 0xc3, 0x91, 0x75, 0x50, 0xbd, 0x3b,
+ 0x80, 0xb8, 0x00, 0x88, 0x55, 0x90, 0x25, 0x39, 0xa0, 0x86, 0x9e, 0xa1, 0x11, 0xae, 0x41, 0x0f,
+ 0x19, 0x15, 0xa8, 0x2b, 0x76, 0x40, 0x15, 0xd4, 0x52, 0xe0, 0xa3, 0x6d, 0xd0, 0xd0, 0x51, 0x22,
+ 0x14, 0x47, 0x56, 0xd0, 0xf0, 0xe6, 0x24, 0x31, 0x8e, 0xca, 0xa1, 0xf1, 0xcb, 0x34, 0x9a, 0xd4,
+ 0x47, 0x01, 0x4e, 0x00, 0x00, 0x8c, 0x60, 0x1f, 0xc2, 0xcd, 0x8e, 0xb2, 0xe2, 0x00, 0x00, 0x00,
+ 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
+};
+
+const BITMAP_OPAQUE unit_mil_xpm[1] = {{ png, sizeof( png ), "unit_mil_xpm" }};
+
+//EOF
diff --git a/bitmaps_png/sources/unit_mil.svg b/bitmaps_png/sources/unit_mil.svg
new file mode 100644
index 000000000..8b8f5e89f
--- /dev/null
+++ b/bitmaps_png/sources/unit_mil.svg
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   height="26"
+   width="26"
+   version="1.1"
+   id="svg2"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="unit_mil.svg">
+  <metadata
+     id="metadata22">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="1150"
+     id="namedview20"
+     showgrid="true"
+     inkscape:snap-to-guides="false"
+     inkscape:snap-grids="true"
+     inkscape:zoom="30.73195"
+     inkscape:cx="14.805041"
+     inkscape:cy="12.607342"
+     inkscape:window-x="0"
+     inkscape:window-y="25"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:object-nodes="true"
+     inkscape:snap-bbox="true">
+    <inkscape:grid
+       type="xygrid"
+       id="grid2999"
+       empspacing="2"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true"
+       spacingx="0.5px"
+       spacingy="0.5px" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <marker
+       inkscape:stockid="Arrow2Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow2Mend"
+       style="overflow:visible;">
+      <path
+         id="path3800"
+         style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+         transform="scale(0.6) rotate(180) translate(0,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Mstart"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow2Mstart"
+       style="overflow:visible">
+      <path
+         id="path3797"
+         style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+         transform="scale(0.6) translate(0,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleInS"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="TriangleInS"
+       style="overflow:visible">
+      <path
+         id="path3912"
+         d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
+         transform="scale(-0.2)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Sstart"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Sstart"
+       style="overflow:visible">
+      <path
+         id="path3785"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
+         transform="scale(0.2) translate(6,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mstart"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mstart"
+       style="overflow:visible">
+      <path
+         id="path3779"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
+         transform="scale(0.4) translate(10,0)" />
+    </marker>
+    <marker
+       id="d"
+       refY="0"
+       refX="0"
+       overflow="visible"
+       orient="auto"
+       style="overflow:visible">
+      <path
+         d="M 5.77,0 -2.88,5 V -5 l 8.65,5 z"
+         transform="scale(0.4,0.4)"
+         id="path7"
+         inkscape:connector-curvature="0"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" />
+    </marker>
+    <marker
+       id="c"
+       refY="0"
+       refX="0"
+       overflow="visible"
+       orient="auto"
+       style="overflow:visible">
+      <path
+         d="M 5.77,0 -2.88,5 V -5 l 8.65,5 z"
+         transform="scale(-0.4,-0.4)"
+         id="path10"
+         inkscape:connector-curvature="0"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" />
+    </marker>
+  </defs>
+  <path
+     style="opacity:0.80000000000000004;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;marker-start:url(#Arrow2Mstart);marker-end:url(#Arrow2Mend)"
+     inkscape:connector-curvature="0"
+     id="path14"
+     d="m 2,18.5 22,0"
+     sodipodi:nodetypes="cc" />
+</svg>
diff --git a/common/base_units.cpp b/common/base_units.cpp
index 4611b182d..5547dda7a 100644
--- a/common/base_units.cpp
+++ b/common/base_units.cpp
@@ -44,8 +44,10 @@
 #if defined( PCBNEW ) || defined( CVPCB ) || defined( EESCHEMA ) || defined( GERBVIEW ) || defined( PL_EDITOR )
 #define IU_TO_MM( x )       ( x / IU_PER_MM )
 #define IU_TO_IN( x )       ( x / IU_PER_MILS / 1000 )
+#define IU_TO_MIL( x )      ( x / IU_PER_MILS )
 #define MM_TO_IU( x )       ( x * IU_PER_MM )
 #define IN_TO_IU( x )       ( x * IU_PER_MILS * 1000 )
+#define MIL_TO_IU( x )      ( x * IU_PER_MILS )
 #else
 #error "Cannot resolve internal units due to no definition of EESCHEMA, CVPCB or PCBNEW."
 #endif
@@ -97,6 +99,9 @@ double To_User_Unit( EDA_UNITS_T aUnit, double aValue )
     case INCHES:
         return IU_TO_IN( aValue );
 
+    case MILS:
+        return IU_TO_MIL( aValue );
+
     case DEGREES:
         return aValue / 10.0f;
 
@@ -145,6 +150,14 @@ wxString LengthDoubleToString( double aValue, bool aConvertToMils )
 #endif
         }
     }
+    else if ( g_UserUnit == MILS )
+    {
+#if defined( EESCHEMA )
+        format = wxT( "%.0f" );
+#else
+        format = wxT( "%.1f" );
+#endif
+    }
     else
     {
 #if defined( EESCHEMA )
@@ -158,6 +171,8 @@ wxString LengthDoubleToString( double aValue, bool aConvertToMils )
 
     if( g_UserUnit == INCHES )
         text += ( aConvertToMils ) ? _( " mils" ) : _( " in" );
+    else if( g_UserUnit == MILS )
+        text += _( " mils" );
     else
         text += _( " mm" );
 
@@ -249,6 +264,10 @@ wxString StringFromValue( EDA_UNITS_T aUnit, int aValue, bool aAddUnitSymbol )
             stringValue += _( " mm" );
             break;
 
+        case MILS:
+            stringValue += _( " mil" );
+            break;
+
         case DEGREES:
             stringValue += _( " deg" );
             break;
@@ -284,6 +303,10 @@ double From_User_Unit( EDA_UNITS_T aUnit, double aValue )
         value = IN_TO_IU( aValue );
         break;
 
+    case MILS:
+        value = MIL_TO_IU( aValue );
+        break;
+
     case DEGREES:
         // Convert to "decidegrees"
         value = aValue * 10;
@@ -347,8 +370,7 @@ double DoubleValueFromString( EDA_UNITS_T aUnits, const wxString& aTextValue )
         }
         else if( unit == wxT( "mi" ) || unit == wxT( "th" ) ) // Mils or thous
         {
-            aUnits = INCHES;
-            dtmp /= 1000;
+            aUnits = MILS;
         }
     }
     else if( aUnits == DEGREES )
@@ -432,6 +454,10 @@ wxString ReturnUnitSymbol( EDA_UNITS_T aUnit, const wxString& formatString )
         tmp = _( "mm" );
         break;
 
+    case MILS:
+        tmp = _( "mil" );
+        break;
+
     case UNSCALED_UNITS:
         break;
 
@@ -463,6 +489,10 @@ wxString GetUnitsLabel( EDA_UNITS_T aUnit )
         label = _( "millimeters" );
         break;
 
+    case MILS:
+        label = _( "mils" );
+        break;
+
     case UNSCALED_UNITS:
         label = _( "units" );
         break;
@@ -490,6 +520,10 @@ wxString GetAbbreviatedUnitsLabel( EDA_UNITS_T aUnit )
         label = _( "mm" );
         break;
 
+    case MILS:
+        label = _( "mil" );
+        break;
+
     case UNSCALED_UNITS:
         break;
 
diff --git a/common/dialogs/dialog_page_settings.cpp b/common/dialogs/dialog_page_settings.cpp
index 819d68a89..7536af675 100644
--- a/common/dialogs/dialog_page_settings.cpp
+++ b/common/dialogs/dialog_page_settings.cpp
@@ -185,6 +185,14 @@ void DIALOG_PAGES_SETTINGS::initDialog()
         m_TextUserSizeY->SetValue( msg );
         break;
 
+    case MILS:
+        msg.Printf( wxT( "%.0f" ), customSizeX );
+        m_TextUserSizeX->SetValue( msg );
+
+        msg.Printf( wxT( "%.0f" ), customSizeY );
+        m_TextUserSizeY->SetValue( msg );
+        break;
+
     default:
     case INCHES:
         customSizeX /= 1000.0;
@@ -466,9 +474,11 @@ bool DIALOG_PAGES_SETTINGS::SavePageSettings()
             {
                 wxString msg = wxString::Format( _( "Selected custom paper size\nis out of the permissible \
 limits\n%.1f - %.1f %s!\nSelect another custom paper size?" ),
-                        g_UserUnit == INCHES ? MIN_PAGE_SIZE / 1000. : MIN_PAGE_SIZE * 25.4 / 1000,
-                        g_UserUnit == INCHES ? MAX_PAGE_SIZE / 1000. : MAX_PAGE_SIZE * 25.4 / 1000,
-                        g_UserUnit == INCHES ? _( "inches" ) : _( "mm" ) );
+                        g_UserUnit != MILLIMETRES
+                            ? MIN_PAGE_SIZE / ( g_UserUnit == INCHES ? 1000. : 1. ) : MIN_PAGE_SIZE * 25.4 / 1000,
+                        g_UserUnit != MILLIMETRES
+                            ? MAX_PAGE_SIZE / ( g_UserUnit == INCHES ? 1000. : 1. ) : MAX_PAGE_SIZE * 25.4 / 1000,
+                        g_UserUnit != MILLIMETRES ? _( "inches" ) : _( "mm" ) );
 
                 if( wxMessageBox( msg, _( "Warning!" ), wxYES_NO | wxICON_EXCLAMATION, this ) == wxYES )
                 {
@@ -787,6 +797,10 @@ void DIALOG_PAGES_SETTINGS::GetCustomSizeMilsFromDialog()
         customSizeY *= 1000. / 25.4;
         break;
 
+    case MILS:
+        // DO NOTHING
+        break;
+
     default:
     case INCHES:
         customSizeX *= 1000.;
diff --git a/common/draw_frame.cpp b/common/draw_frame.cpp
index e09ec55be..c7c8852bf 100644
--- a/common/draw_frame.cpp
+++ b/common/draw_frame.cpp
@@ -106,7 +106,7 @@ BEGIN_EVENT_TABLE( EDA_DRAW_FRAME, KIWAY_PLAYER )
                     EDA_DRAW_FRAME::OnSelectGrid )
 
     EVT_TOOL( ID_TB_OPTIONS_SHOW_GRID, EDA_DRAW_FRAME::OnToggleGridState )
-    EVT_TOOL_RANGE( ID_TB_OPTIONS_SELECT_UNIT_MM, ID_TB_OPTIONS_SELECT_UNIT_INCH,
+    EVT_TOOL_RANGE( ID_TB_OPTIONS_SELECT_UNIT_MM, ID_TB_OPTIONS_SELECT_UNIT_MIL,
                     EDA_DRAW_FRAME::OnSelectUnits )
 
     // Cursor shape cannot be implemented on OS X
@@ -118,7 +118,7 @@ BEGIN_EVENT_TABLE( EDA_DRAW_FRAME, KIWAY_PLAYER )
     EVT_UPDATE_UI( wxID_REDO, EDA_DRAW_FRAME::OnUpdateRedo )
     EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_GRID, EDA_DRAW_FRAME::OnUpdateGrid )
     EVT_UPDATE_UI( ID_TB_OPTIONS_SELECT_CURSOR, EDA_DRAW_FRAME::OnUpdateCrossHairStyle )
-    EVT_UPDATE_UI_RANGE( ID_TB_OPTIONS_SELECT_UNIT_MM, ID_TB_OPTIONS_SELECT_UNIT_INCH,
+    EVT_UPDATE_UI_RANGE( ID_TB_OPTIONS_SELECT_UNIT_MM, ID_TB_OPTIONS_SELECT_UNIT_MIL,
                          EDA_DRAW_FRAME::OnUpdateUnits )
 END_EVENT_TABLE()
 
@@ -304,6 +304,11 @@ void EDA_DRAW_FRAME::OnSelectUnits( wxCommandEvent& aEvent )
         g_UserUnit = INCHES;
         unitsChangeRefresh();
     }
+    else if( aEvent.GetId() == ID_TB_OPTIONS_SELECT_UNIT_MIL && g_UserUnit != MILS )
+    {
+        g_UserUnit = MILS;
+        unitsChangeRefresh();
+    }
 }
 
 
@@ -339,7 +344,8 @@ void EDA_DRAW_FRAME::OnUpdateUnits( wxUpdateUIEvent& aEvent )
     bool enable;
 
     enable = ( ((aEvent.GetId() == ID_TB_OPTIONS_SELECT_UNIT_MM) && (g_UserUnit == MILLIMETRES))
-            || ((aEvent.GetId() == ID_TB_OPTIONS_SELECT_UNIT_INCH) && (g_UserUnit == INCHES)) );
+            || ((aEvent.GetId() == ID_TB_OPTIONS_SELECT_UNIT_INCH) && (g_UserUnit == INCHES))
+            || ((aEvent.GetId() == ID_TB_OPTIONS_SELECT_UNIT_MIL) && (g_UserUnit == MILS)) );
 
     aEvent.Check( enable );
     DisplayUnitsMsg();
@@ -514,6 +520,10 @@ void EDA_DRAW_FRAME::DisplayUnitsMsg()
         msg = _( "mm" );
         break;
 
+    case MILS:
+        msg = _( "mil" );
+        break;
+
     default:
         msg = _( "Units" );
         break;
diff --git a/common/preview_items/preview_utils.cpp b/common/preview_items/preview_utils.cpp
index 897cd5afb..ea47ed334 100644
--- a/common/preview_items/preview_utils.cpp
+++ b/common/preview_items/preview_utils.cpp
@@ -48,6 +48,10 @@ static wxString getDimensionUnit( EDA_UNITS_T aUnits )
 
     case UNSCALED_UNITS:
         break;
+
+    case MILS:
+        return _( "mil" );
+        break;
     // no default: handle all cases
     }
 
@@ -74,6 +78,9 @@ static wxString formatPreviewDimension( double aVal, EDA_UNITS_T aUnits )
         break;
     case UNSCALED_UNITS:
         break;
+    case MILS:
+        precision = 1;  // 0.1mil
+        break;
     }
 
     const wxString fmtStr = wxString::Format( "%%.%df", precision );
diff --git a/common/preview_items/ruler_item.cpp b/common/preview_items/ruler_item.cpp
index 8afee9f16..032fd1455 100644
--- a/common/preview_items/ruler_item.cpp
+++ b/common/preview_items/ruler_item.cpp
@@ -87,7 +87,7 @@ static TICK_FORMAT getTickFormatForScale( double aScale, double& aTickSpace )
     aTickSpace = 1;
 
     // convert to a round (mod-10) number of mils
-    if( g_UserUnit == INCHES )
+    if( g_UserUnit == INCHES || g_UserUnit == MILS )
     {
         aTickSpace *= 2.54;
     }
diff --git a/common/tool/grid_menu.cpp b/common/tool/grid_menu.cpp
index 442b9e7b7..3c3157ee7 100644
--- a/common/tool/grid_menu.cpp
+++ b/common/tool/grid_menu.cpp
@@ -41,7 +41,7 @@ GRID_MENU::GRID_MENU( EDA_DRAW_FRAME* aParent ) : m_parent( aParent )
     SetIcon( grid_select_xpm );
 
     wxArrayString gridsList;
-    screen->BuildGridsChoiceList( gridsList, g_UserUnit != INCHES );
+    screen->BuildGridsChoiceList( gridsList, g_UserUnit != INCHES && g_UserUnit != MILS );
 
     for( unsigned int i = 0; i < gridsList.GetCount(); ++i )
     {
diff --git a/common/zoom.cpp b/common/zoom.cpp
index 216a4ad92..a7a5db2e7 100644
--- a/common/zoom.cpp
+++ b/common/zoom.cpp
@@ -284,7 +284,7 @@ void EDA_DRAW_FRAME::AddMenuZoomAndGrid( wxMenu* MasterMenu )
                      _( "Grid Select" ), KiBitmap( grid_select_xpm ) );
 
         wxArrayString gridsList;
-        int icurr = screen->BuildGridsChoiceList( gridsList, g_UserUnit != INCHES );
+        int icurr = screen->BuildGridsChoiceList( gridsList, g_UserUnit != INCHES && g_UserUnit != MILS );
 
         for( unsigned i = 0; i < gridsList.GetCount(); i++ )
         {
diff --git a/eeschema/sch_base_frame.cpp b/eeschema/sch_base_frame.cpp
index dc038962e..6708f9160 100644
--- a/eeschema/sch_base_frame.cpp
+++ b/eeschema/sch_base_frame.cpp
@@ -181,6 +181,11 @@ void SCH_BASE_FRAME::UpdateStatusBar()
         locformatter = wxT( "dx %.2f  dy %.2f  dist %.2f" );
         break;
 
+    case MILS:
+        absformatter = wxT( "X %.1f  Y %.1f" );
+        locformatter = wxT( "dx %.1f  dy %.1f  dist %.1f" );
+        break;
+
     case UNSCALED_UNITS:
         absformatter = wxT( "X %f  Y %f" );
         locformatter = wxT( "dx %f  dy %f  dist %f" );
diff --git a/gerbview/class_gerber_file_image.cpp b/gerbview/class_gerber_file_image.cpp
index 9e30fc222..4aebe3e51 100644
--- a/gerbview/class_gerber_file_image.cpp
+++ b/gerbview/class_gerber_file_image.cpp
@@ -345,9 +345,9 @@ void GERBER_FILE_IMAGE::DisplayImageInfo(  GERBVIEW_FRAME* aMainFrame  )
     msg = m_ImageJustifyYCenter ? _("Center") : _("Normal");
     aMainFrame->AppendMsgPanel( _( "Y Justify" ), msg, DARKRED );
 
-    if( g_UserUnit == INCHES )
-        msg.Printf( wxT( "X=%f Y=%f" ), Iu2Mils( m_ImageJustifyOffset.x ) / 1000.0,
-                                        Iu2Mils( m_ImageJustifyOffset.y ) / 1000.0 );
+    if( g_UserUnit == INCHES || g_UserUnit == MILS )
+        msg.Printf( wxT( "X=%f Y=%f" ), Iu2Mils( m_ImageJustifyOffset.x ) / (g_UserUnit == MILS ? 1.0 : 1000.0),
+                                        Iu2Mils( m_ImageJustifyOffset.y ) / (g_UserUnit == MILS ? 1.0 : 1000.0) );
     else
         msg.Printf( wxT( "X=%f Y=%f" ), Iu2Millimeter( m_ImageJustifyOffset.x ),
                                         Iu2Millimeter( m_ImageJustifyOffset.y ) );
diff --git a/gerbview/dialogs/gerbview_dialog_display_options_frame.cpp b/gerbview/dialogs/gerbview_dialog_display_options_frame.cpp
index 504d742fd..e55f2dd09 100644
--- a/gerbview/dialogs/gerbview_dialog_display_options_frame.cpp
+++ b/gerbview/dialogs/gerbview_dialog_display_options_frame.cpp
@@ -91,7 +91,25 @@ void DIALOG_DISPLAY_OPTIONS::OnCancelButtonClick( wxCommandEvent& event )
 void DIALOG_DISPLAY_OPTIONS::initOptDialog( )
 {
     m_PolarDisplay->SetSelection( m_Parent->m_DisplayOptions.m_DisplayPolarCood ? 1 : 0 );
-    m_BoxUnits->SetSelection( g_UserUnit ? 1 : 0 );
+
+    switch( g_UserUnit )
+    {
+    case INCHES:
+        m_BoxUnits->SetSelection( 0 );
+        break;
+
+    case MILLIMETRES:
+        m_BoxUnits->SetSelection( 1 );
+        break;
+
+    case MILS:
+        m_BoxUnits->SetSelection( 2 );
+        break;
+
+    default:
+        // other units not used here
+        break;
+    }
 
     // @todo: LEGACY: Cursor shape can be set using the GAL options
     // widget, when that is added to gerbview. For now, access the
@@ -142,7 +160,21 @@ void DIALOG_DISPLAY_OPTIONS::OnOKBUttonClick( wxCommandEvent& event )
 {
     m_Parent->m_DisplayOptions.m_DisplayPolarCood =
         (m_PolarDisplay->GetSelection() == 0) ? false : true;
-    g_UserUnit  = (m_BoxUnits->GetSelection() == 0) ? INCHES : MILLIMETRES;
+    switch( m_BoxUnits->GetSelection() )
+    {
+    case 0:
+        g_UserUnit = INCHES;
+        break;
+
+    case 1:
+        g_UserUnit = MILLIMETRES;
+        break;
+
+    case 2:
+        g_UserUnit = MILS;
+        break;
+
+    }
 
     // @todo LEGACY: as above, this should be via the GAL display widget
 #ifndef __APPLE__
diff --git a/gerbview/dialogs/gerbview_dialog_display_options_frame_base.cpp b/gerbview/dialogs/gerbview_dialog_display_options_frame_base.cpp
index f977d04ce..1b8b943f5 100644
--- a/gerbview/dialogs/gerbview_dialog_display_options_frame_base.cpp
+++ b/gerbview/dialogs/gerbview_dialog_display_options_frame_base.cpp
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version May  6 2016)
+// C++ code generated with wxFormBuilder (version Aug 20 2017)
 // http://www.wxformbuilder.org/
 //
 // PLEASE DO "NOT" EDIT THIS FILE!
@@ -28,7 +28,7 @@ DIALOG_DISPLAY_OPTIONS_BASE::DIALOG_DISPLAY_OPTIONS_BASE( wxWindow* parent, wxWi
 	m_PolarDisplay->SetSelection( 0 );
 	bLeftSizer->Add( m_PolarDisplay, 0, wxALL|wxEXPAND, 5 );
 	
-	wxString m_BoxUnitsChoices[] = { _("Inches"), _("Millimeters") };
+	wxString m_BoxUnitsChoices[] = { _("Inches"), _("Millimeters"), _("Mils") };
 	int m_BoxUnitsNChoices = sizeof( m_BoxUnitsChoices ) / sizeof( wxString );
 	m_BoxUnits = new wxRadioBox( this, wxID_ANY, _("Units"), wxDefaultPosition, wxDefaultSize, m_BoxUnitsNChoices, m_BoxUnitsChoices, 1, wxRA_SPECIFY_COLS );
 	m_BoxUnits->SetSelection( 0 );
diff --git a/gerbview/dialogs/gerbview_dialog_display_options_frame_base.fbp b/gerbview/dialogs/gerbview_dialog_display_options_frame_base.fbp
index 1eafe8b81..1e05b9554 100644
--- a/gerbview/dialogs/gerbview_dialog_display_options_frame_base.fbp
+++ b/gerbview/dialogs/gerbview_dialog_display_options_frame_base.fbp
@@ -219,7 +219,7 @@
                                         <property name="caption"></property>
                                         <property name="caption_visible">1</property>
                                         <property name="center_pane">0</property>
-                                        <property name="choices">&quot;Inches&quot; &quot;Millimeters&quot;</property>
+                                        <property name="choices">&quot;Inches&quot; &quot;Millimeters&quot; &quot;Mils&quot;</property>
                                         <property name="close_button">1</property>
                                         <property name="context_help"></property>
                                         <property name="context_menu">1</property>
diff --git a/gerbview/dialogs/gerbview_dialog_display_options_frame_base.h b/gerbview/dialogs/gerbview_dialog_display_options_frame_base.h
index d9eae9242..16e4472c3 100644
--- a/gerbview/dialogs/gerbview_dialog_display_options_frame_base.h
+++ b/gerbview/dialogs/gerbview_dialog_display_options_frame_base.h
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version May  6 2016)
+// C++ code generated with wxFormBuilder (version Aug 20 2017)
 // http://www.wxformbuilder.org/
 //
 // PLEASE DO "NOT" EDIT THIS FILE!
diff --git a/gerbview/gerbview_frame.cpp b/gerbview/gerbview_frame.cpp
index 418d43fd7..1cf3a8174 100644
--- a/gerbview/gerbview_frame.cpp
+++ b/gerbview/gerbview_frame.cpp
@@ -458,7 +458,7 @@ void GERBVIEW_FRAME::Liste_D_Codes()
     int             ii, jj;
     wxString        Line;
     wxArrayString   list;
-    double          scale = g_UserUnit == INCHES ? IU_PER_MILS * 1000 : IU_PER_MM;
+    double          scale = g_UserUnit != MILLIMETRES ? IU_PER_MILS * (g_UserUnit == MILS ? 1 : 1000) : IU_PER_MM;
     int       curr_layer = getActiveLayer();
 
     for( int layer = 0; layer < (int)ImagesMaxCount(); ++layer )
@@ -478,7 +478,26 @@ void GERBVIEW_FRAME::Liste_D_Codes()
 
         list.Add( Line );
 
-        const char* units = g_UserUnit == INCHES ? "\"" : "mm";
+        const char* units;
+
+        switch( g_UserUnit )
+        {
+        case INCHES:
+            units = "\"";
+            break;
+
+        case MILLIMETRES:
+            units = "mm";
+            break;
+
+        case MILS:
+            units = "mil";
+            break;
+
+        default:
+            // other units not used here
+            break;
+        }
 
         for( ii = 0, jj = 1; ii < TOOLS_MAX_COUNT; ii++ )
         {
@@ -825,6 +844,10 @@ void GERBVIEW_FRAME::UpdateStatusBar()
             formatter = wxT( "Ro %.5f Th %.1f" );
             break;
 
+        case MILS:
+            formatter = wxT( "Ro %.3f Th %.1f" );
+            break;
+
         case UNSCALED_UNITS:
             formatter = wxT( "Ro %f Th %f" );
             break;
@@ -857,6 +880,11 @@ void GERBVIEW_FRAME::UpdateStatusBar()
         locformatter = wxT( "dx %.5f  dy %.5f  dist %.3f" );
         break;
 
+    case MILS:
+        absformatter = wxT( "X %.3f  Y %.3f" );
+        locformatter = wxT( "dx %.3f  dy %.3f  dist %.1f" );
+        break;
+
     case UNSCALED_UNITS:
         absformatter = wxT( "X %f  Y %f" );
         locformatter = wxT( "dx %f  dy %f  dist %f" );
diff --git a/gerbview/hotkeys.cpp b/gerbview/hotkeys.cpp
index 2a830358c..99993a7fd 100644
--- a/gerbview/hotkeys.cpp
+++ b/gerbview/hotkeys.cpp
@@ -176,7 +176,24 @@ bool GERBVIEW_FRAME::OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosit
         break;
 
     case HK_SWITCH_UNITS:
-        g_UserUnit = (g_UserUnit == INCHES ) ? MILLIMETRES : INCHES;
+        switch( g_UserUnit )
+        {
+        case INCHES:
+            g_UserUnit = MILLIMETRES;
+            break;
+
+        case MILLIMETRES:
+            g_UserUnit = MILS;
+            break;
+
+        case MILS:
+            g_UserUnit = INCHES;
+            break;
+
+        default:
+            // other units not used here
+            break;
+        }
         break;
 
     case HK_GBR_LINES_DISPLAY_MODE:
diff --git a/gerbview/toolbars_gerber.cpp b/gerbview/toolbars_gerber.cpp
index 367870265..a84d7ce96 100644
--- a/gerbview/toolbars_gerber.cpp
+++ b/gerbview/toolbars_gerber.cpp
@@ -235,6 +235,10 @@ void GERBVIEW_FRAME::ReCreateOptToolbar( void )
                                KiBitmap( unit_mm_xpm ),
                                _( "Set units to millimeters" ), wxITEM_CHECK );
 
+    m_optionsToolBar->AddTool( ID_TB_OPTIONS_SELECT_UNIT_MIL, wxEmptyString,
+                               KiBitmap( unit_mil_xpm ),
+                               _( "Set units to mils" ), wxITEM_CHECK );
+
 #ifndef __APPLE__
     m_optionsToolBar->AddTool( ID_TB_OPTIONS_SELECT_CURSOR, wxEmptyString,
                                KiBitmap( cursor_shape_xpm ),
@@ -318,8 +322,8 @@ void GERBVIEW_FRAME::updateDCodeSelectBox()
     // Build the aperture list of the current layer, and add it to the combo box:
     wxArrayString dcode_list;
     wxString msg;
-    const char* units = g_UserUnit == INCHES ? "mils" : "mm";
-    double scale = g_UserUnit == INCHES ? IU_PER_MILS : IU_PER_MM;
+    const char* units = g_UserUnit == INCHES || g_UserUnit == MILS ? "mils" : "mm";
+    double scale = g_UserUnit == INCHES || g_UserUnit == MILS ? IU_PER_MILS : IU_PER_MM;
 
     for( int ii = 0; ii < TOOLS_MAX_COUNT; ii++ )
     {
diff --git a/include/base_units.h b/include/base_units.h
index 5cbb0b6d6..532cac743 100644
--- a/include/base_units.h
+++ b/include/base_units.h
@@ -75,7 +75,7 @@ double To_User_Unit( EDA_UNITS_T aUnit, double aValue );
 /**
  * Function CoordinateToString
  * is a helper to convert the \a integer coordinate \a aValue to a string in inches,
- * millimeters, or unscaled units according to the current user units setting.
+ * millimeters, mils, or unscaled units according to the current user units setting.
  *
  * Should be used only to display a coordinate in status, but not in dialogs,
  * because the mantissa of the number displayed has 4 digits max for readability.
@@ -84,7 +84,7 @@ double To_User_Unit( EDA_UNITS_T aUnit, double aValue );
  *
  * @param aValue The integer coordinate to convert.
  * @param aConvertToMils Convert inch values to mils if true.  This setting has no effect if
- *                       the current user unit is millimeters.
+ *                       the current user unit is not inches.
  * @return The converted string for display in user interface elements.
  */
 wxString CoordinateToString( int aValue, bool aConvertToMils = false );
@@ -99,7 +99,7 @@ wxString AngleToStringDegrees( double aAngle );
 /**
  * Function LengthDoubleToString
  * is a helper to convert the \a double length \a aValue to a string in inches,
- * millimeters, or unscaled units according to the current user units setting.
+ * millimeters, mils, or unscaled units according to the current user units setting.
  *
  * Should be used only to display a coordinate in status, but not in dialogs,
  * because the mantissa of the number displayed has 4 digits max for readability.
@@ -108,7 +108,7 @@ wxString AngleToStringDegrees( double aAngle );
  *
  * @param aValue The double value to convert.
  * @param aConvertToMils Convert inch values to mils if true.  This setting has no effect if
- *                       the current user unit is millimeters.
+ *                       the current user unit is not inches.
  * @return The converted string for display in user interface elements.
  */
 wxString LengthDoubleToString( double aValue, bool aConvertToMils = false );
@@ -147,7 +147,7 @@ wxString& operator <<( wxString& aString, const wxPoint& aPoint );
 /**
  * Function PutValueInLocalUnits
  * converts \a aValue from internal units to user units and append the units notation
- * (mm or ")then inserts the string an \a aTextCtrl.
+ * (mm, mil or ")then inserts the string an \a aTextCtrl.
  *
  * This function is used in dialog boxes for entering values depending on selected units.
  */
@@ -155,7 +155,7 @@ void PutValueInLocalUnits( wxTextCtrl& aTextCtr, int aValue );
 
 /**
  * Return in internal units the value "val" given in a real unit
- * such as "in", "mm" or "deg"
+ * such as "in", "mm", "mil" or "deg"
  */
 double From_User_Unit( EDA_UNITS_T aUnit, double aValue );
 
diff --git a/include/bitmaps.h b/include/bitmaps.h
index a5de83bfa..e723fde9d 100644
--- a/include/bitmaps.h
+++ b/include/bitmaps.h
@@ -470,6 +470,7 @@ EXTERN_BITMAP( undelete_xpm )
 EXTERN_BITMAP( undo_xpm )
 EXTERN_BITMAP( unit_inch_xpm )
 EXTERN_BITMAP( unit_mm_xpm )
+EXTERN_BITMAP( unit_mil_xpm )
 EXTERN_BITMAP( unknown_xpm )
 EXTERN_BITMAP( unlocked_xpm )
 EXTERN_BITMAP( unzip_xpm )
diff --git a/include/common.h b/include/common.h
index d0337d562..3c38087ed 100644
--- a/include/common.h
+++ b/include/common.h
@@ -146,6 +146,7 @@ enum EDA_UNITS_T {
     MILLIMETRES = 1,
     UNSCALED_UNITS = 2,
     DEGREES = 3,
+    MILS = 4,
 };
 
 
diff --git a/include/id.h b/include/id.h
index 64411163b..52af2e288 100644
--- a/include/id.h
+++ b/include/id.h
@@ -259,6 +259,7 @@ enum main_id
     // Common to all
     ID_TB_OPTIONS_SELECT_UNIT_MM,
     ID_TB_OPTIONS_SELECT_UNIT_INCH,
+    ID_TB_OPTIONS_SELECT_UNIT_MIL,
     ID_TB_OPTIONS_SELECT_CURSOR,
     ID_TB_OPTIONS_SHOW_POLAR_COORD,
     ID_TB_OPTIONS_SHOW_GRID,
diff --git a/pagelayout_editor/pl_editor_frame.cpp b/pagelayout_editor/pl_editor_frame.cpp
index f75abd334..609369f55 100644
--- a/pagelayout_editor/pl_editor_frame.cpp
+++ b/pagelayout_editor/pl_editor_frame.cpp
@@ -471,6 +471,10 @@ void PL_EDITOR_FRAME::UpdateStatusBar()
         SetStatusText( _("mm"), 5 );
         break;
 
+    case MILS:
+        SetStatusText( _("mils"), 5 );
+        break;
+
     case UNSCALED_UNITS:
         SetStatusText( wxEmptyString, 5 );
         break;
diff --git a/pcbnew/basepcbframe.cpp b/pcbnew/basepcbframe.cpp
index d68da9b85..42bd444d3 100644
--- a/pcbnew/basepcbframe.cpp
+++ b/pcbnew/basepcbframe.cpp
@@ -685,6 +685,10 @@ void PCB_BASE_FRAME::UpdateStatusBar()
         case DEGREES:
             wxASSERT( false );
             break;
+
+        case MILS:
+            formatter = wxT( "Ro %.3f  Th %.1f" );
+            break;
         }
 
         line.Printf( formatter, To_User_Unit( g_UserUnit, ro ), theta );
@@ -719,6 +723,11 @@ void PCB_BASE_FRAME::UpdateStatusBar()
     case DEGREES:
         wxASSERT( false );
         break;
+
+    case MILS:
+        absformatter = wxT( "X %.3f  Y %.3f" );
+        locformatter = wxT( "dx %.3f  dy %.3f  dist %.1f" );
+        break;
     }
 
     line.Printf( absformatter, dXpos, dYpos );
@@ -827,7 +836,7 @@ void PCB_BASE_FRAME::updateGridSelectBox()
     // Update grid values with the current units setting.
     m_gridSelectBox->Clear();
     wxArrayString gridsList;
-    int icurr = GetScreen()->BuildGridsChoiceList( gridsList, g_UserUnit != INCHES );
+    int icurr = GetScreen()->BuildGridsChoiceList( gridsList, g_UserUnit != INCHES && g_UserUnit != MILS );
 
     for( size_t i = 0; i < GetScreen()->GetGridCount(); i++ )
     {
diff --git a/pcbnew/dialogs/dialog_general_options.cpp b/pcbnew/dialogs/dialog_general_options.cpp
index a6c8b1c6b..68d5dcf84 100644
--- a/pcbnew/dialogs/dialog_general_options.cpp
+++ b/pcbnew/dialogs/dialog_general_options.cpp
@@ -63,7 +63,24 @@ void DIALOG_GENERALOPTIONS::init()
 
     /* Set display options */
     m_PolarDisplay->SetSelection( displ_opts->m_DisplayPolarCood ? 1 : 0 );
-    m_UnitsSelection->SetSelection( g_UserUnit ? 1 : 0 );
+    switch( g_UserUnit )
+    {
+    case INCHES:
+        m_UnitsSelection->SetSelection( 0 );
+        break;
+
+    case MILLIMETRES:
+        m_UnitsSelection->SetSelection( 1 );
+        break;
+
+    case MILS:
+        m_UnitsSelection->SetSelection( 2 );
+        break;
+
+    default:
+        // other units not used here
+        break;
+    }
 
     wxString rotationAngle;
     rotationAngle = AngleToStringDegrees( (double)GetParent()->GetRotationAngle() );
@@ -101,7 +118,20 @@ void DIALOG_GENERALOPTIONS::OnOkClick( wxCommandEvent& event )
 
     displ_opts->m_DisplayPolarCood = ( m_PolarDisplay->GetSelection() == 0 ) ? false : true;
     ii = g_UserUnit;
-    g_UserUnit = ( m_UnitsSelection->GetSelection() == 0 )  ? INCHES : MILLIMETRES;
+    switch( m_UnitsSelection->GetSelection() )
+    {
+    case 0:
+        g_UserUnit = INCHES;
+        break;
+
+    case 1:
+        g_UserUnit = MILLIMETRES;
+        break;
+
+    case 2:
+        g_UserUnit = MILS;
+        break;
+    }
 
     if( ii != g_UserUnit )
         GetParent()->ReCreateAuxiliaryToolbar();
diff --git a/pcbnew/dialogs/dialog_general_options_BoardEditor_base.cpp b/pcbnew/dialogs/dialog_general_options_BoardEditor_base.cpp
index 652681de1..930b289e0 100644
--- a/pcbnew/dialogs/dialog_general_options_BoardEditor_base.cpp
+++ b/pcbnew/dialogs/dialog_general_options_BoardEditor_base.cpp
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Jun 17 2015)
+// C++ code generated with wxFormBuilder (version Aug 20 2017)
 // http://www.wxformbuilder.org/
 //
 // PLEASE DO "NOT" EDIT THIS FILE!
@@ -30,7 +30,7 @@ DIALOG_GENERALOPTIONS_BOARDEDITOR_BASE::DIALOG_GENERALOPTIONS_BOARDEDITOR_BASE(
 	
 	bLeftSizer->Add( m_PolarDisplay, 0, wxALL|wxEXPAND, 5 );
 	
-	wxString m_UnitsSelectionChoices[] = { _("Inches"), _("Millimeters") };
+	wxString m_UnitsSelectionChoices[] = { _("Inches"), _("Millimeters"), _("Mils") };
 	int m_UnitsSelectionNChoices = sizeof( m_UnitsSelectionChoices ) / sizeof( wxString );
 	m_UnitsSelection = new wxRadioBox( this, wxID_UNITS, _("Units"), wxDefaultPosition, wxDefaultSize, m_UnitsSelectionNChoices, m_UnitsSelectionChoices, 1, wxRA_SPECIFY_COLS );
 	m_UnitsSelection->SetSelection( 1 );
diff --git a/pcbnew/dialogs/dialog_general_options_BoardEditor_base.fbp b/pcbnew/dialogs/dialog_general_options_BoardEditor_base.fbp
index 7d1568e3e..75b5295a5 100644
--- a/pcbnew/dialogs/dialog_general_options_BoardEditor_base.fbp
+++ b/pcbnew/dialogs/dialog_general_options_BoardEditor_base.fbp
@@ -219,7 +219,7 @@
                                         <property name="caption"></property>
                                         <property name="caption_visible">1</property>
                                         <property name="center_pane">0</property>
-                                        <property name="choices">&quot;Inches&quot; &quot;Millimeters&quot;</property>
+                                        <property name="choices">&quot;Inches&quot; &quot;Millimeters&quot; &quot;Mils&quot;</property>
                                         <property name="close_button">1</property>
                                         <property name="context_help"></property>
                                         <property name="context_menu">1</property>
diff --git a/pcbnew/dialogs/dialog_general_options_BoardEditor_base.h b/pcbnew/dialogs/dialog_general_options_BoardEditor_base.h
index 4edb31f4f..1a20d0cb4 100644
--- a/pcbnew/dialogs/dialog_general_options_BoardEditor_base.h
+++ b/pcbnew/dialogs/dialog_general_options_BoardEditor_base.h
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Jun 17 2015)
+// C++ code generated with wxFormBuilder (version Aug 20 2017)
 // http://www.wxformbuilder.org/
 //
 // PLEASE DO "NOT" EDIT THIS FILE!
diff --git a/pcbnew/dialogs/dialog_plot.cpp b/pcbnew/dialogs/dialog_plot.cpp
index efb727269..38c4a9cf9 100644
--- a/pcbnew/dialogs/dialog_plot.cpp
+++ b/pcbnew/dialogs/dialog_plot.cpp
@@ -672,9 +672,9 @@ void DIALOG_PLOT::applyPlotSettings()
         msg.Printf( _( "Width correction constrained. "
                        "The reasonable width correction value must be in a range of "
                        " [%+f; %+f] (%s) for current design rules. " ),
-                    To_User_Unit( g_UserUnit, m_widthAdjustMinValue ),
-                    To_User_Unit( g_UserUnit, m_widthAdjustMaxValue ),
-                    ( g_UserUnit == INCHES ) ? wxT( "\"" ) : wxT( "mm" ) );
+                    To_User_Unit( (g_UserUnit != MILLIMETRES ? INCHES : MILLIMETRES), m_widthAdjustMinValue ),
+                    To_User_Unit( (g_UserUnit != MILLIMETRES ? INCHES : MILLIMETRES), m_widthAdjustMaxValue ),
+                    ( g_UserUnit != MILLIMETRES ) ? wxT( "\"" ) : wxT( "mm" ) );
         reporter.Report( msg, REPORTER::RPT_WARNING );
     }
 
diff --git a/pcbnew/hotkeys.cpp b/pcbnew/hotkeys.cpp
index 1a8b740fd..fa347a6af 100644
--- a/pcbnew/hotkeys.cpp
+++ b/pcbnew/hotkeys.cpp
@@ -424,8 +424,24 @@ bool FOOTPRINT_VIEWER_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aP
         break;
 
     case HK_SWITCH_UNITS:
-        cmd.SetId( (g_UserUnit == INCHES) ?
-                    ID_TB_OPTIONS_SELECT_UNIT_MM : ID_TB_OPTIONS_SELECT_UNIT_INCH );
+        switch( g_UserUnit )
+        {
+        case INCHES:
+            cmd.SetId( ID_TB_OPTIONS_SELECT_UNIT_MM );
+            break;
+
+        case MILLIMETRES:
+            cmd.SetId( ID_TB_OPTIONS_SELECT_UNIT_MIL );
+            break;
+
+        case MILS:
+            cmd.SetId( ID_TB_OPTIONS_SELECT_UNIT_INCH );
+            break;
+
+        default:
+            // other units not used here
+            break;
+        }
         GetEventHandler()->ProcessEvent( cmd );
         break;
 
diff --git a/pcbnew/hotkeys_board_editor.cpp b/pcbnew/hotkeys_board_editor.cpp
index 516388d9d..4a3ff2861 100644
--- a/pcbnew/hotkeys_board_editor.cpp
+++ b/pcbnew/hotkeys_board_editor.cpp
@@ -274,8 +274,24 @@ bool PCB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosit
         break;
 
     case HK_SWITCH_UNITS:
-        evt_type = (g_UserUnit == INCHES) ?
-                    ID_TB_OPTIONS_SELECT_UNIT_MM : ID_TB_OPTIONS_SELECT_UNIT_INCH;
+        switch( g_UserUnit )
+        {
+        case INCHES:
+            evt_type = ID_TB_OPTIONS_SELECT_UNIT_MM;
+            break;
+
+        case MILLIMETRES:
+            evt_type = ID_TB_OPTIONS_SELECT_UNIT_MIL;
+            break;
+
+        case MILS:
+            evt_type = ID_TB_OPTIONS_SELECT_UNIT_INCH;
+            break;
+
+        default:
+            // other units not used here
+            break;
+        }
         break;
 
     case HK_SWITCH_TRACK_DISPLAY_MODE:
diff --git a/pcbnew/hotkeys_module_editor.cpp b/pcbnew/hotkeys_module_editor.cpp
index a7a73050e..05208a585 100644
--- a/pcbnew/hotkeys_module_editor.cpp
+++ b/pcbnew/hotkeys_module_editor.cpp
@@ -111,8 +111,24 @@ bool FOOTPRINT_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPos
         break;
 
     case HK_SWITCH_UNITS:
-        cmd.SetId( (g_UserUnit == INCHES) ?
-                    ID_TB_OPTIONS_SELECT_UNIT_MM : ID_TB_OPTIONS_SELECT_UNIT_INCH );
+        switch( g_UserUnit )
+        {
+        case INCHES:
+            cmd.SetId( ID_TB_OPTIONS_SELECT_UNIT_MM );
+            break;
+
+        case MILLIMETRES:
+            cmd.SetId( ID_TB_OPTIONS_SELECT_UNIT_MIL );
+            break;
+
+        case MILS:
+            cmd.SetId( ID_TB_OPTIONS_SELECT_UNIT_INCH );
+            break;
+
+        default:
+            // other units not used here
+            break;
+        }
         GetEventHandler()->ProcessEvent( cmd );
         break;
 
diff --git a/pcbnew/tool_modedit.cpp b/pcbnew/tool_modedit.cpp
index b5b6b04db..1933461fe 100644
--- a/pcbnew/tool_modedit.cpp
+++ b/pcbnew/tool_modedit.cpp
@@ -228,6 +228,10 @@ void FOOTPRINT_EDIT_FRAME::ReCreateOptToolbar()
                                KiBitmap( unit_mm_xpm ),
                                _( "Set units to millimeters" ), wxITEM_CHECK );
 
+    m_optionsToolBar->AddTool( ID_TB_OPTIONS_SELECT_UNIT_MIL, wxEmptyString,
+                               KiBitmap( unit_mil_xpm ),
+                               _( "Set units to mils" ), wxITEM_CHECK );
+
 #ifndef __APPLE__
     m_optionsToolBar->AddTool( ID_TB_OPTIONS_SELECT_CURSOR, wxEmptyString,
                                KiBitmap( cursor_shape_xpm ),
diff --git a/pcbnew/tool_pcb.cpp b/pcbnew/tool_pcb.cpp
index c354c188b..8f7971630 100644
--- a/pcbnew/tool_pcb.cpp
+++ b/pcbnew/tool_pcb.cpp
@@ -346,6 +346,10 @@ void PCB_EDIT_FRAME::ReCreateOptToolbar()
                                KiBitmap( unit_mm_xpm ),
                                _( "Set units to millimeters" ), wxITEM_CHECK );
 
+    m_optionsToolBar->AddTool( ID_TB_OPTIONS_SELECT_UNIT_MIL, wxEmptyString,
+                               KiBitmap( unit_mil_xpm ),
+                               _( "Set units to mils" ), wxITEM_CHECK );
+
 #ifndef __APPLE__
     m_optionsToolBar->AddTool( ID_TB_OPTIONS_SELECT_CURSOR, wxEmptyString,
                                KiBitmap( cursor_shape_xpm ),
@@ -619,7 +623,7 @@ void PCB_EDIT_FRAME::updateTraceWidthSelectBox()
         return;
 
     wxString msg;
-    bool mmFirst = g_UserUnit != INCHES;
+    bool mmFirst = g_UserUnit == MILLIMETRES;
 
     m_SelTrackWidthBox->Clear();
 
@@ -627,7 +631,7 @@ void PCB_EDIT_FRAME::updateTraceWidthSelectBox()
     {
         int size = GetDesignSettings().m_TrackWidthList[ii];
 
-        double valueMils = To_User_Unit( INCHES, size ) * 1000;
+        double valueMils = To_User_Unit( MILS, size );
         double value_mm = To_User_Unit( MILLIMETRES, size );
 
         if( mmFirst )
@@ -659,13 +663,13 @@ void PCB_EDIT_FRAME::updateViaSizeSelectBox()
     wxString msg;
 
     m_SelViaSizeBox->Clear();
-    bool mmFirst = g_UserUnit != INCHES;
+    bool mmFirst = g_UserUnit == MILLIMETRES;
 
     for( unsigned ii = 0; ii < GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
     {
         int diam = GetDesignSettings().m_ViasDimensionsList[ii].m_Diameter;
 
-        double valueMils = To_User_Unit( INCHES, diam ) * 1000;
+        double valueMils = To_User_Unit( MILS, diam );
         double value_mm = To_User_Unit( MILLIMETRES, diam );
 
         if( mmFirst )
@@ -681,7 +685,7 @@ void PCB_EDIT_FRAME::updateViaSizeSelectBox()
         {
             msg  << wxT("/ ");
             wxString hole_str;
-            valueMils = To_User_Unit( INCHES, hole ) * 1000;
+            valueMils = To_User_Unit( MILS, hole );
             value_mm = To_User_Unit( MILLIMETRES, hole );
 
             if( mmFirst )
diff --git a/pcbnew/tools/pcbnew_control.cpp b/pcbnew/tools/pcbnew_control.cpp
index c3cc52c5c..b21296b81 100644
--- a/pcbnew/tools/pcbnew_control.cpp
+++ b/pcbnew/tools/pcbnew_control.cpp
@@ -679,10 +679,24 @@ int PCBNEW_CONTROL::SwitchUnits( const TOOL_EVENT& aEvent )
     // TODO should not it be refactored to pcb_frame member function?
     wxCommandEvent evt( wxEVT_COMMAND_MENU_SELECTED );
 
-    if( g_UserUnit == INCHES )
+    switch( g_UserUnit )
+    {
+    case INCHES:
         evt.SetId( ID_TB_OPTIONS_SELECT_UNIT_MM );
-    else
+        break;
+
+    case MILLIMETRES:
+        evt.SetId( ID_TB_OPTIONS_SELECT_UNIT_MIL );
+        break;
+
+    case MILS:
         evt.SetId( ID_TB_OPTIONS_SELECT_UNIT_INCH );
+        break;
+
+    default:
+        // other units not used here
+        break;
+    }
 
     m_frame->ProcessEvent( evt );
 

Follow ups