]> git.saurik.com Git - wxWidgets.git/blame - src/msw/filedlg.cpp
Ensure that validators work even in presence of pushed event handlers.
[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
2bda0e17
KB
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
ba681060 24 #pragma hdrstop
2bda0e17
KB
25#endif
26
3180bc0e 27#if wxUSE_FILEDLG && !(defined(__SMARTPHONE__) && defined(__WXWINCE__))
1e6feb95 28
949c9f74
WS
29#include "wx/filedlg.h"
30
2bda0e17 31#ifndef WX_PRECOMP
57bd4c60
WS
32 #include "wx/msw/wrapcdlg.h"
33 #include "wx/msw/missing.h"
ba681060
VZ
34 #include "wx/utils.h"
35 #include "wx/msgdlg.h"
2b5f62a0 36 #include "wx/filefn.h"
ba681060 37 #include "wx/intl.h"
2662e49e 38 #include "wx/log.h"
f6bcfd97 39 #include "wx/app.h"
18680f86 40 #include "wx/math.h"
8f177c8e 41#endif
2bda0e17 42
2bda0e17
KB
43#include <stdlib.h>
44#include <string.h>
45
8ad9ca97 46#include "wx/filename.h"
8f177c8e
VZ
47#include "wx/tokenzr.h"
48
f6bcfd97
BP
49// ----------------------------------------------------------------------------
50// constants
51// ----------------------------------------------------------------------------
52
53#ifdef __WIN32__
2b5f62a0 54# define wxMAXPATH 65534
f6bcfd97
BP
55#else
56# define wxMAXPATH 1024
57#endif
58
59# define wxMAXFILE 1024
60
61# define wxMAXEXT 5
62
0b11099d
VZ
63// ----------------------------------------------------------------------------
64// globals
65// ----------------------------------------------------------------------------
66
0a7b0229
VZ
67// standard dialog size for the old Windows systems where the dialog wasn't
68// resizeable
0b11099d
VZ
69static wxRect gs_rectDialog(0, 0, 428, 266);
70
f6bcfd97
BP
71// ============================================================================
72// implementation
73// ============================================================================
74
f74172ab 75IMPLEMENT_CLASS(wxFileDialog, wxFileDialogBase)
2bda0e17 76
0b11099d
VZ
77// ----------------------------------------------------------------------------
78// hook function for moving the dialog
79// ----------------------------------------------------------------------------
80
106d80ad 81UINT_PTR APIENTRY
0b11099d
VZ
82wxFileDialogHookFunction(HWND hDlg,
83 UINT iMsg,
84 WPARAM WXUNUSED(wParam),
85 LPARAM lParam)
86{
cb80db46 87 switch ( iMsg )
0b11099d 88 {
d6dae1b4 89#ifndef __WXWINCE__
6fa6d659
VZ
90 case WM_INITDIALOG:
91 {
92 OPENFILENAME* ofn = reinterpret_cast<OPENFILENAME *>(lParam);
93 reinterpret_cast<wxFileDialog *>(ofn->lCustData)
94 ->MSWOnInitDialogHook((WXHWND)hDlg);
95 }
96 break;
d6dae1b4 97#endif // __WXWINCE__
6fa6d659 98
0b11099d
VZ
99 case WM_NOTIFY:
100 {
5c33522f 101 OFNOTIFY *pNotifyCode = reinterpret_cast<OFNOTIFY *>(lParam);
cb80db46 102 if ( pNotifyCode->hdr.code == CDN_INITDONE )
0b11099d 103 {
5c33522f 104 reinterpret_cast<wxFileDialog *>(
0a7b0229
VZ
105 pNotifyCode->lpOFN->lCustData)
106 ->MSWOnInitDone((WXHWND)hDlg);
0b11099d
VZ
107 }
108 }
109 break;
cb80db46
VZ
110
111 case WM_DESTROY:
112 // reuse the position used for the dialog the next time by default
113 //
114 // NB: at least under Windows 2003 this is useless as after the
115 // first time it's shown the dialog always remembers its size
116 // and position itself and ignores any later SetWindowPos calls
117 wxCopyRECTToRect(wxGetWindowRect(::GetParent(hDlg)), gs_rectDialog);
118 break;
0b11099d
VZ
119 }
120
121 // do the default processing
122 return 0;
123}
124
f6bcfd97 125// ----------------------------------------------------------------------------
b600ed13 126// wxFileDialog
f6bcfd97
BP
127// ----------------------------------------------------------------------------
128
2b5f62a0
VZ
129wxFileDialog::wxFileDialog(wxWindow *parent,
130 const wxString& message,
131 const wxString& defaultDir,
132 const wxString& defaultFileName,
133 const wxString& wildCard,
134 long style,
ff3e84ff
VZ
135 const wxPoint& pos,
136 const wxSize& sz,
137 const wxString& name)
0b11099d 138 : wxFileDialogBase(parent, message, defaultDir, defaultFileName,
ff3e84ff 139 wildCard, style, pos, sz, name)
f74172ab 140
2bda0e17 141{
556151f5 142 // NB: all style checks are done by wxFileDialogBase::Create
2bda0e17 143
0b11099d 144 m_bMovedWindow = false;
0a7b0229 145 m_centreDir = 0;
0b11099d
VZ
146
147 // Must set to zero, otherwise the wx routines won't size the window
148 // the second time you call the file dialog, because it thinks it is
149 // already at the requested size.. (when centering)
150 gs_rectDialog.x =
151 gs_rectDialog.y = 0;
0b11099d 152}
0a7b0229 153
c61f4f6d
VZ
154void wxFileDialog::GetPaths(wxArrayString& paths) const
155{
156 paths.Empty();
157
158 wxString dir(m_dir);
9a83f860
VZ
159 if ( m_dir.Last() != wxT('\\') )
160 dir += wxT('\\');
c61f4f6d
VZ
161
162 size_t count = m_fileNames.GetCount();
163 for ( size_t n = 0; n < count; n++ )
164 {
8ad9ca97
JS
165 if (wxFileName(m_fileNames[n]).IsAbsolute())
166 paths.Add(m_fileNames[n]);
167 else
168 paths.Add(dir + m_fileNames[n]);
c61f4f6d
VZ
169 }
170}
171
89654c9a
VZ
172void wxFileDialog::GetFilenames(wxArrayString& files) const
173{
174 files = m_fileNames;
175}
176
cb80db46 177void wxFileDialog::DoGetPosition(int *x, int *y) const
0b11099d 178{
cb80db46
VZ
179 if ( x )
180 *x = gs_rectDialog.x;
181 if ( y )
182 *y = gs_rectDialog.y;
0b11099d
VZ
183}
184
0b11099d
VZ
185void wxFileDialog::DoGetSize(int *width, int *height) const
186{
cb80db46
VZ
187 if ( width )
188 *width = gs_rectDialog.width;
189 if ( height )
190 *height = gs_rectDialog.height;
0b11099d
VZ
191}
192
cb80db46 193void wxFileDialog::DoMoveWindow(int x, int y, int WXUNUSED(w), int WXUNUSED(h))
0b11099d 194{
0b11099d
VZ
195 gs_rectDialog.x = x;
196 gs_rectDialog.y = y;
197
0a7b0229
VZ
198 // our HWND is only set when we're called from MSWOnInitDone(), test if
199 // this is the case
200 HWND hwnd = GetHwnd();
201 if ( hwnd )
202 {
203 // size of the dialog can't be changed because the controls are not
204 // laid out correctly then
205 ::SetWindowPos(hwnd, HWND_TOP, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
206 }
207 else // just remember that we were requested to move the window
208 {
209 m_bMovedWindow = true;
210
211 // if Centre() had been called before, it shouldn't be taken into
212 // account now
213 m_centreDir = 0;
214 }
215}
216
217void wxFileDialog::DoCentre(int dir)
218{
219 m_centreDir = dir;
220 m_bMovedWindow = true;
221
222 // it's unnecessary to do anything else at this stage as we'll redo it in
223 // MSWOnInitDone() anyhow
224}
225
226void wxFileDialog::MSWOnInitDone(WXHWND hDlg)
227{
228 // note the the dialog is the parent window: hDlg is a child of it when
229 // OFN_EXPLORER is used
230 HWND hFileDlg = ::GetParent((HWND)hDlg);
231
232 // set HWND so that our DoMoveWindow() works correctly
233 SetHWND((WXHWND)hFileDlg);
234
235 if ( m_centreDir )
236 {
237 // now we have the real dialog size, remember it
238 RECT rect;
239 GetWindowRect(hFileDlg, &rect);
240 gs_rectDialog = wxRectFromRECT(rect);
241
242 // and position the window correctly: notice that we must use the base
243 // class version as our own doesn't do anything except setting flags
244 wxFileDialogBase::DoCentre(m_centreDir);
245 }
246 else // need to just move it to the correct place
247 {
248 SetPosition(gs_rectDialog.GetPosition());
249 }
250
251 // we shouldn't destroy this HWND
252 SetHWND(NULL);
0b11099d
VZ
253}
254
fe048d77
VZ
255// helper used below in ShowCommFileDialog(): style is used to determine
256// whether to show the "Save file" dialog (if it contains wxFD_SAVE bit) or
257// "Open file" one; returns true on success or false on failure in which case
258// err is filled with the CDERR_XXX constant
c46c1fb8
VZ
259static bool DoShowCommFileDialog(OPENFILENAME *of, long style, DWORD *err)
260{
e031f1df 261 if ( style & wxFD_SAVE ? GetSaveFileName(of) : GetOpenFileName(of) )
c46c1fb8
VZ
262 return true;
263
264 if ( err )
265 {
266#ifdef __WXWINCE__
267 // according to MSDN, CommDlgExtendedError() should work under CE as
268 // well but apparently in practice it doesn't (anybody has more
269 // details?)
270 *err = GetLastError();
271#else
272 *err = CommDlgExtendedError();
273#endif
274 }
275
276 return false;
277}
278
04227efc
VZ
279// We want to use OPENFILENAME struct version 5 (Windows 2000/XP) but we don't
280// know if the OPENFILENAME declared in the currently used headers is a V5 or
281// V4 (smaller) one so we try to manually extend the struct in case it is the
282// old one.
5bb37216 283//
04227efc
VZ
284// We don't do this on Windows CE nor under Win64, however, as there are no
285// compilers with old headers for these architectures
286#if defined(__WXWINCE__) || defined(__WIN64__)
5bb37216
VZ
287 typedef OPENFILENAME wxOPENFILENAME;
288
04227efc
VZ
289 static const DWORD gs_ofStructSize = sizeof(OPENFILENAME);
290#else // !__WXWINCE__ || __WIN64__
291 #define wxTRY_SMALLER_OPENFILENAME
292
5bb37216
VZ
293 struct wxOPENFILENAME : public OPENFILENAME
294 {
295 // fields added in Windows 2000/XP comdlg32.dll version
296 void *pVoid;
297 DWORD dw1;
298 DWORD dw2;
299 };
300
301 // hardcoded sizeof(OPENFILENAME) in the Platform SDK: we have to do it
302 // because sizeof(OPENFILENAME) in the headers we use when compiling the
303 // library could be less if _WIN32_WINNT is not >= 0x500
304 static const DWORD wxOPENFILENAME_V5_SIZE = 88;
305
306 // this is hardcoded sizeof(OPENFILENAME_NT4) from Platform SDK
307 static const DWORD wxOPENFILENAME_V4_SIZE = 76;
5bb37216 308
04227efc
VZ
309 // always try the new one first
310 static DWORD gs_ofStructSize = wxOPENFILENAME_V5_SIZE;
311#endif // __WXWINCE__ || __WIN64__/!...
5bb37216 312
fe048d77
VZ
313static bool ShowCommFileDialog(OPENFILENAME *of, long style)
314{
315 DWORD errCode;
316 bool success = DoShowCommFileDialog(of, style, &errCode);
317
318#ifdef wxTRY_SMALLER_OPENFILENAME
319 // the system might be too old to support the new version file dialog
320 // boxes, try with the old size
321 if ( !success && errCode == CDERR_STRUCTSIZE &&
322 of->lStructSize != wxOPENFILENAME_V4_SIZE )
323 {
324 of->lStructSize = wxOPENFILENAME_V4_SIZE;
325
326 success = DoShowCommFileDialog(of, style, &errCode);
327
328 if ( success || !errCode )
329 {
330 // use this struct size for subsequent dialogs
331 gs_ofStructSize = of->lStructSize;
332 }
333 }
334#endif // wxTRY_SMALLER_OPENFILENAME
335
d4380371
VZ
336 if ( !success &&
337 // FNERR_INVALIDFILENAME is not defined under CE (besides we don't
338 // use CommDlgExtendedError() there anyhow)
339#ifndef __WXWINCE__
340 errCode == FNERR_INVALIDFILENAME &&
341#endif // !__WXWINCE__
342 of->lpstrFile[0] )
fe048d77
VZ
343 {
344 // this can happen if the default file name is invalid, try without it
345 // now
9a83f860 346 of->lpstrFile[0] = wxT('\0');
fe048d77
VZ
347 success = DoShowCommFileDialog(of, style, &errCode);
348 }
349
350 if ( !success )
351 {
352 // common dialog failed - why?
353 if ( errCode != 0 )
354 {
355 wxLogError(_("File dialog failed with error code %0lx."), errCode);
356 }
357 //else: it was just cancelled
358
359 return false;
360 }
361
362 return true;
363}
364
d6dae1b4 365#ifndef __WXWINCE__
6fa6d659
VZ
366void wxFileDialog::MSWOnInitDialogHook(WXHWND hwnd)
367{
368 SetHWND(hwnd);
369
370 CreateExtraControl();
371
372 SetHWND(NULL);
373}
d6dae1b4 374#endif // __WXWINCE__
6fa6d659 375
c61f4f6d 376int wxFileDialog::ShowModal()
2bda0e17 377{
1f2f0331
VZ
378 HWND hWnd = 0;
379 if (m_parent) hWnd = (HWND) m_parent->GetHWND();
f6bcfd97
BP
380 if (!hWnd && wxTheApp->GetTopWindow())
381 hWnd = (HWND) wxTheApp->GetTopWindow()->GetHWND();
2bda0e17 382
f6bcfd97
BP
383 static wxChar fileNameBuffer [ wxMAXPATH ]; // the file-name
384 wxChar titleBuffer [ wxMAXFILE+1+wxMAXEXT ]; // the file-name, without path
2bda0e17 385
223d09f6
KB
386 *fileNameBuffer = wxT('\0');
387 *titleBuffer = wxT('\0');
2bda0e17 388
21416306 389 long msw_flags = OFN_HIDEREADONLY;
21416306 390
b014db05 391 if ( HasFdFlag(wxFD_FILE_MUST_EXIST) )
1f2f0331 392 msw_flags |= OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
0b11099d
VZ
393 /*
394 If the window has been moved the programmer is probably
395 trying to center or position it. Thus we set the callback
396 or hook function so that we can actually adjust the position.
397 Without moving or centering the dlg, it will just stay
398 in the upper left of the frame, it does not center
5bb37216 399 automatically.
0b11099d 400 */
6fa6d659 401 if (m_bMovedWindow || HasExtraControlCreator()) // we need these flags.
503528dc
JS
402 {
403 msw_flags |= OFN_EXPLORER|OFN_ENABLEHOOK;
404#ifndef __WXWINCE__
405 msw_flags |= OFN_ENABLESIZING;
406#endif
407 }
6e8aa701 408
b014db05 409 if ( HasFdFlag(wxFD_MULTIPLE) )
6e8aa701
VZ
410 {
411 // OFN_EXPLORER must always be specified with OFN_ALLOWMULTISELECT
412 msw_flags |= OFN_EXPLORER | OFN_ALLOWMULTISELECT;
413 }
414
e031f1df 415 // if wxFD_CHANGE_DIR flag is not given we shouldn't change the CWD which the
af1f0a76
VZ
416 // standard dialog does by default (notice that under NT it does it anyhow,
417 // OFN_NOCHANGEDIR or not, see below)
b014db05 418 if ( !HasFdFlag(wxFD_CHANGE_DIR) )
6e8aa701
VZ
419 {
420 msw_flags |= OFN_NOCHANGEDIR;
421 }
ac95e671 422
b014db05 423 if ( HasFdFlag(wxFD_OVERWRITE_PROMPT) )
99d1b93d
VZ
424 {
425 msw_flags |= OFN_OVERWRITEPROMPT;
426 }
ac95e671 427
5bb37216 428 wxOPENFILENAME of;
f6bcfd97
BP
429 wxZeroMemory(of);
430
5bb37216 431 of.lStructSize = gs_ofStructSize;
e15e548b 432 of.hwndOwner = hWnd;
e0a050e3 433 of.lpstrTitle = m_message.wx_str();
e15e548b 434 of.lpstrFileTitle = titleBuffer;
5bb37216 435 of.nMaxFileTitle = wxMAXFILE + 1 + wxMAXEXT;
2bda0e17 436
6fa6d659
VZ
437#ifndef __WXWINCE__
438 GlobalPtr hgbl;
439 if ( HasExtraControlCreator() )
440 {
441 msw_flags |= OFN_ENABLETEMPLATEHANDLE;
442
443 hgbl.Init(256, GMEM_ZEROINIT);
444 GlobalPtrLock hgblLock(hgbl);
445 LPDLGTEMPLATE lpdt = static_cast<LPDLGTEMPLATE>(hgblLock.Get());
446
447 // Define a dialog box.
448
449 lpdt->style = DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS;
450 lpdt->cdit = 0; // Number of controls
451 lpdt->x = 0;
452 lpdt->y = 0;
453
c10c791b
VZ
454 // convert the size of the extra controls to the dialog units
455 const wxSize extraSize = GetExtraControlSize();
456 const LONG baseUnits = ::GetDialogBaseUnits();
457 lpdt->cx = ::MulDiv(extraSize.x, 4, LOWORD(baseUnits));
458 lpdt->cy = ::MulDiv(extraSize.y, 8, HIWORD(baseUnits));
6fa6d659
VZ
459
460 // after the DLGTEMPLATE there are 3 additional WORDs for dialog menu,
461 // class and title, all three set to zeros.
462
463 of.hInstance = (HINSTANCE)lpdt;
464 }
465#endif // __WXWINCE__
466
0bc9b25e 467 // Convert forward slashes to backslashes (file selector doesn't like
99d1b93d
VZ
468 // forward slashes) and also squeeze multiple consecutive slashes into one
469 // as it doesn't like two backslashes in a row neither
0627d091 470
cbe874bd
WS
471 wxString dir;
472 size_t i, len = m_dir.length();
99d1b93d 473 dir.reserve(len);
0627d091 474 for ( i = 0; i < len; i++ )
99d1b93d
VZ
475 {
476 wxChar ch = m_dir[i];
477 switch ( ch )
478 {
9a83f860 479 case wxT('/'):
99d1b93d 480 // convert to backslash
9a83f860 481 ch = wxT('\\');
99d1b93d
VZ
482
483 // fall through
0bc9b25e 484
9a83f860 485 case wxT('\\'):
99d1b93d
VZ
486 while ( i < len - 1 )
487 {
488 wxChar chNext = m_dir[i + 1];
9a83f860 489 if ( chNext != wxT('\\') && chNext != wxT('/') )
99d1b93d
VZ
490 break;
491
04d93c3a
CE
492 // ignore the next one, unless it is at the start of a UNC path
493 if (i > 0)
494 i++;
495 else
0b11099d 496 break;
99d1b93d
VZ
497 }
498 // fall through
499
500 default:
501 // normal char
502 dir += ch;
503 }
504 }
505
506 of.lpstrInitialDir = dir.c_str();
2bda0e17 507
e15e548b 508 of.Flags = msw_flags;
0b11099d 509 of.lpfnHook = wxFileDialogHookFunction;
0a7b0229 510 of.lCustData = (LPARAM)this;
2bda0e17 511
daf32463 512 wxArrayString wildDescriptions, wildFilters;
2bda0e17 513
daf32463 514 size_t items = wxParseCommonDialogsFilter(m_wildCard, wildDescriptions, wildFilters);
2bda0e17 515
9a83f860 516 wxASSERT_MSG( items > 0 , wxT("empty wildcard list") );
2bda0e17 517
1f2f0331 518 wxString filterBuffer;
2bda0e17 519
daf32463
WS
520 for (i = 0; i < items ; i++)
521 {
522 filterBuffer += wildDescriptions[i];
523 filterBuffer += wxT("|");
524 filterBuffer += wildFilters[i];
525 filterBuffer += wxT("|");
574c0bbf
JS
526 }
527
574c0bbf 528 // Replace | with \0
e031f1df 529 for (i = 0; i < filterBuffer.length(); i++ ) {
223d09f6
KB
530 if ( filterBuffer.GetChar(i) == wxT('|') ) {
531 filterBuffer[i] = wxT('\0');
e15e548b
VZ
532 }
533 }
2bda0e17 534
c9f78968 535 of.lpstrFilter = (LPTSTR)filterBuffer.wx_str();
cc42eb7a 536 of.nFilterIndex = m_filterIndex + 1;
2bda0e17
KB
537
538 //=== Setting defaultFileName >>=========================================
539
64accea5 540 wxStrlcpy(fileNameBuffer, m_fileName.c_str(), WXSIZEOF(fileNameBuffer));
2bda0e17 541
e15e548b 542 of.lpstrFile = fileNameBuffer; // holds returned filename
f6bcfd97 543 of.nMaxFile = wxMAXPATH;
2bda0e17 544
90bddb85 545 // we must set the default extension because otherwise Windows would check
e031f1df 546 // for the existing of a wrong file with wxFD_OVERWRITE_PROMPT (i.e. if the
90bddb85
VZ
547 // user types "foo" and the default extension is ".bar" we should force it
548 // to check for "foo.bar" existence and not "foo")
549 wxString defextBuffer; // we need it to be alive until GetSaveFileName()!
b014db05 550 if (HasFdFlag(wxFD_SAVE))
90bddb85 551 {
e0a050e3 552 const wxChar* extension = filterBuffer.wx_str();
90bddb85
VZ
553 int maxFilter = (int)(of.nFilterIndex*2L) - 1;
554
555 for( int i = 0; i < maxFilter; i++ ) // get extension
556 extension = extension + wxStrlen( extension ) + 1;
557
558 // use dummy name a to avoid assert in AppendExtension
559 defextBuffer = AppendExtension(wxT("a"), extension);
560 if (defextBuffer.StartsWith(wxT("a.")))
561 {
026ff75b 562 defextBuffer = defextBuffer.Mid(2); // remove "a."
90bddb85
VZ
563 of.lpstrDefExt = defextBuffer.c_str();
564 }
565 }
0b11099d 566
af1f0a76
VZ
567 // store off before the standard windows dialog can possibly change it
568 const wxString cwdOrig = wxGetCwd();
569
2bda0e17
KB
570 //== Execute FileDialog >>=================================================
571
fe048d77
VZ
572 if ( !ShowCommFileDialog(&of, m_windowStyle) )
573 return wxID_CANCEL;
2bda0e17 574
fe048d77
VZ
575 // GetOpenFileName will always change the current working directory on
576 // (according to MSDN) "Windows NT 4.0/2000/XP" because the flag
577 // OFN_NOCHANGEDIR has no effect. If the user did not specify
578 // wxFD_CHANGE_DIR let's restore the current working directory to what it
579 // was before the dialog was shown.
580 if ( msw_flags & OFN_NOCHANGEDIR )
f6bcfd97 581 {
fe048d77 582 wxSetWorkingDirectory(cwdOrig);
f6bcfd97 583 }
c46c1fb8 584
fe048d77 585 m_fileNames.Empty();
c61f4f6d 586
fe048d77 587 if ( ( HasFdFlag(wxFD_MULTIPLE) ) &&
c61f4f6d 588#if defined(OFN_EXPLORER)
fe048d77 589 ( fileNameBuffer[of.nFileOffset-1] == wxT('\0') )
c61f4f6d 590#else
fe048d77 591 ( fileNameBuffer[of.nFileOffset-1] == wxT(' ') )
c61f4f6d 592#endif // OFN_EXPLORER
fe048d77
VZ
593 )
594 {
c61f4f6d 595#if defined(OFN_EXPLORER)
fe048d77
VZ
596 m_dir = fileNameBuffer;
597 i = of.nFileOffset;
598 m_fileName = &fileNameBuffer[i];
599 m_fileNames.Add(m_fileName);
600 i += m_fileName.length() + 1;
c61f4f6d 601
fe048d77
VZ
602 while (fileNameBuffer[i] != wxT('\0'))
603 {
604 m_fileNames.Add(&fileNameBuffer[i]);
605 i += wxStrlen(&fileNameBuffer[i]) + 1;
606 }
c61f4f6d 607#else
9a83f860 608 wxStringTokenizer toke(fileNameBuffer, wxT(" \t\r\n"));
fe048d77
VZ
609 m_dir = toke.GetNextToken();
610 m_fileName = toke.GetNextToken();
611 m_fileNames.Add(m_fileName);
c61f4f6d 612
fe048d77
VZ
613 while (toke.HasMoreTokens())
614 m_fileNames.Add(toke.GetNextToken());
c61f4f6d
VZ
615#endif // OFN_EXPLORER
616
fe048d77 617 wxString dir(m_dir);
9a83f860
VZ
618 if ( m_dir.Last() != wxT('\\') )
619 dir += wxT('\\');
2bda0e17 620
fe048d77
VZ
621 m_path = dir + m_fileName;
622 m_filterIndex = (int)of.nFilterIndex - 1;
623 }
624 else
625 {
626 //=== Adding the correct extension >>=================================
2bda0e17 627
fe048d77 628 m_filterIndex = (int)of.nFilterIndex - 1;
2bda0e17 629
fe048d77
VZ
630 if ( !of.nFileExtension ||
631 (of.nFileExtension && fileNameBuffer[of.nFileExtension] == wxT('\0')) )
632 {
633 // User has typed a filename without an extension:
634 const wxChar* extension = filterBuffer.wx_str();
635 int maxFilter = (int)(of.nFilterIndex*2L) - 1;
a039ccbf 636
fe048d77
VZ
637 for( int i = 0; i < maxFilter; i++ ) // get extension
638 extension = extension + wxStrlen( extension ) + 1;
2bda0e17 639
fe048d77 640 m_fileName = AppendExtension(fileNameBuffer, extension);
e408bf52 641 wxStrlcpy(fileNameBuffer, m_fileName.c_str(), WXSIZEOF(fileNameBuffer));
c61f4f6d 642 }
fe048d77
VZ
643
644 m_path = fileNameBuffer;
645 m_fileName = wxFileNameFromPath(fileNameBuffer);
646 m_fileNames.Add(m_fileName);
647 m_dir = wxPathOnly(fileNameBuffer);
7cc98b3e 648 }
2bda0e17 649
fe048d77 650 return wxID_OK;
2bda0e17
KB
651
652}
653
3180bc0e 654#endif // wxUSE_FILEDLG && !(__SMARTPHONE__ && __WXWINCE__)