File dialog fixes
[wxWidgets.git] / src / os2 / filedlg.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: filedlg.cpp
3 // Purpose: wxFileDialog
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/05/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
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
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"
26 #include "wx/app.h"
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>
37
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
59 IMPLEMENT_CLASS(wxFileDialog, wxDialog)
60
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 )
76 {
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;
92 else
93 sDefaultDirString = "";
94
95 if (pzDefaultFileName)
96 sDefaultFilenameString = pzDefaultFileName;
97 else
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++;
121
122 //
123 // Find the end of the filter
124 //
125 for(; i < sFilter.Len(); i++)
126 {
127 if(sFilter[i] == wxT('|'))
128 break;
129 }
130
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)
145 {
146 return vFileDialog.GetPath();
147 }
148 else
149 return wxEmptyString;
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 )
163 {
164 wxFileDialog vFileDialog( pParent
165 ,pzTitle ? pzTitle : ""
166 ,pzDefaultDir ? pzDefaultDir : ""
167 ,pzDefaultFileName ? pzDefaultFileName : ""
168 ,pzFilter ? pzFilter : ""
169 ,nFlags
170 ,wxPoint(nX, nY)
171 );
172
173 if (vFileDialog.ShowModal() == wxID_OK)
174 {
175 *pnDefaultFilterIndex = vFileDialog.GetFilterIndex();
176 return vFileDialog.GetPath();
177 }
178 else
179 return wxEmptyString;
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 )
195 {
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
225
226 int wxFileDialog::ShowModal()
227 {
228 wxString sTheFilter;
229 wxString sFilterBuffer;
230 wxChar* pzFilterBuffer;
231 static wxChar zFileNameBuffer[wxMAXPATH]; // the file-name
232 HWND hWnd = 0;
233 wxChar zTitleBuffer[wxMAXFILE + 1 + wxMAXEXT]; // the file-name, without path
234 wxString sDir;
235 size_t i;
236 size_t nLen = m_sDir.length();
237 int nCount = 0;
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
251 if (m_lDialogStyle & wxSAVE)
252 lFlags = FDS_SAVEAS_DIALOG;
253 else
254 lFlags = FDS_OPEN_DIALOG;
255
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
316 sTheFilter = m_sWildCard;
317
318 pzFilterBuffer = strtok((char*)sTheFilter.c_str(), "|");
319 while(pzFilterBuffer != NULL)
320 {
321 if (nCount > 0 && !(nCount % 2))
322 sDir += wxT(";");
323 if (nCount % 2)
324 {
325 sDir += pzFilterBuffer;
326 }
327 pzFilterBuffer = strtok(NULL, "|");
328 nCount++;
329 }
330 if (nCount == 0)
331 sDir += m_sFileName;
332 if (sDir.IsEmpty())
333 sDir = "*.*";
334 wxStrcpy(vFileDlg.szFullFile, sDir.c_str());
335 sFilterBuffer = sDir;
336
337 hWnd = ::WinFileDlg( HWND_DESKTOP
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 {
350 m_sDir = wxPathOnly(wxString((const char*)*vFileDlg.papszFQFilename[0]));
351 m_sPath = (const char*)*vFileDlg.papszFQFilename[0];
352 }
353 m_sFileName = wxFileNameFromPath(wxString((const char*)*vFileDlg.papszFQFilename[i]));
354 m_asFileNames.Add(m_sFileName);
355 }
356 ::WinFreeFileDlgList(vFileDlg.papszFQFilename);
357 }
358 else if (!(m_lDialogStyle & wxSAVE))
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;
371 wxString sExt;
372
373 wxSplitPath( zFileNameBuffer
374 ,&m_sPath
375 ,&m_sFileName
376 ,&sExt
377 );
378 if (zFileNameBuffer[nIdx] == wxT('.') || sExt.IsEmpty())
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 }
443 return wxID_CANCEL;
444 } // end of wxFileDialog::ShowModal
445
446 //
447 // Generic file load/save dialog
448 //
449 static wxString wxDefaultFileSelector (
450 bool bLoad
451 , const char* pzWhat
452 , const char* pzExtension
453 , const char* pzDefaultName
454 , wxWindow* pParent
455 )
456 {
457 char* pzExt = (char *)pzExtension;
458 char zPrompt[50];
459 wxString sStr;
460 char zWild[60];
461
462 if (bLoad)
463 sStr = "Load %s file";
464 else
465 sStr = "Save %s file";
466 sprintf(zPrompt, wxGetTranslation(sStr), pzWhat);
467
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
480
481 //
482 // Generic file load dialog
483 //
484 wxString wxLoadFileSelector (
485 const char* pzWhat
486 , const char* pzExtension
487 , const char* pzDefaultName
488 , wxWindow* pParent
489 )
490 {
491 return wxDefaultFileSelector( TRUE
492 ,pzWhat
493 ,pzExtension
494 ,pzDefaultName
495 ,pParent
496 );
497 } // end of wxLoadFileSelector
498
499
500 //
501 // Generic file save dialog
502 //
503 wxString wxSaveFileSelector (
504 const char* pzWhat
505 , const char* pzExtension
506 , const char* pzDefaultName
507 , wxWindow* pParent
508 )
509 {
510 return wxDefaultFileSelector( FALSE
511 ,pzWhat
512 ,pzExtension
513 ,pzDefaultName
514 ,pParent
515 );
516 } // end of wxSaveFileSelector
517