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