/[pcsx2_0.9.7]/branch/r3113_0.9.7_beta/3rdparty/wxWidgets/src/msw/filedlg.cpp
ViewVC logotype

Contents of /branch/r3113_0.9.7_beta/3rdparty/wxWidgets/src/msw/filedlg.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 32 - (show annotations) (download)
Tue Sep 7 03:29:01 2010 UTC (9 years, 11 months ago) by william
File size: 18219 byte(s)
branching from upstream revision (http://pcsx2.googlecode.com/svn/trunk
): r3113 to
https://svn.netsolutions.dnsalias.com/websvn/ps2/pcsx2/pcsx2_0.9.7/branch/r3113_0.9.7_beta
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/filedlg.cpp
3 // Purpose: wxFileDialog
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id: filedlg.cpp 55642 2008-09-15 13:33:35Z VZ $
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
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
27 #if wxUSE_FILEDLG && !(defined(__SMARTPHONE__) && defined(__WXWINCE__))
28
29 #include "wx/filedlg.h"
30
31 #ifndef WX_PRECOMP
32 #include "wx/msw/wrapcdlg.h"
33 #include "wx/msw/missing.h"
34 #include "wx/utils.h"
35 #include "wx/msgdlg.h"
36 #include "wx/filefn.h"
37 #include "wx/intl.h"
38 #include "wx/log.h"
39 #include "wx/app.h"
40 #include "wx/math.h"
41 #endif
42
43 #include <stdlib.h>
44 #include <string.h>
45
46 #include "wx/filename.h"
47 #include "wx/tokenzr.h"
48
49 // ----------------------------------------------------------------------------
50 // constants
51 // ----------------------------------------------------------------------------
52
53 #ifdef __WIN32__
54 # define wxMAXPATH 65534
55 #else
56 # define wxMAXPATH 1024
57 #endif
58
59 # define wxMAXFILE 1024
60
61 # define wxMAXEXT 5
62
63 // ----------------------------------------------------------------------------
64 // globals
65 // ----------------------------------------------------------------------------
66
67 // standard dialog size
68 static wxRect gs_rectDialog(0, 0, 428, 266);
69
70 // ============================================================================
71 // implementation
72 // ============================================================================
73
74 IMPLEMENT_CLASS(wxFileDialog, wxFileDialogBase)
75
76 // ----------------------------------------------------------------------------
77 // hook function for moving the dialog
78 // ----------------------------------------------------------------------------
79
80 UINT_PTR APIENTRY
81 wxFileDialogHookFunction(HWND hDlg,
82 UINT iMsg,
83 WPARAM WXUNUSED(wParam),
84 LPARAM lParam)
85 {
86 switch ( iMsg )
87 {
88 case WM_NOTIFY:
89 {
90 OFNOTIFY *pNotifyCode = wx_reinterpret_cast(OFNOTIFY *, lParam);
91 if ( pNotifyCode->hdr.code == CDN_INITDONE )
92 {
93 // note that we need to move the parent window: hDlg is a
94 // child of it when OFN_EXPLORER is used
95 ::SetWindowPos
96 (
97 ::GetParent(hDlg),
98 HWND_TOP,
99 gs_rectDialog.x, gs_rectDialog.y,
100 0, 0,
101 SWP_NOZORDER | SWP_NOSIZE
102 );
103 }
104 }
105 break;
106
107 case WM_DESTROY:
108 // reuse the position used for the dialog the next time by default
109 //
110 // NB: at least under Windows 2003 this is useless as after the
111 // first time it's shown the dialog always remembers its size
112 // and position itself and ignores any later SetWindowPos calls
113 wxCopyRECTToRect(wxGetWindowRect(::GetParent(hDlg)), gs_rectDialog);
114 break;
115 }
116
117 // do the default processing
118 return 0;
119 }
120
121 // ----------------------------------------------------------------------------
122 // wxFileDialog
123 // ----------------------------------------------------------------------------
124
125 wxFileDialog::wxFileDialog(wxWindow *parent,
126 const wxString& message,
127 const wxString& defaultDir,
128 const wxString& defaultFileName,
129 const wxString& wildCard,
130 long style,
131 const wxPoint& pos,
132 const wxSize& sz,
133 const wxString& name)
134 : wxFileDialogBase(parent, message, defaultDir, defaultFileName,
135 wildCard, style, pos, sz, name)
136
137 {
138 // NB: all style checks are done by wxFileDialogBase::Create
139
140 m_bMovedWindow = false;
141
142 // Must set to zero, otherwise the wx routines won't size the window
143 // the second time you call the file dialog, because it thinks it is
144 // already at the requested size.. (when centering)
145 gs_rectDialog.x =
146 gs_rectDialog.y = 0;
147
148 }
149 void wxFileDialog::GetPaths(wxArrayString& paths) const
150 {
151 paths.Empty();
152
153 wxString dir(m_dir);
154 if ( m_dir.Last() != _T('\\') )
155 dir += _T('\\');
156
157 size_t count = m_fileNames.GetCount();
158 for ( size_t n = 0; n < count; n++ )
159 {
160 if (wxFileName(m_fileNames[n]).IsAbsolute())
161 paths.Add(m_fileNames[n]);
162 else
163 paths.Add(dir + m_fileNames[n]);
164 }
165 }
166
167 void wxFileDialog::GetFilenames(wxArrayString& files) const
168 {
169 files = m_fileNames;
170 }
171
172 void wxFileDialog::SetPath(const wxString& path)
173 {
174 wxString ext;
175 wxSplitPath(path, &m_dir, &m_fileName, &ext);
176 if ( !ext.empty() )
177 m_fileName << _T('.') << ext;
178 }
179
180 void wxFileDialog::DoGetPosition(int *x, int *y) const
181 {
182 if ( x )
183 *x = gs_rectDialog.x;
184 if ( y )
185 *y = gs_rectDialog.y;
186 }
187
188
189 void wxFileDialog::DoGetSize(int *width, int *height) const
190 {
191 if ( width )
192 *width = gs_rectDialog.width;
193 if ( height )
194 *height = gs_rectDialog.height;
195 }
196
197 void wxFileDialog::DoMoveWindow(int x, int y, int WXUNUSED(w), int WXUNUSED(h))
198 {
199 m_bMovedWindow = true;
200
201 gs_rectDialog.x = x;
202 gs_rectDialog.y = y;
203
204 // size of the dialog can't be changed because the controls are not laid
205 // out correctly then
206 }
207
208 // helper used below in ShowModal(): style is used to determine whether to show
209 // the "Save file" dialog (if it contains wxFD_SAVE bit) or "Open file" one;
210 // returns true on success or false on failure in which case err is filled with
211 // the CDERR_XXX constant
212 static bool DoShowCommFileDialog(OPENFILENAME *of, long style, DWORD *err)
213 {
214 if ( style & wxFD_SAVE ? GetSaveFileName(of) : GetOpenFileName(of) )
215 return true;
216
217 if ( err )
218 {
219 #ifdef __WXWINCE__
220 // according to MSDN, CommDlgExtendedError() should work under CE as
221 // well but apparently in practice it doesn't (anybody has more
222 // details?)
223 *err = GetLastError();
224 #else
225 *err = CommDlgExtendedError();
226 #endif
227 }
228
229 return false;
230 }
231
232 // We want to use OPENFILENAME struct version 5 (Windows 2000/XP) but we don't
233 // know if the OPENFILENAME declared in the currently used headers is a V5 or
234 // V4 (smaller) one so we try to manually extend the struct in case it is the
235 // old one.
236 //
237 // We don't do this on Windows CE nor under Win64, however, as there are no
238 // compilers with old headers for these architectures
239 #if defined(__WXWINCE__) || defined(__WIN64__)
240 typedef OPENFILENAME wxOPENFILENAME;
241
242 static const DWORD gs_ofStructSize = sizeof(OPENFILENAME);
243 #else // !__WXWINCE__ || __WIN64__
244 #define wxTRY_SMALLER_OPENFILENAME
245
246 struct wxOPENFILENAME : public OPENFILENAME
247 {
248 // fields added in Windows 2000/XP comdlg32.dll version
249 void *pVoid;
250 DWORD dw1;
251 DWORD dw2;
252 };
253
254 // hardcoded sizeof(OPENFILENAME) in the Platform SDK: we have to do it
255 // because sizeof(OPENFILENAME) in the headers we use when compiling the
256 // library could be less if _WIN32_WINNT is not >= 0x500
257 static const DWORD wxOPENFILENAME_V5_SIZE = 88;
258
259 // this is hardcoded sizeof(OPENFILENAME_NT4) from Platform SDK
260 static const DWORD wxOPENFILENAME_V4_SIZE = 76;
261
262 // always try the new one first
263 static DWORD gs_ofStructSize = wxOPENFILENAME_V5_SIZE;
264 #endif // __WXWINCE__ || __WIN64__/!...
265
266 int wxFileDialog::ShowModal()
267 {
268 HWND hWnd = 0;
269 if (m_parent) hWnd = (HWND) m_parent->GetHWND();
270 if (!hWnd && wxTheApp->GetTopWindow())
271 hWnd = (HWND) wxTheApp->GetTopWindow()->GetHWND();
272
273 static wxChar fileNameBuffer [ wxMAXPATH ]; // the file-name
274 wxChar titleBuffer [ wxMAXFILE+1+wxMAXEXT ]; // the file-name, without path
275
276 *fileNameBuffer = wxT('\0');
277 *titleBuffer = wxT('\0');
278
279 #if WXWIN_COMPATIBILITY_2_4
280 long msw_flags = 0;
281 if ( HasFdFlag(wxHIDE_READONLY) || HasFdFlag(wxFD_SAVE) )
282 msw_flags |= OFN_HIDEREADONLY;
283 #else
284 long msw_flags = OFN_HIDEREADONLY;
285 #endif
286
287 if ( HasFdFlag(wxFD_FILE_MUST_EXIST) )
288 msw_flags |= OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
289 /*
290 If the window has been moved the programmer is probably
291 trying to center or position it. Thus we set the callback
292 or hook function so that we can actually adjust the position.
293 Without moving or centering the dlg, it will just stay
294 in the upper left of the frame, it does not center
295 automatically.
296 */
297 if (m_bMovedWindow) // we need these flags.
298 {
299 msw_flags |= OFN_EXPLORER|OFN_ENABLEHOOK;
300 #ifndef __WXWINCE__
301 msw_flags |= OFN_ENABLESIZING;
302 #endif
303 }
304
305 if ( HasFdFlag(wxFD_MULTIPLE) )
306 {
307 // OFN_EXPLORER must always be specified with OFN_ALLOWMULTISELECT
308 msw_flags |= OFN_EXPLORER | OFN_ALLOWMULTISELECT;
309 }
310
311 // if wxFD_CHANGE_DIR flag is not given we shouldn't change the CWD which the
312 // standard dialog does by default (notice that under NT it does it anyhow,
313 // OFN_NOCHANGEDIR or not, see below)
314 if ( !HasFdFlag(wxFD_CHANGE_DIR) )
315 {
316 msw_flags |= OFN_NOCHANGEDIR;
317 }
318
319 if ( HasFdFlag(wxFD_OVERWRITE_PROMPT) )
320 {
321 msw_flags |= OFN_OVERWRITEPROMPT;
322 }
323
324 wxOPENFILENAME of;
325 wxZeroMemory(of);
326
327 of.lStructSize = gs_ofStructSize;
328 of.hwndOwner = hWnd;
329 of.lpstrTitle = WXSTRINGCAST m_message;
330 of.lpstrFileTitle = titleBuffer;
331 of.nMaxFileTitle = wxMAXFILE + 1 + wxMAXEXT;
332
333 // Convert forward slashes to backslashes (file selector doesn't like
334 // forward slashes) and also squeeze multiple consecutive slashes into one
335 // as it doesn't like two backslashes in a row neither
336
337 wxString dir;
338 size_t i, len = m_dir.length();
339 dir.reserve(len);
340 for ( i = 0; i < len; i++ )
341 {
342 wxChar ch = m_dir[i];
343 switch ( ch )
344 {
345 case _T('/'):
346 // convert to backslash
347 ch = _T('\\');
348
349 // fall through
350
351 case _T('\\'):
352 while ( i < len - 1 )
353 {
354 wxChar chNext = m_dir[i + 1];
355 if ( chNext != _T('\\') && chNext != _T('/') )
356 break;
357
358 // ignore the next one, unless it is at the start of a UNC path
359 if (i > 0)
360 i++;
361 else
362 break;
363 }
364 // fall through
365
366 default:
367 // normal char
368 dir += ch;
369 }
370 }
371
372 of.lpstrInitialDir = dir.c_str();
373
374 of.Flags = msw_flags;
375 of.lpfnHook = wxFileDialogHookFunction;
376
377 wxArrayString wildDescriptions, wildFilters;
378
379 size_t items = wxParseCommonDialogsFilter(m_wildCard, wildDescriptions, wildFilters);
380
381 wxASSERT_MSG( items > 0 , _T("empty wildcard list") );
382
383 wxString filterBuffer;
384
385 for (i = 0; i < items ; i++)
386 {
387 filterBuffer += wildDescriptions[i];
388 filterBuffer += wxT("|");
389 filterBuffer += wildFilters[i];
390 filterBuffer += wxT("|");
391 }
392
393 // Replace | with \0
394 for (i = 0; i < filterBuffer.length(); i++ ) {
395 if ( filterBuffer.GetChar(i) == wxT('|') ) {
396 filterBuffer[i] = wxT('\0');
397 }
398 }
399
400 of.lpstrFilter = (LPTSTR)filterBuffer.c_str();
401 of.nFilterIndex = m_filterIndex + 1;
402
403 //=== Setting defaultFileName >>=========================================
404
405 wxStrncpy( fileNameBuffer, (const wxChar *)m_fileName, wxMAXPATH-1 );
406 fileNameBuffer[ wxMAXPATH-1 ] = wxT('\0');
407
408 of.lpstrFile = fileNameBuffer; // holds returned filename
409 of.nMaxFile = wxMAXPATH;
410
411 // we must set the default extension because otherwise Windows would check
412 // for the existing of a wrong file with wxFD_OVERWRITE_PROMPT (i.e. if the
413 // user types "foo" and the default extension is ".bar" we should force it
414 // to check for "foo.bar" existence and not "foo")
415 wxString defextBuffer; // we need it to be alive until GetSaveFileName()!
416 if (HasFdFlag(wxFD_SAVE))
417 {
418 const wxChar* extension = filterBuffer;
419 int maxFilter = (int)(of.nFilterIndex*2L) - 1;
420
421 for( int i = 0; i < maxFilter; i++ ) // get extension
422 extension = extension + wxStrlen( extension ) + 1;
423
424 // use dummy name a to avoid assert in AppendExtension
425 defextBuffer = AppendExtension(wxT("a"), extension);
426 if (defextBuffer.StartsWith(wxT("a.")))
427 {
428 defextBuffer = defextBuffer.Mid(2); // remove "a."
429 of.lpstrDefExt = defextBuffer.c_str();
430 }
431 }
432
433 // store off before the standard windows dialog can possibly change it
434 const wxString cwdOrig = wxGetCwd();
435
436 //== Execute FileDialog >>=================================================
437
438 DWORD errCode;
439 bool success = DoShowCommFileDialog(&of, m_windowStyle, &errCode);
440
441 if ( !success &&
442 // FNERR_INVALIDFILENAME is not defined under CE (besides we don't
443 // use CommDlgExtendedError() there anyhow)
444 #ifndef __WXWINCE__
445 errCode == FNERR_INVALIDFILENAME &&
446 #endif // !__WXWINCE__
447 of.lpstrFile[0] )
448 {
449 // this can happen if the default file name is invalid, try without it now
450 of.lpstrFile[0] = _T('\0');
451 success = DoShowCommFileDialog(&of, m_windowStyle, &errCode);
452 }
453
454 #ifdef wxTRY_SMALLER_OPENFILENAME
455 // the system might be too old to support the new version file dialog
456 // boxes, try with the old size
457 if ( !success && errCode == CDERR_STRUCTSIZE &&
458 of.lStructSize != wxOPENFILENAME_V4_SIZE )
459 {
460 of.lStructSize = wxOPENFILENAME_V4_SIZE;
461
462 success = DoShowCommFileDialog(&of, m_windowStyle, &errCode);
463
464 if ( success || !errCode )
465 {
466 // use this struct size for subsequent dialogs
467 gs_ofStructSize = of.lStructSize;
468 }
469 }
470 #endif // wxTRY_SMALLER_OPENFILENAME
471
472 if ( success )
473 {
474 // GetOpenFileName will always change the current working directory on
475 // (according to MSDN) "Windows NT 4.0/2000/XP" because the flag
476 // OFN_NOCHANGEDIR has no effect. If the user did not specify
477 // wxFD_CHANGE_DIR let's restore the current working directory to what it
478 // was before the dialog was shown.
479 if ( msw_flags & OFN_NOCHANGEDIR )
480 {
481 wxSetWorkingDirectory(cwdOrig);
482 }
483
484 m_fileNames.Empty();
485
486 if ( ( HasFdFlag(wxFD_MULTIPLE) ) &&
487 #if defined(OFN_EXPLORER)
488 ( fileNameBuffer[of.nFileOffset-1] == wxT('\0') )
489 #else
490 ( fileNameBuffer[of.nFileOffset-1] == wxT(' ') )
491 #endif // OFN_EXPLORER
492 )
493 {
494 #if defined(OFN_EXPLORER)
495 m_dir = fileNameBuffer;
496 i = of.nFileOffset;
497 m_fileName = &fileNameBuffer[i];
498 m_fileNames.Add(m_fileName);
499 i += m_fileName.length() + 1;
500
501 while (fileNameBuffer[i] != wxT('\0'))
502 {
503 m_fileNames.Add(&fileNameBuffer[i]);
504 i += wxStrlen(&fileNameBuffer[i]) + 1;
505 }
506 #else
507 wxStringTokenizer toke(fileNameBuffer, _T(" \t\r\n"));
508 m_dir = toke.GetNextToken();
509 m_fileName = toke.GetNextToken();
510 m_fileNames.Add(m_fileName);
511
512 while (toke.HasMoreTokens())
513 m_fileNames.Add(toke.GetNextToken());
514 #endif // OFN_EXPLORER
515
516 wxString dir(m_dir);
517 if ( m_dir.Last() != _T('\\') )
518 dir += _T('\\');
519
520 m_path = dir + m_fileName;
521 m_filterIndex = (int)of.nFilterIndex - 1;
522 }
523 else
524 {
525 //=== Adding the correct extension >>=================================
526
527 m_filterIndex = (int)of.nFilterIndex - 1;
528
529 if ( !of.nFileExtension ||
530 (of.nFileExtension && fileNameBuffer[of.nFileExtension] == wxT('\0')) )
531 {
532 // User has typed a filename without an extension:
533 const wxChar* extension = filterBuffer;
534 int maxFilter = (int)(of.nFilterIndex*2L) - 1;
535
536 for( int i = 0; i < maxFilter; i++ ) // get extension
537 extension = extension + wxStrlen( extension ) + 1;
538
539 m_fileName = AppendExtension(fileNameBuffer, extension);
540 wxStrncpy(fileNameBuffer, m_fileName.c_str(), wxMin(m_fileName.length(), wxMAXPATH-1));
541 fileNameBuffer[wxMin(m_fileName.length(), wxMAXPATH-1)] = wxT('\0');
542 }
543
544 m_path = fileNameBuffer;
545 m_fileName = wxFileNameFromPath(fileNameBuffer);
546 m_fileNames.Add(m_fileName);
547 m_dir = wxPathOnly(fileNameBuffer);
548 }
549 }
550 #ifdef __WXDEBUG__
551 else
552 {
553 // common dialog failed - why?
554 if ( errCode != 0 )
555 {
556 // this msg is only for developers so don't translate it
557 wxLogError(wxT("Common dialog failed with error code %0lx."),
558 errCode);
559 }
560 //else: it was just cancelled
561 }
562 #endif // __WXDEBUG__
563
564 return success ? wxID_OK : wxID_CANCEL;
565
566 }
567
568 #endif // wxUSE_FILEDLG && !(__SMARTPHONE__ && __WXWINCE__)

  ViewVC Help
Powered by ViewVC 1.1.22