]> git.saurik.com Git - wxWidgets.git/blame - src/msw/filedlg.cpp
Unhide problem of ambiguity in wxSoundBase::Play.
[wxWidgets.git] / src / msw / filedlg.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
f6bcfd97 2// Name: src/msw/filedlg.cpp
2bda0e17
KB
3// Purpose: wxFileDialog
4// Author: Julian Smart
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
6c9a19aa 8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
f6bcfd97
BP
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
14f355c2 20#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
ba681060 21 #pragma implementation "filedlg.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
ba681060 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
d7da7f13 31#if wxUSE_FILEDLG && !defined(__SMARTPHONE__)
1e6feb95 32
2bda0e17 33#ifndef WX_PRECOMP
ba681060
VZ
34 #include "wx/utils.h"
35 #include "wx/msgdlg.h"
ba681060 36 #include "wx/filedlg.h"
2b5f62a0 37 #include "wx/filefn.h"
ba681060 38 #include "wx/intl.h"
2662e49e 39 #include "wx/log.h"
f6bcfd97 40 #include "wx/app.h"
8f177c8e 41#endif
2bda0e17 42
f6bcfd97
BP
43#include "wx/msw/private.h"
44
4676948b 45#if !defined(__WIN32__) || defined(__WXWINCE__)
ba681060 46 #include <commdlg.h>
2bda0e17
KB
47#endif
48
2bda0e17
KB
49#include <math.h>
50#include <stdlib.h>
51#include <string.h>
52
8ad9ca97 53#include "wx/filename.h"
8f177c8e
VZ
54#include "wx/tokenzr.h"
55
6e8aa701
VZ
56#ifndef OFN_EXPLORER
57 #define OFN_EXPLORER 0x00080000
58#endif
59
f6bcfd97
BP
60// ----------------------------------------------------------------------------
61// constants
62// ----------------------------------------------------------------------------
63
64#ifdef __WIN32__
2b5f62a0 65# define wxMAXPATH 65534
f6bcfd97
BP
66#else
67# define wxMAXPATH 1024
68#endif
69
70# define wxMAXFILE 1024
71
72# define wxMAXEXT 5
73
74// ============================================================================
75// implementation
76// ============================================================================
77
f74172ab 78IMPLEMENT_CLASS(wxFileDialog, wxFileDialogBase)
2bda0e17 79
f6bcfd97 80// ----------------------------------------------------------------------------
b600ed13 81// wxFileDialog
f6bcfd97
BP
82// ----------------------------------------------------------------------------
83
2b5f62a0
VZ
84wxFileDialog::wxFileDialog(wxWindow *parent,
85 const wxString& message,
86 const wxString& defaultDir,
87 const wxString& defaultFileName,
88 const wxString& wildCard,
89 long style,
f74172ab
VZ
90 const wxPoint& pos)
91 :wxFileDialogBase(parent, message, defaultDir, defaultFileName, wildCard, style, pos)
92
2bda0e17 93{
c61f4f6d
VZ
94 if ( ( m_dialogStyle & wxMULTIPLE ) && ( m_dialogStyle & wxSAVE ) )
95 m_dialogStyle &= ~wxMULTIPLE;
2bda0e17
KB
96}
97
c61f4f6d
VZ
98void wxFileDialog::GetPaths(wxArrayString& paths) const
99{
100 paths.Empty();
101
102 wxString dir(m_dir);
103 if ( m_dir.Last() != _T('\\') )
104 dir += _T('\\');
105
106 size_t count = m_fileNames.GetCount();
107 for ( size_t n = 0; n < count; n++ )
108 {
8ad9ca97
JS
109 if (wxFileName(m_fileNames[n]).IsAbsolute())
110 paths.Add(m_fileNames[n]);
111 else
112 paths.Add(dir + m_fileNames[n]);
c61f4f6d
VZ
113 }
114}
115
89654c9a
VZ
116void wxFileDialog::GetFilenames(wxArrayString& files) const
117{
118 files = m_fileNames;
119}
120
2b5f62a0
VZ
121void wxFileDialog::SetPath(const wxString& path)
122{
123 wxString ext;
124 wxSplitPath(path, &m_dir, &m_fileName, &ext);
125 if ( !ext.empty() )
126 m_fileName << _T('.') << ext;
127}
128
c61f4f6d 129int wxFileDialog::ShowModal()
2bda0e17 130{
1f2f0331
VZ
131 HWND hWnd = 0;
132 if (m_parent) hWnd = (HWND) m_parent->GetHWND();
f6bcfd97
BP
133 if (!hWnd && wxTheApp->GetTopWindow())
134 hWnd = (HWND) wxTheApp->GetTopWindow()->GetHWND();
2bda0e17 135
f6bcfd97
BP
136 static wxChar fileNameBuffer [ wxMAXPATH ]; // the file-name
137 wxChar titleBuffer [ wxMAXFILE+1+wxMAXEXT ]; // the file-name, without path
2bda0e17 138
223d09f6
KB
139 *fileNameBuffer = wxT('\0');
140 *titleBuffer = wxT('\0');
2bda0e17 141
21416306 142#if WXWIN_COMPATIBILITY_2_4
2bda0e17 143 long msw_flags = 0;
e15e548b 144 if ( (m_dialogStyle & wxHIDE_READONLY) || (m_dialogStyle & wxSAVE) )
1f2f0331 145 msw_flags |= OFN_HIDEREADONLY;
21416306
WS
146#else
147 long msw_flags = OFN_HIDEREADONLY;
148#endif
149
e15e548b 150 if ( m_dialogStyle & wxFILE_MUST_EXIST )
1f2f0331 151 msw_flags |= OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
6e8aa701 152
c61f4f6d 153 if (m_dialogStyle & wxMULTIPLE )
6e8aa701
VZ
154 {
155 // OFN_EXPLORER must always be specified with OFN_ALLOWMULTISELECT
156 msw_flags |= OFN_EXPLORER | OFN_ALLOWMULTISELECT;
157 }
158
99d1b93d
VZ
159 // if wxCHANGE_DIR flag is not given we shouldn't change the CWD which the
160 // standard dialog does by default
6e8aa701
VZ
161 if ( !(m_dialogStyle & wxCHANGE_DIR) )
162 {
163 msw_flags |= OFN_NOCHANGEDIR;
164 }
ac95e671 165
99d1b93d
VZ
166 if ( m_dialogStyle & wxOVERWRITE_PROMPT )
167 {
168 msw_flags |= OFN_OVERWRITEPROMPT;
169 }
ac95e671 170
e15e548b 171 OPENFILENAME of;
f6bcfd97
BP
172 wxZeroMemory(of);
173
174 // the OPENFILENAME struct has been extended in newer version of
175 // comcdlg32.dll, but as we don't use the extended fields anyhow, set
176 // the struct size to the old value - otherwise, the programs compiled
177 // with new headers will not work with the old libraries
178#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0500)
179 of.lStructSize = sizeof(OPENFILENAME) -
180 (sizeof(void *) + 2*sizeof(DWORD));
181#else // old headers
e15e548b 182 of.lStructSize = sizeof(OPENFILENAME);
f6bcfd97
BP
183#endif
184
e15e548b 185 of.hwndOwner = hWnd;
837e5743 186 of.lpstrTitle = WXSTRINGCAST m_message;
e15e548b 187 of.lpstrFileTitle = titleBuffer;
f6bcfd97 188 of.nMaxFileTitle = wxMAXFILE + 1 + wxMAXEXT; // Windows 3.0 and 3.1
2bda0e17 189
0bc9b25e 190 // Convert forward slashes to backslashes (file selector doesn't like
99d1b93d
VZ
191 // forward slashes) and also squeeze multiple consecutive slashes into one
192 // as it doesn't like two backslashes in a row neither
0627d091
RL
193
194 wxString dir;
195 size_t i, len = m_dir.length();
99d1b93d 196 dir.reserve(len);
0627d091 197 for ( i = 0; i < len; i++ )
99d1b93d
VZ
198 {
199 wxChar ch = m_dir[i];
200 switch ( ch )
201 {
202 case _T('/'):
203 // convert to backslash
204 ch = _T('\\');
205
206 // fall through
0bc9b25e 207
99d1b93d
VZ
208 case _T('\\'):
209 while ( i < len - 1 )
210 {
211 wxChar chNext = m_dir[i + 1];
212 if ( chNext != _T('\\') && chNext != _T('/') )
213 break;
214
04d93c3a
CE
215 // ignore the next one, unless it is at the start of a UNC path
216 if (i > 0)
217 i++;
218 else
219 break;
99d1b93d
VZ
220 }
221 // fall through
222
223 default:
224 // normal char
225 dir += ch;
226 }
227 }
228
229 of.lpstrInitialDir = dir.c_str();
2bda0e17 230
e15e548b 231 of.Flags = msw_flags;
2bda0e17
KB
232
233
2bda0e17
KB
234 //=== Like Alejandro Sierra's wildcard modification >>===================
235 /*
1f2f0331
VZ
236 In wxFileSelector you can put, instead of a single wild_card,
237 pairs of strings separated by '|'.
238 The first string is a description, and the
239 second is the wild card. You can put any number of pairs.
2bda0e17 240
1f2f0331 241 eg. "description1 (*.ex1)|*.ex1|description2 (*.ex2)|*.ex2"
2bda0e17 242
1f2f0331
VZ
243 If you put a single wild card, it works as before the modification.
244 */
2bda0e17
KB
245 //=======================================================================
246
4dba84be 247 wxString theFilter;
837e5743 248 if ( wxStrlen(m_wildCard) == 0 )
223d09f6 249 theFilter = wxString(wxT("*.*"));
4dba84be
JS
250 else
251 theFilter = m_wildCard ;
1f2f0331 252 wxString filterBuffer;
2bda0e17 253
223d09f6 254 if ( !wxStrchr( theFilter, wxT('|') ) ) { // only one filter ==> default text
1f2f0331
VZ
255 filterBuffer.Printf(_("Files (%s)|%s"),
256 theFilter.c_str(), theFilter.c_str());
e15e548b 257 }
1f2f0331
VZ
258 else { // more then one filter
259 filterBuffer = theFilter;
2bda0e17 260
574c0bbf
JS
261 }
262
223d09f6 263 filterBuffer += wxT("|");
574c0bbf 264 // Replace | with \0
0bc9b25e 265 for (i = 0; i < filterBuffer.Len(); i++ ) {
223d09f6
KB
266 if ( filterBuffer.GetChar(i) == wxT('|') ) {
267 filterBuffer[i] = wxT('\0');
e15e548b
VZ
268 }
269 }
2bda0e17 270
837e5743 271 of.lpstrFilter = (LPTSTR)(const wxChar *)filterBuffer;
cc42eb7a 272 of.nFilterIndex = m_filterIndex + 1;
2bda0e17
KB
273
274 //=== Setting defaultFileName >>=========================================
275
f6bcfd97
BP
276 wxStrncpy( fileNameBuffer, (const wxChar *)m_fileName, wxMAXPATH-1 );
277 fileNameBuffer[ wxMAXPATH-1 ] = wxT('\0');
2bda0e17 278
e15e548b 279 of.lpstrFile = fileNameBuffer; // holds returned filename
f6bcfd97 280 of.nMaxFile = wxMAXPATH;
2bda0e17
KB
281
282 //== Execute FileDialog >>=================================================
283
3f6638b8
VZ
284 bool success = (m_dialogStyle & wxSAVE ? GetSaveFileName(&of)
285 : GetOpenFileName(&of)) != 0;
2bda0e17 286
f6bcfd97
BP
287 DWORD errCode = CommDlgExtendedError();
288
289#ifdef __WIN32__
290 if (!success && (errCode == CDERR_STRUCTSIZE))
291 {
292 // The struct size has changed so try a smaller or bigger size
293
294 int oldStructSize = of.lStructSize;
295 of.lStructSize = oldStructSize - (sizeof(void *) + 2*sizeof(DWORD));
296 success = (m_dialogStyle & wxSAVE) ? (GetSaveFileName(&of) != 0)
297 : (GetOpenFileName(&of) != 0);
298 errCode = CommDlgExtendedError();
299
300 if (!success && (errCode == CDERR_STRUCTSIZE))
301 {
302 of.lStructSize = oldStructSize + (sizeof(void *) + 2*sizeof(DWORD));
303 success = (m_dialogStyle & wxSAVE) ? (GetSaveFileName(&of) != 0)
304 : (GetOpenFileName(&of) != 0);
305 }
306 }
c6603ac2 307#endif // __WIN32__
f6bcfd97 308
2bda0e17
KB
309 if ( success )
310 {
c61f4f6d
VZ
311 m_fileNames.Empty();
312
313 if ( ( m_dialogStyle & wxMULTIPLE ) &&
314#if defined(OFN_EXPLORER)
c39e82f0 315 ( fileNameBuffer[of.nFileOffset-1] == wxT('\0') )
c61f4f6d 316#else
c39e82f0 317 ( fileNameBuffer[of.nFileOffset-1] == wxT(' ') )
c61f4f6d 318#endif // OFN_EXPLORER
c39e82f0 319 )
c61f4f6d
VZ
320 {
321#if defined(OFN_EXPLORER)
322 m_dir = fileNameBuffer;
323 i = of.nFileOffset;
324 m_fileName = &fileNameBuffer[i];
325 m_fileNames.Add(m_fileName);
326 i += m_fileName.Len() + 1;
327
328 while (fileNameBuffer[i] != wxT('\0'))
329 {
330 m_fileNames.Add(&fileNameBuffer[i]);
331 i += wxStrlen(&fileNameBuffer[i]) + 1;
332 }
333#else
c6603ac2 334 wxStringTokenizer toke(fileNameBuffer, _T(" \t\r\n"));
c61f4f6d
VZ
335 m_dir = toke.GetNextToken();
336 m_fileName = toke.GetNextToken();
337 m_fileNames.Add(m_fileName);
338
339 while (toke.HasMoreTokens())
340 m_fileNames.Add(toke.GetNextToken());
341#endif // OFN_EXPLORER
342
343 wxString dir(m_dir);
344 if ( m_dir.Last() != _T('\\') )
345 dir += _T('\\');
346
c61f4f6d 347 m_path = dir + m_fileName;
f0f43012 348 m_filterIndex = (int)of.nFilterIndex - 1;
c61f4f6d
VZ
349 }
350 else
351 {
c61f4f6d 352 //=== Adding the correct extension >>=================================
2bda0e17 353
cc42eb7a 354 m_filterIndex = (int)of.nFilterIndex - 1;
2bda0e17 355
c6603ac2
VS
356 if ( !of.nFileExtension ||
357 (of.nFileExtension && fileNameBuffer[of.nFileExtension] == wxT('\0')) )
358 {
359 // User has typed a filename without an extension:
f74172ab
VZ
360 const wxChar* extension = filterBuffer;
361 int maxFilter = (int)(of.nFilterIndex*2L) - 1;
2bda0e17 362
f74172ab
VZ
363 for( int i = 0; i < maxFilter; i++ ) // get extension
364 extension = extension + wxStrlen( extension ) + 1;
a039ccbf 365
f74172ab
VZ
366 m_fileName = AppendExtension(fileNameBuffer, extension);
367 wxStrncpy(fileNameBuffer, m_fileName.c_str(), wxMin(m_fileName.Len(), wxMAXPATH-1));
368 fileNameBuffer[wxMin(m_fileName.Len(), wxMAXPATH-1)] = wxT('\0');
2bda0e17 369 }
2bda0e17 370
c61f4f6d
VZ
371 m_path = fileNameBuffer;
372 m_fileName = wxFileNameFromPath(fileNameBuffer);
373 m_fileNames.Add(m_fileName);
374 m_dir = wxPathOnly(fileNameBuffer);
375 }
7cc98b3e
VZ
376 }
377 else
378 {
379 // common dialog failed - why?
380#ifdef __WXDEBUG__
381 DWORD dwErr = CommDlgExtendedError();
382 if ( dwErr != 0 )
383 {
384 // this msg is only for developers
223d09f6 385 wxLogError(wxT("Common dialog failed with error code %0lx."),
7cc98b3e
VZ
386 dwErr);
387 }
388 //else: it was just cancelled
389#endif
390 }
2bda0e17 391
7cc98b3e 392 return success ? wxID_OK : wxID_CANCEL;
2bda0e17
KB
393
394}
395
1e6feb95 396#endif // wxUSE_FILEDLG
c61f4f6d 397