← Back to team overview

kicad-developers team mailing list archive

Re: [PATCH] common.h tidyups

 

Hi Wayne,

They are pretty much all independent in scope, but there might be
(very minor) conflicts if you apply a subset or out of order.

Here are the patches.

Cheers,

John

On Wed, Mar 22, 2017 at 10:03 PM, Wayne Stambaugh <stambaughw@xxxxxxxxx> wrote:
> Hey John,
>
> I'm assuming that the common.h tidy ups are from commit
> cb2ef9ea5e4ee449295c41573beefa2fc0935b84 forward.  If you don't mind, it
> would make my life a bit easier if you would send the patches.  They
> look like they are all stand alone changes so it shouldn't be an issue
> to push them one at a time.  If someone else can get to it before me,
> I'm fine with merging these changes.
>
> Cheers,
>
> Wayne
>
> On 3/22/2017 6:34 AM, John Beard wrote:
>> Hi Wayne,
>>
>> Just an update: the tidy_ups branch [1] has been rebased and a small
>> number of conflicts resolved (mostly includes being added in the same
>> places).
>>
>> Thanks,
>>
>> John
>>
>> [1] https://code.launchpad.net/~john-j-beard/kicad/+git/kicad/+ref/tidy_ups
>>
>> On Thu, Feb 9, 2017 at 10:08 PM, John Beard <john.j.beard@xxxxxxxxx> wrote:
>>> Hi Wayne,
>>>
>>> Yes, first in the list is "8f192fe12 OPENGL_GAL: Init currentTarget"
>>>
>>> That particular one is actually an older patch I had on my tidy-up
>>> branch and isn't really in the common.h set, but it keeps my IDE
>>> quieter! 5e6a022b5 is the first common.h one.
>>>
>>> Cheers,
>>>
>>> John
>>>
>>> On Thu, Feb 9, 2017 at 9:56 PM, Wayne Stambaugh <stambaughw@xxxxxxxxx> wrote:
>>>> John,
>>>>
>>>> I like this idea.  Anything that prevents unnecessary compiling is a
>>>> good thing.  Looking at this repo, I'm guessing that everything from
>>>> commit 8f192fe12eb52efd6d024c82d1416db5e62b345f on is what needs to be
>>>> merged.  I'll try to take a look at it over the weekend.  Keep up the
>>>> great work.
>>>>
>>>> Thanks,
>>>>
>>>> Wayne
>>>>
>>>> On 2/9/2017 8:44 AM, John Beard wrote:
>>>>> Hi,
>>>>>
>>>>> I have a big set of patches on a branch that are mostly to do with
>>>>> stripping seldom-used functions out of common.h into more targeted
>>>>> headers:
>>>>>
>>>>> https://code.launchpad.net/~john-j-beard/kicad/+git/kicad/+ref/tidy_ups
>>>>>
>>>>> The idea here is to reduce the visibility of these functions from
>>>>> almost every file in KiCad to just those that need them. This also
>>>>> means that changing the signatures (or even just adding comments)
>>>>> doesn't force a huge recompile of the whole codebase, just the files
>>>>> that use them. It also makes common.h less of a "dumping ground" for
>>>>> random stuff.
>>>>>
>>>>> There were several old functions or variables that weren't used,
>>>>> weren't defined, or weren't declared too, and these were tidied up.
>>>>>
>>>>> I have used std::unique_ptr in a couple of places, at one was leaking
>>>>> an object before.
>>>>>
>>>>> I only meant to do a few, but since any big work in common.h is as bad
>>>>> as small work, I did quite a few.
>>>>>
>>>>> The patches should mostly be cherry-pickable in case not all of them are wanted.
>>>>>
>>>>> Cheers,
>>>>>
>>>>> John
>>>>>
>>>>> _______________________________________________
>>>>> Mailing list: https://launchpad.net/~kicad-developers
>>>>> Post to     : kicad-developers@xxxxxxxxxxxxxxxxxxx
>>>>> Unsubscribe : https://launchpad.net/~kicad-developers
>>>>> More help   : https://help.launchpad.net/ListHelp
>>>>>
>>>>
>>>> _______________________________________________
>>>> Mailing list: https://launchpad.net/~kicad-developers
>>>> Post to     : kicad-developers@xxxxxxxxxxxxxxxxxxx
>>>> Unsubscribe : https://launchpad.net/~kicad-developers
>>>> More help   : https://help.launchpad.net/ListHelp
From 312c3484134c4de370961a4c9c209bcdfc8508c6 Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Mon, 23 Jan 2017 13:19:10 +0800
Subject: [PATCH 01/13] OPENGL_GAL: Init currentTarget

The currentTarget member of OPENGL_GAL is not initialised, but the
currentManager member is.

This commit uses SetTarget to initialise both target and manager to a
consistent state at construction.
---
 common/gal/opengl/opengl_gal.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp
index 5759aff17..81941547a 100644
--- a/common/gal/opengl/opengl_gal.cpp
+++ b/common/gal/opengl/opengl_gal.cpp
@@ -140,7 +140,7 @@ OPENGL_GAL::OPENGL_GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions, wxWindow* aParent,
 
     gluTessProperty( tesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );
 
-    currentManager = nonCachedManager;
+    SetTarget( TARGET_NONCACHED );
 }
 
 
-- 
2.12.0

From cb2ef9ea5e4ee449295c41573beefa2fc0935b84 Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Thu, 9 Feb 2017 16:09:28 +0800
Subject: [PATCH 02/13] Move file locking utilities to a separate file

The global ::LockFile() function is used in a single place, but it's in
common.h, so visible to all files.

The GetKicadLockFilePath function is used in only two places, and one of
them is LockFile.

This commit puts them both in a separate header, so they're only visible
to code using them.

The implementation of GetKicadLockFilePath is moved to lockfile.cpp,
where LockFile already was.

Also removed a (large) handful of wxT macros, which aren't needed any
more and make code less readable.
---
 common/common.cpp     | 40 ---------------------------------
 common/draw_frame.cpp |  8 ++-----
 common/lockfile.cpp   | 61 ++++++++++++++++++++++++++++++++++++++++++---------
 common/pgm_base.cpp   |  1 +
 include/common.h      | 14 ------------
 include/draw_frame.h  |  2 +-
 include/lockfile.h    | 50 +++++++++++++++++++++++++++++++++++++++++
 7 files changed, 105 insertions(+), 71 deletions(-)
 create mode 100644 include/lockfile.h

diff --git a/common/common.cpp b/common/common.cpp
index 7e5f90f09..faa2b71b4 100644
--- a/common/common.cpp
+++ b/common/common.cpp
@@ -313,46 +313,6 @@ wxConfigBase* GetNewConfig( const wxString& aProgName )
     return cfg;
 }
 
