]> git.saurik.com Git - wxWidgets.git/commitdiff
initial implementation for MSW
authorVadim Zeitlin <vadim@wxwidgets.org>
Tue, 19 Oct 2004 18:50:06 +0000 (18:50 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Tue, 19 Oct 2004 18:50:06 +0000 (18:50 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@30005 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/msw/stdpaths.h [new file with mode: 0644]
src/msw/stdpaths.cpp [new file with mode: 0644]

diff --git a/include/wx/msw/stdpaths.h b/include/wx/msw/stdpaths.h
new file mode 100644 (file)
index 0000000..c1e9bb3
--- /dev/null
@@ -0,0 +1,51 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        wx/msw/stdpaths.h
+// Purpose:     wxStandardPaths for Win32
+// Author:      Vadim Zeitlin
+// Modified by:
+// Created:     2004-10-19
+// RCS-ID:      $Id$
+// Copyright:   (c) 2004 Vadim Zeitlin <vadim@wxwindows.org>
+// Licence:     wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_MSW_STDPATHS_H_
+#define _WX_MSW_STDPATHS_H_
+
+// ----------------------------------------------------------------------------
+// wxStandardPaths
+// ----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_BASE wxStandardPaths : public wxStandardPathsBase
+{
+public:
+    // implement base class pure virtuals
+    virtual wxString GetConfigDir() const;
+    virtual wxString GetUserConfigDir() const;
+    virtual wxString GetDataDir() const;
+    virtual wxString GetUserDataDir() const;
+    virtual wxString GetUserLocalDataDir() const;
+    virtual wxString GetPluginsDir() const;
+
+protected:
+    // append "/appname" suffix if the app name is set
+    static wxString AppendAppName(const wxString& dir);
+
+    // get the path corresponding to the given standard CSIDL_XXX constant
+    static wxString DoGetDirectory(int csidl);
+};
+
+// ----------------------------------------------------------------------------
+// wxStandardPathsWin16: this class is for internal use only
+// ----------------------------------------------------------------------------
+
+// override config file locations to be compatible with the values used by
+// wxFileConfig (dating from Win16 days which explains the class name)
+class WXDLLIMPEXP_BASE wxStandardPathsWin16 : public wxStandardPaths
+{
+public:
+    virtual wxString GetConfigDir() const;
+    virtual wxString GetUserConfigDir() const;
+};
+
+#endif // _WX_MSW_STDPATHS_H_
diff --git a/src/msw/stdpaths.cpp b/src/msw/stdpaths.cpp
new file mode 100644 (file)
index 0000000..dcce507
--- /dev/null
@@ -0,0 +1,292 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        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
+///////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// for compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+    #include "wx/app.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"
+
+// ----------------------------------------------------------------------------
+// types
+// ----------------------------------------------------------------------------
+
+typedef HRESULT (WINAPI *SHGetFolderPath_t)(HWND, int, HANDLE, DWORD, LPTSTR);
+typedef HRESULT (WINAPI *SHGetSpecialFolderPath_t)(HWND, LPTSTR, int, BOOL);
+
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
+
+// used in our wxLogTrace messages
+static const wxChar *TRACE_MASK = _T("stdpaths");
+
+#ifndef CSIDL_LOCAL_APPDATA
+    #define CSIDL_LOCAL_APPDATA   0x001c
+#endif
+
+#ifndef CSIDL_COMMON_APPDATA
+    #define CSIDL_COMMON_APPDATA  0x0023
+#endif
+
+#ifndef CSIDL_PROGRAM_FILES
+    #define CSIDL_PROGRAM_FILES   0x0026
+#endif
+
+// ----------------------------------------------------------------------------
+// module globals
+// ----------------------------------------------------------------------------
+
+struct ShellFunctions
+{
+    ShellFunctions()
+    {
+        pSHGetFolderPath = NULL;
+        pSHGetSpecialFolderPath = NULL;
+        initialized = false;
+    }
+
+    SHGetFolderPath_t pSHGetFolderPath;
+    SHGetSpecialFolderPath_t pSHGetSpecialFolderPath;
+
+    bool initialized;
+};
+
+// 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;
+
+// ----------------------------------------------------------------------------
+// private functions
+// ----------------------------------------------------------------------------
+
+static void ResolveShellFunctions()
+{
+    // don't give errors if the functions are unavailable, we're ready to deal
+    // with this
+    wxLogNull noLog;
+
+    // start with the newest functions, fall back to the oldest ones
+
+    // first check for SHGetFolderPath (shell32.dll 5.0)
+    wxDynamicLibrary dllShell32(_T("shell32"));
+    if ( !dllShell32.IsLoaded() )
+    {
+        wxLogTrace(TRACE_MASK, _T("Failed to load shell32.dll"));
+    }
+
+#if wxUSE_UNICODE
+    static const wchar_t UNICODE_SUFFIX = L'W';
+#else // !Unicode
+    static const char UNICODE_SUFFIX = 'A';
+#endif // Unicode/!Unicode
+
+    wxString funcname(_T("SHGetFolderPath"));
+    gs_shellFuncs.pSHGetFolderPath =
+        (SHGetFolderPath_t)dllShell32.GetSymbol(funcname + UNICODE_SUFFIX);
+
+    // then for SHGetSpecialFolderPath (shell32.dll 4.71)
+    if ( !gs_shellFuncs.pSHGetFolderPath )
+    {
+        funcname = _T("SHGetSpecialFolderPath");
+        gs_shellFuncs.pSHGetSpecialFolderPath = (SHGetSpecialFolderPath_t)
+            dllShell32.GetSymbol(funcname + UNICODE_SUFFIX);
+    }
+
+    // finally we fall back on SHGetSpecialFolderLocation (shell32.dll 4.0),
+    // but we don't need to test for it -- it is available even under Win95
+
+    // shell32.dll is going to be unloaded, but it still remains in memory
+    // because we also link to it statically, so it's ok
+
+    gs_shellFuncs.initialized = true;
+}
+
+// ============================================================================
+// wxStandardPaths implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// private helpers
+// ----------------------------------------------------------------------------
+
+/* static */
+wxString wxStandardPaths::DoGetDirectory(int csidl)
+{
+    if ( !gs_shellFuncs.initialized )
+        ResolveShellFunctions();
+
+    wxString dir;
+    HRESULT hr = E_FAIL;
+
+    // test whether the function is available during compile-time (it must be
+    // defined as either "SHGetFolderPathA" or "SHGetFolderPathW")
+#ifdef SHGetFolderPath
+    // and now test whether we have it during run-time
+    if ( gs_shellFuncs.pSHGetFolderPath )
+    {
+        hr = gs_shellFuncs.pSHGetFolderPath
+             (
+                NULL,               // parent window, not used
+                csidl,
+                NULL,               // access token (current user)
+                SHGFP_TYPE_CURRENT, // current path, not just default value
+                wxStringBuffer(dir, MAX_PATH)
+             );
+
+        // somewhat incredibly, the error code in the Unicode version is
+        // different from the one in ASCII version for this function
+#if wxUSE_UNICODE
+        if ( hr == E_FAIL )
+#else
+        if ( hr == S_FALSE )
+#endif
+        {
+            // directory doesn't exist, maybe we can get its default value?
+            hr = gs_shellFuncs.pSHGetFolderPath
+                 (
+                    NULL,
+                    csidl,
+                    NULL,
+                    SHGFP_TYPE_DEFAULT,
+                    wxStringBuffer(dir, MAX_PATH)
+                 );
+        }
+    }
+#endif // SHGetFolderPath
+
+#ifdef SHGetSpecialFolderPath
+    if ( FAILED(hr) && gs_shellFuncs.pSHGetSpecialFolderPath )
+    {
+        hr = gs_shellFuncs.pSHGetSpecialFolderPath
+             (
+                NULL,               // parent window
+                wxStringBuffer(dir, MAX_PATH),
+                csidl,
+                FALSE               // don't create if doesn't exist
+             );
+    }
+#endif // SHGetSpecialFolderPath
+
+    // SHGetSpecialFolderLocation should be available with all compilers and
+    // under all Win32 systems, so don't test for it (and as it doesn't exist
+    // in "A" and "W" versions anyhow, testing would be more involved, too)
+    if ( FAILED(hr) )
+    {
+        LPITEMIDLIST pidl;
+        hr = SHGetSpecialFolderLocation(NULL, csidl, &pidl);
+
+        if ( SUCCEEDED(hr) )
+        {
+            // creating this temp object has (nice) side effect of freeing pidl
+            dir = wxItemIdList(pidl).GetPath();
+        }
+    }
+
+    return dir;
+}
+
+/* static */
+wxString wxStandardPaths::AppendAppName(const wxString& dir)
+{
+    wxString subdir(dir);
+
+    // empty string indicates that an error has occured, don't touch it then
+    if ( !subdir.empty() )
+    {
+        const wxString appname = wxTheApp->GetAppName();
+        if ( !appname.empty() )
+            subdir << _T('\\') << appname;
+    }
+
+    return subdir;
+}
+
+// ----------------------------------------------------------------------------
+// public functions
+// ----------------------------------------------------------------------------
+
+wxString wxStandardPaths::GetConfigDir() const
+{
+    return AppendAppName(DoGetDirectory(CSIDL_COMMON_APPDATA));
+}
+
+wxString wxStandardPaths::GetUserConfigDir() const
+{
+    return DoGetDirectory(CSIDL_APPDATA);
+}
+
+wxString wxStandardPaths::GetDataDir() const
+{
+    return AppendAppName(DoGetDirectory(CSIDL_PROGRAM_FILES));
+}
+
+wxString wxStandardPaths::GetUserDataDir() const
+{
+    return AppendAppName(GetUserConfigDir());
+}
+
+wxString wxStandardPaths::GetUserLocalDataDir() const
+{
+    return AppendAppName(DoGetDirectory(CSIDL_LOCAL_APPDATA));
+}
+
+wxString wxStandardPaths::GetPluginsDir() const
+{
+    return wxFileName(wxGetFullModuleName()).GetPath();
+}
+
+
+// ============================================================================
+// wxStandardPathsWin16 implementation
+// ============================================================================
+
+wxString wxStandardPathsWin16::GetConfigDir() const
+{
+    // this is for compatibility with earlier wxFileConfig versions
+    // which used the Windows directory for the global files
+    wxString dir;
+    if ( !::GetWindowsDirectory(wxStringBuffer(dir, MAX_PATH), MAX_PATH) )
+    {
+        wxLogLastError(_T("GetWindowsDirectory"));
+    }
+
+    return dir;
+}
+
+wxString wxStandardPathsWin16::GetUserConfigDir() const
+{
+    // again, for wxFileConfig which uses $HOME for its user config file
+    return wxGetHomeDir();
+}
+