]> git.saurik.com Git - wxWidgets.git/blame - src/msw/stdpaths.cpp
Must strip menu codes from labels before measuring (fixes bug 1400552)
[wxWidgets.git] / src / msw / stdpaths.cpp
CommitLineData
40e8ee37
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: msw/stdpaths.cpp
3// Purpose: wxStandardPaths implementation for Win32
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 2004-10-19
7// RCS-ID: $Id$
8// Copyright: (c) 2004 Vadim Zeitlin <vadim@wxwindows.org>
9// License: wxWindows license
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// for compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
cd9a8d40
VZ
27#if wxUSE_STDPATHS
28
40e8ee37
VZ
29#ifndef WX_PRECOMP
30 #include "wx/app.h"
31#endif //WX_PRECOMP
32
33#include "wx/dynlib.h"
34#include "wx/filename.h"
35
36#include "wx/stdpaths.h"
37
38#include "wx/msw/private.h"
39#include "wx/msw/wrapshl.h"
40
41// ----------------------------------------------------------------------------
42// types
43// ----------------------------------------------------------------------------
44
45typedef HRESULT (WINAPI *SHGetFolderPath_t)(HWND, int, HANDLE, DWORD, LPTSTR);
46typedef HRESULT (WINAPI *SHGetSpecialFolderPath_t)(HWND, LPTSTR, int, BOOL);
47
48// ----------------------------------------------------------------------------
49// constants
50// ----------------------------------------------------------------------------
51
52// used in our wxLogTrace messages
53static const wxChar *TRACE_MASK = _T("stdpaths");
54
61c2afed
WS
55#ifndef CSIDL_APPDATA
56 #define CSIDL_APPDATA 0x001a
57#endif
58
40e8ee37
VZ
59#ifndef CSIDL_LOCAL_APPDATA
60 #define CSIDL_LOCAL_APPDATA 0x001c
61#endif
62
63#ifndef CSIDL_COMMON_APPDATA
64 #define CSIDL_COMMON_APPDATA 0x0023
65#endif
66
67#ifndef CSIDL_PROGRAM_FILES
68 #define CSIDL_PROGRAM_FILES 0x0026
69#endif
70
cd0c4800
WS
71#ifndef SHGFP_TYPE_CURRENT
72 #define SHGFP_TYPE_CURRENT 0
73#endif
74
75#ifndef SHGFP_TYPE_DEFAULT
76 #define SHGFP_TYPE_DEFAULT 1
77#endif
78
40e8ee37
VZ
79// ----------------------------------------------------------------------------
80// module globals
81// ----------------------------------------------------------------------------
82
83struct ShellFunctions
84{
85 ShellFunctions()
86 {
87 pSHGetFolderPath = NULL;
88 pSHGetSpecialFolderPath = NULL;
89 initialized = false;
90 }
91
92 SHGetFolderPath_t pSHGetFolderPath;
93 SHGetSpecialFolderPath_t pSHGetSpecialFolderPath;
94
95 bool initialized;
96};
97
98// in spite of using a static variable, this is MT-safe as in the worst case it
99// results in initializing the function pointer several times -- but this is
100// harmless
101static ShellFunctions gs_shellFuncs;
102
103// ----------------------------------------------------------------------------
104// private functions
105// ----------------------------------------------------------------------------
106
107static void ResolveShellFunctions()
108{
40e8ee37 109 // start with the newest functions, fall back to the oldest ones
780d7317
JS
110#ifdef __WXWINCE__
111 wxString shellDllName(_T("coredll"));
112#else
40e8ee37 113 // first check for SHGetFolderPath (shell32.dll 5.0)
780d7317
JS
114 wxString shellDllName(_T("shell32"));
115#endif
116
117 wxDynamicLibrary dllShellFunctions( shellDllName );
118 if ( !dllShellFunctions.IsLoaded() )
40e8ee37 119 {
14e9e56d 120 wxLogTrace(TRACE_MASK, _T("Failed to load %s.dll"), shellDllName.c_str() );
40e8ee37
VZ
121 }
122
780d7317
JS
123 // don't give errors if the functions are unavailable, we're ready to deal
124 // with this
125 wxLogNull noLog;
126
40e8ee37 127#if wxUSE_UNICODE
780d7317
JS
128 #ifdef __WXWINCE__
129 static const wchar_t UNICODE_SUFFIX = L''; // WinCE SH functions don't seem to have 'W'
130 #else
131 static const wchar_t UNICODE_SUFFIX = L'W';
132 #endif
40e8ee37
VZ
133#else // !Unicode
134 static const char UNICODE_SUFFIX = 'A';
135#endif // Unicode/!Unicode
136
137 wxString funcname(_T("SHGetFolderPath"));
138 gs_shellFuncs.pSHGetFolderPath =
780d7317 139 (SHGetFolderPath_t)dllShellFunctions.GetSymbol(funcname + UNICODE_SUFFIX);
40e8ee37
VZ
140
141 // then for SHGetSpecialFolderPath (shell32.dll 4.71)
142 if ( !gs_shellFuncs.pSHGetFolderPath )
143 {
144 funcname = _T("SHGetSpecialFolderPath");
145 gs_shellFuncs.pSHGetSpecialFolderPath = (SHGetSpecialFolderPath_t)
780d7317 146 dllShellFunctions.GetSymbol(funcname + UNICODE_SUFFIX);
40e8ee37
VZ
147 }
148
149 // finally we fall back on SHGetSpecialFolderLocation (shell32.dll 4.0),
150 // but we don't need to test for it -- it is available even under Win95
151
152 // shell32.dll is going to be unloaded, but it still remains in memory
153 // because we also link to it statically, so it's ok
154
155 gs_shellFuncs.initialized = true;
156}
157
158// ============================================================================
159// wxStandardPaths implementation
160// ============================================================================
161
162// ----------------------------------------------------------------------------
163// private helpers
164// ----------------------------------------------------------------------------
165
166/* static */
167wxString wxStandardPaths::DoGetDirectory(int csidl)
168{
169 if ( !gs_shellFuncs.initialized )
170 ResolveShellFunctions();
171
172 wxString dir;
173 HRESULT hr = E_FAIL;
174
175 // test whether the function is available during compile-time (it must be
176 // defined as either "SHGetFolderPathA" or "SHGetFolderPathW")
177#ifdef SHGetFolderPath
178 // and now test whether we have it during run-time
179 if ( gs_shellFuncs.pSHGetFolderPath )
180 {
181 hr = gs_shellFuncs.pSHGetFolderPath
182 (
183 NULL, // parent window, not used
184 csidl,
185 NULL, // access token (current user)
186 SHGFP_TYPE_CURRENT, // current path, not just default value
187 wxStringBuffer(dir, MAX_PATH)
188 );
189
190 // somewhat incredibly, the error code in the Unicode version is
191 // different from the one in ASCII version for this function
192#if wxUSE_UNICODE
193 if ( hr == E_FAIL )
194#else
195 if ( hr == S_FALSE )
196#endif
197 {
198 // directory doesn't exist, maybe we can get its default value?
199 hr = gs_shellFuncs.pSHGetFolderPath
200 (
201 NULL,
202 csidl,
203 NULL,
204 SHGFP_TYPE_DEFAULT,
205 wxStringBuffer(dir, MAX_PATH)
206 );
207 }
208 }
209#endif // SHGetFolderPath
210
211#ifdef SHGetSpecialFolderPath
212 if ( FAILED(hr) && gs_shellFuncs.pSHGetSpecialFolderPath )
213 {
214 hr = gs_shellFuncs.pSHGetSpecialFolderPath
215 (
216 NULL, // parent window
217 wxStringBuffer(dir, MAX_PATH),
218 csidl,
219 FALSE // don't create if doesn't exist
220 );
221 }
222#endif // SHGetSpecialFolderPath
223
224 // SHGetSpecialFolderLocation should be available with all compilers and
225 // under all Win32 systems, so don't test for it (and as it doesn't exist
226 // in "A" and "W" versions anyhow, testing would be more involved, too)
227 if ( FAILED(hr) )
228 {
229 LPITEMIDLIST pidl;
230 hr = SHGetSpecialFolderLocation(NULL, csidl, &pidl);
231
232 if ( SUCCEEDED(hr) )
233 {
234 // creating this temp object has (nice) side effect of freeing pidl
235 dir = wxItemIdList(pidl).GetPath();
236 }
237 }
238
239 return dir;
240}
241
40e8ee37
VZ
242// ----------------------------------------------------------------------------
243// public functions
244// ----------------------------------------------------------------------------
245
246wxString wxStandardPaths::GetConfigDir() const
247{
248 return AppendAppName(DoGetDirectory(CSIDL_COMMON_APPDATA));
249}
250
251wxString wxStandardPaths::GetUserConfigDir() const
252{
253 return DoGetDirectory(CSIDL_APPDATA);
254}
255
256wxString wxStandardPaths::GetDataDir() const
257{
90537299
VZ
258 // under Windows each program is usually installed in its own directory and
259 // so its datafiles are in the same directory as its main executable
260 return wxFileName(wxGetFullModuleName()).GetPath();
40e8ee37
VZ
261}
262
263wxString wxStandardPaths::GetUserDataDir() const
264{
265 return AppendAppName(GetUserConfigDir());
266}
267
268wxString wxStandardPaths::GetUserLocalDataDir() const
269{
270 return AppendAppName(DoGetDirectory(CSIDL_LOCAL_APPDATA));
271}
272
273wxString wxStandardPaths::GetPluginsDir() const
274{
275 return wxFileName(wxGetFullModuleName()).GetPath();
276}
277
278
279// ============================================================================
280// wxStandardPathsWin16 implementation
281// ============================================================================
282
283wxString wxStandardPathsWin16::GetConfigDir() const
284{
285 // this is for compatibility with earlier wxFileConfig versions
286 // which used the Windows directory for the global files
287 wxString dir;
e2072525 288#ifndef __WXWINCE__
40e8ee37
VZ
289 if ( !::GetWindowsDirectory(wxStringBuffer(dir, MAX_PATH), MAX_PATH) )
290 {
291 wxLogLastError(_T("GetWindowsDirectory"));
292 }
e2072525 293#else
503602df 294 // TODO: use CSIDL_WINDOWS (eVC4, possibly not eVC3)
4fb9d560 295 dir = wxT("\\Windows");
e2072525 296#endif
40e8ee37
VZ
297
298 return dir;
299}
300
301wxString wxStandardPathsWin16::GetUserConfigDir() const
302{
303 // again, for wxFileConfig which uses $HOME for its user config file
304 return wxGetHomeDir();
305}
306
cd9a8d40 307#endif // wxUSE_STDPATHS