FileDlg updates.
[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
336 hWnd = ::WinFileDlg( HWND_DESKTOP
337 ,GetHwndOf(m_pParent)
338 ,&vFileDlg
339 );
340 if (hWnd && vFileDlg.lReturn == DID_OK)
341 {
342 m_asFileNames.Empty();
343 if ((m_lDialogStyle & wxMULTIPLE ) && vFileDlg.ulFQFCount > 1)
344 {
345 for (int i = 0; i < vFileDlg.ulFQFCount; i++)
346 {
347 if (i == 0)
348 {
349 m_sDir = wxPathOnly(wxString((const char*)*vFileDlg.papszFQFilename[0]));
350 m_sPath = (const char*)*vFileDlg.papszFQFilename[0];
351 }
352 m_sFileName = wxFileNameFromPath(wxString((const char*)*vFileDlg.papszFQFilename[i]));
353 m_asFileNames.Add(m_sFileName);
354 }
355 ::WinFreeFileDlgList(vFileDlg.papszFQFilename);
356 }
357 else if (!(m_lDialogStyle & wxSAVE))
358 {
359 m_sPath = vFileDlg.szFullFile;
360 m_sFileName = wxFileNameFromPath(vFileDlg.szFullFile);
361 m_sDir = wxPathOnly(vFileDlg.szFullFile);
362 }
363 else // save file
364 {
365 const wxChar* pzExtension = NULL;
366
367 wxStrcpy(zFileNameBuffer, vFileDlg.szFullFile);
368
369 int nIdx = wxStrlen(zFileNameBuffer) - 1;
370
371 if (zFileNameBuffer[nIdx] == wxT('.') )
372 {
373 zFileNameBuffer[nIdx] = wxT('\0');
374
375 //
376 // User has typed a filename without an extension:
377 //
378 // A filename can end in a "." here ("abc."), this means it
379 // does not have an extension. Because later on a "." with
380 // the default extension is appended we remove the "." if
381 // filename ends with one (We don't want files called
382 // "abc..ext")
383 //
384 pzExtension = sFilterBuffer.c_str();
385
386 for( int i = 0; i < sFilterBuffer.length(); i++ )
387 {
388 //
389 // Get extension
390 //
391 pzExtension = wxStrrchr(pzExtension, wxT('.'));
392 if ( pzExtension &&
393 !wxStrrchr(pzExtension, wxT('*')) &&
394 !wxStrrchr(pzExtension, wxT('?')) &&
395 pzExtension[1] &&
396 pzExtension[1] != wxT(' ')
397 ) // != "blabla. "
398 {
399 //
400 // Now concat extension to the fileName:
401 //
402 m_sPath = wxString(zFileNameBuffer) + pzExtension;
403 }
404 }
405 }
406 else
407 {
408 m_sPath = vFileDlg.szFullFile;
409 }
410 m_sFileName = wxFileNameFromPath(vFileDlg.szFullFile);
411 m_sDir = wxPathOnly(vFileDlg.szFullFile);
412
413 //
414 // === Simulating the wxOVERWRITE_PROMPT >>============================
415 //
416 if ((m_lDialogStyle & wxOVERWRITE_PROMPT) &&
417 (m_lDialogStyle & wxSAVE) &&
418 (wxFileExists(m_sPath.c_str())))
419 {
420 wxString sMessageText;
421
422 sMessageText.Printf( _("File '%s' already exists.\nDo you want to replace it?")
423 ,m_sPath.c_str()
424 );
425 if (wxMessageBox( sMessageText
426 ,wxT("Save File As")
427 ,wxYES_NO | wxICON_EXCLAMATION
428 ) != wxYES)
429 {
430 return wxID_CANCEL;
431 }
432 }
433 }
434 return wxID_OK;
435 }
436 return wxID_CANCEL;
437 } // end of wxFileDialog::ShowModal
438
439 //
440 // Generic file load/save dialog
441 //
442 static wxString wxDefaultFileSelector (
443 bool bLoad
444 , const char* pzWhat
445 , const char* pzExtension
446 , const char* pzDefaultName
447 , wxWindow* pParent
448 )
449 {
450 char* pzExt = (char *)pzExtension;
451 char zPrompt[50];
452 wxString sStr;
453 char zWild[60];
454
455 if (bLoad)
456 sStr = "Load %s file";
457 else
458 sStr = "Save %s file";
459 sprintf(zPrompt, wxGetTranslation(sStr), pzWhat);
460
461 if (*pzExt == '.')
462 pzExt++;
463 sprintf(zWild, "*.%s", pzExt);
464 return wxFileSelector ( zPrompt
465 ,NULL
466 ,pzDefaultName
467 ,pzExt
468 ,zWild
469 ,0
470 ,pParent
471 );
472 } // end of wxDefaultFileSelector
473
474 //
475 // Generic file load dialog
476 //
477 wxString wxLoadFileSelector (
478 const char* pzWhat
479 , const char* pzExtension
480 , const char* pzDefaultName
481 , wxWindow* pParent
482 )
483 {
484 return wxDefaultFileSelector( TRUE
485 ,pzWhat
486 ,pzExtension
487 ,pzDefaultName
488 ,pParent
489 );
490 } // end of wxLoadFileSelector
491
492
493 //
494 // Generic file save dialog
495 //
496 wxString wxSaveFileSelector (
497 const char* pzWhat
498 , const char* pzExtension
499 , const char* pzDefaultName
500 , wxWindow* pParent
501 )
502 {
503 return wxDefaultFileSelector( FALSE
504 ,pzWhat
505 ,pzExtension
506 ,pzDefaultName
507 ,pParent
508 );
509 } // end of wxSaveFileSelector
510