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