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