]> git.saurik.com Git - wxWidgets.git/blame - src/msw/filedlg.cpp
move parsing helpers, too (part of r59656)
[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);
159 if ( m_dir.Last() != _T('\\') )
160 dir += _T('\\');
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
2b5f62a0
VZ
177void wxFileDialog::SetPath(const wxString& path)
178{
179 wxString ext;
bd365871 180 wxFileName::SplitPath(path, &m_dir, &m_fileName, &ext);
2b5f62a0
VZ
181 if ( !ext.empty() )
182 m_fileName << _T('.') << ext;
183}
184
cb80db46 185void wxFileDialog::DoGetPosition(int *x, int *y) const
0b11099d 186{
cb80db46
VZ
187 if ( x )
188 *x = gs_rectDialog.x;
189 if ( y )
190 *y = gs_rectDialog.y;
0b11099d
VZ
191}
192
0b11099d
VZ
193void wxFileDialog::DoGetSize(int *width, int *height) const
194{
cb80db46
VZ
195 if ( width )
196 *width = gs_rectDialog.width;
197 if ( height )
198 *height = gs_rectDialog.height;
0b11099d
VZ
199}
200
cb80db46 201void wxFileDialog::DoMoveWindow(int x, int y, int WXUNUSED(w), int WXUNUSED(h))
0b11099d 202{
0b11099d
VZ
203 gs_rectDialog.x = x;
204 gs_rectDialog.y = y;
205
0a7b0229
VZ
206 // our HWND is only set when we're called from MSWOnInitDone(), test if
207 // this is the case
208 HWND hwnd = GetHwnd();
209 if ( hwnd )
210 {
211 // size of the dialog can't be changed because the controls are not
212 // laid out correctly then
213 ::SetWindowPos(hwnd, HWND_TOP, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
214 }
215 else // just remember that we were requested to move the window
216 {
217 m_bMovedWindow = true;
218
219 // if Centre() had been called before, it shouldn't be taken into
220 // account now
221 m_centreDir = 0;
222 }
223}
224
225void wxFileDialog::DoCentre(int dir)
226{
227 m_centreDir = dir;
228 m_bMovedWindow = true;
229
230 // it's unnecessary to do anything else at this stage as we'll redo it in
231 // MSWOnInitDone() anyhow
232}
233
234void wxFileDialog::MSWOnInitDone(WXHWND hDlg)
235{
236 // note the the dialog is the parent window: hDlg is a child of it when
237 // OFN_EXPLORER is used
238 HWND hFileDlg = ::GetParent((HWND)hDlg);
239
240 // set HWND so that our DoMoveWindow() works correctly
241 SetHWND((WXHWND)hFileDlg);
242
243 if ( m_centreDir )
244 {
245 // now we have the real dialog size, remember it
246 RECT rect;
247 GetWindowRect(hFileDlg, &rect);
248 gs_rectDialog = wxRectFromRECT(rect);
249
250 // and position the window correctly: notice that we must use the base
251 // class version as our own doesn't do anything except setting flags
252 wxFileDialogBase::DoCentre(m_centreDir);
253 }
254 else // need to just move it to the correct place
255 {
256 SetPosition(gs_rectDialog.GetPosition());
257 }
258
259 // we shouldn't destroy this HWND
260 SetHWND(NULL);
0b11099d
VZ
261}
262
fe048d77
VZ
263// helper used below in ShowCommFileDialog(): style is used to determine
264// whether to show the "Save file" dialog (if it contains wxFD_SAVE bit) or
265// "Open file" one; returns true on success or false on failure in which case
266// err is filled with the CDERR_XXX constant
c46c1fb8
VZ
267static bool DoShowCommFileDialog(OPENFILENAME *of, long style, DWORD *err)
268{
e031f1df 269 if ( style & wxFD_SAVE ? GetSaveFileName(of) : GetOpenFileName(of) )
c46c1fb8
VZ
270 return true;
271
272 if ( err )
273 {
274#ifdef __WXWINCE__
275 // according to MSDN, CommDlgExtendedError() should work under CE as
276 // well but apparently in practice it doesn't (anybody has more
277 // details?)
278 *err = GetLastError();
279#else
280 *err = CommDlgExtendedError();
281#endif
282 }
283
284 return false;
285}
286
04227efc
VZ
287// We want to use OPENFILENAME struct version 5 (Windows 2000/XP) but we don't
288// know if the OPENFILENAME declared in the currently used headers is a V5 or
289// V4 (smaller) one so we try to manually extend the struct in case it is the
290// old one.
5bb37216 291//
04227efc
VZ
292// We don't do this on Windows CE nor under Win64, however, as there are no
293// compilers with old headers for these architectures
294#if defined(__WXWINCE__) || defined(__WIN64__)
5bb37216
VZ
295 typedef OPENFILENAME wxOPENFILENAME;
296
04227efc
VZ
297 static const DWORD gs_ofStructSize = sizeof(OPENFILENAME);
298#else // !__WXWINCE__ || __WIN64__
299 #define wxTRY_SMALLER_OPENFILENAME
300
5bb37216
VZ
301 struct wxOPENFILENAME : public OPENFILENAME
302 {
303 // fields added in Windows 2000/XP comdlg32.dll version
304 void *pVoid;
305 DWORD dw1;
306 DWORD dw2;
307 };
308
309 // hardcoded sizeof(OPENFILENAME) in the Platform SDK: we have to do it
310 // because sizeof(OPENFILENAME) in the headers we use when compiling the
311 // library could be less if _WIN32_WINNT is not >= 0x500
312 static const DWORD wxOPENFILENAME_V5_SIZE = 88;
313
314 // this is hardcoded sizeof(OPENFILENAME_NT4) from Platform SDK
315 static const DWORD wxOPENFILENAME_V4_SIZE = 76;
5bb37216 316
04227efc
VZ
317 // always try the new one first
318 static DWORD gs_ofStructSize = wxOPENFILENAME_V5_SIZE;
319#endif // __WXWINCE__ || __WIN64__/!...
5bb37216 320
fe048d77
VZ
321static bool ShowCommFileDialog(OPENFILENAME *of, long style)
322{
323 DWORD errCode;
324 bool success = DoShowCommFileDialog(of, style, &errCode);
325
326#ifdef wxTRY_SMALLER_OPENFILENAME
327 // the system might be too old to support the new version file dialog
328 // boxes, try with the old size
329 if ( !success && errCode == CDERR_STRUCTSIZE &&
330 of->lStructSize != wxOPENFILENAME_V4_SIZE )
331 {
332 of->lStructSize = wxOPENFILENAME_V4_SIZE;
333
334 success = DoShowCommFileDialog(of, style, &errCode);
335
336 if ( success || !errCode )
337 {
338 // use this struct size for subsequent dialogs
339 gs_ofStructSize = of->lStructSize;
340 }
341 }
342#endif // wxTRY_SMALLER_OPENFILENAME
343
d4380371
VZ
344 if ( !success &&
345 // FNERR_INVALIDFILENAME is not defined under CE (besides we don't
346 // use CommDlgExtendedError() there anyhow)
347#ifndef __WXWINCE__
348 errCode == FNERR_INVALIDFILENAME &&
349#endif // !__WXWINCE__
350 of->lpstrFile[0] )
fe048d77
VZ
351 {
352 // this can happen if the default file name is invalid, try without it
353 // now
354 of->lpstrFile[0] = _T('\0');
355 success = DoShowCommFileDialog(of, style, &errCode);
356 }
357
358 if ( !success )
359 {
360 // common dialog failed - why?
361 if ( errCode != 0 )
362 {
363 wxLogError(_("File dialog failed with error code %0lx."), errCode);
364 }
365 //else: it was just cancelled
366
367 return false;
368 }
369
370 return true;
371}
372
d6dae1b4 373#ifndef __WXWINCE__
6fa6d659
VZ
374void wxFileDialog::MSWOnInitDialogHook(WXHWND hwnd)
375{
376 SetHWND(hwnd);
377
378 CreateExtraControl();
379
380 SetHWND(NULL);
381}
d6dae1b4 382#endif // __WXWINCE__
6fa6d659 383
c61f4f6d 384int wxFileDialog::ShowModal()
2bda0e17 385{
1f2f0331
VZ
386 HWND hWnd = 0;
387 if (m_parent) hWnd = (HWND) m_parent->GetHWND();
f6bcfd97
BP
388 if (!hWnd && wxTheApp->GetTopWindow())
389 hWnd = (HWND) wxTheApp->GetTopWindow()->GetHWND();
2bda0e17 390
f6bcfd97
BP
391 static wxChar fileNameBuffer [ wxMAXPATH ]; // the file-name
392 wxChar titleBuffer [ wxMAXFILE+1+wxMAXEXT ]; // the file-name, without path
2bda0e17 393
223d09f6
KB
394 *fileNameBuffer = wxT('\0');
395 *titleBuffer = wxT('\0');
2bda0e17 396
21416306 397 long msw_flags = OFN_HIDEREADONLY;
21416306 398
b014db05 399 if ( HasFdFlag(wxFD_FILE_MUST_EXIST) )
1f2f0331 400 msw_flags |= OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
0b11099d
VZ
401 /*
402 If the window has been moved the programmer is probably
403 trying to center or position it. Thus we set the callback
404 or hook function so that we can actually adjust the position.
405 Without moving or centering the dlg, it will just stay
406 in the upper left of the frame, it does not center
5bb37216 407 automatically.
0b11099d 408 */
6fa6d659 409 if (m_bMovedWindow || HasExtraControlCreator()) // we need these flags.
503528dc
JS
410 {
411 msw_flags |= OFN_EXPLORER|OFN_ENABLEHOOK;
412#ifndef __WXWINCE__
413 msw_flags |= OFN_ENABLESIZING;
414#endif
415 }
6e8aa701 416
b014db05 417 if ( HasFdFlag(wxFD_MULTIPLE) )
6e8aa701
VZ
418 {
419 // OFN_EXPLORER must always be specified with OFN_ALLOWMULTISELECT
420 msw_flags |= OFN_EXPLORER | OFN_ALLOWMULTISELECT;
421 }
422
e031f1df 423 // if wxFD_CHANGE_DIR flag is not given we shouldn't change the CWD which the
af1f0a76
VZ
424 // standard dialog does by default (notice that under NT it does it anyhow,
425 // OFN_NOCHANGEDIR or not, see below)
b014db05 426 if ( !HasFdFlag(wxFD_CHANGE_DIR) )
6e8aa701
VZ
427 {
428 msw_flags |= OFN_NOCHANGEDIR;
429 }
ac95e671 430
b014db05 431 if ( HasFdFlag(wxFD_OVERWRITE_PROMPT) )
99d1b93d
VZ
432 {
433 msw_flags |= OFN_OVERWRITEPROMPT;
434 }
ac95e671 435
5bb37216 436 wxOPENFILENAME of;
f6bcfd97
BP
437 wxZeroMemory(of);
438
5bb37216 439 of.lStructSize = gs_ofStructSize;
e15e548b 440 of.hwndOwner = hWnd;
e0a050e3 441 of.lpstrTitle = m_message.wx_str();
e15e548b 442 of.lpstrFileTitle = titleBuffer;
5bb37216 443 of.nMaxFileTitle = wxMAXFILE + 1 + wxMAXEXT;
2bda0e17 444
6fa6d659
VZ
445#ifndef __WXWINCE__
446 GlobalPtr hgbl;
447 if ( HasExtraControlCreator() )
448 {
449 msw_flags |= OFN_ENABLETEMPLATEHANDLE;
450
451 hgbl.Init(256, GMEM_ZEROINIT);
452 GlobalPtrLock hgblLock(hgbl);
453 LPDLGTEMPLATE lpdt = static_cast<LPDLGTEMPLATE>(hgblLock.Get());
454
455 // Define a dialog box.
456
457 lpdt->style = DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS;
458 lpdt->cdit = 0; // Number of controls
459 lpdt->x = 0;
460 lpdt->y = 0;
461
c10c791b
VZ
462 // convert the size of the extra controls to the dialog units
463 const wxSize extraSize = GetExtraControlSize();
464 const LONG baseUnits = ::GetDialogBaseUnits();
465 lpdt->cx = ::MulDiv(extraSize.x, 4, LOWORD(baseUnits));
466 lpdt->cy = ::MulDiv(extraSize.y, 8, HIWORD(baseUnits));
6fa6d659
VZ
467
468 // after the DLGTEMPLATE there are 3 additional WORDs for dialog menu,
469 // class and title, all three set to zeros.
470
471 of.hInstance = (HINSTANCE)lpdt;
472 }
473#endif // __WXWINCE__
474
0bc9b25e 475 // Convert forward slashes to backslashes (file selector doesn't like
99d1b93d
VZ
476 // forward slashes) and also squeeze multiple consecutive slashes into one
477 // as it doesn't like two backslashes in a row neither
0627d091 478
cbe874bd
WS
479 wxString dir;
480 size_t i, len = m_dir.length();
99d1b93d 481 dir.reserve(len);
0627d091 482 for ( i = 0; i < len; i++ )
99d1b93d
VZ
483 {
484 wxChar ch = m_dir[i];
485 switch ( ch )
486 {
487 case _T('/'):
488 // convert to backslash
489 ch = _T('\\');
490
491 // fall through
0bc9b25e 492
99d1b93d
VZ
493 case _T('\\'):
494 while ( i < len - 1 )
495 {
496 wxChar chNext = m_dir[i + 1];
497 if ( chNext != _T('\\') && chNext != _T('/') )
498 break;
499
04d93c3a
CE
500 // ignore the next one, unless it is at the start of a UNC path
501 if (i > 0)
502 i++;
503 else
0b11099d 504 break;
99d1b93d
VZ
505 }
506 // fall through
507
508 default:
509 // normal char
510 dir += ch;
511 }
512 }
513
514 of.lpstrInitialDir = dir.c_str();
2bda0e17 515
e15e548b 516 of.Flags = msw_flags;
0b11099d 517 of.lpfnHook = wxFileDialogHookFunction;
0a7b0229 518 of.lCustData = (LPARAM)this;
2bda0e17 519
daf32463 520 wxArrayString wildDescriptions, wildFilters;
2bda0e17 521
daf32463 522 size_t items = wxParseCommonDialogsFilter(m_wildCard, wildDescriptions, wildFilters);
2bda0e17 523
daf32463 524 wxASSERT_MSG( items > 0 , _T("empty wildcard list") );
2bda0e17 525
1f2f0331 526 wxString filterBuffer;
2bda0e17 527
daf32463
WS
528 for (i = 0; i < items ; i++)
529 {
530 filterBuffer += wildDescriptions[i];
531 filterBuffer += wxT("|");
532 filterBuffer += wildFilters[i];
533 filterBuffer += wxT("|");
574c0bbf
JS
534 }
535
574c0bbf 536 // Replace | with \0
e031f1df 537 for (i = 0; i < filterBuffer.length(); i++ ) {
223d09f6
KB
538 if ( filterBuffer.GetChar(i) == wxT('|') ) {
539 filterBuffer[i] = wxT('\0');
e15e548b
VZ
540 }
541 }
2bda0e17 542
c9f78968 543 of.lpstrFilter = (LPTSTR)filterBuffer.wx_str();
cc42eb7a 544 of.nFilterIndex = m_filterIndex + 1;
2bda0e17
KB
545
546 //=== Setting defaultFileName >>=========================================
547
64accea5 548 wxStrlcpy(fileNameBuffer, m_fileName.c_str(), WXSIZEOF(fileNameBuffer));
2bda0e17 549
e15e548b 550 of.lpstrFile = fileNameBuffer; // holds returned filename
f6bcfd97 551 of.nMaxFile = wxMAXPATH;
2bda0e17 552
90bddb85 553 // we must set the default extension because otherwise Windows would check
e031f1df 554 // for the existing of a wrong file with wxFD_OVERWRITE_PROMPT (i.e. if the
90bddb85
VZ
555 // user types "foo" and the default extension is ".bar" we should force it
556 // to check for "foo.bar" existence and not "foo")
557 wxString defextBuffer; // we need it to be alive until GetSaveFileName()!
b014db05 558 if (HasFdFlag(wxFD_SAVE))
90bddb85 559 {
e0a050e3 560 const wxChar* extension = filterBuffer.wx_str();
90bddb85
VZ
561 int maxFilter = (int)(of.nFilterIndex*2L) - 1;
562
563 for( int i = 0; i < maxFilter; i++ ) // get extension
564 extension = extension + wxStrlen( extension ) + 1;
565
566 // use dummy name a to avoid assert in AppendExtension
567 defextBuffer = AppendExtension(wxT("a"), extension);
568 if (defextBuffer.StartsWith(wxT("a.")))
569 {
026ff75b 570 defextBuffer = defextBuffer.Mid(2); // remove "a."
90bddb85
VZ
571 of.lpstrDefExt = defextBuffer.c_str();
572 }
573 }
0b11099d 574
af1f0a76
VZ
575 // store off before the standard windows dialog can possibly change it
576 const wxString cwdOrig = wxGetCwd();
577
2bda0e17
KB
578 //== Execute FileDialog >>=================================================
579
fe048d77
VZ
580 if ( !ShowCommFileDialog(&of, m_windowStyle) )
581 return wxID_CANCEL;
2bda0e17 582
fe048d77
VZ
583 // GetOpenFileName will always change the current working directory on
584 // (according to MSDN) "Windows NT 4.0/2000/XP" because the flag
585 // OFN_NOCHANGEDIR has no effect. If the user did not specify
586 // wxFD_CHANGE_DIR let's restore the current working directory to what it
587 // was before the dialog was shown.
588 if ( msw_flags & OFN_NOCHANGEDIR )
f6bcfd97 589 {
fe048d77 590 wxSetWorkingDirectory(cwdOrig);
f6bcfd97 591 }
c46c1fb8 592
fe048d77 593 m_fileNames.Empty();
c61f4f6d 594
fe048d77 595 if ( ( HasFdFlag(wxFD_MULTIPLE) ) &&
c61f4f6d 596#if defined(OFN_EXPLORER)
fe048d77 597 ( fileNameBuffer[of.nFileOffset-1] == wxT('\0') )
c61f4f6d 598#else
fe048d77 599 ( fileNameBuffer[of.nFileOffset-1] == wxT(' ') )
c61f4f6d 600#endif // OFN_EXPLORER
fe048d77
VZ
601 )
602 {
c61f4f6d 603#if defined(OFN_EXPLORER)
fe048d77
VZ
604 m_dir = fileNameBuffer;
605 i = of.nFileOffset;
606 m_fileName = &fileNameBuffer[i];
607 m_fileNames.Add(m_fileName);
608 i += m_fileName.length() + 1;
c61f4f6d 609
fe048d77
VZ
610 while (fileNameBuffer[i] != wxT('\0'))
611 {
612 m_fileNames.Add(&fileNameBuffer[i]);
613 i += wxStrlen(&fileNameBuffer[i]) + 1;
614 }
c61f4f6d 615#else
fe048d77
VZ
616 wxStringTokenizer toke(fileNameBuffer, _T(" \t\r\n"));
617 m_dir = toke.GetNextToken();
618 m_fileName = toke.GetNextToken();
619 m_fileNames.Add(m_fileName);
c61f4f6d 620
fe048d77
VZ
621 while (toke.HasMoreTokens())
622 m_fileNames.Add(toke.GetNextToken());
c61f4f6d
VZ
623#endif // OFN_EXPLORER
624
fe048d77
VZ
625 wxString dir(m_dir);
626 if ( m_dir.Last() != _T('\\') )
627 dir += _T('\\');
2bda0e17 628
fe048d77
VZ
629 m_path = dir + m_fileName;
630 m_filterIndex = (int)of.nFilterIndex - 1;
631 }
632 else
633 {
634 //=== Adding the correct extension >>=================================
2bda0e17 635
fe048d77 636 m_filterIndex = (int)of.nFilterIndex - 1;
2bda0e17 637
fe048d77
VZ
638 if ( !of.nFileExtension ||
639 (of.nFileExtension && fileNameBuffer[of.nFileExtension] == wxT('\0')) )
640 {
641 // User has typed a filename without an extension:
642 const wxChar* extension = filterBuffer.wx_str();
643 int maxFilter = (int)(of.nFilterIndex*2L) - 1;
a039ccbf 644
fe048d77
VZ
645 for( int i = 0; i < maxFilter; i++ ) // get extension
646 extension = extension + wxStrlen( extension ) + 1;
2bda0e17 647
fe048d77 648 m_fileName = AppendExtension(fileNameBuffer, extension);
e408bf52 649 wxStrlcpy(fileNameBuffer, m_fileName.c_str(), WXSIZEOF(fileNameBuffer));
c61f4f6d 650 }
fe048d77
VZ
651
652 m_path = fileNameBuffer;
653 m_fileName = wxFileNameFromPath(fileNameBuffer);
654 m_fileNames.Add(m_fileName);
655 m_dir = wxPathOnly(fileNameBuffer);
7cc98b3e 656 }
2bda0e17 657
fe048d77 658 return wxID_OK;
2bda0e17
KB
659
660}
661
3180bc0e 662#endif // wxUSE_FILEDLG && !(__SMARTPHONE__ && __WXWINCE__)