///////////////////////////////////////////////////////////////////////////////
-// Name: msw/stdpaths.cpp
+// Name: src/msw/stdpaths.cpp
// Purpose: wxStandardPaths implementation for Win32
// Author: Vadim Zeitlin
// Modified by:
// Created: 2004-10-19
// RCS-ID: $Id$
// Copyright: (c) 2004 Vadim Zeitlin <vadim@wxwindows.org>
-// License: wxWindows license
+// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
#pragma hdrstop
#endif
+#if wxUSE_STDPATHS
+
+#include "wx/stdpaths.h"
+
#ifndef WX_PRECOMP
- #include "wx/app.h"
+ #include "wx/utils.h"
#endif //WX_PRECOMP
#include "wx/dynlib.h"
#include "wx/filename.h"
-#include "wx/stdpaths.h"
-
#include "wx/msw/private.h"
#include "wx/msw/wrapshl.h"
// ----------------------------------------------------------------------------
// used in our wxLogTrace messages
-static const wxChar *TRACE_MASK = _T("stdpaths");
+#define TRACE_MASK wxT("stdpaths")
+
+#ifndef CSIDL_APPDATA
+ #define CSIDL_APPDATA 0x001a
+#endif
#ifndef CSIDL_LOCAL_APPDATA
#define CSIDL_LOCAL_APPDATA 0x001c
#define CSIDL_PROGRAM_FILES 0x0026
#endif
+#ifndef CSIDL_PERSONAL
+ #define CSIDL_PERSONAL 0x0005
+#endif
+
+#ifndef SHGFP_TYPE_CURRENT
+ #define SHGFP_TYPE_CURRENT 0
+#endif
+
+#ifndef SHGFP_TYPE_DEFAULT
+ #define SHGFP_TYPE_DEFAULT 1
+#endif
+
// ----------------------------------------------------------------------------
// module globals
// ----------------------------------------------------------------------------
+namespace
+{
+
struct ShellFunctions
{
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()
{
- // don't give errors if the functions are unavailable, we're ready to deal
- // with this
- wxLogNull noLog;
+#if wxUSE_DYNLIB_CLASS
// start with the newest functions, fall back to the oldest ones
-
+#ifdef __WXWINCE__
+ wxString shellDllName(wxT("coredll"));
+#else
// first check for SHGetFolderPath (shell32.dll 5.0)
- wxDynamicLibrary dllShell32(_T("shell32"));
- if ( !dllShell32.IsLoaded() )
+ wxString shellDllName(wxT("shell32"));
+#endif
+
+ wxDynamicLibrary dllShellFunctions( shellDllName );
+ if ( !dllShellFunctions.IsLoaded() )
{
- wxLogTrace(TRACE_MASK, _T("Failed to load shell32.dll"));
+ wxLogTrace(TRACE_MASK, wxT("Failed to load %s.dll"), shellDllName.c_str() );
}
+ // don't give errors if the functions are unavailable, we're ready to deal
+ // with this
+ wxLogNull noLog;
+
#if wxUSE_UNICODE
- static const wchar_t UNICODE_SUFFIX = L'W';
+ #ifdef __WXWINCE__
+ static const wchar_t UNICODE_SUFFIX = L''; // WinCE SH functions don't seem to have 'W'
+ #else
+ static const wchar_t UNICODE_SUFFIX = L'W';
+ #endif
#else // !Unicode
static const char UNICODE_SUFFIX = 'A';
#endif // Unicode/!Unicode
- wxString funcname(_T("SHGetFolderPath"));
+ wxString funcname(wxT("SHGetFolderPath"));
gs_shellFuncs.pSHGetFolderPath =
- (SHGetFolderPath_t)dllShell32.GetSymbol(funcname + UNICODE_SUFFIX);
+ (SHGetFolderPath_t)dllShellFunctions.GetSymbol(funcname + UNICODE_SUFFIX);
// then for SHGetSpecialFolderPath (shell32.dll 4.71)
if ( !gs_shellFuncs.pSHGetFolderPath )
{
- funcname = _T("SHGetSpecialFolderPath");
+ funcname = wxT("SHGetSpecialFolderPath");
gs_shellFuncs.pSHGetSpecialFolderPath = (SHGetSpecialFolderPath_t)
- dllShell32.GetSymbol(funcname + UNICODE_SUFFIX);
+ dllShellFunctions.GetSymbol(funcname + UNICODE_SUFFIX);
}
// finally we fall back on SHGetSpecialFolderLocation (shell32.dll 4.0),
// because we also link to it statically, so it's ok
gs_shellFuncs.initialized = true;
+#endif
}
+} // anonymous namespace
+
// ============================================================================
// wxStandardPaths implementation
// ============================================================================
return dir;
}
-/* static */
-wxString wxStandardPaths::AppendAppName(const wxString& dir)
+wxString wxStandardPaths::GetAppDir() const
+{
+ if ( m_appDir.empty() )
+ {
+ m_appDir = wxFileName(wxGetFullModuleName()).GetPath();
+ }
+
+ return m_appDir;
+}
+
+wxString wxStandardPaths::GetDocumentsDir() const
{
- wxString subdir(dir);
+ return DoGetDirectory(CSIDL_PERSONAL);
+}
- // empty string indicates that an error has occured, don't touch it then
- if ( !subdir.empty() )
+// ----------------------------------------------------------------------------
+// MSW-specific functions
+// ----------------------------------------------------------------------------
+
+void wxStandardPaths::IgnoreAppSubDir(const wxString& subdirPattern)
+{
+ wxFileName fn = wxFileName::DirName(GetAppDir());
+
+ if ( !fn.GetDirCount() )
{
- const wxString appname = wxTheApp->GetAppName();
- if ( !appname.empty() )
- subdir << _T('\\') << appname;
+ // no last directory to ignore anyhow
+ return;
}
- return subdir;
+ 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();
+}
+
+/* static */
+wxString wxStandardPaths::MSWGetShellDir(int csidl)
+{
+ return DoGetDirectory(csidl);
}
// ----------------------------------------------------------------------------
// public functions
// ----------------------------------------------------------------------------
+wxStandardPaths::wxStandardPaths()
+{
+ // make it possible to run uninstalled application from the build directory
+ IgnoreAppBuildSubDirs();
+}
+
+wxString wxStandardPaths::GetExecutablePath() const
+{
+ return wxGetFullModuleName();
+}
+
wxString wxStandardPaths::GetConfigDir() const
{
- return AppendAppName(DoGetDirectory(CSIDL_COMMON_APPDATA));
+ return AppendAppInfo(DoGetDirectory(CSIDL_COMMON_APPDATA));
}
wxString wxStandardPaths::GetUserConfigDir() const
wxString wxStandardPaths::GetDataDir() const
{
- return AppendAppName(DoGetDirectory(CSIDL_PROGRAM_FILES));
+ // under Windows each program is usually installed in its own directory and
+ // so its datafiles are in the same directory as its main executable
+ return GetAppDir();
}
wxString wxStandardPaths::GetUserDataDir() const
{
- return AppendAppName(GetUserConfigDir());
+ return AppendAppInfo(GetUserConfigDir());
}
wxString wxStandardPaths::GetUserLocalDataDir() const
{
- return AppendAppName(DoGetDirectory(CSIDL_LOCAL_APPDATA));
+ return AppendAppInfo(DoGetDirectory(CSIDL_LOCAL_APPDATA));
}
wxString wxStandardPaths::GetPluginsDir() const
{
- return wxFileName(wxGetFullModuleName()).GetPath();
+ // there is no standard location for plugins, suppose they're in the same
+ // directory as the .exe
+ return GetAppDir();
}
-
// ============================================================================
// wxStandardPathsWin16 implementation
// ============================================================================
// this is for compatibility with earlier wxFileConfig versions
// which used the Windows directory for the global files
wxString dir;
+#ifndef __WXWINCE__
if ( !::GetWindowsDirectory(wxStringBuffer(dir, MAX_PATH), MAX_PATH) )
{
- wxLogLastError(_T("GetWindowsDirectory"));
+ wxLogLastError(wxT("GetWindowsDirectory"));
}
+#else
+ // TODO: use CSIDL_WINDOWS (eVC4, possibly not eVC3)
+ dir = wxT("\\Windows");
+#endif
return dir;
}
return wxGetHomeDir();
}
+#endif // wxUSE_STDPATHS