X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2f1ae4143271ae63a17e052a1a471d16e9cd8c44..793921582e924133aa0712d780d04b9a87ce2450:/src/mac/carbon/filedlg.cpp diff --git a/src/mac/carbon/filedlg.cpp b/src/mac/carbon/filedlg.cpp index 7837183e2a..59807f398d 100644 --- a/src/mac/carbon/filedlg.cpp +++ b/src/mac/carbon/filedlg.cpp @@ -1,11 +1,11 @@ ///////////////////////////////////////////////////////////////////////////// // Name: filedlg.cpp -// Purpose: wxFileDialog -// Author: AUTHOR +// Purpose: wxFileDialog +// Author: Stefan Csomor // Modified by: -// Created: ??/??/98 +// Created: 1998-01-01 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR +// Copyright: (c) Stefan Csomor // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -14,36 +14,36 @@ #endif #include "wx/defs.h" +#include "wx/app.h" #include "wx/utils.h" #include "wx/dialog.h" #include "wx/filedlg.h" #include "wx/intl.h" +#include "wx/tokenzr.h" +#include "wx/filename.h" + +#ifndef __DARWIN__ + #include "PLStringFuncs.h" +#endif #if !USE_SHARED_LIBRARY -IMPLEMENT_CLASS(wxFileDialog, wxDialog) +IMPLEMENT_CLASS(wxFileDialog, wxFileDialogBase) #endif // begin wxmac -#include "morefile.h" -#include "moreextr.h" -#include "fullpath.h" -#include "fspcompa.h" -#include "PLStringFuncs.h" +#include "wx/mac/private.h" -char * gfilters[] = -{ - "*.TXT" , - - NULL -} ; +#include -OSType gfiltersmac[] = -{ - 'TEXT' , - - '****' -} ; +#ifdef __DARWIN__ +# include "MoreFilesX.h" +#else +# include "MoreFiles.h" +# include "MoreFilesExtras.h" +#endif + +extern bool gUseNavServices ; // the data we need to pass to our standard file hook routine // includes a pointer to the dialog, a pointer to the standard @@ -51,505 +51,597 @@ OSType gfiltersmac[] = // and a copy of the "previous" file spec of the reply record // so we can see if the selection has changed -const int kwxMacFileTypes = 10 ; - struct OpenUserDataRec { - StandardFileReply *sfrPtr; - FSSpec oldSelectionFSSpec; - char filter[kwxMacFileTypes][10] ; - OSType filtermactypes[kwxMacFileTypes] ; - int numfilters ; - DialogPtr theDlgPtr; + int currentfilter ; + bool saveMode ; + wxArrayString name ; + wxArrayString extensions ; + wxArrayLong filtermactypes ; + wxString defaultLocation; +#if TARGET_CARBON + CFArrayRef menuitems ; +#else + NavMenuItemSpecArrayHandle menuitems ; +#endif }; + typedef struct OpenUserDataRec - OpenUserDataRec, *OpenUserDataRecPtr; +OpenUserDataRec, *OpenUserDataRecPtr; -#if !TARGET_CARBON +static pascal void NavEventProc( + NavEventCallbackMessage inSelector, + NavCBRecPtr ioParams, + NavCallBackUserData ioUserData); -static void wxMacSetupStandardFile(short newVRefNum, long newDirID) -{ - enum - { SFSaveDisk = 0x214, CurDirStore = 0x398 }; - *(short *) SFSaveDisk = -1 * newVRefNum; - *(long *) CurDirStore = newDirID; -} +#if TARGET_CARBON + static NavEventUPP sStandardNavEventFilter = NewNavEventUPP(NavEventProc); +#else + static NavEventUPP sStandardNavEventFilter = NewNavEventProc(NavEventProc); +#endif -static void wxMacSetupStandardFileFromPath( const char* s ) +static pascal void +NavEventProc( + NavEventCallbackMessage inSelector, + NavCBRecPtr ioParams, + NavCallBackUserData ioUserData ) { - Str255 volume ; - Str255 path ; - short vRefNum ; - long dirRef ; - short i,j ; - Boolean isDirectory ; - - for (i=0 ; (s[i]!=0) && (s[i]!=':') ;i++) - { - volume[i]=s[i] ; - } - volume[i]=':' ; - volume[i+1]=0 ; - - // then copy the rest of the filename - - for (j=0;(s[i]!=0);i++,j++) - { - path[j]=s[i] ; - } - path[j]=0 ; - - c2pstr((Ptr) volume) ; - c2pstr((Ptr) path) ; - - SetVol(volume, 0) ; - GetVol( NULL, &vRefNum ) ; - - GetDirectoryID( vRefNum , fsRtDirID , path , &dirRef , &isDirectory ) ; - wxMacSetupStandardFile(vRefNum, dirRef) ; + OpenUserDataRec * data = ( OpenUserDataRec *) ioUserData ; + if (inSelector == kNavCBEvent) { +#if TARGET_CARBON +#else + wxTheApp->MacHandleOneEvent(ioParams->eventData.eventDataParms.event); +#endif + } + else if ( inSelector == kNavCBStart ) + { +#if TARGET_CARBON + if (data && !(data->defaultLocation).IsEmpty()) + { + // Set default location for the modern Navigation APIs + // Apple Technical Q&A 1151 + FSSpec theFSSpec; + wxMacFilename2FSSpec(data->defaultLocation, &theFSSpec); + AEDesc theLocation = {typeNull, NULL}; + if (noErr == ::AECreateDesc(typeFSS, &theFSSpec, sizeof(FSSpec), &theLocation)) + ::NavCustomControl(ioParams->context, kNavCtlSetLocation, (void *) &theLocation); + } +#else + if ( data->menuitems ) + NavCustomControl(ioParams->context, kNavCtlSelectCustomType, &(*data->menuitems)[data->currentfilter]); +#endif + } + else if ( inSelector == kNavCBPopupMenuSelect ) + { + NavMenuItemSpec * menu = (NavMenuItemSpec *) ioParams->eventData.eventDataParms.param ; +#if TARGET_CARBON +#else + if ( menu->menuCreator == 'WXNG' ) +#endif + { + data->currentfilter = menu->menuType ; + if ( data->saveMode ) + { + int i = menu->menuType ; + wxString extension = data->extensions[i].AfterLast('.') ; + extension.MakeLower() ; + wxString sfilename ; + +#if TARGET_CARBON + wxMacCFStringHolder cfString( NavDialogGetSaveFileName( ioParams->context ) , false ); + sfilename = cfString.AsString() ; +#else + Str255 filename ; + // get the current filename + NavCustomControl(ioParams->context, kNavCtlGetEditFileName, &filename); + sfilename = wxMacMakeStringFromPascal( filename ) ; +#endif + + int pos = sfilename.Find('.', true) ; + if ( pos != wxNOT_FOUND ) + { + sfilename = sfilename.Left(pos+1)+extension ; +#if TARGET_CARBON + cfString.Assign( sfilename , wxFONTENCODING_DEFAULT ) ; + NavDialogSetSaveFileName( ioParams->context , cfString ) ; +#else + wxMacStringToPascal( sfilename , filename ) ; + NavCustomControl(ioParams->context, kNavCtlSetEditFileName, &filename); +#endif + } + } + } + } } -enum { - kSelectItem = 10, // select button item number - kSFGetFileDlgID = 251, // dialog resource number - kStrListID = 251, // our strings - kSelectStrNum = 1, // word 'Select: ' for button - kDesktopStrNum = 2, // word 'Desktop' for button - kSelectNoQuoteStrNum = 3, // word 'Select: ' for button - - kUseQuotes = true, // parameter for SetButtonName - kDontUseQuotes = false -}; -static void GetLabelString(StringPtr theStr, short stringNum) +void MakeUserDataRec(OpenUserDataRec *myData , const wxString& filter ) { - GetIndString(theStr, kStrListID, stringNum); + myData->menuitems = NULL ; + myData->currentfilter = 0 ; + myData->saveMode = false ; + + if ( filter && filter[0] ) + { + wxString filter2(filter) ; + int filterIndex = 0; + bool isName = true ; + wxString current ; + for( unsigned int i = 0; i < filter2.Len() ; i++ ) + { + if( filter2.GetChar(i) == wxT('|') ) + { + if( isName ) { + myData->name.Add( current ) ; + } + else { + myData->extensions.Add( current.MakeUpper() ) ; + ++filterIndex ; + } + isName = !isName ; + current = wxEmptyString ; + } + else + { + current += filter2.GetChar(i) ; + } + } + // we allow for compatibility reason to have a single filter expression (like *.*) without + // an explanatory text, in that case the first part is name and extension at the same time + + wxASSERT_MSG( filterIndex == 0 || !isName , wxT("incorrect format of format string") ) ; + if ( current.IsEmpty() ) + myData->extensions.Add( myData->name[filterIndex] ) ; + else + myData->extensions.Add( current.MakeUpper() ) ; + if ( filterIndex == 0 || isName ) + myData->name.Add( current.MakeUpper() ) ; + + ++filterIndex ; + + const size_t extCount = myData->extensions.GetCount(); + for ( size_t i = 0 ; i < extCount; i++ ) + { + wxUint32 fileType; + wxUint32 creator; + wxString extension = myData->extensions[i]; + + if (extension.GetChar(0) == '*') + extension = extension.Mid(1); // Remove leading * + + if (extension.GetChar(0) == '.') + { + extension = extension.Mid(1); // Remove leading . + } + + if (wxFileName::MacFindDefaultTypeAndCreator( extension, &fileType, &creator )) + { + myData->filtermactypes.Add( (OSType)fileType ); + } + else + { + myData->filtermactypes.Add( '****' ) ; // We'll fail safe if it's not recognized + } + } + } } -static void CopyPStr(StringPtr src, StringPtr dest) +static Boolean CheckFile( const wxString &filename , OSType type , OpenUserDataRecPtr data) { - BlockMoveData(src, dest, 1 + src[0]); + wxString file(filename) ; + file.MakeUpper() ; + + if ( data->extensions.GetCount() > 0 ) + { + //for ( int i = 0 ; i < data->numfilters ; ++i ) + int i = data->currentfilter ; + if ( data->extensions[i].Right(2) == wxT(".*") ) + return true ; + + { + if ( type == (OSType)data->filtermactypes[i] ) + return true ; + + wxStringTokenizer tokenizer( data->extensions[i] , wxT(";") ) ; + while( tokenizer.HasMoreTokens() ) + { + wxString extension = tokenizer.GetNextToken() ; + if ( extension.GetChar(0) == '*' ) + extension = extension.Mid(1) ; + + if ( file.Len() >= extension.Len() && extension == file.Right(extension.Len() ) ) + return true ; + } + } + return false ; + } + return true ; } -static char GetSelectKey(void) +#ifndef __DARWIN__ +static pascal Boolean CrossPlatformFileFilter(CInfoPBPtr myCInfoPBPtr, void *dataPtr) { - // this is the key used to trigger the select button - - // NOT INTERNATIONAL SAVVY; should at least grab it from resources - - return 's'; -} + OpenUserDataRecPtr data = (OpenUserDataRecPtr) dataPtr ; + // return true if this item is invisible or a file -// FlashButton briefly highlights the dialog button -// as feedback for key equivalents + Boolean visibleFlag; + Boolean folderFlag; -static void FlashButton(DialogPtr theDlgPtr, short buttonID) -{ - short buttonType; - Handle buttonHandle; - Rect buttonRect; - unsigned long finalTicks; - - GetDialogItem(theDlgPtr, buttonID, &buttonType, &buttonHandle, &buttonRect); - HiliteControl((ControlHandle) buttonHandle, kControlButtonPart); - Delay(10, &finalTicks); - HiliteControl((ControlHandle) buttonHandle, 0); -} + visibleFlag = ! (myCInfoPBPtr->hFileInfo.ioFlFndrInfo.fdFlags & kIsInvisible); + folderFlag = (myCInfoPBPtr->hFileInfo.ioFlAttrib & 0x10); -static Boolean SameFSSpec(FSSpecPtr spec1, FSSpecPtr spec2) -{ - return (spec1->vRefNum == spec2->vRefNum - && spec1->parID == spec2->parID - && EqualString(spec1->name, spec2->name, false, false)); + // because the semantics of the filter proc are "true means don't show + // it" we need to invert the result that we return + + if ( !visibleFlag ) + return true ; + + if ( !folderFlag ) + { + wxString file = wxMacMakeStringFromPascal( myCInfoPBPtr->hFileInfo.ioNamePtr ) ; + return !CheckFile( file , myCInfoPBPtr->hFileInfo.ioFlFndrInfo.fdType , data ) ; + } + + return false ; } -// MyModalDialogFilter maps a key to the Select button, and handles -// flashing of the button when the key is hit +#endif -static pascal Boolean SFGetFolderModalDialogFilter(DialogPtr theDlgPtr, EventRecord *eventRec, - short *item, Ptr dataPtr) +// end wxmac + +wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message, + const wxString& defaultDir, const wxString& defaultFileName, const wxString& wildCard, + long style, const wxPoint& pos) + :wxFileDialogBase(parent, message, defaultDir, defaultFileName, wildCard, style, pos) { -#pragma unused (dataPtr) - - // make certain the proper dialog is showing, 'cause standard file - // can nest dialogs but calls the same filter for each - - if (((WindowPeek) theDlgPtr)->refCon == sfMainDialogRefCon) - { - // check if the select button was hit - /* - if ((eventRec->what == keyDown) - && (eventRec->modifiers & cmdKey) - && ((eventRec->message & charCodeMask) == GetSelectKey())) - { - *item = kSelectItem; - FlashButton(theDlgPtr, kSelectItem); - return true; - } - */ - } - - return false; + wxASSERT_MSG( NavServicesAvailable() , wxT("Navigation Services are not running") ) ; } -#endif -void ExtendedOpenFile( ConstStr255Param message , ConstStr255Param path , const char *filter , FileFilterYDUPP fileFilter, StandardFileReply *theSFR) +pascal Boolean CrossPlatformFilterCallback ( + AEDesc *theItem, + void *info, + void *callBackUD, + NavFilterModes filterMode +) { - Point thePt; - OpenUserDataRec myData; - FSSpec tempSpec; - Boolean folderFlag; - Boolean wasAliasedFlag; - DlgHookYDUPP dlgHookUPP; - ModalFilterYDUPP myModalFilterUPP; - OSErr err; - SFTypeList types ; - - - // presumably we're running System 7 or later so CustomGetFile is - // available - - // set initial contents of Select button to a space - - memcpy( theSFR->sfFile.name , "\p " , 2 ) ; - - // point the user data parameter at the reply record so we can get to it later - - myData.sfrPtr = theSFR; - if ( filter && filter[0] ) - { - myData.numfilters = 1 ; - for ( int i = 0 ; i < myData.numfilters ; i++ ) - { - int j ; - - strcpy( myData.filter[i] , filter ) ; - for( j = 0 ; myData.filter[i][j] ; j++ ) - { - myData.filter[i][j] = toupper( myData.filter[i][j] ) ; - } - for ( j = 0 ; gfilters[j] ; j++ ) - { - if ( strcmp( myData.filter[i] , gfilters[j] ) == 0 ) - { - myData.filtermactypes[i] = gfiltersmac[j] ; - break ; - } - } - if( gfilters[j] == NULL ) - { - myData.filtermactypes[i] = '****' ; - } - } - } - else - { - myData.numfilters = 0 ; - } - // display the dialog - -#if !TARGET_CARBON - - dlgHookUPP = NULL ; -// dlgHookUPP = NewDlgHookYDProc(SFGetFolderDialogHook); - myModalFilterUPP = NewModalFilterYDProc(SFGetFolderModalDialogFilter); - - thePt.h = thePt.v = -1; // center dialog - - ParamText( message , NULL , NULL , NULL ) ; - - CustomGetFile( fileFilter, - -1, // show all types - NULL, - theSFR, - kSFGetFileDlgID, - thePt, // top left point - dlgHookUPP, - myModalFilterUPP, - nil, // activate list - nil, // activate proc - &myData); - - DisposeRoutineDescriptor(dlgHookUPP); - DisposeRoutineDescriptor(myModalFilterUPP); + bool display = true; + OpenUserDataRecPtr data = (OpenUserDataRecPtr) callBackUD ; + + if (filterMode == kNavFilteringBrowserList) + { + NavFileOrFolderInfo* theInfo = (NavFileOrFolderInfo*) info ; + if ( !theInfo->isFolder ) + { + if (theItem->descriptorType == typeFSS ) + { + FSSpec spec; + memcpy( &spec , *theItem->dataHandle , sizeof(FSSpec) ) ; + wxString file = wxMacMakeStringFromPascal( spec.name ) ; + display = CheckFile( file , theInfo->fileAndFolder.fileInfo.finderInfo.fdType , data ) ; + } + #if TARGET_CARBON + else if ( theItem->descriptorType == typeFSRef ) + { + FSRef fsref ; + memcpy( &fsref , *theItem->dataHandle , sizeof(FSRef) ) ; + + + + CFURLRef fullURLRef; + fullURLRef = ::CFURLCreateFromFSRef(NULL, &fsref); +#ifdef __UNIX__ + CFURLPathStyle pathstyle = kCFURLPOSIXPathStyle; #else -#endif - // if cancel wasn't pressed and no fatal error occurred... - - if (theSFR->sfGood) - { - // if no name is in the reply record file spec, - // use the file spec of the parent folder - - if (theSFR->sfFile.name[0] == '\0') - { - err = FSMakeFSSpec(theSFR->sfFile.vRefNum, theSFR->sfFile.parID, - "\p", &tempSpec); - if (err == noErr) - { - theSFR->sfFile = tempSpec; - } - else - { - // no name to return, forget it - - theSFR->sfGood = false; - } - } - - // if there is now a name in the file spec, check if it's - // for a folder or a volume - - if (theSFR->sfFile.name[0] != '\0') - { - // the parID of the root of a disk is always fsRtParID == 1 - - if (theSFR->sfFile.parID == fsRtParID) - { - theSFR->sfIsVolume = true; - theSFR->sfIsFolder = false; // it would be reasonable for this to be true, too - } - - // we have a valid FSSpec, now let's make sure it's not for an alias file - - err = ResolveAliasFile(&theSFR->sfFile, true, &folderFlag, &wasAliasedFlag); - if (err != noErr) - { - theSFR->sfGood = false; - } - - // did the alias resolve to a folder? - - if (folderFlag && ! theSFR->sfIsVolume) - { - theSFR->sfIsFolder = true; - } - } - } -} + CFURLPathStyle pathstyle = kCFURLHFSPathStyle; +#endif + CFStringRef cfString = CFURLCopyFileSystemPath(fullURLRef, pathstyle); + ::CFRelease( fullURLRef ) ; + wxString file = wxMacCFStringHolder(cfString).AsString(wxFont::GetDefaultEncoding()); -static pascal Boolean CrossPlatformFileFilter(CInfoPBPtr myCInfoPBPtr, Ptr dataPtr) -{ - Str255 filename ; - OpenUserDataRecPtr data = (OpenUserDataRecPtr) dataPtr ; - // return true if this item is invisible or a file - - Boolean visibleFlag; - Boolean folderFlag; - - visibleFlag = ! (myCInfoPBPtr->hFileInfo.ioFlFndrInfo.fdFlags & kIsInvisible); - folderFlag = (myCInfoPBPtr->hFileInfo.ioFlAttrib & 0x10); - - // because the semantics of the filter proc are "true means don't show - // it" we need to invert the result that we return - - if ( !visibleFlag ) - return true ; - - if ( !folderFlag ) - { - if ( data->numfilters > 0 ) - { - PLstrcpy( filename ,myCInfoPBPtr->hFileInfo.ioNamePtr ) ; - if ( filename[0] >= 4 ) - { - for( int j = 1 ; j <= filename[0] ; j++ ) - { - filename[j] = toupper( filename[j] ) ; - } - for ( int i = 0 ; i < data->numfilters ; ++i ) - { - if ( myCInfoPBPtr->hFileInfo.ioFlFndrInfo.fdType == data->filtermactypes[i] ) - return false ; - - if ( strncmp( (char*) filename + 1 + filename[0] - 4 , - & data->filter[i][ strlen(data->filter[i]) - 4 ] , 4 ) == 0 ) - return false ; - } - } - return true ; - } - } - - return false ; -} + display = CheckFile( file , theInfo->fileAndFolder.fileInfo.finderInfo.fdType , data ) ; + } +#endif + } + } -// end wxmac + return display; +} -wxString wxFileSelector(const char *title, - const char *defaultDir, const char *defaultFileName, - const char *defaultExtension, const char *filter, int flags, - wxWindow *parent, int x, int y) +int wxFileDialog::ShowModal() { - // If there's a default extension specified but no filter, we create a suitable - // filter. - - wxString filter2(""); - if ( defaultExtension && !filter ) - filter2 = wxString("*.") + wxString(defaultExtension) ; - else if ( filter ) - filter2 = filter; - - wxString defaultDirString; - if (defaultDir) - defaultDirString = defaultDir; - else - defaultDirString = ""; +#if TARGET_CARBON + OSErr err; + NavDialogCreationOptions dialogCreateOptions; + // set default options + ::NavGetDefaultDialogCreationOptions(&dialogCreateOptions); + + // this was always unset in the old code + dialogCreateOptions.optionFlags &= ~kNavSelectDefaultLocation; + + wxMacCFStringHolder message(m_message, m_font.GetEncoding()); + dialogCreateOptions.windowTitle = message; + + wxMacCFStringHolder defaultFileName(m_fileName, m_font.GetEncoding()); + dialogCreateOptions.saveFileName = defaultFileName; - wxString defaultFilenameString; - if (defaultFileName) - defaultFilenameString = defaultFileName; - else - defaultFilenameString = ""; - wxFileDialog fileDialog(parent, title, defaultDirString, defaultFilenameString, filter2, flags, wxPoint(x, y)); + NavDialogRef dialog; + NavObjectFilterUPP navFilterUPP = NULL; + CFArrayRef cfArray = NULL; // for popupExtension + OpenUserDataRec myData; + myData.defaultLocation = m_dir; - if ( fileDialog.ShowModal() == wxID_OK ) + if (m_dialogStyle & wxSAVE) { - strcpy(wxBuffer, (const char *)fileDialog.GetPath()); - return wxBuffer; + dialogCreateOptions.optionFlags |= kNavNoTypePopup; + dialogCreateOptions.optionFlags |= kNavDontAutoTranslate; + dialogCreateOptions.optionFlags |= kNavDontAddTranslateItems; + + // The extension is important + dialogCreateOptions.optionFlags |= kNavPreserveSaveFileExtension; + + err = ::NavCreatePutFileDialog(&dialogCreateOptions, + 'TEXT', + 'TEXT', + sStandardNavEventFilter, + &myData, // for defaultLocation + &dialog); } else - return wxGetEmptyString(); -} + { + MakeUserDataRec(&myData , m_wildCard); + size_t numfilters = myData.extensions.GetCount(); + if (numfilters > 0) + { + CFMutableArrayRef popup = CFArrayCreateMutable( kCFAllocatorDefault , + numfilters , &kCFTypeArrayCallBacks ) ; + dialogCreateOptions.popupExtension = popup ; + myData.menuitems = dialogCreateOptions.popupExtension ; + for ( size_t i = 0 ; i < numfilters ; ++i ) + { + CFArrayAppendValue( popup , (CFStringRef) wxMacCFStringHolder( myData.name[i] , m_font.GetEncoding() ) ) ; + } + } + + navFilterUPP = NewNavObjectFilterUPP(CrossPlatformFilterCallback); + err = ::NavCreateGetFileDialog(&dialogCreateOptions, + NULL, // NavTypeListHandle + sStandardNavEventFilter, + NULL, // NavPreviewUPP + navFilterUPP, + (void *) &myData, // inClientData + &dialog); + } -WXDLLEXPORT wxString wxFileSelectorEx(const char *title, - const char *defaultDir, - const char *defaultFileName, - int* defaultFilterIndex, - const char *filter, - int flags, - wxWindow* parent, - int x, - int y) + if (err == noErr) + err = ::NavDialogRun(dialog); -{ - wxFileDialog fileDialog(parent, title ? title : "", defaultDir ? defaultDir : "", - defaultFileName ? defaultFileName : "", filter ? filter : "", flags, wxPoint(x, y)); + // clean up filter related data, etc. + if (navFilterUPP) + ::DisposeNavObjectFilterUPP(navFilterUPP); + if (cfArray) + ::CFRelease(cfArray); + + if (err != noErr) + return wxID_CANCEL; - if ( fileDialog.ShowModal() == wxID_OK ) + NavReplyRecord navReply; + err = ::NavDialogGetReply(dialog, &navReply); + if (err == noErr && navReply.validRecord) { - *defaultFilterIndex = fileDialog.GetFilterIndex(); - strcpy(wxBuffer, (const char *)fileDialog.GetPath()); - return wxBuffer; + AEKeyword theKeyword; + DescType actualType; + Size actualSize; + FSRef theFSRef; + wxString thePath ; + long count; + ::AECountItems(&navReply.selection , &count); + for (long i = 1; i <= count; ++i) + { + err = ::AEGetNthPtr(&(navReply.selection), i, typeFSRef, &theKeyword, &actualType, + &theFSRef, sizeof(theFSRef), &actualSize); + if (err != noErr) + break; + + CFURLRef fullURLRef; + if (m_dialogStyle & wxSAVE) + { + CFURLRef parentURLRef = ::CFURLCreateFromFSRef(NULL, &theFSRef); + + if (parentURLRef) + { + fullURLRef = + ::CFURLCreateCopyAppendingPathComponent(NULL, + parentURLRef, + navReply.saveFileName, + false); + ::CFRelease(parentURLRef); + } + } + else + { + fullURLRef = ::CFURLCreateFromFSRef(NULL, &theFSRef); + } +#ifdef __UNIX__ + CFURLPathStyle pathstyle = kCFURLPOSIXPathStyle; +#else + CFURLPathStyle pathstyle = kCFURLHFSPathStyle; +#endif + CFStringRef cfString = CFURLCopyFileSystemPath(fullURLRef, pathstyle); + thePath = wxMacCFStringHolder(cfString).AsString(m_font.GetEncoding()); + if (!thePath) + { + ::NavDisposeReply(&navReply); + return wxID_CANCEL; + } + m_path = thePath; + m_paths.Add(m_path); + m_fileName = wxFileNameFromPath(m_path); + m_fileNames.Add(m_fileName); + } + // set these to the first hit + m_path = m_paths[0]; + m_fileName = wxFileNameFromPath(m_path); + m_dir = wxPathOnly(m_path); } - else - return wxGetEmptyString(); -} + ::NavDisposeReply(&navReply); -wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message, - const wxString& defaultDir, const wxString& defaultFileName, const wxString& wildCard, - long style, const wxPoint& pos) -{ - m_message = message; - m_dialogStyle = style; - m_parent = parent; - m_path = ""; - m_fileName = defaultFileName; - m_dir = defaultDir; - m_wildCard = wildCard; - m_filterIndex = 1; -} + return (err == noErr) ? wxID_OK : wxID_CANCEL; +#else // TARGET_CARBON -int wxFileDialog::ShowModal() -{ - if ( m_dialogStyle & wxSAVE ) - { - StandardFileReply reply ; - Str255 prompt ; - Str255 filename ; - - strcpy((char *)prompt, m_message) ; - c2pstr((char *)prompt ) ; - - strcpy((char *)filename, m_fileName) ; - c2pstr((char *)filename ) ; - #if !TARGET_CARBON - - StandardPutFile( prompt , filename , &reply ) ; - - #else - #endif - if ( reply.sfGood == false ) - { - m_path = "" ; - return wxID_CANCEL ; - } - else - { - m_path = wxMacFSSpec2UnixFilename( &reply.sfFile ) ; - return wxID_OK ; - } - } - else - { - OSType types = '????' ; - Str255 prompt ; - Str255 path ; - - strcpy((char *)prompt, m_message) ; - c2pstr((char *)prompt ) ; - - strcpy((char *)path, m_path ) ; - c2pstr((char *)path ) ; - - StandardFileReply reply ; - FileFilterYDUPP crossPlatformFileFilterUPP = 0 ; - #if !TARGET_CARBON - crossPlatformFileFilterUPP = - NewFileFilterYDProc(CrossPlatformFileFilter); - #endif - - ExtendedOpenFile( prompt , path , m_wildCard , crossPlatformFileFilterUPP, &reply); - #if !TARGET_CARBON - DisposeFileFilterYDUPP(crossPlatformFileFilterUPP); - #endif - if ( reply.sfGood == false ) - { - m_path = "" ; - return wxID_CANCEL ; - } - else - { - m_path = wxMacFSSpec2UnixFilename( &reply.sfFile ) ; - return wxID_OK ; - } - } - return wxID_CANCEL; -} + NavDialogOptions mNavOptions; + NavObjectFilterUPP mNavFilterUPP = NULL; + NavPreviewUPP mNavPreviewUPP = NULL ; + NavReplyRecord mNavReply; + AEDesc mDefaultLocation ; + bool mSelectDefault = false ; + OSStatus err = noErr ; + // setup dialog -// Generic file load/save dialog -static wxString -wxDefaultFileSelector(bool load, const char *what, const char *extension, const char *default_name, wxWindow *parent) -{ - char *ext = (char *)extension; - - char prompt[50]; - wxString str; - if (load) - str = "Load %s file"; - else - str = "Save %s file"; - sprintf(prompt, wxGetTranslation(str), what); - - if (*ext == '.') ext++; - char wild[60]; - sprintf(wild, "*.%s", ext); - - return wxFileSelector (prompt, NULL, default_name, ext, wild, 0, parent); -} + mNavFilterUPP = nil; + mNavPreviewUPP = nil; + mSelectDefault = false; + mDefaultLocation.descriptorType = typeNull; + mDefaultLocation.dataHandle = nil; -// Generic file load dialog -wxString -wxLoadFileSelector(const char *what, const char *extension, const char *default_name, wxWindow *parent) -{ - return wxDefaultFileSelector(TRUE, what, extension, default_name, parent); -} + NavGetDefaultDialogOptions(&mNavOptions); + wxMacStringToPascal( m_message , (StringPtr)mNavOptions.message ) ; + wxMacStringToPascal( m_fileName , (StringPtr)mNavOptions.savedFileName ) ; + // Set default location, the location + // that's displayed when the dialog + // first appears -// Generic file save dialog -wxString -wxSaveFileSelector(const char *what, const char *extension, const char *default_name, wxWindow *parent) -{ - return wxDefaultFileSelector(FALSE, what, extension, default_name, parent); -} + FSSpec location ; + wxMacFilename2FSSpec( m_dir , &location ) ; + + err = ::AECreateDesc(typeFSS, &location, sizeof(FSSpec), &mDefaultLocation ); + + if ( mDefaultLocation.dataHandle ) + { + if (mSelectDefault) + { + mNavOptions.dialogOptionFlags |= kNavSelectDefaultLocation; + } else { + mNavOptions.dialogOptionFlags &= ~kNavSelectDefaultLocation; + } + } + + memset( &mNavReply , 0 , sizeof( mNavReply ) ) ; + mNavReply.validRecord = false; + mNavReply.replacing = false; + mNavReply.isStationery = false; + mNavReply.translationNeeded = false; + mNavReply.selection.descriptorType = typeNull; + mNavReply.selection.dataHandle = nil; + mNavReply.keyScript = smSystemScript; + mNavReply.fileTranslation = nil; + mNavReply.version = kNavReplyRecordVersion ; + + // zero all data + + m_path = wxEmptyString ; + m_fileName = wxEmptyString ; + m_paths.Empty(); + m_fileNames.Empty(); + + OpenUserDataRec myData; + MakeUserDataRec( &myData , m_wildCard ) ; + myData.currentfilter = m_filterIndex ; + if ( myData.extensions.GetCount() > 0 ) + { + mNavOptions.popupExtension = (NavMenuItemSpecArrayHandle) NewHandle( sizeof( NavMenuItemSpec ) * myData.extensions.GetCount() ) ; + myData.menuitems = mNavOptions.popupExtension ; + for ( size_t i = 0 ; i < myData.extensions.GetCount() ; ++i ) + { + (*mNavOptions.popupExtension)[i].version = kNavMenuItemSpecVersion ; + (*mNavOptions.popupExtension)[i].menuCreator = 'WXNG' ; + // TODO : according to the new docs -1 to 10 are reserved for the OS + (*mNavOptions.popupExtension)[i].menuType = i ; + wxMacStringToPascal( myData.name[i] , (StringPtr)(*mNavOptions.popupExtension)[i].menuItemName ) ; + } + } + if ( m_dialogStyle & wxSAVE ) + { + myData.saveMode = true ; + + mNavOptions.dialogOptionFlags |= kNavDontAutoTranslate ; + mNavOptions.dialogOptionFlags |= kNavDontAddTranslateItems ; + + err = ::NavPutFile( + &mDefaultLocation, + &mNavReply, + &mNavOptions, + sStandardNavEventFilter , + NULL, + kNavGenericSignature, + &myData); // User Data + m_filterIndex = myData.currentfilter ; + } + else + { + myData.saveMode = false ; + + mNavFilterUPP = NewNavObjectFilterUPP( CrossPlatformFilterCallback ) ; + if ( m_dialogStyle & wxMULTIPLE ) + mNavOptions.dialogOptionFlags |= kNavAllowMultipleFiles ; + else + mNavOptions.dialogOptionFlags &= ~kNavAllowMultipleFiles ; + + err = ::NavGetFile( + &mDefaultLocation, + &mNavReply, + &mNavOptions, + sStandardNavEventFilter , + mNavPreviewUPP, + mNavFilterUPP, + NULL , + &myData); + m_filterIndex = myData.currentfilter ; + } + + DisposeNavObjectFilterUPP(mNavFilterUPP); + if ( mDefaultLocation.dataHandle != nil ) + { + ::AEDisposeDesc(&mDefaultLocation); + } + + if ( (err != noErr) && (err != userCanceledErr) ) { + return wxID_CANCEL ; + } + if (mNavReply.validRecord) + { + FSSpec outFileSpec ; + AEDesc specDesc ; + AEKeyword keyWord ; + + long count ; + ::AECountItems( &mNavReply.selection , &count ) ; + for ( long i = 1 ; i <= count ; ++i ) + { + OSErr err = ::AEGetNthDesc( &mNavReply.selection , i , typeFSS, &keyWord , &specDesc); + if ( err != noErr ) + { + m_path = wxT("") ; + return wxID_CANCEL ; + } + outFileSpec = **(FSSpec**) specDesc.dataHandle; + if (specDesc.dataHandle != nil) { + ::AEDisposeDesc(&specDesc); + } + m_path = wxMacFSSpec2MacFilename( &outFileSpec ) ; + + m_paths.Add( m_path ) ; + m_fileName = wxFileNameFromPath(m_path); + m_fileNames.Add(m_fileName); + } + // set these to the first hit + m_path = m_paths[ 0 ] ; + m_fileName = wxFileNameFromPath(m_path); + m_dir = wxPathOnly(m_path); + NavDisposeReply( &mNavReply ) ; + return wxID_OK ; + } + return wxID_CANCEL; +#endif // TARGET_CARBON +}