//************************************************************************************** // Filename: BinJugglerCM.cp // Part of Contextual Menu Workshop by Abracode Inc. // http://free.abracode.com/cmworkshop/ // Copyright © 2002-2003 Abracode, Inc. All rights reserved. // // Description: Mac Binary encoder and decoder CM plugin // //************************************************************************************** #include "CFAbstractCMPlugin.h" #include "CMUtils.h" #include "MacBinaryIII.h" #include "StAEDesc.h" #include "StAllocThrowDisable.h" #include "DebugSettings.h" // Strings enum { kCommandStrings = 130, // STR# id kEncOrDecStrIndx = 1, kDecodeStrIndx, kEncodeStrIndx }; OSStatus FSSpecCheckFileOrFolder(const FSSpec *inSpec, void *ioData); OSStatus FSSpecProcessFileOrFolder(const FSSpec *inSpec, void *ioData); struct BJProcessData { AEDescList filesToKick; }; // --------------------------------------------------------------------------- // CMPluginExamineContext // --------------------------------------------------------------------------- // Have a look at the selection and decides whether to display any commands OSStatus CMPluginExamineContext( void *thisInstance, const AEDesc *inContext, AEDescList *outCommandPairs ) { StAllocThrowDisable disableNewThrows;//for MSL operator new TRACE_STR( "\pBinJugglerCM->CMPluginExamineContext" ); AbstractCMPluginType *theThis = (AbstractCMPluginType *)thisInstance; if(inContext == NULL) return errAENotAEDesc; if(inContext->descriptorType == typeNull) return errAENotAEDesc; UInt32 theFlags = kProcBreakOnFirst; Boolean isMacBinary = false; if( CMUtils::ProcessObjectList( inContext, theFlags, FSSpecCheckFileOrFolder, &isMacBinary ) ) { StBundleResOpen resOpen( theThis->bundleRef ); if( resOpen.IsValid() ) { if( (theFlags & kListOutMultipleObjects) != 0 ) { CMUtils::AddResCommand( outCommandPairs, kCommandStrings, kEncOrDecStrIndx, kEncodeDecodeCommand ); } else { if(isMacBinary) CMUtils::AddResCommand( outCommandPairs, kCommandStrings, kDecodeStrIndx, kEncodeDecodeCommand ); else CMUtils::AddResCommand( outCommandPairs, kCommandStrings, kEncodeStrIndx, kEncodeDecodeCommand ); } } } return noErr; } // --------------------------------------------------------------------------- // CMPluginHandleSelection // --------------------------------------------------------------------------- // Carry out the command that the user selected. The commandID indicates // which command was selected OSStatus CMPluginHandleSelection( void *thisInstance, AEDesc *inContext, SInt32 inCommandID ) { StAllocThrowDisable disableNewThrows;//for MSL operator new TRACE_STR( "\pBinJugglerCM->CMPluginHandleSelection" ); AbstractCMPluginType *theThis = (AbstractCMPluginType *)thisInstance; if(inCommandID == kEncodeDecodeCommand) { UInt32 theFlags = kListClear; BJProcessData processData; processData.filesToKick.descriptorType = typeNull; processData.filesToKick.dataHandle = NULL; OSStatus err = ::AECreateList( NULL, 0, false, &(processData.filesToKick) ); UInt32 fileCount = 0; CMUtils::ProcessObjectList( inContext, theFlags, FSSpecProcessFileOrFolder, &fileCount ); StAEDesc theDel(processData.filesToKick); if(processData.filesToKick.dataHandle != NULL) { SInt32 listItemsCount = 0; if( ::AECountItems( &processData.filesToKick, &listItemsCount) == noErr ) { if(listItemsCount > 0) {//tell Finder to update the modified items look CMUtils::SendAppleEventToFinder( kAEFinderSuite, kAESync, processData.filesToKick, false, false ); } } } } return noErr; } // --------------------------------------------------------------------------- // CMPluginPostMenuCleanup // --------------------------------------------------------------------------- void CMPluginPostMenuCleanup( void *thisInstance ) { StAllocThrowDisable disableNewThrows;//for MSL operator new TRACE_STR( "\pBinJugglerCM->CMPluginPostMenuCleanup" ); AbstractCMPluginType *theThis = (AbstractCMPluginType *)thisInstance; } #pragma mark - OSStatus FSSpecCheckFileOrFolder(const FSSpec *inSpec, void *ioData) { if( (inSpec == NULL) || (ioData == NULL) ) return paramErr; TRACE_STR( "\pBinJugglerCM->FSSpecCheckFileOrFolder" ); Boolean *outMacBin = (Boolean *)ioData; *outMacBin = false; //we are interested in files only Boolean isFolder = false; OSErr err = CMUtils::IsFolder(inSpec, isFolder); if(err == noErr) { if(isFolder) err = fnfErr; else *outMacBin = FSpIsMacBinary( inSpec ); } return err; } OSStatus FSSpecProcessFileOrFolder(const FSSpec *inSpec, void *ioData) { if( (inSpec == NULL) || (ioData == NULL) ) return paramErr; BJProcessData *processData = (BJProcessData *)ioData; TRACE_STR( "\pBinJugglerCM->FSSpecProcessFileOrFolder" ); Boolean isFolder = false; OSStatus err = CMUtils::IsFolder(inSpec, isFolder); if( err == noErr ) {//it is a file if(isFolder) return fnfErr; FSSpec specCopy; ::BlockMoveData( inSpec, &specCopy, sizeof(FSSpec) ); if( FSpIsMacBinary( &specCopy ) ) { err = DecodeMacBinaryFile( &specCopy ); } else { err = EncodeMacbinaryFile( &specCopy ); } if( (err == noErr) && (processData->filesToKick.dataHandle != NULL)) { StAEDesc fileDesc; err = CMUtils::CreateAliasDesc( &specCopy, fileDesc ); if( err == noErr ) { err = ::AEPutDesc( &(processData->filesToKick), 0, fileDesc ); } } } else { err = fnfErr;//indicate an error } return err; }