]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/filedlg.cpp
added a call for invalidating the dc setup on mac explicitely (needed in case of...
[wxWidgets.git] / src / mac / carbon / filedlg.cpp
CommitLineData
e9576ca5
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: filedlg.cpp
2f1ae414 3// Purpose: wxFileDialog
e9576ca5
SC
4// Author: AUTHOR
5// Modified by:
6// Created: ??/??/98
7// RCS-ID: $Id$
8// Copyright: (c) AUTHOR
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "filedlg.h"
14#endif
15
16#include "wx/defs.h"
17#include "wx/utils.h"
18#include "wx/dialog.h"
19#include "wx/filedlg.h"
20#include "wx/intl.h"
21
03e11df5
GD
22#if !defined(__UNIX__)
23 #include "PLStringFuncs.h"
24#endif
5b781a67 25
2f1ae414 26#if !USE_SHARED_LIBRARY
e9576ca5 27IMPLEMENT_CLASS(wxFileDialog, wxDialog)
2f1ae414 28#endif
e9576ca5 29
519cb848
SC
30// begin wxmac
31
03e11df5
GD
32#if defined(__UNIX__)
33 #include <NavigationServices/Navigation.h>
34#else
35 #include <Navigation.h>
36#endif
5b781a67 37
03e11df5
GD
38#ifndef __UNIX__
39 #include "morefile.h"
40 #include "moreextr.h"
41 #include "fullpath.h"
42 #include "fspcompa.h"
43 #include "PLStringFuncs.h"
44#endif
519cb848 45
5b781a67
SC
46extern bool gUseNavServices ;
47
48static pascal void NavEventProc(
49 NavEventCallbackMessage inSelector,
50 NavCBRecPtr ioParams,
51 NavCallBackUserData ioUserData);
52
53#if TARGET_CARBON
54 static NavEventUPP sStandardNavEventFilter = NewNavEventUPP(NavEventProc);
55#else
56 static NavEventUPP sStandardNavEventFilter = NewNavEventProc(NavEventProc);
57#endif
58
59static pascal void
60NavEventProc(
61 NavEventCallbackMessage inSelector,
62 NavCBRecPtr ioParams,
63 NavCallBackUserData /* ioUserData */)
64{
65 if (inSelector == kNavCBEvent) {
66 // In Universal Headers 3.2, Apple changed the definition of
67 /*
68 #if UNIVERSAL_INTERFACES_VERSION >= 0x0320 // Universal Headers 3.2
69 UModalAlerts::ProcessModalEvent(*(ioParams->eventData.eventDataParms.event));
70
71 #else
72 UModalAlerts::ProcessModalEvent(*(ioParams->eventData.event));
73 #endif
74 */
75
76 }
77}
78
519cb848
SC
79char * gfilters[] =
80{
81 "*.TXT" ,
82
83 NULL
84} ;
85
86OSType gfiltersmac[] =
87{
88 'TEXT' ,
89
90 '****'
91} ;
92
2f1ae414
SC
93// the data we need to pass to our standard file hook routine
94// includes a pointer to the dialog, a pointer to the standard
95// file reply record (so we can inspect the current selection)
96// and a copy of the "previous" file spec of the reply record
97// so we can see if the selection has changed
98
99const int kwxMacFileTypes = 10 ;
100
101struct OpenUserDataRec {
102 StandardFileReply *sfrPtr;
103 FSSpec oldSelectionFSSpec;
104 char filter[kwxMacFileTypes][10] ;
105 OSType filtermactypes[kwxMacFileTypes] ;
106 int numfilters ;
107 DialogPtr theDlgPtr;
108};
109typedef struct OpenUserDataRec
110 OpenUserDataRec, *OpenUserDataRecPtr;
111
112#if !TARGET_CARBON
113
519cb848
SC
114static void wxMacSetupStandardFile(short newVRefNum, long newDirID)
115{
116 enum
117 { SFSaveDisk = 0x214, CurDirStore = 0x398 };
118 *(short *) SFSaveDisk = -1 * newVRefNum;
119 *(long *) CurDirStore = newDirID;
120}
121
122static void wxMacSetupStandardFileFromPath( const char* s )
123{
124 Str255 volume ;
125 Str255 path ;
126 short vRefNum ;
127 long dirRef ;
128 short i,j ;
129 Boolean isDirectory ;
130
131 for (i=0 ; (s[i]!=0) && (s[i]!=':') ;i++)
132 {
133 volume[i]=s[i] ;
134 }
135 volume[i]=':' ;
136 volume[i+1]=0 ;
137
138 // then copy the rest of the filename
139
140 for (j=0;(s[i]!=0);i++,j++)
141 {
142 path[j]=s[i] ;
143 }
144 path[j]=0 ;
145
146 c2pstr((Ptr) volume) ;
147 c2pstr((Ptr) path) ;
148
149 SetVol(volume, 0) ;
150 GetVol( NULL, &vRefNum ) ;
151
152 GetDirectoryID( vRefNum , fsRtDirID , path , &dirRef , &isDirectory ) ;
153 wxMacSetupStandardFile(vRefNum, dirRef) ;
154}
155
156enum {
157 kSelectItem = 10, // select button item number
158 kSFGetFileDlgID = 251, // dialog resource number
159 kStrListID = 251, // our strings
160 kSelectStrNum = 1, // word 'Select: ' for button
161 kDesktopStrNum = 2, // word 'Desktop' for button
162 kSelectNoQuoteStrNum = 3, // word 'Select: ' for button
163
164 kUseQuotes = true, // parameter for SetButtonName
165 kDontUseQuotes = false
166};
167
519cb848
SC
168static void GetLabelString(StringPtr theStr, short stringNum)
169{
170 GetIndString(theStr, kStrListID, stringNum);
171}
172
173static void CopyPStr(StringPtr src, StringPtr dest)
174{
175 BlockMoveData(src, dest, 1 + src[0]);
176}
177
178static char GetSelectKey(void)
179{
180 // this is the key used to trigger the select button
181
182 // NOT INTERNATIONAL SAVVY; should at least grab it from resources
183
184 return 's';
185}
186
187// FlashButton briefly highlights the dialog button
188// as feedback for key equivalents
189
190static void FlashButton(DialogPtr theDlgPtr, short buttonID)
191{
192 short buttonType;
193 Handle buttonHandle;
194 Rect buttonRect;
195 unsigned long finalTicks;
196
197 GetDialogItem(theDlgPtr, buttonID, &buttonType, &buttonHandle, &buttonRect);
198 HiliteControl((ControlHandle) buttonHandle, kControlButtonPart);
199 Delay(10, &finalTicks);
200 HiliteControl((ControlHandle) buttonHandle, 0);
201}
202
203static Boolean SameFSSpec(FSSpecPtr spec1, FSSpecPtr spec2)
204{
205 return (spec1->vRefNum == spec2->vRefNum
206 && spec1->parID == spec2->parID
207 && EqualString(spec1->name, spec2->name, false, false));
208}
209// MyModalDialogFilter maps a key to the Select button, and handles
210// flashing of the button when the key is hit
211
212static pascal Boolean SFGetFolderModalDialogFilter(DialogPtr theDlgPtr, EventRecord *eventRec,
213 short *item, Ptr dataPtr)
214{
215#pragma unused (dataPtr)
216
217 // make certain the proper dialog is showing, 'cause standard file
218 // can nest dialogs but calls the same filter for each
219
220 if (((WindowPeek) theDlgPtr)->refCon == sfMainDialogRefCon)
221 {
222 // check if the select button was hit
223 /*
224 if ((eventRec->what == keyDown)
225 && (eventRec->modifiers & cmdKey)
226 && ((eventRec->message & charCodeMask) == GetSelectKey()))
227 {
228 *item = kSelectItem;
229 FlashButton(theDlgPtr, kSelectItem);
230 return true;
231 }
232 */
233 }
234
235 return false;
236}
5b781a67 237#endif !TARGET_CARBON
519cb848
SC
238
239void ExtendedOpenFile( ConstStr255Param message , ConstStr255Param path , const char *filter , FileFilterYDUPP fileFilter, StandardFileReply *theSFR)
240{
241 Point thePt;
242 OpenUserDataRec myData;
243 FSSpec tempSpec;
244 Boolean folderFlag;
245 Boolean wasAliasedFlag;
246 DlgHookYDUPP dlgHookUPP;
247 ModalFilterYDUPP myModalFilterUPP;
248 OSErr err;
249 SFTypeList types ;
250
251
252 // presumably we're running System 7 or later so CustomGetFile is
253 // available
254
255 // set initial contents of Select button to a space
256
2f1ae414 257 memcpy( theSFR->sfFile.name , "\p " , 2 ) ;
519cb848
SC
258
259 // point the user data parameter at the reply record so we can get to it later
260
261 myData.sfrPtr = theSFR;
262 if ( filter && filter[0] )
263 {
264 myData.numfilters = 1 ;
265 for ( int i = 0 ; i < myData.numfilters ; i++ )
266 {
267 int j ;
268
269 strcpy( myData.filter[i] , filter ) ;
270 for( j = 0 ; myData.filter[i][j] ; j++ )
271 {
272 myData.filter[i][j] = toupper( myData.filter[i][j] ) ;
273 }
274 for ( j = 0 ; gfilters[j] ; j++ )
275 {
276 if ( strcmp( myData.filter[i] , gfilters[j] ) == 0 )
277 {
278 myData.filtermactypes[i] = gfiltersmac[j] ;
279 break ;
280 }
281 }
282 if( gfilters[j] == NULL )
283 {
284 myData.filtermactypes[i] = '****' ;
285 }
286 }
287 }
288 else
289 {
290 myData.numfilters = 0 ;
291 }
292 // display the dialog
2f1ae414
SC
293
294#if !TARGET_CARBON
519cb848
SC
295
296 dlgHookUPP = NULL ;
297// dlgHookUPP = NewDlgHookYDProc(SFGetFolderDialogHook);
298 myModalFilterUPP = NewModalFilterYDProc(SFGetFolderModalDialogFilter);
299
300 thePt.h = thePt.v = -1; // center dialog
301
302 ParamText( message , NULL , NULL , NULL ) ;
303
304 CustomGetFile( fileFilter,
305 -1, // show all types
306 NULL,
307 theSFR,
308 kSFGetFileDlgID,
309 thePt, // top left point
310 dlgHookUPP,
311 myModalFilterUPP,
312 nil, // activate list
313 nil, // activate proc
314 &myData);
315
316 DisposeRoutineDescriptor(dlgHookUPP);
317 DisposeRoutineDescriptor(myModalFilterUPP);
2f1ae414
SC
318#else
319#endif
519cb848
SC
320 // if cancel wasn't pressed and no fatal error occurred...
321
322 if (theSFR->sfGood)
323 {
324 // if no name is in the reply record file spec,
325 // use the file spec of the parent folder
326
327 if (theSFR->sfFile.name[0] == '\0')
328 {
329 err = FSMakeFSSpec(theSFR->sfFile.vRefNum, theSFR->sfFile.parID,
330 "\p", &tempSpec);
331 if (err == noErr)
332 {
333 theSFR->sfFile = tempSpec;
334 }
335 else
336 {
337 // no name to return, forget it
338
339 theSFR->sfGood = false;
340 }
341 }
342
343 // if there is now a name in the file spec, check if it's
344 // for a folder or a volume
345
346 if (theSFR->sfFile.name[0] != '\0')
347 {
348 // the parID of the root of a disk is always fsRtParID == 1
349
350 if (theSFR->sfFile.parID == fsRtParID)
351 {
352 theSFR->sfIsVolume = true;
353 theSFR->sfIsFolder = false; // it would be reasonable for this to be true, too
354 }
355
356 // we have a valid FSSpec, now let's make sure it's not for an alias file
357
358 err = ResolveAliasFile(&theSFR->sfFile, true, &folderFlag, &wasAliasedFlag);
359 if (err != noErr)
360 {
361 theSFR->sfGood = false;
362 }
363
364 // did the alias resolve to a folder?
365
366 if (folderFlag && ! theSFR->sfIsVolume)
367 {
368 theSFR->sfIsFolder = true;
369 }
370 }
371 }
372}
373
374static pascal Boolean CrossPlatformFileFilter(CInfoPBPtr myCInfoPBPtr, Ptr dataPtr)
375{
376 Str255 filename ;
377 OpenUserDataRecPtr data = (OpenUserDataRecPtr) dataPtr ;
378 // return true if this item is invisible or a file
379
380 Boolean visibleFlag;
381 Boolean folderFlag;
382
383 visibleFlag = ! (myCInfoPBPtr->hFileInfo.ioFlFndrInfo.fdFlags & kIsInvisible);
384 folderFlag = (myCInfoPBPtr->hFileInfo.ioFlAttrib & 0x10);
385
386 // because the semantics of the filter proc are "true means don't show
387 // it" we need to invert the result that we return
388
389 if ( !visibleFlag )
390 return true ;
391
392 if ( !folderFlag )
393 {
394 if ( data->numfilters > 0 )
395 {
396 PLstrcpy( filename ,myCInfoPBPtr->hFileInfo.ioNamePtr ) ;
397 if ( filename[0] >= 4 )
398 {
399 for( int j = 1 ; j <= filename[0] ; j++ )
400 {
401 filename[j] = toupper( filename[j] ) ;
402 }
403 for ( int i = 0 ; i < data->numfilters ; ++i )
404 {
405 if ( myCInfoPBPtr->hFileInfo.ioFlFndrInfo.fdType == data->filtermactypes[i] )
406 return false ;
407
408 if ( strncmp( (char*) filename + 1 + filename[0] - 4 ,
409 & data->filter[i][ strlen(data->filter[i]) - 4 ] , 4 ) == 0 )
410 return false ;
411 }
412 }
413 return true ;
414 }
415 }
416
417 return false ;
418}
419
420// end wxmac
421
422wxString wxFileSelector(const char *title,
e9576ca5
SC
423 const char *defaultDir, const char *defaultFileName,
424 const char *defaultExtension, const char *filter, int flags,
425 wxWindow *parent, int x, int y)
426{
427 // If there's a default extension specified but no filter, we create a suitable
428 // filter.
429
430 wxString filter2("");
431 if ( defaultExtension && !filter )
432 filter2 = wxString("*.") + wxString(defaultExtension) ;
433 else if ( filter )
434 filter2 = filter;
435
436 wxString defaultDirString;
437 if (defaultDir)
438 defaultDirString = defaultDir;
439 else
440 defaultDirString = "";
441
442 wxString defaultFilenameString;
443 if (defaultFileName)
444 defaultFilenameString = defaultFileName;
445 else
446 defaultFilenameString = "";
447
448 wxFileDialog fileDialog(parent, title, defaultDirString, defaultFilenameString, filter2, flags, wxPoint(x, y));
449
450 if ( fileDialog.ShowModal() == wxID_OK )
451 {
452 strcpy(wxBuffer, (const char *)fileDialog.GetPath());
453 return wxBuffer;
454 }
455 else
8be97d65 456 return wxGetEmptyString();
e9576ca5
SC
457}
458
169935ad 459WXDLLEXPORT wxString wxFileSelectorEx(const char *title,
e9576ca5
SC
460 const char *defaultDir,
461 const char *defaultFileName,
462 int* defaultFilterIndex,
463 const char *filter,
464 int flags,
465 wxWindow* parent,
466 int x,
467 int y)
468
469{
470 wxFileDialog fileDialog(parent, title ? title : "", defaultDir ? defaultDir : "",
471 defaultFileName ? defaultFileName : "", filter ? filter : "", flags, wxPoint(x, y));
472
473 if ( fileDialog.ShowModal() == wxID_OK )
474 {
475 *defaultFilterIndex = fileDialog.GetFilterIndex();
476 strcpy(wxBuffer, (const char *)fileDialog.GetPath());
477 return wxBuffer;
478 }
479 else
8be97d65 480 return wxGetEmptyString();
e9576ca5
SC
481}
482
483wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message,
484 const wxString& defaultDir, const wxString& defaultFileName, const wxString& wildCard,
485 long style, const wxPoint& pos)
486{
487 m_message = message;
488 m_dialogStyle = style;
489 m_parent = parent;
490 m_path = "";
491 m_fileName = defaultFileName;
492 m_dir = defaultDir;
493 m_wildCard = wildCard;
494 m_filterIndex = 1;
495}
496
497int wxFileDialog::ShowModal()
498{
5b781a67
SC
499 #if !TARGET_CARBON
500 if ( !gUseNavServices )
501 {
519cb848
SC
502 if ( m_dialogStyle & wxSAVE )
503 {
504 StandardFileReply reply ;
505 Str255 prompt ;
506 Str255 filename ;
507
03e11df5
GD
508#if TARGET_CARBON
509 c2pstrcpy((StringPtr)prompt, m_message) ;
510#else
519cb848
SC
511 strcpy((char *)prompt, m_message) ;
512 c2pstr((char *)prompt ) ;
03e11df5
GD
513#endif
514#if TARGET_CARBON
515 c2pstrcpy((StringPtr)filename, m_fileName) ;
516#else
519cb848
SC
517 strcpy((char *)filename, m_fileName) ;
518 c2pstr((char *)filename ) ;
03e11df5
GD
519#endif
520
2f1ae414 521 #if !TARGET_CARBON
519cb848
SC
522
523 StandardPutFile( prompt , filename , &reply ) ;
2f1ae414
SC
524
525 #else
526 #endif
519cb848
SC
527 if ( reply.sfGood == false )
528 {
529 m_path = "" ;
530 return wxID_CANCEL ;
531 }
532 else
533 {
534 m_path = wxMacFSSpec2UnixFilename( &reply.sfFile ) ;
535 return wxID_OK ;
536 }
537 }
538 else
539 {
540 OSType types = '????' ;
541 Str255 prompt ;
542 Str255 path ;
543
03e11df5
GD
544#if TARGET_CARBON
545 c2pstrcpy((StringPtr)prompt, m_message) ;
546#else
519cb848
SC
547 strcpy((char *)prompt, m_message) ;
548 c2pstr((char *)prompt ) ;
03e11df5
GD
549#endif
550#if TARGET_CARBON
551 c2pstrcpy((StringPtr)path, m_dir ) ;
552#else
553 strcpy((char *)path, m_dir ) ;
519cb848 554 c2pstr((char *)path ) ;
03e11df5 555#endif
519cb848 556
519cb848 557 StandardFileReply reply ;
2f1ae414
SC
558 FileFilterYDUPP crossPlatformFileFilterUPP = 0 ;
559 #if !TARGET_CARBON
519cb848
SC
560 crossPlatformFileFilterUPP =
561 NewFileFilterYDProc(CrossPlatformFileFilter);
2f1ae414 562 #endif
519cb848
SC
563
564 ExtendedOpenFile( prompt , path , m_wildCard , crossPlatformFileFilterUPP, &reply);
2f1ae414
SC
565 #if !TARGET_CARBON
566 DisposeFileFilterYDUPP(crossPlatformFileFilterUPP);
567 #endif
519cb848
SC
568 if ( reply.sfGood == false )
569 {
570 m_path = "" ;
571 return wxID_CANCEL ;
572 }
573 else
574 {
575 m_path = wxMacFSSpec2UnixFilename( &reply.sfFile ) ;
576 return wxID_OK ;
577 }
578 }
e9576ca5
SC
579 return wxID_CANCEL;
580}
5b781a67
SC
581 else
582#endif
583 {
584 NavDialogOptions mNavOptions;
585 NavObjectFilterUPP mNavFilterUPP = NULL;
586 NavPreviewUPP mNavPreviewUPP = NULL ;
587 NavReplyRecord mNavReply;
588 AEDesc mDefaultLocation ;
589 bool mSelectDefault = false ;
590
591 ::NavGetDefaultDialogOptions(&mNavOptions);
592
593 mNavFilterUPP = nil;
594 mNavPreviewUPP = nil;
595 mSelectDefault = false;
596 mNavReply.validRecord = false;
597 mNavReply.replacing = false;
598 mNavReply.isStationery = false;
599 mNavReply.translationNeeded = false;
600 mNavReply.selection.descriptorType = typeNull;
601 mNavReply.selection.dataHandle = nil;
602 mNavReply.keyScript = smSystemScript;
603 mNavReply.fileTranslation = nil;
604
605 // Set default location, the location
606 // that's displayed when the dialog
607 // first appears
608
609 FSSpec location ;
610 wxUnixFilename2FSSpec( m_dir , &location ) ;
611 OSErr err = noErr ;
612
613 mDefaultLocation.descriptorType = typeNull;
614 mDefaultLocation.dataHandle = nil;
615
616 err = ::AECreateDesc(typeFSS, &location, sizeof(FSSpec), &mDefaultLocation );
617
618 if ( mDefaultLocation.dataHandle ) {
619
620 if (mSelectDefault) {
621 mNavOptions.dialogOptionFlags |= kNavSelectDefaultLocation;
622 } else {
623 mNavOptions.dialogOptionFlags &= ~kNavSelectDefaultLocation;
624 }
625 }
626
03e11df5
GD
627#if TARGET_CARBON
628 c2pstrcpy((StringPtr)mNavOptions.message, m_message) ;
629#else
5b781a67
SC
630 strcpy((char *)mNavOptions.message, m_message) ;
631 c2pstr((char *)mNavOptions.message ) ;
03e11df5
GD
632#endif
633#if TARGET_CARBON
634 c2pstrcpy((StringPtr)mNavOptions.savedFileName, m_fileName) ;
635#else
5b781a67
SC
636 strcpy((char *)mNavOptions.savedFileName, m_fileName) ;
637 c2pstr((char *)mNavOptions.savedFileName ) ;
03e11df5 638#endif
5b781a67
SC
639
640 if ( m_dialogStyle & wxSAVE )
641 {
642
643 mNavOptions.dialogOptionFlags |= kNavNoTypePopup ;
644 mNavOptions.dialogOptionFlags |= kNavDontAutoTranslate ;
645 mNavOptions.dialogOptionFlags |= kNavDontAddTranslateItems ;
646
647 err = ::NavPutFile(
648 &mDefaultLocation,
649 &mNavReply,
650 &mNavOptions,
651 sStandardNavEventFilter ,
652 'TEXT',
653 'TEXT',
654 0L); // User Data
655 }
656 else
657 {
658 if ( m_dialogStyle & wxMULTIPLE )
659 mNavOptions.dialogOptionFlags |= kNavAllowMultipleFiles ;
660 else
661 mNavOptions.dialogOptionFlags &= ~kNavAllowMultipleFiles ;
662
663 err = ::NavGetFile(
664 &mDefaultLocation,
665 &mNavReply,
666 &mNavOptions,
667 sStandardNavEventFilter ,
668 mNavPreviewUPP,
669 mNavFilterUPP,
670 0L /*inFileTypes.TypeListHandle() */,
671 0L); // User Data
672 }
673
674 if ( mDefaultLocation.dataHandle != nil )
675 {
676 ::AEDisposeDesc(&mDefaultLocation);
677 }
678
679 if ( (err != noErr) && (err != userCanceledErr) ) {
680 m_path = "" ;
681 return wxID_CANCEL ;
682 }
683
684 if (mNavReply.validRecord) {
685
686 FSSpec outFileSpec ;
687 AEDesc specDesc ;
688
689 long count ;
690 ::AECountItems( &mNavReply.selection , &count ) ;
691 for ( long i = 1 ; i <= count ; ++i )
692 {
693 OSErr err = ::AEGetNthDesc( &mNavReply.selection , i , typeFSS, NULL , &specDesc);
694 if ( err != noErr ) {
695 m_path = "" ;
696 return wxID_CANCEL ;
697 }
698 outFileSpec = **(FSSpec**) specDesc.dataHandle;
699 if (specDesc.dataHandle != nil) {
700 ::AEDisposeDesc(&specDesc);
701 }
702
703
704 // outFolderDirID = thePB.dirInfo.ioDrDirID;
705 m_path = wxMacFSSpec2UnixFilename( &outFileSpec ) ;
706 m_paths.Add( m_path ) ;
707 m_fileNames.Add(m_fileName);
708 }
709 // set these to the first hit
710 m_path = m_paths[ 0 ] ;
711 m_fileName = wxFileNameFromPath(m_path);
712 m_dir = wxPathOnly(m_path);
713
714 return wxID_OK ;
715 }
716 return wxID_CANCEL;
717 }
718}
e9576ca5
SC
719
720// Generic file load/save dialog
169935ad 721static wxString
e9576ca5
SC
722wxDefaultFileSelector(bool load, const char *what, const char *extension, const char *default_name, wxWindow *parent)
723{
724 char *ext = (char *)extension;
725
726 char prompt[50];
727 wxString str;
728 if (load)
729 str = "Load %s file";
730 else
731 str = "Save %s file";
732 sprintf(prompt, wxGetTranslation(str), what);
733
734 if (*ext == '.') ext++;
735 char wild[60];
736 sprintf(wild, "*.%s", ext);
737
738 return wxFileSelector (prompt, NULL, default_name, ext, wild, 0, parent);
739}
740
741// Generic file load dialog
169935ad 742wxString
e9576ca5
SC
743wxLoadFileSelector(const char *what, const char *extension, const char *default_name, wxWindow *parent)
744{
745 return wxDefaultFileSelector(TRUE, what, extension, default_name, parent);
746}
747
748
749// Generic file save dialog
169935ad 750wxString
e9576ca5
SC
751wxSaveFileSelector(const char *what, const char *extension, const char *default_name, wxWindow *parent)
752{
753 return wxDefaultFileSelector(FALSE, what, extension, default_name, parent);
754}
755
756