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