Weekly updates and file dialog implementation
[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 static wxChar zFileNameBuffer[wxMAXPATH]; // the file-name
231 HWND hWnd = 0;
232 wxChar zTitleBuffer[wxMAXFILE + 1 + wxMAXEXT]; // the file-name, without path
233 wxString sDir;
234 size_t i;
235 size_t nLen = m_sDir.length();
236 FILEDLG vFileDlg;
237 ULONG lFlags = 0L;
238
239 memset(&vFileDlg, '\0', sizeof(FILEDLG));
240 if (m_pParent)
241 hWnd = (HWND) m_pParent->GetHWND();
242 if (!hWnd && wxTheApp->GetTopWindow())
243 hWnd = (HWND) wxTheApp->GetTopWindow()->GetHWND();
244
245
246 *zFileNameBuffer = wxT('\0');
247 *zTitleBuffer = wxT('\0');
248
249 m_lDialogStyle & wxSAVE ? lFlags != FDS_SAVEAS_DIALOG
250 : FDS_OPEN_DIALOG
251 ;
252 if ((m_lDialogStyle & wxHIDE_READONLY) || (m_lDialogStyle & wxSAVE))
253 lFlags |= FDS_SAVEAS_DIALOG;
254 if (m_lDialogStyle & wxMULTIPLE )
255 lFlags |= FDS_OPEN_DIALOG | FDS_MULTIPLESEL;
256
257 vFileDlg.cbSize = sizeof(FILEDLG);
258 vFileDlg.fl = lFlags;
259 vFileDlg.pszTitle = zTitleBuffer;
260
261 //
262 // Convert forward slashes to backslashes (file selector doesn't like
263 // forward slashes) and also squeeze multiple consecutive slashes into one
264 // as it doesn't like two backslashes in a row neither
265 //
266 sDir.reserve(nLen);
267 for ( i = 0; i < nLen; i++ )
268 {
269 wxChar ch = m_sDir[i];
270
271 switch (ch)
272 {
273 case _T('/'):
274 //
275 // Convert to backslash
276 //
277 ch = _T('\\');
278
279 //
280 // Fall through
281 //
282 case _T('\\'):
283 while (i < nLen - 1)
284 {
285 wxChar chNext = m_sDir[i + 1];
286
287 if (chNext != _T('\\') && chNext != _T('/'))
288 break;
289
290 //
291 // Ignore the next one, unless it is at the start of a UNC path
292 //
293 if (i > 0)
294 i++;
295 else
296 break;
297 }
298
299 //
300 // Fall through
301 //
302
303 default:
304 //
305 // Normal char
306 sDir += ch;
307 }
308 }
309 if ( wxStrlen(m_sWildCard) == 0 )
310 sTheFilter = "";
311 else
312 sTheFilter = m_sWildCard ;
313
314 if (!wxStrchr(sTheFilter, wxT('|') ) )
315 {
316 //
317 // Only one filter ==> default text
318 //
319 sFilterBuffer.Printf( _("Files (%s)|%s")
320 ,sTheFilter.c_str()
321 ,sTheFilter.c_str()
322 );
323 }
324 else
325 { // more then one filter
326 sFilterBuffer = sTheFilter;
327 }
328
329 sFilterBuffer += wxT("|");
330
331 //
332 // Replace | with \0
333 //
334 for (i = 0; i < sFilterBuffer.Len(); i++ )
335 {
336 if (sFilterBuffer.GetChar(i) == wxT('|'))
337 {
338 sFilterBuffer[i] = wxT('\0');
339 }
340 }
341 if (!sTheFilter.IsEmpty())
342 sDir += sTheFilter;
343 else
344 sDir += m_sFileName;
345 wxStrcpy(vFileDlg.szFullFile, sDir.c_str());
346
347 hWnd = ::WinFileDlg( GetHwndOf(m_pParent)
348 ,GetHwndOf(m_pParent)
349 ,&vFileDlg
350 );
351 if (hWnd && vFileDlg.lReturn == DID_OK)
352 {
353 m_asFileNames.Empty();
354 if ((m_lDialogStyle & wxMULTIPLE ) && vFileDlg.ulFQFCount > 1)
355 {
356 for (int i = 0; i < vFileDlg.ulFQFCount; i++)
357 {
358 if (i == 0)
359 {
360 m_sDir = wxPathOnly(wxString((const char*)vFileDlg.papszFQFilename[i]));
361 m_sPath = (const char*)vFileDlg.papszFQFilename[i];
362 }
363 m_sFileName = wxFileNameFromPath(wxString((const char*)vFileDlg.papszFQFilename[i]));
364 m_asFileNames.Add(m_sFileName);
365 }
366 }
367 else if (!m_lDialogStyle & wxSAVE)
368 {
369 m_sPath = vFileDlg.szFullFile;
370 m_sFileName = wxFileNameFromPath(vFileDlg.szFullFile);
371 m_sDir = wxPathOnly(vFileDlg.szFullFile);
372 }
373 else // save file
374 {
375 const wxChar* pzExtension = NULL;
376
377 wxStrcpy(zFileNameBuffer, vFileDlg.szFullFile);
378
379 int nIdx = wxStrlen(zFileNameBuffer) - 1;
380
381 if (zFileNameBuffer[nIdx] == wxT('.') )
382 {
383 zFileNameBuffer[nIdx] = wxT('\0');
384
385 //
386 // User has typed a filename without an extension:
387 //
388 // A filename can end in a "." here ("abc."), this means it
389 // does not have an extension. Because later on a "." with
390 // the default extension is appended we remove the "." if
391 // filename ends with one (We don't want files called
392 // "abc..ext")
393 //
394 pzExtension = sFilterBuffer.c_str();
395
396 for( int i = 0; i < sFilterBuffer.length(); i++ )
397 {
398 //
399 // Get extension
400 //
401 pzExtension = wxStrrchr(pzExtension, wxT('.'));
402 if ( pzExtension &&
403 !wxStrrchr(pzExtension, wxT('*')) &&
404 !wxStrrchr(pzExtension, wxT('?')) &&
405 pzExtension[1] &&
406 pzExtension[1] != wxT(' ')
407 ) // != "blabla. "
408 {
409 //
410 // Now concat extension to the fileName:
411 //
412 m_sPath = wxString(zFileNameBuffer) + pzExtension;
413 }
414 }
415 }
416 else
417 {
418 m_sPath = vFileDlg.szFullFile;
419 }
420 m_sFileName = wxFileNameFromPath(vFileDlg.szFullFile);
421 m_sDir = wxPathOnly(vFileDlg.szFullFile);
422
423 //
424 // === Simulating the wxOVERWRITE_PROMPT >>============================
425 //
426 if ((m_lDialogStyle & wxOVERWRITE_PROMPT) &&
427 (m_lDialogStyle & wxSAVE) &&
428 (wxFileExists(m_sPath.c_str())))
429 {
430 wxString sMessageText;
431
432 sMessageText.Printf( _("File '%s' already exists.\nDo you want to replace it?")
433 ,m_sPath.c_str()
434 );
435 if (wxMessageBox( sMessageText
436 ,wxT("Save File As")
437 ,wxYES_NO | wxICON_EXCLAMATION
438 ) != wxYES)
439 {
440 return wxID_CANCEL;
441 }
442 }
443 }
444 return wxID_OK;
445 }
446 return wxID_CANCEL;
447 } // end of wxFileDialog::ShowModal
448
449 //
450 // Generic file load/save dialog
451 //
452 static wxString wxDefaultFileSelector (
453 bool bLoad
454 , const char* pzWhat
455 , const char* pzExtension
456 , const char* pzDefaultName
457 , wxWindow* pParent
458 )
459 {
460 char* pzExt = (char *)pzExtension;
461 char zPrompt[50];
462 wxString sStr;
463 char zWild[60];
464
465 if (bLoad)
466 sStr = "Load %s file";
467 else
468 sStr = "Save %s file";
469 sprintf(zPrompt, wxGetTranslation(sStr), pzWhat);
470
471 if (*pzExt == '.')
472 pzExt++;
473 sprintf(zWild, "*.%s", pzExt);
474 return wxFileSelector ( zPrompt
475 ,NULL
476 ,pzDefaultName
477 ,pzExt
478 ,zWild
479 ,0
480 ,pParent
481 );
482 } // end of wxDefaultFileSelector
483
484 //
485 // Generic file load dialog
486 //
487 wxString wxLoadFileSelector (
488 const char* pzWhat
489 , const char* pzExtension
490 , const char* pzDefaultName
491 , wxWindow* pParent
492 )
493 {
494 return wxDefaultFileSelector( TRUE
495 ,pzWhat
496 ,pzExtension
497 ,pzDefaultName
498 ,pParent
499 );
500 } // end of wxLoadFileSelector
501
502
503 //
504 // Generic file save dialog
505 //
506 wxString wxSaveFileSelector (
507 const char* pzWhat
508 , const char* pzExtension
509 , const char* pzDefaultName
510 , wxWindow* pParent
511 )
512 {
513 return wxDefaultFileSelector( FALSE
514 ,pzWhat
515 ,pzExtension
516 ,pzDefaultName
517 ,pParent
518 );
519 } // end of wxSaveFileSelector
520