X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4891a3d58e04064c680c360eb275fc05f2efdd1c..57ab966bab900a399e5b75382fcfe62263ff06d6:/src/mac/carbon/filedlg.cpp?ds=inline diff --git a/src/mac/carbon/filedlg.cpp b/src/mac/carbon/filedlg.cpp index 6347f87577..59807f398d 100644 --- a/src/mac/carbon/filedlg.cpp +++ b/src/mac/carbon/filedlg.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // Name: filedlg.cpp -// Purpose: wxFileDialog +// Purpose: wxFileDialog // Author: Stefan Csomor // Modified by: // Created: 1998-01-01 @@ -20,6 +20,7 @@ #include "wx/filedlg.h" #include "wx/intl.h" #include "wx/tokenzr.h" +#include "wx/filename.h" #ifndef __DARWIN__ #include "PLStringFuncs.h" @@ -41,7 +42,7 @@ IMPLEMENT_CLASS(wxFileDialog, wxFileDialogBase) # include "MoreFiles.h" # include "MoreFilesExtras.h" #endif - + extern bool gUseNavServices ; // the data we need to pass to our standard file hook routine @@ -51,20 +52,21 @@ extern bool gUseNavServices ; // so we can see if the selection has changed struct OpenUserDataRec { - int currentfilter ; - bool saveMode ; + int currentfilter ; + bool saveMode ; wxArrayString name ; wxArrayString extensions ; wxArrayLong filtermactypes ; + wxString defaultLocation; #if TARGET_CARBON - CFArrayRef menuitems ; + CFArrayRef menuitems ; #else NavMenuItemSpecArrayHandle menuitems ; #endif }; typedef struct OpenUserDataRec - OpenUserDataRec, *OpenUserDataRecPtr; +OpenUserDataRec, *OpenUserDataRecPtr; static pascal void NavEventProc( NavEventCallbackMessage inSelector, @@ -84,17 +86,26 @@ NavEventProc( NavCallBackUserData ioUserData ) { OpenUserDataRec * data = ( OpenUserDataRec *) ioUserData ; - if (inSelector == kNavCBEvent) { + if (inSelector == kNavCBEvent) { #if TARGET_CARBON -#else - wxTheApp->MacHandleOneEvent(ioParams->eventData.eventDataParms.event); +#else + wxTheApp->MacHandleOneEvent(ioParams->eventData.eventDataParms.event); #endif - } + } else if ( inSelector == kNavCBStart ) { #if TARGET_CARBON - // there is no way to set this in the new API - #else + 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 @@ -114,7 +125,7 @@ NavEventProc( wxString extension = data->extensions[i].AfterLast('.') ; extension.MakeLower() ; wxString sfilename ; - + #if TARGET_CARBON wxMacCFStringHolder cfString( NavDialogGetSaveFileName( ioParams->context ) , false ); sfilename = cfString.AsString() ; @@ -125,12 +136,12 @@ NavEventProc( sfilename = wxMacMakeStringFromPascal( filename ) ; #endif - int pos = sfilename.Find('.',TRUE) ; + int pos = sfilename.Find('.', true) ; if ( pos != wxNOT_FOUND ) { sfilename = sfilename.Left(pos+1)+extension ; #if TARGET_CARBON - cfString = sfilename ; + cfString.Assign( sfilename , wxFONTENCODING_DEFAULT ) ; NavDialogSetSaveFileName( ioParams->context , cfString ) ; #else wxMacStringToPascal( sfilename , filename ) ; @@ -142,32 +153,13 @@ NavEventProc( } } -const wxChar * gfilters[] = -{ - wxT("*.TXT") , - wxT("*.TIF") , - wxT("*.JPG") , - - NULL -} ; - -OSType gfiltersmac[] = -{ - 'TEXT' , - 'TIFF' , - 'JPEG' , - - '****' -} ; - - void MakeUserDataRec(OpenUserDataRec *myData , const wxString& filter ) { myData->menuitems = NULL ; myData->currentfilter = 0 ; - myData->saveMode = FALSE ; - + myData->saveMode = false ; + if ( filter && filter[0] ) { wxString filter2(filter) ; @@ -195,7 +187,7 @@ void MakeUserDataRec(OpenUserDataRec *myData , const wxString& filter ) } // 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] ) ; @@ -203,53 +195,59 @@ void MakeUserDataRec(OpenUserDataRec *myData , const wxString& filter ) 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++ ) { - int j ; - for ( j = 0 ; gfilters[j] ; j++ ) + wxUint32 fileType; + wxUint32 creator; + wxString extension = myData->extensions[i]; + + if (extension.GetChar(0) == '*') + extension = extension.Mid(1); // Remove leading * + + if (extension.GetChar(0) == '.') { - if ( myData->extensions[i] == gfilters[j] ) - { - myData->filtermactypes.Add( gfiltersmac[j] ) ; - break ; - } + extension = extension.Mid(1); // Remove leading . } - if( gfilters[j] == NULL ) + + if (wxFileName::MacFindDefaultTypeAndCreator( extension, &fileType, &creator )) { - myData->filtermactypes.Add( '****' ) ; + myData->filtermactypes.Add( (OSType)fileType ); } + else + { + myData->filtermactypes.Add( '****' ) ; // We'll fail safe if it's not recognized + } } } } static Boolean CheckFile( const wxString &filename , OSType type , OpenUserDataRecPtr data) { - wxString file = filename ; + 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 ; } @@ -261,28 +259,28 @@ static Boolean CheckFile( const wxString &filename , OSType type , OpenUserDataR #ifndef __DARWIN__ static pascal Boolean CrossPlatformFileFilter(CInfoPBPtr myCInfoPBPtr, void *dataPtr) -{ +{ 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 ) { - wxString file = wxMacMakeStringFromPascal( myCInfoPBPtr->hFileInfo.ioNamePtr ) ; + wxString file = wxMacMakeStringFromPascal( myCInfoPBPtr->hFileInfo.ioNamePtr ) ; return !CheckFile( file , myCInfoPBPtr->hFileInfo.ioFlFndrInfo.fdType , data ) ; - } - + } + return false ; } #endif @@ -298,15 +296,15 @@ wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message, } pascal Boolean CrossPlatformFilterCallback ( - AEDesc *theItem, - void *info, - void *callBackUD, + AEDesc *theItem, + void *info, + void *callBackUD, NavFilterModes filterMode ) { bool display = true; OpenUserDataRecPtr data = (OpenUserDataRecPtr) callBackUD ; - + if (filterMode == kNavFilteringBrowserList) { NavFileOrFolderInfo* theInfo = (NavFileOrFolderInfo*) info ; @@ -316,37 +314,180 @@ pascal Boolean CrossPlatformFilterCallback ( { FSSpec spec; memcpy( &spec , *theItem->dataHandle , sizeof(FSSpec) ) ; - wxString file = wxMacMakeStringFromPascal( spec.name ) ; + 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) ) ; - wxString file ; - const short maxpath = 1024 ; - FSRefMakePath( &fsref , (UInt8*) file.GetWriteBuf(maxpath+1),maxpath) ; - file.UngetWriteBuf() ; + + + + CFURLRef fullURLRef; + fullURLRef = ::CFURLCreateFromFSRef(NULL, &fsref); +#ifdef __UNIX__ + CFURLPathStyle pathstyle = kCFURLPOSIXPathStyle; +#else + CFURLPathStyle pathstyle = kCFURLHFSPathStyle; +#endif + CFStringRef cfString = CFURLCopyFileSystemPath(fullURLRef, pathstyle); + ::CFRelease( fullURLRef ) ; + wxString file = wxMacCFStringHolder(cfString).AsString(wxFont::GetDefaultEncoding()); + display = CheckFile( file , theInfo->fileAndFolder.fileInfo.finderInfo.fdType , data ) ; } #endif } } - + return display; } int wxFileDialog::ShowModal() { #if TARGET_CARBON - NavDialogCreationOptions mNavOptions; - NavDialogRef navDialogRef = NULL ; -// since the same field has been renamed ... -#define dialogOptionFlags optionFlags + 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; + + + NavDialogRef dialog; + NavObjectFilterUPP navFilterUPP = NULL; + CFArrayRef cfArray = NULL; // for popupExtension + OpenUserDataRec myData; + myData.defaultLocation = m_dir; + + if (m_dialogStyle & wxSAVE) + { + 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 + { + 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); + } + + if (err == noErr) + err = ::NavDialogRun(dialog); + + // clean up filter related data, etc. + if (navFilterUPP) + ::DisposeNavObjectFilterUPP(navFilterUPP); + if (cfArray) + ::CFRelease(cfArray); + + if (err != noErr) + return wxID_CANCEL; + + NavReplyRecord navReply; + err = ::NavDialogGetReply(dialog, &navReply); + if (err == noErr && navReply.validRecord) + { + 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 - NavDialogOptions mNavOptions; + 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); + } + ::NavDisposeReply(&navReply); + + return (err == noErr) ? wxID_OK : wxID_CANCEL; +#else // TARGET_CARBON + + NavDialogOptions mNavOptions; NavObjectFilterUPP mNavFilterUPP = NULL; NavPreviewUPP mNavPreviewUPP = NULL ; NavReplyRecord mNavReply; @@ -354,20 +495,13 @@ int wxFileDialog::ShowModal() bool mSelectDefault = false ; OSStatus err = noErr ; // setup dialog - + mNavFilterUPP = nil; mNavPreviewUPP = nil; mSelectDefault = false; mDefaultLocation.descriptorType = typeNull; mDefaultLocation.dataHandle = nil; -#if TARGET_CARBON - NavGetDefaultDialogCreationOptions( &mNavOptions ) ; - wxMacCFStringHolder cfMessage(m_message) ; - wxMacCFStringHolder cfFileName(m_fileName) ; - mNavOptions.saveFileName = cfFileName ; - mNavOptions.message = cfMessage ; -#else NavGetDefaultDialogOptions(&mNavOptions); wxMacStringToPascal( m_message , (StringPtr)mNavOptions.message ) ; wxMacStringToPascal( m_fileName , (StringPtr)mNavOptions.savedFileName ) ; @@ -375,21 +509,21 @@ int wxFileDialog::ShowModal() // Set default location, the location // that's displayed when the dialog // first appears - + FSSpec location ; wxMacFilename2FSSpec( m_dir , &location ) ; - + err = ::AECreateDesc(typeFSS, &location, sizeof(FSSpec), &mDefaultLocation ); - if ( mDefaultLocation.dataHandle ) { - - if (mSelectDefault) { + if ( mDefaultLocation.dataHandle ) + { + if (mSelectDefault) + { mNavOptions.dialogOptionFlags |= kNavSelectDefaultLocation; } else { mNavOptions.dialogOptionFlags &= ~kNavSelectDefaultLocation; } } -#endif memset( &mNavReply , 0 , sizeof( mNavReply ) ) ; mNavReply.validRecord = false; @@ -401,9 +535,9 @@ int wxFileDialog::ShowModal() mNavReply.keyScript = smSystemScript; mNavReply.fileTranslation = nil; mNavReply.version = kNavReplyRecordVersion ; - + // zero all data - + m_path = wxEmptyString ; m_fileName = wxEmptyString ; m_paths.Empty(); @@ -414,19 +548,9 @@ int wxFileDialog::ShowModal() myData.currentfilter = m_filterIndex ; if ( myData.extensions.GetCount() > 0 ) { -#if TARGET_CARBON - CFMutableArrayRef popup = CFArrayCreateMutable( kCFAllocatorDefault , - myData.extensions.GetCount() , &kCFTypeArrayCallBacks ) ; - mNavOptions.popupExtension = popup ; - myData.menuitems = mNavOptions.popupExtension ; - for ( size_t i = 0 ; i < myData.extensions.GetCount() ; ++i ) - { - CFArrayAppendValue( popup , (CFStringRef) wxMacCFStringHolder( myData.name[i] ) ) ; - } -#else mNavOptions.popupExtension = (NavMenuItemSpecArrayHandle) NewHandle( sizeof( NavMenuItemSpec ) * myData.extensions.GetCount() ) ; myData.menuitems = mNavOptions.popupExtension ; - for ( size_t i = 0 ; i < myData.extensions.GetCount() ; ++i ) + for ( size_t i = 0 ; i < myData.extensions.GetCount() ; ++i ) { (*mNavOptions.popupExtension)[i].version = kNavMenuItemSpecVersion ; (*mNavOptions.popupExtension)[i].menuCreator = 'WXNG' ; @@ -434,7 +558,6 @@ int wxFileDialog::ShowModal() (*mNavOptions.popupExtension)[i].menuType = i ; wxMacStringToPascal( myData.name[i] , (StringPtr)(*mNavOptions.popupExtension)[i].menuItemName ) ; } -#endif } if ( m_dialogStyle & wxSAVE ) { @@ -442,20 +565,7 @@ int wxFileDialog::ShowModal() mNavOptions.dialogOptionFlags |= kNavDontAutoTranslate ; mNavOptions.dialogOptionFlags |= kNavDontAddTranslateItems ; - -#if TARGET_CARBON - err = NavCreatePutFileDialog( &mNavOptions , NULL , kNavGenericSignature , sStandardNavEventFilter , - &myData , &navDialogRef ) ; - if ( err == noErr ) - { - err = NavDialogRun( navDialogRef ) ; - NavUserAction userAction = NavDialogGetUserAction( navDialogRef ) ; - if ( userAction != kNavUserActionCancel && userAction != kNavUserActionNone ) - { - NavDialogGetReply( navDialogRef, &mNavReply ) ; - } - } -#else + err = ::NavPutFile( &mDefaultLocation, &mNavReply, @@ -464,7 +574,6 @@ int wxFileDialog::ShowModal() NULL, kNavGenericSignature, &myData); // User Data -#endif m_filterIndex = myData.currentfilter ; } else @@ -476,20 +585,7 @@ int wxFileDialog::ShowModal() mNavOptions.dialogOptionFlags |= kNavAllowMultipleFiles ; else mNavOptions.dialogOptionFlags &= ~kNavAllowMultipleFiles ; - -#if TARGET_CARBON - err = NavCreateGetFileDialog( &mNavOptions , NULL , sStandardNavEventFilter , - mNavPreviewUPP , mNavFilterUPP , &myData , &navDialogRef ) ; - if ( err == noErr ) - { - err = NavDialogRun( navDialogRef ) ; - NavUserAction userAction = NavDialogGetUserAction( navDialogRef ) ; - if ( userAction != kNavUserActionCancel && userAction != kNavUserActionNone ) - { - NavDialogGetReply( navDialogRef, &mNavReply ) ; - } - } -#else + err = ::NavGetFile( &mDefaultLocation, &mNavReply, @@ -499,47 +595,41 @@ int wxFileDialog::ShowModal() mNavFilterUPP, NULL , &myData); -#endif m_filterIndex = myData.currentfilter ; } - + DisposeNavObjectFilterUPP(mNavFilterUPP); if ( mDefaultLocation.dataHandle != nil ) { ::AEDisposeDesc(&mDefaultLocation); } - + if ( (err != noErr) && (err != userCanceledErr) ) { return wxID_CANCEL ; } - if (mNavReply.validRecord) { - + 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 ) { + if ( err != noErr ) + { m_path = wxT("") ; return wxID_CANCEL ; - } + } outFileSpec = **(FSSpec**) specDesc.dataHandle; if (specDesc.dataHandle != nil) { ::AEDisposeDesc(&specDesc); } m_path = wxMacFSSpec2MacFilename( &outFileSpec ) ; -#if TARGET_CARBON - if ( m_dialogStyle & wxSAVE ) - { - wxMacCFStringHolder cfString = NavDialogGetSaveFileName( navDialogRef ) ; - m_path += wxFILE_SEP_PATH + cfString.AsString() ; - } -#endif + m_paths.Add( m_path ) ; m_fileName = wxFileNameFromPath(m_path); m_fileNames.Add(m_fileName); @@ -549,16 +639,9 @@ int wxFileDialog::ShowModal() m_fileName = wxFileNameFromPath(m_path); m_dir = wxPathOnly(m_path); NavDisposeReply( &mNavReply ) ; -#if TARGET_CARBON - if ( navDialogRef ) - NavDialogDispose( navDialogRef ) ; -#endif return wxID_OK ; } -#if TARGET_CARBON - if ( navDialogRef ) - NavDialogDispose( navDialogRef ) ; -#endif return wxID_CANCEL; +#endif // TARGET_CARBON }