← Back to team overview

kicad-developers team mailing list archive

Re: [PATCH] common.h tidyups

 

Hi Wayne,

Like this?

As for the patches that don't apply out of order, in this case it is
due to removing the following line in the previous commit. If you want
to cherry-pick that patch, doing it by git rather than raw patches
would be much easier. Git would be able to flag the conflict up and it
should be a simple one to resolve.

In this case, the conflict caused by cherry-picking "Remove reference
to InitKiCadAbout in kicad.i SWIG file" without the preceding commit
would be:

<<<<<<< HEAD
%ignore InitKiCadAbout;
%ignore GetCommandOptions;

=======
>>>>>>> adce35d99... Remove reference to InitKiCadAbout in kicad.i SWIG file

After resolution, it would be just:

%ignore GetCommandOptions;

Cheers,

John

On Fri, Mar 24, 2017 at 11:04 PM, Wayne Stambaugh <stambaughw@xxxxxxxxx> wrote:
> On 3/24/2017 9:50 AM, John Beard wrote:
>> Hi Wayne,
>>
>> The InitKicadAbout function was removed in 2010 by commit
>> b45a35b719739e1ed1a723a4e7412d63020e5f2c. Is it still useful in the
>> swig file?
>
> It should be removed but unfortunately this patch now no longer applies
> cleanly.
>
>>
>> As for the directory_utils compile failure, perhaps there's a
>> difference in WX on Windows?
>> Does #include <wx/config.h> at the top of common/directory_utils.cpp fix it?
>
> You need to add #include <wx/fileconf.h>.  On windows <wx/confbase.h>
> defaults to the wxRegConfig and wxFileConfig is not exposed.
>
>>
>> Cheers,
>>
>> John
>>
>>
>>
>> On Fri, Mar 24, 2017 at 2:21 AM, Wayne Stambaugh <stambaughw@xxxxxxxxx> wrote:
>>> John,
>>>
>>> I committed up to patch 9.  Patch 6 did not apply cleanly.  Apparently
>>> it needs the broken patch 5 so it will need to be rebased once you fix
>>> patch 5.
>>>
>>> I have a question about patch 10.  Did you test InitAboutKicad from the
>>> python scripting.  It was originally ignored because there were issues
>>> so I just want to be sure before I commit this patch.
>>>
>>> Thanks,
>>>
>>> Wayne
>>>
>>> On 3/23/2017 9:25 AM, Wayne Stambaugh wrote:
>>>> So far, I've tested patches 1-4 and they seem fine.  Patch 5 fails to
>>>> compile on windows with the following compiler output:
>>>>
>>>> C:/msys64/home/wstambaugh/src/kicad-trunk/common/directory_utils.cpp: In
>>>> function 'wxConfigBase* GetNewConfig(const wxString&)':
>>>> C:/msys64/home/wstambaugh/src/kicad-trunk/common/directory_utils.cpp:78:15:
>>>> error: expected type-specifier before 'wxFileConfig'
>>>>      cfg = new wxFileConfig( wxT( "" ), wxT( "" ),
>>>> configname.GetFullPath() );
>>>>
>>>> I'll commit what I've tested thus far and continue testing the remaining
>>>> patches as time permits.
>>>>
>>>> On 3/23/2017 9:17 AM, Maciej Sumiński wrote:
>>>>> Hi John,
>>>>>
>>>>> Thank you for the patches. I have committed:
>>>>>   0001 OPENGL_GAL: Init currentTarget
>>>>>   0003 Rework zone creation in GAL (committed yesterday)
>>>>>
>>>>> I had a look at other changes, and they appear to be a sensible common.h
>>>>> clean-up. All patches received the Orson Approves™ badge, but I leave
>>>>> the final decision to Wayne.
>>>>>
>>>>> Regards,
>>>>> Orson
>>>>>
>>>>> On 03/22/2017 03:12 PM, John Beard wrote:
>>>>>> 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
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> 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
>>>>>
>>>
>>> _______________________________________________
>>> 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 6c4d506ae968391c6702b9a84ebf32e19087e2ec 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 1/7] 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 ad1cd5dee..ade430176 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -234,6 +234,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
@@ -242,6 +243,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 b101fa26c..26e3a2a28 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;
 
@@ -200,166 +201,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..af3fb2319
--- /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>
+#include <wx/fileconf.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 504496024..c3175e4d7 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 4fe4a6546..52d8c90f1 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 d0337d562..fe18127cb 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.
@@ -251,94 +245,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 b17a68ac1..e841c82a3 100644
--- a/pcbnew/pcbnew.cpp
+++ b/pcbnew/pcbnew.cpp
@@ -44,6 +44,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


Follow ups

References