Daniel Gehriger <dgehrige@dmtsun.epfl.ch> patch for default extension filter
[wxWidgets.git] / src / msw / filedlg.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: filedlg.cpp
3 // Purpose: wxFileDialog
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "filedlg.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include <stdio.h>
25 #include "wx/defs.h"
26 #include "wx/utils.h"
27 #include "wx/msgdlg.h"
28 #include "wx/dialog.h"
29 #include "wx/filedlg.h"
30 #include "wx/intl.h"
31 #endif
32
33 #include <windows.h>
34
35 #if !defined(__WIN32__) || defined(__SALFORDC__)
36 #include <commdlg.h>
37 #endif
38
39 #include "wx/msw/private.h"
40
41 #include <math.h>
42 #include <stdlib.h>
43 #include <string.h>
44
45 #if !USE_SHARED_LIBRARY
46 IMPLEMENT_CLASS(wxFileDialog, wxDialog)
47 #endif
48
49 char *wxFileSelector(const char *title,
50 const char *defaultDir, const char *defaultFileName,
51 const char *defaultExtension, const char *filter, int flags,
52 wxWindow *parent, int x, int y)
53 {
54 // In the original implementation, defaultExtension is passed to the
55 // lpstrDefExt member of OPENFILENAME. This extension, if non-NULL, is
56 // appended to the filename if the user fails to type an extension. The new
57 // implementation (taken from wxFileSelectorEx) appends the extension
58 // automatically, by looking at the filter specification. In fact this
59 // should be better than the native Microsoft implementation because
60 // Windows only allows *one* default extension, whereas here we do the
61 // right thing depending on the filter the user has chosen.
62
63 // If there's a default extension specified but no filter, we create a
64 // suitable filter.
65
66 wxString filter2;
67 if ( defaultExtension && !filter )
68 filter2 = wxString("*.") + defaultExtension;
69 else if ( filter )
70 filter2 = filter;
71
72 wxString defaultDirString;
73 if (defaultDir)
74 defaultDirString = defaultDir;
75
76 wxString defaultFilenameString;
77 if (defaultFileName)
78 defaultFilenameString = defaultFileName;
79
80 wxFileDialog fileDialog(parent, title, defaultDirString,
81 defaultFilenameString, filter2,
82 flags, wxPoint(x, y));
83 if( Strlen(defaultExtension) != 0 )
84 {
85 int filterFind = 1,
86 filterIndex = 0;
87
88 for( unsigned int i = 0; i < filter2.Len(); i++ )
89 {
90 if( filter2.GetChar(i) == '|' )
91 {
92 // save the start index of the new filter
93 unsigned int is = i++;
94 filterIndex++;
95
96 // find the end of the filter
97 for( ; i < filter2.Len(); i++ )
98 {
99 if(filter2[i] == '|')
100 break;
101 }
102
103 if( i-is-1 > 0 && is+1 < filter2.Len() )
104 {
105 if( filter2.Mid(is+1,i-is-1).Contains(defaultExtension) )
106 {
107 filterFind = filterIndex;
108 break;
109 }
110 }
111 }
112 }
113
114 fileDialog.SetFilterIndex(filterFind);
115 }
116
117 if ( fileDialog.ShowModal() == wxID_OK )
118 {
119 strcpy(wxBuffer, (const char *)fileDialog.GetPath());
120 return wxBuffer;
121 }
122 else
123 return NULL;
124 }
125
126 # if __BORLANDC__
127 # include <dir.h> // for MAXPATH etc. ( Borland 3.1 )
128 # endif
129
130 # ifndef MAXPATH
131 # define MAXPATH 400
132 # endif
133
134 # ifndef MAXDRIVE
135 # define MAXDRIVE 3
136 # endif
137
138 # ifndef MAXFILE
139 # define MAXFILE 9
140 # endif
141
142 # ifndef MAXEXT
143 # define MAXEXT 5
144 # endif
145
146
147 char *wxFileSelectorEx(const char *title,
148 const char *defaultDir,
149 const char *defaultFileName,
150 int* defaultFilterIndex,
151 const char *filter,
152 int flags,
153 wxWindow* parent,
154 int x,
155 int y)
156
157 {
158 wxFileDialog fileDialog(parent, title ? title : "", defaultDir ? defaultDir : "",
159 defaultFileName ? defaultFileName : "", filter ? filter : "", flags, wxPoint(x, y));
160
161 if ( fileDialog.ShowModal() == wxID_OK )
162 {
163 *defaultFilterIndex = fileDialog.GetFilterIndex();
164 strcpy(wxBuffer, (const char *)fileDialog.GetPath());
165 return wxBuffer;
166 }
167 else
168 return NULL;
169 }
170
171 wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message,
172 const wxString& defaultDir, const wxString& defaultFileName, const wxString& wildCard,
173 long style, const wxPoint& pos)
174 {
175 m_message = message;
176 m_dialogStyle = style;
177 m_parent = parent;
178 m_path = "";
179 m_fileName = defaultFileName;
180 m_dir = defaultDir;
181 m_wildCard = wildCard;
182 m_filterIndex = 1;
183 }
184
185 int wxFileDialog::ShowModal(void)
186 {
187 HWND hWnd = 0;
188 if (m_parent) hWnd = (HWND) m_parent->GetHWND();
189
190 static char fileNameBuffer [ MAXPATH ]; // the file-name
191 char titleBuffer [ MAXFILE+1+MAXEXT ]; // the file-name, without path
192
193 *fileNameBuffer = '\0';
194 *titleBuffer = '\0';
195
196 long msw_flags = 0;
197 if ( (m_dialogStyle & wxHIDE_READONLY) || (m_dialogStyle & wxSAVE) )
198 msw_flags |= OFN_HIDEREADONLY;
199 if ( m_dialogStyle & wxFILE_MUST_EXIST )
200 msw_flags |= OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
201
202 OPENFILENAME of;
203 memset(&of, 0, sizeof(OPENFILENAME));
204
205 of.lpstrCustomFilter = NULL; // system should not save custom filter
206 of.nMaxCustFilter = 0L;
207
208 of.nFileOffset = 0; // 0-based pointer to filname in lpstFile
209 of.nFileExtension = 0; // 0-based pointer to extension in lpstrFile
210 of.lpstrDefExt = NULL; // no default extension
211
212 of.lStructSize = sizeof(OPENFILENAME);
213 of.hwndOwner = hWnd;
214 of.lpstrTitle = (char *)(const char *)m_message;
215
216
217 of.lpstrFileTitle = titleBuffer;
218 of.nMaxFileTitle = MAXFILE + 1 + MAXEXT; // Windows 3.0 and 3.1
219
220 of.lpstrInitialDir = (const char *) m_dir;
221
222 of.Flags = msw_flags;
223
224
225
226 //=== Like Alejandro Sierra's wildcard modification >>===================
227 /*
228 In wxFileSelector you can put, instead of a single wild_card,
229 pairs of strings separated by '|'.
230 The first string is a description, and the
231 second is the wild card. You can put any number of pairs.
232
233 eg. "description1 (*.ex1)|*.ex1|description2 (*.ex2)|*.ex2"
234
235 If you put a single wild card, it works as before the modification.
236 */
237 //=======================================================================
238
239 wxString theFilter = ( Strlen(m_wildCard) == 0 ) ? "*.*" : m_wildCard;
240 wxString filterBuffer;
241
242 if ( !strchr( theFilter, '|' ) ) { // only one filter ==> default text
243 filterBuffer.Printf(_("Files (%s)|%s"),
244 theFilter.c_str(), theFilter.c_str());
245 }
246 else { // more then one filter
247 filterBuffer = theFilter;
248
249 for ( unsigned int i = 0; i < filterBuffer.Len(); i++ ) {
250 if ( filterBuffer.GetChar(i) == '|' ) {
251 filterBuffer[i] = '\0';
252 }
253 }
254 }
255
256 of.lpstrFilter = (LPSTR)(const char *)filterBuffer;
257 of.nFilterIndex = m_filterIndex;
258
259 //=== Setting defaultFileName >>=========================================
260
261 strncpy( fileNameBuffer, (const char *)m_fileName, MAXPATH-1 );
262 fileNameBuffer[ MAXPATH-1 ] = '\0';
263
264 of.lpstrFile = fileNameBuffer; // holds returned filename
265 of.nMaxFile = MAXPATH;
266
267 //== Execute FileDialog >>=================================================
268
269 bool success = (m_dialogStyle & wxSAVE) ? (GetSaveFileName(&of) != 0)
270 : (GetOpenFileName(&of) != 0);
271
272 if ( success )
273 {
274 const char* extension = NULL;
275
276 //=== Adding the correct extension >>=================================
277
278 m_filterIndex = (int)of.nFilterIndex;
279
280 if ( of.nFileExtension && fileNameBuffer[ of.nFileExtension-1] != '.' )
281 { // user has typed an filename
282 // without an extension:
283
284 int maxFilter = (int)(of.nFilterIndex*2L-1L);
285 extension = filterBuffer;
286
287 for( int i = 0; i < maxFilter; i++ ) { // get extension
288 extension = extension + strlen( extension ) +1;
289 }
290
291 extension = strrchr( extension, '.' );
292 if ( extension // != "blabla"
293 && !strrchr( extension, '*' ) // != "blabla.*"
294 && !strrchr( extension, '?' ) // != "blabla.?"
295 && extension[1] // != "blabla."
296 && extension[1] != ' ' ) // != "blabla. "
297 {
298 // now concat extension to the fileName:
299 m_fileName = wxString(fileNameBuffer) + extension;
300
301 int len = strlen( fileNameBuffer );
302 strncpy( fileNameBuffer + len, extension, MAXPATH - len );
303 fileNameBuffer[ MAXPATH -1 ] = '\0';
304 }
305 }
306
307 m_path = fileNameBuffer;
308 m_fileName = wxFileNameFromPath(fileNameBuffer);
309
310
311 //=== Simulating the wxOVERWRITE_PROMPT >>============================
312
313 if ( (m_dialogStyle & wxOVERWRITE_PROMPT) &&
314 ::wxFileExists( fileNameBuffer ) )
315 {
316 wxString messageText;
317 messageText.Printf(_("Replace file '%s'?"), fileNameBuffer);
318
319 if ( wxMessageBox(messageText, m_message, wxYES_NO ) != wxYES )
320 {
321 success = FALSE;
322 }
323 }
324
325 } // END: if ( success )
326
327 return (success ? wxID_OK : wxID_CANCEL) ;
328
329 }
330
331 // Generic file load/save dialog
332 static char *
333 wxDefaultFileSelector(bool load, const char *what, const char *extension, const char *default_name, wxWindow *parent)
334 {
335
336 wxString prompt;
337 wxString str;
338 if (load)
339 str = _("Load %s file");
340 else
341 str = _("Save %s file");
342 prompt.Printf(str, what);
343
344 const char *ext = extension;
345 if (*ext == '.')
346 ext++;
347
348 wxString wild;
349 wild.Printf("*.%s", ext);
350
351 return wxFileSelector (prompt, NULL, default_name, ext, wild, 0, parent);
352 }
353
354 // Generic file load dialog
355 char *
356 wxLoadFileSelector(const char *what, const char *extension, const char *default_name, wxWindow *parent)
357 {
358 return wxDefaultFileSelector(TRUE, what, extension, default_name, parent);
359 }
360
361
362 // Generic file save dialog
363 char *
364 wxSaveFileSelector(const char *what, const char *extension, const char *default_name, wxWindow *parent)
365 {
366 return wxDefaultFileSelector(FALSE, what, extension, default_name, parent);
367 }
368
369