void AEGenericClass::SetDataForListOrObject(const AEDesc *tokenOrTokenList, const AppleEvent *appleEvent, AppleEvent *reply) { StAEDesc data; switch (tokenOrTokenList->descriptorType) { case typeAEList: { AECoreClass::GetAECoreHandler()->GetEventKeyDataParameter(appleEvent, typeWildCard, &data); SetDataForList(tokenOrTokenList, &data); } break; case cProperty: { ConstAETokenDesc tokenDesc(tokenOrTokenList); DescType propertyCode = tokenDesc.GetPropertyCode(); //DescType objectClass = tokenDesc.GetObjectClass(); if (CanSetProperty(propertyCode)) { AECoreClass::GetAECoreHandler()->GetEventKeyDataParameter(appleEvent, GetKeyEventDataAs(propertyCode), &data); SetDataForObject(tokenOrTokenList, &data); } else { ThrowIfOSErr(errAENotModifiable); } } break; default: ThrowIfOSErr(errAENotModifiable); } }
/*---------------------------------------------------------------------------- HandleCount ----------------------------------------------------------------------------*/ void AEGenericClass::HandleCount(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply) { ConstAETokenDesc tokenDesc(token); long numberOfObjects = 0; DescType objectClass; OSErr err = noErr; if (!reply->dataHandle) return; // Get the class of object that we will count err = GetObjectClassFromAppleEvent(appleEvent, &objectClass); ThrowIfOSErr(err); err = CheckForUnusedParameters(appleEvent); ThrowIfOSErr(err); if (AEListUtils::TokenContainsTokenList(token)) { err = AECountItems(token, &numberOfObjects); ThrowIfOSErr(err); } else { CountObjects(objectClass, tokenDesc.GetDispatchClass(), token, &numberOfObjects); } err = AEPutParamPtr(reply, keyAEResult, typeLongInteger, (Ptr)&numberOfObjects, sizeof(long)); ThrowIfOSErr(err); }
void AECoreClass::ExtractData(const AEDesc *source, AEDesc *data) { OSErr err = noErr; StAEDesc temp; DescType dispatchClass; if ((source->descriptorType == typeNull) || (source->dataHandle == nil)) ThrowIfOSErr(errAENoSuchObject); // If it's an object specifier, resolve into a token // Otherwise, just copy it if (source->descriptorType == typeObjectSpecifier) { err = AEResolve(source, kAEIDoMinimum, &temp); } else { err = AEDuplicateDesc(source, &temp); } ThrowIfOSErr(err); // Next, determine which object should handle it, if any. // If it's a property token, get the dispatch class. // Otherwise, just get the descriptorType. if (temp.descriptorType == typeProperty) { ConstAETokenDesc tokenDesc(&temp); dispatchClass = tokenDesc.GetDispatchClass(); } else dispatchClass = temp.descriptorType; // If it's a property token, get the data it refers to, // otherwise duplicate it and return AEDispatchHandler* handler = GetDispatchHandler(dispatchClass); if (handler) { /* case cApplication: // why? ThrowIfOSErr(errAEEventNotHandled); break; */ handler->GetDataFromListOrObject(&temp, nil, data); } else { err = AEDuplicateDesc(&temp, data); ThrowIfOSErr(err); } }
/*---------------------------------------------------------------------------- GetDataFromObject ----------------------------------------------------------------------------*/ void AEGenericClass::GetDataFromObject(const AEDesc *token, AEDesc *desiredTypes, AEDesc *data) { ConstAETokenDesc tokenDesc(token); DescType propertyCode = tokenDesc.GetPropertyCode(); OSErr err = noErr; switch (propertyCode) { case pContents: case typeNull: // must mean contents. Make a self specifier. CreateSpecifier(token, data); break; default: err = errAECantSupplyType; break; } ThrowIfOSErr(err); }
/*---------------------------------------------------------------------------- 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); }