home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1996-04-22 | 60.0 KB | 1,897 lines | [ TEXT/MPS ]
/* File: MssgIntf.cpp Contains: Implementation of ODMessageInterface class Owned by: Nick Pilch Copyright: © 1994 - 1996 by Apple Computer, Inc., all rights reserved. Change History (most recent first): <6> .03.1996 NP Added comments about checking for the current process. <5> 3/14/96 TJ Changed volatile to ODVolatile. <4> 3/1/96 JP 1321991: Fixed potential memory leak <3> 1/15/96 TJ Cleaned Up <2> 1/5/96 JP 1308887: Fixed aete handling <64> 10/10/95 NP 1290945: Memory leaks. <63> 10/4/95 jpa Added missing ODVolatiles [1285799] <62> 25/09/95 NP 1979071: Check results of operator new. <61> 9/19/95 JP 1285737: Renumber OpenDoc aete <60> 9/12/95 JP 1280292 & 1283803: Add Part to Send <59> 9/11/95 NP 1272294: Messaging code cleanup. <58> 8/26/95 TÇ 1274606 FB2: Patching Remarks <57> 8/25/95 JP 1272288: Terminology and Subject Attribute implementation <56> 8/23/95 NP 1276287: Move constant kODAppShell. <55> 8/16/95 eeh 1276765: check for bit in sendmode; 1276765: remove DeleteAll <54> 8/16/95 NP 1275241: IDL Review. Remove unnecessary overrides. <53> 8/7/95 NP 1275102: Memory leak. <52> 8/3/95 RR #1257260: Collapse B classes. Remove somInit methods. Don't call IsInitialized or SubclassResponsibility <51> 8/1/95 eeh 1265319: update token to be disposed <50> 7/27/95 DM #1270320: mem leaks: fix ordering problem with deletion <49> 7/27/95 DM #1270320: mem leaks: delete theToken in HandleAllSEventsAux despite exception <48> 7/24/95 CG #1270320: Memory leak fixes. <47> 7/21/95 eeh 1251249: remove ReleaseRealPart call; 1262143: call ODDisposeAppleEvent <46> 7/18/95 eeh 1262143: memory leaks <45> 6/30/95 JP Use FlushContextCache <44> 6/28/95 eeh 1263332: don't dispose uninitialized var <43> 6/23/95 NP 1262326: Memory leak calling coercion handlers. <42> 6/22/95 NP 1251894: Handle lists returned by OSL. <41> 6/22/95 jpa Added ODVolatile decls for semt intfs to fix ref-counting errors. [1261644] <40> 6/19/95 eeh 1246443: add PartFrameFromStandardPartToken etc. <39> 6/13/95 eeh 1254943: call default handler only on eventnothandled <38> 6/7/95 eeh 1251403: fixed refcounting <37> 5/26/95 RR #1251403: Multithreading naming support <36> 5/24/95 CG #1250398 BB: (for eeh) Replaced DebugStr with Throw. <35> 5/21/95 NP 1251643: BlockMove reply data back into descriptor that AE Manager passed in. <34> 5/21/95 NP 1248898: GetUserToken, ODDescToAEDesc, etc. recipe change. <32> 5/18/95 eeh 1250424, 1246442: try root part and embedded when eventNotHandled returned <31> 5/12/95 NP 1246048: Final token from Resolve not disposed. 1246018: Dispose object specifier. <30> 5/3/95 NP 1211084: Remove 5$ <29> 4/27/95 eeh 1240648: call part::ReleaseExtension <28> 4/25/95 NP 1230729: Comment out code that doesn't do anything. <27> 3/24/95 eeh 1232249: remove ClearLastSwapFrame <26> 3/21/95 JP 1192027: Include ODRgstry & change some constant names <25> 3/2/95 eeh 1214783: finish work on lists <24> 3/1/95 NP 1224604: Fix write to nil problem. <23> 2/21/95 eeh 1214783: remove (sendee != kODAppShell) test from DispatchToEventHandlerAux <22> 2/13/95 eeh 1214783: new param to DispatchToEventHandler and DispatchToEventHandlerAux <21> 2/8/95 NP 1218542: Removed special case shell code. Default handlers do this now. <20> 2/3/95 eeh 1217393: use new ODDesc etc <19> 1/27/95 NP 1213948: New classes for ODDesc et al. <18> 1/25/95 eeh 1214783: add GetDefaultSI, other changes for default accessors <17> 1/16/95 eeh 1195186: remove $&@%$%@ got it DebugStr <16> 1/11/95 NP #1199991-Don't use ODPartWrapper. <15> 1/9/95 NP 1194880: SemtIntf name changes. <14> 12/23/94 JBS 1186869: hide ODPartWrapper from public API; 1192557: ODPartWrapper realPart access <13> 11/15/94 NP 1199847,1199991-Many changes. <12> 10/10/94 NP 1192023: create default handler table and add function to initialize it. <11> 9/15/94 NP 1186778: strip private token info off when returning from resolve. <10> 9/13/94 NP 1186338: Fixed: random error return values passed back to Apple event manager when event handler succeeeded. <9> 9/9/94 NP 1185851: implement scripting. <8> 9/9/94 jpa Added more TRY/CATCH error handling now that SOM exceptions are being thrown. [1185656] <7> 8/13/94 NP 1180819-Call InitBaseMessageInterface and not InitObject. <6> 8/3/94 NP Fixed event handler return value propogation and creation and handling of part object specifiers. <5> 7/8/94 NP Fixed event handling, added coercion handling. <4> 7/5/94 NP Tweaking… <3> 7/1/94 NP Filled in most of the implementation. <1> 6/29/94 NP first checked in To Do: Check all functions and methods that call methods that *now* return ev parameters. In Progress: */ #ifndef _SIHELPER_ #include "SIHelper.h" #endif #ifndef _DFLTACS_ #include <DfltAcs.h> #endif #ifndef _SEPRIV_ #include "SEPriv.h" #endif #ifndef _BARRAY_ #include "BArray.h" #endif #ifndef _ORDCOLL_ #include "OrdColl.h" #endif #ifndef _EXCEPT_ #include "Except.h" #endif #ifndef _SEUTILS_ #include "SEUtils.h" #endif #ifndef _ODDESUTL_ #include "ODDesUtl.h" #endif #ifndef _ODMEMORY_ #include "ODMemory.h" #endif #ifndef SOM_ODNameSpaceManager_xh #include "NmSpcMg.xh" #endif #ifndef _USERSRCM_ #include <UseRsrcM.h> #endif #ifndef SOM_ODSession_xh #include "ODSessn.xh" #endif #ifndef SOM_ODPartWrapper_xh #include "PartWrap.xh" #endif #ifndef SOM_ODNameResolver_xh #include "NamRslvr.xh" #endif #ifndef SOM_ODSemanticInterface_xh #include "SemtIntB.xh" #endif #ifndef SOM_DefaultAccessorSI_xh #include "MssgSI.xh" #endif #ifndef SOM_ODAppleEvent_xh #include "ODAplEvt.xh" #endif #ifndef SOM_ODObjectSpec_xh #include "ODObjSpc.xh" #endif #ifndef SOM_ODAddressDesc_xh #include "ODAdrDes.xh" #endif #ifndef _TEMPOBJ_ #include <TempObj.h> #endif #ifndef SOM_ODDesc_xh #include "ODDesc.xh" #endif #ifndef SOM_ODOSLToken_xh #include "ODOSLTkn.xh" #endif #ifndef _ODREGISTRY_ #include "ODRgstry.xh" #endif #ifndef SOM_Module_OpenDoc_StdDefs_defined #include <StdDefs.xh> #endif #ifndef __AEPACKOBJECT__ #include <AEPackObject.h> #endif #ifndef __AEOBJECTS__ #include <AEObjects.h> #endif #ifndef __ASREGISTRY__ #include <ASRegistry.h> #endif #ifndef __OSA__ #include <OSA.h> #endif #define VARIABLE_MACROS #define ODMessageInterface_Class_Source #include <MssgIntf.xih> #pragma segment ODMessageInterface #include "MssgIntB.cpp" // Platform-independent methods, if any //============================================================================== // Globals defined //============================================================================== ODMessageInterface* gMessageInterface = kODNULL; //============================================================================== // Local Classes //============================================================================== class SETransactionLink : public Link { public: SETransactionLink(ODPart* part, ODSShort returnID) {fPart = part; fReturnID = returnID;} ~ SETransactionLink() {} ODPart* fPart; ODSShort fReturnID; }; class SETransactionList { public: void Add(ODPart* part, ODSShort returnID); void Remove(ODPart* part, ODSShort returnID); ODBoolean Find(ODSShort returnID, ODPart** part); // returns kODFalse if not found. // void DeleteAll(); ~SETransactionList(); private: LinkedList fList; }; struct PreHandlerInfo { public: PreHandlerInfo(ODSemanticInterface* face, ODULong refCon) {fSemanticInterface = face; fRefCon = refCon;} ODSemanticInterface* GetSemanticInterface() {return fSemanticInterface;} ODULong GetRefCon() {return fRefCon;} private: ODSemanticInterface* fSemanticInterface; ODULong fRefCon; }; //============================================================================== // Function Prototype //============================================================================== static ODSShort GetReturnID(AppleEvent* ae); static ODBoolean SentToSelf(AppleEvent* ae); static ODPart* GetTokenPart( Environment* ev, ODNameResolver* resolver, AEDesc* token ); static pascal OSErr HandleAllSEvents( AppleEvent* message, AppleEvent* reply, long refCon); static pascal OSErr HandleReplies( AppleEvent* message, AppleEvent* reply, long refCon); static pascal OSErr HandleGetAETE( AppleEvent* message, AppleEvent* reply, long refCon); static pascal OSErr HandleAllCoercions( const AEDesc* theAEDesc, DescType toType, long refCon, AEDesc* retDesc); static pascal OSErr HandlePreDispatch( AppleEvent* message, AppleEvent* reply, long refCon); static void PlaceEmptyListIntoReply(AppleEvent* reply); static void CreateSubjectObject(Environment* ev, ODFrame* frame, AEDesc* objSpec); //============================================================================== // SETransactionList //============================================================================== //------------------------------------------------------------------------------ // SETransactionList::Add //------------------------------------------------------------------------------ void SETransactionList::Add(ODPart* part, ODSShort returnID) { SETransactionLink* aLink = new SETransactionLink(part, returnID); if (!aLink) THROW(kODErrOutOfMemory); fList.AddLast(aLink); } //------------------------------------------------------------------------------ // SETransactionList::Remove // // Do I really need to match both things? How about only the returnID? //------------------------------------------------------------------------------ void SETransactionList::Remove(ODPart* part, ODSShort returnID) { LinkedListIterator iter(&fList); SETransactionLink* aLink = (SETransactionLink*)iter.First(); while (aLink != NULL) { if ((aLink->fPart == part) && (aLink->fReturnID) == returnID) { fList.Remove(*aLink); delete aLink; break; } else aLink = (SETransactionLink*)iter.Next(); } } //------------------------------------------------------------------------------ // SETransactionList::Find //------------------------------------------------------------------------------ ODBoolean SETransactionList::Find(ODSShort returnID, ODPart** part) { LinkedListIterator iter(&fList); SETransactionLink* aLink = (SETransactionLink*)iter.First(); while (aLink != NULL) { if (aLink->fReturnID == returnID) { *part = aLink->fPart; return kODTrue; } else aLink = (SETransactionLink*)iter.Next(); } return kODFalse; } //------------------------------------------------------------------------------ // SETransactionList::DeleteAll (Copied from OrderedCollection::DeleteAll) //------------------------------------------------------------------------------ // This is a no-op now that value isn't being deleted (which it never should // have been.) So we just call the destructor instead. #if 0 void SETransactionList::DeleteAll() { Link* link; // = fList.RemoveFirst(); while ((link = fList.RemoveFirst()) != kODNULL) { ElementType value = ((ValueLink*) link)->GetValue(); // delete value; // <eeh> no value was allocated by Add. This is // an ODPartWrapper* that may have a refcount > 0. // And if I'm right that we should not delete value, // then this whole method can be replaced with a call: // fList.DeleteAllLinks(); delete link; // link = fList.RemoveFirst(); } } #endif //------------------------------------------------------------------------------ // SETransactionList::~SETransactionList //------------------------------------------------------------------------------ SETransactionList::~SETransactionList() { fList.DeleteAllLinks(); } //============================================================================== // ODMessageInterface //============================================================================== //------------------------------------------------------------------------------ // ODMessageInterface::InitMessageInterface //------------------------------------------------------------------------------ SOM_Scope void SOMLINK ODMessageInterfaceInitMessageInterface(ODMessageInterface *somSelf, Environment *ev, ODSession* session) { SOM_CATCH return; ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfaceInitMessageInterface"); /* Moved from somInit. SOM itself sets fields to zero _fPreHandlers = kODNULL; _fTransactionList = kODNULL; _fSession = kODNULL; _fNameResolver = kODNULL; _fDefaultSI = kODNULL; */ _fNextReturnID = 1; somSelf->InitObject(ev); gMessageInterface = somSelf; // FOR THE PREHANDLER PROC THAT DOESN'T HAVE A // REFCON. _fSession = session; _fNameResolver = _fSession->GetNameResolver(ev); _fTransactionList = new SETransactionList; _fPreHandlers = new OrderedCollection; DefaultAccessorSI* face = new DefaultAccessorSI(); // SIHelper* help = new SIHelper(); // help->InitSIHelper(face); // face->InitCPlusSemanticInterface(ev, kODAppShell, help, _fSession); face->InitCPlusSemanticInterface(ev, kODAppShell, kODNULL, _fSession); _fDefaultSI = face; THROW_IF_ERROR(AEInstallEventHandler(typeWildCard, typeWildCard, NewAEEventHandlerProc(HandleAllSEvents), (long)somSelf, ! kIsSysHandler)); THROW_IF_ERROR(AEInstallEventHandler(kCoreEventClass, kAEAnswer, NewAEEventHandlerProc(HandleReplies), (long)somSelf, ! kIsSysHandler)); THROW_IF_ERROR(AEInstallEventHandler(kASAppleScriptSuite, kGetAETE, NewAEEventHandlerProc(HandleGetAETE), (long)somSelf, ! kIsSysHandler)); THROW_IF_ERROR(AEInstallSpecialHandler(keyPreDispatch, (UniversalProcPtr)NewAEEventHandlerProc(HandlePreDispatch), ! kIsSysHandler)); THROW_IF_ERROR(AEInstallCoercionHandler(typeWildCard, typeWildCard, (AECoercionHandlerUPP)NewAECoerceDescProc(HandleAllCoercions), (long)somSelf, kFromTypeIsDesc, ! kIsSysHandler)); } //------------------------------------------------------------------------------ // ODMessageInterface::somUninit //------------------------------------------------------------------------------ SOM_Scope void SOMLINK ODMessageInterfacesomUninit(ODMessageInterface *somSelf) { ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfacesomUninit"); Environment* ev = somGetGlobalEnvironment (); ODDeleteObject( _fTransactionList ); if (_fPreHandlers) { _fPreHandlers->DeleteAll(); ODDeleteObject( _fPreHandlers ); } ODReleaseObject(ev, _fDefaultSI); } #if 0 //------------------------------------------------------------------------------ // ODMessageInterface::Purge //------------------------------------------------------------------------------ SOM_Scope ODSize SOMLINK ODMessageInterfacePurge(ODMessageInterface *somSelf, Environment *ev, ODSize size) { // ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfacePurge"); ODSize purged = 0; ODVolatile( purged ); SOM_TRY purged = ODMessageInterface_parent_ODObject_Purge(somSelf,ev,size); SOM_CATCH_ALL WARN("Error %ld trying to purge in ODMessageInterfacePurge",ErrorCode()); SetErrorCode(kODNoError); // Eat the exception; Purge should not // propagate it because clients function // fine whether memory was purged or not. // dh - Also removed zeroing of purge total if an exception was thrown. // The number should be accurate regardless of exceptions because of // the initializer of the counter. SOM_ENDTRY return purged; } #endif /* 0 */ //------------------------------------------------------------------------------ // ODMessageInterface::CreateEvent //------------------------------------------------------------------------------ SOM_Scope ODSShort SOMLINK ODMessageInterfaceCreateEvent(ODMessageInterface *somSelf, Environment *ev, ODEventClass theAEEventClass, ODEventID theAEEventID, ODAddressDesc* target, ODSLong transactionID, ODAppleEvent** result) { ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfaceCreateEvent"); OSErr error; ODSShort retVal = 0; SOM_TRY // TO BE ABSOLUTELY CORRECT, I SHOULD CHECK THAT THE RETURN ID I'M USING IS // NOT IN THE _fTransactionList. HOWEVER, IS THIS OVERKILL? -- Yes. AppleEvent newEvent; AEAddressDesc targetAsAEDesc; error = ODDescToAEDesc( target, &targetAsAEDesc ); if ( !error ) { error = AECreateAppleEvent(theAEEventClass, theAEEventID, &targetAsAEDesc, _fNextReturnID, transactionID, &newEvent); AEDisposeDesc(&targetAsAEDesc); } if ( !error ) { // stick it in the event ODAppleEvent* coverEvent = new ODAppleEvent(); THROW_IF_NULL(coverEvent); coverEvent->InitODAppleEvent(ev); error = AEDescToODDesc( &newEvent, coverEvent ); ODDisposeAppleEvent(&newEvent); if ( !error ) *result = coverEvent; else { ODDeleteObject(coverEvent); *result = kODNULL; } } THROW_IF_ERROR (error); retVal = _fNextReturnID++; SOM_CATCH_ALL SOM_ENDTRY return retVal; } //------------------------------------------------------------------------------ // ODMessageInterface::Send //------------------------------------------------------------------------------ SOM_Scope void SOMLINK ODMessageInterfaceSend(ODMessageInterface *somSelf, Environment *ev, ODFrame* toFrame, ODPart* fromPart, ODAppleEvent* theAppleEvent, ODAppleEvent* reply, ODSendMode sendMode, ODSendPriority sendPriority, ODULong timeOutInTicks) { ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfaceSend"); // MIGHT CHECK WHETHER WE'RE SENDING IN THE SAME PROCESS. THEN WE CAN // AVOID THE APPLEEVENT MANAGER ALTOGETHER PERHAPS!!!! AppleEvent realEvent = NULL_DESCRIPTOR_DEFINITION; AppleEvent realReply = NULL_DESCRIPTOR_DEFINITION; OSErr result; ODSShort returnID; ODBoolean isCurrentProcess; SOM_TRY THROW_IF_ERROR( ODDescToAEDesc(theAppleEvent, &realEvent )); // THROW_IF_ERROR( ODDescToAEDesc(reply, &realReply )); // add subject attribute if (toFrame) { AEDesc subj = NULL_DESCRIPTOR_DEFINITION; CreateSubjectObject(ev, toFrame, &subj); THROW_IF_ERROR( AEPutAttributeDesc(&realEvent, keySubjectAttr, &subj) ); AEDisposeDesc(&subj); } TRY returnID = GetReturnID( &realEvent ); CATCH_ALL returnID = _fNextReturnID++; ENDTRY _fTransactionList->Add(fromPart, returnID); // $$$$$ CURRENTLY, THIS DOES NOT RETURN THE CORRECT RESULT. THEREFORE, // THE "if" WILL ONLY BE ENTERED IF THE CALLING PART SPECIFIES // kCurrentProcess IN THE ADDRESS DESCRIPTOR AND kAEQueueReply. THERE // ARE NO TEST CASES FOR THIS THAT I KNOW OF, HOWEVER. isCurrentProcess = SentToSelf( &realEvent ); if ((sendMode == kAEQueueReply) && isCurrentProcess) { // WORK AROUND CONDITION THAT REPLY HANDLER IS NOT CALLED IF SENDING // IN THE SAME PROCESS. DO WE HAVE TO DO THIS? PEOPLE SHOULD ALREADY // EXPECT IT. MAYBE WE LET THE USUAL THING HAPPEN FOR A PART SENDING // TO ITSELF AND DO THE MAGIC IF THE SENDER AND RECEIVER PARTS ARE // DIFFERENT!!!! result = AESend(&realEvent, &realReply, kAEWaitReply, sendPriority, timeOutInTicks, (AEIdleUPP)kODNULL, (AEFilterUPP)kODNULL); if (result == noErr) // <eeh> is this right? result = somSelf->DispatchToEventHandler(ev, &realReply, nil, fromPart, kODNULL); _fTransactionList->Remove(fromPart, returnID); } else { result = AESend(&realEvent, &realReply, sendMode, sendPriority, timeOutInTicks, (AEIdleUPP)kODNULL, (AEFilterUPP)kODNULL); if ((sendMode & kAEWaitReply != 0) || (sendMode == kAENoReply) || (result != noErr)) _fTransactionList->Remove(fromPart, returnID); } // UPDATE REPLY FOR CALLER THROW_IF_ERROR(AEDescToODDesc(&realReply, reply)); #ifdef TO_BE_DELETED if (realReply.descriptorType != typeNull && realReply.dataHandle != kODNULL) { AEDesc tempDesc; OSErr tempErr; tempErr = AEGetParamDesc(&realReply, keyDirectObject, typeWildCard, &tempDesc); if (!tempErr) AEDisposeDesc(&tempDesc); } #endif THROW_IF_ERROR (result); SOM_CATCH_ALL SOM_ENDTRY ODDisposeAppleEvent(&realReply); ODDisposeAppleEvent(&realEvent); } //------------------------------------------------------------------------------ // ODMessageInterface::ProcessSemanticEvent //------------------------------------------------------------------------------ SOM_Scope ODBoolean SOMLINK ODMessageInterfaceProcessSemanticEvent(ODMessageInterface *somSelf, Environment *ev, ODEventData* theEvent) { // ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ProcessSemanticEvent"); return ! AEProcessAppleEvent((const EventRecord*)theEvent); } //------------------------------------------------------------------------------ // HandleAllSEvents //------------------------------------------------------------------------------ static pascal OSErr HandleAllSEvents(AppleEvent* message, AppleEvent* reply, long refCon) { ODMessageInterface* self = (ODMessageInterface*)refCon; return self->HandleAllSEventsAux(somGetGlobalEnvironment(), message, reply); } //------------------------------------------------------------------------------ // ODMessageInterface::HandleAllSEventsAux // // If there's an object specifier in the direct parameter, we use it to find // out to whom to send the event. // // Rework flow of control!!!! // // Since it's a private method, I'm not using SOM exceptions for now. //------------------------------------------------------------------------------ SOM_Scope OSErr SOMLINK ODMessageInterfaceHandleAllSEventsAux(ODMessageInterface *somSelf, Environment *ev, AppleEvent* message, AppleEvent* reply) { ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfaceHandleAllSEventsAux"); //DebugStr("\pOK. Here we are."); OSErr result; AEDesc theObject; OSLToken tokenAsAEDesc = NULL_DESCRIPTOR_DEFINITION; ODBoolean doResolution = kODFalse; ODBoolean gotSubject = kODFalse; ODPart* destinationPart = kODAppShell; ODBoolean haveValidObject = kODFalse; // Reset these, because I might be examining them real soon. // _fNameResolver->SetLastContainer(ev, typeNull); // _fNameResolver->SetLastObject(ev, typeNull); // _fNameResolver->ClearLastSwapFrame(ev) ; //DebugStr("\pStart event handler;ht;g"); TRY _fNameResolver->NeedContextCache(ev, kODTrue); // SEE IF WE HAVE TO SPECIAL CASE THIS EVENT // if (somSelf->HandleSpecialEvents(ev, message, reply, &result)) // return result; result = AEGetParamDesc(message, keyDirectObject, typeWildCard, &theObject); if (!result) haveValidObject = kODTrue; // IF WE HAVE AN OBJECT SPECIFIER IN THE DIRECT OBJECT, USE IT TO FIND // PART TO DISPATCH TO. // BUT CHECK FOR SPECIAL OBJECT SPECIFIER if (!result && (theObject.descriptorType == typeObjectSpecifier)) { DescType gotType; DescType desiredPartSize = sizeof(ODPart*); DescType desiredDescSize = sizeof(DescType); DescType gotSize; DescType keyForm; ODPart* thePart; AEDesc objSpecCopy; AEDesc objSpecAsRecord; // DebugStr("\pgot it."); // IS IT ONE OF OUR SPECIAL OBJECT SPECIFIERS? THROW_IF_ERROR(AEDuplicateDesc(&theObject, &objSpecCopy)); result = AECoerceDesc(&objSpecCopy, typeAERecord, &objSpecAsRecord); if (!result) { result = AEGetKeyPtr(&objSpecAsRecord, keyAEKeyForm, typeEnumerated, &gotType, &keyForm, desiredDescSize, (long*)&gotSize); if (!result && (gotType == typeEnumerated) && (gotSize == desiredDescSize) && (keyForm == cPart)) { result = AEGetKeyPtr(&objSpecAsRecord, keyAEKeyData, typeLongInteger, &gotType, &thePart, desiredPartSize, (long*)&gotSize); if (!result && (gotType == typeLongInteger) && (gotSize == desiredPartSize)) destinationPart = thePart; else doResolution = kODTrue; } else doResolution = kODTrue; } else doResolution = kODTrue; AEDisposeDesc(&objSpecCopy); AEDisposeDesc(&objSpecAsRecord); } else { // NO DIRECT OBJECT, BUT HAVE A SUBJECT ATTRIBUTE, USE IT TO FIND // PART TO DISPATCH TO. AEDesc theSubject = NULL_DESCRIPTOR_DEFINITION; result = AEGetAttributeDesc(message, keySubjectAttr, typeWildCard, &theSubject); if (!result && (theSubject.descriptorType == typeObjectSpecifier)) { theObject = theSubject; doResolution = kODTrue; gotSubject = kODTrue; haveValidObject = kODTrue; } else AEDisposeDesc(&theSubject); } if (doResolution) { OSErr error = noErr; ODObjectSpec* objWrapper = new ODObjectSpec(); THROW_IF_NULL(objWrapper); objWrapper->InitODObjectSpec(ev); ODOSLToken* theToken = new ODOSLToken(); THROW_IF_NULL(theToken); theToken->InitODOSLToken(ev); TRY THROW_IF_ERROR( AEDescToODDesc(&theObject, objWrapper ) ); theToken->SetDescType(ev, typeNull); _fNameResolver->Resolve(ev, objWrapper, theToken, kODAppShell); THROW_IF_ERROR(ODDescToAEDesc(theToken, &tokenAsAEDesc)); CATCH_ALL result = ErrorCode(); ENDTRY ODDeleteObject( objWrapper ); if ( !result ) { result = somSelf->DispatchEventWithToken(ev, &tokenAsAEDesc, message, reply, gotSubject, kODFalse); // DispatchEventWithToken may have modified the token. Copy // into the ODDesc that will be passed to DisposeToken. THROW_IF_ERROR( AEDescToODDesc( &tokenAsAEDesc, theToken )); AEDisposeDesc(&tokenAsAEDesc); } if (theToken) _fNameResolver->DisposeToken(ev, theToken); } else if ( theObject.descriptorType == typeUserToken ) { result = somSelf->DispatchEventWithToken(ev, &theObject, message, reply, gotSubject, kODTrue ); } else // SEND TO THE DESTINATION DIRECTLY result = somSelf->DispatchToEventHandler(ev, message, reply, destinationPart, kODNULL ); CATCH_ALL result = ErrorCode(); if (haveValidObject) AEDisposeDesc(&theObject); ENDTRY if (haveValidObject) AEDisposeDesc(&theObject); _fNameResolver->NeedContextCache(ev, kODFalse); _fNameResolver->FlushContextCache(ev); //DebugStr("\p with event handler;ht"); return result; } // HandleAllSEventsAux //------------------------------------------------------------------------------ // ODMessageInterface::DispatchEventWithToken // // Recursive routine to deal with list tokens whose items might be other // lists. But should we stop dispatching if we get an error???? // // Need to clean up flow of control here. // // Since it's a private method, I'm not using SOM exceptions for now. //------------------------------------------------------------------------------ SOM_Scope OSErr SOMLINK ODMessageInterfaceDispatchEventWithToken(ODMessageInterface *somSelf, Environment *ev, OSLToken* token, AppleEvent* message, AppleEvent* reply, ODBoolean usingSubjectAttr, ODBoolean dpAlreadyToken) { ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfaceDispatchEventWithToken"); OSErr error = noErr; ODBoolean handledEventRightHere = kODFalse; // WE USED TO UNPACK ALL LISTS, EVEN THOSE CREATED BY A PART EDITOR. NOW // WE ONLY NEED TO DEAL WITH LISTS IF THE OSL CREATES THEM ITSELF. // UNFORTUNATELY, I'M NOT SURE WHAT THE RIGHT THING TO DO IS. IF WE UNPACK // THE LIST AND MULTICAST OURSELVES, WE COULD END UP WITH MULTIPLE EVENTS // WHEN ONLY ONE WAS APPROPRIATE. NEED TO CONFER WITH KURT. -NP 5/19/95 if (token->descriptorType == typeAEList) { AEDesc embeddedToken; ODSLong itemCount; AEKeyword returnedKeyWord; ODFrame* prevFrame; ODFrame* thisFrame; ODPart* prevPart; ODPart* thisPart; #if ODDebug // ASSERTM(kODFalse, errAEEventNotHandled, "ODMessageInterfaceDispatchEventWithToken: Handling of lists returned by OSL not yet implemented."); #else // DebugStr("\pHandling of lists returned by OSL not yet implemented."); // THROW(errAEEventNotHandled); #endif THROW_IF_ERROR(AECountItems(token, &itemCount)); // I THINK ALL THE TOKENS IN THE LIST SHOULD HAVE BEEN CREATED IN THE // SAME CONTEXT. FOR NOW, I JUST WANT TO VERIFY THIS IS SO AND RAISE // AN ERROR IF NOT. ALSO VERIFYING THAT ALL DESCRIPTORS IN THE LIST // ARE OPENDOC TOKENS. if (itemCount == 0) { PlaceEmptyListIntoReply(reply); handledEventRightHere = kODTrue; } else { for (ODSLong i = 1; i <= itemCount; i++) { THROW_IF_ERROR(AEGetNthDesc(token, i, typeWildCard, &returnedKeyWord, &embeddedToken)); ODOSLToken* odToken = new ODOSLToken; THROW_IF_NULL(odToken); odToken->InitODOSLToken(ev); THROW_IF_ERROR( AEDescToODDesc(&embeddedToken, odToken ) ); AEDisposeDesc(&embeddedToken); // SANITY CHECKING if (!_fNameResolver->IsODToken(ev, odToken)) { delete odToken; ASSERTM(kODFalse, errAEEventNotHandled, "ODMessageInterfaceDispatchEventWithToken: Found descriptor that was not an OpenDoc token while handling list."); } _fNameResolver->GetContextFromToken(ev, odToken, &thisPart, &thisFrame); if (i > 1) { // SANITY CHECKING if (thisPart != prevPart || thisFrame != prevFrame) ASSERTM(kODFalse, errAEEventNotHandled, "ODMessageInterfaceDispatchEventWithToken: Not all tokens of list came from same place."); } prevPart = thisPart; prevFrame = thisFrame; ODDeleteObject(odToken); } ODDesc* userODToken = new ODDesc; THROW_IF_NULL(userODToken); userODToken->InitODDesc(ev); AEDescToODDesc(token, userODToken); OSLDisposeToken(token); _fNameResolver->CreateNewODOSLToken(ev, token, userODToken, thisPart, thisFrame); } } if (!handledEventRightHere) { ODPart* contextPart = _fNameResolver->GetPartFromToken(ev, token); if ( !dpAlreadyToken && !usingSubjectAttr ) THROW_IF_ERROR(AEPutParamDesc(message, keyDirectObject, token)); error = somSelf->DispatchToEventHandler(ev, message, reply, contextPart, token); } return error; } //------------------------------------------------------------------------------ // PlaceEmptyListIntoReply // // Place an empty AE list into a reply as the direct parameter. //------------------------------------------------------------------------------ static void PlaceEmptyListIntoReply(AppleEvent* reply) { AEDesc emptyList; const Boolean kCreateListNotRecord = kODFalse; THROW_IF_ERROR(AECreateList(kODNULL, 0, kCreateListNotRecord, &emptyList)); THROW_IF_ERROR(AEPutParamDesc(reply, keyDirectObject, &emptyList)); AEDisposeDesc(&emptyList); } #if 0 //------------------------------------------------------------------------------ // ODMessageInterface::HandleSpecialEvents // // Special case some events, like recording events, etc. // Return kODTrue if handled the event, kODFalse, if not. // // Since it's a private method, I'm not using SOM exceptions for now. //------------------------------------------------------------------------------ SOM_Scope ODBoolean SOMLINK ODMessageInterfaceHandleSpecialEvents(ODMessageInterface *somSelf, Environment *ev, AppleEvent* message, AppleEvent* reply, OSErr* error) { ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfaceHandleSpecialEvents"); ODUnused(reply); ODBoolean result = kODFalse; DescType eventClass; DescType eventID; DescType actualType; Size maxSize = sizeof(DescType); Size actualSize; *error = noErr; *error = AEGetAttributePtr(message, keyEventClassAttr, typeType, &actualType, (Ptr)&eventClass, maxSize, &actualSize); if (error || actualType != typeType || actualSize != maxSize) return result; *error = AEGetAttributePtr(message, keyEventIDAttr, typeType, &actualType, (Ptr)&eventID, maxSize, &actualSize); if (error || actualType != typeType || actualSize != maxSize) return result; switch (eventClass) { case kCoreEventClass: switch (eventID) { // SEND THESE TO ALL RUNNING PARTS THAT HAVE A HANDLER FOR THIS case kAENotifyStartRecording: result = kODTrue; break; case kAENotifyStopRecording: result = kODTrue; break; } break; case kOSASuite: switch (eventID) { // SEND THESE TO ALL RUNNING PARTS THAT HAVE A HANDLER FOR THIS case kOSARecordedText: result = kODTrue; break; } break; } return result; } #endif /* 0 */ //------------------------------------------------------------------------------ // ODMessageInterface::DispatchToEventHandler // // Since it's a private method, I'm not using SOM exceptions for now. //------------------------------------------------------------------------------ SOM_Scope OSErr SOMLINK ODMessageInterfaceDispatchToEventHandler(ODMessageInterface *somSelf, Environment *ev, AppleEvent* message, AppleEvent* reply, ODPart* contextPart, AEDesc* realToken ) { ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfaceDispatchToEventHandler"); // FN_CATCH return (OSErr)ErrorCode(); // Not SOM_CATCH: we don't want to set ev! // * SET THE CURRENT CONTEXT SO THAT COERCIONS ARE HANDLED CORRECTLY ODPart* savedPart = _fNameResolver->GetCurrentContextPart(ev); _fNameResolver->SetCurrentContextPart(ev, contextPart); // <eeh> optimization note: calling GetTokenPart in the recursive case // is stupid since the result will always be the same as before. It // would be better to pass the ODPart* itself. But no time now. // On later consideration, I don't think this makes sense. The recursive // case is fairly rare and I don't think it's worth the extra calls to // pass in default values (or null) from the other places DispatchToEventHandler // is called just to avoid this one. Plus there's no way to avoid adding // another parameter to this method. ODPart* partFromStdToken = GetTokenPart( ev, _fNameResolver, realToken ); ODBoolean tokenFromDefault = realToken? _fNameResolver->TokenIsDefault(ev, realToken):kODFalse; OSErr result = somSelf->DispatchToEventHandlerAux(ev, message, reply, contextPart, tokenFromDefault, partFromStdToken!=kODNULL ); // If we got back errAEEventNotHandled, two things could be wrong in // addition to the usual case where the part that should have gotten // the event got it and couldn't handle it. One possibility is that // the event should have gone to the root part but went to the shell, // which barfed. This will happen when there's no direct parameter, // and hence no resolution (with swapping) has taken place. So we // give the root part a chance. The second possibility is that the // event should have gone to an embedded part (eg.: tell part 1 to // play part 1) but went to the container, which couldn't handle it. // In this case we should swap to the embedded part so it can try. // Note that *both* can happen in the course of handling the same // event, so we can get three levels of recursion. Actually, if the // embedded part fails to handle the event we'll almost get a fourth, // but the swapPart != contextPart test will stop the process. if ( result == errAEEventNotHandled ) { TempODPart swapPart = kODNULL; if ( contextPart == kODAppShell ) { ODFrame* frame = GetDefaultRootFrameToSwapTo(ev, _fSession); if ( frame ) swapPart = frame->AcquirePart(ev); } else // this may fail, ie return null, which means don't recurse { if ( (swapPart = partFromStdToken) != kODNULL ) swapPart->Acquire( ev ); } if ( swapPart ) { if ( !ODObjectsAreEqual(ev, swapPart, contextPart) ) result = somSelf->DispatchToEventHandler( ev, message, reply, swapPart, realToken ); // ODReleaseObject( ev, swapPart ); } } // * CAN RESTORE CONTEXT NOW. _fNameResolver->SetCurrentContextPart(ev, savedPart); return result; } // DispatchToEventHandler //------------------------------------------------------------------------------ // ODMessageInterface::DispatchToEventHandlerAux // // Since it's a private method, I'm not using SOM exceptions for now. //------------------------------------------------------------------------------ SOM_Scope OSErr SOMLINK ODMessageInterfaceDispatchToEventHandlerAux(ODMessageInterface *somSelf, Environment *ev, AppleEvent* message, AppleEvent* reply, ODPart* sendee, ODBoolean tokenFromDefault, ODBoolean isStdPartToken) { ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfaceDispatchToEventHandlerAux"); OSErr result = noErr; ODSemanticInterface* si = kODNULL; ODVolatile(si); ODVolatile(sendee); ODAppleEvent* msgWrapper; ODVolatile(msgWrapper); ODAppleEvent* replyWrapper; ODVolatile(replyWrapper); TRY msgWrapper = new ODAppleEvent(); THROW_IF_NULL(msgWrapper); msgWrapper->InitODAppleEvent(ev); THROW_IF_ERROR( AEDescToODDesc( message, msgWrapper ) ); replyWrapper = new ODAppleEvent(); THROW_IF_NULL(replyWrapper); replyWrapper->InitODAppleEvent(ev); THROW_IF_ERROR( AEDescToODDesc( reply, replyWrapper ) ); TRY si = _fNameResolver->AcquireSemtIntf(ev, sendee); if (si && (!tokenFromDefault || isStdPartToken )) si->CallEventHandler(ev, sendee, msgWrapper, replyWrapper); else result = errAEEventNotHandled; CATCH_ALL result = ErrorCode(); ENDTRY if (result == errAEEventNotHandled) // shell doesn't have default accessors! NP - Huh? 6/21/95 { TRY _fDefaultSI->CallEventHandler(ev, sendee, msgWrapper, replyWrapper); result = noErr; CATCH_ALL result = ErrorCode(); ENDTRY } CATCH_ALL result = ErrorCode(); ENDTRY ODReleaseObject(ev,si); ODDeleteObject(msgWrapper); // THE AE MANAGER REALLY WANTS US TO USE THE REPLY DESCRIPTOR THAT IT // ALLOCATED. SO WE MUST BLOCKMOVE OUR DATA BACK IN. if (reply->descriptorType != typeNull && reply->dataHandle != kODNULL) { // This code overwrites whatever in the header tells the AEM that // this is a valid reply. Execute this code and the AEM will dispose // the reply before returning from AESend -- in the send-to-self // case, that is. <eeh> ODByteArray data = replyWrapper->GetRawData(ev); SetHandleSize(reply->dataHandle, data._length); THROW_IF_ERROR(MemError()); ODBlockMove(data._buffer, *(reply->dataHandle), data._length); DisposeByteArrayStruct(data); } ODDeleteObject(replyWrapper); return result; } //------------------------------------------------------------------------------ // HandleReplies //------------------------------------------------------------------------------ static pascal OSErr HandleReplies(AppleEvent* message, AppleEvent* reply, long refCon) { ODMessageInterface* self = (ODMessageInterface*)refCon; OSErr result = noErr ; TRY result = self->HandleRepliesAux(somGetGlobalEnvironment(), message, reply); CATCH_ALL result = ErrorCode(); ENDTRY return result ; } //------------------------------------------------------------------------------ // ODMessageInterface::HandleRepliesAux // // Since it's a private method, I'm not using SOM exceptions for now. //------------------------------------------------------------------------------ SOM_Scope OSErr SOMLINK ODMessageInterfaceHandleRepliesAux(ODMessageInterface *somSelf, Environment *ev, AppleEvent* message, AppleEvent* reply) { ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfaceHandleRepliesAux"); ODPart* aPart; ODSShort returnID; returnID = GetReturnID(message); if (!_fTransactionList->Find(returnID, &aPart)) return errAEEventNotHandled; if (aPart == NULL) return errAEEventNotHandled; else return somSelf->DispatchToEventHandler(ev, message, reply, aPart, kODNULL ); } //------------------------------------------------------------------------------ // HandleAllCoercions //------------------------------------------------------------------------------ static OSErr pascal HandleAllCoercions(const AEDesc* theAEDesc, DescType toType, long refCon, AEDesc* retDesc) { ODMessageInterface* self = (ODMessageInterface*)refCon; return self->HandleAllCoercionsAux(somGetGlobalEnvironment(), (AEDesc*)theAEDesc, toType, retDesc); } //------------------------------------------------------------------------------ // ODMessageInterface::HandleAllCoercionsAux // // Since it's a private method, I'm not using SOM exceptions for now. //------------------------------------------------------------------------------ SOM_Scope OSErr SOMLINK ODMessageInterfaceHandleAllCoercionsAux(ODMessageInterface *somSelf, Environment *ev, AEDesc* theAEDesc, ODDescType toType, AEDesc* retDesc) { ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfaceHandleAllCoercionsAux"); ODPart* contextPart = _fNameResolver->GetCurrentContextPart(ev); return somSelf->DispatchToCoercionHandler(ev, theAEDesc, toType, contextPart, retDesc); } #if 0 #endif /* 0 */ //------------------------------------------------------------------------------ // ODMessageInterface::DispatchToCoercionHandler // // Since it's a private method, I'm not using SOM exceptions for now. //------------------------------------------------------------------------------ SOM_Scope OSErr SOMLINK ODMessageInterfaceDispatchToCoercionHandler(ODMessageInterface *somSelf, Environment *ev, AEDesc* theAEDesc, ODDescType toType, ODPart* sendee, AEDesc* retDesc) { ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfaceDispatchToCoercionHandler"); OSErr result = noErr; ODSemanticInterface* si = kODNULL; ODVolatile(si); TRY si = _fNameResolver->AcquireSemtIntf(ev, sendee); if (si) { ODDesc* realInDesc = new ODDesc(); THROW_IF_NULL(realInDesc); realInDesc->InitODDesc(ev); THROW_IF_ERROR( AEDescToODDesc(theAEDesc, realInDesc ) ); ODDesc* realOutDesc = new ODDesc(); THROW_IF_NULL(realOutDesc); realOutDesc->InitODDesc(ev); // APPLE EVENTS DOESN'T PASS US A NULL DESC APPARENTLY. IT'S FULL // OF GARBAGE. MakeNULLDesc(retDesc); THROW_IF_ERROR( AEDescToODDesc(retDesc, realOutDesc ) ); TRY si->CallCoercionHandler(ev, sendee, realInDesc, toType, realOutDesc); THROW_IF_ERROR(ODDescToAEDesc(realOutDesc, retDesc)); CATCH_ALL result = ErrorCode(); ENDTRY ODDeleteObject(realInDesc); ODDeleteObject(realOutDesc); } else result = errAECoercionFail; CATCH_ALL result = ErrorCode(); ENDTRY ODReleaseObject(ev,si); return result; } //------------------------------------------------------------------------------ // HandlePreDispatch // // Allow all pre-dispatch procs to look at it. Return noErr IF ANY ONE OF THEM // said they handled it. //------------------------------------------------------------------------------ static OSErr pascal HandlePreDispatch(AppleEvent* message, AppleEvent* reply, long refCon) { ODUnused(refCon); OSErr error = errAEEventNotHandled; ODBoolean someoneHandled = kODFalse; Environment* ev = somGetGlobalEnvironment(); ODMessageInterface* msgIntf = gMessageInterface; OrderedCollectionIterator iter(msgIntf->GetPreHandlers(ev)); PreHandlerInfo* element; TRY for (element = (PreHandlerInfo*)iter.First(); iter.IsNotComplete(); element = (PreHandlerInfo*)iter.Next()) { ODAppleEvent* coverEvent = new ODAppleEvent(); THROW_IF_NULL(coverEvent); coverEvent->InitODAppleEvent(ev); THROW_IF_ERROR( AEDescToODDesc(message, coverEvent ) ); ODAppleEvent* coverReply = new ODAppleEvent(); THROW_IF_NULL(coverReply); coverReply->InitODAppleEvent(ev); THROW_IF_ERROR( AEDescToODDesc(reply, coverReply ) ); TRY element->GetSemanticInterface()->CallPredispatchProc(ev, kODNULL, coverEvent, coverReply); CATCH_ALL error = ErrorCode(); ENDTRY if (error == noErr) someoneHandled = kODTrue; ODDeleteObject(coverEvent); ODDeleteObject(coverReply); } CATCH_ALL error = ErrorCode(); ENDTRY if (someoneHandled) return noErr; else return error; } //------------------------------------------------------------------------------ // ODMessageInterface::GetPreHandlers //------------------------------------------------------------------------------ SOM_Scope OrderedCollection* SOMLINK ODMessageInterfaceGetPreHandlers(ODMessageInterface *somSelf, Environment *ev) { ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfaceGetPreHandlers"); return _fPreHandlers; } //------------------------------------------------------------------------------ // ODMessageInterface::GetDefaultSI //------------------------------------------------------------------------------ SOM_Scope ODSemanticInterface* SOMLINK ODMessageInterfaceGetDefaultSI(ODMessageInterface *somSelf, Environment *ev) { ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfaceGetDefaultSI"); return _fDefaultSI; } //------------------------------------------------------------------------------ // ODMessageInterface::PreHandlerAdded //------------------------------------------------------------------------------ SOM_Scope void SOMLINK ODMessageInterfacePreHandlerAdded(ODMessageInterface *somSelf, Environment *ev, ODSemanticInterface* face, ODSLong refCon) { ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfacePreHandlerAdded"); SOM_CATCH return; PreHandlerInfo* info = new PreHandlerInfo(face, refCon); _fPreHandlers->AddFirst((ElementType)info); } //------------------------------------------------------------------------------ // ODMessageInterface::PreHandlerRemoved //------------------------------------------------------------------------------ SOM_Scope void SOMLINK ODMessageInterfacePreHandlerRemoved(ODMessageInterface *somSelf, Environment *ev, ODSemanticInterface* face, ODSLong refCon) { ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfacePreHandlerRemoved"); OrderedCollectionIterator iter(somSelf->GetPreHandlers(ev)); PreHandlerInfo* element; ElementType elementToRemove = kODNULL; for (element = (PreHandlerInfo*)iter.First(); iter.IsNotComplete(); element = (PreHandlerInfo*)iter.Next()) { if (element->GetSemanticInterface() == face && element->GetRefCon() == refCon) elementToRemove = element; } if (elementToRemove) _fPreHandlers->Remove(elementToRemove); } //------------------------------------------------------------------------------ // ODMessageInterface::CreatePartAddrDesc //------------------------------------------------------------------------------ SOM_Scope void SOMLINK ODMessageInterfaceCreatePartAddrDesc(ODMessageInterface *somSelf, Environment *ev, ODAddressDesc** theAddressDesc, ODPart* part) { // ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfaceCreatePartAddrDesc"); ODUnused(part); ProcessSerialNumber PSN; OSErr result; AEDesc addressDesc; ODVolatile(addressDesc); SOM_TRY PSN.highLongOfPSN = 0; PSN.lowLongOfPSN = kCurrentProcess; result = AECreateDesc( typeProcessSerialNumber, (Ptr)&PSN, sizeof(PSN), &addressDesc ); if ( !result ) { ODAddressDesc* newODAddress = new ODAddressDesc(); THROW_IF_NULL(newODAddress); newODAddress->InitODAddressDesc(ev); result = AEDescToODDesc( &addressDesc, newODAddress); AEDisposeDesc(&addressDesc); if (!result) *theAddressDesc = newODAddress; else *theAddressDesc = kODNULL; } THROW_IF_ERROR (result); SOM_CATCH_ALL *theAddressDesc = kODNULL; SOM_ENDTRY } //------------------------------------------------------------------------------ // ODMessageInterface::CreatePartObjSpec //------------------------------------------------------------------------------ SOM_Scope void SOMLINK ODMessageInterfaceCreatePartObjSpec(ODMessageInterface *somSelf, Environment *ev, ODObjectSpec** theObjSpec, ODPart* thePart) { // ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfaceCreatePartObjSpec"); const Boolean kDisposeInputs = kODTrue; AEDesc keyData; AEDesc nullDesc = NULL_DESCRIPTOR_DEFINITION; AEDesc newObjSpec; ODVolatile(newObjSpec); SOM_TRY THROW_IF_ERROR(AECreateDesc(typeLongInteger, &thePart, sizeof(long), &keyData)); // USE cPart as the keyform. THROW_IF_ERROR(CreateObjSpecifier(cPart, &nullDesc, cPart, &keyData, kDisposeInputs, &newObjSpec)); ODObjectSpec* newODObjSpec = new ODObjectSpec(); THROW_IF_NULL(newODObjSpec); newODObjSpec->InitODObjectSpec(ev); THROW_IF_ERROR( AEDescToODDesc(&newObjSpec, newODObjSpec ) ); AEDisposeDesc(&newObjSpec); *theObjSpec = newODObjSpec; SOM_CATCH_ALL *theObjSpec = kODNULL; SOM_ENDTRY } //------------------------------------------------------------------------------ // ODMessageInterface::InstallDefaultHandlers //------------------------------------------------------------------------------ SOM_Scope void SOMLINK ODMessageInterfaceInstallDefaultHandlers(ODMessageInterface *somSelf, Environment *ev) { ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","ODMessageInterfaceInstallDefaultHandlers"); } #ifdef TO_BE_DELETED //------------------------------------------------------------------------------ // ODMessageInterface: HandleGDUT //------------------------------------------------------------------------------ // <eeh> this reversed the order of enclosed lists. Shouldn't matter to // the current AppleScript, but who knows. #define ReturnIfError( funcCall ) \ { OSErr err = (funcCall); \ if ( err != noErr ) { return err; } } static OSErr AddDPToList( AppleEvent* reply, AEDescList* theList ) { OSErr err = noErr ; AEDesc item ; ReturnIfError( AEGetKeyDesc( reply, keyDirectObject, typeWildCard, &item )); if ((item.descriptorType == typeAETE) || (item.descriptorType == typeAEUT)) { err = AEPutDesc( theList, 0, &item ) ; } else if ( item.descriptorType == typeAEList ) { long itemCount ; AECountItems( &item, &itemCount ) ; for( long i = 1; err == noErr && i <= itemCount; ++i ) { AEDesc subItem ; DescType ignore ; ReturnIfError( AEGetNthDesc( &item, i, typeWildCard, &ignore, &subItem ) ) ; err = AddDPToList( &subItem, theList ) ; AEDisposeDesc( &subItem ) ; } } else { WASSERTM( kODFalse, "neither aete nor aeut" ) ; } AEDisposeDesc( &item ) ; return err ; } // AddDPToList() SOM_Scope pascal OSErr SOMLINK ODMessageInterfaceHandleGDUT(ODMessageInterface *somSelf, Environment *ev, AppleEvent* message, AppleEvent* reply, long refCon) { ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); ODMessageInterfaceMethodDebug("ODMessageInterface","HandleGDUT"); ODMessageInterface* self = (ODMessageInterface*)refCon; ODMessageInterface* msgInterface = self->_fSession->GetMessageInterface(ev); // Call the shell's GetAETE handler, then iterate through every // part editor getting theirs as well. Put them all in a list, // making sure the list contains no lists. AEDescList resultList ; ReturnIfError( AECreateList( kODNULL, 0, kODFalse, &resultList ) ) ; ODSemanticInterface* shellSemInt = self->_fSession->GetShellSemtInterface(ev); if ( shellSemInt != kODNULL ) { OSErr err = msgInterface->DispatchToEventHandler( message, reply, kODAppShell ) ; if ( err == noErr ) ReturnIfError( AddDPToList( reply, &resultList ) ); } #ifdef TO_BE_DELETED EditorIterator* ei = self->MakeEditorIterator() ; for( ODSemanticInterface* si = ei->First() ; ie->IsNotComplete() ; si = ei->Next() ) { if ( si->HasExtension() && si->IsSemanticEventsExt() ) { ReturnIfError( CallGetAETE( si, &oneAETE ) ) ; ReturnIfError( AddDPToList( reply, &resultList ) ) ; } } #endif /* TO_BE_DELETED */ ReturnIfError( AEPutKeyDesc( reply, keyDirectObject, &resultList ) ) ; AEDisposeDesc( &resultList ) ; return noErr ; } // HandleGDUT() #endif /* TO_BE_DELETED */ //------------------------------------------------------------------------------ // GetReturnID //------------------------------------------------------------------------------ static ODSShort GetReturnID(AppleEvent* ae) { ODSShort returnID; DescType actualType; Size sizeOfBuffer = sizeof(ODSShort); Size actualSize; THROW_IF_ERROR(AEGetAttributePtr(ae, keyReturnIDAttr, typeShortInteger, &actualType, (Ptr)&returnID, sizeOfBuffer, &actualSize)); if ((actualType != typeShortInteger) || (actualSize != sizeOfBuffer)) THROW(kODErrOutOfMemory); return returnID; } //------------------------------------------------------------------------------ // SentToSelf //------------------------------------------------------------------------------ static ODBoolean SentToSelf(AppleEvent* theAppleEvent) { ProcessSerialNumber PSN; DescType actualType; Size sizeOfBuffer = sizeof(ProcessSerialNumber); Size actualSize; Boolean isCurrentProcess; THROW_IF_ERROR(AEGetAttributePtr(theAppleEvent, keyAddressAttr, typeProcessSerialNumber, &actualType, (Ptr)&PSN, sizeOfBuffer, &actualSize )); if ((actualType != typeProcessSerialNumber) || (actualSize != sizeOfBuffer)) THROW(kODErrOutOfMemory); //$$$$$ THIS IS WRONG. SHOULD BE CALLING SameProcess. AM TOO WORRIED ABOUT // BREAKING SOMETHING TO FIX IT AT THIS LATE DATE, HOWEVER. -NP 8/30/95 isCurrentProcess = ( PSN.lowLongOfPSN == kCurrentProcess ); return isCurrentProcess; } //------------------------------------------------------------------------------ // GetTokenPart // Given a token (of type 'tokn'), determine if the user token it contains // is a StandardPartToken and if so return the ODPart* field therefrom. // Return NULL in all other cases. //------------------------------------------------------------------------------ static ODPart* GetTokenPart( Environment* ev, ODNameResolver* resolver, AEDesc* realToken ) { if ( !realToken || (realToken->descriptorType != typeUserToken)) return kODNULL; ODPart* result = kODNULL; ODOSLToken* token = new ODOSLToken; THROW_IF_NULL(token); token->InitODOSLToken(ev); if ( AEDescToODDesc( realToken, token ) ) { ODDeleteObject(token); return kODNULL; } ODDesc* userToken; userToken = resolver->GetUserToken( ev, token ); AEDesc realUserToken; if ( ODDescToAEDesc( userToken, &realUserToken ) ) return kODNULL; if ( CanBeStandardPartToken( &realUserToken ) ) result = PartFromStandardPartToken( &realUserToken ); AEDisposeDesc(&realUserToken); ODDeleteObject(token); return result; } //------------------------------------------------------------------------------ // HandleGetAETE //------------------------------------------------------------------------------ pascal OSErr HandleGetAETE( AppleEvent* message, AppleEvent* reply, long refCon) { ODMessageInterface *somSelf = (ODMessageInterface*) refCon; ODMessageInterfaceData *somThis = ODMessageInterfaceGetData(somSelf); AEDesc theAETE = NULL_DESCRIPTOR_DEFINITION; AEDesc scsz = NULL_DESCRIPTOR_DEFINITION; AEDescList theList = NULL_DESCRIPTOR_DEFINITION; AppleEvent realEvent = NULL_DESCRIPTOR_DEFINITION; AppleEvent realReply = NULL_DESCRIPTOR_DEFINITION; Environment* ev = somGetGlobalEnvironment(); DescType returnedType; ODSize actualSize; ODSLong languageCode; ODAddressDesc* address; ODAppleEvent* myEvent; ODAppleEvent* myReply; OSErr result; ODSession* session = _fSession; ODError error = noErr; ODVolatile(error); TRY result = AEGetParamPtr(message, keyDirectObject, typeLongInteger, &returnedType, (Ptr)&languageCode, sizeof(languageCode), (Size *)&actualSize); THROW_IF_ERROR( AECreateList(kODNULL, 0, false, &theList) ); // get aete list for all part editors session->GetNameSpaceManager(ev)->GetAETEs(ev, languageCode, &theList); // get aete for shell myReply = new ODAppleEvent(); THROW_IF_NULL(myReply); myReply->InitODAppleEvent(ev); TRY somSelf->CreatePartAddrDesc(ev, &address, kODNULL); somSelf->CreateEvent(ev, kAEOpenDocSuite, kGetAETE, address, kAnyTransactionID, &myEvent); THROW_IF_ERROR( ODDescToAEDesc(myEvent, &realEvent) ); THROW_IF_ERROR( AEPutParamPtr(&realEvent, keyDirectObject, typeLongInteger, (Ptr) &languageCode, sizeof(languageCode)) ); THROW_IF_ERROR( AEDescToODDesc(&realEvent, myEvent) ); somSelf->Send(ev, kODNULL, kODNULL, myEvent, myReply, kAEWaitReply+kAEDontRecord, kAENormalPriority, kAEDefaultTimeout); THROW_IF_ERROR( ODDescToAEDesc(myReply, &realReply) ); THROW_IF_ERROR( AEGetParamDesc(&realReply, keyAEResult, typeAETE, &theAETE) ); THROW_IF_ERROR( AEPutDesc(&theList, 0, &theAETE) ); CATCH_ALL // error = ErrorCode(); // we're ignoring this, so we're commented out WARN("Couldn't get shell aete"); ENDTRY AEDisposeDesc(&realEvent); AEDisposeDesc(&realReply); AEDisposeDesc(&theAETE); ODDeleteObject(myEvent); ODDeleteObject(myReply); // get aete for OpenDoc from messaging library TRY CUsingLibraryResources ref; // We pervert the language code because we need two aetes in the single // library version, one for the shell and one for OpenDoc. This way // container apps can override the shell's aete and provide their own. // The shell aete is numbered normally, but OpenDoc's aetes are numbered // according to this scheme (-1 - languageCode) so that they start at -1 // and proceed down from there (as opposed to the normal ones which // start at 0 and proceed upward). theAETE.dataHandle = Get1Resource(typeAETE, (short)(-1-languageCode)); THROW_IF_NULL(theAETE.dataHandle); theAETE.descriptorType = typeAETE; result = AEPutDesc(&theList, 0, &theAETE); ReleaseResource(theAETE.dataHandle); THROW_IF_ERROR(result); CATCH_ALL // error = ErrorCode(); // we're ignoring this, so we're commented out WARN("Couldn't get OpenDoc aete"); ENDTRY TRY scsz.descriptorType = 'scsz'; scsz.dataHandle = Get1Resource('scsz', 0); THROW_IF_NULL(scsz.dataHandle); THROW_IF_ERROR( AEPutParamDesc(reply, keyScszResource, &scsz) ); CATCH_ALL // error = ErrorCode(); // we're ignoring this, so we're commented out WARN("Couldn't get OpenDoc scsz"); ENDTRY THROW_IF_ERROR( AEPutParamDesc(reply, keyDirectObject, &theList) ); THROW_IF_ERROR( AEDisposeDesc(&theList) ); CATCH_ALL error = ErrorCode(); ENDTRY return error; } // HandleGetAETE() void CreateSubjectObject(Environment* ev, ODFrame* frame, AEDesc* objSpec) { AEDesc nullDesc = NULL_DESCRIPTOR_DEFINITION; AEDesc id; ODPersistentObjectID foo; OSErr err; ODStorageUnit* su = frame->GetStorageUnit(ev); WASSERT(su); ODDraft* draft = su->GetDraft(ev); WASSERT(draft); foo = draft->GetPersistentObjectID( ev, frame, kODFrameObject); THROW_IF_ERROR( AECreateDesc(typeInteger, (Ptr) &foo, sizeof(foo), &id) ); err = CreateObjSpecifier(cPart, &nullDesc, formUniqueID, &id, kODFalse, objSpec); AEDisposeDesc(&id); THROW_IF_ERROR(err); } // CreateSubjectObject