]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/filedlg.cpp
checklist implementation
[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 #include "wx/tokenzr.h"
23
24 #ifndef __DARWIN__
25 #include "PLStringFuncs.h"
26 #endif
27
28 #if !USE_SHARED_LIBRARY
29 IMPLEMENT_CLASS(wxFileDialog, wxDialog)
30 #endif
31
32 // begin wxmac
33
34 #include <Navigation.h>
35
36 #include "MoreFiles.h"
37 #include "MoreFilesExtras.h"
38
39 extern 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
47 const int kwxMacFileTypes = 10 ;
48
49 struct OpenUserDataRec {
50 int currentfilter ;
51 wxString name [kwxMacFileTypes] ;
52 wxString extensions[kwxMacFileTypes] ;
53 OSType filtermactypes[kwxMacFileTypes] ;
54 int numfilters ;
55 };
56 typedef struct OpenUserDataRec
57 OpenUserDataRec, *OpenUserDataRecPtr;
58
59 static 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
70 static pascal void
71 NavEventProc(
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
96 const char * gfilters[] =
97 {
98 "*.TXT" ,
99 "*.TIF" ,
100 "*.JPG" ,
101
102 NULL
103 } ;
104
105 OSType gfiltersmac[] =
106 {
107 'TEXT' ,
108 'TIFF' ,
109 'JPEG' ,
110
111 '****'
112 } ;
113
114
115 #if !TARGET_CARBON
116
117 static 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
125 static 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
159 enum {
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
171 static void GetLabelString(StringPtr theStr, short stringNum)
172 {
173 GetIndString(theStr, kStrListID, stringNum);
174 }
175
176 static void CopyPStr(StringPtr src, StringPtr dest)
177 {
178 BlockMoveData(src, dest, 1 + src[0]);
179 }
180
181 static 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
193 static 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
206 static 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
215 static 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
242 void 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__
304 void 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
410 static 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__
451 static 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
479 wxString 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
516 WXDLLEXPORT 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
540 wxFileDialog::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
555 pascal 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
579 int 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
807 static wxString
808 wxDefaultFileSelector(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
828 wxString
829 wxLoadFileSelector(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
836 wxString
837 wxSaveFileSelector(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