AECoreClass::AECoreClass(Boolean suspendEvents) : mSuspendEventHandlerUPP(nil) , mStandardSuiteHandlerUPP(nil) , mRequiredSuiteHandlerUPP(nil) , mCreateElementHandlerUPP(nil) , mMozillaSuiteHandlerUPP(nil) , mGetURLSuiteHandlerUPP(nil) , mSpyGlassSuiteHandlerUPP(nil) , mPropertyFromListAccessor(nil) , mAnythingFromAppAccessor(nil) , mCountItemsCallback(nil) , mCompareItemsCallback(nil) { mSuspendedEvent.descriptorType = typeNull; mSuspendedEvent.dataHandle = nil; mReplyToSuspendedEvent.descriptorType = typeNull; mReplyToSuspendedEvent.dataHandle = nil; OSErr err = ::AEObjectInit(); ThrowIfOSErr(err); mSuspendEventHandlerUPP = NewAEEventHandlerUPP(AECoreClass::SuspendEventHandler); ThrowIfNil(mSuspendEventHandlerUPP); mRequiredSuiteHandlerUPP = NewAEEventHandlerUPP(AECoreClass::RequiredSuiteHandler); ThrowIfNil(mRequiredSuiteHandlerUPP); mStandardSuiteHandlerUPP = NewAEEventHandlerUPP(AECoreClass::CoreSuiteHandler); ThrowIfNil(mStandardSuiteHandlerUPP); mMozillaSuiteHandlerUPP = NewAEEventHandlerUPP(AECoreClass::MozillaSuiteHandler); ThrowIfNil(mMozillaSuiteHandlerUPP); mGetURLSuiteHandlerUPP = NewAEEventHandlerUPP(AECoreClass::GetURLSuiteHandler); ThrowIfNil(mGetURLSuiteHandlerUPP); mSpyGlassSuiteHandlerUPP = NewAEEventHandlerUPP(AECoreClass::SpyglassSuiteHandler); ThrowIfNil(mSpyGlassSuiteHandlerUPP); InstallSuiteHandlers(suspendEvents); mCreateElementHandlerUPP = NewAEEventHandlerUPP(AECoreClass::CreateElementHandler); ThrowIfNil(mCreateElementHandlerUPP); // Special handler for StandardSuite Make (CreateElement) event // Make (CreateElement) is different than the other events processed above // because it passes its ospec in the insertionLoc parameter instead of // in the direct object parameter. err = ::AEInstallEventHandler(kAECoreSuite, kAECreateElement, mCreateElementHandlerUPP, (long)this, false); ThrowIfOSErr(err); /* We'd like to be able to install a generic handler that is used to get anything from null. Unfortunately, some formRelative requests require a handler for getting an item from another of the same type (e.g. "get the window after window 'foo'" requires a cWindow from cWindow handler). */ // Install a generic handler to get an item from the app mAnythingFromAppAccessor = NewOSLAccessorUPP(AECoreClass::AnythingFromAppAccessor); ThrowIfNil(mAnythingFromAppAccessor); // Install a handler to get properties from anything. err = ::AEInstallObjectAccessor(typeWildCard, typeWildCard, mAnythingFromAppAccessor, (long)this, false); ThrowIfOSErr(err); // Install a generic handler to get a property from a typeAEList of tokens mPropertyFromListAccessor = NewOSLAccessorUPP(AECoreClass::PropertyTokenFromAnything); ThrowIfNil(mPropertyFromListAccessor); // Install a handler to get properties from anything. err = ::AEInstallObjectAccessor(cProperty, typeWildCard, mPropertyFromListAccessor, (long)this, false); ThrowIfOSErr(err); // Install the OSL object callbacks, use for compare and count mCountItemsCallback = NewOSLCountUPP(AECoreClass::CountObjectsCallback); ThrowIfNil(mCountItemsCallback); mCompareItemsCallback = NewOSLCompareUPP(AECoreClass::CompareObjectsCallback); ThrowIfNil(mCompareItemsCallback); err = ::AESetObjectCallbacks( mCompareItemsCallback, mCountItemsCallback, (OSLDisposeTokenUPP) nil, (OSLGetMarkTokenUPP) nil, (OSLMarkUPP) nil, (OSLAdjustMarksUPP) nil, (OSLGetErrDescUPP) nil); ThrowIfOSErr(err); // create the dispatchers for various object types. This should be the only place // that new classes have to be added AEApplicationClass* appDispatcher = new AEApplicationClass; RegisterClassHandler(cApplication, appDispatcher); RegisterClassHandler(typeNull, appDispatcher, true); AEDocumentClass* docDispatcher = new AEDocumentClass; RegisterClassHandler(cDocument, docDispatcher); AEWindowClass* windowDispatcher = new AEWindowClass(cWindow, kAnyWindowKind); RegisterClassHandler(cWindow, windowDispatcher); /* AETextClass* textDispatcher = new AETextClass; RegisterClassHandler(AETextClass::cTEText, textDispatcher); AEWordClass* wordDispatcher = new AEWordClass; RegisterClassHandler(cWord, wordDispatcher); AECharacterClass* charDispatcher = new AECharacterClass; RegisterClassHandler(cChar, charDispatcher); */ }
/*---------------------------------------------------------------------------- HandleClose ----------------------------------------------------------------------------*/ void AEGenericClass::HandleClose(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) { ThrowIfOSErr(errAEEventNotHandled); }
/*---------------------------------------------------------------------------- HandleCoreSuiteEvent ----------------------------------------------------------------------------*/ void AECoreClass::HandleCoreSuiteEvent(const AppleEvent *appleEvent, AppleEvent *reply) { StAEDesc directParameter; StAEDesc token; OSErr err = noErr; // extract the direct parameter (an object specifier) err = ::AEGetKeyDesc(appleEvent, keyDirectObject, typeWildCard, &directParameter); ThrowIfOSErr(err); DescType tokenType = typeNull; DescType dispatchClass = typeNull; // check for null descriptor, which AEResolve doesn't handle well // If it's not null, then AEResolve will return an application-defined token if (directParameter.descriptorType == typeNull) { token = directParameter; // can throw } else { // The direct parameter contains an object specifier, or an "reference" in // AppleScript terminology, such as "rectangle 1 of document 1". // AEResolve() will recursively call our installed object accessors // until it returns a token with data referencing the requested object. err = ::AEResolve(&directParameter, kAEIDoMinimum, &token); } if (err == errAENoSuchObject || err == errAEIllegalIndex) { // If we were executing an "Exists..." AppleEvent, we can reply it here // because we have already determined that it DOES NOT exist. // First, we get the event ID. We use "eventError" instead of "err" // so that the result of AEGetAttributePtr() does not disturb the // errAENoSuchObject result previously returned. AEEventID eventID; OSType typeCode; Size actualSize = 0; OSErr eventError = ::AEGetAttributePtr(appleEvent, keyEventIDAttr, typeType, &typeCode, (Ptr)&eventID, // Get the eventID from the AppleEvent sizeof(eventID), &actualSize); // If event was an "Exists..." message, store the result (false) in the reply // because AEResolve() returned errAENoSuchObject. if (eventError == noErr && eventID == kAEDoObjectsExist) { Boolean foundIt = false; (void)AEPutParamPtr(reply, keyAEResult, typeBoolean, (Ptr)&foundIt, sizeof(Boolean)); // Now, we set the err to noErr so that the scripting component doesn't complain // that the object does not exist. We only do this if we were executing an "Exists..." // event. Otherwise, the errAENoSuchObject will be returned. ThrowNoErr(); } ThrowIfOSErr(err); return; } ThrowIfOSErr(err); // Pass the token returned by AEResolve(), and the original AppleEvent event and reply, // on to the appropriate object dispatcher // The token type is, by convention, the same as class ID that handles this event. // However, for property tokens, tokenType is cProperty for all objects, so // we look inside the token at its dispatchClass to find out which class of object // should really handle this AppleEvent. // Also, if the resolver returned a list of objects in the token, // the type will be typeAEList or one of our special list types, so // we set the dispatch class based on the list type // instead of on the type of the token itself if (AEListUtils::TokenContainsTokenList(&token)) { SInt32 numItems; err = AECountItems(&token, &numItems); if (numItems == 0) // could be an empty list { dispatchClass = typeNull; } else { StAEDesc tempToken; err = AEListUtils::GetFirstNonListToken((AEDesc *)&token, &tempToken); if (err == noErr && tempToken.descriptorType != typeNull) { ConstAETokenDesc tokenDesc(&tempToken); dispatchClass = tokenDesc.GetDispatchClass(); } else { dispatchClass = typeNull; err = noErr; } } } else if (token.descriptorType == typeNull) // make sure we correctly handle things for cApplication that don't have a direct parameter { dispatchClass = typeNull; } else { ConstAETokenDesc tokenDesc(&token); dispatchClass = tokenDesc.GetDispatchClass(); } // why is this special-cased? if (dispatchClass == cFile) { AEEventID eventID = 0; OSType typeCode = 0; Size actualSize = 0; OSErr eventError = AEGetAttributePtr(appleEvent, keyEventIDAttr, typeType, &typeCode, (Ptr)&eventID, // Get the eventID from the AppleEvent sizeof(eventID), &actualSize); } AEDispatchHandler* handler = GetDispatchHandler(dispatchClass); if (!handler) ThrowIfOSErr(errAEEventNotHandled); handler->DispatchEvent(&token, appleEvent, reply); }