-wxString GetKicadLockFilePath()
-{
-    wxFileName lockpath;
-    lockpath.AssignDir( wxGetHomeDir() ); // Default wx behavior
-
-#if defined( __WXMAC__ )
-    // In OSX use the standard per user cache directory
-    lockpath.AppendDir( wxT( "Library" ) );
-    lockpath.AppendDir( wxT( "Caches" ) );
-    lockpath.AppendDir( wxT( "kicad" ) );
-#elif defined( __UNIX__ )
-    wxString envstr;
-    // Try first the standard XDG_RUNTIME_DIR, falling back to XDG_CACHE_HOME
-    if( wxGetEnv( wxT( "XDG_RUNTIME_DIR" ), &envstr ) && !envstr.IsEmpty() )
-    {
-        lockpath.AssignDir( envstr );
-    }
-    else if( wxGetEnv( wxT( "XDG_CACHE_HOME" ), &envstr ) && !envstr.IsEmpty() )
-    {
-        lockpath.AssignDir( envstr );
-    }
-    else
-    {
-        // If all fails, just use ~/.cache
-        lockpath.AppendDir( wxT( ".cache" ) );
-    }
-
-    lockpath.AppendDir( wxT( "kicad" ) );
-#endif
-
-#if defined( __WXMAC__ ) || defined( __UNIX__ )
-    if( !lockpath.DirExists() )
-    {
-        // Lockfiles should be only readable by the user
-        lockpath.Mkdir( 0700, wxPATH_MKDIR_FULL );
-    }
-#endif
-    return lockpath.GetPath();
-}
-
 
 wxString GetKicadConfigPath()
 {
diff --git a/common/draw_frame.cpp b/common/draw_frame.cpp
index 99d683993..f1ed3aa39 100644
--- a/common/draw_frame.cpp
+++ b/common/draw_frame.cpp
@@ -45,6 +45,7 @@
 #include <dialog_helpers.h>
 #include <base_units.h>
 #include <math/box2.h>
+#include <lockfile.h>
 
 #include <wx/fontdlg.h>
 #include <wx/snglinst.h>
@@ -130,8 +131,6 @@ EDA_DRAW_FRAME::EDA_DRAW_FRAME( KIWAY* aKiway, wxWindow* aParent,
     KIWAY_PLAYER( aKiway, aParent, aFrameType, aTitle, aPos, aSize, aStyle, aFrameName ),
     m_galDisplayOptions( std::make_unique<KIGFX::GAL_DISPLAY_OPTIONS>() )
 {
-    m_file_checker        = NULL;
-
     m_drawToolBar         = NULL;
     m_optionsToolBar      = NULL;
     m_gridSelectBox       = NULL;
@@ -229,15 +228,12 @@ EDA_DRAW_FRAME::~EDA_DRAW_FRAME()
 
 void EDA_DRAW_FRAME::ReleaseFile()
 {
-    delete m_file_checker;
-    m_file_checker = 0;
+    m_file_checker = nullptr;
 }
 
 
 bool EDA_DRAW_FRAME::LockFile( const wxString& aFileName )
 {
-    delete m_file_checker;
-
     m_file_checker = ::LockFile( aFileName );
 
     return bool( m_file_checker );
diff --git a/common/lockfile.cpp b/common/lockfile.cpp
index b3c371400..92ee0bd54 100644
--- a/common/lockfile.cpp
+++ b/common/lockfile.cpp
@@ -2,7 +2,7 @@
  * This program source code file is part of KiCad, a free EDA CAD application.
  *
  * Copyright (C) 2014-2015 SoftPLC Corporation, Dick Hollenbeck <dick@xxxxxxxxxxx>
- * Copyright (C) 2014-2015 KiCad Developers, see CHANGELOG.TXT for contributors.
+ * Copyright (C) 2014-2017 KiCad Developers, see CHANGELOG.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
@@ -22,12 +22,14 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
+#include <lockfile.h>
+
 #include <wx/filename.h>
 #include <wx/snglinst.h>
-#include <common.h>
 
+#include <common.h>
 
-wxSingleInstanceChecker* LockFile( const wxString& aFileName )
+std::unique_ptr<wxSingleInstanceChecker> LockFile( const wxString& aFileName )
 {
     // first make absolute and normalize, to avoid that different lock files
     // for the same file can be created
@@ -35,22 +37,61 @@ wxSingleInstanceChecker* LockFile( const wxString& aFileName )
 
     fn.MakeAbsolute();
 
-    wxString lockFileName = fn.GetFullPath() + wxT( ".lock" );
+    wxString lockFileName = fn.GetFullPath() + ".lock";
 
-    lockFileName.Replace( wxT( "/" ), wxT( "_" ) );
+    lockFileName.Replace( "/", "_" );
 
     // We can have filenames coming from Windows, so also convert Windows separator
-    lockFileName.Replace( wxT( "\\" ), wxT( "_" ) );
+    lockFileName.Replace( "\\", "_" );
 
-    wxSingleInstanceChecker* p = new wxSingleInstanceChecker( lockFileName,
-                                                              GetKicadLockFilePath() );
+    auto p = std::make_unique<wxSingleInstanceChecker>( lockFileName,
+                                                        GetKicadLockFilePath() );
 
     if( p->IsAnotherRunning() )
     {
-        delete p;
-        p = NULL;
+        p = nullptr;
     }
 
     return p;
 }
 
+
+wxString GetKicadLockFilePath()
+{
+    wxFileName lockpath;
+    lockpath.AssignDir( wxGetHomeDir() ); // Default wx behavior
+
+#if defined( __WXMAC__ )
+    // In OSX use the standard per user cache directory
+    lockpath.AppendDir( "Library" );
+    lockpath.AppendDir( "Caches" );
+    lockpath.AppendDir( "kicad" );
+#elif defined( __UNIX__ )
+    wxString envstr;
+    // Try first the standard XDG_RUNTIME_DIR, falling back to XDG_CACHE_HOME
+    if( wxGetEnv( "XDG_RUNTIME_DIR", &envstr ) && !envstr.IsEmpty() )
+    {
+        lockpath.AssignDir( envstr );
+    }
+    else if( wxGetEnv( "XDG_CACHE_HOME", &envstr ) && !envstr.IsEmpty() )
+    {
+        lockpath.AssignDir( envstr );
+    }
+    else
+    {
+        // If all fails, just use ~/.cache
+        lockpath.AppendDir( ".cache" );
+    }
+
+    lockpath.AppendDir( "kicad" );
+#endif
+
+#if defined( __WXMAC__ ) || defined( __UNIX__ )
+    if( !lockpath.DirExists() )
+    {
+        // Lockfiles should be only readable by the user
+        lockpath.Mkdir( 0700, wxPATH_MKDIR_FULL );
+    }
+#endif
+    return lockpath.GetPath();
+}
diff --git a/common/pgm_base.cpp b/common/pgm_base.cpp
index cb9538118..c5a728cbf 100644
--- a/common/pgm_base.cpp
+++ b/common/pgm_base.cpp
@@ -51,6 +51,7 @@
 #include <menus_helpers.h>
 #include <confirm.h>
 #include <dialog_env_var_config.h>
+#include <lockfile.h>
 
 
 #define KICAD_COMMON                     wxT( "kicad_common" )
diff --git a/include/common.h b/include/common.h
index a083de89a..b448f3b3f 100644
--- a/include/common.h
+++ b/include/common.h
@@ -49,7 +49,6 @@
 
 class wxAboutDialogInfo;
 class SEARCH_STACK;
-class wxSingleInstanceChecker;
 class REPORTER;
 
 
@@ -350,14 +349,6 @@ bool EnsureFileDirectoryExists( wxFileName*     aTargetFullFileName,
                                   const wxString& aBaseFilename,
                                   REPORTER*       aReporter = NULL );
 
-/**
- * Function LockFile
- * tests to see if aFileName can be locked (is not already locked) and only then
- * returns a wxSingleInstanceChecker protecting aFileName.  Caller owns the return value.
- */
-wxSingleInstanceChecker* LockFile( const wxString& aFileName );
-
-
 /// Put aPriorityPath in front of all paths in the value of aEnvVar.
 const wxString PrePendPath( const wxString& aEnvVar, const wxString& aPriorityPath );
 
@@ -377,11 +368,6 @@ const wxString PrePendPath( const wxString& aEnvVar, const wxString& aPriorityPa
  */
 wxConfigBase* GetNewConfig( const wxString& aProgName );
 
-/**
- * Function GetKicadLockFilePath
- * @return A wxString containing the path for lockfiles in Kicad
- */
-wxString GetKicadLockFilePath();
 
 /**
  * Function GetKicadConfigPath
diff --git a/include/draw_frame.h b/include/draw_frame.h
index 90d517eb0..69b07160d 100644
--- a/include/draw_frame.h
+++ b/include/draw_frame.h
@@ -71,7 +71,7 @@ class EDA_DRAW_FRAME : public KIWAY_PLAYER
 
 protected:
 
-    wxSingleInstanceChecker* m_file_checker;    ///< prevents opening same file multiple times.
+    std::unique_ptr<wxSingleInstanceChecker> m_file_checker;    ///< prevents opening same file multiple times.
 
     EDA_HOTKEY_CONFIG* m_hotkeysDescrList;
     int         m_LastGridSizeId;           // the command id offset (>= 0) of the last selected grid
diff --git a/include/lockfile.h b/include/lockfile.h
new file mode 100644
index 000000000..586b46a26
--- /dev/null
+++ b/include/lockfile.h
@@ -0,0 +1,50 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+/**
+ * File locking utilities
+ * @file lock_file.h
+ */
+
+#ifndef INCLUDE__LOCK_FILE_H_
+#define INCLUDE__LOCK_FILE_H_
+
+#include <wx/string.h>
+#include <memory>
+
+class wxSingleInstanceChecker;
+
+/**
+ * Function LockFile
+ * tests to see if aFileName can be locked (is not already locked) and only then
+ * returns a wxSingleInstanceChecker protecting aFileName.
+ */
+std::unique_ptr<wxSingleInstanceChecker> LockFile( const wxString& aFileName );
+
+/**
+ * Function GetKicadLockFilePath
+ * @return A wxString containing the path for lockfiles in Kicad
+ */
+wxString GetKicadLockFilePath();
+
+#endif  // INCLUDE__LOCK_FILE_H_
-- 
2.12.0

From edbca3d13bfa8621eec05447f702878a38c78324 Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Thu, 9 Feb 2017 16:25:33 +0800
Subject: [PATCH 03/13] Move SystemDirsAppend to own header

This function is called only from three sites, it doesn't need to be in
common.h.

The implementation was already in systemdirsappend.cpp, so a matching
header was created for it.

This reduces the visibility of the function to only the files that need
it and slightly shrinks common.h.
---
 common/kiface_i.cpp        |  1 +
 common/pgm_base.cpp        |  1 +
 include/common.h           | 10 ----------
 include/systemdirsappend.h | 42 ++++++++++++++++++++++++++++++++++++++++++
 kicad/kicad.cpp            |  2 ++
 5 files changed, 46 insertions(+), 10 deletions(-)
 create mode 100644 include/systemdirsappend.h

diff --git a/common/kiface_i.cpp b/common/kiface_i.cpp
index fdafa4eeb..a91df04a7 100644
--- a/common/kiface_i.cpp
+++ b/common/kiface_i.cpp
@@ -29,6 +29,7 @@
 
 #include <kiface_i.h>
 #include <pgm_base.h>
+#include <systemdirsappend.h>
 
 #include <common.h>
 
diff --git a/common/pgm_base.cpp b/common/pgm_base.cpp
index c5a728cbf..790d9792e 100644
--- a/common/pgm_base.cpp
+++ b/common/pgm_base.cpp
@@ -52,6 +52,7 @@
 #include <confirm.h>
 #include <dialog_env_var_config.h>
 #include <lockfile.h>
+#include <systemdirsappend.h>
 
 
 #define KICAD_COMMON                     wxT( "kicad_common" )
diff --git a/include/common.h b/include/common.h
index b448f3b3f..63703ad5e 100644
--- a/include/common.h
+++ b/include/common.h
@@ -304,16 +304,6 @@ double RoundTo0( double x, double precision );
  */
 void wxStringSplit( const wxString& aText, wxArrayString& aStrings, wxChar aSplitter );
 
-
-/**
- * Function SystemDirsAppend
- * appends system places to aSearchStack in a platform specific way, and pertinent
- * to KiCad programs.  It seems to be a place to collect bad ideas and keep them
- * out of view.
- */
-void SystemDirsAppend( SEARCH_STACK* aSearchStack );
-
-
 /**
  * Function SearchHelpFileFullPath
  * returns the help file's full path.
diff --git a/include/systemdirsappend.h b/include/systemdirsappend.h
new file mode 100644
index 000000000..9608ef56b
--- /dev/null
+++ b/include/systemdirsappend.h
@@ -0,0 +1,42 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+/**
+ * System directories search utilities
+ * @file systemdirsappend.h
+ */
+
+#ifndef INCLUDE__SYSTEM_DIRS_APPEND_H_
+#define INCLUDE__SYSTEM_DIRS_APPEND_H_
+
+class SEARCH_STACK;
+
+/**
+ * Function SystemDirsAppend
+ * appends system places to aSearchStack in a platform specific way, and pertinent
+ * to KiCad programs.  It seems to be a place to collect bad ideas and keep them
+ * out of view.
+ */
+void SystemDirsAppend( SEARCH_STACK* aSearchStack );
+
+#endif  // INCLUDE__SYSTEM_DIRS_APPEND_H_
diff --git a/kicad/kicad.cpp b/kicad/kicad.cpp
index 00edea617..90b950b98 100644
--- a/kicad/kicad.cpp
+++ b/kicad/kicad.cpp
@@ -38,6 +38,8 @@
 #include <kiway.h>
 #include <richio.h>
 #include <wildcards_and_files_ext.h>
+#include <systemdirsappend.h>
+
 #include <stdexcept>
 
 #include "pgm_kicad.h"
-- 
2.12.0

From 968c75011467a2b1622c0796643b4f667c571340 Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Thu, 9 Feb 2017 17:36:38 +0800
Subject: [PATCH 04/13] Move executable name constants to own file

The executable name constants are only used by two files, they do not
have to be in common.h.

Also converted to const wxString for better type-safety and removed
old-style wxT macros.
---
 common/CMakeLists.txt            |  1 +
 common/executable_names.cpp      | 46 ++++++++++++++++++++++++++++++++++++++++
 eeschema/schframe.cpp            |  1 +
 include/common.h                 | 20 -----------------
 include/executable_names.h       | 42 ++++++++++++++++++++++++++++++++++++
 kicad/class_treeproject_item.cpp |  1 +
 kicad/mainframe.cpp              |  1 +
 7 files changed, 92 insertions(+), 20 deletions(-)
 create mode 100644 common/executable_names.cpp
 create mode 100644 include/executable_names.h

diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index a9e017c5f..8aaa5d90a 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -239,6 +239,7 @@ set( COMMON_SRCS
     eda_doc.cpp
     eda_pattern_match.cpp
     exceptions.cpp
+    executable_names.cpp
     filter_reader.cpp
     lib_id.cpp
     lib_table_keywords.cpp
diff --git a/common/executable_names.cpp b/common/executable_names.cpp
new file mode 100644
index 000000000..f5475c591
--- /dev/null
+++ b/common/executable_names.cpp
@@ -0,0 +1,46 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2014-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 2008-2015 Wayne Stambaugh <stambaughw@xxxxxxxxxxx>
+ * Copyright (C) 1992-2015 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+
+#include <executable_names.h>
+
+// TODO Executable names TODO
+#ifdef __WINDOWS__
+const wxString CVPCB_EXE           ( "cvpcb.exe" );
+const wxString PCBNEW_EXE          ( "pcbnew.exe" );
+const wxString EESCHEMA_EXE        ( "eeschema.exe" );
+const wxString GERBVIEW_EXE        ( "gerbview.exe" );
+const wxString BITMAPCONVERTER_EXE ( "bitmap2component.exe" );
+const wxString PCB_CALCULATOR_EXE  ( "pcb_calculator.exe" );
+const wxString PL_EDITOR_EXE       ( "pl_editor.exe" );
+#else
+const wxString CVPCB_EXE           ( "cvpcb" );
+const wxString PCBNEW_EXE          ( "pcbnew" );
+const wxString EESCHEMA_EXE        ( "eeschema" );
+const wxString GERBVIEW_EXE        ( "gerbview" );
+const wxString BITMAPCONVERTER_EXE ( "bitmap2component" );
+const wxString PCB_CALCULATOR_EXE  ( "pcb_calculator" );
+const wxString PL_EDITOR_EXE       ( "pl_editor" );
+#endif
diff --git a/eeschema/schframe.cpp b/eeschema/schframe.cpp
index be5b110b8..42687c20f 100644
--- a/eeschema/schframe.cpp
+++ b/eeschema/schframe.cpp
@@ -36,6 +36,7 @@
 #include <base_units.h>
 #include <msgpanel.h>
 #include <html_messagebox.h>
+#include <executable_names.h>
 
 #include <general.h>
 #include <eeschema_id.h>
diff --git a/include/common.h b/include/common.h
index 63703ad5e..8f6d1a1dc 100644
--- a/include/common.h
+++ b/include/common.h
@@ -86,26 +86,6 @@ enum pseudokeys {
 
 #define ESC 27
 
-// TODO Executable names TODO
-#ifdef __WINDOWS__
-#define CVPCB_EXE           wxT( "cvpcb.exe" )
-#define PCBNEW_EXE          wxT( "pcbnew.exe" )
-#define EESCHEMA_EXE        wxT( "eeschema.exe" )
-#define GERBVIEW_EXE        wxT( "gerbview.exe" )
-#define BITMAPCONVERTER_EXE wxT( "bitmap2component.exe" )
-#define PCB_CALCULATOR_EXE  wxT( "pcb_calculator.exe" )
-#define PL_EDITOR_EXE       wxT( "pl_editor.exe" )
-#else
-#define CVPCB_EXE           wxT( "cvpcb" )
-#define PCBNEW_EXE          wxT( "pcbnew" )
-#define EESCHEMA_EXE        wxT( "eeschema" )
-#define GERBVIEW_EXE        wxT( "gerbview" )
-#define BITMAPCONVERTER_EXE wxT( "bitmap2component" )
-#define PCB_CALCULATOR_EXE  wxT( "pcb_calculator" )
-#define PL_EDITOR_EXE       wxT( "pl_editor" )
-#endif
-
-
 /// Frequent text rotations, used with {Set,Get}TextAngle(),
 /// in 0.1 degrees for now, hoping to migrate to degrees eventually.
 #define TEXT_ANGLE_HORIZ    0
diff --git a/include/executable_names.h b/include/executable_names.h
new file mode 100644
index 000000000..12d3da8f1
--- /dev/null
+++ b/include/executable_names.h
@@ -0,0 +1,42 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+/**
+ * KiCad executable names
+ * @file executable_names.h
+ */
+
+#ifndef INCLUDE__EXECUTABLE_NAMES_H_
+#define INCLUDE__EXECUTABLE_NAMES_H_
+
+#include <wx/string.h>
+
+extern const wxString CVPCB_EXE;
+extern const wxString PCBNEW_EXE;
+extern const wxString EESCHEMA_EXE;
+extern const wxString GERBVIEW_EXE;
+extern const wxString BITMAPCONVERTER_EXE;
+extern const wxString PCB_CALCULATOR_EXE;
+extern const wxString PL_EDITOR_EXE;
+
+#endif  // INCLUDE__EXECUTABLE_NAMES_H_
diff --git a/kicad/class_treeproject_item.cpp b/kicad/class_treeproject_item.cpp
index 6fa6278b4..b5c4fc9e6 100644
--- a/kicad/class_treeproject_item.cpp
+++ b/kicad/class_treeproject_item.cpp
@@ -32,6 +32,7 @@
 #include <wx/regex.h>
 
 #include <gestfich.h>
+#include <executable_names.h>
 
 #include "class_treeprojectfiles.h"
 #include "pgm_kicad.h"
diff --git a/kicad/mainframe.cpp b/kicad/mainframe.cpp
index 99f9695da..f135ee058 100644
--- a/kicad/mainframe.cpp
+++ b/kicad/mainframe.cpp
@@ -36,6 +36,7 @@
 #include <kiway_player.h>
 #include <wildcards_and_files_ext.h>
 #include <bitmaps.h>
+#include <executable_names.h>
 
 #include "pgm_kicad.h"
 #include "tree_project_frame.h"
-- 
2.12.0

From c773893a3a9903f0bc1b4b14ea178b7f37d92611 Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Thu, 9 Feb 2017 16:47:13 +0800
Subject: [PATCH 05/13] Move directory/path/env var utils to own headers

These functions, previously in common.h, are only used in about 20 files
in the whole of kicad in total, which means they don't really need to be
in common.h and visible to every single translation unit.

This commit introduces:

* directory_utils.h for generic directory and config path utils
* help_file_utils.h for utilities to do with the help file stack
* env_var_utils.h for utilities to do with environment variables
---
 3d-viewer/3d_cache/3d_cache.cpp                  |   3 +-
 3d-viewer/3d_cache/3d_cache_wrapper.cpp          |   1 +
 3d-viewer/3d_cache/3d_filename_resolver.cpp      |   1 +
 3d-viewer/3d_cache/3d_plugin_manager.cpp         |   1 +
 3d-viewer/3d_cache/dialogs/dlg_3d_pathconfig.cpp |   1 +
 bitmap2component/bitmap2cmp_gui.cpp              |   1 +
 common/CMakeLists.txt                            |   2 +
 common/basicframe.cpp                            |   2 +
 common/bin_mod.cpp                               |   2 +-
 common/common.cpp                                | 164 +-------------------
 common/directory_utils.cpp                       | 181 +++++++++++++++++++++++
 common/eda_doc.cpp                               |   1 +
 common/env_var_utils.cpp                         |  48 ++++++
 common/fp_lib_table.cpp                          |   1 +
 common/gestfich.cpp                              |   1 +
 common/hotkeys_basic.cpp                         |   1 +
 common/lib_table_base.cpp                        |   1 +
 common/page_layout/class_worksheet_layout.cpp    |   1 +
 common/pgm_base.cpp                              |   1 +
 common/searchhelpfilefullpath.cpp                |   4 +-
 common/systemdirsappend.cpp                      |   1 +
 eeschema/dialogs/dialog_bom.cpp                  |   1 +
 eeschema/dialogs/dialog_netlist.cpp              |   1 +
 eeschema/dialogs/dialog_plot_schematic.cpp       |   1 +
 eeschema/schframe.h                              |   1 +
 eeschema/symbol_lib_table.cpp                    |   1 +
 include/common.h                                 |  95 ------------
 include/directory_utils.h                        |  93 ++++++++++++
 include/env_var_utils.h                          |  45 ++++++
 include/help_file_utils.h                        |  56 +++++++
 include/wxstruct.h                               |   1 +
 kicad/prjconfig.cpp                              |   1 +
 pcb_calculator/pcb_calculator_frame.cpp          |   1 +
 pcbnew/dialogs/dialog_SVG_print.cpp              |   1 +
 pcbnew/dialogs/dialog_plot.cpp                   |   1 +
 pcbnew/dialogs/wizard_add_fplib.cpp              |   1 +
 pcbnew/exporters/gen_modules_placefile.cpp       |   1 +
 pcbnew/pcbnew.cpp                                |   1 +
 pcbnew/pcbplot.cpp                               |   2 +-
 pcbnew/swig/python_scripting.cpp                 |   1 +
 40 files changed, 461 insertions(+), 263 deletions(-)
 create mode 100644 common/directory_utils.cpp
 create mode 100644 common/env_var_utils.cpp
 create mode 100644 include/directory_utils.h
 create mode 100644 include/env_var_utils.h
 create mode 100644 include/help_file_utils.h

diff --git a/3d-viewer/3d_cache/3d_cache.cpp b/3d-viewer/3d_cache/3d_cache.cpp
index 46d9acadf..8a6529a6e 100644
--- a/3d-viewer/3d_cache/3d_cache.cpp
+++ b/3d-viewer/3d_cache/3d_cache.cpp
@@ -40,6 +40,7 @@
 #include <glm/ext.hpp>
 
 #include "common.h"
+#include "env_var_utils.h"
 #include "3d_cache.h"
 #include "3d_info.h"
 #include "sg/scenegraph.h"
@@ -644,7 +645,7 @@ wxString S3D_CACHE::Get3DConfigDir( bool createDefault )
     if( !m_ConfigDir.empty() || !createDefault )
         return m_ConfigDir;
 
-    // note: duplicated from common/common.cpp GetKicadConfigPath() to avoid
+    // note: duplicated from common/directory_utils.cpp GetKicadConfigPath() to avoid
     // code coupling; ideally the instantiating code should call
     // Set3DConfigDir() to set the directory rather than relying on this
     // directory remaining the same in future KiCad releases.
diff --git a/3d-viewer/3d_cache/3d_cache_wrapper.cpp b/3d-viewer/3d_cache/3d_cache_wrapper.cpp
index 0e92b7aea..15d8c36a5 100644
--- a/3d-viewer/3d_cache/3d_cache_wrapper.cpp
+++ b/3d-viewer/3d_cache/3d_cache_wrapper.cpp
@@ -24,6 +24,7 @@
 
 #include <common.h>
 #include <pgm_base.h>
+#include <directory_utils.h>
 #include "3d_cache_wrapper.h"
 
 static wxCriticalSection lock3D_wrapper;
diff --git a/3d-viewer/3d_cache/3d_filename_resolver.cpp b/3d-viewer/3d_cache/3d_filename_resolver.cpp
index d3da5d745..c2026c321 100644
--- a/3d-viewer/3d_cache/3d_filename_resolver.cpp
+++ b/3d-viewer/3d_cache/3d_filename_resolver.cpp
@@ -29,6 +29,7 @@
 #include <wx/log.h>
 #include <wx/msgdlg.h>
 #include <pgm_base.h>
+#include <env_var_utils.h>
 
 #include "common.h"
 #include "3d_filename_resolver.h"
diff --git a/3d-viewer/3d_cache/3d_plugin_manager.cpp b/3d-viewer/3d_cache/3d_plugin_manager.cpp
index fbc02fa69..ebb89d02b 100644
--- a/3d-viewer/3d_cache/3d_plugin_manager.cpp
+++ b/3d-viewer/3d_cache/3d_plugin_manager.cpp
@@ -35,6 +35,7 @@
 #include <wx/string.h>
 
 #include "common.h"
+#include "env_var_utils.h"
 #include "pgm_base.h"
 #include "3d_plugin_manager.h"
 #include "plugins/3d/3d_plugin.h"
diff --git a/3d-viewer/3d_cache/dialogs/dlg_3d_pathconfig.cpp b/3d-viewer/3d_cache/dialogs/dlg_3d_pathconfig.cpp
index ceb85e9b4..d5efe0b21 100644
--- a/3d-viewer/3d_cache/dialogs/dlg_3d_pathconfig.cpp
+++ b/3d-viewer/3d_cache/dialogs/dlg_3d_pathconfig.cpp
@@ -24,6 +24,7 @@
 
 #include <wx/msgdlg.h>
 #include <pgm_base.h>
+#include <env_var_utils.h>
 #include <html_messagebox.h>
 #include "3d_cache/dialogs/dlg_3d_pathconfig.h"
 #include "3d_cache/3d_filename_resolver.h"
diff --git a/bitmap2component/bitmap2cmp_gui.cpp b/bitmap2component/bitmap2cmp_gui.cpp
index bab981c0a..6cf7fd1fa 100644
--- a/bitmap2component/bitmap2cmp_gui.cpp
+++ b/bitmap2component/bitmap2cmp_gui.cpp
@@ -36,6 +36,7 @@
 #include <menus_helpers.h>
 #include <kiway.h>
 #include <kiface_i.h>
+#include <directory_utils.h>
 
 #include <potracelib.h>
 
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index 8aaa5d90a..8c195f931 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -230,6 +230,7 @@ set( COMMON_SRCS
     copy_to_clipboard.cpp
     convert_basic_shapes_to_polygon.cpp
     dialog_shim.cpp
+    directory_utils.cpp
     displlst.cpp
     draw_frame.cpp
     draw_panel.cpp
@@ -238,6 +239,7 @@ set( COMMON_SRCS
     eda_dde.cpp
     eda_doc.cpp
     eda_pattern_match.cpp
+    env_var_utils.cpp
     exceptions.cpp
     executable_names.cpp
     filter_reader.cpp
diff --git a/common/basicframe.cpp b/common/basicframe.cpp
index 9ea253fe7..63c0b9109 100644
--- a/common/basicframe.cpp
+++ b/common/basicframe.cpp
@@ -40,6 +40,8 @@
 #include <wxstruct.h>
 #include <menus_helpers.h>
 #include <bitmaps.h>
+#include <directory_utils.h>
+#include <help_file_utils.h>
 
 #include <wx/display.h>
 #include <wx/utils.h>
diff --git a/common/bin_mod.cpp b/common/bin_mod.cpp
index 116bc206f..1025e670f 100644
--- a/common/bin_mod.cpp
+++ b/common/bin_mod.cpp
@@ -24,7 +24,7 @@
 
 #include <bin_mod.h>
 #include <common.h>
-
+#include <directory_utils.h>
 
 BIN_MOD::BIN_MOD( const char* aName ) :
     m_name( aName ),
diff --git a/common/common.cpp b/common/common.cpp
index faa2b71b4..52c842490 100644
--- a/common/common.cpp
+++ b/common/common.cpp
@@ -41,6 +41,7 @@
 #include <wx/stdpaths.h>
 
 #include <pgm_base.h>
+#include <directory_utils.h>
 
 using KIGFX::COLOR4D;
 
@@ -300,166 +301,3 @@ double RoundTo0( double x, double precision )
 
     return (double) ix / precision;
 }
-
-
-wxConfigBase* GetNewConfig( const wxString& aProgName )
-{
-    wxConfigBase* cfg = 0;
-    wxFileName configname;
-    configname.AssignDir( GetKicadConfigPath() );
-    configname.SetFullName( aProgName );
-
-    cfg = new wxFileConfig( wxT( "" ), wxT( "" ), configname.GetFullPath() );
-    return cfg;
-}
-
-
-wxString GetKicadConfigPath()
-{
-    wxFileName cfgpath;
-
-    // From the wxWidgets wxStandardPaths::GetUserConfigDir() help:
-    //      Unix: ~ (the home directory)
-    //      Windows: "C:\Documents and Settings\username\Application Data"
-    //      Mac: ~/Library/Preferences
-    cfgpath.AssignDir( wxStandardPaths::Get().GetUserConfigDir() );
-
-#if !defined( __WINDOWS__ ) && !defined( __WXMAC__ )
-    wxString envstr;
-
-    if( !wxGetEnv( wxT( "XDG_CONFIG_HOME" ), &envstr ) || envstr.IsEmpty() )
-    {
-        // XDG_CONFIG_HOME is not set, so use the fallback
-        cfgpath.AppendDir( wxT( ".config" ) );
-    }
-    else
-    {
-        // Override the assignment above with XDG_CONFIG_HOME
-        cfgpath.AssignDir( envstr );
-    }
-#endif
-
-    cfgpath.AppendDir( wxT( "kicad" ) );
-
-    if( !cfgpath.DirExists() )
-    {
-        cfgpath.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
-    }
-
-    return cfgpath.GetPath();
-}
-
-
-#include <ki_mutex.h>
-const wxString ExpandEnvVarSubstitutions( const wxString& aString )
-{
-    // wxGetenv( wchar_t* ) is not re-entrant on linux.
-    // Put a lock on multithreaded use of wxGetenv( wchar_t* ), called from wxEpandEnvVars(),
-    static MUTEX    getenv_mutex;
-
-    MUTLOCK lock( getenv_mutex );
-
-    // We reserve the right to do this another way, by providing our own member
-    // function.
-    return wxExpandEnvVars( aString );
-}
-
-bool EnsureFileDirectoryExists( wxFileName*     aTargetFullFileName,
-                                const wxString& aBaseFilename,
-                                REPORTER*       aReporter )
-{
-    wxString msg;
-    wxString baseFilePath = wxFileName( aBaseFilename ).GetPath();
-
-    // make aTargetFullFileName path, which is relative to aBaseFilename path (if it is not
-    // already an absolute path) absolute:
-    if( !aTargetFullFileName->MakeAbsolute( baseFilePath ) )
-    {
-        if( aReporter )
-        {
-            msg.Printf( _( "Cannot make path '%s' absolute with respect to '%s'." ),
-                        GetChars( aTargetFullFileName->GetPath() ),
-                        GetChars( baseFilePath ) );
-            aReporter->Report( msg, REPORTER::RPT_ERROR );
-        }
-
-        return false;
-    }
-
-    // Ensure the path of aTargetFullFileName exists, and create it if needed:
-    wxString outputPath( aTargetFullFileName->GetPath() );
-
-    if( !wxFileName::DirExists( outputPath ) )
-    {
-        if( wxMkdir( outputPath ) )
-        {
-            if( aReporter )
-            {
-                msg.Printf( _( "Output directory '%s' created.\n" ), GetChars( outputPath ) );
-                aReporter->Report( msg, REPORTER::RPT_INFO );
-                return true;
-            }
-        }
-        else
-        {
-            if( aReporter )
-            {
-                msg.Printf( _( "Cannot create output directory '%s'.\n" ),
-                            GetChars( outputPath ) );
-                aReporter->Report( msg, REPORTER::RPT_ERROR );
-            }
-
-            return false;
-        }
-    }
-
-    return true;
-}
-
-
-#ifdef __WXMAC__
-wxString GetOSXKicadUserDataDir()
-{
-    // According to wxWidgets documentation for GetUserDataDir:
-    // Mac: ~/Library/Application Support/appname
-    wxFileName udir( wxStandardPaths::Get().GetUserDataDir(), wxEmptyString );
-
-    // Since appname is different if started via launcher or standalone binary
-    // map all to "kicad" here
-    udir.RemoveLastDir();
-    udir.AppendDir( wxT( "kicad" ) );
-
-    return udir.GetPath();
-}
-
-
-wxString GetOSXKicadMachineDataDir()
-{
-    return wxT( "/Library/Application Support/kicad" );
-}
-
-
-wxString GetOSXKicadDataDir()
-{
-    // According to wxWidgets documentation for GetDataDir:
-    // Mac: appname.app/Contents/SharedSupport bundle subdirectory
-    wxFileName ddir( wxStandardPaths::Get().GetDataDir(), wxEmptyString );
-
-    // This must be mapped to main bundle for everything but kicad.app
-    const wxArrayString dirs = ddir.GetDirs();
-    if( dirs[dirs.GetCount() - 3] != wxT( "kicad.app" ) )
-    {
-        // Bundle structure resp. current path is
-        //   kicad.app/Contents/Applications/<standalone>.app/Contents/SharedSupport
-        // and will be mapped to
-        //   kicad.app/Contents/SharedSupprt
-        ddir.RemoveLastDir();
-        ddir.RemoveLastDir();
-        ddir.RemoveLastDir();
-        ddir.RemoveLastDir();
-        ddir.AppendDir( wxT( "SharedSupport" ) );
-    }
-
-    return ddir.GetPath();
-}
-#endif
diff --git a/common/directory_utils.cpp b/common/directory_utils.cpp
new file mode 100644
index 000000000..ca21a7877
--- /dev/null
+++ b/common/directory_utils.cpp
@@ -0,0 +1,181 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2014-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 2008-2015 Wayne Stambaugh <stambaughw@xxxxxxxxxxx>
+ * Copyright (C) 1992-2015 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#include <directory_utils.h>
+
+#include <macros.h>
+#include <reporter.h>
+
+#include <wx/stdpaths.h>
+#include <wx/utils.h>
+
+
+wxString GetKicadConfigPath()
+{
+    wxFileName cfgpath;
+
+    // From the wxWidgets wxStandardPaths::GetUserConfigDir() help:
+    //      Unix: ~ (the home directory)
+    //      Windows: "C:\Documents and Settings\username\Application Data"
+    //      Mac: ~/Library/Preferences
+    cfgpath.AssignDir( wxStandardPaths::Get().GetUserConfigDir() );
+
+#if !defined( __WINDOWS__ ) && !defined( __WXMAC__ )
+    wxString envstr;
+
+    if( !wxGetEnv( wxT( "XDG_CONFIG_HOME" ), &envstr ) || envstr.IsEmpty() )
+    {
+        // XDG_CONFIG_HOME is not set, so use the fallback
+        cfgpath.AppendDir( wxT( ".config" ) );
+    }
+    else
+    {
+        // Override the assignment above with XDG_CONFIG_HOME
+        cfgpath.AssignDir( envstr );
+    }
+#endif
+
+    cfgpath.AppendDir( wxT( "kicad" ) );
+
+    if( !cfgpath.DirExists() )
+    {
+        cfgpath.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
+    }
+
+    return cfgpath.GetPath();
+}
+
+
+wxConfigBase* GetNewConfig( const wxString& aProgName )
+{
+    wxConfigBase* cfg = 0;
+    wxFileName configname;
+    configname.AssignDir( GetKicadConfigPath() );
+    configname.SetFullName( aProgName );
+
+    cfg = new wxFileConfig( wxT( "" ), wxT( "" ), configname.GetFullPath() );
+    return cfg;
+}
+
+
+bool EnsureFileDirectoryExists( wxFileName*     aTargetFullFileName,
+                                const wxString& aBaseFilename,
+                                REPORTER*       aReporter )
+{
+    wxString msg;
+    wxString baseFilePath = wxFileName( aBaseFilename ).GetPath();
+
+    // make aTargetFullFileName path, which is relative to aBaseFilename path (if it is not
+    // already an absolute path) absolute:
+    if( !aTargetFullFileName->MakeAbsolute( baseFilePath ) )
+    {
+        if( aReporter )
+        {
+            msg.Printf( _( "Cannot make path '%s' absolute with respect to '%s'." ),
+                        GetChars( aTargetFullFileName->GetPath() ),
+                        GetChars( baseFilePath ) );
+            aReporter->Report( msg, REPORTER::RPT_ERROR );
+        }
+
+        return false;
+    }
+
+    // Ensure the path of aTargetFullFileName exists, and create it if needed:
+    wxString outputPath( aTargetFullFileName->GetPath() );
+
+    if( !wxFileName::DirExists( outputPath ) )
+    {
+        if( wxMkdir( outputPath ) )
+        {
+            if( aReporter )
+            {
+                msg.Printf( _( "Output directory '%s' created.\n" ), GetChars( outputPath ) );
+                aReporter->Report( msg, REPORTER::RPT_INFO );
+                return true;
+            }
+        }
+        else
+        {
+            if( aReporter )
+            {
+                msg.Printf( _( "Cannot create output directory '%s'.\n" ),
+                            GetChars( outputPath ) );
+                aReporter->Report( msg, REPORTER::RPT_ERROR );
+            }
+
+            return false;
+        }
+    }
+
+    return true;
+}
+
+
+#ifdef __WXMAC__
+wxString GetOSXKicadUserDataDir()
+{
+    // According to wxWidgets documentation for GetUserDataDir:
+    // Mac: ~/Library/Application Support/appname
+    wxFileName udir( wxStandardPaths::Get().GetUserDataDir(), wxEmptyString );
+
+    // Since appname is different if started via launcher or standalone binary
+    // map all to "kicad" here
+    udir.RemoveLastDir();
+    udir.AppendDir( wxT( "kicad" ) );
+
+    return udir.GetPath();
+}
+
+
+wxString GetOSXKicadMachineDataDir()
+{
+    return wxT( "/Library/Application Support/kicad" );
+}
+
+
+wxString GetOSXKicadDataDir()
+{
+    // According to wxWidgets documentation for GetDataDir:
+    // Mac: appname.app/Contents/SharedSupport bundle subdirectory
+    wxFileName ddir( wxStandardPaths::Get().GetDataDir(), wxEmptyString );
+
+    // This must be mapped to main bundle for everything but kicad.app
+    const wxArrayString dirs = ddir.GetDirs();
+    if( dirs[dirs.GetCount() - 3] != wxT( "kicad.app" ) )
+    {
+        // Bundle structure resp. current path is
+        //   kicad.app/Contents/Applications/<standalone>.app/Contents/SharedSupport
+        // and will be mapped to
+        //   kicad.app/Contents/SharedSupprt
+        ddir.RemoveLastDir();
+        ddir.RemoveLastDir();
+        ddir.RemoveLastDir();
+        ddir.RemoveLastDir();
+        ddir.AppendDir( wxT( "SharedSupport" ) );
+    }
+
+    return ddir.GetPath();
+}
+#endif
diff --git a/common/eda_doc.cpp b/common/eda_doc.cpp
index 608a6b3e4..851059233 100644
--- a/common/eda_doc.cpp
+++ b/common/eda_doc.cpp
@@ -32,6 +32,7 @@
 #include <confirm.h>
 #include <gestfich.h>
 
+#include <wx/config.h>
 #include <wx/mimetype.h>
 #include <wx/tokenzr.h>
 #include <wx/filename.h>
diff --git a/common/env_var_utils.cpp b/common/env_var_utils.cpp
new file mode 100644
index 000000000..3c2d367b0
--- /dev/null
+++ b/common/env_var_utils.cpp
@@ -0,0 +1,48 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2014-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 2008-2015 Wayne Stambaugh <stambaughw@xxxxxxxxxxx>
+ * Copyright (C) 1992-2015 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+/**
+ * @file env_var_utils.cpp
+ */
+
+#include <env_var_utils.h>
+
+#include <wx/confbase.h>
+
+#include <ki_mutex.h>
+
+
+const wxString ExpandEnvVarSubstitutions( const wxString& aString )
+{
+    // wxGetenv( wchar_t* ) is not re-entrant on linux.
+    // Put a lock on multithreaded use of wxGetenv( wchar_t* ), called from wxEpandEnvVars(),
+    static MUTEX    getenv_mutex;
+
+    MUTLOCK lock( getenv_mutex );
+
+    // We reserve the right to do this another way, by providing our own member
+    // function.
+    return wxExpandEnvVars( aString );
+}
diff --git a/common/fp_lib_table.cpp b/common/fp_lib_table.cpp
index 4c4f6e203..6648ea36a 100644
--- a/common/fp_lib_table.cpp
+++ b/common/fp_lib_table.cpp
@@ -32,6 +32,7 @@
 #include <lib_table_lexer.h>
 #include <fp_lib_table.h>
 #include <class_module.h>
+#include <directory_utils.h>
 
 #define OPT_SEP     '|'         ///< options separator character
 
diff --git a/common/gestfich.cpp b/common/gestfich.cpp
index 3a0957687..8c8b4852d 100644
--- a/common/gestfich.cpp
+++ b/common/gestfich.cpp
@@ -38,6 +38,7 @@
 #include <confirm.h>
 #include <common.h>
 #include <macros.h>
+#include <directory_utils.h>
 
 #include <gestfich.h>
 
diff --git a/common/hotkeys_basic.cpp b/common/hotkeys_basic.cpp
index ef4fa2d82..1b7971f1e 100644
--- a/common/hotkeys_basic.cpp
+++ b/common/hotkeys_basic.cpp
@@ -40,6 +40,7 @@
 #include <dialog_hotkeys_editor.h>
 #include <menus_helpers.h>
 #include <tool/tool_manager.h>
+#include <directory_utils.h>
 
 #include <wx/apptrait.h>
 #include <wx/stdpaths.h>
diff --git a/common/lib_table_base.cpp b/common/lib_table_base.cpp
index 422f74cef..93ea7e28a 100644
--- a/common/lib_table_base.cpp
+++ b/common/lib_table_base.cpp
@@ -34,6 +34,7 @@
 #include <kiface_i.h>
 #include <lib_table_lexer.h>
 #include <lib_table_base.h>
+#include <env_var_utils.h>
 
 
 #define OPT_SEP     '|'         ///< options separator character
diff --git a/common/page_layout/class_worksheet_layout.cpp b/common/page_layout/class_worksheet_layout.cpp
index 94c11a1bb..d887624e9 100644
--- a/common/page_layout/class_worksheet_layout.cpp
+++ b/common/page_layout/class_worksheet_layout.cpp
@@ -56,6 +56,7 @@
 #include <class_title_block.h>
 #include <worksheet_shape_builder.h>
 #include <class_worksheet_dataitem.h>
+#include <env_var_utils.h>
 
 
 // The layout shape used in the application
diff --git a/common/pgm_base.cpp b/common/pgm_base.cpp
index 790d9792e..5568e6b43 100644
--- a/common/pgm_base.cpp
+++ b/common/pgm_base.cpp
@@ -53,6 +53,7 @@
 #include <dialog_env_var_config.h>
 #include <lockfile.h>
 #include <systemdirsappend.h>
+#include <directory_utils.h>
 
 
 #define KICAD_COMMON                     wxT( "kicad_common" )
diff --git a/common/searchhelpfilefullpath.cpp b/common/searchhelpfilefullpath.cpp
index 3d1625505..5900355d2 100644
--- a/common/searchhelpfilefullpath.cpp
+++ b/common/searchhelpfilefullpath.cpp
@@ -27,7 +27,7 @@
 #include <common.h>
 #include <config.h>     // to define DEFAULT_INSTALL_PATH
 #include <macros.h>
-
+#include <directory_utils.h>
 
 /**
  * Function FindFileInSearchPaths
@@ -35,7 +35,7 @@
  * path by appending a list of path fragments from aSubdirs.  That modification
  * is not relative.
  */
-wxString FindFileInSearchPaths( const SEARCH_STACK& aStack,
+static wxString FindFileInSearchPaths( const SEARCH_STACK& aStack,
         const wxString& aFilename, const wxArrayString* aSubdirs )
 {
     wxPathList paths;
diff --git a/common/systemdirsappend.cpp b/common/systemdirsappend.cpp
index 3ce86dc3a..a3734359f 100644
--- a/common/systemdirsappend.cpp
+++ b/common/systemdirsappend.cpp
@@ -29,6 +29,7 @@
 #include <search_stack.h>
 #include <pgm_base.h>
 #include <config.h>     // to define DEFAULT_INSTALL_PATH
+#include <directory_utils.h>
 
 
 // put your best guesses in here, send the computer on a wild goose chase, its
diff --git a/eeschema/dialogs/dialog_bom.cpp b/eeschema/dialogs/dialog_bom.cpp
index 4fcc81d15..c945d8470 100644
--- a/eeschema/dialogs/dialog_bom.cpp
+++ b/eeschema/dialogs/dialog_bom.cpp
@@ -44,6 +44,7 @@
 #include <dialog_bom_base.h>
 #include <html_messagebox.h>
 #include <reporter.h>
+#include <directory_utils.h>
 
 #define BOM_PLUGINS_KEY wxT("bom_plugins")
 #define BOM_PLUGIN_SELECTED_KEY wxT("bom_plugin_selected")
diff --git a/eeschema/dialogs/dialog_netlist.cpp b/eeschema/dialogs/dialog_netlist.cpp
index d5e71da33..51f717d8f 100644
--- a/eeschema/dialogs/dialog_netlist.cpp
+++ b/eeschema/dialogs/dialog_netlist.cpp
@@ -53,6 +53,7 @@
 #include <wildcards_and_files_ext.h>
 #include <invoke_sch_dialog.h>
 #include <netlist_exporters/netlist_exporter_pspice.h>
+#include <directory_utils.h>
 
 #include <eeschema_id.h>
 
diff --git a/eeschema/dialogs/dialog_plot_schematic.cpp b/eeschema/dialogs/dialog_plot_schematic.cpp
index 5d57f954b..e2f5895fc 100644
--- a/eeschema/dialogs/dialog_plot_schematic.cpp
+++ b/eeschema/dialogs/dialog_plot_schematic.cpp
@@ -31,6 +31,7 @@
 #include <fctsys.h>
 #include <pgm_base.h>
 #include <kiface_i.h>
+#include <directory_utils.h>
 #include <worksheet.h>
 #include <plot_common.h>
 #include <class_sch_screen.h>
diff --git a/eeschema/schframe.h b/eeschema/schframe.h
index 356290899..a92a55fb7 100644
--- a/eeschema/schframe.h
+++ b/eeschema/schframe.h
@@ -64,6 +64,7 @@ class DIALOG_SCH_FIND;
 class wxFindDialogEvent;
 class wxFindReplaceData;
 class SCHLIB_FILTER;
+class REPORTER;
 
 
 /// enum used in RotationMiroir()
diff --git a/eeschema/symbol_lib_table.cpp b/eeschema/symbol_lib_table.cpp
index 1d71216b2..5601c4d2b 100644
--- a/eeschema/symbol_lib_table.cpp
+++ b/eeschema/symbol_lib_table.cpp
@@ -31,6 +31,7 @@
 #include <lib_table_lexer.h>
 #include <symbol_lib_table.h>
 #include <class_libentry.h>
+#include <directory_utils.h>
 
 #define OPT_SEP     '|'         ///< options separator character
 
diff --git a/include/common.h b/include/common.h
index 8f6d1a1dc..a0ad0cb17 100644
--- a/include/common.h
+++ b/include/common.h
@@ -36,8 +36,6 @@
 #include <boost/cstdint.hpp>
 
 #include <wx/wx.h>
-#include <wx/confbase.h>
-#include <wx/fileconf.h>
 
 #include <richio.h>
 #include <gal/color4d.h>
@@ -47,10 +45,6 @@
 // C++11 "polyfill" for the C++14 std::make_unique function
 #include "make_unique.h"
 
-class wxAboutDialogInfo;
-class SEARCH_STACK;
-class REPORTER;
-
 
 // Flag for special keys
 // This type could be extended to 64 bits to add room for more flags.
@@ -284,94 +278,5 @@ double RoundTo0( double x, double precision );
  */
 void wxStringSplit( const wxString& aText, wxArrayString& aStrings, wxChar aSplitter );
 
-/**
- * Function SearchHelpFileFullPath
- * returns the help file's full path.
- * <p>
- * Return the KiCad help file with path and extension.
- * Help files can be html (.html ext) or pdf (.pdf ext) files.
- * A \<BaseName\>.html file is searched and if not found,
- * \<BaseName\>.pdf file is searched in the same path.
- * If the help file for the current locale is not found, an attempt to find
- * the English version of the help file is made.
- * Help file is searched in directories in this order:
- *  help/\<canonical name\> like help/en_GB
- *  help/\<short name\> like help/en
- *  help/en
- * </p>
- * @param aSearchStack contains some possible base dirs that may be above the
- *  the one actually holding @a aBaseName.  These are starting points for nested searches.
- * @param aBaseName is the name of the help file to search for, <p>without extension</p>.
- * @return  wxEmptyString is returned if aBaseName is not found, else the full path & filename.
- */
-wxString SearchHelpFileFullPath( const SEARCH_STACK& aSearchStack, const wxString& aBaseName );
-
-/**
- * Helper function EnsureFileDirectoryExists
- * make \a aTargetFullFileName absolute and creates the path of this file if it doesn't yet exist.
- * @param aTargetFullFileName  the wxFileName containing the full path and file name to modify.  The path
- *                    may be absolute or relative to \a aBaseFilename .
- * @param aBaseFilename a full filename. Only its path is used to set the aTargetFullFileName path.
- * @param aReporter a point to a REPORTER object use to show messages (can be NULL)
- * @return true if \a aOutputDir already exists or was successfully created.
- */
-bool EnsureFileDirectoryExists( wxFileName*     aTargetFullFileName,
-                                  const wxString& aBaseFilename,
-                                  REPORTER*       aReporter = NULL );
-
-/// Put aPriorityPath in front of all paths in the value of aEnvVar.
-const wxString PrePendPath( const wxString& aEnvVar, const wxString& aPriorityPath );
-
-/**
- * Function GetNewConfig
- *
- * Use this function instead of creating a new wxConfig so we can put config files in
- * a more proper place for each platform. This is generally $HOME/.config/kicad/ in Linux
- * according to the FreeDesktop specification at
- * http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
- * The config object created here should be destroyed by the caller.
- *
- * @param aProgName is the name of the program calling this function - can be obtained by
- *  calling Pgm().App().GetAppName().  This will be the actual file name of the config file.
- * @return A pointer to a new wxConfigBase derived object is returned.  The caller is in charge
- *  of deleting it.
- */
-wxConfigBase* GetNewConfig( const wxString& aProgName );
-
-
-/**
- * Function GetKicadConfigPath
- * @return A wxString containing the config path for Kicad
- */
-wxString GetKicadConfigPath();
-
-/**
- * Function ExpandEnvVarSubstitutions
- * replaces any environment variable references with their values
- * @param aString = a string containing (perhaps) references to env var
- * @return a string where env var are replaced by their value
- */
-const wxString ExpandEnvVarSubstitutions( const wxString& aString );
-
-
-#ifdef __WXMAC__
-/**
- * OSX specific function GetOSXKicadUserDataDir
- * @return A wxString pointing to the user data directory for Kicad
- */
-wxString GetOSXKicadUserDataDir();
-
-/**
- * OSX specific function GetOSXMachineDataDir
- * @return A wxString pointing to the machine data directory for Kicad
- */
-wxString GetOSXKicadMachineDataDir();
-
-/**
- * OSX specific function GetOSXKicadDataDir
- * @return A wxString pointing to the bundle data directory for Kicad
- */
-wxString GetOSXKicadDataDir();
-#endif
 
 #endif  // INCLUDE__COMMON_H_
diff --git a/include/directory_utils.h b/include/directory_utils.h
new file mode 100644
index 000000000..1db01f94f
--- /dev/null
+++ b/include/directory_utils.h
@@ -0,0 +1,93 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+/**
+ * Directory utilities
+ * @file directory_utils.h
+ */
+
+#ifndef INCLUDE__DIRECTORY_UTILS_H_
+#define INCLUDE__DIRECTORY_UTILS_H_
+
+#include <wx/filename.h>
+#include <wx/config.h>
+
+class REPORTER;
+
+/**
+ * Helper function EnsureFileDirectoryExists
+ * make \a aTargetFullFileName absolute and creates the path of this file if it doesn't yet exist.
+ * @param aTargetFullFileName  the wxFileName containing the full path and file name to modify.  The path
+ *                    may be absolute or relative to \a aBaseFilename .
+ * @param aBaseFilename a full filename. Only its path is used to set the aTargetFullFileName path.
+ * @param aReporter a point to a REPORTER object use to show messages (can be NULL)
+ * @return true if \a aOutputDir already exists or was successfully created.
+ */
+bool EnsureFileDirectoryExists( wxFileName*     aTargetFullFileName,
+                                const wxString& aBaseFilename,
+                                REPORTER*       aReporter = nullptr );
+
+/**
+ * Function GetKicadConfigPath
+ * @return A wxString containing the config path for Kicad
+ */
+wxString GetKicadConfigPath();
+
+/**
+ * Function GetNewConfig
+ *
+ * Use this function instead of creating a new wxConfig so we can put config files in
+ * a more proper place for each platform. This is generally $HOME/.config/kicad/ in Linux
+ * according to the FreeDesktop specification at
+ * http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
+ * The config object created here should be destroyed by the caller.
+ *
+ * @param aProgName is the name of the program calling this function - can be obtained by
+ *  calling Pgm().App().GetAppName().  This will be the actual file name of the config file.
+ * @return A pointer to a new wxConfigBase derived object is returned.  The caller is in charge
+ *  of deleting it.
+ */
+wxConfigBase* GetNewConfig( const wxString& aProgName );
+
+
+#ifdef __WXMAC__
+/**
+ * OSX specific function GetOSXKicadUserDataDir
+ * @return A wxString pointing to the user data directory for Kicad
+ */
+wxString GetOSXKicadUserDataDir();
+
+/**
+ * OSX specific function GetOSXMachineDataDir
+ * @return A wxString pointing to the machine data directory for Kicad
+ */
+wxString GetOSXKicadMachineDataDir();
+
+/**
+ * OSX specific function GetOSXKicadDataDir
+ * @return A wxString pointing to the bundle data directory for Kicad
+ */
+wxString GetOSXKicadDataDir();
+#endif
+
+#endif  // INCLUDE__DIRECTORY_UTILS_H_
diff --git a/include/env_var_utils.h b/include/env_var_utils.h
new file mode 100644
index 000000000..cc756d3e1
--- /dev/null
+++ b/include/env_var_utils.h
@@ -0,0 +1,45 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+/**
+ * Environment variable utilities
+ * @file env_var_utils.h
+ */
+
+#ifndef INCLUDE__ENV_VAR_UTILS_H_
+#define INCLUDE__ENV_VAR_UTILS_H_
+
+#include <wx/string.h>
+
+/// Put aPriorityPath in front of all paths in the value of aEnvVar.
+const wxString PrePendPath( const wxString& aEnvVar, const wxString& aPriorityPath );
+
+/**
+ * Function ExpandEnvVarSubstitutions
+ * replaces any environment variable references with their values
+ * @param aString = a string containing (perhaps) references to env var
+ * @return a string where env var are replaced by their value
+ */
+const wxString ExpandEnvVarSubstitutions( const wxString& aString );
+
+#endif  // INCLUDE__ENV_VAR_UTILS_H_
diff --git a/include/help_file_utils.h b/include/help_file_utils.h
new file mode 100644
index 000000000..97abe3c58
--- /dev/null
+++ b/include/help_file_utils.h
@@ -0,0 +1,56 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+/**
+ * Help file utilities
+ * @file help_file_utils.h
+ */
+
+#ifndef INCLUDE__HELP_FILE_UTILS_H_
+#define INCLUDE__HELP_FILE_UTILS_H_
+
+class SEARCH_STACK;
+
+/**
+ * Function SearchHelpFileFullPath
+ * returns the help file's full path.
+ * <p>
+ * Return the KiCad help file with path and extension.
+ * Help files can be html (.html ext) or pdf (.pdf ext) files.
+ * A \<BaseName\>.html file is searched and if not found,
+ * \<BaseName\>.pdf file is searched in the same path.
+ * If the help file for the current locale is not found, an attempt to find
+ * the English version of the help file is made.
+ * Help file is searched in directories in this order:
+ *  help/\<canonical name\> like help/en_GB
+ *  help/\<short name\> like help/en
+ *  help/en
+ * </p>
+ * @param aSearchStack contains some possible base dirs that may be above the
+ *  the one actually holding @a aBaseName.  These are starting points for nested searches.
+ * @param aBaseName is the name of the help file to search for, <p>without extension</p>.
+ * @return  wxEmptyString is returned if aBaseName is not found, else the full path & filename.
+ */
+wxString SearchHelpFileFullPath( const SEARCH_STACK& aSearchStack, const wxString& aBaseName );
+
+#endif  // INCLUDE__HELP_FILE_UTILS_H_
diff --git a/include/wxstruct.h b/include/wxstruct.h
index 990adf29e..c7f7449c7 100644
--- a/include/wxstruct.h
+++ b/include/wxstruct.h
@@ -84,6 +84,7 @@ class MSG_PANEL_ITEM;
 class TOOL_MANAGER;
 class TOOL_DISPATCHER;
 class ACTIONS;
+class SEARCH_STACK;
 
 
 enum id_librarytype {
diff --git a/kicad/prjconfig.cpp b/kicad/prjconfig.cpp
index a74f1df7d..13fe7ad85 100644
--- a/kicad/prjconfig.cpp
+++ b/kicad/prjconfig.cpp
@@ -38,6 +38,7 @@
 #include <kiway.h>
 #include <project.h>
 #include <wildcards_and_files_ext.h>
+#include <directory_utils.h>
 
 #include "dialogs/dialog_template_selector.h"
 
diff --git a/pcb_calculator/pcb_calculator_frame.cpp b/pcb_calculator/pcb_calculator_frame.cpp
index 476dee9a9..badb6e78b 100644
--- a/pcb_calculator/pcb_calculator_frame.cpp
+++ b/pcb_calculator/pcb_calculator_frame.cpp
@@ -28,6 +28,7 @@
 #include <pcb_calculator.h>
 #include <UnitSelector.h>
 #include <bitmaps.h>
+#include <directory_utils.h>
 
 
 #define KEYWORD_FRAME_POSX                      wxT( "Pcb_calculator_Pos_x" )
diff --git a/pcbnew/dialogs/dialog_SVG_print.cpp b/pcbnew/dialogs/dialog_SVG_print.cpp
index af39ad843..6d7637421 100644
--- a/pcbnew/dialogs/dialog_SVG_print.cpp
+++ b/pcbnew/dialogs/dialog_SVG_print.cpp
@@ -39,6 +39,7 @@
 #include <macros.h>
 #include <reporter.h>
 #include <confirm.h>
+#include <directory_utils.h>
 
 #include <pcbnew.h>
 #include <pcbplot.h>
diff --git a/pcbnew/dialogs/dialog_plot.cpp b/pcbnew/dialogs/dialog_plot.cpp
index dea1cec63..8d66ea6df 100644
--- a/pcbnew/dialogs/dialog_plot.cpp
+++ b/pcbnew/dialogs/dialog_plot.cpp
@@ -34,6 +34,7 @@
 #include <base_units.h>
 #include <macros.h>
 #include <reporter.h>
+#include <directory_utils.h>
 
 #include <class_board.h>
 #include <wx/ffile.h>
diff --git a/pcbnew/dialogs/wizard_add_fplib.cpp b/pcbnew/dialogs/wizard_add_fplib.cpp
index b9c7cb46c..3de72335e 100644
--- a/pcbnew/dialogs/wizard_add_fplib.cpp
+++ b/pcbnew/dialogs/wizard_add_fplib.cpp
@@ -37,6 +37,7 @@
 #include <wx/uri.h>
 #include <wx/dir.h>
 #include <wx/progdlg.h>
+#include <wx/config.h>
 
 #include <pgm_base.h>
 #include <project.h>
diff --git a/pcbnew/exporters/gen_modules_placefile.cpp b/pcbnew/exporters/gen_modules_placefile.cpp
index 5bbfd0370..d75174650 100644
--- a/pcbnew/exporters/gen_modules_placefile.cpp
+++ b/pcbnew/exporters/gen_modules_placefile.cpp
@@ -38,6 +38,7 @@
 #include <build_version.h>
 #include <macros.h>
 #include <reporter.h>
+#include <directory_utils.h>
 
 #include <class_board.h>
 #include <class_module.h>
diff --git a/pcbnew/pcbnew.cpp b/pcbnew/pcbnew.cpp
index 65d4a2d95..27c8dffbf 100644
--- a/pcbnew/pcbnew.cpp
+++ b/pcbnew/pcbnew.cpp
@@ -42,6 +42,7 @@
 #include <eda_dde.h>
 #include <colors_selection.h>
 #include <wx/stdpaths.h>
+#include <directory_utils.h>
 
 #include <wx/file.h>
 #include <wx/snglinst.h>
diff --git a/pcbnew/pcbplot.cpp b/pcbnew/pcbplot.cpp
index 60bf96169..ca775d6b7 100644
--- a/pcbnew/pcbplot.cpp
+++ b/pcbnew/pcbplot.cpp
@@ -43,7 +43,7 @@
 #include <dialog_plot.h>
 #include <macros.h>
 #include <build_version.h>
-
+#include <directory_utils.h>
 
 const wxString GetGerberProtelExtension( LAYER_NUM aLayer )
 {
diff --git a/pcbnew/swig/python_scripting.cpp b/pcbnew/swig/python_scripting.cpp
index 0ffc9aff6..b0b23e45f 100644
--- a/pcbnew/swig/python_scripting.cpp
+++ b/pcbnew/swig/python_scripting.cpp
@@ -36,6 +36,7 @@
 #include <common.h>
 #include <gal/color4d.h>
 #include <macros.h>
+#include <directory_utils.h>
 
 #include <pgm_base.h>
 
-- 
2.12.0

From aab0488ef0ab9f10c9e4d52a3f4df4b16b7fa5a9 Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Thu, 9 Feb 2017 17:01:58 +0800
Subject: [PATCH 06/13] Remove unused PrePendPath function

---
 common/CMakeLists.txt   |  1 -
 common/prependpath.cpp  | 40 ----------------------------------------
 include/env_var_utils.h |  2 --
 3 files changed, 43 deletions(-)
 delete mode 100644 common/prependpath.cpp

diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index 8c195f931..16b62259e 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -264,7 +264,6 @@ set( COMMON_SRCS
     msgpanel.cpp
     netlist_keywords.cpp
     observable.cpp
-    prependpath.cpp
     project.cpp
     properties.cpp
     ptree.cpp
diff --git a/common/prependpath.cpp b/common/prependpath.cpp
deleted file mode 100644
index e0522dc03..000000000
--- a/common/prependpath.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright (C) 2014 CERN
- * Copyright (C) 2014 KiCad Developers, see CHANGELOG.TXT for contributors.
- * @author Maciej Suminski <maciej.suminski@xxxxxxx>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, you may find one here:
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- * or you may search the http://www.gnu.org website for the version 2 license,
- * or you may write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
- */
-
-#include <macros.h>
-#include <fctsys.h>
-#include <wx/filename.h>
-
-
-/// Put aPriorityPath in front of all paths in the value of aEnvVar.
-const wxString PrePendPath( const wxString& aEnvVar, const wxString& aPriorityPath )
-{
-    wxPathList  paths;
-
-    paths.AddEnvList( aEnvVar );
-    paths.Insert( aPriorityPath, 0 );
-
-    return wxJoin( paths, wxPATH_SEP[0] );
-}
diff --git a/include/env_var_utils.h b/include/env_var_utils.h
index cc756d3e1..603784255 100644
--- a/include/env_var_utils.h
+++ b/include/env_var_utils.h
@@ -31,8 +31,6 @@
 
 #include <wx/string.h>
 
-/// Put aPriorityPath in front of all paths in the value of aEnvVar.
-const wxString PrePendPath( const wxString& aEnvVar, const wxString& aPriorityPath );
 
 /**
  * Function ExpandEnvVarSubstitutions
-- 
2.12.0

From 30f42d7a94ea7b77e3682286f6bfd37ba09f66b8 Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Thu, 9 Feb 2017 18:16:28 +0800
Subject: [PATCH 07/13] Move some unit related util function to base_units.h

---
 common/base_units.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++
 common/common.cpp     | 99 ---------------------------------------------------
 include/base_units.h  | 31 ++++++++++++++++
 include/common.h      | 33 -----------------
 4 files changed, 129 insertions(+), 132 deletions(-)

diff --git a/common/base_units.cpp b/common/base_units.cpp
index bd03bcf3a..4611b182d 100644
--- a/common/base_units.cpp
+++ b/common/base_units.cpp
@@ -416,3 +416,101 @@ wxString AngleToStringDegrees( double aAngle )
     return text;
 }
 
+
+wxString ReturnUnitSymbol( EDA_UNITS_T aUnit, const wxString& formatString )
+{
+    wxString tmp;
+    wxString label;
+
+    switch( aUnit )
+    {
+    case INCHES:
+        tmp = _( "\"" );
+        break;
+
+    case MILLIMETRES:
+        tmp = _( "mm" );
+        break;
+
+    case UNSCALED_UNITS:
+        break;
+
+    case DEGREES:
+        wxASSERT( false );
+        break;
+    }
+
+    if( formatString.IsEmpty() )
+        return tmp;
+
+    label.Printf( formatString, GetChars( tmp ) );
+
+    return label;
+}
+
+
+wxString GetUnitsLabel( EDA_UNITS_T aUnit )
+{
+    wxString label;
+
+    switch( aUnit )
+    {
+    case INCHES:
+        label = _( "inches" );
+        break;
+
+    case MILLIMETRES:
+        label = _( "millimeters" );
+        break;
+
+    case UNSCALED_UNITS:
+        label = _( "units" );
+        break;
+
+    case DEGREES:
+        label = _( "degrees" );
+        break;
+    }
+
+    return label;
+}
+
+
+wxString GetAbbreviatedUnitsLabel( EDA_UNITS_T aUnit )
+{
+    wxString label;
+
+    switch( aUnit )
+    {
+    case INCHES:
+        label = _( "in" );
+        break;
+
+    case MILLIMETRES:
+        label = _( "mm" );
+        break;
+
+    case UNSCALED_UNITS:
+        break;
+
+    case DEGREES:
+        label = _( "deg" );
+        break;
+
+    default:
+        label = wxT( "??" );
+        break;
+    }
+
+    return label;
+}
+
+
+void AddUnitSymbol( wxStaticText& Stext, EDA_UNITS_T aUnit )
+{
+    wxString msg = Stext.GetLabel();
+
+    msg += ReturnUnitSymbol( aUnit );
+
+    Stext.SetLabel( msg );
+}
diff --git a/common/common.cpp b/common/common.cpp
index 52c842490..f102be3c4 100644
--- a/common/common.cpp
+++ b/common/common.cpp
@@ -136,105 +136,6 @@ bool EnsureTextCtrlWidth( wxTextCtrl* aCtrl, const wxString* aString )
 }
 
 
-wxString ReturnUnitSymbol( EDA_UNITS_T aUnit, const wxString& formatString )
-{
-    wxString tmp;
-    wxString label;
-
-    switch( aUnit )
-    {
-    case INCHES:
-        tmp = _( "\"" );
-        break;
-
-    case MILLIMETRES:
-        tmp = _( "mm" );
-        break;
-
-    case UNSCALED_UNITS:
-        break;
-
-    case DEGREES:
-        wxASSERT( false );
-        break;
-    }
-
-    if( formatString.IsEmpty() )
-        return tmp;
-
-    label.Printf( formatString, GetChars( tmp ) );
-
-    return label;
-}
-
-
-wxString GetUnitsLabel( EDA_UNITS_T aUnit )
-{
-    wxString label;
-
-    switch( aUnit )
-    {
-    case INCHES:
-        label = _( "inches" );
-        break;
-
-    case MILLIMETRES:
-        label = _( "millimeters" );
-        break;
-
-    case UNSCALED_UNITS:
-        label = _( "units" );
-        break;
-
-    case DEGREES:
-        label = _( "degrees" );
-        break;
-    }
-
-    return label;
-}
-
-
-wxString GetAbbreviatedUnitsLabel( EDA_UNITS_T aUnit )
-{
-    wxString label;
-
-    switch( aUnit )
-    {
-    case INCHES:
-        label = _( "in" );
-        break;
-
-    case MILLIMETRES:
-        label = _( "mm" );
-        break;
-
-    case UNSCALED_UNITS:
-        break;
-
-    case DEGREES:
-        label = _( "deg" );
-        break;
-
-    default:
-        label = wxT( "??" );
-        break;
-    }
-
-    return label;
-}
-
-
-void AddUnitSymbol( wxStaticText& Stext, EDA_UNITS_T aUnit )
-{
-    wxString msg = Stext.GetLabel();
-
-    msg += ReturnUnitSymbol( aUnit );
-
-    Stext.SetLabel( msg );
-}
-
-
 void wxStringSplit( const wxString& aText, wxArrayString& aStrings, wxChar aSplitter )
 {
     wxString tmp;
diff --git a/include/base_units.h b/include/base_units.h
index 6d37d99f9..5cbb0b6d6 100644
--- a/include/base_units.h
+++ b/include/base_units.h
@@ -37,6 +37,12 @@
 #include <common.h>
 #include <convert_to_biu.h>
 
+/// Convert mm to mils.
+inline int Mm2mils( double x ) { return KiROUND( x * 1000./25.4 ); }
+
+/// Convert mils to mm.
+inline int Mils2mm( double x ) { return KiROUND( x * 25.4 / 1000. ); }
+
 /** Helper function Double2Str to print a float number without
  * using scientific notation and no trailing 0
  * We want to avoid scientific notation in S-expr files (not easy to read)
@@ -191,4 +197,29 @@ int ValueFromString( const wxString& aTextValue );
  */
 int ValueFromTextCtrl( const wxTextCtrl& aTextCtr );
 
+/**
+ * Returns the units symbol.
+ *
+ * @param aUnits - Units type, default is current units setting.
+ * @param aFormatString - A formatting string to embed the units symbol into.  Note:
+ *                        the format string must contain the %s format specifier.
+ * @return The formatted units symbol.
+ */
+wxString ReturnUnitSymbol( EDA_UNITS_T aUnits = g_UserUnit,
+                           const wxString& aFormatString = _( " (%s):" ) );
+
+/**
+ * Get a human readable units string.
+ *
+ * The strings returned are full text name and not abbreviations or symbolic
+ * representations of the units.  Use ReturnUnitSymbol() for that.
+ *
+ * @param aUnits - The units text to return.
+ * @return The human readable units string.
+ */
+wxString GetUnitsLabel( EDA_UNITS_T aUnits );
+wxString GetAbbreviatedUnitsLabel( EDA_UNITS_T aUnit = g_UserUnit );
+
+void AddUnitSymbol( wxStaticText& Stext, EDA_UNITS_T aUnit = g_UserUnit );
+
 #endif   // _BASE_UNITS_H_
diff --git a/include/common.h b/include/common.h
index a0ad0cb17..fe18127cb 100644
--- a/include/common.h
+++ b/include/common.h
@@ -135,14 +135,6 @@ static inline int kiRound_( double v, int line, const char* filename )
 //-----</KiROUND KIT>-----------------------------------------------------------
 
 
-
-/// Convert mm to mils.
-inline int Mm2mils( double x ) { return KiROUND( x * 1000./25.4 ); }
-
-/// Convert mils to mm.
-inline int Mils2mm( double x ) { return KiROUND( x * 25.4 / 1000. ); }
-
-
 enum EDA_UNITS_T {
     INCHES = 0,
     MILLIMETRES = 1,
@@ -235,31 +227,6 @@ int GetCommandOptions( const int argc, const char** argv,
                        int* optind );
 
 /**
- * Returns the units symbol.
- *
- * @param aUnits - Units type, default is current units setting.
- * @param aFormatString - A formatting string to embed the units symbol into.  Note:
- *                        the format string must contain the %s format specifier.
- * @return The formatted units symbol.
- */
-wxString ReturnUnitSymbol( EDA_UNITS_T aUnits = g_UserUnit,
-                           const wxString& aFormatString = _( " (%s):" ) );
-
-/**
- * Get a human readable units string.
- *
- * The strings returned are full text name and not abbreviations or symbolic
- * representations of the units.  Use ReturnUnitSymbol() for that.
- *
- * @param aUnits - The units text to return.
- * @return The human readable units string.
- */
-wxString GetUnitsLabel( EDA_UNITS_T aUnits );
-wxString GetAbbreviatedUnitsLabel( EDA_UNITS_T aUnit = g_UserUnit );
-
-void AddUnitSymbol( wxStaticText& Stext, EDA_UNITS_T aUnit = g_UserUnit );
-
-/**
  * Round to the nearest precision.
  *
  * Try to approximate a coordinate using a given precision to prevent
-- 
2.12.0

From e1dbcd27d12e27055e73c6bc82530923e9d14f32 Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Thu, 9 Feb 2017 18:21:00 +0800
Subject: [PATCH 08/13] Remove unused g_ShowPageLimits global variable

This variable was only defined, not declared in any header.
---
 common/common.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/common/common.cpp b/common/common.cpp
index f102be3c4..26e3a2a28 100644
--- a/common/common.cpp
+++ b/common/common.cpp
@@ -54,7 +54,6 @@ using KIGFX::COLOR4D;
  *       application class.
  */
 
-bool           g_ShowPageLimits = true;
 EDA_UNITS_T    g_UserUnit;
 COLOR4D        g_GhostColor;
 
-- 
2.12.0

From 41a8829a6dc03304ffd50dc1322f434c68efe8ec Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Thu, 9 Feb 2017 18:22:19 +0800
Subject: [PATCH 09/13] Remove unused GetCommandOptions function

---
 common/swig/kicad.i | 1 -
 include/common.h    | 4 ----
 2 files changed, 5 deletions(-)

diff --git a/common/swig/kicad.i b/common/swig/kicad.i
index 768b9b66e..f75ba2e22 100644
--- a/common/swig/kicad.i
+++ b/common/swig/kicad.i
@@ -67,7 +67,6 @@ principle should be easily implemented by adapting the current STL containers.
 // ignore other functions that cause trouble
 
 %ignore InitKiCadAbout;
-%ignore GetCommandOptions;
 
 %rename(getWxRect) operator wxRect;
 %ignore operator <<;
diff --git a/include/common.h b/include/common.h
index fe18127cb..ee65c2d40 100644
--- a/include/common.h
+++ b/include/common.h
@@ -222,10 +222,6 @@ int ProcessExecute( const wxString& aCommandLine, int aFlags = wxEXEC_ASYNC,
  */
 time_t GetNewTimeStamp();
 
-int GetCommandOptions( const int argc, const char** argv,
-                       const char* stringtst, const char** optarg,
-                       int* optind );
-
 /**
  * Round to the nearest precision.
  *
-- 
2.12.0

From edfe769bc17aa30d751fcd37928241d0fad80e2a Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Thu, 9 Feb 2017 18:28:48 +0800
Subject: [PATCH 10/13] Remove reference to InitKiCadAbout in kicad.i SWIG file

This function was removed in 2010, it no longer needs to be ignored.
---
 common/swig/kicad.i | 2 --
 1 file changed, 2 deletions(-)

diff --git a/common/swig/kicad.i b/common/swig/kicad.i
index f75ba2e22..f4453f6f2 100644
--- a/common/swig/kicad.i
+++ b/common/swig/kicad.i
@@ -66,8 +66,6 @@ principle should be easily implemented by adapting the current STL containers.
 
 // ignore other functions that cause trouble
 
-%ignore InitKiCadAbout;
-
 %rename(getWxRect) operator wxRect;
 %ignore operator <<;
 %ignore operator=;
-- 
2.12.0

From bed3a21e60bea20fa00b5c620e4f1f0a8e858af8 Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Thu, 9 Feb 2017 18:39:09 +0800
Subject: [PATCH 11/13] Move ProcessExecute to its own header

This function is only used in 4 places, it doesn't need to be in
common.h
---
 common/eda_doc.cpp                           |  1 +
 common/gestfich.cpp                          |  1 +
 eeschema/netform.cpp                         |  1 +
 include/common.h                             | 15 ---------
 include/process.h                            | 48 ++++++++++++++++++++++++++++
 pcbnew/dialogs/dialog_freeroute_exchange.cpp |  1 +
 6 files changed, 52 insertions(+), 15 deletions(-)
 create mode 100644 include/process.h

diff --git a/common/eda_doc.cpp b/common/eda_doc.cpp
index 851059233..5f2fd39b8 100644
--- a/common/eda_doc.cpp
+++ b/common/eda_doc.cpp
@@ -37,6 +37,7 @@
 #include <wx/tokenzr.h>
 #include <wx/filename.h>
 #include <macros.h>
+#include <process.h>
 
 
 void PGM_BASE::ReadPdfBrowserInfos()
diff --git a/common/gestfich.cpp b/common/gestfich.cpp
index 8c8b4852d..b604e5a6b 100644
--- a/common/gestfich.cpp
+++ b/common/gestfich.cpp
@@ -39,6 +39,7 @@
 #include <common.h>
 #include <macros.h>
 #include <directory_utils.h>
+#include <process.h>
 
 #include <gestfich.h>
 
diff --git a/eeschema/netform.cpp b/eeschema/netform.cpp
index 6b41c02e1..7f0f65900 100644
--- a/eeschema/netform.cpp
+++ b/eeschema/netform.cpp
@@ -34,6 +34,7 @@
 #include <pgm_base.h>
 #include <schframe.h>
 #include <reporter.h>
+#include <process.h>
 
 #include <netlist.h>
 #include <netlist_exporter.h>
diff --git a/include/common.h b/include/common.h
index ee65c2d40..2c790e300 100644
--- a/include/common.h
+++ b/include/common.h
@@ -198,21 +198,6 @@ wxSize GetTextSize( const wxString& aSingleLine, wxWindow* aWindow );
 bool EnsureTextCtrlWidth( wxTextCtrl* aCtrl, const wxString* aString = NULL );
 
 
-/**
- * Function ProcessExecute
- * runs a child process.
- * @param aCommandLine The process and any arguments to it all in a single
- *                     string.
- * @param aFlags The same args as allowed for wxExecute()
- * @param callback wxProcess implementing OnTerminate to be run when the
-                   child process finishes
- * @return int - pid of process, 0 in case of error (like return values of
- *               wxExecute())
- */
-int ProcessExecute( const wxString& aCommandLine, int aFlags = wxEXEC_ASYNC,
-                    wxProcess *callback = NULL );
-
-
 /**************/
 /* common.cpp */
 /**************/
diff --git a/include/process.h b/include/process.h
new file mode 100644
index 000000000..4389a5015
--- /dev/null
+++ b/include/process.h
@@ -0,0 +1,48 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+/**
+ * Process utilities
+ * @file process.h
+ */
+
+#ifndef INCLUDE__PROCESS_H_
+#define INCLUDE__PROCESS_H_
+
+#include <wx/string.h>
+
+/**
+ * Function ProcessExecute
+ * runs a child process.
+ * @param aCommandLine The process and any arguments to it all in a single
+ *                     string.
+ * @param aFlags The same args as allowed for wxExecute()
+ * @param callback wxProcess implementing OnTerminate to be run when the
+                   child process finishes
+ * @return int - pid of process, 0 in case of error (like return values of
+ *               wxExecute())
+ */
+int ProcessExecute( const wxString& aCommandLine, int aFlags = wxEXEC_ASYNC,
+                    wxProcess *callback = NULL );
+
+#endif  // INCLUDE__PROCESS_H_
diff --git a/pcbnew/dialogs/dialog_freeroute_exchange.cpp b/pcbnew/dialogs/dialog_freeroute_exchange.cpp
index bdfb2a816..b00d46809 100644
--- a/pcbnew/dialogs/dialog_freeroute_exchange.cpp
+++ b/pcbnew/dialogs/dialog_freeroute_exchange.cpp
@@ -34,6 +34,7 @@
 #include <wxPcbStruct.h>
 #include <macros.h>
 #include <class_board.h>
+#include <process.h>
 
 #include <../common/dialogs/dialog_display_info_HTML_base.h>
 
-- 
2.12.0

From 423f7d669db88524e049cefa26d5569c57e05660 Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Thu, 9 Feb 2017 18:47:07 +0800
Subject: [PATCH 12/13] Move NAMELESS_PROJECT to directory_utils.h

Only 5 files need this constant, so put it with the
directory/config utils.

Also make it a proper wxString rather than a #define
---
 common/directory_utils.cpp   | 1 +
 common/project.cpp           | 2 +-
 eeschema/schframe.cpp        | 1 +
 include/common.h             | 3 ---
 include/directory_utils.h    | 5 +++++
 kicad/kicad.cpp              | 3 ++-
 kicad/prjconfig.cpp          | 2 +-
 kicad/tree_project_frame.cpp | 1 +
 8 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/common/directory_utils.cpp b/common/directory_utils.cpp
index ca21a7877..794dc8b24 100644
--- a/common/directory_utils.cpp
+++ b/common/directory_utils.cpp
@@ -31,6 +31,7 @@
 #include <wx/stdpaths.h>
 #include <wx/utils.h>
 
+const wxString NAMELESS_PROJECT( "noname" );
 
 wxString GetKicadConfigPath()
 {
diff --git a/common/project.cpp b/common/project.cpp
index e55ed94b0..a78cc0d43 100644
--- a/common/project.cpp
+++ b/common/project.cpp
@@ -29,7 +29,7 @@
 #include <macros.h>
 #include <pgm_base.h>
 #include <project.h>
-#include <common.h>         // NAMELESS_PROJECT
+#include <directory_utils.h>         // NAMELESS_PROJECT
 #include <confirm.h>
 #include <kicad_string.h>
 #include <config_params.h>
diff --git a/eeschema/schframe.cpp b/eeschema/schframe.cpp
index 42687c20f..31da0256a 100644
--- a/eeschema/schframe.cpp
+++ b/eeschema/schframe.cpp
@@ -37,6 +37,7 @@
 #include <msgpanel.h>
 #include <html_messagebox.h>
 #include <executable_names.h>
+#include <directory_utils.h>
 
 #include <general.h>
 #include <eeschema_id.h>
diff --git a/include/common.h b/include/common.h
index 2c790e300..92fa0991d 100644
--- a/include/common.h
+++ b/include/common.h
@@ -63,9 +63,6 @@ typedef uint32_t EDA_KEY;
 #define GR_KEY_INVALID      ( EDA_KEY_C( 0x80000000 ) )
 #define GR_KEY_NONE         ( EDA_KEY_C( 0 ) )
 
-/// default name for nameless projects
-#define NAMELESS_PROJECT wxT( "noname" )
-
 
 /// Pseudo key codes for command panning
 enum pseudokeys {
diff --git a/include/directory_utils.h b/include/directory_utils.h
index 1db01f94f..62e0db88d 100644
--- a/include/directory_utils.h
+++ b/include/directory_utils.h
@@ -35,6 +35,11 @@
 class REPORTER;
 
 /**
+ * Default name for nameless projects
+ */
+extern const wxString NAMELESS_PROJECT;
+
+/**
  * Helper function EnsureFileDirectoryExists
  * make \a aTargetFullFileName absolute and creates the path of this file if it doesn't yet exist.
  * @param aTargetFullFileName  the wxFileName containing the full path and file name to modify.  The path
diff --git a/kicad/kicad.cpp b/kicad/kicad.cpp
index 90b950b98..a94543188 100644
--- a/kicad/kicad.cpp
+++ b/kicad/kicad.cpp
@@ -39,6 +39,7 @@
 #include <richio.h>
 #include <wildcards_and_files_ext.h>
 #include <systemdirsappend.h>
+#include <directory_utils.h>
 
 #include <stdexcept>
 
@@ -153,7 +154,7 @@ bool PGM_KICAD::OnPgmInit()
             prjloaded = true;    // OnFileHistory() loads the project
         }
     }
-    else	 // there is no history
+    else    // there is no history
     {
         wxFileName namelessProject( wxStandardPaths::Get().GetDocumentsDir(), NAMELESS_PROJECT,
                                     ProjectFileExtension );
diff --git a/kicad/prjconfig.cpp b/kicad/prjconfig.cpp
index 13fe7ad85..761949e81 100644
--- a/kicad/prjconfig.cpp
+++ b/kicad/prjconfig.cpp
@@ -294,7 +294,7 @@ void KICAD_MANAGER_FRAME::OnLoadProject( wxCommandEvent& event )
 
     wxString prj_filename = GetProjectFileName();
 
-    wxString nameless_prj = NAMELESS_PROJECT  wxT( ".pro" );
+    wxString nameless_prj = NAMELESS_PROJECT + ".pro";
 
     wxLogDebug( wxT( "%s: %s" ),
                 GetChars( wxFileName( prj_filename ).GetFullName() ),
diff --git a/kicad/tree_project_frame.cpp b/kicad/tree_project_frame.cpp
index ff147c84b..051c1a44e 100644
--- a/kicad/tree_project_frame.cpp
+++ b/kicad/tree_project_frame.cpp
@@ -39,6 +39,7 @@
 #include <gestfich.h>
 #include <menus_helpers.h>
 #include <wildcards_and_files_ext.h>
+#include <directory_utils.h>
 
 #include "class_treeproject_item.h"
 #include "class_treeprojectfiles.h"
-- 
2.12.0

From f9b31217212b198911ae0ffe0c27bc3c4857506b Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Thu, 9 Feb 2017 19:22:13 +0800
Subject: [PATCH 13/13] Use smart pointer for ownership of GetNewConfig

This was previously done by a raw pointer, which made ownership of the
object prone to failure. It is now done by smart pointer, so the object
cannot be accidentally leaked.

The object was in fact leaked in one of the cases, in the constructor
of PCB_CALCULATOR_FRAME.
---
 bitmap2component/bitmap2cmp_gui.cpp     | 4 +---
 common/bin_mod.cpp                      | 6 ++----
 common/directory_utils.cpp              | 7 ++++---
 common/hotkeys_basic.cpp                | 6 ++----
 common/pgm_base.cpp                     | 3 +--
 include/bin_mod.h                       | 4 +++-
 include/directory_utils.h               | 4 +++-
 include/kiface_i.h                      | 2 +-
 include/pgm_base.h                      | 6 ++++--
 kicad/pgm_kicad.h                       | 2 +-
 pcb_calculator/pcb_calculator_frame.cpp | 6 +++---
 11 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/bitmap2component/bitmap2cmp_gui.cpp b/bitmap2component/bitmap2cmp_gui.cpp
index 6cf7fd1fa..2c98e5afa 100644
--- a/bitmap2component/bitmap2cmp_gui.cpp
+++ b/bitmap2component/bitmap2cmp_gui.cpp
@@ -81,7 +81,7 @@ private:
     wxString        m_ConvertedFileName;
     wxSize          m_frameSize;
     wxPoint         m_framePos;
-    wxConfigBase*   m_config;
+    std::unique_ptr<wxConfigBase>   m_config;
 
 public:
     BM2CMP_FRAME( KIWAY* aKiway, wxWindow* aParent );
@@ -224,8 +224,6 @@ BM2CMP_FRAME::~BM2CMP_FRAME()
     m_config->Write( KEYWORD_LAST_FORMAT,  m_radioBoxFormat->GetSelection() );
     m_config->Write( KEYWORD_LAST_MODLAYER,  m_radio_PCBLayer->GetSelection() );
 
-    delete m_config;
-
     /* This needed for OSX: avoids further OnDraw processing after this
      * destructor and before the native window is destroyed
      */
diff --git a/common/bin_mod.cpp b/common/bin_mod.cpp
index 1025e670f..cd0d9750a 100644
--- a/common/bin_mod.cpp
+++ b/common/bin_mod.cpp
@@ -27,8 +27,7 @@
 #include <directory_utils.h>
 
 BIN_MOD::BIN_MOD( const char* aName ) :
-    m_name( aName ),
-    m_config( 0 )
+    m_name( aName )
 {
 }
 
@@ -58,8 +57,7 @@ void BIN_MOD::End()
 
         // Deleting a wxConfigBase writes its contents to disk if changed.
         // Might be NULL if called twice, in which case nothing happens.
-        delete m_config;
-        m_config = 0;
+        m_config = nullptr;
     }
 }
 
diff --git a/common/directory_utils.cpp b/common/directory_utils.cpp
index 794dc8b24..6d1bb8d9d 100644
--- a/common/directory_utils.cpp
+++ b/common/directory_utils.cpp
@@ -27,6 +27,7 @@
 
 #include <macros.h>
 #include <reporter.h>
+#include <common.h>
 
 #include <wx/stdpaths.h>
 #include <wx/utils.h>
@@ -69,14 +70,14 @@ wxString GetKicadConfigPath()
 }
 
 
-wxConfigBase* GetNewConfig( const wxString& aProgName )
+std::unique_ptr<wxConfigBase> GetNewConfig( const wxString& aProgName )
 {
-    wxConfigBase* cfg = 0;
     wxFileName configname;
     configname.AssignDir( GetKicadConfigPath() );
     configname.SetFullName( aProgName );
 
-    cfg = new wxFileConfig( wxT( "" ), wxT( "" ), configname.GetFullPath() );
+    auto cfg = std::make_unique<wxFileConfig>(
+                    "", "" , configname.GetFullPath() );
     return cfg;
 }
 
diff --git a/common/hotkeys_basic.cpp b/common/hotkeys_basic.cpp
index 1b7971f1e..34e43ca1f 100644
--- a/common/hotkeys_basic.cpp
+++ b/common/hotkeys_basic.cpp
@@ -590,9 +590,8 @@ int EDA_BASE_FRAME::WriteHotkeyConfig( struct EDA_HOTKEY_CONFIG* aDescList,
     {
         wxFileName fn( GetName() );
         fn.SetExt( DEFAULT_HOTKEY_FILENAME_EXT );
-        wxConfigBase* config = GetNewConfig( fn.GetFullPath() );
+        auto config = GetNewConfig( fn.GetFullPath() );
         config->Write( HOTKEYS_CONFIG_KEY, msg );
-        delete config;
     }
 
     return 1;
@@ -636,8 +635,7 @@ void ReadHotkeyConfig( const wxString& Appname, struct EDA_HOTKEY_CONFIG* aDescL
     wxFileName fn( Appname );
     fn.SetExt( DEFAULT_HOTKEY_FILENAME_EXT );
 
-    std::unique_ptr<wxConfigBase> config;
-    config.reset( GetNewConfig( fn.GetFullPath() ) );
+    auto config = GetNewConfig( fn.GetFullPath() );
 
     if( !config->HasEntry( HOTKEYS_CONFIG_KEY ) )
     {
diff --git a/common/pgm_base.cpp b/common/pgm_base.cpp
index 5568e6b43..323ad1bbc 100644
--- a/common/pgm_base.cpp
+++ b/common/pgm_base.cpp
@@ -308,8 +308,7 @@ void PGM_BASE::Destroy()
 {
     // unlike a normal destructor, this is designed to be called more than once safely:
 
-    delete m_common_settings;
-    m_common_settings = 0;
+    m_common_settings = nullptr;
 
     delete m_pgm_checker;
     m_pgm_checker = 0;
diff --git a/include/bin_mod.h b/include/bin_mod.h
index cbf360dbe..d762a7442 100644
--- a/include/bin_mod.h
+++ b/include/bin_mod.h
@@ -34,6 +34,8 @@
 
 #include <search_stack.h>
 
+#include <memory>
+
 class wxConfigBase;
 
 /**
@@ -54,7 +56,7 @@ struct BIN_MOD
 
     const char*         m_name;             ///< name of this binary module, static C string.
 
-    wxConfigBase*       m_config;           ///< maybe from $HOME/.${m_name}
+    std::unique_ptr<wxConfigBase>   m_config;   ///< maybe from $HOME/.${m_name}
     wxFileHistory       m_history;
     wxString            m_help_file;
 
diff --git a/include/directory_utils.h b/include/directory_utils.h
index 62e0db88d..482959971 100644
--- a/include/directory_utils.h
+++ b/include/directory_utils.h
@@ -32,6 +32,8 @@
 #include <wx/filename.h>
 #include <wx/config.h>
 
+#include <memory>
+
 class REPORTER;
 
 /**
@@ -72,7 +74,7 @@ wxString GetKicadConfigPath();
  * @return A pointer to a new wxConfigBase derived object is returned.  The caller is in charge
  *  of deleting it.
  */
-wxConfigBase* GetNewConfig( const wxString& aProgName );
+std::unique_ptr<wxConfigBase> GetNewConfig( const wxString& aProgName );
 
 
 #ifdef __WXMAC__
diff --git a/include/kiface_i.h b/include/kiface_i.h
index 6a4134f7a..12ffb50d6 100644
--- a/include/kiface_i.h
+++ b/include/kiface_i.h
@@ -98,7 +98,7 @@ public:
 
     const wxString Name()                               { return wxString::FromUTF8( m_bm.m_name ); }
 
-    wxConfigBase* KifaceSettings() const                { return m_bm.m_config; }
+    wxConfigBase* KifaceSettings() const                { return m_bm.m_config.get(); }
 
     /**
      * Function StartFlags
diff --git a/include/pgm_base.h b/include/pgm_base.h
index 0fa00f7be..872b57019 100644
--- a/include/pgm_base.h
+++ b/include/pgm_base.h
@@ -32,6 +32,8 @@
 #define  PGM_BASE_H_
 
 #include <map>
+#include <memory>
+
 #include <wx/filename.h>
 #include <search_stack.h>
 #include <wx/gdicmn.h>
@@ -142,7 +144,7 @@ public:
      */
     VTBL_ENTRY void MacOpenFile( const wxString& aFileName ) = 0;
 
-    VTBL_ENTRY wxConfigBase* CommonSettings() const                 { return m_common_settings; }
+    VTBL_ENTRY wxConfigBase* CommonSettings() const                 { return m_common_settings.get(); }
 
     VTBL_ENTRY void SetEditorName( const wxString& aFileName );
 
@@ -341,7 +343,7 @@ protected:
 
     /// Configuration settings common to all KiCad program modules,
     /// like as in $HOME/.kicad_common
-    wxConfigBase*   m_common_settings;
+    std::unique_ptr<wxConfigBase> m_common_settings;
 
     /// full path to this program
     wxString        m_bin_dir;
diff --git a/kicad/pgm_kicad.h b/kicad/pgm_kicad.h
index 2ebed9172..f6986fb8b 100644
--- a/kicad/pgm_kicad.h
+++ b/kicad/pgm_kicad.h
@@ -56,7 +56,7 @@ public:
 
     wxFileHistory&  GetFileHistory()            { return m_bm.m_history; }
 
-    wxConfigBase*   PgmSettings()               { return m_bm.m_config; }
+    wxConfigBase*   PgmSettings()               { return m_bm.m_config.get(); }
 
     SEARCH_STACK&   SysSearch()                 { return m_bm.m_search; }
 
diff --git a/pcb_calculator/pcb_calculator_frame.cpp b/pcb_calculator/pcb_calculator_frame.cpp
index badb6e78b..1c3a039a1 100644
--- a/pcb_calculator/pcb_calculator_frame.cpp
+++ b/pcb_calculator/pcb_calculator_frame.cpp
@@ -84,15 +84,15 @@ PCB_CALCULATOR_FRAME::PCB_CALCULATOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
     m_attenuator_list.push_back( new ATTENUATOR_SPLITTER() );
     m_currAttenuator = m_attenuator_list[0];
 
-    wxConfigBase* config = GetNewConfig( Pgm().App().GetAppName() );
-    LoadSettings( config );
+    auto config = GetNewConfig( Pgm().App().GetAppName() );
+    LoadSettings( config.get() );
 
     ReadDataFile();
 
     TranslineTypeSelection( m_currTransLineType );
     m_TranslineSelection->SetSelection( m_currTransLineType );
 
-    TW_Init( config );
+    TW_Init( config.get() );
 
     SetAttenuator( m_AttenuatorsSelection->GetSelection() );
 
-- 
2.12.0


Follow ups

References