]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/filedlg.cpp
toplevel fixes
[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 #if TARGET_CARBON
564 ::AEGetDescData(theItem, &spec, sizeof(FSSpec) ) ;
565 #else
566 memcpy( &spec , (*theItem->dataHandle) , sizeof(FSSpec) ) ;
567 #endif
568 display = CheckFile( spec.name , theInfo->fileAndFolder.fileInfo.finderInfo.fdType , data ) ;
569 }
570 }
571
572 return display;
573 }
574
575 int wxFileDialog::ShowModal()
576 {
577 #if !TARGET_CARBON
578 if ( !gUseNavServices )
579 {
580 if ( m_dialogStyle & wxSAVE )
581 {
582 StandardFileReply reply ;
583 Str255 prompt ;
584 Str255 filename ;
585
586 #if TARGET_CARBON
587 c2pstrcpy((StringPtr)prompt, m_message) ;
588 #else
589 strcpy((char *)prompt, m_message) ;
590 c2pstr((char *)prompt ) ;
591 #endif
592 #if TARGET_CARBON
593 c2pstrcpy((StringPtr)filename, m_fileName) ;
594 #else
595 strcpy((char *)filename, m_fileName) ;
596 c2pstr((char *)filename ) ;
597 #endif
598
599 #if !TARGET_CARBON
600
601 StandardPutFile( prompt , filename , &reply ) ;
602
603 #else
604 #endif
605 if ( reply.sfGood == false )
606 {
607 m_path = "" ;
608 return wxID_CANCEL ;
609 }
610 else
611 {
612 m_path = wxMacFSSpec2MacFilename( &reply.sfFile ) ;
613 return wxID_OK ;
614 }
615 }
616 else
617 {
618 OSType types = '????' ;
619 Str255 prompt ;
620 Str255 path ;
621
622 #if TARGET_CARBON
623 c2pstrcpy((StringPtr)prompt, m_message) ;
624 #else
625 strcpy((char *)prompt, m_message) ;
626 c2pstr((char *)prompt ) ;
627 #endif
628 #if TARGET_CARBON
629 c2pstrcpy((StringPtr)path, m_dir ) ;
630 #else
631 strcpy((char *)path, m_dir ) ;
632 c2pstr((char *)path ) ;
633 #endif
634
635 StandardFileReply reply ;
636 FileFilterYDUPP crossPlatformFileFilterUPP = 0 ;
637 #if !TARGET_CARBON
638 crossPlatformFileFilterUPP =
639 NewFileFilterYDProc(CrossPlatformFileFilter);
640 #endif
641
642 ExtendedOpenFile( prompt , path , m_wildCard , crossPlatformFileFilterUPP, &reply);
643 #if !TARGET_CARBON
644 DisposeFileFilterYDUPP(crossPlatformFileFilterUPP);
645 #endif
646 if ( reply.sfGood == false )
647 {
648 m_path = "" ;
649 return wxID_CANCEL ;
650 }
651 else
652 {
653 m_path = wxMacFSSpec2MacFilename( &reply.sfFile ) ;
654 return wxID_OK ;
655 }
656 }
657 return wxID_CANCEL;
658 }
659 else
660 #endif
661 {
662 NavDialogOptions mNavOptions;
663 NavObjectFilterUPP mNavFilterUPP = NULL;
664 NavPreviewUPP mNavPreviewUPP = NULL ;
665 NavReplyRecord mNavReply;
666 AEDesc mDefaultLocation ;
667 bool mSelectDefault = false ;
668
669 ::NavGetDefaultDialogOptions(&mNavOptions);
670
671 mNavFilterUPP = nil;
672 mNavPreviewUPP = nil;
673 mSelectDefault = false;
674 mNavReply.validRecord = false;
675 mNavReply.replacing = false;
676 mNavReply.isStationery = false;
677 mNavReply.translationNeeded = false;
678 mNavReply.selection.descriptorType = typeNull;
679 mNavReply.selection.dataHandle = nil;
680 mNavReply.keyScript = smSystemScript;
681 mNavReply.fileTranslation = nil;
682
683 // Set default location, the location
684 // that's displayed when the dialog
685 // first appears
686
687 FSSpec location ;
688 wxMacFilename2FSSpec( m_dir , &location ) ;
689 OSErr err = noErr ;
690
691 mDefaultLocation.descriptorType = typeNull;
692 mDefaultLocation.dataHandle = nil;
693
694 err = ::AECreateDesc(typeFSS, &location, sizeof(FSSpec), &mDefaultLocation );
695
696 if ( mDefaultLocation.dataHandle ) {
697
698 if (mSelectDefault) {
699 mNavOptions.dialogOptionFlags |= kNavSelectDefaultLocation;
700 } else {
701 mNavOptions.dialogOptionFlags &= ~kNavSelectDefaultLocation;
702 }
703 }
704
705 #if TARGET_CARBON
706 c2pstrcpy((StringPtr)mNavOptions.message, m_message) ;
707 #else
708 strcpy((char *)mNavOptions.message, m_message) ;
709 c2pstr((char *)mNavOptions.message ) ;
710 #endif
711 #if TARGET_CARBON
712 c2pstrcpy((StringPtr)mNavOptions.savedFileName, m_fileName) ;
713 #else
714 strcpy((char *)mNavOptions.savedFileName, m_fileName) ;
715 c2pstr((char *)mNavOptions.savedFileName ) ;
716 #endif
717
718 if ( m_dialogStyle & wxSAVE )
719 {
720
721 mNavOptions.dialogOptionFlags |= kNavNoTypePopup ;
722 mNavOptions.dialogOptionFlags |= kNavDontAutoTranslate ;
723 mNavOptions.dialogOptionFlags |= kNavDontAddTranslateItems ;
724
725 err = ::NavPutFile(
726 &mDefaultLocation,
727 &mNavReply,
728 &mNavOptions,
729 sStandardNavEventFilter ,
730 'TEXT',
731 'TEXT',
732 0L); // User Data
733 }
734 else
735 {
736 OpenUserDataRec myData;
737 MakeUserDataRec( &myData , m_wildCard ) ;
738 NavTypeListHandle typelist = NULL ;
739
740 if ( myData.numfilters > 0 )
741 {
742 mNavOptions.popupExtension = (NavMenuItemSpecArrayHandle) NewHandle( sizeof( NavMenuItemSpec ) * myData.numfilters ) ;
743 for ( int i = 0 ; i < myData.numfilters ; ++i ) {
744 (*mNavOptions.popupExtension)[i].version = kNavMenuItemSpecVersion ;
745 (*mNavOptions.popupExtension)[i].menuCreator = 'WXNG' ;
746 (*mNavOptions.popupExtension)[i].menuType = i ;
747 #if TARGET_CARBON
748 c2pstrcpy((StringPtr)(*mNavOptions.popupExtension)[i].menuItemName, myData.name[i]) ;
749 #else
750 strcpy((char *)(*mNavOptions.popupExtension)[i].menuItemName, myData.name[i]) ;
751 c2pstr((char *)(*mNavOptions.popupExtension)[i].menuItemName ) ;
752 #endif
753 }
754 }
755
756 mNavFilterUPP = NewNavObjectFilterUPP( CrossPlatformFilterCallback ) ;
757 if ( m_dialogStyle & wxMULTIPLE )
758 mNavOptions.dialogOptionFlags |= kNavAllowMultipleFiles ;
759 else
760 mNavOptions.dialogOptionFlags &= ~kNavAllowMultipleFiles ;
761
762 err = ::NavGetFile(
763 &mDefaultLocation,
764 &mNavReply,
765 &mNavOptions,
766 sStandardNavEventFilter ,
767 mNavPreviewUPP,
768 mNavFilterUPP,
769 typelist /*inFileTypes.TypeListHandle() */,
770 &myData); // User Data
771 if ( typelist )
772 DisposeHandle( (Handle) typelist ) ;
773 }
774
775 DisposeNavObjectFilterUPP(mNavFilterUPP);
776 if ( mDefaultLocation.dataHandle != nil )
777 {
778 ::AEDisposeDesc(&mDefaultLocation);
779 }
780
781 if ( (err != noErr) && (err != userCanceledErr) ) {
782 m_path = "" ;
783 return wxID_CANCEL ;
784 }
785
786 if (mNavReply.validRecord) {
787
788 FSSpec outFileSpec ;
789 AEDesc specDesc ;
790
791 long count ;
792 ::AECountItems( &mNavReply.selection , &count ) ;
793 for ( long i = 1 ; i <= count ; ++i )
794 {
795 OSErr err = ::AEGetNthDesc( &mNavReply.selection , i , typeFSS, NULL , &specDesc);
796 if ( err != noErr ) {
797 m_path = "" ;
798 return wxID_CANCEL ;
799 }
800 outFileSpec = **(FSSpec**) specDesc.dataHandle;
801 if (specDesc.dataHandle != nil) {
802 ::AEDisposeDesc(&specDesc);
803 }
804
805
806 // outFolderDirID = thePB.dirInfo.ioDrDirID;
807 m_path = wxMacFSSpec2MacFilename( &outFileSpec ) ;
808 m_paths.Add( m_path ) ;
809 m_fileNames.Add(m_fileName);
810 }
811 // set these to the first hit
812 m_path = m_paths[ 0 ] ;
813 m_fileName = wxFileNameFromPath(m_path);
814 m_dir = wxPathOnly(m_path);
815
816 return wxID_OK ;
817 }
818 return wxID_CANCEL;
819 }
820 }
821
822 // Generic file load/save dialog
823 static wxString
824 wxDefaultFileSelector(bool load, const char *what, const char *extension, const char *default_name, wxWindow *parent)
825 {
826 char *ext = (char *)extension;
827
828 char prompt[50];
829 wxString str;
830 if (load)
831 str = "Load %s file";
832 else
833 str = "Save %s file";
834 sprintf(prompt, wxGetTranslation(str), what);
835
836 if (*ext == '.') ext++;
837 char wild[60];
838 sprintf(wild, "*.%s", ext);
839
840 return wxFileSelector (prompt, NULL, default_name, ext, wild, 0, parent);
841 }
842
843 // Generic file load dialog
844 wxString
845 wxLoadFileSelector(const char *what, const char *extension, const char *default_name, wxWindow *parent)
846 {
847 return wxDefaultFileSelector(TRUE, what, extension, default_name, parent);
848 }
849
850
851 // Generic file save dialog
852 wxString
853 wxSaveFileSelector(const char *what, const char *extension, const char *default_name, wxWindow *parent)
854 {
855 return wxDefaultFileSelector(FALSE, what, extension, default_name, parent);
856 }
857
858