]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/filedlg.cpp
fixed crash in HitTest() with y position below the last line
[wxWidgets.git] / src / mac / carbon / filedlg.cpp
CommitLineData
e9576ca5
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: filedlg.cpp
2f1ae414 3// Purpose: wxFileDialog
e9576ca5
SC
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"
5fde6fcc 17#include "wx/app.h"
e9576ca5
SC
18#include "wx/utils.h"
19#include "wx/dialog.h"
20#include "wx/filedlg.h"
21#include "wx/intl.h"
22
f11bdd03 23#ifndef __DARWIN__
03e11df5
GD
24 #include "PLStringFuncs.h"
25#endif
5b781a67 26
2f1ae414 27#if !USE_SHARED_LIBRARY
e9576ca5 28IMPLEMENT_CLASS(wxFileDialog, wxDialog)
2f1ae414 29#endif
e9576ca5 30
519cb848
SC
31// begin wxmac
32
f11bdd03 33#ifndef __DARWIN__
03e11df5
GD
34 #include <Navigation.h>
35#endif
5b781a67 36
f11bdd03 37#ifndef __DARWIN__
03e11df5
GD
38 #include "morefile.h"
39 #include "moreextr.h"
40 #include "fullpath.h"
41 #include "fspcompa.h"
42 #include "PLStringFuncs.h"
43#endif
519cb848 44
5b781a67
SC
45extern bool gUseNavServices ;
46
4d4d8bbf
SC
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
53const int kwxMacFileTypes = 10 ;
54
55struct OpenUserDataRec {
56 int currentfilter ;
57 wxString name [kwxMacFileTypes] ;
58 wxString extensions[kwxMacFileTypes] ;
59 OSType filtermactypes[kwxMacFileTypes] ;
60 int numfilters ;
61};
62typedef struct OpenUserDataRec
63 OpenUserDataRec, *OpenUserDataRecPtr;
64
5b781a67
SC
65static 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
76static pascal void
77NavEventProc(
78 NavEventCallbackMessage inSelector,
79 NavCBRecPtr ioParams,
4d4d8bbf 80 NavCallBackUserData ioUserData )
5b781a67 81{
4d4d8bbf 82 OpenUserDataRec * data = ( OpenUserDataRec *) ioUserData ;
5b781a67
SC
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
5fde6fcc 94 wxTheApp->MacHandleOneEvent(ioParams->eventData.eventDataParms.event);
4d4d8bbf
SC
95 } else if ( inSelector == kNavCBPopupMenuSelect )
96 {
97 NavMenuItemSpec * menu = (NavMenuItemSpec *) ioParams->eventData.eventDataParms.param ;
98 data->currentfilter = menu->menuType ;
5b781a67
SC
99 }
100}
101
519cb848
SC
102char * gfilters[] =
103{
104 "*.TXT" ,
4d4d8bbf
SC
105 "*.TIF" ,
106 "*.JPG" ,
519cb848
SC
107
108 NULL
109} ;
110
111OSType gfiltersmac[] =
112{
113 'TEXT' ,
4d4d8bbf
SC
114 'TIFF' ,
115 'JPEG' ,
519cb848
SC
116
117 '****'
118} ;
119
2f1ae414
SC
120
121#if !TARGET_CARBON
122
519cb848
SC
123static 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
131static 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
165enum {
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
519cb848
SC
177static void GetLabelString(StringPtr theStr, short stringNum)
178{
179 GetIndString(theStr, kStrListID, stringNum);
180}
181
182static void CopyPStr(StringPtr src, StringPtr dest)
183{
184 BlockMoveData(src, dest, 1 + src[0]);
185}
186
187static 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
199static 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
212static 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
221static pascal Boolean SFGetFolderModalDialogFilter(DialogPtr theDlgPtr, EventRecord *eventRec,
5fde6fcc 222 short *item, void *dataPtr)
519cb848
SC
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}
5b781a67 246#endif !TARGET_CARBON
519cb848 247
4d4d8bbf
SC
248void 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}
308void ExtendedOpenFile( ConstStr255Param message , ConstStr255Param path , const char *filter , FileFilterYDUPP fileFilter, StandardFileReply *theSFR )
519cb848
SC
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
2f1ae414 326 memcpy( theSFR->sfFile.name , "\p " , 2 ) ;
519cb848
SC
327
328 // point the user data parameter at the reply record so we can get to it later
329
4d4d8bbf 330 MakeUserDataRec( &myData , filter ) ;
519cb848 331 // display the dialog
2f1ae414
SC
332
333#if !TARGET_CARBON
519cb848
SC
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);
2f1ae414
SC
357#else
358#endif
519cb848
SC
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
4d4d8bbf
SC
413static Boolean CheckFile( ConstStr255Param name , OSType type , OpenUserDataRecPtr data)
414{
415 Str255 filename ;
416 PLstrcpy( filename , name ) ;
9f92f6fb
SC
417 p2cstr( filename ) ;
418 wxString file(filename) ;
419 file.MakeUpper() ;
420
4d4d8bbf
SC
421 if ( data->numfilters > 0 )
422 {
4d4d8bbf
SC
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
9f92f6fb 436 if ( file.Len() >= extension.Len() && extension == file.Right(extension.Len() ) )
4d4d8bbf
SC
437 return true ;
438 }
439 return false ;
440 }
441 return true ;
442}
443
5fde6fcc 444static pascal Boolean CrossPlatformFileFilter(CInfoPBPtr myCInfoPBPtr, void *dataPtr)
519cb848 445{
519cb848
SC
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 {
4d4d8bbf 463 return !CheckFile( myCInfoPBPtr->hFileInfo.ioNamePtr , myCInfoPBPtr->hFileInfo.ioFlFndrInfo.fdType , data ) ;
519cb848
SC
464 }
465
466 return false ;
467}
468
469// end wxmac
470
471wxString wxFileSelector(const char *title,
e9576ca5
SC
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
8be97d65 505 return wxGetEmptyString();
e9576ca5
SC
506}
507
169935ad 508WXDLLEXPORT wxString wxFileSelectorEx(const char *title,
e9576ca5
SC
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
8be97d65 529 return wxGetEmptyString();
e9576ca5
SC
530}
531
532wxFileDialog::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
4d4d8bbf 546
f11bdd03 547pascal Boolean CrossPlatformFilterCallback (
4d4d8bbf
SC
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
e9576ca5
SC
571int wxFileDialog::ShowModal()
572{
5b781a67
SC
573 #if !TARGET_CARBON
574 if ( !gUseNavServices )
575 {
519cb848
SC
576 if ( m_dialogStyle & wxSAVE )
577 {
578 StandardFileReply reply ;
579 Str255 prompt ;
580 Str255 filename ;
581
03e11df5
GD
582#if TARGET_CARBON
583 c2pstrcpy((StringPtr)prompt, m_message) ;
584#else
519cb848
SC
585 strcpy((char *)prompt, m_message) ;
586 c2pstr((char *)prompt ) ;
03e11df5
GD
587#endif
588#if TARGET_CARBON
589 c2pstrcpy((StringPtr)filename, m_fileName) ;
590#else
519cb848
SC
591 strcpy((char *)filename, m_fileName) ;
592 c2pstr((char *)filename ) ;
03e11df5
GD
593#endif
594
2f1ae414 595 #if !TARGET_CARBON
519cb848
SC
596
597 StandardPutFile( prompt , filename , &reply ) ;
2f1ae414
SC
598
599 #else
600 #endif
519cb848
SC
601 if ( reply.sfGood == false )
602 {
603 m_path = "" ;
604 return wxID_CANCEL ;
605 }
606 else
607 {
bedaf53e 608 m_path = wxMacFSSpec2MacFilename( &reply.sfFile ) ;
519cb848
SC
609 return wxID_OK ;
610 }
611 }
612 else
613 {
614 OSType types = '????' ;
615 Str255 prompt ;
616 Str255 path ;
617
03e11df5
GD
618#if TARGET_CARBON
619 c2pstrcpy((StringPtr)prompt, m_message) ;
620#else
519cb848
SC
621 strcpy((char *)prompt, m_message) ;
622 c2pstr((char *)prompt ) ;
03e11df5
GD
623#endif
624#if TARGET_CARBON
625 c2pstrcpy((StringPtr)path, m_dir ) ;
626#else
627 strcpy((char *)path, m_dir ) ;
519cb848 628 c2pstr((char *)path ) ;
03e11df5 629#endif
519cb848 630
519cb848 631 StandardFileReply reply ;
2f1ae414
SC
632 FileFilterYDUPP crossPlatformFileFilterUPP = 0 ;
633 #if !TARGET_CARBON
519cb848
SC
634 crossPlatformFileFilterUPP =
635 NewFileFilterYDProc(CrossPlatformFileFilter);
2f1ae414 636 #endif
519cb848
SC
637
638 ExtendedOpenFile( prompt , path , m_wildCard , crossPlatformFileFilterUPP, &reply);
2f1ae414
SC
639 #if !TARGET_CARBON
640 DisposeFileFilterYDUPP(crossPlatformFileFilterUPP);
641 #endif
519cb848
SC
642 if ( reply.sfGood == false )
643 {
644 m_path = "" ;
645 return wxID_CANCEL ;
646 }
647 else
648 {
bedaf53e 649 m_path = wxMacFSSpec2MacFilename( &reply.sfFile ) ;
519cb848
SC
650 return wxID_OK ;
651 }
652 }
e9576ca5
SC
653 return wxID_CANCEL;
654}
5b781a67
SC
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 ;
bedaf53e 684 wxMacFilename2FSSpec( m_dir , &location ) ;
5b781a67
SC
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
03e11df5
GD
701#if TARGET_CARBON
702 c2pstrcpy((StringPtr)mNavOptions.message, m_message) ;
703#else
5b781a67
SC
704 strcpy((char *)mNavOptions.message, m_message) ;
705 c2pstr((char *)mNavOptions.message ) ;
03e11df5
GD
706#endif
707#if TARGET_CARBON
708 c2pstrcpy((StringPtr)mNavOptions.savedFileName, m_fileName) ;
709#else
5b781a67
SC
710 strcpy((char *)mNavOptions.savedFileName, m_fileName) ;
711 c2pstr((char *)mNavOptions.savedFileName ) ;
03e11df5 712#endif
5b781a67
SC
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 {
4d4d8bbf
SC
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
f11bdd03 752 mNavFilterUPP = NewNavObjectFilterUPP( CrossPlatformFilterCallback ) ;
5b781a67
SC
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,
4d4d8bbf
SC
765 typelist /*inFileTypes.TypeListHandle() */,
766 &myData); // User Data
767 if ( typelist )
768 DisposeHandle( (Handle) typelist ) ;
5b781a67
SC
769 }
770
4d4d8bbf 771 DisposeNavObjectFilterUPP(mNavFilterUPP);
5b781a67
SC
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;
bedaf53e 803 m_path = wxMacFSSpec2MacFilename( &outFileSpec ) ;
5b781a67
SC
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}
e9576ca5
SC
817
818// Generic file load/save dialog
169935ad 819static wxString
e9576ca5
SC
820wxDefaultFileSelector(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
169935ad 840wxString
e9576ca5
SC
841wxLoadFileSelector(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
169935ad 848wxString
e9576ca5
SC
849wxSaveFileSelector(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