From 4cd15b49b45eefa12d64802d6c4052ba04b1fbcb Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 11 Jun 2009 16:46:19 +0000 Subject: [PATCH] allow customizing wxStandardPaths logic for the program directory determination git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@61003 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + include/wx/msw/stdpaths.h | 43 +++++++++++++++--- interface/wx/stdpaths.h | 60 +++++++++++++++++++++++++ src/msw/stdpaths.cpp | 92 ++++++++++++++++++++++++++++++++------- 4 files changed, 173 insertions(+), 23 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 5cbf0265b1..305e4254ad 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -356,6 +356,7 @@ MSW: - Update CRT environment block in wxSetEnv() too. - Fix wxMDIChildFrame::SetSize() (Lars Rosenboom). - Fix wxTreeCtrl::UnselectItem() in single selection controls. +- Allow customizing wxStandardPaths logic for program directory determination. i18n: diff --git a/include/wx/msw/stdpaths.h b/include/wx/msw/stdpaths.h index cb141af92c..e6668daa14 100644 --- a/include/wx/msw/stdpaths.h +++ b/include/wx/msw/stdpaths.h @@ -19,12 +19,9 @@ class WXDLLIMPEXP_BASE wxStandardPaths : public wxStandardPathsBase { public: - wxStandardPaths() - { - UseAppInfo(AppInfo_AppName | AppInfo_VendorName); - } - - ~wxStandardPaths() { } + // ctor calls IgnoreAppBuildSubDirs() and also sets up the object to use + // both vendor and application name by default + wxStandardPaths(); // implement base class pure virtuals virtual wxString GetExecutablePath() const; @@ -36,12 +33,44 @@ public: virtual wxString GetPluginsDir() const; virtual wxString GetDocumentsDir() const; + + // MSW-specific methods + + // This class supposes that data, plugins &c files are located under the + // program directory which is the directory containing the application + // binary itself. But sometimes this binary may be in a subdirectory of the + // main program directory, e.g. this happens in at least the following + // common cases: + // 1. The program is in "bin" subdirectory of the installation directory. + // 2. The program is in "debug" subdirectory of the directory containing + // sources and data files during development + // + // By calling this function you instruct the class to remove the last + // component of the path if it matches its argument. Notice that it may be + // called more than once, e.g. you can call both IgnoreAppSubDir("bin") and + // IgnoreAppSubDir("debug") to take care of both production and development + // cases above but that each call will only remove the last path component. + // Finally note that the argument can contain wild cards so you can also + // call IgnoreAppSubDir("vc*msw*") to ignore all build directories at once + // when using wxWidgets-inspired output directories names. + void IgnoreAppSubDir(const wxString& subdirPattern); + + // This function is used to ignore all common build directories and is + // called from the ctor -- use DontIgnoreAppSubDir() to undo this. + void IgnoreAppBuildSubDirs(); + + // Undo the effects of all preceding IgnoreAppSubDir() calls. + void DontIgnoreAppSubDir(); + protected: // get the path corresponding to the given standard CSIDL_XXX constant static wxString DoGetDirectory(int csidl); // return the directory of the application itself - static wxString GetAppDir(); + wxString GetAppDir() const; + + // directory returned by GetAppDir() + mutable wxString m_appDir; }; // ---------------------------------------------------------------------------- diff --git a/interface/wx/stdpaths.h b/interface/wx/stdpaths.h index d082af4b97..fa4d965c4f 100644 --- a/interface/wx/stdpaths.h +++ b/interface/wx/stdpaths.h @@ -48,6 +48,19 @@ class wxStandardPaths { public: + /** + MSW-specific function undoing the effect of IgnoreAppSubDir() calls. + + After a call to this function the program directory will be exactly the + directory containing the main application binary, i.e. it undoes the + effect of any previous IgnoreAppSubDir() calls including the ones done + indirectly by IgnoreAppBuildSubDirs() called from the class + constructor. + + @since 2.9.1 + */ + void DontIgnoreAppSubDir(); + /** Returns reference to the unique global standard paths object. */ @@ -215,6 +228,53 @@ public: */ virtual wxString GetUserLocalDataDir() const; + /** + MSW-specific function to customize application directory detection. + + This class supposes that data, plugins &c files are located under the + program directory which is the directory containing the application + binary itself. But sometimes this binary may be in a subdirectory of + the main program directory, e.g. this happens in at least the following + common cases: + - The program is in "bin" subdirectory of the installation directory. + - The program is in "debug" subdirectory of the directory containing + sources and data files during development + + By calling this function you instruct the class to remove the last + component of the path if it matches its argument. Notice that it may be + called more than once, e.g. you can call both IgnoreAppSubDir("bin") and + IgnoreAppSubDir("debug") to take care of both production and development + cases above but that each call will only remove the last path component. + Finally note that the argument can contain wild cards so you can also + call IgnoreAppSubDir("vc*msw*") to ignore all build directories at once + when using wxWidgets-inspired output directories names. + + @since 2.9.1 + + @see IgnoreAppBuildSubDirs() + + @param subdirPattern + The subdirectory containing the application binary which should be + ignored when determining the top application directory. The pattern + is case-insensitive and may contain wild card characters @c '?' and + @c '*'. + */ + void IgnoreAppSubDir(const wxString& subdirPattern); + + /** + MSW-specific function to ignore all common build directories. + + This function calls IgnoreAppSubDir() with all common values for build + directory, e.g. @c "debug" and @c "release". + + It is called by the class constructor and so the build directories are + always ignored by default. You may use DontIgnoreAppSubDir() to avoid + ignoring them if this is inappropriate for your application. + + @since 2.9.1 + */ + void IgnoreAppBuildSubDirs(); + /** Lets wxStandardPaths know about the real program installation prefix on a Unix system. By default, the value returned by GetInstallPrefix() is used. diff --git a/src/msw/stdpaths.cpp b/src/msw/stdpaths.cpp index e8340f1a26..4f2cfd65c5 100644 --- a/src/msw/stdpaths.cpp +++ b/src/msw/stdpaths.cpp @@ -79,10 +79,14 @@ typedef HRESULT (WINAPI *SHGetSpecialFolderPath_t)(HWND, LPTSTR, int, BOOL); #ifndef SHGFP_TYPE_DEFAULT #define SHGFP_TYPE_DEFAULT 1 #endif + // ---------------------------------------------------------------------------- // module globals // ---------------------------------------------------------------------------- +namespace +{ + struct ShellFunctions { ShellFunctions() @@ -101,13 +105,13 @@ struct ShellFunctions // in spite of using a static variable, this is MT-safe as in the worst case it // results in initializing the function pointer several times -- but this is // harmless -static ShellFunctions gs_shellFuncs; +ShellFunctions gs_shellFuncs; // ---------------------------------------------------------------------------- // private functions // ---------------------------------------------------------------------------- -static void ResolveShellFunctions() +void ResolveShellFunctions() { #if wxUSE_DYNLIB_CLASS @@ -161,6 +165,8 @@ static void ResolveShellFunctions() #endif } +} // anonymous namespace + // ============================================================================ // wxStandardPaths implementation // ============================================================================ @@ -245,24 +251,14 @@ wxString wxStandardPaths::DoGetDirectory(int csidl) return dir; } -/* static */ -wxString wxStandardPaths::GetAppDir() +wxString wxStandardPaths::GetAppDir() const { - wxFileName fn(wxGetFullModuleName()); - - // allow running the apps directly from build directory in MSVC debug builds -#ifdef _DEBUG - wxString lastdir; - if ( fn.GetDirCount() ) + if ( m_appDir.empty() ) { - lastdir = fn.GetDirs().Last(); - lastdir.MakeLower(); - if ( lastdir.Matches(_T("debug*")) || lastdir.Matches(_T("vc*msw*")) ) - fn.RemoveLastDir(); + m_appDir = wxFileName(wxGetFullModuleName()).GetPath(); } -#endif // _DEBUG - return fn.GetPath(); + return m_appDir; } wxString wxStandardPaths::GetDocumentsDir() const @@ -270,10 +266,74 @@ wxString wxStandardPaths::GetDocumentsDir() const return DoGetDirectory(CSIDL_PERSONAL); } +// ---------------------------------------------------------------------------- +// MSW-specific functions +// ---------------------------------------------------------------------------- + +void wxStandardPaths::IgnoreAppSubDir(const wxString& subdirPattern) +{ + wxFileName fn = wxFileName::DirName(GetAppDir()); + + if ( !fn.GetDirCount() ) + { + // no last directory to ignore anyhow + return; + } + + const wxString lastdir = fn.GetDirs().Last().Lower(); + if ( lastdir.Matches(subdirPattern.Lower()) ) + { + fn.RemoveLastDir(); + + // store the cached value so that subsequent calls to GetAppDir() will + // reuse it instead of using just the program binary directory + m_appDir = fn.GetPath(); + } +} + +void wxStandardPaths::IgnoreAppBuildSubDirs() +{ + IgnoreAppSubDir("debug"); + IgnoreAppSubDir("release"); + + wxString compilerPrefix; +#ifdef __VISUALC__ + compilerPrefix = "vc"; +#elif defined(__GNUG__) + compilerPrefix = "gcc"; +#elif defined(__BORLANDC__) + compilerPrefix = "bcc"; +#elif defined(__DIGITALMARS__) + compilerPrefix = "dmc"; +#elif defined(__WATCOMC__) + compilerPrefix = "wat"; +#else + return; +#endif + + IgnoreAppSubDir(compilerPrefix + "_msw*"); +} + +void wxStandardPaths::DontIgnoreAppSubDir() +{ + // this will force the next call to GetAppDir() to use the program binary + // path as the application directory + m_appDir.clear(); +} + // ---------------------------------------------------------------------------- // public functions // ---------------------------------------------------------------------------- +wxStandardPaths::wxStandardPaths() +{ + // under MSW it's common to use both the applicatio nand vendor + UseAppInfo(AppInfo_AppName | AppInfo_VendorName); + + // make it possible to run uninstalled application from the build directory + IgnoreAppBuildSubDirs(); +} + wxString wxStandardPaths::GetExecutablePath() const { return wxGetFullModuleName(); -- 2.45.2