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