]>
Commit | Line | Data |
---|---|---|
0e320a79 DW |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: filedlg.cpp | |
3 | // Purpose: wxFileDialog | |
f0a56ab0 | 4 | // Author: David Webster |
0e320a79 | 5 | // Modified by: |
f0a56ab0 | 6 | // Created: 10/05/99 |
0e320a79 | 7 | // RCS-ID: $Id$ |
f0a56ab0 | 8 | // Copyright: (c) David Webster |
0e320a79 DW |
9 | // Licence: wxWindows licence |
10 | ///////////////////////////////////////////////////////////////////////////// | |
11 | ||
fb46a9a6 DW |
12 | // For compilers that support precompilation, includes "wx.h". |
13 | #include "wx/wxprec.h" | |
14 | ||
15 | #ifdef __BORLANDC__ | |
16 | #pragma hdrstop | |
17 | #endif | |
18 | ||
19 | #ifndef WX_PRECOMP | |
fb46a9a6 DW |
20 | #include "wx/utils.h" |
21 | #include "wx/msgdlg.h" | |
22 | #include "wx/dialog.h" | |
23 | #include "wx/filedlg.h" | |
24 | #include "wx/intl.h" | |
25 | #include "wx/log.h" | |
4efd4259 | 26 | #include "wx/app.h" |
fb46a9a6 DW |
27 | #endif |
28 | ||
29 | #define INCL_PM | |
30 | #include <os2.h> | |
31 | ||
32 | #include "wx/os2/private.h" | |
33 | ||
34 | #include <math.h> | |
35 | #include <stdlib.h> | |
36 | #include <string.h> | |
0e320a79 | 37 | |
4efd4259 DW |
38 | #include "wx/tokenzr.h" |
39 | ||
40 | #define wxMAXPATH 1024 | |
41 | #define wxMAXFILE 1024 | |
42 | #define wxMAXEXT 5 | |
43 | ||
44 | #ifndef MAXPATH | |
45 | # define MAXPATH 400 | |
46 | #endif | |
47 | ||
48 | #ifndef MAXDRIVE | |
49 | # define MAXDRIVE 3 | |
50 | #endif | |
51 | ||
52 | #ifndef MAXFILE | |
53 | # define MAXFILE 9 | |
54 | #endif | |
55 | ||
56 | #ifndef MAXEXT | |
57 | # define MAXEXT 5 | |
58 | #endif | |
0e320a79 | 59 | IMPLEMENT_CLASS(wxFileDialog, wxDialog) |
0e320a79 | 60 | |
4efd4259 DW |
61 | // ---------------------------------------------------------------------------- |
62 | // global functions | |
63 | // ---------------------------------------------------------------------------- | |
64 | ||
65 | wxString wxFileSelector( | |
66 | const char* pzTitle | |
67 | , const char* pzDefaultDir | |
68 | , const char* pzDefaultFileName | |
69 | , const char* pzDefaultExtension | |
70 | , const char* pzFilter | |
71 | , int nFlags | |
72 | , wxWindow* pParent | |
73 | , int nX | |
74 | , int nY | |
75 | ) | |
0e320a79 | 76 | { |
4efd4259 DW |
77 | wxString sFilter(""); |
78 | wxString sDefaultDirString; | |
79 | wxString sDefaultFilenameString; | |
80 | ||
81 | // | |
82 | // If there's a default extension specified but no filter, we create | |
83 | // a suitable filter. | |
84 | // | |
85 | if (pzDefaultExtension && !pzFilter) | |
86 | sFilter = wxString("*.") + wxString(pzDefaultExtension); | |
87 | else if (pzFilter) | |
88 | sFilter = pzFilter; | |
89 | ||
90 | if (pzDefaultDir) | |
91 | sDefaultDirString = pzDefaultDir; | |
0e320a79 | 92 | else |
4efd4259 | 93 | sDefaultDirString = ""; |
0e320a79 | 94 | |
4efd4259 DW |
95 | if (pzDefaultFileName) |
96 | sDefaultFilenameString = pzDefaultFileName; | |
0e320a79 | 97 | else |
4efd4259 DW |
98 | sDefaultFilenameString = ""; |
99 | ||
100 | wxFileDialog vFileDialog( pParent | |
101 | ,pzTitle | |
102 | ,sDefaultDirString | |
103 | ,sDefaultFilenameString | |
104 | ,sFilter | |
105 | ,nFlags | |
106 | ,wxPoint(nX, nY) | |
107 | ); | |
108 | ||
109 | if (wxStrlen(pzDefaultExtension) != 0) | |
110 | { | |
111 | int nFilterFind = 0; | |
112 | int nFilterIndex = 0; | |
113 | ||
114 | for (unsigned int i = 0; i < sFilter.Len(); i++) | |
115 | { | |
116 | if (sFilter.GetChar(i) == wxT('|')) | |
117 | { | |
118 | // | |
119 | // Save the start index of the new filter | |
120 | unsigned int uIs = i++; | |
0e320a79 | 121 | |
4efd4259 DW |
122 | // |
123 | // Find the end of the filter | |
124 | // | |
125 | for(; i < sFilter.Len(); i++) | |
126 | { | |
127 | if(sFilter[i] == wxT('|')) | |
128 | break; | |
129 | } | |
0e320a79 | 130 | |
4efd4259 DW |
131 | if( i - uIs - 1 > 0 && uIs + 1 < sFilter.Len() ) |
132 | { | |
133 | if(sFilter.Mid(uIs + 1, i - uIs - 1).Contains(pzDefaultExtension)) | |
134 | { | |
135 | nFilterFind = nFilterIndex; | |
136 | break; | |
137 | } | |
138 | } | |
139 | nFilterIndex++; | |
140 | } | |
141 | } | |
142 | vFileDialog.SetFilterIndex(nFilterFind); | |
143 | } | |
144 | if (vFileDialog.ShowModal() == wxID_OK) | |
0e320a79 | 145 | { |
4efd4259 | 146 | return vFileDialog.GetPath(); |
0e320a79 DW |
147 | } |
148 | else | |
149 | return wxEmptyString; | |
4efd4259 DW |
150 | } // end of wxFileSelector |
151 | ||
152 | wxString wxFileSelectorEx ( | |
153 | const char* pzTitle | |
154 | , const char* pzDefaultDir | |
155 | , const char* pzDefaultFileName | |
156 | , int* pnDefaultFilterIndex | |
157 | , const char* pzFilter | |
158 | , int nFlags | |
159 | , wxWindow* pParent | |
160 | , int nX | |
161 | , int nY | |
162 | ) | |
0e320a79 | 163 | { |
4efd4259 DW |
164 | wxFileDialog vFileDialog( pParent |
165 | ,pzTitle ? pzTitle : "" | |
166 | ,pzDefaultDir ? pzDefaultDir : "" | |
167 | ,pzDefaultFileName ? pzDefaultFileName : "" | |
168 | ,pzFilter ? pzFilter : "" | |
169 | ,nFlags | |
170 | ,wxPoint(nX, nY) | |
171 | ); | |
0e320a79 | 172 | |
4efd4259 | 173 | if (vFileDialog.ShowModal() == wxID_OK) |
0e320a79 | 174 | { |
4efd4259 DW |
175 | *pnDefaultFilterIndex = vFileDialog.GetFilterIndex(); |
176 | return vFileDialog.GetPath(); | |
0e320a79 DW |
177 | } |
178 | else | |
179 | return wxEmptyString; | |
4efd4259 DW |
180 | } // end of wxFileSelectorEx |
181 | ||
182 | // ---------------------------------------------------------------------------- | |
183 | // CLASS wxFileDialog | |
184 | // ---------------------------------------------------------------------------- | |
185 | ||
186 | wxFileDialog::wxFileDialog ( | |
187 | wxWindow* pParent | |
188 | , const wxString& rsMessage | |
189 | , const wxString& rsDefaultDir | |
190 | , const wxString& rsDefaultFileName | |
191 | , const wxString& rsWildCard | |
192 | , long lStyle | |
193 | , const wxPoint& rPos | |
194 | ) | |
0e320a79 | 195 | { |
4efd4259 DW |
196 | m_sMessage = rsMessage; |
197 | m_lDialogStyle = lStyle; | |
198 | if ((m_lDialogStyle & wxMULTIPLE) && (m_lDialogStyle & wxSAVE)) | |
199 | m_lDialogStyle &= ~wxMULTIPLE; | |
200 | m_pParent = pParent; | |
201 | m_sPath = ""; | |
202 | m_sFileName = rsDefaultFileName; | |
203 | m_sDir = rsDefaultDir; | |
204 | m_sWildCard = rsWildCard; | |
205 | m_nFilterIndex = 1; | |
206 | m_vPos = rPos; | |
207 | } // end of wxFileDialog::wxFileDialog | |
208 | ||
209 | void wxFileDialog::GetPaths ( | |
210 | wxArrayString& rasPaths | |
211 | ) const | |
212 | { | |
213 | wxString sDir(m_sDir); | |
214 | size_t nCount = m_asFileNames.GetCount(); | |
215 | ||
216 | rasPaths.Empty(); | |
217 | if (m_sDir.Last() != _T('\\')) | |
218 | sDir += _T('\\'); | |
219 | ||
220 | for ( size_t n = 0; n < nCount; n++ ) | |
221 | { | |
222 | rasPaths.Add(sDir + m_asFileNames[n]); | |
223 | } | |
224 | } // end of wxFileDialog::GetPaths | |
0e320a79 DW |
225 | |
226 | int wxFileDialog::ShowModal() | |
227 | { | |
4efd4259 DW |
228 | wxString sTheFilter; |
229 | wxString sFilterBuffer; | |
b93f4bb9 | 230 | wxChar* pzFilterBuffer; |
4efd4259 DW |
231 | static wxChar zFileNameBuffer[wxMAXPATH]; // the file-name |
232 | HWND hWnd = 0; | |
233 | wxChar zTitleBuffer[wxMAXFILE + 1 + wxMAXEXT]; // the file-name, without path | |
b93f4bb9 DW |
234 | wxString sDir; |
235 | size_t i; | |
4efd4259 | 236 | size_t nLen = m_sDir.length(); |
b93f4bb9 | 237 | int nCount = 0; |
4efd4259 DW |
238 | FILEDLG vFileDlg; |
239 | ULONG lFlags = 0L; | |
240 | ||
241 | memset(&vFileDlg, '\0', sizeof(FILEDLG)); | |
242 | if (m_pParent) | |
243 | hWnd = (HWND) m_pParent->GetHWND(); | |
244 | if (!hWnd && wxTheApp->GetTopWindow()) | |
245 | hWnd = (HWND) wxTheApp->GetTopWindow()->GetHWND(); | |
246 | ||
247 | ||
248 | *zFileNameBuffer = wxT('\0'); | |
249 | *zTitleBuffer = wxT('\0'); | |
250 | ||
b93f4bb9 DW |
251 | if (m_lDialogStyle & wxSAVE) |
252 | lFlags = FDS_SAVEAS_DIALOG; | |
253 | else | |
254 | lFlags = FDS_OPEN_DIALOG; | |
255 | ||
4efd4259 DW |
256 | if ((m_lDialogStyle & wxHIDE_READONLY) || (m_lDialogStyle & wxSAVE)) |
257 | lFlags |= FDS_SAVEAS_DIALOG; | |
258 | if (m_lDialogStyle & wxMULTIPLE ) | |
259 | lFlags |= FDS_OPEN_DIALOG | FDS_MULTIPLESEL; | |
260 | ||
261 | vFileDlg.cbSize = sizeof(FILEDLG); | |
262 | vFileDlg.fl = lFlags; | |
263 | vFileDlg.pszTitle = zTitleBuffer; | |
264 | ||
265 | // | |
266 | // Convert forward slashes to backslashes (file selector doesn't like | |
267 | // forward slashes) and also squeeze multiple consecutive slashes into one | |
268 | // as it doesn't like two backslashes in a row neither | |
269 | // | |
270 | sDir.reserve(nLen); | |
271 | for ( i = 0; i < nLen; i++ ) | |
272 | { | |
273 | wxChar ch = m_sDir[i]; | |
274 | ||
275 | switch (ch) | |
276 | { | |
277 | case _T('/'): | |
278 | // | |
279 | // Convert to backslash | |
280 | // | |
281 | ch = _T('\\'); | |
282 | ||
283 | // | |
284 | // Fall through | |
285 | // | |
286 | case _T('\\'): | |
287 | while (i < nLen - 1) | |
288 | { | |
289 | wxChar chNext = m_sDir[i + 1]; | |
290 | ||
291 | if (chNext != _T('\\') && chNext != _T('/')) | |
292 | break; | |
293 | ||
294 | // | |
295 | // Ignore the next one, unless it is at the start of a UNC path | |
296 | // | |
297 | if (i > 0) | |
298 | i++; | |
299 | else | |
300 | break; | |
301 | } | |
302 | ||
303 | // | |
304 | // Fall through | |
305 | // | |
306 | ||
307 | default: | |
308 | // | |
309 | // Normal char | |
310 | sDir += ch; | |
311 | } | |
312 | } | |
313 | if ( wxStrlen(m_sWildCard) == 0 ) | |
314 | sTheFilter = ""; | |
315 | else | |
b93f4bb9 | 316 | sTheFilter = m_sWildCard; |
4efd4259 | 317 | |
b93f4bb9 DW |
318 | pzFilterBuffer = strtok((char*)sTheFilter.c_str(), "|"); |
319 | while(pzFilterBuffer != NULL) | |
4efd4259 | 320 | { |
b93f4bb9 DW |
321 | if (nCount > 0 && !(nCount % 2)) |
322 | sDir += wxT(";"); | |
323 | if (nCount % 2) | |
4efd4259 | 324 | { |
b93f4bb9 | 325 | sDir += pzFilterBuffer; |
4efd4259 | 326 | } |
b93f4bb9 DW |
327 | pzFilterBuffer = strtok(NULL, "|"); |
328 | nCount++; | |
4efd4259 | 329 | } |
b93f4bb9 | 330 | if (nCount == 0) |
4efd4259 | 331 | sDir += m_sFileName; |
b93f4bb9 DW |
332 | if (sDir.IsEmpty()) |
333 | sDir = "*.*"; | |
4efd4259 | 334 | wxStrcpy(vFileDlg.szFullFile, sDir.c_str()); |
25fc812c | 335 | sFilterBuffer = sDir; |
4efd4259 | 336 | |
b93f4bb9 | 337 | hWnd = ::WinFileDlg( HWND_DESKTOP |
4efd4259 DW |
338 | ,GetHwndOf(m_pParent) |
339 | ,&vFileDlg | |
340 | ); | |
341 | if (hWnd && vFileDlg.lReturn == DID_OK) | |
342 | { | |
343 | m_asFileNames.Empty(); | |
344 | if ((m_lDialogStyle & wxMULTIPLE ) && vFileDlg.ulFQFCount > 1) | |
345 | { | |
346 | for (int i = 0; i < vFileDlg.ulFQFCount; i++) | |
347 | { | |
348 | if (i == 0) | |
349 | { | |
b93f4bb9 DW |
350 | m_sDir = wxPathOnly(wxString((const char*)*vFileDlg.papszFQFilename[0])); |
351 | m_sPath = (const char*)*vFileDlg.papszFQFilename[0]; | |
4efd4259 | 352 | } |
b93f4bb9 | 353 | m_sFileName = wxFileNameFromPath(wxString((const char*)*vFileDlg.papszFQFilename[i])); |
4efd4259 DW |
354 | m_asFileNames.Add(m_sFileName); |
355 | } | |
b93f4bb9 | 356 | ::WinFreeFileDlgList(vFileDlg.papszFQFilename); |
4efd4259 | 357 | } |
b93f4bb9 | 358 | else if (!(m_lDialogStyle & wxSAVE)) |
4efd4259 DW |
359 | { |
360 | m_sPath = vFileDlg.szFullFile; | |
361 | m_sFileName = wxFileNameFromPath(vFileDlg.szFullFile); | |
362 | m_sDir = wxPathOnly(vFileDlg.szFullFile); | |
363 | } | |
364 | else // save file | |
365 | { | |
366 | const wxChar* pzExtension = NULL; | |
367 | ||
368 | wxStrcpy(zFileNameBuffer, vFileDlg.szFullFile); | |
369 | ||
370 | int nIdx = wxStrlen(zFileNameBuffer) - 1; | |
25fc812c | 371 | wxString sExt; |
4efd4259 | 372 | |
25fc812c DW |
373 | wxSplitPath( zFileNameBuffer |
374 | ,&m_sPath | |
375 | ,&m_sFileName | |
376 | ,&sExt | |
377 | ); | |
378 | if (zFileNameBuffer[nIdx] == wxT('.') || sExt.IsEmpty()) | |
4efd4259 DW |
379 | { |
380 | zFileNameBuffer[nIdx] = wxT('\0'); | |
381 | ||
382 | // | |
383 | // User has typed a filename without an extension: | |
384 | // | |
385 | // A filename can end in a "." here ("abc."), this means it | |
386 | // does not have an extension. Because later on a "." with | |
387 | // the default extension is appended we remove the "." if | |
388 | // filename ends with one (We don't want files called | |
389 | // "abc..ext") | |
390 | // | |
391 | pzExtension = sFilterBuffer.c_str(); | |
392 | ||
393 | for( int i = 0; i < sFilterBuffer.length(); i++ ) | |
394 | { | |
395 | // | |
396 | // Get extension | |
397 | // | |
398 | pzExtension = wxStrrchr(pzExtension, wxT('.')); | |
399 | if ( pzExtension && | |
400 | !wxStrrchr(pzExtension, wxT('*')) && | |
401 | !wxStrrchr(pzExtension, wxT('?')) && | |
402 | pzExtension[1] && | |
403 | pzExtension[1] != wxT(' ') | |
404 | ) // != "blabla. " | |
405 | { | |
406 | // | |
407 | // Now concat extension to the fileName: | |
408 | // | |
409 | m_sPath = wxString(zFileNameBuffer) + pzExtension; | |
410 | } | |
411 | } | |
412 | } | |
413 | else | |
414 | { | |
415 | m_sPath = vFileDlg.szFullFile; | |
416 | } | |
417 | m_sFileName = wxFileNameFromPath(vFileDlg.szFullFile); | |
418 | m_sDir = wxPathOnly(vFileDlg.szFullFile); | |
419 | ||
420 | // | |
421 | // === Simulating the wxOVERWRITE_PROMPT >>============================ | |
422 | // | |
423 | if ((m_lDialogStyle & wxOVERWRITE_PROMPT) && | |
424 | (m_lDialogStyle & wxSAVE) && | |
425 | (wxFileExists(m_sPath.c_str()))) | |
426 | { | |
427 | wxString sMessageText; | |
428 | ||
429 | sMessageText.Printf( _("File '%s' already exists.\nDo you want to replace it?") | |
430 | ,m_sPath.c_str() | |
431 | ); | |
432 | if (wxMessageBox( sMessageText | |
433 | ,wxT("Save File As") | |
434 | ,wxYES_NO | wxICON_EXCLAMATION | |
435 | ) != wxYES) | |
436 | { | |
437 | return wxID_CANCEL; | |
438 | } | |
439 | } | |
440 | } | |
441 | return wxID_OK; | |
442 | } | |
0e320a79 | 443 | return wxID_CANCEL; |
4efd4259 | 444 | } // end of wxFileDialog::ShowModal |
0e320a79 | 445 | |
4efd4259 | 446 | // |
0e320a79 | 447 | // Generic file load/save dialog |
4efd4259 DW |
448 | // |
449 | static wxString wxDefaultFileSelector ( | |
450 | bool bLoad | |
451 | , const char* pzWhat | |
452 | , const char* pzExtension | |
453 | , const char* pzDefaultName | |
454 | , wxWindow* pParent | |
455 | ) | |
0e320a79 | 456 | { |
4efd4259 DW |
457 | char* pzExt = (char *)pzExtension; |
458 | char zPrompt[50]; | |
459 | wxString sStr; | |
460 | char zWild[60]; | |
0e320a79 | 461 | |
4efd4259 DW |
462 | if (bLoad) |
463 | sStr = "Load %s file"; | |
464 | else | |
465 | sStr = "Save %s file"; | |
466 | sprintf(zPrompt, wxGetTranslation(sStr), pzWhat); | |
0e320a79 | 467 | |
4efd4259 DW |
468 | if (*pzExt == '.') |
469 | pzExt++; | |
470 | sprintf(zWild, "*.%s", pzExt); | |
471 | return wxFileSelector ( zPrompt | |
472 | ,NULL | |
473 | ,pzDefaultName | |
474 | ,pzExt | |
475 | ,zWild | |
476 | ,0 | |
477 | ,pParent | |
478 | ); | |
479 | } // end of wxDefaultFileSelector | |
0e320a79 | 480 | |
4efd4259 | 481 | // |
0e320a79 | 482 | // Generic file load dialog |
4efd4259 DW |
483 | // |
484 | wxString wxLoadFileSelector ( | |
485 | const char* pzWhat | |
486 | , const char* pzExtension | |
487 | , const char* pzDefaultName | |
488 | , wxWindow* pParent | |
489 | ) | |
0e320a79 | 490 | { |
4efd4259 DW |
491 | return wxDefaultFileSelector( TRUE |
492 | ,pzWhat | |
493 | ,pzExtension | |
494 | ,pzDefaultName | |
495 | ,pParent | |
496 | ); | |
497 | } // end of wxLoadFileSelector | |
0e320a79 DW |
498 | |
499 | ||
4efd4259 | 500 | // |
0e320a79 | 501 | // Generic file save dialog |
4efd4259 DW |
502 | // |
503 | wxString wxSaveFileSelector ( | |
504 | const char* pzWhat | |
505 | , const char* pzExtension | |
506 | , const char* pzDefaultName | |
507 | , wxWindow* pParent | |
508 | ) | |
0e320a79 | 509 | { |
4efd4259 DW |
510 | return wxDefaultFileSelector( FALSE |
511 | ,pzWhat | |
512 | ,pzExtension | |
513 | ,pzDefaultName | |
514 | ,pParent | |
515 | ); | |
516 | } // end of wxSaveFileSelector | |
0e320a79 | 517 |