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